Stefan Dösinger : wined3d: Beware of the frontbuffer coordinate system difference.

Alexandre Julliard julliard at winehq.org
Mon Aug 4 08:53:36 CDT 2008


Module: wine
Branch: master
Commit: 474e7ed98c23348ac227c0f611e0bf25d7fe8345
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=474e7ed98c23348ac227c0f611e0bf25d7fe8345

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Sun Aug  3 11:33:07 2008 -0500

wined3d: Beware of the frontbuffer coordinate system difference.

---

 dlls/wined3d/device.c  |   42 ++++++++++++++++++++++++++++++++----------
 dlls/wined3d/surface.c |   36 +++++++++++++++++++++++++++---------
 2 files changed, 59 insertions(+), 19 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 12ec046..ffe1cf3 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -6606,6 +6606,7 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED
     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
     IWineD3DSwapChain *src_swapchain, *dst_swapchain;
     GLenum gl_filter;
+    POINT offset = {0, 0};
 
     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter, flip);
@@ -6628,7 +6629,7 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED
     /* Attach src surface to src fbo */
     src_swapchain = get_swapchain(src_surface);
     if (src_swapchain) {
-        GLenum buffer;
+        GLenum buffer = surface_get_gl_buffer(src_surface, src_swapchain);
 
         TRACE("Source surface %p is onscreen\n", src_surface);
         ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD);
@@ -6636,14 +6637,24 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED
          * attach_surface_fbo() implicitly takes care of this. */
         IWineD3DSurface_LoadLocation(src_surface, SFLAG_INDRAWABLE, NULL);
 
+        if(buffer == GL_FRONT) {
+            RECT windowsize;
+            UINT h;
+            ClientToScreen(This->ddraw_window, &offset);
+            GetClientRect(This->ddraw_window, &windowsize);
+            h = windowsize.bottom - windowsize.top;
+            src_rect->x1 -= offset.x; src_rect->x2 -=offset.x;
+            src_rect->y1 =  offset.y + h - src_rect->y1;
+            src_rect->y2 =  offset.y + h - src_rect->y2;
+        } else {
+            src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
+            src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
+        }
+
         ENTER_GL();
         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
-        buffer = surface_get_gl_buffer(src_surface, src_swapchain);
         glReadBuffer(buffer);
         checkGLcall("glReadBuffer()");
-
-        src_rect->y1 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y1;
-        src_rect->y2 = ((IWineD3DSurfaceImpl *)src_surface)->currentDesc.Height - src_rect->y2;
     } else {
         TRACE("Source surface %p is offscreen\n", src_surface);
         ENTER_GL();
@@ -6659,7 +6670,7 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED
     /* Attach dst surface to dst fbo */
     dst_swapchain = get_swapchain(dst_surface);
     if (dst_swapchain) {
-        GLenum buffer;
+        GLenum buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
 
         TRACE("Destination surface %p is onscreen\n", dst_surface);
         ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD);
@@ -6667,14 +6678,25 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED
          * attach_surface_fbo() implicitly takes care of this. */
         IWineD3DSurface_LoadLocation(dst_surface, SFLAG_INDRAWABLE, NULL);
 
+        if(buffer == GL_FRONT) {
+            RECT windowsize;
+            UINT h;
+            ClientToScreen(This->ddraw_window, &offset);
+            GetClientRect(This->ddraw_window, &windowsize);
+            h = windowsize.bottom - windowsize.top;
+            dst_rect->x1 -= offset.x; dst_rect->x2 -=offset.x;
+            dst_rect->y1 =  offset.y + h - dst_rect->y1;
+            dst_rect->y2 =  offset.y + h - dst_rect->y2;
+        } else {
+            /* Screen coords = window coords, surface height = window height */
+            dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
+            dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
+        }
+
         ENTER_GL();
         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
-        buffer = surface_get_gl_buffer(dst_surface, dst_swapchain);
         glDrawBuffer(buffer);
         checkGLcall("glDrawBuffer()");
-
-        dst_rect->y1 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y1;
-        dst_rect->y2 = ((IWineD3DSurfaceImpl *)dst_surface)->currentDesc.Height - dst_rect->y2;
     } else {
         TRACE("Destination surface %p is offscreen\n", dst_surface);
 
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 2227243..cb4d879 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -3268,6 +3268,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
         WINEDDCOLORKEY oldBltCKey = Src->SrcBltCKey;
         RECT SourceRectangle;
         BOOL paletteOverride = FALSE;
+        GLenum buffer;
 
         TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
 
@@ -3340,22 +3341,39 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
 
         /* Activate the destination context, set it up for blitting */
         ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
-        ENTER_GL();
-
-        glEnable(Src->glDescription.target);
-        checkGLcall("glEnable(Src->glDescription.target)");
 
         if(!dstSwapchain) {
             TRACE("Drawing to offscreen buffer\n");
-            glDrawBuffer(myDevice->offscreenBuffer);
-            checkGLcall("glDrawBuffer");
+            buffer = myDevice->offscreenBuffer;
         } else {
-            GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *)This, (IWineD3DSwapChain *)dstSwapchain);
+            buffer = surface_get_gl_buffer((IWineD3DSurface *)This, (IWineD3DSwapChain *)dstSwapchain);
+
+            /* Front buffer coordinates are screen coordinates, while OpenGL coordinates are
+             * window relative. Also beware of the origin difference(top left vs bottom left).
+             * Also beware that the front buffer's surface size is screen width x screen height,
+             * whereas the real gl drawable size is the size of the window.
+             */
+            if(buffer == GL_FRONT) {
+                RECT windowsize;
+                POINT offset = {0,0};
+                UINT h;
+                ClientToScreen(myDevice->ddraw_window, &offset);
+                GetClientRect(myDevice->ddraw_window, &windowsize);
+                h = windowsize.bottom - windowsize.top;
+                rect.x1 -= offset.x; rect.x2 -=offset.x;
+                rect.y1 -= offset.y; rect.y2 -=offset.y;
+                rect.y1 += This->currentDesc.Height - h; rect.y2 += This->currentDesc.Height - h;
+            }
             TRACE("Drawing to %#x buffer\n", buffer);
-            glDrawBuffer(buffer);
-            checkGLcall("glDrawBuffer");
         }
 
+        ENTER_GL();
+        glDrawBuffer(buffer);
+        checkGLcall("glDrawBuffer");
+
+        glEnable(Src->glDescription.target);
+        checkGLcall("glEnable(Src->glDescription.target)");
+
         /* Bind the texture */
         glBindTexture(Src->glDescription.target, Src->glDescription.textureName);
         checkGLcall("glBindTexture");




More information about the wine-cvs mailing list