gitlab-ci: enable sanitizers for the meson builds
[mesa-waffle.git] / src / waffle / wgl / wgl_context.c
blobd8cf9decf924f03c727e861fbf64d8ccf5f6957e
1 // SPDX-FileCopyrightText: Copyright 2014 Emil Velikov
2 // SPDX-License-Identifier: BSD-2-Clause
4 #include <assert.h>
5 #include <stdlib.h>
6 #include <windows.h>
8 #include "wcore_error.h"
10 #include "wgl_config.h"
11 #include "wgl_context.h"
12 #include "wgl_display.h"
13 #include "wgl_window.h"
15 bool
16 wgl_context_destroy(struct wcore_context *wc_self)
18 struct wgl_context *self = wgl_context(wc_self);
19 bool ok = true;
21 if (self->hglrc)
22 ok &= wglDeleteContext(self->hglrc);
24 free(self);
25 return ok;
29 /// @brief Fill @a attrib_list, which will be given to wglCreateContextAttribsARB().
30 ///
31 /// This does not validate the `config->context_*` attributes. That validation
32 /// occurred during waffle_config_choose().
33 static bool
34 wgl_context_fill_attrib_list(struct wgl_config *config,
35 int attrib_list[])
37 struct wcore_config_attrs *attrs = &config->wcore.attrs;
38 int i = 0;
39 int context_flags = 0;
41 // XXX: Check if the following workaround is relevant under Windows.
43 // As a workaround for NVidia, do not specify
44 // WGL_CONTEXT_MAJOR_VERSION_ARB and WGL_CONTEXT_MINOR_VERSION_ARB in the
45 // call to wglCreateContextAttribsARB if the user requested an OpenGL
46 // context of unspecified version or if the user explicitly requested an
47 // OpenGL 1.0 context.
49 // Calling wglCreateContextAttribARB with MAJOR=1 and MINOR=0, according
50 // to the spec, is equivalent to calling it with MAJOR and MINOR
51 // unspecified. From the WGL_ARB_create_context spec:
53 // If an attribute is not specified in <attrib_list>,
54 // then the default value specified below is used instead.
56 // The default values for WGL_CONTEXT_MAJOR_VERSION_ARB and
57 // WGL_CONTEXT_MINOR_VERSION_ARB are 1 and 0 respectively. In this
58 // case, implementations will typically return the most recent version
59 // of OpenGL they support which is backwards compatible with OpenGL 1.0
60 // (e.g. 3.0, 3.1 + GL_ARB_compatibility, or 3.2 compatibility profile)
62 // However, NVidia's libGL, circa 2012-12-19, is not compliant. Calling
63 // wglCreateContextAttribsARB with MAJOR=1 and MINOR=0 returns an OpenGL
64 // 2.1 context. Calling it with MAJOR and MINOR unspecified returns
65 // a context of the latest supported OpenGL version.
66 if (!(wcore_config_attrs_version_eq(attrs, 10) &&
67 attrs->context_api == WAFFLE_CONTEXT_OPENGL))
69 attrib_list[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
70 attrib_list[i++] = attrs->context_major_version;
72 attrib_list[i++] = WGL_CONTEXT_MINOR_VERSION_ARB;
73 attrib_list[i++] = attrs->context_minor_version;
76 switch (attrs->context_api) {
77 case WAFFLE_CONTEXT_OPENGL:
78 if (wcore_config_attrs_version_ge(attrs, 32)) {
79 switch (attrs->context_profile) {
80 case WAFFLE_CONTEXT_CORE_PROFILE:
81 attrib_list[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
82 attrib_list[i++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
83 break;
84 case WAFFLE_CONTEXT_COMPATIBILITY_PROFILE:
85 attrib_list[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
86 attrib_list[i++] = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
87 break;
88 default:
89 assert(false);
90 break;
94 if (attrs->context_forward_compatible) {
95 context_flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
98 break;
99 case WAFFLE_CONTEXT_OPENGL_ES1:
100 case WAFFLE_CONTEXT_OPENGL_ES2:
101 case WAFFLE_CONTEXT_OPENGL_ES3:
102 attrib_list[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
103 attrib_list[i++] = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
104 break;
107 if (attrs->context_debug) {
108 context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
111 if (attrs->context_robust) {
112 context_flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
115 if (context_flags != 0) {
116 attrib_list[i++] = WGL_CONTEXT_FLAGS_ARB;
117 attrib_list[i++] = context_flags;
120 attrib_list[i++] = 0;
121 return true;
124 static HGLRC
125 wgl_context_create_native(struct wgl_config *config,
126 struct wgl_context *share_ctx)
128 struct wgl_display *dpy = wgl_display(config->wcore.display);
129 const struct wcore_config_attrs *attrs = &config->wcore.attrs;
130 HGLRC real_share_ctx = share_ctx ? share_ctx->hglrc : NULL;
131 HGLRC hglrc;
133 // Optionally use ARB_create_context for OpenGL 1.0, if available.
134 if (dpy->ARB_create_context &&
135 (wgl_context_needs_arb_create_context(attrs) ||
136 (attrs->context_api == WAFFLE_CONTEXT_OPENGL &&
137 wcore_config_attrs_version_eq(attrs, 10)))) {
138 bool ok;
140 // Choose a large size to prevent accidental overflow.
141 int attrib_list[64];
143 ok = wgl_context_fill_attrib_list(config, attrib_list);
144 if (!ok)
145 return NULL;
147 hglrc = dpy->wglCreateContextAttribsARB(config->window->hDC,
148 real_share_ctx,
149 attrib_list);
150 if (!hglrc) {
151 wcore_errorf(WAFFLE_ERROR_UNKNOWN,
152 "wglCreateContextAttribsARB failed");
153 return NULL;
156 else {
157 hglrc = wglCreateContext(config->window->hDC);
158 if (!hglrc) {
159 wcore_errorf(WAFFLE_ERROR_UNKNOWN, "wglCreateContext failed");
160 return NULL;
164 return hglrc;
167 struct wcore_context*
168 wgl_context_create(struct wcore_platform *wc_plat,
169 struct wcore_config *wc_config,
170 struct wcore_context *wc_share_ctx)
172 struct wgl_config *config = wgl_config(wc_config);
173 struct wgl_context *share_ctx = wgl_context(wc_share_ctx);
174 struct wgl_context *self;
176 self = wcore_calloc(sizeof(*self));
177 if (!self)
178 return NULL;
180 wcore_context_init(&self->wcore, wc_config);
182 self->hglrc = wgl_context_create_native(config, share_ctx);
183 if (!self->hglrc)
184 goto fail;
186 return &self->wcore;
188 fail:
189 wgl_context_destroy(&self->wcore);
190 return NULL;