gbm: factor out gbm_window_{init,teardown}
[mesa-waffle.git] / src / waffle / wgl / wgl_config.c
blob69efd533f8a42c62e5f541e2a09596025a22cb65
1 // Copyright 2014 Emil Velikov
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
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.
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <windows.h>
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"
41 bool
42 wgl_config_destroy(struct wcore_config *wc_self)
44 struct wgl_config *self = wgl_config(wc_self);
45 bool ok = true;
47 if (!self)
48 return true;
50 if (self->window)
51 ok &= wgl_window_priv_destroy(&self->window->wcore);
53 ok &= wcore_config_teardown(wc_self);
54 free(self);
55 return ok;
58 /// @brief Check the values of `attrs->context_*`.
59 static bool
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");
72 return false;
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");
79 return false;
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");
89 return false;
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");
95 return false;
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");
106 return false;
109 return true;
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");
116 return false;
119 return true;
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");
128 return false;
131 return true;
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");
138 return false;
141 return true;
143 default:
144 assert(false);
145 return false;
149 static void
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);
156 pfd->nVersion = 1;
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;
186 static bool
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 };
195 int iAttribs[] = {
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;
221 bool ok;
223 // But first we need a current context to use it...
224 ok = wglMakeCurrent(dpy->hDC, dpy->hglrc);
225 if (!ok)
226 return false;
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");
236 return false;
240 else {
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");
245 return false;
249 return true;
253 struct wcore_config*
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;
261 bool ok;
263 ok = wgl_config_check_context_attrs(dpy, attrs);
264 if (!ok)
265 return NULL;
267 self = wcore_calloc(sizeof(*self));
268 if (!self)
269 return NULL;
271 ok = wcore_config_init(&self->wcore, wc_dpy, attrs);
272 if (!ok)
273 goto error;
275 wgl_config_set_pixeldescriptor(self, attrs);
277 ok = wgl_config_choose_native(self, dpy, attrs);
278 if (!ok)
279 goto error;
281 // Hurray, we've got the pixel format.
283 wc_window = wgl_window_priv_create(wc_plat, &self->wcore, 10, 10);
284 if (!wc_window)
285 goto error;
287 self->window = wgl_window(wc_window);
289 // Now let's pray that the root window's hDC is compatible with the
290 // new window hDC.
291 ok = SetPixelFormat(self->window->hDC, self->pixel_format, &self->pfd);
292 if (!ok)
293 goto error;
295 return &self->wcore;
297 error:
298 wgl_config_destroy(&self->wcore);
299 return NULL;