diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 0d6550ae2c1..739a038d53d 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -30,6 +30,8 @@ #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); +WINE_DECLARE_DEBUG_CHANNEL(d3d_synchronous); static DWORD wined3d_context_tls_idx; @@ -1257,6 +1259,37 @@ static void bind_dummy_textures(const struct wined3d_device *device, const struc } } +BOOL context_debug_output_enabled(const struct wined3d_gl_info *gl_info) +{ + return gl_info->supported[ARB_DEBUG_OUTPUT] + && (ERR_ON(d3d) || FIXME_ON(d3d) || WARN_ON(d3d_perf)); +} + +static void WINE_GLAPI wined3d_debug_callback(GLenum source, GLenum type, GLuint id, + GLenum severity, GLsizei length, const char *message, void *ctx) +{ + switch (type) + { + case GL_DEBUG_TYPE_ERROR_ARB: + ERR("%p: %s.\n", ctx, debugstr_an(message, length)); + break; + + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: + case GL_DEBUG_TYPE_PORTABILITY_ARB: + FIXME("%p: %s.\n", ctx, debugstr_an(message, length)); + break; + + case GL_DEBUG_TYPE_PERFORMANCE_ARB: + WARN_(d3d_perf)("%p: %s.\n", ctx, debugstr_an(message, length)); + break; + + default: + FIXME("ctx %p, type %#x: %s.\n", ctx, type, debugstr_an(message, length)); + break; + } +} + /* Do not call while under the GL lock. */ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, struct wined3d_surface *target, const struct wined3d_format *ds_format) @@ -1370,7 +1403,17 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, share_ctx = device->context_count ? device->contexts[0]->glCtx : NULL; if (gl_info->p_wglCreateContextAttribsARB) { - if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, NULL))) + unsigned int ctx_attrib_idx = 0; + GLint ctx_attribs[3]; + + if (context_debug_output_enabled(gl_info)) + { + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB; + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB; + } + ctx_attribs[ctx_attrib_idx] = 0; + + if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, ctx_attribs))) { ERR("Failed to create a WGL context.\n"); context_release(ret); @@ -1440,6 +1483,33 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, goto out; } + if (context_debug_output_enabled(gl_info)) + { + GL_EXTCALL(glDebugMessageCallbackARB(wined3d_debug_callback, ret)); + if (TRACE_ON(d3d_synchronous)) + gl_info->gl_ops.gl.p_glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_FALSE)); + if (ERR_ON(d3d)) + { + GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_ERROR_ARB, + GL_DONT_CARE, 0, NULL, GL_TRUE)); + } + if (FIXME_ON(d3d)) + { + GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, + GL_DONT_CARE, 0, NULL, GL_TRUE)); + GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB, + GL_DONT_CARE, 0, NULL, GL_TRUE)); + GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PORTABILITY_ARB, + GL_DONT_CARE, 0, NULL, GL_TRUE)); + } + if (WARN_ON(d3d_perf)) + { + GL_EXTCALL(glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_PERFORMANCE_ARB, + GL_DONT_CARE, 0, NULL, GL_TRUE)); + } + } + switch (swapchain->desc.swap_interval) { case WINED3DPRESENT_INTERVAL_IMMEDIATE: diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 8f1dfb7d9cd..9b3ff1f0d39 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -93,6 +93,7 @@ static const struct wined3d_extension_map gl_extension_map[] = /* ARB */ {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT }, + {"GL_ARB_debug_output", ARB_DEBUG_OUTPUT }, {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT }, {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP }, {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE }, @@ -297,14 +298,14 @@ static void WineD3D_ReleaseFakeGLContext(const struct wined3d_fake_gl_ctx *ctx) } static void wined3d_create_fake_gl_context_attribs(struct wined3d_fake_gl_ctx *fake_gl_ctx, - struct wined3d_gl_info *gl_info) + struct wined3d_gl_info *gl_info, const GLint *ctx_attribs) { HGLRC new_ctx; if (!(gl_info->p_wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB"))) return; - if (!(new_ctx = gl_info->p_wglCreateContextAttribsARB(fake_gl_ctx->dc, NULL, NULL))) + if (!(new_ctx = gl_info->p_wglCreateContextAttribsARB(fake_gl_ctx->dc, NULL, ctx_attribs))) { ERR("Failed to create a context using wglCreateContextAttribsARB(), last error %#x.\n", GetLastError()); gl_info->p_wglCreateContextAttribsARB = NULL; @@ -4902,7 +4903,9 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal) { struct wined3d_gl_info *gl_info = &adapter->gl_info; struct wined3d_fake_gl_ctx fake_gl_ctx = {0}; + unsigned int ctx_attrib_idx = 0; DISPLAY_DEVICEW display_device; + GLint ctx_attribs[3]; TRACE("adapter %p, ordinal %u.\n", adapter, ordinal); @@ -4948,7 +4951,13 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal) return FALSE; } - wined3d_create_fake_gl_context_attribs(&fake_gl_ctx, gl_info); + if (context_debug_output_enabled(gl_info)) + { + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB; + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB; + } + ctx_attribs[ctx_attrib_idx] = 0; + wined3d_create_fake_gl_context_attribs(&fake_gl_ctx, gl_info, ctx_attribs); if (!wined3d_adapter_init_gl_caps(adapter)) { diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index 06b527467ea..85756cb0b6f 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -44,6 +44,7 @@ enum wined3d_gl_extension APPLE_YCBCR_422, /* ARB */ ARB_COLOR_BUFFER_FLOAT, + ARB_DEBUG_OUTPUT, ARB_DEPTH_BUFFER_FLOAT, ARB_DEPTH_CLAMP, ARB_DEPTH_TEXTURE, @@ -179,6 +180,11 @@ enum wined3d_gl_extension USE_GL_FUNC(glFlushMappedBufferRangeAPPLE) \ /* GL_ARB_color_buffer_float */ \ USE_GL_FUNC(glClampColorARB) \ + /* GL_ARB_debug_output */ \ + USE_GL_FUNC(glDebugMessageCallbackARB) \ + USE_GL_FUNC(glDebugMessageControlARB) \ + USE_GL_FUNC(glDebugMessageInsertARB) \ + USE_GL_FUNC(glGetDebugMessageLogARB) \ /* GL_ARB_draw_buffers */ \ USE_GL_FUNC(glDrawBuffersARB) \ /* GL_ARB_draw_elements_base_vertex */ \ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c8b4ff9cdb2..17f3a68f16d 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1265,6 +1265,7 @@ void context_bind_texture(struct wined3d_context *context, GLenum target, GLuint void context_check_fbo_status(const struct wined3d_context *context, GLenum target) DECLSPEC_HIDDEN; struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, struct wined3d_surface *target, const struct wined3d_format *ds_format) DECLSPEC_HIDDEN; +BOOL context_debug_output_enabled(const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN; void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;