[PATCH 4/4] Add a blit method to arbfp_blit.

Roderick Colenbrander thunderbird2k at gmail.com
Thu Apr 1 05:50:32 CDT 2010


---
 dlls/wined3d/arb_program_shader.c |   68 ++++++++++++++++++++++++++++++++----
 dlls/wined3d/surface.c            |   36 +++++++++++++++++++-
 dlls/wined3d/wined3d_private.h    |    8 ++++-
 3 files changed, 102 insertions(+), 10 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 207df22..f928bc0 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -6820,19 +6820,14 @@ static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info, enum bli
         dump_color_fixup_desc(src_format_desc->color_fixup);
     }
 
+    /* TODO: support color keying in case of 8-bit */
     if (blit_op != BLIT_OP_BLIT)
     {
         TRACE("Unsupported blit_op=%d\n", blit_op);
         return FALSE;
     }
 
-    if (is_identity_fixup(src_format_desc->color_fixup))
-    {
-        TRACE("[OK]\n");
-        return TRUE;
-    }
-
-    /* We only support YUV conversions. */
+    /* We only support complex conversions. */
     if (!is_complex_fixup(src_format_desc->color_fixup))
     {
         TRACE("[FAILED]\n");
@@ -6850,12 +6845,68 @@ static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info, enum bli
             return TRUE;
 
         default:
-            FIXME("Unsupported YUV fixup %#x\n", complex_fixup);
+            FIXME("Unsupported complex fixup %#x\n", complex_fixup);
             TRACE("[FAILED]\n");
             return FALSE;
     }
 }
 
