[PATCH 3/5] wined3d: Move the OpenGL fixed-function blitter to texture.c.

Henri Verbeet hverbeet at codeweavers.com
Wed Apr 22 16:34:56 CDT 2020


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/surface.c | 390 -----------------------------------------
 dlls/wined3d/texture.c | 389 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 389 insertions(+), 390 deletions(-)

diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 06912203122..2c072454f32 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1106,396 +1106,6 @@ void wined3d_raw_blitter_create(struct wined3d_blitter **next, const struct wine
     *next = blitter;
 }
 
-/* Context activation is done by the caller. */
-static void ffp_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
-{
-    struct wined3d_blitter *next;
-
-    if ((next = blitter->next))
-        next->ops->blitter_destroy(next, context);
-
-    heap_free(blitter);
-}
-
-static BOOL ffp_blit_supported(enum wined3d_blit_op blit_op, const struct wined3d_context *context,
-        const struct wined3d_resource *src_resource, DWORD src_location,
-        const struct wined3d_resource *dst_resource, DWORD dst_location)
-{
-    const struct wined3d_format *src_format = src_resource->format;
-    const struct wined3d_format *dst_format = dst_resource->format;
-    BOOL decompress;
-
-    if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D)
-        return FALSE;
-
-    decompress = (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
-            && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED);
-    if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
-    {
-        TRACE("Source or destination resource is not GPU accessible.\n");
-        return FALSE;
-    }
-
-    if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id)
-    {
-        if (dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
-            blit_op = WINED3D_BLIT_OP_DEPTH_BLIT;
-        else
-            blit_op = WINED3D_BLIT_OP_COLOR_BLIT;
-    }
-
-    switch (blit_op)
-    {
-        case WINED3D_BLIT_OP_COLOR_BLIT_CKEY:
-            if (context->d3d_info->shader_color_key)
-            {
-                TRACE("Color keying requires converted textures.\n");
-                return FALSE;
-            }
-        case WINED3D_BLIT_OP_COLOR_BLIT:
-        case WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST:
-            if (!wined3d_context_gl_const(context)->gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
-                return FALSE;
-
-            if (TRACE_ON(d3d))
-            {
-                TRACE("Checking support for fixup:\n");
-                dump_color_fixup_desc(src_format->color_fixup);
-            }
-
-            /* We only support identity conversions. */
-            if (!is_identity_fixup(src_format->color_fixup)
-                    || !is_identity_fixup(dst_format->color_fixup))
-            {
-                if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER
-                        && dst_format->id == src_format->id && dst_location == WINED3D_LOCATION_DRAWABLE)
-                {
-                    WARN("Claiming fixup support because of ORM_BACKBUFFER.\n");
-                }
-                else
-                {
-                    TRACE("Fixups are not supported.\n");
-                    return FALSE;
-                }
-            }
-
-            if (!(dst_resource->bind_flags & WINED3D_BIND_RENDER_TARGET))
-            {
-                TRACE("Can only blit to render targets.\n");
-                return FALSE;
-            }
-            return TRUE;
-
-        default:
-            TRACE("Unsupported blit operation %#x.\n", blit_op);
-            return FALSE;
-    }
-}
-
-static BOOL ffp_blitter_use_cpu_clear(struct wined3d_rendertarget_view *view)
-{
-    struct wined3d_resource *resource;
-    struct wined3d_texture *texture;
-    DWORD locations;
-
-    resource = view->resource;
-    if (resource->type == WINED3D_RTYPE_BUFFER)
-        return !(resource->access & WINED3D_RESOURCE_ACCESS_GPU);
-
-    texture = texture_from_resource(resource);
-    locations = texture->sub_resources[view->sub_resource_idx].locations;
-    if (locations & (resource->map_binding | WINED3D_LOCATION_DISCARDED))
-        return !(resource->access & WINED3D_RESOURCE_ACCESS_GPU)
-                || (texture->flags & WINED3D_TEXTURE_PIN_SYSMEM);
-
-    return !(resource->access & WINED3D_RESOURCE_ACCESS_GPU)
-            && !(texture->flags & WINED3D_TEXTURE_CONVERTED);
-}
-
-static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_device *device,
-        unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects,
-        const RECT *draw_rect, DWORD flags, const struct wined3d_color *colour, float depth, DWORD stencil)
-{
-    struct wined3d_rendertarget_view *view, *previous = NULL;
-    BOOL have_identical_size = TRUE;
-    struct wined3d_fb_state tmp_fb;
-    unsigned int next_rt_count = 0;
-    struct wined3d_blitter *next;
-    DWORD next_flags = 0;
-    unsigned int i;
-
-    if (flags & WINED3DCLEAR_TARGET)
-    {
-        for (i = 0; i < rt_count; ++i)
-        {
-            if (!(view = fb->render_targets[i]))
-                continue;
-
-            if (ffp_blitter_use_cpu_clear(view)
-                    || (!(view->resource->bind_flags & WINED3D_BIND_RENDER_TARGET)
-                    && (wined3d_settings.offscreen_rendering_mode != ORM_FBO
-                    || !(view->format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE))))
-            {
-                next_flags |= WINED3DCLEAR_TARGET;
-                flags &= ~WINED3DCLEAR_TARGET;
-                next_rt_count = rt_count;
-                rt_count = 0;
-                break;
-            }
-
-            /* FIXME: We should reject colour fills on formats with fixups,
-             * but this would break P8 colour fills for example. */
-        }
-    }
-
-    if ((flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) && (view = fb->depth_stencil)
-            && (!view->format->depth_size || (flags & WINED3DCLEAR_ZBUFFER))
-            && (!view->format->stencil_size || (flags & WINED3DCLEAR_STENCIL))
-            && ffp_blitter_use_cpu_clear(view))
-    {
-        next_flags |= flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL);
-        flags &= ~(WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL);
-    }
-
-    if (flags)
-    {
-        for (i = 0; i < rt_count; ++i)
-        {
-            if (!(view = fb->render_targets[i]))
-                continue;
-
-            if (previous && (previous->width != view->width || previous->height != view->height))
-                have_identical_size = FALSE;
-            previous = view;
-        }
-        if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
-        {
-            view = fb->depth_stencil;
-
-            if (previous && (previous->width != view->width || previous->height != view->height))
-                have_identical_size = FALSE;
-        }
-
-        if (have_identical_size)
-        {
-            device_clear_render_targets(device, rt_count, fb, rect_count,
-                    clear_rects, draw_rect, flags, colour, depth, stencil);
-        }
-        else
-        {
-            for (i = 0; i < rt_count; ++i)
-            {
-                if (!(view = fb->render_targets[i]))
-                    continue;
-
-                tmp_fb.render_targets[0] = view;
-                tmp_fb.depth_stencil = NULL;
-                device_clear_render_targets(device, 1, &tmp_fb, rect_count,
-                        clear_rects, draw_rect, WINED3DCLEAR_TARGET, colour, depth, stencil);
-            }
-            if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
-            {
-                tmp_fb.render_targets[0] = NULL;
-                tmp_fb.depth_stencil = fb->depth_stencil;
-                device_clear_render_targets(device, 0, &tmp_fb, rect_count,
-                        clear_rects, draw_rect, flags & ~WINED3DCLEAR_TARGET, colour, depth, stencil);
-            }
-        }
-    }
-
-    if (next_flags && (next = blitter->next))
-        next->ops->blitter_clear(next, device, next_rt_count, fb, rect_count,
-                clear_rects, draw_rect, next_flags, colour, depth, stencil);
-}
-
-static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
-        struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
-        DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture,
-        unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect,
-        const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter)
-{
-    struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture);
-    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
-    const struct wined3d_gl_info *gl_info = context_gl->gl_info;
-    struct wined3d_resource *src_resource, *dst_resource;
-    struct wined3d_texture *staging_texture = NULL;
-    struct wined3d_color_key old_blt_key;
-    struct wined3d_device *device;
-    struct wined3d_blitter *next;
-    DWORD old_color_key_flags;
-    RECT r;
-
-    src_resource = &src_texture->resource;
-    dst_resource = &dst_texture->resource;
-    device = dst_resource->device;
-
-    if (!ffp_blit_supported(op, context, src_resource, src_location, dst_resource, dst_location))
-    {
-        if ((next = blitter->next))
-            return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location,
-                    src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, color_key, filter);
-    }
-
-    TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n",
-            src_texture, src_sub_resource_idx, dst_texture, dst_sub_resource_idx);
-
-    old_blt_key = src_texture->async.src_blt_color_key;
-    old_color_key_flags = src_texture->async.color_key_flags;
-    wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT, color_key);
-
-    if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
-    {
-        struct wined3d_resource_desc desc;
-        struct wined3d_box upload_box;
-        unsigned int src_level;
-        HRESULT hr;
-
-        TRACE("Source texture is not GPU accessible, creating a staging texture.\n");
-
-        src_level = src_sub_resource_idx % src_texture->level_count;
-        desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
-        desc.format = src_texture->resource.format->id;
-        desc.multisample_type = src_texture->resource.multisample_type;
-        desc.multisample_quality = src_texture->resource.multisample_quality;
-        desc.usage = WINED3DUSAGE_PRIVATE;
-        desc.bind_flags = 0;
-        desc.access = WINED3D_RESOURCE_ACCESS_GPU;
-        desc.width = wined3d_texture_get_level_width(src_texture, src_level);
-        desc.height = wined3d_texture_get_level_height(src_texture, src_level);
-        desc.depth = 1;
-        desc.size = 0;
-
-        if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0,
-                NULL, NULL, &wined3d_null_parent_ops, &staging_texture)))
-        {
-            ERR("Failed to create staging texture, hr %#x.\n", hr);
-            return dst_location;
-        }
-
-        wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth);
-        wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0,
-                src_texture, src_sub_resource_idx, &upload_box);
-
-        src_texture = staging_texture;
-        src_texture_gl = wined3d_texture_gl(src_texture);
-        src_sub_resource_idx = 0;
-    }
-    else
-    {
-        /* Make sure the surface is up-to-date. This should probably use
-         * surface_load_location() and worry about the destination surface
-         * too, unless we're overwriting it completely. */
-        wined3d_texture_load(src_texture, context, FALSE);
-    }
-
-    wined3d_context_gl_apply_ffp_blit_state(context_gl, device);
-
-    if (dst_location == WINED3D_LOCATION_DRAWABLE)
-    {
-        r = *dst_rect;
-        wined3d_texture_translate_drawable_coords(dst_texture, context_gl->window, &r);
-        dst_rect = &r;
-    }
-
-    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
-    {
-        GLenum buffer;
-
-        if (dst_location == WINED3D_LOCATION_DRAWABLE)
-        {
-            TRACE("Destination texture %p is onscreen.\n", dst_texture);
-            buffer = wined3d_texture_get_gl_buffer(dst_texture);
-        }
-        else
-        {
-            TRACE("Destination texture %p is offscreen.\n", dst_texture);
-            buffer = GL_COLOR_ATTACHMENT0;
-        }
-        wined3d_context_gl_apply_fbo_state_blit(context_gl, GL_DRAW_FRAMEBUFFER,
-                dst_resource, dst_sub_resource_idx, NULL, 0, dst_location);
-        wined3d_context_gl_set_draw_buffer(context_gl, buffer);
-        wined3d_context_gl_check_fbo_status(context_gl, GL_DRAW_FRAMEBUFFER);
-        context_invalidate_state(context, STATE_FRAMEBUFFER);
-    }
-
-    gl_info->gl_ops.gl.p_glEnable(src_texture_gl->target);
-    checkGLcall("glEnable(target)");
-
-    if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST || color_key)
-    {
-        gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST);
-        checkGLcall("glEnable(GL_ALPHA_TEST)");
-    }
-
-    if (color_key)
-    {
-        /* For P8 surfaces, the alpha component contains the palette index.
-         * Which means that the colorkey is one of the palette entries. In
-         * other cases pixels that should be masked away have alpha set to 0. */
-        if (src_texture->resource.format->id == WINED3DFMT_P8_UINT)
-            gl_info->gl_ops.gl.p_glAlphaFunc(GL_NOTEQUAL,
-                    (float)src_texture->async.src_blt_color_key.color_space_low_value / 255.0f);
-        else
-            gl_info->gl_ops.gl.p_glAlphaFunc(GL_NOTEQUAL, 0.0f);
-        checkGLcall("glAlphaFunc");
-    }
-
-    wined3d_context_gl_draw_textured_quad(context_gl, src_texture_gl,
-            src_sub_resource_idx, src_rect, dst_rect, filter);
-
-    if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST || color_key)
-    {
-        gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
-        checkGLcall("glDisable(GL_ALPHA_TEST)");
-    }
-
-    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
-    checkGLcall("glDisable(GL_TEXTURE_2D)");
-    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
-    {
-        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
-        checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
-    }
-    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
-    {
-        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
-        checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
-    }
-
-    if (dst_texture->swapchain && dst_texture->swapchain->front_buffer == dst_texture)
-        gl_info->gl_ops.gl.p_glFlush();
-
-    /* Restore the color key parameters */
-    wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT,
-            (old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_blt_key : NULL);
-
-    if (staging_texture)
-        wined3d_texture_decref(staging_texture);
-
-    return dst_location;
-}
-
-static const struct wined3d_blitter_ops ffp_blitter_ops =
-{
-    ffp_blitter_destroy,
-    ffp_blitter_clear,
-    ffp_blitter_blit,
-};
-
-void wined3d_ffp_blitter_create(struct wined3d_blitter **next, const struct wined3d_gl_info *gl_info)
-{
-    struct wined3d_blitter *blitter;
-
-    if (!(blitter = heap_alloc(sizeof(*blitter))))
-        return;
-
-    TRACE("Created blitter %p.\n", blitter);
-
-    blitter->ops = &ffp_blitter_ops;
-    blitter->next = *next;
-    *next = blitter;
-}
-
 /* Context activation is done by the caller. */
 static void cpu_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
 {
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index ac3601d4f47..c11490057c3 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -4821,3 +4821,392 @@ HRESULT wined3d_texture_vk_init(struct wined3d_texture_vk *texture_vk, struct wi
     return wined3d_texture_init(&texture_vk->t, desc, layer_count, level_count,
             flags, device, parent, parent_ops, &texture_vk[1], &wined3d_texture_vk_ops);
 }
+
+static void ffp_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
+{
+    struct wined3d_blitter *next;
+
+    if ((next = blitter->next))
+        next->ops->blitter_destroy(next, context);
+
+    heap_free(blitter);
+}
+
+static bool ffp_blit_supported(enum wined3d_blit_op blit_op, const struct wined3d_context *context,
+        const struct wined3d_resource *src_resource, DWORD src_location,
+        const struct wined3d_resource *dst_resource, DWORD dst_location)
+{
+    const struct wined3d_format *src_format = src_resource->format;
+    const struct wined3d_format *dst_format = dst_resource->format;
+    bool decompress;
+
+    if (src_resource->type != WINED3D_RTYPE_TEXTURE_2D)
+        return false;
+
+    decompress = (src_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
+            && !(dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED);
+    if (!decompress && !(src_resource->access & dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
+    {
+        TRACE("Source or destination resource is not GPU accessible.\n");
+        return false;
+    }
+
+    if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id)
+    {
+        if (dst_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
+            blit_op = WINED3D_BLIT_OP_DEPTH_BLIT;
+        else
+            blit_op = WINED3D_BLIT_OP_COLOR_BLIT;
+    }
+
+    switch (blit_op)
+    {
+        case WINED3D_BLIT_OP_COLOR_BLIT_CKEY:
+            if (context->d3d_info->shader_color_key)
+            {
+                TRACE("Colour keying requires converted textures.\n");
+                return false;
+            }
+        case WINED3D_BLIT_OP_COLOR_BLIT:
+        case WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST:
+            if (!wined3d_context_gl_const(context)->gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
+                return false;
+
+            if (TRACE_ON(d3d))
+            {
+                TRACE("Checking support for fixup:\n");
+                dump_color_fixup_desc(src_format->color_fixup);
+            }
+
+            /* We only support identity conversions. */
+            if (!is_identity_fixup(src_format->color_fixup)
+                    || !is_identity_fixup(dst_format->color_fixup))
+            {
+                if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER
+                        && dst_format->id == src_format->id && dst_location == WINED3D_LOCATION_DRAWABLE)
+                {
+                    WARN("Claiming fixup support because of ORM_BACKBUFFER.\n");
+                }
+                else
+                {
+                    TRACE("Fixups are not supported.\n");
+                    return false;
+                }
+            }
+
+            if (!(dst_resource->bind_flags & WINED3D_BIND_RENDER_TARGET))
+            {
+                TRACE("Can only blit to render targets.\n");
+                return false;
+            }
+            return true;
+
+        default:
+            TRACE("Unsupported blit operation %#x.\n", blit_op);
+            return false;
+    }
+}
+
+static bool ffp_blitter_use_cpu_clear(struct wined3d_rendertarget_view *view)
+{
+    struct wined3d_resource *resource;
+    struct wined3d_texture *texture;
+    DWORD locations;
+
+    resource = view->resource;
+    if (resource->type == WINED3D_RTYPE_BUFFER)
+        return !(resource->access & WINED3D_RESOURCE_ACCESS_GPU);
+
+    texture = texture_from_resource(resource);
+    locations = texture->sub_resources[view->sub_resource_idx].locations;
+    if (locations & (resource->map_binding | WINED3D_LOCATION_DISCARDED))
+        return !(resource->access & WINED3D_RESOURCE_ACCESS_GPU)
+                || (texture->flags & WINED3D_TEXTURE_PIN_SYSMEM);
+
+    return !(resource->access & WINED3D_RESOURCE_ACCESS_GPU)
+            && !(texture->flags & WINED3D_TEXTURE_CONVERTED);
+}
+
+static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_device *device,
+        unsigned int rt_count, const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects,
+        const RECT *draw_rect, DWORD flags, const struct wined3d_color *colour, float depth, DWORD stencil)
+{
+    struct wined3d_rendertarget_view *view, *previous = NULL;
+    bool have_identical_size = TRUE;
+    struct wined3d_fb_state tmp_fb;
+    unsigned int next_rt_count = 0;
+    struct wined3d_blitter *next;
+    DWORD next_flags = 0;
+    unsigned int i;
+
+    if (flags & WINED3DCLEAR_TARGET)
+    {
+        for (i = 0; i < rt_count; ++i)
+        {
+            if (!(view = fb->render_targets[i]))
+                continue;
+
+            if (ffp_blitter_use_cpu_clear(view)
+                    || (!(view->resource->bind_flags & WINED3D_BIND_RENDER_TARGET)
+                    && (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+                    || !(view->format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE))))
+            {
+                next_flags |= WINED3DCLEAR_TARGET;
+                flags &= ~WINED3DCLEAR_TARGET;
+                next_rt_count = rt_count;
+                rt_count = 0;
+                break;
+            }
+
+            /* FIXME: We should reject colour fills on formats with fixups,
+             * but this would break P8 colour fills for example. */
+        }
+    }
+
+    if ((flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) && (view = fb->depth_stencil)
+            && (!view->format->depth_size || (flags & WINED3DCLEAR_ZBUFFER))
+            && (!view->format->stencil_size || (flags & WINED3DCLEAR_STENCIL))
+            && ffp_blitter_use_cpu_clear(view))
+    {
+        next_flags |= flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL);
+        flags &= ~(WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL);
+    }
+
+    if (flags)
+    {
+        for (i = 0; i < rt_count; ++i)
+        {
+            if (!(view = fb->render_targets[i]))
+                continue;
+
+            if (previous && (previous->width != view->width || previous->height != view->height))
+                have_identical_size = false;
+            previous = view;
+        }
+        if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
+        {
+            view = fb->depth_stencil;
+
+            if (previous && (previous->width != view->width || previous->height != view->height))
+                have_identical_size = false;
+        }
+
+        if (have_identical_size)
+        {
+            device_clear_render_targets(device, rt_count, fb, rect_count,
+                    clear_rects, draw_rect, flags, colour, depth, stencil);
+        }
+        else
+        {
+            for (i = 0; i < rt_count; ++i)
+            {
+                if (!(view = fb->render_targets[i]))
+                    continue;
+
+                tmp_fb.render_targets[0] = view;
+                tmp_fb.depth_stencil = NULL;
+                device_clear_render_targets(device, 1, &tmp_fb, rect_count,
+                        clear_rects, draw_rect, WINED3DCLEAR_TARGET, colour, depth, stencil);
+            }
+            if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
+            {
+                tmp_fb.render_targets[0] = NULL;
+                tmp_fb.depth_stencil = fb->depth_stencil;
+                device_clear_render_targets(device, 0, &tmp_fb, rect_count,
+                        clear_rects, draw_rect, flags & ~WINED3DCLEAR_TARGET, colour, depth, stencil);
+            }
+        }
+    }
+
+    if (next_flags && (next = blitter->next))
+        next->ops->blitter_clear(next, device, next_rt_count, fb, rect_count,
+                clear_rects, draw_rect, next_flags, colour, depth, stencil);
+}
+
+static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op,
+        struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx,
+        DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture,
+        unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect,
+        const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter)
+{
+    struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture);
+    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
+    const struct wined3d_gl_info *gl_info = context_gl->gl_info;
+    struct wined3d_resource *src_resource, *dst_resource;
+    struct wined3d_texture *staging_texture = NULL;
+    struct wined3d_color_key old_blt_key;
+    struct wined3d_device *device;
+    struct wined3d_blitter *next;
+    DWORD old_colour_key_flags;
+    RECT r;
+
+    src_resource = &src_texture->resource;
+    dst_resource = &dst_texture->resource;
+    device = dst_resource->device;
+
+    if (!ffp_blit_supported(op, context, src_resource, src_location, dst_resource, dst_location))
+    {
+        if ((next = blitter->next))
+            return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location,
+                    src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter);
+    }
+
+    TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n",
+            src_texture, src_sub_resource_idx, dst_texture, dst_sub_resource_idx);
+
+    old_blt_key = src_texture->async.src_blt_color_key;
+    old_colour_key_flags = src_texture->async.color_key_flags;
+    wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT, colour_key);
+
+    if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
+    {
+        struct wined3d_resource_desc desc;
+        struct wined3d_box upload_box;
+        unsigned int src_level;
+        HRESULT hr;
+
+        TRACE("Source texture is not GPU accessible, creating a staging texture.\n");
+
+        src_level = src_sub_resource_idx % src_texture->level_count;
+        desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
+        desc.format = src_texture->resource.format->id;
+        desc.multisample_type = src_texture->resource.multisample_type;
+        desc.multisample_quality = src_texture->resource.multisample_quality;
+        desc.usage = WINED3DUSAGE_PRIVATE;
+        desc.bind_flags = 0;
+        desc.access = WINED3D_RESOURCE_ACCESS_GPU;
+        desc.width = wined3d_texture_get_level_width(src_texture, src_level);
+        desc.height = wined3d_texture_get_level_height(src_texture, src_level);
+        desc.depth = 1;
+        desc.size = 0;
+
+        if (FAILED(hr = wined3d_texture_create(device, &desc, 1, 1, 0,
+                NULL, NULL, &wined3d_null_parent_ops, &staging_texture)))
+        {
+            ERR("Failed to create staging texture, hr %#x.\n", hr);
+            return dst_location;
+        }
+
+        wined3d_box_set(&upload_box, 0, 0, desc.width, desc.height, 0, desc.depth);
+        wined3d_texture_upload_from_texture(staging_texture, 0, 0, 0, 0,
+                src_texture, src_sub_resource_idx, &upload_box);
+
+        src_texture = staging_texture;
+        src_texture_gl = wined3d_texture_gl(src_texture);
+        src_sub_resource_idx = 0;
+    }
+    else
+    {
+        /* Make sure the surface is up-to-date. This should probably use
+         * surface_load_location() and worry about the destination surface
+         * too, unless we're overwriting it completely. */
+        wined3d_texture_load(src_texture, context, FALSE);
+    }
+
+    wined3d_context_gl_apply_ffp_blit_state(context_gl, device);
+
+    if (dst_location == WINED3D_LOCATION_DRAWABLE)
+    {
+        r = *dst_rect;
+        wined3d_texture_translate_drawable_coords(dst_texture, context_gl->window, &r);
+        dst_rect = &r;
+    }
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    {
+        GLenum buffer;
+
+        if (dst_location == WINED3D_LOCATION_DRAWABLE)
+        {
+            TRACE("Destination texture %p is onscreen.\n", dst_texture);
+            buffer = wined3d_texture_get_gl_buffer(dst_texture);
+        }
+        else
+        {
+            TRACE("Destination texture %p is offscreen.\n", dst_texture);
+            buffer = GL_COLOR_ATTACHMENT0;
+        }
+        wined3d_context_gl_apply_fbo_state_blit(context_gl, GL_DRAW_FRAMEBUFFER,
+                dst_resource, dst_sub_resource_idx, NULL, 0, dst_location);
+        wined3d_context_gl_set_draw_buffer(context_gl, buffer);
+        wined3d_context_gl_check_fbo_status(context_gl, GL_DRAW_FRAMEBUFFER);
+        context_invalidate_state(context, STATE_FRAMEBUFFER);
+    }
+
+    gl_info->gl_ops.gl.p_glEnable(src_texture_gl->target);
+    checkGLcall("glEnable(target)");
+
+    if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST || colour_key)
+    {
+        gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST);
+        checkGLcall("glEnable(GL_ALPHA_TEST)");
+    }
+
+    if (colour_key)
+    {
+        /* For P8 surfaces, the alpha component contains the palette index.
+         * Which means that the colourkey is one of the palette entries. In
+         * other cases pixels that should be masked away have alpha set to 0. */
+        if (src_texture->resource.format->id == WINED3DFMT_P8_UINT)
+            gl_info->gl_ops.gl.p_glAlphaFunc(GL_NOTEQUAL,
+                    (float)src_texture->async.src_blt_color_key.color_space_low_value / 255.0f);
+        else
+            gl_info->gl_ops.gl.p_glAlphaFunc(GL_NOTEQUAL, 0.0f);
+        checkGLcall("glAlphaFunc");
+    }
+
+    wined3d_context_gl_draw_textured_quad(context_gl, src_texture_gl,
+            src_sub_resource_idx, src_rect, dst_rect, filter);
+
+    if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST || colour_key)
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
+        checkGLcall("glDisable(GL_ALPHA_TEST)");
+    }
+
+    gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
+    checkGLcall("glDisable(GL_TEXTURE_2D)");
+    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+        checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
+    }
+    if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
+        checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
+    }
+
+    if (dst_texture->swapchain && dst_texture->swapchain->front_buffer == dst_texture)
+        gl_info->gl_ops.gl.p_glFlush();
+
+    /* Restore the colour key parameters */
+    wined3d_texture_set_color_key(src_texture, WINED3D_CKEY_SRC_BLT,
+            (old_colour_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_blt_key : NULL);
+
+    if (staging_texture)
+        wined3d_texture_decref(staging_texture);
+
+    return dst_location;
+}
+
+static const struct wined3d_blitter_ops ffp_blitter_ops =
+{
+    ffp_blitter_destroy,
+    ffp_blitter_clear,
+    ffp_blitter_blit,
+};
+
+void wined3d_ffp_blitter_create(struct wined3d_blitter **next, const struct wined3d_gl_info *gl_info)
+{
+    struct wined3d_blitter *blitter;
+
+    if (!(blitter = heap_alloc(sizeof(*blitter))))
+        return;
+
+    TRACE("Created blitter %p.\n", blitter);
+
+    blitter->ops = &ffp_blitter_ops;
+    blitter->next = *next;
+    *next = blitter;
+}
-- 
2.20.1




More information about the wine-devel mailing list