wined3d: Implement mipmap auto generation.
This commit is contained in:
parent
5ab9d85c39
commit
160258b637
|
@ -126,6 +126,73 @@ static void test_cube_textures(IDirect3DDevice9 *device_ptr, DWORD caps)
|
|||
test_cube_texture_from_pool(device_ptr, caps, D3DPOOL_SCRATCH, FALSE);
|
||||
}
|
||||
|
||||
static void test_mipmap_gen(IDirect3DDevice9 *device)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDirect3D9 *d3d9;
|
||||
IDirect3DTexture9 *texture;
|
||||
IDirect3DSurface9 *surface;
|
||||
DWORD levels;
|
||||
D3DSURFACE_DESC desc;
|
||||
int i;
|
||||
D3DLOCKED_RECT lr;
|
||||
|
||||
hr = IDirect3DDevice9_GetDirect3D(device, &d3d9);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_GetDirect3D returned %#x\n", hr);
|
||||
|
||||
hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
|
||||
D3DUSAGE_AUTOGENMIPMAP,
|
||||
D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
skip("No mipmap generation support\n");
|
||||
}
|
||||
|
||||
hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
|
||||
D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed(%08x)\n", hr);
|
||||
|
||||
levels = IDirect3DTexture9_GetLevelCount(texture);
|
||||
ok(levels == 1, "Got %d levels, expected 1\n", levels);
|
||||
|
||||
for(i = 0; i < 6 /* 64 = 2 ^ 6 */; i++)
|
||||
{
|
||||
surface = NULL;
|
||||
hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
|
||||
ok(hr == (i == 0 ? D3D_OK : D3DERR_INVALIDCALL),
|
||||
"GetSurfaceLevel on level %d returned %#x\n", i, hr);
|
||||
if(surface) IDirect3DSurface9_Release(surface);
|
||||
|
||||
hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
|
||||
ok(hr == (i == 0 ? D3D_OK : D3DERR_INVALIDCALL),
|
||||
"GetLevelDesc on level %d returned %#x\n", i, hr);
|
||||
|
||||
hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
|
||||
ok(hr == (i == 0 ? D3D_OK : D3DERR_INVALIDCALL),
|
||||
"LockRect on level %d returned %#x\n", i, hr);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
hr = IDirect3DTexture9_UnlockRect(texture, i);
|
||||
ok(hr == D3D_OK, "Unlock returned %08x\n", hr);
|
||||
}
|
||||
}
|
||||
IDirect3DTexture9_Release(texture);
|
||||
|
||||
hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2 /* levels */, D3DUSAGE_AUTOGENMIPMAP,
|
||||
D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
|
||||
ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture(levels = 2) returned %08x\n", hr);
|
||||
hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6 /* levels */, D3DUSAGE_AUTOGENMIPMAP,
|
||||
D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
|
||||
ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture(levels = 6) returned %08x\n", hr);
|
||||
|
||||
hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1 /* levels */, D3DUSAGE_AUTOGENMIPMAP,
|
||||
D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture(levels = 1) returned %08x\n", hr);
|
||||
levels = IDirect3DTexture9_GetLevelCount(texture);
|
||||
ok(levels == 1, "Got %d levels, expected 1\n", levels);
|
||||
IDirect3DTexture9_Release(texture);
|
||||
}
|
||||
|
||||
START_TEST(texture)
|
||||
{
|
||||
D3DCAPS9 caps;
|
||||
|
@ -146,4 +213,5 @@ START_TEST(texture)
|
|||
|
||||
test_texture_stage_states(device_ptr, caps.MaxTextureBlendStages);
|
||||
test_cube_textures(device_ptr, caps.TextureCaps);
|
||||
test_mipmap_gen(device_ptr);
|
||||
}
|
||||
|
|
|
@ -2822,6 +2822,115 @@ static void x8l8v8u8_test(IDirect3DDevice9 *device)
|
|||
IDirect3DTexture9_Release(texture);
|
||||
}
|
||||
|
||||
static void autogen_mipmap_test(IDirect3DDevice9 *device)
|
||||
{
|
||||
HRESULT hr;
|
||||
IDirect3D9 *d3d;
|
||||
IDirect3DTexture9 *texture = NULL;
|
||||
IDirect3DSurface9 *surface;
|
||||
DWORD color;
|
||||
const RECT r1 = {256, 256, 512, 512};
|
||||
const RECT r2 = {512, 256, 768, 512};
|
||||
const RECT r3 = {256, 512, 512, 768};
|
||||
const RECT r4 = {512, 512, 768, 768};
|
||||
unsigned int x, y;
|
||||
D3DLOCKED_RECT lr;
|
||||
memset(&lr, 0, sizeof(lr));
|
||||
|
||||
IDirect3DDevice9_GetDirect3D(device, &d3d);
|
||||
if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
|
||||
D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) {
|
||||
skip("No autogenmipmap support\n");
|
||||
IDirect3D9_Release(d3d);
|
||||
return;
|
||||
}
|
||||
IDirect3D9_Release(d3d);
|
||||
|
||||
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
|
||||
|
||||
/* Make the mipmap big, so that a smaller mipmap is used
|
||||
*/
|
||||
hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP,
|
||||
D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
|
||||
|
||||
hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
|
||||
ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
|
||||
ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %s\n", DXGetErrorString9(hr));
|
||||
for(y = 0; y < 1024; y++) {
|
||||
for(x = 0; x < 1024; x++) {
|
||||
DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4);
|
||||
POINT pt;
|
||||
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
if(PtInRect(&r1, pt)) {
|
||||
*dst = 0xffff0000;
|
||||
} else if(PtInRect(&r2, pt)) {
|
||||
*dst = 0xff00ff00;
|
||||
} else if(PtInRect(&r3, pt)) {
|
||||
*dst = 0xff0000ff;
|
||||
} else if(PtInRect(&r4, pt)) {
|
||||
*dst = 0xff000000;
|
||||
} else {
|
||||
*dst = 0xffffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
hr = IDirect3DSurface9_UnlockRect(surface);
|
||||
ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %s\n", DXGetErrorString9(hr));
|
||||
IDirect3DSurface9_Release(surface);
|
||||
|
||||
hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
|
||||
|
||||
hr = IDirect3DDevice9_BeginScene(device);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
|
||||
if(SUCCEEDED(hr)) {
|
||||
const float quad[] = {
|
||||
-0.5, -0.5, 0.1, 0.0, 0.0,
|
||||
-0.5, 0.5, 0.1, 0.0, 1.0,
|
||||
0.5, -0.5, 0.1, 1.0, 0.0,
|
||||
0.5, 0.5, 0.1, 1.0, 1.0
|
||||
};
|
||||
|
||||
hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
|
||||
ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
|
||||
hr = IDirect3DDevice9_EndScene(device);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
|
||||
}
|
||||
hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
|
||||
hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
|
||||
IDirect3DTexture9_Release(texture);
|
||||
|
||||
hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
|
||||
ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
|
||||
color = getPixelColor(device, 200, 200);
|
||||
ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color);
|
||||
color = getPixelColor(device, 280, 200);
|
||||
ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color);
|
||||
color = getPixelColor(device, 360, 200);
|
||||
ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color);
|
||||
color = getPixelColor(device, 440, 200);
|
||||
ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
|
||||
color = getPixelColor(device, 200, 270);
|
||||
ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color);
|
||||
color = getPixelColor(device, 280, 270);
|
||||
ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color);
|
||||
color = getPixelColor(device, 360, 270);
|
||||
ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color);
|
||||
color = getPixelColor(device, 440, 270);
|
||||
ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
|
||||
}
|
||||
|
||||
START_TEST(visual)
|
||||
{
|
||||
IDirect3DDevice9 *device_ptr;
|
||||
|
@ -2899,6 +3008,7 @@ START_TEST(visual)
|
|||
release_buffer_test(device_ptr);
|
||||
float_texture_test(device_ptr);
|
||||
texture_transform_flags_test(device_ptr);
|
||||
autogen_mipmap_test(device_ptr);
|
||||
|
||||
|
||||
if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
|
||||
|
|
|
@ -161,11 +161,39 @@ DWORD WINAPI IWineD3DBaseTextureImpl_GetLevelCount(IWineD3DBaseTexture *iface) {
|
|||
|
||||
HRESULT WINAPI IWineD3DBaseTextureImpl_SetAutoGenFilterType(IWineD3DBaseTexture *iface, WINED3DTEXTUREFILTERTYPE FilterType) {
|
||||
IWineD3DBaseTextureImpl *This = (IWineD3DBaseTextureImpl *)iface;
|
||||
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
|
||||
UINT textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(iface);
|
||||
|
||||
if (!(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP)) {
|
||||
TRACE("(%p) : returning invalid call\n", This);
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
if(This->baseTexture.filterType != FilterType) {
|
||||
/* What about multithreading? Do we want all the context overhead just to set this value?
|
||||
* Or should we delay the applying until the texture is used for drawing? For now, apply
|
||||
* immediately.
|
||||
*/
|
||||
ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
|
||||
ENTER_GL();
|
||||
glBindTexture(textureDimensions, This->baseTexture.textureName);
|
||||
checkGLcall("glBindTexture");
|
||||
switch(FilterType) {
|
||||
case WINED3DTEXF_NONE:
|
||||
case WINED3DTEXF_POINT:
|
||||
glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST);
|
||||
checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST)");
|
||||
|
||||
case WINED3DTEXF_LINEAR:
|
||||
glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
|
||||
checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST)");
|
||||
|
||||
default:
|
||||
WARN("Unexpected filter type %d, setting to GL_NICEST\n", FilterType);
|
||||
glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
|
||||
checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST)");
|
||||
}
|
||||
LEAVE_GL();
|
||||
}
|
||||
This->baseTexture.filterType = FilterType;
|
||||
TRACE("(%p) :\n", This);
|
||||
return WINED3D_OK;
|
||||
|
@ -239,6 +267,16 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) {
|
|||
This->baseTexture.states[WINED3DTEXSTA_TSSADDRESSW] = WINED3DTADDRESS_WRAP;
|
||||
IWineD3DBaseTexture_SetDirty(iface, TRUE);
|
||||
isNewTexture = TRUE;
|
||||
|
||||
if(This->resource.usage & WINED3DUSAGE_AUTOGENMIPMAP) {
|
||||
/* This means double binding the texture at creation, but keeps the code simpler all
|
||||
* in all, and the run-time path free from additional checks
|
||||
*/
|
||||
glBindTexture(textureDimensions, This->baseTexture.textureName);
|
||||
checkGLcall("glBindTexture");
|
||||
glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
||||
checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)");
|
||||
}
|
||||
}
|
||||
|
||||
/* Bind the texture */
|
||||
|
|
|
@ -882,7 +882,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U
|
|||
TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
|
||||
|
||||
/* Calculate levels for mip mapping */
|
||||
if (Levels == 0) {
|
||||
if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
|
||||
if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
|
||||
WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
if(Levels > 1) {
|
||||
WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
object->baseTexture.levels = 1;
|
||||
} else if (Levels == 0) {
|
||||
TRACE("calculating levels %d\n", object->baseTexture.levels);
|
||||
object->baseTexture.levels++;
|
||||
tmpW = Width;
|
||||
|
@ -956,7 +966,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
|
|||
object->depth = Depth;
|
||||
|
||||
/* Calculate levels for mip mapping */
|
||||
if (Levels == 0) {
|
||||
if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
|
||||
if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
|
||||
WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
if(Levels > 1) {
|
||||
WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
Levels = 1;
|
||||
} else if (Levels == 0) {
|
||||
object->baseTexture.levels++;
|
||||
tmpW = Width;
|
||||
tmpH = Height;
|
||||
|
@ -1076,7 +1096,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
|
|||
object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
|
||||
|
||||
/* Calculate levels for mip mapping */
|
||||
if (Levels == 0) {
|
||||
if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
|
||||
if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
|
||||
WARN("No mipmap generation support, returning D3DERR_INVALIDCALL\n");
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
if(Levels > 1) {
|
||||
WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL\n");
|
||||
return WINED3DERR_INVALIDCALL;
|
||||
}
|
||||
Levels = 1;
|
||||
} else if (Levels == 0) {
|
||||
object->baseTexture.levels++;
|
||||
tmpW = EdgeLength;
|
||||
while (tmpW > 1) {
|
||||
|
|
|
@ -117,6 +117,9 @@ static const struct {
|
|||
{"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1},
|
||||
{"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2},
|
||||
{"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3},
|
||||
|
||||
/* SGI */
|
||||
{"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP},
|
||||
};
|
||||
|
||||
/**********************************************************
|
||||
|
@ -1477,6 +1480,13 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt
|
|||
}
|
||||
}
|
||||
|
||||
if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
|
||||
if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
|
||||
TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
|
||||
return WINED3DERR_NOTAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
|
||||
* See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
|
||||
* and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
|
||||
|
|
|
@ -2833,6 +2833,13 @@ typedef void (WINE_GLAPI * PGLFNGETTEXBUMPPARAMETERFVATIPROC) (GLenum, GLfloat *
|
|||
typedef int (WINE_GLAPI * PGLXFNGETVIDEOSYNCSGIPROC) (unsigned int *);
|
||||
typedef int (WINE_GLAPI * PGLXFNWAITVIDEOSYNCSGIPROC) (int, int, unsigned int *);
|
||||
|
||||
/* GL_SGIS_generate_mipmap */
|
||||
#ifndef GLX_SGIS_generate_mipmap
|
||||
#define GL_GENERATE_MIPMAP_SGIS 0x8191
|
||||
#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
|
||||
#define GLX_SGIS_generate_mipmap
|
||||
#endif
|
||||
|
||||
/* GL_VERSION_2_0 */
|
||||
#ifndef GL_VERSION_2_0
|
||||
#define GL_VERSION_2_0 1
|
||||
|
@ -3181,6 +3188,7 @@ typedef enum _GL_SupportedExt {
|
|||
APPLE_CLIENT_STORAGE,
|
||||
/* SGI */
|
||||
SGI_VIDEO_SYNC,
|
||||
SGIS_GENERATE_MIPMAP,
|
||||
|
||||
/* WGL extensions */
|
||||
WGL_ARB_PBUFFER,
|
||||
|
|
Loading…
Reference in New Issue