[PATCH 2/6] wined3d: Store the context's current rendertarget as a texture and sub-resource index.
Henri Verbeet
hverbeet at codeweavers.com
Tue Mar 29 09:45:32 CDT 2016
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/wined3d/context.c | 119 ++++++++++++++++++++++++++---------------
dlls/wined3d/query.c | 14 ++---
dlls/wined3d/surface.c | 44 +++++++--------
dlls/wined3d/wined3d_private.h | 15 +++++-
4 files changed, 119 insertions(+), 73 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index dfeb4fb..41647f5 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -852,22 +852,26 @@ static void context_queue_fbo_entry_destruction(struct wined3d_context *context,
void context_resource_released(const struct wined3d_device *device,
struct wined3d_resource *resource, enum wined3d_resource_type type)
{
+ struct wined3d_texture *texture;
UINT i;
- struct wined3d_surface *surface;
if (!device->d3d_initialized)
return;
switch (type)
{
- case WINED3D_RTYPE_SURFACE:
- surface = surface_from_resource(resource);
+ case WINED3D_RTYPE_TEXTURE_2D:
+ case WINED3D_RTYPE_TEXTURE_3D:
+ texture = wined3d_texture_from_resource(resource);
for (i = 0; i < device->context_count; ++i)
{
struct wined3d_context *context = device->contexts[i];
- if (context->current_rt == surface)
- context->current_rt = NULL;
+ if (context->current_rt.texture == texture)
+ {
+ context->current_rt.texture = NULL;
+ context->current_rt.sub_resource_idx = 0;
+ }
}
break;
@@ -1318,7 +1322,8 @@ void context_release(struct wined3d_context *context)
* A to avoid breaking caller code. */
void context_restore(struct wined3d_context *context, struct wined3d_surface *restore)
{
- if (context->current_rt != restore)
+ if (context->current_rt.texture != restore->container
+ || context->current_rt.sub_resource_idx != surface_get_sub_resource_idx(restore))
{
context_release(context);
context = context_acquire(restore->container->resource.device, restore);
@@ -1777,7 +1782,8 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
}
ret->swapchain = swapchain;
- ret->current_rt = target->sub_resources[0].u.surface;
+ ret->current_rt.texture = target;
+ ret->current_rt.sub_resource_idx = 0;
ret->tid = GetCurrentThreadId();
ret->render_offscreen = wined3d_resource_is_offscreen(&target->resource);
@@ -2031,9 +2037,10 @@ static void set_blit_dimension(const struct wined3d_gl_info *gl_info, UINT width
static void context_get_rt_size(const struct wined3d_context *context, SIZE *size)
{
- const struct wined3d_surface *rt = context->current_rt;
+ const struct wined3d_texture *rt = context->current_rt.texture;
+ unsigned int level;
- if (rt->container->swapchain && rt->container->swapchain->front_buffer == rt->container)
+ if (rt->swapchain && rt->swapchain->front_buffer == rt)
{
RECT window_size;
@@ -2044,8 +2051,9 @@ static void context_get_rt_size(const struct wined3d_context *context, SIZE *siz
return;
}
- size->cx = rt->resource.width;
- size->cy = rt->resource.height;
+ level = context->current_rt.sub_resource_idx % rt->level_count;
+ size->cx = wined3d_texture_get_level_width(rt, level);
+ size->cy = wined3d_texture_get_level_height(rt, level);
}
/*****************************************************************************
@@ -2412,7 +2420,8 @@ static void context_validate_onscreen_formats(struct wined3d_context *context,
const struct wined3d_rendertarget_view *depth_stencil)
{
/* Onscreen surfaces are always in a swapchain */
- struct wined3d_swapchain *swapchain = context->current_rt->container->swapchain;
+ struct wined3d_swapchain *swapchain = context->current_rt.texture->swapchain;
+ struct wined3d_surface *surface;
if (context->render_offscreen || !depth_stencil) return;
if (match_depth_stencil_format(swapchain->ds_format, depth_stencil->format)) return;
@@ -2423,7 +2432,8 @@ static void context_validate_onscreen_formats(struct wined3d_context *context,
WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n");
/* The currently active context is the necessary context to access the swapchain's onscreen buffers */
- surface_load_location(context->current_rt, context, WINED3D_LOCATION_TEXTURE_RGB);
+ surface = context->current_rt.texture->sub_resources[context->current_rt.sub_resource_idx].u.surface;
+ surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB);
swapchain->render_to_fbo = TRUE;
swapchain_update_draw_bindings(swapchain);
context_set_render_offscreen(context, TRUE);
@@ -2458,7 +2468,8 @@ static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *conte
/* Context activation is done by the caller. */
void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device)
{
- struct wined3d_surface *rt = context->current_rt;
+ struct wined3d_texture *rt = context->current_rt.texture;
+ struct wined3d_surface *surface;
DWORD rt_mask, *cur_mask;
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
@@ -2467,10 +2478,11 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
if (context->render_offscreen)
{
- wined3d_texture_load(rt->container, context, FALSE);
+ wined3d_texture_load(rt, context, FALSE);
- context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, rt, NULL, rt->container->resource.draw_binding);
- if (rt->container->resource.format->id != WINED3DFMT_NULL)
+ surface = rt->sub_resources[context->current_rt.sub_resource_idx].u.surface;
+ context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, surface, NULL, rt->resource.draw_binding);
+ if (rt->resource.format->id != WINED3DFMT_NULL)
rt_mask = 1;
else
rt_mask = 0;
@@ -2479,12 +2491,12 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
{
context->current_fbo = NULL;
context_bind_fbo(context, GL_FRAMEBUFFER, 0);
- rt_mask = context_generate_rt_mask_from_resource(&rt->container->resource);
+ rt_mask = context_generate_rt_mask_from_resource(&rt->resource);
}
}
else
{
- rt_mask = context_generate_rt_mask_no_fbo(context, rt->container);
+ rt_mask = context_generate_rt_mask_no_fbo(context, rt);
}
cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask;
@@ -3418,34 +3430,38 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
return TRUE;
}
-static void context_setup_target(struct wined3d_context *context, struct wined3d_surface *target)
+static void context_setup_target(struct wined3d_context *context,
+ struct wined3d_texture *texture, unsigned int sub_resource_idx)
{
BOOL old_render_offscreen = context->render_offscreen, render_offscreen;
- render_offscreen = wined3d_resource_is_offscreen(&target->container->resource);
- if (context->current_rt == target && render_offscreen == old_render_offscreen) return;
+ render_offscreen = wined3d_resource_is_offscreen(&texture->resource);
+ if (context->current_rt.texture == texture
+ && context->current_rt.sub_resource_idx == sub_resource_idx
+ && render_offscreen == old_render_offscreen)
+ return;
/* To compensate the lack of format switching with some offscreen rendering methods and on onscreen buffers
* the alpha blend state changes with different render target formats. */
- if (!context->current_rt)
+ if (!context->current_rt.texture)
{
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
}
else
{
- const struct wined3d_format *old = context->current_rt->container->resource.format;
- const struct wined3d_format *new = target->container->resource.format;
+ const struct wined3d_format *old = context->current_rt.texture->resource.format;
+ const struct wined3d_format *new = texture->resource.format;
if (old->id != new->id)
{
/* Disable blending when the alpha mask has changed and when a format doesn't support blending. */
if ((old->alpha_size && !new->alpha_size) || (!old->alpha_size && new->alpha_size)
- || !(target->container->resource.format_flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
+ || !(texture->resource.format_flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE));
/* Update sRGB writing when switching between formats that do/do not support sRGB writing */
- if ((context->current_rt->container->resource.format_flags & WINED3DFMT_FLAG_SRGB_WRITE)
- != (target->container->resource.format_flags & WINED3DFMT_FLAG_SRGB_WRITE))
+ if ((context->current_rt.texture->resource.format_flags & WINED3DFMT_FLAG_SRGB_WRITE)
+ != (texture->resource.format_flags & WINED3DFMT_FLAG_SRGB_WRITE))
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE));
}
@@ -3457,25 +3473,32 @@ static void context_setup_target(struct wined3d_context *context, struct wined3d
* has to be called with the old rendertarget active, otherwise a
* wrong drawable is read. */
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
- && old_render_offscreen && context->current_rt != target)
+ && old_render_offscreen && (context->current_rt.texture != texture
+ || context->current_rt.sub_resource_idx != sub_resource_idx))
{
- struct wined3d_texture *texture = context->current_rt->container;
+ unsigned int prev_sub_resource_idx = context->current_rt.sub_resource_idx;
+ struct wined3d_texture *prev_texture = context->current_rt.texture;
+ struct wined3d_surface *prev_surface;
/* Read the back buffer of the old drawable into the destination texture. */
- if (texture->texture_srgb.name)
- wined3d_texture_load(texture, context, TRUE);
- wined3d_texture_load(texture, context, FALSE);
- surface_invalidate_location(context->current_rt, WINED3D_LOCATION_DRAWABLE);
+ if (prev_texture->texture_srgb.name)
+ wined3d_texture_load(prev_texture, context, TRUE);
+ wined3d_texture_load(prev_texture, context, FALSE);
+ prev_surface = prev_texture->sub_resources[prev_sub_resource_idx].u.surface;
+ surface_invalidate_location(prev_surface, WINED3D_LOCATION_DRAWABLE);
}
}
- context->current_rt = target;
+ context->current_rt.texture = texture;
+ context->current_rt.sub_resource_idx = sub_resource_idx;
context_set_render_offscreen(context, render_offscreen);
}
struct wined3d_context *context_acquire(const struct wined3d_device *device, struct wined3d_surface *target)
{
struct wined3d_context *current_context = context_get_current();
+ struct wined3d_texture *target_texture;
+ unsigned int target_sub_resource_idx;
struct wined3d_context *context;
TRACE("device %p, target %p.\n", device, target);
@@ -3483,33 +3506,41 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, str
if (current_context && current_context->destroyed)
current_context = NULL;
- if (!target)
+ if (target)
+ {
+ target_texture = target->container;
+ target_sub_resource_idx = surface_get_sub_resource_idx(target);
+ }
+ else
{
if (current_context
- && current_context->current_rt
+ && current_context->current_rt.texture
&& current_context->swapchain->device == device)
{
- target = current_context->current_rt;
+ target_texture = current_context->current_rt.texture;
+ target_sub_resource_idx = current_context->current_rt.sub_resource_idx;
}
else
{
struct wined3d_swapchain *swapchain = device->swapchains[0];
+
if (swapchain->back_buffers)
- target = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0));
+ target_texture = swapchain->back_buffers[0];
else
- target = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0));
+ target_texture = swapchain->front_buffer;
+ target_sub_resource_idx = 0;
}
}
- if (current_context && current_context->current_rt == target)
+ if (current_context && current_context->current_rt.texture == target_texture)
{
context = current_context;
}
- else if (target->container->swapchain)
+ else if (target_texture->swapchain)
{
TRACE("Rendering onscreen.\n");
- context = swapchain_get_context(target->container->swapchain);
+ context = swapchain_get_context(target_texture->swapchain);
}
else
{
@@ -3525,7 +3556,7 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, str
context_enter(context);
context_update_window(context);
- context_setup_target(context, target);
+ context_setup_target(context, target_texture, target_sub_resource_idx);
if (!context->valid) return context;
if (context != current_context)
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index b86adf1..410ce6c 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -58,7 +58,7 @@ static enum wined3d_event_query_result wined3d_event_query_test(const struct win
return WINED3D_EVENT_QUERY_WRONG_THREAD;
}
- context = context_acquire(device, query->context->current_rt);
+ context = context_acquire(device, context_get_rt_surface(query->context));
gl_info = context->gl_info;
if (gl_info->supported[ARB_SYNC])
@@ -132,7 +132,7 @@ enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_
return WINED3D_EVENT_QUERY_WRONG_THREAD;
}
- context = context_acquire(device, query->context->current_rt);
+ context = context_acquire(device, context_get_rt_surface(query->context));
if (gl_info->supported[ARB_SYNC])
{
@@ -192,7 +192,7 @@ void wined3d_event_query_issue(struct wined3d_event_query *query, const struct w
}
else
{
- context = context_acquire(device, query->context->current_rt);
+ context = context_acquire(device, context_get_rt_surface(query->context));
}
}
else
@@ -348,7 +348,7 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query,
return S_OK;
}
- context = context_acquire(query->device, oq->context->current_rt);
+ context = context_acquire(device, context_get_rt_surface(oq->context));
GL_EXTCALL(glGetQueryObjectuiv(oq->id, GL_QUERY_RESULT_AVAILABLE, &available));
checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)");
@@ -490,7 +490,7 @@ static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DW
}
else
{
- context = context_acquire(query->device, oq->context->current_rt);
+ context = context_acquire(device, context_get_rt_surface(oq->context));
GL_EXTCALL(glEndQuery(GL_SAMPLES_PASSED));
checkGLcall("glEndQuery()");
@@ -522,7 +522,7 @@ static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DW
}
else
{
- context = context_acquire(query->device, oq->context->current_rt);
+ context = context_acquire(device, context_get_rt_surface(oq->context));
GL_EXTCALL(glEndQuery(GL_SAMPLES_PASSED));
checkGLcall("glEndQuery()");
@@ -578,7 +578,7 @@ static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query,
return S_OK;
}
- context = context_acquire(query->device, tq->context->current_rt);
+ context = context_acquire(device, context_get_rt_surface(tq->context));
GL_EXTCALL(glGetQueryObjectuiv(tq->id, GL_QUERY_RESULT_AVAILABLE, &available));
checkGLcall("glGetQueryObjectuiv(GL_QUERY_RESULT_AVAILABLE)");
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 114b368..cd8c863 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -108,8 +108,8 @@ void surface_get_drawable_size(const struct wined3d_surface *surface, const stru
/* The drawable size of an onscreen drawable is the surface size.
* (Actually: The window size, but the surface is created in window
* size.) */
- *width = context->current_rt->resource.width;
- *height = context->current_rt->resource.height;
+ *width = context->current_rt.texture->resource.width;
+ *height = context->current_rt.texture->resource.height;
}
else if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
{
@@ -123,10 +123,13 @@ void surface_get_drawable_size(const struct wined3d_surface *surface, const stru
}
else
{
+ struct wined3d_surface *rt;
+
/* The drawable size of an FBO target is the OpenGL texture size,
* which is the power of two size. */
- *width = context->current_rt->pow2Width;
- *height = context->current_rt->pow2Height;
+ rt = context->current_rt.texture->sub_resources[context->current_rt.sub_resource_idx].u.surface;
+ *width = rt->pow2Width;
+ *height = rt->pow2Height;
}
}
@@ -675,11 +678,11 @@ static void surface_blt_fbo(const struct wined3d_device *device,
else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface;
else required_rt = NULL;
- if (required_rt && required_rt != old_ctx->current_rt)
- {
- restore_rt = old_ctx->current_rt;
+ restore_rt = context_get_rt_surface(old_ctx);
+ if (restore_rt != required_rt)
context = context_acquire(device, required_rt);
- }
+ else
+ restore_rt = NULL;
if (!context->valid)
{
@@ -1852,11 +1855,11 @@ static void read_from_framebuffer(struct wined3d_surface *surface,
surface_get_memory(surface, &data, dst_location);
- if (surface != old_ctx->current_rt)
- {
- restore_rt = old_ctx->current_rt;
+ restore_rt = context_get_rt_surface(old_ctx);
+ if (restore_rt != surface)
context = context_acquire(device, surface);
- }
+ else
+ restore_rt = NULL;
context_apply_blit_state(context, device);
gl_info = context->gl_info;
@@ -1962,11 +1965,11 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb, struct
struct wined3d_context *context = old_ctx;
struct wined3d_surface *restore_rt = NULL;
- if (old_ctx->current_rt != surface)
- {
- restore_rt = old_ctx->current_rt;
+ restore_rt = context_get_rt_surface(old_ctx);
+ if (restore_rt != surface)
context = context_acquire(device, surface);
- }
+ else
+ restore_rt = NULL;
gl_info = context->gl_info;
device_invalidate_state(device, STATE_FRAMEBUFFER);
@@ -2485,12 +2488,11 @@ static void surface_blt_to_drawable(const struct wined3d_device *device,
src_rect = *src_rect_in;
dst_rect = *dst_rect_in;
-
- if (old_ctx->current_rt != dst_surface)
- {
- restore_rt = old_ctx->current_rt;
+ restore_rt = context_get_rt_surface(old_ctx);
+ if (restore_rt != dst_surface)
context = context_acquire(device, dst_surface);
- }
+ else
+ restore_rt = NULL;
gl_info = context->gl_info;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 6e5b96b..d6645fa 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1274,7 +1274,11 @@ struct wined3d_context
DWORD isStateDirty[STATE_HIGHEST / (sizeof(DWORD) * CHAR_BIT) + 1]; /* Bitmap to find out quickly if a state is dirty */
struct wined3d_swapchain *swapchain;
- struct wined3d_surface *current_rt;
+ struct
+ {
+ struct wined3d_texture *texture;
+ unsigned int sub_resource_idx;
+ } current_rt;
DWORD tid; /* Thread ID which owns this context at the moment */
/* Stores some information about the context state for optimization */
@@ -3464,6 +3468,15 @@ static inline BOOL can_use_texture_swizzle(const struct wined3d_gl_info *gl_info
&& !is_scaling_fixup(format->color_fixup);
}
+static inline struct wined3d_surface *context_get_rt_surface(const struct wined3d_context *context)
+{
+ struct wined3d_texture *texture = context->current_rt.texture;
+
+ if (!texture)
+ return NULL;
+ return texture->sub_resources[context->current_rt.sub_resource_idx].u.surface;
+}
+
/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
--
2.1.4
More information about the wine-patches
mailing list