[PATCH 3/5] wined3d: Use staging resources to blit from CPU resources in the GLSL blitter.
Henri Verbeet
hverbeet at codeweavers.com
Mon Apr 16 08:29:28 CDT 2018
From: Matteo Bruni <mbruni at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/wined3d/glsl_shader.c | 49 ++++++++++++++++++++++++++++----
dlls/wined3d/surface.c | 64 ++++++------------------------------------
dlls/wined3d/texture.c | 46 ++++++++++++++++++++++++++++++
dlls/wined3d/wined3d_private.h | 3 ++
4 files changed, 100 insertions(+), 62 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index e839369f11c..7f1e66bc877 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -12428,11 +12428,9 @@ static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wi
return FALSE;
}
- /* FIXME: We never want to blit from resources without
+ /* We don't necessarily want to blit from resources without
* WINED3D_RESOURCE_ACCESS_GPU, but that may be the only way to decompress
- * compressed textures. We should probably create an explicit staging
- * texture for this purpose instead of loading the resource into an
- * invalid location. */
+ * compressed textures. */
decompress = src_format && (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))
@@ -12465,8 +12463,10 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
{
struct wined3d_device *device = dst_texture->resource.device;
const struct wined3d_gl_info *gl_info = context->gl_info;
+ struct wined3d_texture *staging_texture = NULL;
struct wined3d_glsl_blitter *glsl_blitter;
struct wined3d_blitter *next;
+ unsigned int src_level;
GLuint program_id;
RECT s, d;
@@ -12491,12 +12491,45 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter);
- if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
+ if (!(src_texture->resource.access & WINED3D_RESOURCE_ACCESS_GPU))
+ {
+ struct wined3d_resource_desc desc;
+ struct wined3d_box upload_box;
+ 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.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_sub_resource_idx = 0;
+ }
+ else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
&& (src_texture->sub_resources[src_sub_resource_idx].locations
& (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) == WINED3D_LOCATION_DRAWABLE
&& !wined3d_resource_is_offscreen(&src_texture->resource))
{
- unsigned int src_level = src_sub_resource_idx % src_texture->level_count;
/* Without FBO blits transferring from the drawable to the texture is
* expensive, because we have to flip the data in sysmem. Since we can
@@ -12506,6 +12539,7 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
texture2d_load_fb_texture(src_texture, src_sub_resource_idx, FALSE, context);
s = *src_rect;
+ src_level = src_sub_resource_idx % src_texture->level_count;
s.top = wined3d_texture_get_level_height(src_texture, src_level) - s.top;
s.bottom = wined3d_texture_get_level_height(src_texture, src_level) - s.bottom;
src_rect = &s;
@@ -12557,6 +12591,9 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
if (dst_texture->swapchain && (dst_texture->swapchain->front_buffer == dst_texture))
gl_info->gl_ops.gl.p_glFlush();
+ if (staging_texture)
+ wined3d_texture_decref(staging_texture);
+
return dst_location;
}
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index ad4ed1c33a8..7a13b5883be 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -566,52 +566,6 @@ static void texture2d_download_data(struct wined3d_texture *texture, unsigned in
heap_free(temporary_mem);
}
-static HRESULT texture2d_upload_from_surface(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
- unsigned int dst_x, unsigned int dst_y, struct wined3d_texture *src_texture,
- unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
-{
- unsigned int src_row_pitch, src_slice_pitch;
- unsigned int src_level, dst_level;
- struct wined3d_context *context;
- struct wined3d_bo_address data;
- UINT update_w, update_h;
-
- TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, "
- "src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
- dst_texture, dst_sub_resource_idx, dst_x, dst_y,
- src_texture, src_sub_resource_idx, debug_box(src_box));
-
- context = context_acquire(dst_texture->resource.device, NULL, 0);
-
- /* Only load the sub-resource for partial updates. For newly allocated
- * textures the texture wouldn't be the current location, and we'd upload
- * zeroes just to overwrite them again. */
- update_w = src_box->right - src_box->left;
- update_h = src_box->bottom - src_box->top;
- dst_level = dst_sub_resource_idx % dst_texture->level_count;
- if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level)
- && update_h == wined3d_texture_get_level_height(dst_texture, dst_level))
- wined3d_texture_prepare_texture(dst_texture, context, FALSE);
- else
- wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
- wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
-
- src_level = src_sub_resource_idx % src_texture->level_count;
- wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data,
- src_texture->sub_resources[src_sub_resource_idx].locations);
- wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch);
-
- wined3d_texture_upload_data(dst_texture, dst_sub_resource_idx, context, src_texture->resource.format,
- src_box, wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, dst_x, dst_y, 0, FALSE);
-
- context_release(context);
-
- wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
- wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
-
- return WINED3D_OK;
-}
-
/* See also float_16_to_32() in wined3d_private.h */
static inline unsigned short float_32_to_16(const float *in)
{
@@ -3459,18 +3413,16 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_
TRACE("Not doing upload because the destination format needs conversion.\n");
else
{
- if (SUCCEEDED(texture2d_upload_from_surface(dst_texture, dst_sub_resource_idx,
- dst_box->left, dst_box->top, src_texture, src_sub_resource_idx, src_box)))
+ wined3d_texture_upload_from_texture(dst_texture, dst_sub_resource_idx, dst_box->left,
+ dst_box->top, dst_box->front, src_texture, src_sub_resource_idx, src_box);
+ if (!wined3d_resource_is_offscreen(&dst_texture->resource))
{
- if (!wined3d_resource_is_offscreen(&dst_texture->resource))
- {
- context = context_acquire(device, dst_texture, dst_sub_resource_idx);
- wined3d_texture_load_location(dst_texture, dst_sub_resource_idx,
- context, dst_texture->resource.draw_binding);
- context_release(context);
- }
- return WINED3D_OK;
+ context = context_acquire(device, dst_texture, dst_sub_resource_idx);
+ wined3d_texture_load_location(dst_texture, dst_sub_resource_idx,
+ context, dst_texture->resource.draw_binding);
+ context_release(context);
}
+ return WINED3D_OK;
}
}
else if (dst_swapchain && dst_swapchain->back_buffers
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 427ed4f3570..dadcd0323a0 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -3488,3 +3488,49 @@ HRESULT CDECL wined3d_texture_release_dc(struct wined3d_texture *texture, unsign
return WINED3D_OK;
}
+
+void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+ unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture,
+ unsigned int src_sub_resource_idx, const struct wined3d_box *src_box)
+{
+ unsigned int src_row_pitch, src_slice_pitch;
+ unsigned int update_w, update_h, update_d;
+ unsigned int src_level, dst_level;
+ struct wined3d_context *context;
+ struct wined3d_bo_address data;
+
+ TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
+ "src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
+ dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z,
+ src_texture, src_sub_resource_idx, debug_box(src_box));
+
+ context = context_acquire(dst_texture->resource.device, NULL, 0);
+
+ /* Only load the sub-resource for partial updates. For newly allocated
+ * textures the texture wouldn't be the current location, and we'd upload
+ * zeroes just to overwrite them again. */
+ update_w = src_box->right - src_box->left;
+ update_h = src_box->bottom - src_box->top;
+ update_d = src_box->back - src_box->front;
+ dst_level = dst_sub_resource_idx % dst_texture->level_count;
+ if (update_w == wined3d_texture_get_level_width(dst_texture, dst_level)
+ && update_h == wined3d_texture_get_level_height(dst_texture, dst_level)
+ && update_d == wined3d_texture_get_level_depth(dst_texture, dst_level))
+ wined3d_texture_prepare_texture(dst_texture, context, FALSE);
+ else
+ wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB);
+ wined3d_texture_bind_and_dirtify(dst_texture, context, FALSE);
+
+ src_level = src_sub_resource_idx % src_texture->level_count;
+ wined3d_texture_get_memory(src_texture, src_sub_resource_idx, &data,
+ src_texture->sub_resources[src_sub_resource_idx].locations);
+ wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch);
+
+ wined3d_texture_upload_data(dst_texture, dst_sub_resource_idx, context, src_texture->resource.format,
+ src_box, wined3d_const_bo_address(&data), src_row_pitch, src_slice_pitch, dst_x, dst_y, dst_z, FALSE);
+
+ context_release(context);
+
+ wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
+ wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e5a61e7af0e..24d923265e3 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3305,6 +3305,9 @@ void wined3d_texture_upload_data(struct wined3d_texture *texture, unsigned int s
struct wined3d_context *context, const struct wined3d_format *format, const struct wined3d_box *src_box,
const struct wined3d_const_bo_address *data, unsigned int row_pitch, unsigned int slice_pitch,
unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, BOOL srgb) DECLSPEC_HIDDEN;
+void wined3d_texture_upload_from_texture(struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx,
+ unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, struct wined3d_texture *src_texture,
+ unsigned int src_sub_resource_idx, const struct wined3d_box *src_box) DECLSPEC_HIDDEN;
void wined3d_texture_validate_location(struct wined3d_texture *texture,
unsigned int sub_resource_idx, DWORD location) DECLSPEC_HIDDEN;
--
2.11.0
More information about the wine-devel
mailing list