[4/5] wined3d: Allow wined3d to handle multiple render targets

H. Verbeet hverbeet at gmail.com
Tue Dec 19 12:25:42 CST 2006


This increases the draw buffer limit to the amount the graphics card
supports. As a result of this the assumption that the render target
index can only be 0 has to be removed. Although the first render
target can never be set to 0, higher render targets can, and typically
will be.

Changelog:
  - Allow wined3d to handle multiple render targets
-------------- next part --------------
---

 dlls/wined3d/device.c      |   28 +++++++++++++++++-----------
 dlls/wined3d/directx.c     |   13 +++++++------
 dlls/wined3d/glsl_shader.c |   12 ++++--------
 3 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index bc5fd32..069771e 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -5643,11 +5643,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
 
-    /* FIXME: Implelent RenderTargetIndex >0 */
-    if(RenderTargetIndex > 0)
-        FIXME("(%p) : RenderTargetIndex %d >0 not currently supported\n", This, RenderTargetIndex);
+    if (RenderTargetIndex >= GL_LIMITS(buffers)) {
+        ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
+        return WINED3DERR_INVALIDCALL;
+    }
 
-    *ppRenderTarget = This->render_targets[0];
+    *ppRenderTarget = This->render_targets[RenderTargetIndex];
     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
     /* Note inc ref on returned surface */
     if(*ppRenderTarget != NULL)
@@ -5849,10 +5850,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     HRESULT  hr = WINED3D_OK;
     WINED3DVIEWPORT viewport;
 
-    TRACE("(%p) Swapping rendertarget\n",This);
-    if (RenderTargetIndex > 0) {
-        FIXME("(%p) Render targets other than the first are not supported\n",This);
-        RenderTargetIndex = 0;
+    TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
+
+    if (RenderTargetIndex >= GL_LIMITS(buffers)) {
+        ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
+        return WINED3DERR_INVALIDCALL;
     }
 
     /* MSDN says that null disables the render target
@@ -5867,7 +5869,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         return WINED3DERR_INVALIDCALL;
     }
     /* TODO: replace Impl* usage with interface usage */
-    if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
+    if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
         FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
         return WINED3DERR_INVALIDCALL;
     }
@@ -5875,7 +5877,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
      *        builds, but I think wine counts as a 'debug' build for now.
       ******************************/
     /* If we are trying to set what we already have, don't bother */
-    if (pRenderTarget == This->render_targets[0]) {
+    if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
         TRACE("Trying to do a NOP SetRenderTarget operation\n");
     } else {
         /* Otherwise, set the render target up */
@@ -5890,7 +5892,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         A shared context implementation will share all buffers between all rendertargets (including swapchains),
         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
         stencil buffer and incure an extra memory overhead */
-        hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
+        if (RenderTargetIndex == 0) {
+            hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
+        } else {
+            hr = WINED3D_OK;
+        }
 
         /* Replace the render target */
         if (This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index b3b891f..fb65bab 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -804,6 +804,11 @@ #undef USE_GL_FUNC
         wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
     }
 
+    /* MRTs are currently only supported when FBOs are used. */
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
+        gl_info->max_buffers = 1;
+    }
+
     /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
      * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
      * in case of the latest videocards in the number of pixel/vertex pipelines.
@@ -2284,12 +2289,8 @@ #endif
         } else
             *pCaps->DeclTypes                         = 0;
 
-#if 0 /* We don't properly support multiple render targets yet, so disable this for now */
-        if (GL_SUPPORT(ARB_DRAWBUFFERS)) {
-            *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
-        } else    
-#endif
-            *pCaps->NumSimultaneousRTs = 1;
+        *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
+
             
         *pCaps->StretchRectFilterCaps             = 0;
         *pCaps->VertexTextureFilterCaps           = 0;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index dffc1aa..17b6a47 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -680,17 +680,13 @@ static void shader_glsl_get_register_nam
             sprintf(tmpStr, "Vsampler%u", reg);
     break;
     case WINED3DSPR_COLOROUT:
+        if (reg >= GL_LIMITS(buffers)) {
+            WARN("Write to render target %u, only %d supported\n", reg, 4);
+        }
         if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
             sprintf(tmpStr, "gl_FragData[%u]", reg);
-            if (reg > 0) {
-                /* TODO: See GL_ARB_draw_buffers */
-                FIXME("Unsupported write to render target %u\n", reg);
-            }
         } else { /* On older cards with GLSL support like the GeforceFX there's only one buffer. */
-            if (reg > 0)
-                WARN("This OpenGL implementation doesn't support writing to multiple render targets!\n");
-            else
-                sprintf(tmpStr, "gl_FragColor");
+            sprintf(tmpStr, "gl_FragColor");
         }
     break;
     case WINED3DSPR_RASTOUT:


More information about the wine-patches mailing list