Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/wined3d/cs.c | 30 ++++++++++++ dlls/wined3d/texture.c | 11 ----- dlls/wined3d/view.c | 102 +++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 2 +- dlls/wined3d/wined3d_private.h | 2 + include/wine/wined3d.h | 2 +- 6 files changed, 136 insertions(+), 13 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index f7c943e98e..dbe9f42beb 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -71,6 +71,7 @@ enum wined3d_cs_op WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION, WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW, WINED3D_CS_OP_COPY_UAV_COUNTER, + WINED3D_CS_OP_GENERATE_MIPMAPS, WINED3D_CS_OP_STOP, };
@@ -421,6 +422,12 @@ struct wined3d_cs_copy_uav_counter struct wined3d_unordered_access_view *view; };
+struct wined3d_cs_generate_mipmaps +{ + enum wined3d_cs_op opcode; + struct wined3d_shader_resource_view *view; +}; + struct wined3d_cs_stop { enum wined3d_cs_op opcode; @@ -2336,6 +2343,28 @@ void wined3d_cs_emit_copy_uav_counter(struct wined3d_cs *cs, struct wined3d_buff cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); }
+static void wined3d_cs_exec_generate_mipmaps(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_generate_mipmaps *op = data; + struct wined3d_shader_resource_view *view = op->view; + + shader_resource_view_generate_mipmaps(view); + wined3d_resource_release(view->resource); +} + +void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs *cs, struct wined3d_shader_resource_view *view) +{ + struct wined3d_cs_generate_mipmaps *op; + + op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_GENERATE_MIPMAPS; + op->view = view; + + wined3d_resource_acquire(view->resource); + + cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); +} + static void wined3d_cs_emit_stop(struct wined3d_cs *cs) { struct wined3d_cs_stop *op; @@ -2394,6 +2423,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_ADD_DIRTY_TEXTURE_REGION */ wined3d_cs_exec_add_dirty_texture_region, /* WINED3D_CS_OP_CLEAR_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_clear_unordered_access_view, /* WINED3D_CS_OP_COPY_UAV_COUNTER */ wined3d_cs_exec_copy_uav_counter, + /* WINED3D_CS_OP_GENERATE_MIPMAPS */ wined3d_cs_exec_generate_mipmaps, };
static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size, enum wined3d_cs_queue_id queue_id) diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 7a8e1fb7d1..ddbe340dc8 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -1580,17 +1580,6 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned } }
-void CDECL wined3d_texture_generate_mipmaps(struct wined3d_texture *texture) -{ - FIXME("texture %p stub!\n", texture); - - if (!(texture->flags & WINED3D_TEXTURE_GENERATE_MIPMAPS)) - { - WARN("Texture without the WINED3D_TEXTURE_GENERATE_MIPMAPS flag, ignoring.\n"); - return; - } -} - static struct wined3d_texture_sub_resource *wined3d_texture_get_sub_resource(struct wined3d_texture *texture, unsigned int sub_resource_idx) { diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index b35b66bfeb..4463fabb6a 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -803,6 +803,108 @@ void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view wined3d_sampler_bind(sampler, unit, texture, context); }
+/* Context activation is done by the caller. */ +static void shader_resource_view_bind_and_dirtify(struct wined3d_shader_resource_view *view, + struct wined3d_context *context) +{ + if (context->active_texture < ARRAY_SIZE(context->rev_tex_unit_map)) + { + DWORD active_sampler = context->rev_tex_unit_map[context->active_texture]; + if (active_sampler != WINED3D_UNMAPPED_STAGE) + context_invalidate_state(context, STATE_SAMPLER(active_sampler)); + } + /* FIXME: Ideally we'd only do this when touching a binding that's used by + * a shader. */ + context_invalidate_compute_state(context, STATE_COMPUTE_SHADER_RESOURCE_BINDING); + context_invalidate_state(context, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); + + context_bind_texture(context, view->gl_view.target, view->gl_view.name); +} + +void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view *view) +{ + struct wined3d_texture *texture = texture_from_resource(view->resource); + unsigned int i, j, layer_count, level_count, base_level, max_level; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + struct gl_texture *gl_tex; + DWORD location; + BOOL srgb; + + TRACE("view %p.\n", view); + + wined3d_from_cs(view->resource->device->cs); + + context = context_acquire(view->resource->device, NULL, 0); + gl_info = context->gl_info; + layer_count = view->desc.u.texture.layer_count; + level_count = view->desc.u.texture.level_count; + base_level = view->desc.u.texture.level_idx; + max_level = base_level + level_count - 1; + + srgb = !!(texture->flags & WINED3D_TEXTURE_IS_SRGB); + location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; + for (i = 0; i < layer_count; ++i) + wined3d_texture_load_location(texture, i * level_count + base_level, context, location); + if (view->gl_view.name) + shader_resource_view_bind_and_dirtify(view, context); + else + wined3d_texture_bind_and_dirtify(texture, context, srgb); + if (gl_info->supported[ARB_SAMPLER_OBJECTS]) + GL_EXTCALL(glBindSampler(context->active_texture, 0)); + gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, base_level); + gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, max_level); + gl_tex = wined3d_texture_get_gl_texture(texture, srgb); + if (context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) + { + gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_SRGB_DECODE_EXT, + GL_SKIP_DECODE_EXT); + gl_tex->sampler_desc.srgb_decode = FALSE; + } + + gl_info->fbo_ops.glGenerateMipmap(texture->target); + checkGLcall("glGenerateMipMap()"); + + for (i = 0; i < layer_count; ++i) + { + for (j = base_level + 1; j <= max_level; ++j) + { + wined3d_texture_validate_location(texture, i * level_count + j, location); + wined3d_texture_invalidate_location(texture, i * level_count + j, ~location); + } + } + + gl_info->gl_ops.gl.p_glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, level_count - 1); + if (srgb) + texture->texture_srgb.base_level = base_level; + else + texture->texture_rgb.base_level = base_level; + + context_release(context); +} + +void CDECL wined3d_shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view *view) +{ + struct wined3d_texture *texture; + + TRACE("view %p.\n", view); + + if (view->resource->type == WINED3D_RTYPE_BUFFER) + { + WARN("Called on buffer resource %p.\n", view->resource); + return; + } + + texture = texture_from_resource(view->resource); + if (!(texture->flags & WINED3D_TEXTURE_GENERATE_MIPMAPS)) + { + WARN("Texture without the WINED3D_TEXTURE_GENERATE_MIPMAPS flag, ignoring.\n"); + return; + } + + wined3d_cs_emit_generate_mipmaps(view->resource->device->cs, view); +} + ULONG CDECL wined3d_unordered_access_view_incref(struct wined3d_unordered_access_view *view) { ULONG refcount = InterlockedIncrement(&view->refcount); diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 0825b93660..74e61eab39 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -254,6 +254,7 @@
@ cdecl wined3d_shader_resource_view_create(ptr ptr ptr ptr ptr) @ cdecl wined3d_shader_resource_view_decref(ptr) +@ cdecl wined3d_shader_resource_view_generate_mipmaps(ptr) @ cdecl wined3d_shader_resource_view_get_parent(ptr) @ cdecl wined3d_shader_resource_view_incref(ptr)
@@ -287,7 +288,6 @@ @ cdecl wined3d_texture_create(ptr ptr long long long ptr ptr ptr ptr) @ cdecl wined3d_texture_decref(ptr) @ cdecl wined3d_texture_from_resource(ptr) -@ cdecl wined3d_texture_generate_mipmaps(ptr) @ cdecl wined3d_texture_get_autogen_filter_type(ptr) @ cdecl wined3d_texture_get_dc(ptr long ptr) @ cdecl wined3d_texture_get_level_count(ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index da06ba159f..01f0e1695b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3508,6 +3508,7 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, GLenum primitive_type, unsigned void wined3d_cs_emit_draw_indirect(struct wined3d_cs *cs, GLenum primitive_type, unsigned int patch_vertex_count, struct wined3d_buffer *buffer, unsigned int offset, BOOL indexed) DECLSPEC_HIDDEN; void wined3d_cs_emit_flush(struct wined3d_cs *cs) DECLSPEC_HIDDEN; +void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs *cs, struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags) DECLSPEC_HIDDEN; @@ -3705,6 +3706,7 @@ struct wined3d_shader_resource_view struct wined3d_view_desc desc; };
+void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view, unsigned int unit, struct wined3d_sampler *sampler, struct wined3d_context *context) DECLSPEC_HIDDEN;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index ad9fd1362b..282e7338db 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2609,6 +2609,7 @@ HRESULT __cdecl wined3d_shader_resource_view_create(const struct wined3d_view_de struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_shader_resource_view **view); ULONG __cdecl wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view *view); +void __cdecl wined3d_shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view *view); void * __cdecl wined3d_shader_resource_view_get_parent(const struct wined3d_shader_resource_view *view); ULONG __cdecl wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view *view);
@@ -2661,7 +2662,6 @@ HRESULT __cdecl wined3d_texture_create(struct wined3d_device *device, const stru void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture); struct wined3d_texture * __cdecl wined3d_texture_from_resource(struct wined3d_resource *resource); ULONG __cdecl wined3d_texture_decref(struct wined3d_texture *texture); -void __cdecl wined3d_texture_generate_mipmaps(struct wined3d_texture *texture); enum wined3d_texture_filter_type __cdecl wined3d_texture_get_autogen_filter_type(const struct wined3d_texture *texture); HRESULT __cdecl wined3d_texture_get_dc(struct wined3d_texture *texture, unsigned int sub_resource_idx, HDC *dc); DWORD __cdecl wined3d_texture_get_level_count(const struct wined3d_texture *texture);