From f7904211a20672d35e89c40d6298a1f81e120c0c Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 22 Aug 2018 22:13:00 +0430 Subject: [PATCH] wined3d: Make the adapter responsible for creating GL contexts. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- 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.4.GIT