[PATCH] wined3d: Make the adapter responsible for creating GL contexts.
Henri Verbeet
hverbeet at codeweavers.com
Wed Aug 22 12:43:00 CDT 2018
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/wined3d/adapter_gl.c | 6 +
dlls/wined3d/context.c | 298 ++++++++++++++++++++++-------------------
dlls/wined3d/directx.c | 12 ++
dlls/wined3d/wined3d_private.h | 10 ++
4 files changed, 188 insertions(+), 138 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index 686c79ac73f..3a7270fff47 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -4178,6 +4178,11 @@ static DWORD get_max_gl_version(const struct wined3d_gl_info *gl_info, DWORD fla
return wined3d_settings.max_gl_version;
}
+static const struct wined3d_adapter_ops wined3d_adapter_opengl_ops =
+{
+ wined3d_adapter_opengl_create_context,
+};
+
BOOL wined3d_adapter_opengl_init(struct wined3d_adapter *adapter, DWORD wined3d_creation_flags)
{
static const DWORD supported_gl_versions[] =
@@ -4285,6 +4290,7 @@ BOOL wined3d_adapter_opengl_init(struct wined3d_adapter *adapter, DWORD wined3d_
wined3d_caps_gl_ctx_destroy(&caps_gl_ctx);
wined3d_adapter_init_ffp_attrib_ops(adapter);
+ adapter->adapter_ops = &wined3d_adapter_opengl_ops;
return TRUE;
}
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 21ad11d9586..ce9d740145d 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1884,108 +1884,171 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
struct wined3d_texture *target, const struct wined3d_format *ds_format)
{
struct wined3d_device *device = swapchain->device;
- const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
- const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
- const struct wined3d_format *color_format;
- struct wined3d_context *ret;
- BOOL auxBuffers = FALSE;
- HGLRC ctx, share_ctx;
- DWORD target_usage;
- unsigned int i;
+ struct wined3d_context *context;
DWORD state;
TRACE("swapchain %p, target %p, window %p.\n", swapchain, target, swapchain->win_handle);
wined3d_from_cs(device->cs);
- if (!(ret = heap_alloc_zero(sizeof(*ret))))
+ if (!(context = heap_alloc_zero(sizeof(*context))))
return NULL;
- ret->free_timestamp_query_size = 4;
- if (!(ret->free_timestamp_queries = heap_calloc(ret->free_timestamp_query_size,
- sizeof(*ret->free_timestamp_queries))))
+ context->free_timestamp_query_size = 4;
+ if (!(context->free_timestamp_queries = heap_calloc(context->free_timestamp_query_size,
+ sizeof(*context->free_timestamp_queries))))
goto out;
- list_init(&ret->timestamp_queries);
+ list_init(&context->timestamp_queries);
- ret->free_occlusion_query_size = 4;
- if (!(ret->free_occlusion_queries = heap_calloc(ret->free_occlusion_query_size,
- sizeof(*ret->free_occlusion_queries))))
+ context->free_occlusion_query_size = 4;
+ if (!(context->free_occlusion_queries = heap_calloc(context->free_occlusion_query_size,
+ sizeof(*context->free_occlusion_queries))))
goto out;
- list_init(&ret->occlusion_queries);
+ list_init(&context->occlusion_queries);
- ret->free_fence_size = 4;
- if (!(ret->free_fences = heap_calloc(ret->free_fence_size, sizeof(*ret->free_fences))))
+ context->free_fence_size = 4;
+ if (!(context->free_fences = heap_calloc(context->free_fence_size, sizeof(*context->free_fences))))
goto out;
- list_init(&ret->fences);
+ list_init(&context->fences);
- list_init(&ret->so_statistics_queries);
+ list_init(&context->so_statistics_queries);
- list_init(&ret->pipeline_statistics_queries);
+ list_init(&context->pipeline_statistics_queries);
- list_init(&ret->fbo_list);
- list_init(&ret->fbo_destroy_list);
+ list_init(&context->fbo_list);
+ list_init(&context->fbo_destroy_list);
- if (!device->shader_backend->shader_allocate_context_data(ret))
+ if (!device->shader_backend->shader_allocate_context_data(context))
{
ERR("Failed to allocate shader backend context data.\n");
goto out;
}
- if (!device->adapter->fragment_pipe->allocate_context_data(ret))
+ if (!device->adapter->fragment_pipe->allocate_context_data(context))
{
ERR("Failed to allocate fragment pipeline context data.\n");
goto out;
}
- for (i = 0; i < ARRAY_SIZE(ret->tex_unit_map); ++i)
- ret->tex_unit_map[i] = WINED3D_UNMAPPED_STAGE;
- for (i = 0; i < ARRAY_SIZE(ret->rev_tex_unit_map); ++i)
- ret->rev_tex_unit_map[i] = WINED3D_UNMAPPED_STAGE;
+ if (!(context->hdc = GetDCEx(swapchain->win_handle, 0, DCX_USESTYLE | DCX_CACHE)))
+ {
+ WARN("Failed to retrieve device context, trying swapchain backup.\n");
+
+ if ((context->hdc = swapchain_get_backup_dc(swapchain)))
+ context->hdc_is_private = TRUE;
+ else
+ {
+ ERR("Failed to retrieve a device context.\n");
+ goto out;
+ }
+ }
+
+ if (!device_context_add(device, context))
+ {
+ ERR("Failed to add the newly created context to the context list\n");
+ goto out;
+ }
+
+ context->win_handle = swapchain->win_handle;
+ context->gl_info = &device->adapter->gl_info;
+ context->d3d_info = &device->adapter->d3d_info;
+ context->state_table = device->StateTable;
+
+ /* Mark all states dirty to force a proper initialization of the states on
+ * the first use of the context. Compute states do not need initialization. */
+ for (state = 0; state <= STATE_HIGHEST; ++state)
+ {
+ if (context->state_table[state].representative && !STATE_IS_COMPUTE(state))
+ context_invalidate_state(context, state);
+ }
+
+ context->device = device;
+ context->swapchain = swapchain;
+ context->current_rt.texture = target;
+ context->current_rt.sub_resource_idx = 0;
+ context->tid = GetCurrentThreadId();
+
+ if (!(device->adapter->adapter_ops->adapter_create_context(context, target, ds_format)))
+ {
+ device_context_remove(device, context);
+ goto out;
+ }
+
+ device->shader_backend->shader_init_context_state(context);
+ context->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL)
+ | (1u << WINED3D_SHADER_TYPE_VERTEX)
+ | (1u << WINED3D_SHADER_TYPE_GEOMETRY)
+ | (1u << WINED3D_SHADER_TYPE_HULL)
+ | (1u << WINED3D_SHADER_TYPE_DOMAIN)
+ | (1u << WINED3D_SHADER_TYPE_COMPUTE);
+
+ TRACE("Created context %p.\n", context);
+
+ return context;
+
+out:
+ if (context->hdc)
+ wined3d_release_dc(swapchain->win_handle, context->hdc);
+ device->shader_backend->shader_free_context_data(context);
+ device->adapter->fragment_pipe->free_context_data(context);
+ heap_free(context->free_fences);
+ heap_free(context->free_occlusion_queries);
+ heap_free(context->free_timestamp_queries);
+ heap_free(context);
+ return NULL;
+}
+
+BOOL wined3d_adapter_opengl_create_context(struct wined3d_context *context,
+ struct wined3d_texture *target, const struct wined3d_format *ds_format)
+{
+ struct wined3d_device *device = context->device;
+ const struct wined3d_format *color_format;
+ const struct wined3d_d3d_info *d3d_info;
+ const struct wined3d_gl_info *gl_info;
+ BOOL aux_buffers = FALSE;
+ HGLRC ctx, share_ctx;
+ DWORD target_usage;
+ unsigned int i;
+
+ gl_info = context->gl_info;
+ d3d_info = context->d3d_info;
+
+ for (i = 0; i < ARRAY_SIZE(context->tex_unit_map); ++i)
+ context->tex_unit_map[i] = WINED3D_UNMAPPED_STAGE;
+ for (i = 0; i < ARRAY_SIZE(context->rev_tex_unit_map); ++i)
+ context->rev_tex_unit_map[i] = WINED3D_UNMAPPED_STAGE;
if (gl_info->limits.graphics_samplers >= MAX_COMBINED_SAMPLERS)
{
/* Initialize the texture unit mapping to a 1:1 mapping. */
unsigned int base, count;
wined3d_gl_limits_get_texture_unit_range(&gl_info->limits, WINED3D_SHADER_TYPE_PIXEL, &base, &count);
- if (base + MAX_FRAGMENT_SAMPLERS > ARRAY_SIZE(ret->rev_tex_unit_map))
+ if (base + MAX_FRAGMENT_SAMPLERS > ARRAY_SIZE(context->rev_tex_unit_map))
{
ERR("Unexpected texture unit base index %u.\n", base);
- goto out;
+ return FALSE;
}
for (i = 0; i < min(count, MAX_FRAGMENT_SAMPLERS); ++i)
{
- ret->tex_unit_map[i] = base + i;
- ret->rev_tex_unit_map[base + i] = i;
+ context->tex_unit_map[i] = base + i;
+ context->rev_tex_unit_map[base + i] = i;
}
wined3d_gl_limits_get_texture_unit_range(&gl_info->limits, WINED3D_SHADER_TYPE_VERTEX, &base, &count);
- if (base + MAX_VERTEX_SAMPLERS > ARRAY_SIZE(ret->rev_tex_unit_map))
+ if (base + MAX_VERTEX_SAMPLERS > ARRAY_SIZE(context->rev_tex_unit_map))
{
ERR("Unexpected texture unit base index %u.\n", base);
- goto out;
+ return FALSE;
}
for (i = 0; i < min(count, MAX_VERTEX_SAMPLERS); ++i)
{
- ret->tex_unit_map[MAX_FRAGMENT_SAMPLERS + i] = base + i;
- ret->rev_tex_unit_map[base + i] = MAX_FRAGMENT_SAMPLERS + i;
+ context->tex_unit_map[MAX_FRAGMENT_SAMPLERS + i] = base + i;
+ context->rev_tex_unit_map[base + i] = MAX_FRAGMENT_SAMPLERS + i;
}
}
- if (!(ret->texture_type = heap_calloc(gl_info->limits.combined_samplers,
- sizeof(*ret->texture_type))))
- goto out;
-
- if (!(ret->hdc = GetDCEx(swapchain->win_handle, 0, DCX_USESTYLE | DCX_CACHE)))
- {
- WARN("Failed to retrieve device context, trying swapchain backup.\n");
-
- if ((ret->hdc = swapchain_get_backup_dc(swapchain)))
- ret->hdc_is_private = TRUE;
- else
- {
- ERR("Failed to retrieve a device context.\n");
- goto out;
- }
- }
+ if (!(context->texture_type = heap_calloc(gl_info->limits.combined_samplers,
+ sizeof(*context->texture_type))))
+ return FALSE;
color_format = target->resource.format;
target_usage = target->resource.usage;
@@ -1994,7 +2057,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
* X4R4G4B4/X8R8G8B8 as we might need it for the backbuffer. */
if (wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER)
{
- auxBuffers = TRUE;
+ aux_buffers = TRUE;
if (color_format->id == WINED3DFMT_B4G4R4X4_UNORM)
color_format = wined3d_get_format(gl_info, WINED3DFMT_B4G4R4A4_UNORM, target_usage);
@@ -2026,94 +2089,73 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
}
/* Try to find a pixel format which matches our requirements. */
- if (!(ret->pixel_format = context_choose_pixel_format(device, ret->hdc, color_format, ds_format, auxBuffers)))
- goto out;
-
- ret->gl_info = gl_info;
- ret->win_handle = swapchain->win_handle;
+ if (!(context->pixel_format = context_choose_pixel_format(device,
+ context->hdc, color_format, ds_format, aux_buffers)))
+ return FALSE;
- context_enter(ret);
+ context_enter(context);
- if (!context_set_pixel_format(ret))
+ if (!context_set_pixel_format(context))
{
- ERR("Failed to set pixel format %d on device context %p.\n", ret->pixel_format, ret->hdc);
- context_release(ret);
- goto out;
+ ERR("Failed to set pixel format %d on device context %p.\n", context->pixel_format, context->hdc);
+ context_release(context);
+ heap_free(context->texture_type);
+ return FALSE;
}
share_ctx = device->context_count ? device->contexts[0]->glCtx : NULL;
if (gl_info->p_wglCreateContextAttribsARB)
{
- if (!(ctx = context_create_wgl_attribs(gl_info, ret->hdc, share_ctx)))
- goto out;
+ if (!(ctx = context_create_wgl_attribs(gl_info, context->hdc, share_ctx)))
+ {
+ context_release(context);
+ heap_free(context->texture_type);
+ return FALSE;
+ }
}
else
{
- if (!(ctx = wglCreateContext(ret->hdc)))
+ if (!(ctx = wglCreateContext(context->hdc)))
{
ERR("Failed to create a WGL context.\n");
- context_release(ret);
- goto out;
+ context_release(context);
+ heap_free(context->texture_type);
+ return FALSE;
}
if (share_ctx && !wglShareLists(share_ctx, ctx))
{
ERR("wglShareLists(%p, %p) failed, last error %#x.\n", share_ctx, ctx, GetLastError());
- context_release(ret);
+ context_release(context);
if (!wglDeleteContext(ctx))
ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, GetLastError());
- goto out;
+ heap_free(context->texture_type);
+ return FALSE;
}
}
- if (!device_context_add(device, ret))
- {
- ERR("Failed to add the newly created context to the context list\n");
- context_release(ret);
- if (!wglDeleteContext(ctx))
- ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, GetLastError());
- goto out;
- }
-
- ret->d3d_info = d3d_info;
- ret->state_table = device->StateTable;
-
- /* Mark all states dirty to force a proper initialization of the states on
- * the first use of the context. Compute states do not need initialization. */
- for (state = 0; state <= STATE_HIGHEST; ++state)
- {
- if (ret->state_table[state].representative && !STATE_IS_COMPUTE(state))
- context_invalidate_state(ret, state);
- }
-
- ret->device = device;
- ret->swapchain = swapchain;
- ret->current_rt.texture = target;
- ret->current_rt.sub_resource_idx = 0;
- ret->tid = GetCurrentThreadId();
-
- ret->render_offscreen = wined3d_resource_is_offscreen(&target->resource);
- ret->draw_buffers_mask = context_generate_rt_mask(GL_BACK);
- ret->valid = 1;
+ context->render_offscreen = wined3d_resource_is_offscreen(&target->resource);
+ context->draw_buffers_mask = context_generate_rt_mask(GL_BACK);
+ context->valid = 1;
- ret->glCtx = ctx;
- ret->hdc_has_format = TRUE;
- ret->needs_set = 1;
+ context->glCtx = ctx;
+ context->hdc_has_format = TRUE;
+ context->needs_set = 1;
/* Set up the context defaults */
- if (!context_set_current(ret))
+ if (!context_set_current(context))
{
ERR("Cannot activate context to set up defaults.\n");
- device_context_remove(device, ret);
- context_release(ret);
+ context_release(context);
if (!wglDeleteContext(ctx))
ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx, GetLastError());
- goto out;
+ heap_free(context->texture_type);
+ return FALSE;
}
if (context_debug_output_enabled(gl_info))
{
- GL_EXTCALL(glDebugMessageCallback(wined3d_debug_callback, ret));
+ GL_EXTCALL(glDebugMessageCallback(wined3d_debug_callback, context));
if (TRACE_ON(d3d_synchronous))
gl_info->gl_ops.gl.p_glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
GL_EXTCALL(glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_FALSE));
@@ -2139,7 +2181,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
}
if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
- gl_info->gl_ops.gl.p_glGetIntegerv(GL_AUX_BUFFERS, &ret->aux_buffers);
+ gl_info->gl_ops.gl.p_glGetIntegerv(GL_AUX_BUFFERS, &context->aux_buffers);
TRACE("Setting up the screen\n");
@@ -2175,7 +2217,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
*/
for (i = 1; i < gl_info->limits.textures; ++i)
{
- context_active_texture(ret, gl_info, i);
+ context_active_texture(context, gl_info, i);
gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV,
GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB + i - 1);
checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, ...");
@@ -2196,16 +2238,17 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
"!!ARBfp1.0\n"
"MOV result.color, fragment.color.primary;\n"
"END\n";
- GL_EXTCALL(glGenProgramsARB(1, &ret->dummy_arbfp_prog));
- GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret->dummy_arbfp_prog));
- GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dummy_program), dummy_program));
+ GL_EXTCALL(glGenProgramsARB(1, &context->dummy_arbfp_prog));
+ GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, context->dummy_arbfp_prog));
+ GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
+ GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dummy_program), dummy_program));
}
if (gl_info->supported[ARB_POINT_SPRITE])
{
for (i = 0; i < gl_info->limits.textures; ++i)
{
- context_active_texture(ret, gl_info, i);
+ context_active_texture(context, gl_info, i);
gl_info->gl_ops.gl.p_glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
checkGLcall("glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE)");
}
@@ -2239,39 +2282,18 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
}
if (gl_info->supported[ARB_CLIP_CONTROL])
GL_EXTCALL(glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT));
- device->shader_backend->shader_init_context_state(ret);
- ret->shader_update_mask = (1u << WINED3D_SHADER_TYPE_PIXEL)
- | (1u << WINED3D_SHADER_TYPE_VERTEX)
- | (1u << WINED3D_SHADER_TYPE_GEOMETRY)
- | (1u << WINED3D_SHADER_TYPE_HULL)
- | (1u << WINED3D_SHADER_TYPE_DOMAIN)
- | (1u << WINED3D_SHADER_TYPE_COMPUTE);
/* If this happens to be the first context for the device, dummy textures
* are not created yet. In that case, they will be created (and bound) by
* create_dummy_textures right after this context is initialized. */
if (device->dummy_textures.tex_2d)
- context_bind_dummy_textures(device, ret);
+ context_bind_dummy_textures(device, context);
/* Initialise all rectangles to avoid resetting unused ones later. */
gl_info->gl_ops.gl.p_glScissor(0, 0, 0, 0);
checkGLcall("glScissor");
- TRACE("Created context %p.\n", ret);
-
- return ret;
-
-out:
- if (ret->hdc)
- wined3d_release_dc(swapchain->win_handle, ret->hdc);
- device->shader_backend->shader_free_context_data(ret);
- device->adapter->fragment_pipe->free_context_data(ret);
- heap_free(ret->texture_type);
- heap_free(ret->free_fences);
- heap_free(ret->free_occlusion_queries);
- heap_free(ret->free_timestamp_queries);
- heap_free(ret);
- return NULL;
+ return TRUE;
}
void context_destroy(struct wined3d_device *device, struct wined3d_context *context)
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index a6f190c4d0a..de1f9d993d7 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2456,6 +2456,17 @@ HRESULT CDECL wined3d_device_create(struct wined3d *wined3d, UINT adapter_idx, e
return WINED3D_OK;
}
+static BOOL wined3d_adapter_no3d_create_context(struct wined3d_context *context,
+ struct wined3d_texture *target, const struct wined3d_format *ds_format)
+{
+ return TRUE;
+}
+
+static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops =
+{
+ wined3d_adapter_no3d_create_context,
+};
+
static BOOL wined3d_adapter_no3d_init(struct wined3d_adapter *adapter)
{
TRACE("adapter %p.\n", adapter);
@@ -2473,6 +2484,7 @@ static BOOL wined3d_adapter_no3d_init(struct wined3d_adapter *adapter)
adapter->vertex_pipe = &none_vertex_pipe;
adapter->fragment_pipe = &none_fragment_pipe;
adapter->shader_backend = &none_shader_backend;
+ adapter->adapter_ops = &wined3d_adapter_no3d_ops;
return TRUE;
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 60369ccb51b..3f168dc4c0f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2653,6 +2653,15 @@ struct wined3d_driver_info
void wined3d_driver_info_init(struct wined3d_driver_info *driver_info,
const struct wined3d_gpu_description *gpu_description, UINT64 vram_bytes) DECLSPEC_HIDDEN;
+struct wined3d_adapter_ops
+{
+ BOOL (*adapter_create_context)(struct wined3d_context *context,
+ struct wined3d_texture *target, const struct wined3d_format *ds_format);
+};
+
+BOOL wined3d_adapter_opengl_create_context(struct wined3d_context *context,
+ struct wined3d_texture *target, const struct wined3d_format *ds_format) DECLSPEC_HIDDEN;
+
/* The adapter structure */
struct wined3d_adapter
{
@@ -2673,6 +2682,7 @@ struct wined3d_adapter
const struct wined3d_vertex_pipe_ops *vertex_pipe;
const struct fragment_pipeline *fragment_pipe;
const struct wined3d_shader_backend_ops *shader_backend;
+ const struct wined3d_adapter_ops *adapter_ops;
};
BOOL wined3d_adapter_opengl_init(struct wined3d_adapter *adapter, DWORD wined3d_creation_flags) DECLSPEC_HIDDEN;
--
2.11.0
More information about the wine-devel
mailing list