From deeeda6802bc3fbca599ad287c5fcfd69172a525 Mon Sep 17 00:00:00 2001 From: "H. Verbeet" Date: Mon, 16 Apr 2007 21:20:56 +0200 Subject: [PATCH] wined3d: Properly handle the difference between GL_BACK and GL_FRONT for onscreen surfaces. --- dlls/wined3d/device.c | 44 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 2fe9c0ef824..1e3d18a165d 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5280,23 +5280,24 @@ void apply_fbo_state(IWineD3DDevice *iface) { check_fbo_status(iface); } -static BOOL is_onscreen(IWineD3DSurface *target) { +static IWineD3DSwapChain *get_swapchain(IWineD3DSurface *target) { HRESULT hr; - void *tmp; + IWineD3DSwapChain *swapchain; - hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, &tmp); + hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, (void **)&swapchain); if (SUCCEEDED(hr)) { - IWineD3DSwapChain_Release((IUnknown *)tmp); - return TRUE; + IWineD3DSwapChain_Release((IUnknown *)swapchain); + return swapchain; } - return FALSE; + return NULL; } void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const WINED3DRECT *src_rect, IWineD3DSurface *dst_surface, const WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */ + IWineD3DSwapChain *src_swapchain, *dst_swapchain; GLenum gl_filter; TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n", @@ -5321,25 +5322,45 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const } /* Attach src surface to src fbo */ - if (is_onscreen(src_surface)) { + src_swapchain = get_swapchain(src_surface); + if (src_swapchain) { + GLenum buffer; + TRACE("Source surface %p is onscreen\n", src_surface); + GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0)); + buffer = surface_get_gl_buffer(src_surface, src_swapchain); + glReadBuffer(buffer); + checkGLcall("glReadBuffer()"); + flip = !flip; } else { TRACE("Source surface %p is offscreen\n", src_surface); bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo); attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + checkGLcall("glReadBuffer()"); } /* Attach dst surface to dst fbo */ - if (is_onscreen(dst_surface)) { + dst_swapchain = get_swapchain(dst_surface); + if (dst_swapchain) { + GLenum buffer; + TRACE("Destination surface %p is onscreen\n", dst_surface); + GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0)); + buffer = surface_get_gl_buffer(dst_surface, dst_swapchain); + glDrawBuffer(buffer); + checkGLcall("glDrawBuffer()"); + flip = !flip; } else { TRACE("Destination surface %p is offscreen\n", dst_surface); bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo); attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + checkGLcall("glDrawBuffer()"); } if (flip) { @@ -5356,6 +5377,13 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); checkGLcall("glBindFramebuffer()"); } + + /* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */ + if (dst_swapchain && dst_surface == ((IWineD3DSwapChainImpl *)dst_swapchain)->frontBuffer + && ((IWineD3DSwapChainImpl *)dst_swapchain)->backBuffer) { + glDrawBuffer(GL_BACK); + checkGLcall("glDrawBuffer()"); + } } static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {