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