1 // SPDX-FileCopyrightText: Copyright 2014 Emil Velikov
2 // SPDX-License-Identifier: BSD-2-Clause
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"
16 wgl_context_destroy(struct wcore_context
*wc_self
)
18 struct wgl_context
*self
= wgl_context(wc_self
);
22 ok
&= wglDeleteContext(self
->hglrc
);
29 /// @brief Fill @a attrib_list, which will be given to wglCreateContextAttribsARB().
31 /// This does not validate the `config->context_*` attributes. That validation
32 /// occurred during waffle_config_choose().
34 wgl_context_fill_attrib_list(struct wgl_config
*config
,
37 struct wcore_config_attrs
*attrs
= &config
->wcore
.attrs
;
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
;
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
;
94 if (attrs
->context_forward_compatible
) {
95 context_flags
|= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
;
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
;
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;
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
;
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)))) {
140 // Choose a large size to prevent accidental overflow.
143 ok
= wgl_context_fill_attrib_list(config
, attrib_list
);
147 hglrc
= dpy
->wglCreateContextAttribsARB(config
->window
->hDC
,
151 wcore_errorf(WAFFLE_ERROR_UNKNOWN
,
152 "wglCreateContextAttribsARB failed");
157 hglrc
= wglCreateContext(config
->window
->hDC
);
159 wcore_errorf(WAFFLE_ERROR_UNKNOWN
, "wglCreateContext failed");
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
));
180 wcore_context_init(&self
->wcore
, wc_config
);
182 self
->hglrc
= wgl_context_create_native(config
, share_ctx
);
189 wgl_context_destroy(&self
->wcore
);