diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index cc13413faf5..6807fc868dd 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -1564,6 +1564,74 @@ static void release_buffer_test(IDirect3DDevice9 *device) IDirect3DVertexBuffer9_Release(vb); } +static void float_texture_test(IDirect3DDevice9 *device) +{ + IDirect3D9 *d3d = NULL; + HRESULT hr; + IDirect3DTexture9 *texture = NULL; + D3DLOCKED_RECT lr; + float *data; + DWORD color; + float quad[] = { + -1.0, -1.0, 0.1, 0.0, 0.0, + -1.0, 1.0, 0.1, 0.0, 1.0, + 1.0, -1.0, 0.1, 1.0, 0.0, + 1.0, 1.0, 0.1, 1.0, 1.0, + }; + + memset(&lr, 0, sizeof(lr)); + IDirect3DDevice9_GetDirect3D(device, &d3d); + if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, + D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) { + skip("D3DFMT_R32F textures not supported\n"); + goto out; + } + + hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F, + D3DPOOL_MANAGED, &texture, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr)); + if(!texture) { + skip("Failed to create R32F texture\n"); + goto out; + } + + hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0); + ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %s\n", DXGetErrorString9(hr)); + data = lr.pBits; + *data = 0.0; + hr = IDirect3DTexture9_UnlockRect(texture, 0); + ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture); + ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr)); + if(SUCCEEDED(hr)) + { + hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1); + ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float)); + ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr); + + hr = IDirect3DDevice9_EndScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr)); + } + hr = IDirect3DDevice9_SetTexture(device, 0, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr)); + + color = getPixelColor(device, 240, 320); + ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color); + +out: + if(texture) IDirect3DTexture9_Release(texture); + IDirect3D9_Release(d3d); +} + START_TEST(visual) { IDirect3DDevice9 *device_ptr; @@ -1639,6 +1707,7 @@ START_TEST(visual) } offscreen_test(device_ptr); release_buffer_test(device_ptr); + float_texture_test(device_ptr); if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0)) { diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 5ba1dec42db..58b4ed61450 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1607,6 +1607,30 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ *target_bpp = 2; break; + case WINED3DFMT_R32F: + /* Can be loaded in theory with fmt=GL_RED, type=GL_FLOAT, but this fails. The reason + * is that D3D expects the undefined green, blue and alpha channels to return 1.0 + * when sampling, but OpenGL sets green and blue to 0.0 instead. Thus we have to inject + * 1.0 instead. + * + * The alpha channel defaults to 1.0 in opengl, so nothing has to be done about it. + */ + *convert = CONVERT_R32F; + *format = GL_RGB; + *internal = GL_RGB32F_ARB; + *type = GL_FLOAT; + *target_bpp = 12; + break; + + case WINED3DFMT_R16F: + /* Simmilar to R32F */ + *convert = CONVERT_R16F; + *format = GL_RGB; + *internal = GL_RGB16F_ARB; + *type = GL_HALF_FLOAT_ARB; + *target_bpp = 6; + break; + default: break; } @@ -1810,6 +1834,45 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN } break; } + + case CONVERT_R32F: + { + unsigned int x, y; + float *Source; + float *Dest; + for(y = 0; y < height; y++) { + Source = (float *) (src + y * pitch); + Dest = (float *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) { + float color = (*Source++); + Dest[0] = color; + Dest[1] = 1.0; + Dest[2] = 1.0; + Dest += 3; + } + } + break; + } + + case CONVERT_R16F: + { + unsigned int x, y; + WORD *Source; + WORD *Dest; + WORD one = 0x3c00; + for(y = 0; y < height; y++) { + Source = (WORD *) (src + y * pitch); + Dest = (WORD *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) { + WORD color = (*Source++); + Dest[0] = color; + Dest[1] = one; + Dest[2] = one; + Dest += 3; + } + } + break; + } default: ERR("Unsupported conversation type %d\n", convert); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3110ce20a0d..29bd24d42c5 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1233,7 +1233,9 @@ typedef enum { CONVERT_X8L8V8U8, CONVERT_Q8W8V8U8, CONVERT_V16U16, - CONVERT_A4L4 + CONVERT_A4L4, + CONVERT_R32F, + CONVERT_R16F } CONVERT_TYPES; HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp, BOOL srgb_mode);