+static HRESULT arbfp_blit_surface(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect,
+                                  IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, enum blit_operation blit_op,
+                                  DWORD Filter)
+{
+    struct wined3d_context *context;
+    IWineD3DSwapChainImpl *dst_swapchain = NULL;
+    RECT dst_rect = *dst_rect_in;
+
+    /* Now load the surface */
+    surface_internal_preload((IWineD3DSurface *)src_surface, SRGB_RGB);
+
+    /* Activate the destination context, set it up for blitting */
+    context = context_acquire(device, (IWineD3DSurface *)dst_surface, CTXUSAGE_BLIT);
+
+    /* The coordinates of the ddraw front buffer are always fullscreen ('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.
+     */
+    IWineD3DSurface_GetContainer((IWineD3DSurface *)dst_surface, &IID_IWineD3DSwapChain, (void **)&dst_swapchain);
+    if (dst_swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *)dst_swapchain);
+    if (dst_swapchain && (IWineD3DSurface *)dst_surface == dst_swapchain->frontBuffer)
+    {
+        RECT windowsize;
+        POINT offset = {0,0};
+        UINT h;
+        ClientToScreen(context->win_handle, &offset);
+        GetClientRect(context->win_handle, &windowsize);
+        h = windowsize.bottom - windowsize.top;
+        dst_rect.left -= offset.x; dst_rect.right -=offset.x;
+        dst_rect.top -= offset.y; dst_rect.bottom -=offset.y;
+        dst_rect.top += dst_surface->currentDesc.Height - h; dst_rect.bottom += dst_surface->currentDesc.Height - h;
+    }
+
+    arbfp_blit.set_shader((IWineD3DDevice *)device, src_surface->resource.format_desc,
+                          src_surface->texture_target, src_surface->pow2Width, src_surface->pow2Height);
+
+    ENTER_GL();
+
+    /* Draw a textured quad */
+    draw_textured_quad(src_surface, src_rect, &dst_rect, Filter);
+
+    LEAVE_GL();
+
+    /* Leave the opengl state valid for blitting */
+    arbfp_blit_unset((IWineD3DDevice *)device);
+
+    wglFlush(); /* Flush to ensure ordering across contexts. */
+
+    context_release(context);
+
+    IWineD3DSurface_ModifyLocation((IWineD3DSurface *)dst_surface, SFLAG_INDRAWABLE, TRUE);
+    return WINED3D_OK;
+}
+
 static HRESULT arbfp_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color)
 {
     FIXME("Color filling not implemented by arbfp_blit\n");
@@ -6868,6 +6919,7 @@ const struct blit_shader arbfp_blit = {
     arbfp_blit_set,
     arbfp_blit_unset,
     arbfp_blit_supported,
+    arbfp_blit_surface,
     arbfp_blit_color_fill
 };
 
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 936a490..2d99c77 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -287,7 +287,7 @@ static inline void surface_get_rect(IWineD3DSurfaceImpl *This, const RECT *rect_
 }
 
 /* GL locking and context activation is done by the caller */
-static void draw_textured_quad(IWineD3DSurfaceImpl *src_surface, const RECT *src_rect, const RECT *dst_rect, WINED3DTEXTUREFILTERTYPE Filter)
+void draw_textured_quad(IWineD3DSurfaceImpl *src_surface, const RECT *src_rect, const RECT *dst_rect, WINED3DTEXTUREFILTERTYPE Filter)
 {
     IWineD3DBaseTextureImpl *texture;
     struct blt_info info;
@@ -4018,9 +4018,13 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const
         WINEDDCOLORKEY oldBltCKey = Src->SrcBltCKey;
         struct wined3d_context *context;
         BOOL paletteOverride = FALSE;
+        enum blit_operation blit_op = BLIT_OP_BLIT;
 
         TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
 
+        if (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE))
+            blit_op = BLIT_OP_COLOR_KEYED_BLIT;
+
         /* When blitting from an offscreen surface to a rendertarget, the source
          * surface is not required to have a palette. Our rendering / conversion
          * code further down the road retrieves the palette from the surface, so
@@ -4050,6 +4054,18 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const
             return WINED3D_OK;
         }
 
+        if (arbfp_blit.blit_supported(&myDevice->adapter->gl_info, blit_op,
+                                      Src->resource.usage, Src->resource.pool, Src->resource.format_desc,
+                                      This->resource.usage, This->resource.pool, This->resource.format_desc))
+        {
+            arbfp_blit.blit(myDevice, Src, &src_rect, This, &dst_rect, blit_op, Filter);
+
+            /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
+            if(paletteOverride)
+                Src->palette = NULL;
+            return WINED3D_OK;
+        }
+
         /* Color keying: Check if we have to do a color keyed blt,
          * and if not check if a color key is activated.
          *
@@ -5219,6 +5235,14 @@ static BOOL ffp_blit_supported(const struct wined3d_gl_info *gl_info, enum blit_
     return FALSE;
 }
 
+static HRESULT ffp_blit_surface(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect,
+                                IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, enum blit_operation blit_op,
+                                DWORD Filter)
+{
+    FIXME("Blitting not implemented by ffp_blit\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
 static HRESULT ffp_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color)
 {
     return IWineD3DDeviceImpl_ClearSurface(device, dst_surface, 1 /* Number of rectangles */,
@@ -5231,6 +5255,7 @@ const struct blit_shader ffp_blit =  {
     ffp_blit_set,
     ffp_blit_unset,
     ffp_blit_supported,
+    ffp_blit_surface,
     ffp_blit_color_fill
 };
 
@@ -5263,6 +5288,14 @@ static BOOL cpu_blit_supported(const struct wined3d_gl_info *gl_info, enum blit_
     return FALSE;
 }
 
+static HRESULT cpu_blit_surface(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect,
+                                IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, enum blit_operation blit_op,
+                                DWORD Filter)
+{
+    FIXME("Blitting not implemented by cpu_blit\n");
+    return WINED3DERR_INVALIDCALL;
+}
+
 static HRESULT cpu_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color)
 {
     WINEDDBLTFX BltFx;
@@ -5278,5 +5311,6 @@ const struct blit_shader cpu_blit =  {
     cpu_blit_set,
     cpu_blit_unset,
     cpu_blit_supported,
+    cpu_blit_surface,
     cpu_blit_color_fill
 };
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index c22d1a3..caef1b2 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1170,7 +1170,8 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_
 
 enum blit_operation
 {
-    BLIT_OP_BLIT
+    BLIT_OP_BLIT,
+    BLIT_OP_COLOR_KEYED_BLIT
 };
 
 /* Shaders for color conversions in blits */
@@ -1184,6 +1185,9 @@ struct blit_shader
     BOOL (*blit_supported)(const struct wined3d_gl_info *gl_info, enum blit_operation blit_op,
                            DWORD src_usage, WINED3DPOOL src_pool, const struct wined3d_format_desc *src_format_desc,
                            DWORD dst_usage, WINED3DPOOL dst_pool, const struct wined3d_format_desc *dst_format_desc);
+    HRESULT (*blit)(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect,
+                    IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, enum blit_operation blit_op,
+                    DWORD Filter);
     HRESULT (*color_fill)(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect, DWORD fill_color);
 };
 
@@ -2168,6 +2172,8 @@ void get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, U
 void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN;
 void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN;
 
+void draw_textured_quad(IWineD3DSurfaceImpl *src_surface, const RECT *src_rect,
+                        const RECT *dst_rect, WINED3DTEXTUREFILTERTYPE Filter) DECLSPEC_HIDDEN;
 void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) DECLSPEC_HIDDEN;
 
 /* Surface flags: */
-- 
1.6.3.3




More information about the wine-patches mailing list