diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 173d64869f6..00506abedb2 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -2720,6 +2720,108 @@ static void texkill_test(IDirect3DDevice9 *device) ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color); } +static void x8l8v8u8_test(IDirect3DDevice9 *device) +{ + IDirect3D9 *d3d9; + HRESULT hr; + IDirect3DTexture9 *texture; + IDirect3DPixelShader9 *shader; + IDirect3DPixelShader9 *shader2; + D3DLOCKED_RECT lr; + DWORD color; + DWORD shader_code[] = { + 0xffff0101, /* ps_1_1 */ + 0x00000042, 0xb00f0000, /* tex t0 */ + 0x00000001, 0x800f0000, 0xb0e40000, /* mov r0, t0 */ + 0x0000ffff /* end */ + }; + DWORD shader_code2[] = { + 0xffff0101, /* ps_1_1 */ + 0x00000042, 0xb00f0000, /* tex t0 */ + 0x00000001, 0x800f0000, 0xb0ff0000, /* mov r0, t0.w */ + 0x0000ffff /* end */ + }; + + float quad[] = { + -1.0, -1.0, 0.1, 0.5, 0.5, + 1.0, -1.0, 0.1, 0.5, 0.5, + -1.0, 1.0, 0.1, 0.5, 0.5, + 1.0, 1.0, 0.1, 0.5, 0.5, + }; + + memset(&lr, 0, sizeof(lr)); + IDirect3DDevice9_GetDirect3D(device, &d3d9); + hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, + 0, D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8); + IDirect3D9_Release(d3d9); + if(FAILED(hr)) { + skip("No D3DFMT_X8L8V8U8 support\n"); + }; + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &texture, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed (%08x)\n", hr); + hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0); + ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed (%08x)\n", hr); + *((DWORD *) lr.pBits) = 0x11ca3141; + hr = IDirect3DTexture9_UnlockRect(texture, 0); + ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed (%08x)\n", hr); + + hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr); + hr = IDirect3DDevice9_CreatePixelShader(device, shader_code2, &shader2); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr); + + hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1); + ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed (%08x)\n", hr); + hr = IDirect3DDevice9_SetPixelShader(device, shader); + ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr); + hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture); + ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr); + + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr); + if(SUCCEEDED(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_BeginScene failed (%08x)\n", hr); + } + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr)); + color = getPixelColor(device, 578, 430); + ok(color == 0x008262ca, "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color); + + hr = IDirect3DDevice9_SetPixelShader(device, shader2); + ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr); + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr); + if(SUCCEEDED(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_BeginScene failed (%08x)\n", hr); + } + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr)); + color = getPixelColor(device, 578, 430); + ok(color == 0x00ffffff, "w component of D3DFMT_X8L8V8U8 = 0x11ca3141 returns color %08x\n", color); + + hr = IDirect3DDevice9_SetPixelShader(device, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr); + hr = IDirect3DDevice9_SetTexture(device, 0, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr); + IDirect3DPixelShader9_Release(shader); + IDirect3DPixelShader9_Release(shader2); + IDirect3DTexture9_Release(texture); +} + START_TEST(visual) { IDirect3DDevice9 *device_ptr; @@ -2816,6 +2918,7 @@ START_TEST(visual) texbem_test(device_ptr); texdepth_test(device_ptr); texkill_test(device_ptr); + x8l8v8u8_test(device_ptr); } else skip("No ps_1_1 support\n"); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 2acd0680865..aecf7f27873 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1573,13 +1573,21 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ break; case WINED3DFMT_X8L8V8U8: - if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break; *convert = CONVERT_X8L8V8U8; - *format = GL_BGRA; - *internal = GL_RGBA8; - *type = GL_UNSIGNED_BYTE; *target_bpp = 4; - /* Not supported by GL_ATI_envmap_bumpmap */ + if(GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* Use formats from gl table. It is a bit unfortunate, but the conversion + * is needed to set the X format to 255 to get 1.0 for alpha when sampling + * the texture. OpenGL can't use GL_DSDT8_MAG8_NV as internal format with + * the needed type and format parameter, so the internal format contains a + * 4th component, which is returned as alpha + */ + } else { + /* Not supported by GL_ATI_envmap_bumpmap */ + *format = GL_BGRA; + *internal = GL_RGBA8; + *type = GL_UNSIGNED_BYTE; + } break; case WINED3DFMT_Q8W8V8U8: @@ -1647,9 +1655,9 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ return WINED3D_OK; } -HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf) { +HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *This) { BYTE *source, *dest; - TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert, surf); + TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert,This); switch (convert) { case NO_CONVERSION: @@ -1660,7 +1668,7 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN case CONVERT_PALETTED: case CONVERT_PALETTED_CK: { - IWineD3DPaletteImpl* pal = surf->palette; + IWineD3DPaletteImpl* pal = This->palette; BYTE table[256][4]; unsigned int i; unsigned int x, y; @@ -1673,14 +1681,14 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN /* Still no palette? Use the device's palette */ /* Get the surface's palette */ for (i = 0; i < 256; i++) { - IWineD3DDeviceImpl *device = surf->resource.wineD3DDevice; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; table[i][0] = device->palettes[device->currentPalette][i].peRed; table[i][1] = device->palettes[device->currentPalette][i].peGreen; table[i][2] = device->palettes[device->currentPalette][i].peBlue; if ((convert == CONVERT_PALETTED_CK) && - (i >= surf->SrcBltCKey.dwColorSpaceLowValue) && - (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) { + (i >= This->SrcBltCKey.dwColorSpaceLowValue) && + (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { /* We should maybe here put a more 'neutral' color than the standard bright purple one often used by application to prevent the nice purple borders when bi-linear filtering is on */ @@ -1697,8 +1705,8 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN table[i][1] = pal->palents[i].peGreen; table[i][2] = pal->palents[i].peBlue; if ((convert == CONVERT_PALETTED_CK) && - (i >= surf->SrcBltCKey.dwColorSpaceLowValue) && - (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) { + (i >= This->SrcBltCKey.dwColorSpaceLowValue) && + (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { /* We should maybe here put a more 'neutral' color than the standard bright purple one often used by application to prevent the nice purple borders when bi-linear filtering is on */ @@ -1751,8 +1759,8 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN for (x = 0; x < width; x++ ) { WORD color = *Source++; *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1)); - if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) || - (color > surf->SrcBltCKey.dwColorSpaceHighValue)) { + if ((color < This->SrcBltCKey.dwColorSpaceLowValue) || + (color > This->SrcBltCKey.dwColorSpaceHighValue)) { *Dest |= 0x0001; } Dest++; @@ -1774,8 +1782,8 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN for (x = 0; x < width; x++ ) { WORD color = *Source++; *Dest = color; - if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) || - (color > surf->SrcBltCKey.dwColorSpaceHighValue)) { + if ((color < This->SrcBltCKey.dwColorSpaceLowValue) || + (color > This->SrcBltCKey.dwColorSpaceHighValue)) { *Dest |= (1 << 15); } else { @@ -1826,6 +1834,38 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN break; } + case CONVERT_X8L8V8U8: + { + unsigned int x, y; + DWORD *Source; + unsigned char *Dest; + + if(GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* This implementation works with the fixed function pipeline and shaders + * without further modification after converting the surface. + */ + for(y = 0; y < height; y++) { + Source = (DWORD *) (src + y * pitch); + Dest = (unsigned char *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) { + long color = (*Source++); + /* L */ Dest[2] = ((color >> 16) & 0xff); /* L */ + /* V */ Dest[1] = ((color >> 8 ) & 0xff); /* V */ + /* U */ Dest[0] = (color & 0xff); /* U */ + /* I */ Dest[3] = 255; /* X */ + Dest += 4; + } + } + } else { + /* Doesn't work correctly with the fixed function pipeline, but can work in + * shaders if the shader is adjusted. (There's no use for this format in gl's + * standard fixed function pipeline anyway). + */ + FIXME("Implement CONVERT_X8L8V8U8 with standard unsigned GL_RGB\n"); + } + break; + } + case CONVERT_A4L4: { unsigned int x, y; diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 6ac8e5472d0..472907fbc1f 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -170,7 +170,7 @@ static const GlPixelFormatDescTemplate gl_formats_template[] = { /* Bump mapping stuff */ {WINED3DFMT_V8U8 ,GL_DSDT8_NV ,GL_DSDT8_NV ,GL_DSDT_NV ,GL_BYTE }, {WINED3DFMT_L6V5U5 ,GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX ,GL_UNSIGNED_SHORT_5_5_5_1 }, - {WINED3DFMT_X8L8V8U8 ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT_MAG_INTENSITY_NV ,GL_BYTE }, + {WINED3DFMT_X8L8V8U8 ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT_MAG_VIB_NV ,GL_UNSIGNED_INT_8_8_S8_S8_REV_NV}, {WINED3DFMT_Q8W8V8U8 ,GL_SIGNED_RGBA8_NV ,GL_SIGNED_RGBA8_NV ,GL_RGBA ,GL_BYTE }, {WINED3DFMT_V16U16 ,GL_SIGNED_HILO16_NV ,GL_SIGNED_HILO16_NV ,GL_HILO_NV ,GL_SHORT }, {WINED3DFMT_W11V11U10 ,0 ,0 ,0 ,0 },