[PATCH 5/6] wined3d: Implement manual mipmap generation.
Matteo Bruni
mbruni at codeweavers.com
Mon Dec 4 11:07:31 CST 2017
Signed-off-by: Matteo Bruni <mbruni at 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);
--
2.13.6
More information about the wine-devel
mailing list