Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/texture.c | 58 +++++++++++++++++++++++++++------- dlls/wined3d/wined3d_private.h | 3 ++ 2 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index c495de171d5..18fd0847296 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -816,17 +816,8 @@ BOOL wined3d_texture_load_location(struct wined3d_texture *texture,
if (current & WINED3D_LOCATION_CLEARED) { - struct wined3d_bo_address addr; - - /* FIXME: Clear textures on the GPU if possible. */ - - if (!wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM)) - return FALSE; - wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); - memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size); - wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM); - current |= WINED3D_LOCATION_SYSMEM; - + texture->texture_ops->texture_clear(texture, sub_resource_idx, context, location); + current = texture->sub_resources[sub_resource_idx].locations; if (current & location) return TRUE; } @@ -3447,6 +3438,20 @@ static void wined3d_texture_gl_unload_location(struct wined3d_texture *texture, } }
+static void wined3d_texture_gl_clear(struct wined3d_texture *texture, + unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) +{ + struct wined3d_bo_address addr; + + TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", + texture, sub_resource_idx, context, wined3d_debug_location(location)); + + wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM); + wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); + memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size); + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM); +} + static const struct wined3d_texture_ops texture_gl_ops = { wined3d_texture_gl_prepare_location, @@ -3454,6 +3459,7 @@ static const struct wined3d_texture_ops texture_gl_ops = wined3d_texture_gl_unload_location, wined3d_texture_gl_upload_data, wined3d_texture_gl_download_data, + wined3d_texture_gl_clear, };
struct wined3d_texture * __cdecl wined3d_texture_from_resource(struct wined3d_resource *resource) @@ -4681,6 +4687,20 @@ static void wined3d_texture_no3d_unload_location(struct wined3d_texture *texture TRACE("texture %p, context %p, location %s.\n", texture, context, wined3d_debug_location(location)); }
+static void wined3d_texture_no3d_clear(struct wined3d_texture *texture, + unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) +{ + struct wined3d_bo_address addr; + + TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", + texture, sub_resource_idx, context, wined3d_debug_location(location)); + + wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM); + wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); + memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size); + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM); +} + static const struct wined3d_texture_ops wined3d_texture_no3d_ops = { wined3d_texture_no3d_prepare_location, @@ -4688,6 +4708,7 @@ static const struct wined3d_texture_ops wined3d_texture_no3d_ops = wined3d_texture_no3d_unload_location, wined3d_texture_no3d_upload_data, wined3d_texture_no3d_download_data, + wined3d_texture_no3d_clear, };
HRESULT wined3d_texture_no3d_init(struct wined3d_texture *texture_no3d, struct wined3d_device *device, @@ -5458,6 +5479,20 @@ static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture, } }
+static void wined3d_texture_vk_clear(struct wined3d_texture *texture, + unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) +{ + struct wined3d_bo_address addr; + + TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", + texture, sub_resource_idx, context, wined3d_debug_location(location)); + + wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM); + wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); + memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size); + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM); +} + static const struct wined3d_texture_ops wined3d_texture_vk_ops = { wined3d_texture_vk_prepare_location, @@ -5465,6 +5500,7 @@ static const struct wined3d_texture_ops wined3d_texture_vk_ops = wined3d_texture_vk_unload_location, wined3d_texture_vk_upload_data, wined3d_texture_vk_download_data, + wined3d_texture_vk_clear, };
HRESULT wined3d_texture_vk_init(struct wined3d_texture_vk *texture_vk, struct wined3d_device *device, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 54bccb3db5e..9cfb3a217d2 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4393,6 +4393,9 @@ struct wined3d_texture_ops const struct wined3d_bo_address *dst_bo_addr, const struct wined3d_format *dst_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, unsigned int dst_row_pitch, unsigned int dst_slice_pitch); + /* "location" is a hint, and need not be the resulting location. */ + void (*texture_clear)(struct wined3d_texture *texture, unsigned int sub_resource_idx, + struct wined3d_context *context, unsigned int location); };
#define WINED3D_TEXTURE_COND_NP2 0x00000001
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/texture.c | 62 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 18fd0847296..27ce651422e 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -5482,15 +5482,69 @@ static void wined3d_texture_vk_unload_location(struct wined3d_texture *texture, static void wined3d_texture_vk_clear(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) { + struct wined3d_context_vk *context_vk = wined3d_context_vk(context); + struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture); + const struct wined3d_format *format = texture->resource.format; + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + static const VkClearDepthStencilValue depth_value; + static const VkClearColorValue colour_value; + VkCommandBuffer vk_command_buffer; + VkImageSubresourceRange vk_range; struct wined3d_bo_address addr; + VkImageAspectFlags aspect_mask; + VkImage vk_image;
TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", texture, sub_resource_idx, context, wined3d_debug_location(location));
- wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM); - wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); - memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size); - wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM); + if (location == WINED3D_LOCATION_TEXTURE_RGB) + { + wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB); + vk_image = texture_vk->image.vk_image; + + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + { + ERR("Failed to get command buffer.\n"); + return; + } + + aspect_mask = vk_aspect_mask_from_format(format); + + vk_range.aspectMask = aspect_mask; + vk_range.baseMipLevel = sub_resource_idx % texture->level_count; + vk_range.levelCount = 1; + vk_range.baseArrayLayer = sub_resource_idx / texture->level_count; + vk_range.layerCount = 1; + + wined3d_context_vk_end_current_render_pass(context_vk); + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + vk_access_mask_from_bind_flags(texture->resource.bind_flags), VK_ACCESS_TRANSFER_WRITE_BIT, + texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk_image, &vk_range); + + if (format->depth_size || format->stencil_size) + VK_CALL(vkCmdClearDepthStencilImage(vk_command_buffer, vk_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depth_value, 1, &vk_range)); + else + VK_CALL(vkCmdClearColorImage(vk_command_buffer, vk_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colour_value, 1, &vk_range)); + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, vk_access_mask_from_bind_flags(texture->resource.bind_flags), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_vk->layout, vk_image, &vk_range); + wined3d_context_vk_reference_texture(context_vk, texture_vk); + + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB); + } + else + { + wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM); + wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); + memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size); + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM); + } }
static const struct wined3d_texture_ops wined3d_texture_vk_ops =
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/arb_program_shader.c | 21 +--------------- dlls/wined3d/context_gl.c | 38 ++++++++++++++++++++++++++++ dlls/wined3d/glsl_shader.c | 21 +--------------- dlls/wined3d/texture.c | 42 +++---------------------------- dlls/wined3d/wined3d_private.h | 2 ++ 5 files changed, 46 insertions(+), 78 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index b4c395ec355..12606bbd0b0 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -7908,26 +7908,7 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl dst_rect = &d; }
- 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_texture->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); - } + context_gl_apply_texture_draw_state(context_gl, dst_texture, dst_sub_resource_idx, dst_location);
if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST) { diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 8ac5c28c892..dd4204067bc 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -3613,6 +3613,44 @@ static uint32_t find_draw_buffers_mask(const struct wined3d_context_gl *context_ return rt_mask; }
+void context_gl_apply_texture_draw_state(struct wined3d_context_gl *context_gl, + struct wined3d_texture *texture, unsigned int sub_resource_idx, unsigned int location) +{ + const struct wined3d_format *format = texture->resource.format; + GLenum buffer; + + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) + return; + + if (format->depth_size || format->stencil_size) + { + wined3d_context_gl_apply_fbo_state_blit(context_gl, GL_DRAW_FRAMEBUFFER, + NULL, 0, &texture->resource, sub_resource_idx, location); + + buffer = GL_NONE; + } + else + { + wined3d_context_gl_apply_fbo_state_blit(context_gl, GL_DRAW_FRAMEBUFFER, + &texture->resource, sub_resource_idx, NULL, 0, location); + + if (location == WINED3D_LOCATION_DRAWABLE) + { + TRACE("Texture %p is onscreen.\n", texture); + buffer = wined3d_texture_get_gl_buffer(texture); + } + else + { + TRACE("Texture %p is offscreen.\n", texture); + buffer = GL_COLOR_ATTACHMENT0; + } + } + + wined3d_context_gl_set_draw_buffer(context_gl, buffer); + wined3d_context_gl_check_fbo_status(context_gl, GL_DRAW_FRAMEBUFFER); + context_invalidate_state(&context_gl->c, STATE_FRAMEBUFFER); +} + /* Context activation is done by the caller. */ void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index f79fa1571e6..82c022e4ba7 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -13205,26 +13205,7 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli dst_rect = &d; }
- 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_texture->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); - } + context_gl_apply_texture_draw_state(context_gl, dst_texture, dst_sub_resource_idx, dst_location);
if (op == WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST) { diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 27ce651422e..5979d8d6a28 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -523,25 +523,14 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont checkGLcall("glReadBuffer()"); wined3d_context_gl_check_fbo_status(context_gl, GL_READ_FRAMEBUFFER);
+ context_gl_apply_texture_draw_state(context_gl, dst_texture, dst_sub_resource_idx, dst_location); + if (dst_location == WINED3D_LOCATION_DRAWABLE) { - TRACE("Destination texture %p is onscreen.\n", dst_texture); - buffer = wined3d_texture_get_gl_buffer(dst_texture); d = *dst_rect; wined3d_texture_translate_drawable_coords(dst_texture, context_gl->window, &d); dst_rect = &d; } - 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_texture->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_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); context_invalidate_state(context, STATE_BLEND); @@ -633,11 +622,7 @@ static void texture2d_depth_blt_fbo(const struct wined3d_device *device, struct &src_texture->resource, src_sub_resource_idx, src_location); wined3d_context_gl_check_fbo_status(context_gl, GL_READ_FRAMEBUFFER);
- wined3d_context_gl_apply_fbo_state_blit(context_gl, GL_DRAW_FRAMEBUFFER, NULL, 0, - &dst_texture->resource, dst_sub_resource_idx, dst_location); - wined3d_context_gl_set_draw_buffer(context_gl, GL_NONE); - wined3d_context_gl_check_fbo_status(context_gl, GL_DRAW_FRAMEBUFFER); - context_invalidate_state(context, STATE_FRAMEBUFFER); + context_gl_apply_texture_draw_state(context_gl, dst_texture, dst_sub_resource_idx, dst_location);
if (gl_mask & GL_DEPTH_BUFFER_BIT) { @@ -6143,26 +6128,7 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit 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); - } + context_gl_apply_texture_draw_state(context_gl, dst_texture, dst_sub_resource_idx, dst_location);
gl_info->gl_ops.gl.p_glEnable(src_texture_gl->target); checkGLcall("glEnable(target)"); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9cfb3a217d2..67a2ee1f043 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2824,6 +2824,8 @@ BOOL wined3d_clip_blit(const RECT *clip_rect, RECT *clipped, RECT *other) DECLSP
HGLRC context_create_wgl_attribs(const struct wined3d_gl_info *gl_info, HDC hdc, HGLRC share_ctx) DECLSPEC_HIDDEN; DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN; +void context_gl_apply_texture_draw_state(struct wined3d_context_gl *context_gl, + struct wined3d_texture *texture, unsigned int sub_resource_idx, unsigned int location); void context_gl_resource_released(struct wined3d_device *device, GLuint name, BOOL rb_namespace) DECLSPEC_HIDDEN; void context_invalidate_compute_state(struct wined3d_context *context, DWORD state_id) DECLSPEC_HIDDEN;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/context_gl.c | 36 +++++++++++++++++----------------- dlls/wined3d/wined3d_private.h | 1 - 2 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index dd4204067bc..45c1062b3ec 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -466,6 +466,24 @@ static inline DWORD context_generate_rt_mask_from_resource(struct wined3d_resour return (1u << 31) | wined3d_texture_get_gl_buffer(texture_from_resource(resource)); }
+/* Context activation is done by the caller. */ +static void wined3d_context_gl_set_draw_buffer(struct wined3d_context_gl *context_gl, GLenum buffer) +{ + const struct wined3d_gl_info *gl_info = context_gl->gl_info; + struct fbo_entry *current_fbo = context_gl->current_fbo; + uint32_t new_mask = context_generate_rt_mask(buffer); + uint32_t *current_mask; + + current_mask = current_fbo ? ¤t_fbo->rt_mask : &context_gl->draw_buffers_mask; + if (new_mask == *current_mask) + return; + + gl_info->gl_ops.gl.p_glDrawBuffer(buffer); + checkGLcall("glDrawBuffer()"); + + *current_mask = new_mask; +} + static inline void wined3d_context_gl_set_fbo_key_for_render_target(const struct wined3d_context_gl *context_gl, struct wined3d_fbo_entry_key *key, unsigned int idx, const struct wined3d_rendertarget_info *render_target, DWORD location) @@ -2502,24 +2520,6 @@ static void wined3d_context_gl_apply_draw_buffers(struct wined3d_context_gl *con checkGLcall("apply draw buffers"); }
-/* Context activation is done by the caller. */ -void wined3d_context_gl_set_draw_buffer(struct wined3d_context_gl *context_gl, GLenum buffer) -{ - const struct wined3d_gl_info *gl_info = context_gl->gl_info; - struct fbo_entry *current_fbo = context_gl->current_fbo; - uint32_t new_mask = context_generate_rt_mask(buffer); - uint32_t *current_mask; - - current_mask = current_fbo ? ¤t_fbo->rt_mask : &context_gl->draw_buffers_mask; - if (new_mask == *current_mask) - return; - - gl_info->gl_ops.gl.p_glDrawBuffer(buffer); - checkGLcall("glDrawBuffer()"); - - *current_mask = new_mask; -} - /* Context activation is done by the caller. */ void wined3d_context_gl_active_texture(struct wined3d_context_gl *context_gl, const struct wined3d_gl_info *gl_info, unsigned int unit) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 67a2ee1f043..0be77c55b5d 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2383,7 +2383,6 @@ void *wined3d_context_gl_map_bo_address(struct wined3d_context_gl *context_gl, struct wined3d_context_gl *wined3d_context_gl_reacquire(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; void wined3d_context_gl_release(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; BOOL wined3d_context_gl_set_current(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; -void wined3d_context_gl_set_draw_buffer(struct wined3d_context_gl *context_gl, GLenum buffer) DECLSPEC_HIDDEN; void wined3d_context_gl_submit_command_fence(struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; void wined3d_context_gl_texture_update(struct wined3d_context_gl *context_gl, const struct wined3d_texture_gl *texture_gl) DECLSPEC_HIDDEN;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/wined3d/texture.c | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 5979d8d6a28..53d34682ad0 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -3423,14 +3423,87 @@ static void wined3d_texture_gl_unload_location(struct wined3d_texture *texture, } }
+static bool use_ffp_clear(const struct wined3d_texture *texture, unsigned int location) +{ + if (location == WINED3D_LOCATION_DRAWABLE) + return true; + + /* If we are not using FBOs (and not rendering to the drawable), always + * upload. The upload should always succeed in this case; we cannot have + * ARB_texture_multisample without ARB_framebuffer_object. */ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) + return false; + + if (location == WINED3D_LOCATION_TEXTURE_RGB + && !(texture->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE)) + return false; + if (location == WINED3D_LOCATION_TEXTURE_SRGB + && !(texture->resource.format_flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)) + return false; + + return location & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED + | WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB); +} + static void wined3d_texture_gl_clear(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) { + struct wined3d_context_gl *context_gl = wined3d_context_gl(context); + const struct wined3d_format *format = texture->resource.format; + const struct wined3d_gl_info *gl_info = context_gl->gl_info; struct wined3d_bo_address addr;
TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", texture, sub_resource_idx, context, wined3d_debug_location(location));
+ if (use_ffp_clear(texture, location)) + { + GLbitfield clear_mask = 0; + + wined3d_texture_prepare_location(texture, sub_resource_idx, context, location); + + context_gl_apply_texture_draw_state(context_gl, texture, sub_resource_idx, location); + + gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST); + context_invalidate_state(context, STATE_RASTERIZER); + + if (format->depth_size) + { + gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE); + context_invalidate_state(context, STATE_DEPTH_STENCIL); + + if (gl_info->supported[ARB_ES2_COMPATIBILITY]) + GL_EXTCALL(glClearDepthf(0.0f)); + else + gl_info->gl_ops.gl.p_glClearDepth(0.0); + clear_mask |= GL_DEPTH_BUFFER_BIT; + } + + if (format->stencil_size) + { + if (gl_info->supported[EXT_STENCIL_TWO_SIDE]) + gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); + gl_info->gl_ops.gl.p_glStencilMask(~0u); + context_invalidate_state(context, STATE_DEPTH_STENCIL); + gl_info->gl_ops.gl.p_glClearStencil(0); + clear_mask |= GL_STENCIL_BUFFER_BIT; + } + + if (!format->depth_size && !format->stencil_size) + { + gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + context_invalidate_state(context, STATE_BLEND); + gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + clear_mask |= GL_COLOR_BUFFER_BIT; + } + + gl_info->gl_ops.gl.p_glClear(clear_mask); + checkGLcall("clear texture"); + + wined3d_texture_validate_location(texture, sub_resource_idx, location); + return; + } + wined3d_texture_prepare_location(texture, sub_resource_idx, context, WINED3D_LOCATION_SYSMEM); wined3d_texture_get_bo_address(texture, sub_resource_idx, &addr, WINED3D_LOCATION_SYSMEM); memset(addr.addr, 0, texture->sub_resources[sub_resource_idx].size);
On Wed, 20 Apr 2022 at 03:20, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -4393,6 +4393,9 @@ struct wined3d_texture_ops const struct wined3d_bo_address *dst_bo_addr, const struct wined3d_format *dst_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, unsigned int dst_row_pitch, unsigned int dst_slice_pitch);
- /* "location" is a hint, and need not be the resulting location. */
- void (*texture_clear)(struct wined3d_texture *texture, unsigned int sub_resource_idx,
struct wined3d_context *context, unsigned int location);
};
Why do we need this? More specifically, what prevents us from using the existing texture_load_location() op?
On 4/20/22 10:04, Henri Verbeet wrote:
On Wed, 20 Apr 2022 at 03:20, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -4393,6 +4393,9 @@ struct wined3d_texture_ops const struct wined3d_bo_address *dst_bo_addr, const struct wined3d_format *dst_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, unsigned int dst_row_pitch, unsigned int dst_slice_pitch);
- /* "location" is a hint, and need not be the resulting location. */
- void (*texture_clear)(struct wined3d_texture *texture, unsigned int sub_resource_idx,
};struct wined3d_context *context, unsigned int location);
Why do we need this? More specifically, what prevents us from using the existing texture_load_location() op?
It's not necessary, but because of the way wined3d_texture_load_location() is structured, with the sysmem locations being shared across backends, it seemed like the least awkward way to handle it. I'm not immediately sure what would be better; I guess we could duplicate the sysmem handling across backends?
Or alternatively do something like
if (current & WINED3D_LOCATION_CLEARED) { if (location == WINED3D_LOCATION_TEXTURE_RGB) ... else ...
return wined3d_texture_load_location(texture, location); }
in the individual backends.
On Wed, 20 Apr 2022 at 21:49, Zebediah Figura zfigura@codeweavers.com wrote:
On 4/20/22 10:04, Henri Verbeet wrote:
On Wed, 20 Apr 2022 at 03:20, Zebediah Figura zfigura@codeweavers.com wrote:
@@ -4393,6 +4393,9 @@ struct wined3d_texture_ops const struct wined3d_bo_address *dst_bo_addr, const struct wined3d_format *dst_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, unsigned int dst_row_pitch, unsigned int dst_slice_pitch);
- /* "location" is a hint, and need not be the resulting location. */
- void (*texture_clear)(struct wined3d_texture *texture, unsigned int sub_resource_idx,
};struct wined3d_context *context, unsigned int location);
Why do we need this? More specifically, what prevents us from using the existing texture_load_location() op?
It's not necessary, but because of the way wined3d_texture_load_location() is structured, with the sysmem locations being shared across backends, it seemed like the least awkward way to handle it. I'm not immediately sure what would be better; I guess we could duplicate the sysmem handling across backends?
Or alternatively do something like
if (current & WINED3D_LOCATION_CLEARED) { if (location == WINED3D_LOCATION_TEXTURE_RGB) ... else ...
return wined3d_texture_load_location(texture, location);
}
in the individual backends.
I already mentioned this on IRC, but for the benefit of the mailing list:
Yes, that's fine; we already use such a scheme in a couple of other places as well.