1 // Copyright 2014 Emil Velikov
3 // All rights reserved.
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
8 // - Redistributions of source code must retain the above copyright notice, this
9 // list of conditions and the following disclaimer.
11 // - Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "wcore_config_attrs.h"
32 #include "wcore_error.h"
34 #include "wgl_config.h"
35 #include "wgl_context.h"
36 #include "wgl_display.h"
37 #include "wgl_error.h"
38 #include "wgl_platform.h"
39 #include "wgl_window.h"
42 wgl_config_destroy(struct wcore_config
*wc_self
)
44 struct wgl_config
*self
= wgl_config(wc_self
);
51 ok
&= wgl_window_priv_destroy(&self
->window
->wcore
);
53 ok
&= wcore_config_teardown(wc_self
);
58 /// @brief Check the values of `attrs->context_*`.
60 wgl_config_check_context_attrs(struct wgl_display
*dpy
,
61 const struct wcore_config_attrs
*attrs
)
63 if (attrs
->context_forward_compatible
) {
64 assert(attrs
->context_api
== WAFFLE_CONTEXT_OPENGL
);
65 assert(wcore_config_attrs_version_ge(attrs
, 30));
68 if (attrs
->context_debug
&& !dpy
->ARB_create_context
) {
69 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
,
70 "WGL_ARB_create_context is required in order to "
71 "request a debug context");
75 if (attrs
->context_robust
&& !dpy
->ARB_create_context_robustness
) {
76 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
,
77 "WGL_ARB_create_context_robustness is required in order to "
78 "request a robust access context");
82 switch (attrs
->context_api
) {
83 case WAFFLE_CONTEXT_OPENGL
:
84 if (wgl_context_needs_arb_create_context(attrs
) &&
85 !dpy
->ARB_create_context
) {
86 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
,
87 "WGL_ARB_create_context is required in order to "
88 "request an OpenGL version greater or equal than 3.2");
91 else if (wcore_config_attrs_version_ge(attrs
, 32) && !dpy
->ARB_create_context_profile
) {
92 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
,
93 "WGL_ARB_create_context_profile is required "
94 "to create a context with version >= 3.2");
97 else if (wcore_config_attrs_version_ge(attrs
, 32)) {
98 assert(attrs
->context_profile
== WAFFLE_CONTEXT_CORE_PROFILE
||
99 attrs
->context_profile
== WAFFLE_CONTEXT_COMPATIBILITY_PROFILE
);
102 if (attrs
->context_forward_compatible
&& !dpy
->ARB_create_context
) {
103 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
,
104 "WGL_ARB_create_context is required in order to "
105 "request a forward-compatible context");
111 case WAFFLE_CONTEXT_OPENGL_ES1
:
112 if (!dpy
->EXT_create_context_es_profile
) {
113 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
,
114 "WGL_EXT_create_context_es_profile is required "
115 "to create an OpenGL ES1 context");
121 case WAFFLE_CONTEXT_OPENGL_ES2
:
122 if (!dpy
->EXT_create_context_es2_profile
123 && !dpy
->EXT_create_context_es_profile
) {
124 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
,
125 "WGL_EXT_create_context_es_profile or "
126 "WGL_EXT_create_context_es2_profile is required "
127 "to create an OpenGL ES2 context");
133 case WAFFLE_CONTEXT_OPENGL_ES3
:
134 if (!dpy
->EXT_create_context_es_profile
) {
135 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM
,
136 "WGL_EXT_create_context_es_profile is required "
137 "to create an OpenGL ES3 context");
150 wgl_config_set_pixeldescriptor(struct wgl_config
*config
,
151 const struct wcore_config_attrs
*attrs
)
153 PIXELFORMATDESCRIPTOR
*pfd
= &config
->pfd
;
155 pfd
->nSize
= sizeof(PIXELFORMATDESCRIPTOR
);
158 pfd
->dwFlags
= PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
;
159 if (attrs
->double_buffered
)
160 pfd
->dwFlags
|= PFD_DOUBLEBUFFER
;
162 pfd
->iPixelType
= PFD_TYPE_RGBA
;
164 pfd
->cColorBits
= attrs
->rgba_size
;
165 pfd
->cRedBits
= attrs
->red_size
;
166 pfd
->cGreenBits
= attrs
->green_size
;
167 pfd
->cBlueBits
= attrs
->blue_size
;
168 pfd
->cAlphaBits
= attrs
->alpha_size
;
170 pfd
->cDepthBits
= attrs
->depth_size
;
171 pfd
->cStencilBits
= attrs
->stencil_size
;
173 // XXX: Double check these
174 pfd
->cAccumRedBits
= attrs
->accum_buffer
;
175 pfd
->cAccumGreenBits
= attrs
->accum_buffer
;
176 pfd
->cAccumBlueBits
= attrs
->accum_buffer
;
177 pfd
->cAccumAlphaBits
= attrs
->accum_buffer
;
178 pfd
->cAccumBits
= pfd
->cAccumRedBits
+
179 pfd
->cAccumGreenBits
+
180 pfd
->cAccumBlueBits
+
181 pfd
->cAccumAlphaBits
;
183 pfd
->iLayerType
= PFD_MAIN_PLANE
;
187 wgl_config_choose_native(struct wgl_config
*config
,
188 struct wgl_display
*dpy
,
189 const struct wcore_config_attrs
*attrs
)
192 // Use wglChoosePixelFormatARB if available.
193 if (dpy
->ARB_pixel_format
) {
194 float fAttribs
[1] = { 0 };
196 WGL_COLOR_BITS_ARB
, attrs
->rgba_size
,
197 WGL_RED_BITS_ARB
, attrs
->red_size
,
198 WGL_GREEN_BITS_ARB
, attrs
->green_size
,
199 WGL_BLUE_BITS_ARB
, attrs
->blue_size
,
200 WGL_ALPHA_BITS_ARB
, attrs
->alpha_size
,
202 WGL_DEPTH_BITS_ARB
, attrs
->depth_size
,
203 WGL_STENCIL_BITS_ARB
, attrs
->stencil_size
,
205 WGL_SAMPLE_BUFFERS_ARB
, attrs
->sample_buffers
,
206 WGL_STEREO_ARB
, attrs
->samples
,
208 WGL_DOUBLE_BUFFER_ARB
, attrs
->double_buffered
,
210 WGL_ACCUM_RED_BITS_ARB
, attrs
->accum_buffer
,
211 WGL_ACCUM_GREEN_BITS_ARB
, attrs
->accum_buffer
,
212 WGL_ACCUM_BLUE_BITS_ARB
, attrs
->accum_buffer
,
213 WGL_ACCUM_ALPHA_BITS_ARB
, attrs
->accum_buffer
,
215 WGL_DRAW_TO_WINDOW_ARB
, GL_TRUE
,
216 WGL_ACCELERATION_ARB
, WGL_FULL_ACCELERATION_ARB
,
220 unsigned int num_formats
;
223 // But first we need a current context to use it...
224 ok
= wglMakeCurrent(dpy
->hDC
, dpy
->hglrc
);
228 ok
= dpy
->wglChoosePixelFormatARB(dpy
->hDC
, iAttribs
, fAttribs
, 1,
229 &config
->pixel_format
, &num_formats
);
231 wglMakeCurrent(NULL
, NULL
);
233 if (!ok
|| !num_formats
) {
234 wcore_errorf(WAFFLE_ERROR_UNKNOWN
,
235 "wglChoosePixelFormatARB failed");
241 config
->pixel_format
= ChoosePixelFormat(dpy
->hDC
, &config
->pfd
);
242 if (!config
->pixel_format
) {
243 wcore_errorf(WAFFLE_ERROR_UNKNOWN
,
244 "ChoosePixelFormat failed to find a matching format");
254 wgl_config_choose(struct wcore_platform
*wc_plat
,
255 struct wcore_display
*wc_dpy
,
256 const struct wcore_config_attrs
*attrs
)
258 struct wgl_config
*self
;
259 struct wgl_display
*dpy
= wgl_display(wc_dpy
);
260 struct wcore_window
*wc_window
;
263 ok
= wgl_config_check_context_attrs(dpy
, attrs
);
267 self
= wcore_calloc(sizeof(*self
));
271 ok
= wcore_config_init(&self
->wcore
, wc_dpy
, attrs
);
275 wgl_config_set_pixeldescriptor(self
, attrs
);
277 ok
= wgl_config_choose_native(self
, dpy
, attrs
);
281 // Hurray, we've got the pixel format.
283 wc_window
= wgl_window_priv_create(wc_plat
, &self
->wcore
, 10, 10);
287 self
->window
= wgl_window(wc_window
);
289 // Now let's pray that the root window's hDC is compatible with the
291 ok
= SetPixelFormat(self
->window
->hDC
, self
->pixel_format
, &self
->pfd
);
298 wgl_config_destroy(&self
->wcore
);