[PATCH 2/5] wined3d: Track render_offscreen in the context.

Henri Verbeet hverbeet at codeweavers.com
Thu Aug 6 01:12:19 CDT 2009


This makes sure the relevant states in FindContext() are actually marked dirty
when needed.
---
 dlls/wined3d/arb_program_shader.c |    8 +++++---
 dlls/wined3d/context.c            |   22 ++++++++++++----------
 dlls/wined3d/device.c             |   10 ++++++----
 dlls/wined3d/drawprim.c           |    2 +-
 dlls/wined3d/glsl_shader.c        |   19 ++++++++++---------
 dlls/wined3d/state.c              |   27 ++++++++++++++++-----------
 dlls/wined3d/surface.c            |    9 ++++++---
 dlls/wined3d/wined3d_private.h    |    5 ++---
 8 files changed, 58 insertions(+), 44 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 9b891a2..180d929 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -428,8 +428,9 @@ static void shader_arb_load_np2fixup_constants(
 /* GL locking is done by the caller. */
 static inline void shader_arb_ps_local_constants(IWineD3DDeviceImpl* deviceImpl)
 {
+    const struct wined3d_context *context = context_get_current();
     IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
-    const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
     unsigned char i;
     struct shader_arb_priv *priv = deviceImpl->shader_priv;
     const struct arb_ps_compiled_shader *gl_shader = priv->compiled_fprog;
@@ -463,8 +464,9 @@ static inline void shader_arb_ps_local_constants(IWineD3DDeviceImpl* deviceImpl)
         * ycorrection.w: 0.0
         */
         float val[4];
-        val[0] = deviceImpl->render_offscreen ? 0.0f : ((IWineD3DSurfaceImpl *) deviceImpl->render_targets[0])->currentDesc.Height;
-        val[1] = deviceImpl->render_offscreen ? 1.0f : -1.0f;
+        val[0] = context->render_offscreen ? 0.0f
+                : ((IWineD3DSurfaceImpl *) deviceImpl->render_targets[0])->currentDesc.Height;
+        val[1] = context->render_offscreen ? 1.0f : -1.0f;
         val[2] = 1.0f;
         val[3] = 0.0f;
         GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->ycorrection, val));
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index d0b23b7..6cd67f2 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -438,9 +438,7 @@ static void context_apply_fbo_entry(struct wined3d_context *context, struct fbo_
 /* GL locking is done by the caller */
 static void context_apply_fbo_state(struct wined3d_context *context)
 {
-    IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.wineD3DDevice;
-
-    if (device->render_offscreen)
+    if (context->render_offscreen)
     {
         context->current_fbo = context_find_fbo_entry(context);
         context_apply_fbo_entry(context, context->current_fbo);
@@ -1723,11 +1721,10 @@ static struct wined3d_context *findThreadContextForSwapChain(IWineD3DSwapChain *
 static inline struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, DWORD tid)
 {
     IWineD3DSwapChain *swapchain = NULL;
-    BOOL readTexture = wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_offscreen;
     struct wined3d_context *current_context = context_get_current();
-    BOOL oldRenderOffscreen = This->render_offscreen;
     const struct StateEntry *StateTable = This->StateTable;
     struct wined3d_context *context;
+    BOOL old_render_offscreen;
 
     if (current_context && current_context->destroyed) current_context = NULL;
 
@@ -1757,7 +1754,8 @@ static inline struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWin
 
         context = findThreadContextForSwapChain(swapchain, tid);
 
-        This->render_offscreen = FALSE;
+        old_render_offscreen = context->render_offscreen;
+        context->render_offscreen = FALSE;
         /* The context != This->activeContext will catch a NOP context change. This can occur
          * if we are switching back to swapchain rendering in case of FBO or Back Buffer offscreen
          * rendering. No context change is needed in that case
@@ -1773,7 +1771,6 @@ static inline struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWin
     else
     {
         TRACE("Rendering offscreen\n");
-        This->render_offscreen = TRUE;
 
 retry:
         if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER)
@@ -1831,9 +1828,12 @@ retry:
                 context = findThreadContextForSwapChain(This->swapchains[0], tid);
             }
         }
+
+        old_render_offscreen = context->render_offscreen;
+        context->render_offscreen = TRUE;
     }
 
-    if (This->render_offscreen != oldRenderOffscreen)
+    if (context->render_offscreen != old_render_offscreen)
     {
         Context_MarkStateDirty(context, WINED3DTS_PROJECTION, StateTable);
         Context_MarkStateDirty(context, STATE_VDECL, StateTable);
@@ -1890,7 +1890,8 @@ retry:
      *    After that, the outer ActivateContext(which calls PreLoad) can activate the new
      *    target for the new thread
      */
-    if (readTexture && context->current_rt && context->current_rt != target)
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && old_render_offscreen
+            && context->current_rt && context->current_rt != target)
     {
         BOOL oldInDraw = This->isInDraw;
 
@@ -2035,7 +2036,8 @@ struct wined3d_context *ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurfac
 
         case CTXUSAGE_BLIT:
             if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
-                if (This->render_offscreen) {
+                if (context->render_offscreen)
+                {
                     FIXME("Activating for CTXUSAGE_BLIT for an offscreen target with ORM_FBO. This should be avoided.\n");
                     ENTER_GL();
                     context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->dst_fbo);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 40ea34d..c9e50d1 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4939,7 +4939,7 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This,  IWineD3DSurfa
     }
 
     if (Flags & WINED3DCLEAR_ZBUFFER) {
-        DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
+        DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
         glDepthMask(GL_TRUE);
         glClearDepth(Z);
         checkGLcall("glClearDepth");
@@ -4985,7 +4985,8 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This,  IWineD3DSurfa
         if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
             IntersectRect(&vp_rect, &vp_rect, &This->stateBlock->scissorRect);
         }
-        if(This->render_offscreen) {
+        if (context->render_offscreen)
+        {
             glScissor(vp_rect.left, vp_rect.top,
                         vp_rect.right - vp_rect.left, vp_rect.bottom - vp_rect.top);
         } else {
@@ -5017,7 +5018,8 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This,  IWineD3DSurfa
                 continue;
             }
 
-            if(This->render_offscreen) {
+            if (context->render_offscreen)
+            {
                 glScissor(curRect.x1, curRect.y1,
                           curRect.x2 - curRect.x1, curRect.y2 - curRect.y1);
             } else {
@@ -5049,7 +5051,7 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This,  IWineD3DSurfa
     }
     if (Flags & WINED3DCLEAR_ZBUFFER) {
         /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
-        DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
+        DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
         surface_modify_ds_location(This->stencilBufferTarget, location);
     }
 
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index d6d1469..09cb960 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -589,7 +589,7 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT numberOfVertice
          * Z-compare function into account, but we could skip loading the
          * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note
          * that we never copy the stencil data.*/
-        DWORD location = This->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
+        DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN;
         if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE]
                 || This->stateBlock->renderState[WINED3DRS_ZENABLE])
             surface_load_ds_location(This->stencilBufferTarget, context, location);
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 95649ec..a6b98ff 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -627,15 +627,13 @@ static void shader_glsl_load_np2fixup_constants(
  * Loads the app-supplied constants into the currently set GLSL program.
  */
 /* GL locking is done by the caller (state handler) */
-static void shader_glsl_load_constants(
-    IWineD3DDevice* device,
-    char usePixelShader,
-    char useVertexShader) {
-   
+static void shader_glsl_load_constants(IWineD3DDevice *device, char usePixelShader, char useVertexShader)
+{
+    const struct wined3d_context *context = context_get_current();
     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device;
     struct shader_glsl_priv *priv = deviceImpl->shader_priv;
     IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
-    const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
 
     GLhandleARB programId;
     struct glsl_shader_prog_link *prog = priv->glsl_program;
@@ -713,7 +711,9 @@ static void shader_glsl_load_constants(
 
         if(((IWineD3DPixelShaderImpl *) pshader)->vpos_uniform) {
             float correction_params[4];
-            if(deviceImpl->render_offscreen) {
+
+            if (context->render_offscreen)
+            {
                 correction_params[0] = 0.0f;
                 correction_params[1] = 1.0f;
             } else {
@@ -808,6 +808,7 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
         struct wined3d_shader_buffer *buffer, const struct wined3d_gl_info *gl_info,
         struct shader_glsl_ctx_priv *ctx_priv)
 {
+    const struct wined3d_context *context = context_get_current();
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
     const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args;
@@ -931,8 +932,8 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
                  */
                 FIXME("Cannot find a free uniform for vpos correction params\n");
                 shader_addline(buffer, "const vec4 ycorrection = vec4(%f, %f, 0.0, 0.0);\n",
-                        device->render_offscreen ? 0.0f : ((IWineD3DSurfaceImpl *)device->render_targets[0])->currentDesc.Height,
-                        device->render_offscreen ? 1.0f : -1.0f);
+                        context->render_offscreen ? 0.0f : ((IWineD3DSurfaceImpl *)device->render_targets[0])->currentDesc.Height,
+                        context->render_offscreen ? 1.0f : -1.0f);
             }
             shader_addline(buffer, "vec4 vpos;\n");
         }
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index c8f3d4d..c61f897 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -3591,9 +3591,7 @@ static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wi
         glMatrixMode(GL_MODELVIEW);
         glPushMatrix();
         glLoadIdentity();
-        if(stateblock->wineD3DDevice->render_offscreen) {
-            glScalef(1.0f, -1.0f, 1.0f);
-        }
+        if (context->render_offscreen) glScalef(1.0f, -1.0f, 1.0f);
     }
 
     TRACE("Clipplane [%f,%f,%f,%f]\n",
@@ -3808,7 +3806,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock
              * problem either.
              */
             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
-            if(stateblock->wineD3DDevice->render_offscreen) {
+            if (context->render_offscreen)
+            {
                 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
             } else {
                 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
@@ -3822,7 +3821,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock
              * replacement shader.
              */
             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
-            if(stateblock->wineD3DDevice->render_offscreen) {
+            if (context->render_offscreen)
+            {
                 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
             } else {
                 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
@@ -3835,7 +3835,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock
         checkGLcall("glTranslatef(0.5f, 0.5f, 0.0f)");
         /* D3D texture coordinates are flipped compared to OpenGL ones, so
          * render everything upside down when rendering offscreen. */
-        if (stateblock->wineD3DDevice->render_offscreen) {
+        if (context->render_offscreen)
+        {
             glScalef(1.0f, -1.0f, 1.0f);
             checkGLcall("glScalef");
         }
@@ -3877,7 +3878,8 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock
          * glScalef(1.0, flip, 2.0);
          */
 
-        if (stateblock->wineD3DDevice->render_offscreen) {
+        if (context->render_offscreen)
+        {
             /* D3D texture coordinates are flipped compared to OpenGL ones, so
              * render everything upside down when rendering offscreen. */
             glTranslatef(1.0f / stateblock->viewport.Width, 1.0f / stateblock->viewport.Height, -1.0f);
@@ -4489,7 +4491,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, s
          * TODO: Move to the viewport state
          */
         if (useVertexShaderFunction) {
-            device->posFixup[1] = device->render_offscreen ? -1.0f : 1.0f;
+            device->posFixup[1] = context->render_offscreen ? -1.0f : 1.0f;
             device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
         }
     }
@@ -4616,7 +4618,8 @@ static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, s
     checkGLcall("glDepthRange");
     /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
      */
-    if(stateblock->wineD3DDevice->render_offscreen) {
+    if (context->render_offscreen)
+    {
         glViewport(stateblock->viewport.X,
                    stateblock->viewport.Y,
                    stateblock->viewport.Width, stateblock->viewport.Height);
@@ -4774,7 +4777,8 @@ static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, struct
     TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
           pRect->right - pRect->left, pRect->bottom - pRect->top);
 
-    if (stateblock->wineD3DDevice->render_offscreen) {
+    if (context->render_offscreen)
+    {
         glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
     } else {
         glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
@@ -4794,7 +4798,8 @@ static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, struct
 
 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
 {
-    if(stateblock->wineD3DDevice->render_offscreen) {
+    if (context->render_offscreen)
+    {
         glFrontFace(GL_CCW);
         checkGLcall("glFrontFace(GL_CCW)");
     } else {
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 1cf4c71..66bdbed 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -4529,7 +4529,9 @@ static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct float
     f->b = ((r->bottom * 2.0f) / h) - 1.0f;
 }
 
-static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in) {
+static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in)
+{
+    const struct wined3d_context *context;
     struct coords coords[4];
     RECT rect;
     IWineD3DSwapChain *swapchain;
@@ -4636,7 +4638,8 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT
             return;
     }
 
-    ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT);
+    context = ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT);
+
     ENTER_GL();
 
     glEnable(bind_target);
@@ -4648,7 +4651,7 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT
     glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     checkGLcall("glTexParameteri");
 
-    if (device->render_offscreen)
+    if (context->render_offscreen)
     {
         LONG tmp = rect.top;
         rect.top = rect.bottom;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index c83ee20..414b519 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1169,6 +1169,7 @@ struct wined3d_context
     DWORD                   tid;    /* Thread ID which owns this context at the moment */
 
     /* Stores some information about the context state for optimization */
+    WORD render_offscreen : 1;
     WORD draw_buffer_dirty : 1;
     WORD last_was_rhw : 1;              /* true iff last draw_primitive was in xyzrhw mode */
     WORD last_was_pshader : 1;
@@ -1183,7 +1184,6 @@ struct wined3d_context
     WORD num_untracked_materials : 2;   /* Max value 2 */
     WORD current : 1;
     WORD destroyed : 1;
-    WORD padding : 1;
     BYTE texShaderBumpMap;              /* MAX_TEXTURES, 8 */
     BYTE lastWasPow2Texture;            /* MAX_TEXTURES, 8 */
     DWORD                   numbered_array_mask;
@@ -1535,7 +1535,6 @@ struct IWineD3DDeviceImpl
     WORD vertexBlendUsed : 1;           /* To avoid needless setting of the blend matrices */
     WORD isRecordingState : 1;
     WORD isInDraw : 1;
-    WORD render_offscreen : 1;
     WORD bCursorVisible : 1;
     WORD haveHardwareCursor : 1;
     WORD d3d_initialized : 1;
@@ -1543,7 +1542,7 @@ struct IWineD3DDeviceImpl
     WORD softwareVertexProcessing : 1;  /* process vertex shaders using software or hardware */
     WORD useDrawStridedSlow : 1;
     WORD instancedDraw : 1;
-    WORD padding : 3;
+    WORD padding : 4;
 
     BYTE fixed_function_usage_map;      /* MAX_TEXTURES, 8 */
 
-- 
1.6.0.6




More information about the wine-patches mailing list