diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 89ee91b0d4e..97989baa770 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1845,6 +1845,73 @@ WINED3DFORMAT DepthStencilFormat) return FALSE; } +/* Check the render target capabilities of a format */ +static BOOL CheckRenderTargetCapability(WINED3DFORMAT AdapterFormat, WINED3DFORMAT CheckFormat) +{ + UINT Adapter = 0; + + /* Filter out non-RT formats */ + switch(CheckFormat) + { + /* Don't offer 8bit, windows doesn't either although we could emulate it */ + case WINED3DFMT_A8P8: + case WINED3DFMT_P8: + + /* No DXTC render targets */ + case WINED3DFMT_DXT1: + case WINED3DFMT_DXT2: + case WINED3DFMT_DXT3: + case WINED3DFMT_DXT4: + case WINED3DFMT_DXT5: + return FALSE; + default: + break; + } + + if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) { + WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs; + int it; + short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize; + short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize; + + getColorBits(AdapterFormat, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize); + getColorBits(CheckFormat, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize); + + /* In backbuffer mode the front and backbuffer share the same WGL pixelformat. + * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */ + if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) { + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + } + + /* Check if there is a WGL pixel format matching the requirements, the format should also be window + * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */ + for (it = 0; it < Adapters[Adapter].nCfgs; ++it) { + if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) { + TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat)); + return TRUE; + } + } + } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) { + /* We can propably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */ + WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs; + int it; + + /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */ + for (it = 0; it < Adapters[Adapter].nCfgs; ++it) { + if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) { + TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat)); + return TRUE; + } + } + } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){ + /* For now return TRUE for FBOs until we have some proper checks. + * Note that this function will only be called when the format is around for texturing. */ + return TRUE; + } + return FALSE; +} + /* Check if a texture format is supported on the given adapter */ static BOOL CheckTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat) { @@ -2095,6 +2162,15 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt /* No usage checks were requested, so return because we know that the format is supported */ if(!Usage) return WINED3D_OK; + + if(Usage & WINED3DUSAGE_RENDERTARGET) { + if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_RENDERTARGET; + } else { + TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } } } } else if(RType == WINED3DRTYPE_SURFACE) { @@ -2111,7 +2187,16 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n"); return WINED3DERR_NOTAVAILABLE; } - } + } + + if(Usage & WINED3DUSAGE_RENDERTARGET) { + if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_RENDERTARGET; + } else { + TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } } else if(RType == WINED3DRTYPE_TEXTURE) { /* Texture allows: * - D3DUSAGE_AUTOGENMIPMAP @@ -2130,6 +2215,14 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt if(!Usage) return WINED3D_OK; + if(Usage & WINED3DUSAGE_RENDERTARGET) { + if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) { + UsageCaps |= WINED3DUSAGE_RENDERTARGET; + } else { + TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n"); + return WINED3DERR_NOTAVAILABLE; + } + } } else if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) { if(Usage & WINED3DUSAGE_DEPTHSTENCIL) UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL; @@ -2215,43 +2308,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt } } - if(Usage & WINED3DUSAGE_RENDERTARGET) { - switch (CheckFormat) { - case WINED3DFMT_R8G8B8: - case WINED3DFMT_A8R8G8B8: - case WINED3DFMT_X8R8G8B8: - case WINED3DFMT_R5G6B5: - case WINED3DFMT_X1R5G5B5: - case WINED3DFMT_A1R5G5B5: - case WINED3DFMT_A4R4G4B4: - case WINED3DFMT_R3G3B2: - case WINED3DFMT_X4R4G4B4: - case WINED3DFMT_A8B8G8R8: - case WINED3DFMT_X8B8G8R8: - case WINED3DFMT_P8: - case WINED3DFMT_G16R16: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - case WINED3DFMT_R16F: - case WINED3DFMT_A16B16G16R16F: - if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) { - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - case WINED3DFMT_A32B32G32R32F: - if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) { - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - default: - TRACE_(d3d_caps)("[FAILED]\n"); - return WINED3DERR_NOTAVAILABLE; - } - } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) { + if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) { if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) { switch (CheckFormat) { case WINED3DFMT_V8U8: @@ -3672,6 +3729,7 @@ BOOL InitAdapters(void) { PUSH1(WGL_ALPHA_BITS_ARB) PUSH1(WGL_DEPTH_BITS_ARB) PUSH1(WGL_STENCIL_BITS_ARB) + PUSH1(WGL_DRAW_TO_WINDOW_ARB) for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) { res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values)); @@ -3687,8 +3745,19 @@ BOOL InitAdapters(void) { cfgs->alphaSize = values[3]; cfgs->depthSize = values[4]; cfgs->stencilSize = values[5]; + cfgs->windowDrawable = values[6]; - TRACE("iPixelFormat=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d\n", cfgs->iPixelFormat, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize); + cfgs->pbufferDrawable = FALSE; + /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown +attributes. */ + if(GL_SUPPORT(WGL_ARB_PBUFFER)) { + int attrib = WGL_DRAW_TO_PBUFFER_ARB; + int value; + if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value))) + cfgs->pbufferDrawable = value; + } + + TRACE("iPixelFormat=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable); cfgs++; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index a3efde989d4..6b0cfb8b374 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -638,6 +638,8 @@ typedef struct WineD3D_PixelFormat int iPixelFormat; /* WGL pixel format */ int redSize, greenSize, blueSize, alphaSize; int depthSize, stencilSize; + BOOL windowDrawable; + BOOL pbufferDrawable; } WineD3D_PixelFormat; /* The adapter structure */