1 /*
2 * Copyright © Microsoft Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "state_tracker/st_context.h"
25
26 #include <eglcontext.h>
27 #include <eglcurrent.h>
28 #include <egldriver.h>
29 #include <egllog.h>
30 #include <eglsurface.h>
31
32 #include "egl_wgl.h"
33
34 #include <stw_context.h>
35 #include <stw_device.h>
36 #include <stw_ext_interop.h>
37 #include <stw_framebuffer.h>
38 #include <stw_image.h>
39 #include <stw_pixelformat.h>
40 #include <stw_winsys.h>
41
42 #include <GL/wglext.h>
43
44 #include <pipe/p_context.h>
45 #include <pipe/p_screen.h>
46 #include <pipe/p_state.h>
47
48 #include "util/u_call_once.h"
49 #include <mapi/glapi/glapi.h>
50
51 #include <GL/mesa_glinterop.h>
52
53 static EGLBoolean
wgl_match_config(const _EGLConfig * conf,const _EGLConfig * criteria)54 wgl_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
55 {
56 if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
57 return EGL_FALSE;
58
59 if (!_eglMatchConfig(conf, criteria))
60 return EGL_FALSE;
61
62 return EGL_TRUE;
63 }
64
65 static struct wgl_egl_config *
wgl_add_config(_EGLDisplay * disp,const struct stw_pixelformat_info * stw_config,int id,EGLint surface_type)66 wgl_add_config(_EGLDisplay *disp, const struct stw_pixelformat_info *stw_config,
67 int id, EGLint surface_type)
68 {
69 struct wgl_egl_config *conf;
70 _EGLConfig base;
71 unsigned int double_buffer;
72 _EGLConfig *matching_config;
73 EGLint num_configs = 0;
74 EGLint config_id;
75
76 _eglInitConfig(&base, disp, id);
77
78 double_buffer = (stw_config->pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;
79
80 if (stw_config->pfd.iPixelType != PFD_TYPE_RGBA)
81 return NULL;
82
83 base.RedSize = stw_config->pfd.cRedBits;
84 base.GreenSize = stw_config->pfd.cGreenBits;
85 base.BlueSize = stw_config->pfd.cBlueBits;
86 base.AlphaSize = stw_config->pfd.cAlphaBits;
87 base.BufferSize = stw_config->pfd.cColorBits;
88
89 if (stw_config->pfd.cAccumBits) {
90 /* Don't expose visuals with the accumulation buffer. */
91 return NULL;
92 }
93
94 base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH;
95 base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT;
96
97 base.DepthSize = stw_config->pfd.cDepthBits;
98 base.StencilSize = stw_config->pfd.cStencilBits;
99 base.Samples = stw_config->stvis.samples;
100 base.SampleBuffers = base.Samples > 1;
101
102 base.NativeRenderable = EGL_TRUE;
103
104 if (surface_type & EGL_PBUFFER_BIT) {
105 base.BindToTextureRGB = stw_config->bindToTextureRGB;
106 if (base.AlphaSize > 0)
107 base.BindToTextureRGBA = stw_config->bindToTextureRGBA;
108 }
109
110 if (double_buffer) {
111 surface_type &= ~EGL_PIXMAP_BIT;
112 }
113
114 if (!(stw_config->pfd.dwFlags & PFD_DRAW_TO_WINDOW)) {
115 surface_type &= ~EGL_WINDOW_BIT;
116 }
117
118 if (!surface_type)
119 return NULL;
120
121 base.SurfaceType = surface_type;
122 base.RenderableType = disp->ClientAPIs;
123 base.Conformant = disp->ClientAPIs;
124
125 base.MinSwapInterval = 0;
126 base.MaxSwapInterval = 4;
127 base.YInvertedNOK = EGL_TRUE;
128
129 if (!_eglValidateConfig(&base, EGL_FALSE)) {
130 _eglLog(_EGL_DEBUG, "wgl: failed to validate config %d", id);
131 return NULL;
132 }
133
134 config_id = base.ConfigID;
135 base.ConfigID = EGL_DONT_CARE;
136 base.SurfaceType = EGL_DONT_CARE;
137 num_configs = _eglFilterArray(disp->Configs, (void **)&matching_config, 1,
138 (_EGLArrayForEach)wgl_match_config, &base);
139
140 if (num_configs == 1) {
141 conf = (struct wgl_egl_config *)matching_config;
142
143 if (!conf->stw_config[double_buffer])
144 conf->stw_config[double_buffer] = stw_config;
145 else
146 /* a similar config type is already added (unlikely) => discard */
147 return NULL;
148 } else if (num_configs == 0) {
149 conf = calloc(1, sizeof(*conf));
150 if (conf == NULL)
151 return NULL;
152
153 conf->stw_config[double_buffer] = stw_config;
154
155 memcpy(&conf->base, &base, sizeof base);
156 conf->base.SurfaceType = 0;
157 conf->base.ConfigID = config_id;
158
159 _eglLinkConfig(&conf->base);
160 } else {
161 unreachable("duplicates should not be possible");
162 return NULL;
163 }
164
165 conf->base.SurfaceType |= surface_type;
166
167 return conf;
168 }
169
170 static EGLBoolean
wgl_add_configs(_EGLDisplay * disp)171 wgl_add_configs(_EGLDisplay *disp)
172 {
173 unsigned int config_count = 0;
174 unsigned surface_type = EGL_PBUFFER_BIT | EGL_WINDOW_BIT;
175
176 // This is already a filtered set of what the driver supports,
177 // and there's no further filtering needed per-visual
178 for (unsigned i = 1; stw_pixelformat_get_info(i) != NULL; i++) {
179
180 struct wgl_egl_config *wgl_conf = wgl_add_config(
181 disp, stw_pixelformat_get_info(i), config_count + 1, surface_type);
182
183 if (wgl_conf) {
184 if (wgl_conf->base.ConfigID == config_count + 1)
185 config_count++;
186 }
187 }
188
189 return (config_count != 0);
190 }
191
192 static void
wgl_display_destroy(_EGLDisplay * disp)193 wgl_display_destroy(_EGLDisplay *disp)
194 {
195 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
196
197 st_screen_destroy(&wgl_dpy->base);
198 free(wgl_dpy);
199 }
200
201 static int
wgl_egl_st_get_param(struct pipe_frontend_screen * fscreen,enum st_manager_param param)202 wgl_egl_st_get_param(struct pipe_frontend_screen *fscreen,
203 enum st_manager_param param)
204 {
205 /* no-op */
206 return 0;
207 }
208
209 static bool
wgl_get_egl_image(struct pipe_frontend_screen * fscreen,void * image,struct st_egl_image * out)210 wgl_get_egl_image(struct pipe_frontend_screen *fscreen, void *image,
211 struct st_egl_image *out)
212 {
213 struct wgl_egl_image *wgl_img = (struct wgl_egl_image *)image;
214 stw_translate_image(wgl_img->img, out);
215 return true;
216 }
217
218 static bool
wgl_validate_egl_image(struct pipe_frontend_screen * fscreen,void * image)219 wgl_validate_egl_image(struct pipe_frontend_screen *fscreen, void *image)
220 {
221 struct wgl_egl_display *wgl_dpy = (struct wgl_egl_display *)fscreen;
222 _EGLDisplay *disp = _eglLockDisplay(wgl_dpy->parent);
223 _EGLImage *img = _eglLookupImage(image, disp);
224 _eglUnlockDisplay(disp);
225
226 if (img == NULL) {
227 _eglError(EGL_BAD_PARAMETER, "wgl_validate_egl_image");
228 return false;
229 }
230
231 return true;
232 }
233
234 static EGLBoolean
wgl_initialize_impl(_EGLDisplay * disp,HDC hdc)235 wgl_initialize_impl(_EGLDisplay *disp, HDC hdc)
236 {
237 struct wgl_egl_display *wgl_dpy;
238 const char *err;
239
240 wgl_dpy = calloc(1, sizeof(*wgl_dpy));
241 if (!wgl_dpy)
242 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
243
244 disp->DriverData = (void *)wgl_dpy;
245 wgl_dpy->parent = disp;
246
247 if (!stw_init_screen(hdc)) {
248 err = "wgl: failed to initialize screen";
249 goto cleanup;
250 }
251
252 struct stw_device *stw_dev = stw_get_device();
253 wgl_dpy->screen = stw_dev->screen;
254
255 wgl_dpy->base.screen = stw_dev->screen;
256 wgl_dpy->base.get_param = wgl_egl_st_get_param;
257 wgl_dpy->base.get_egl_image = wgl_get_egl_image;
258 wgl_dpy->base.validate_egl_image = wgl_validate_egl_image;
259
260 disp->ClientAPIs = 0;
261 if (_eglIsApiValid(EGL_OPENGL_API))
262 disp->ClientAPIs |= EGL_OPENGL_BIT;
263 if (_eglIsApiValid(EGL_OPENGL_ES_API))
264 disp->ClientAPIs |=
265 EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
266
267 disp->Extensions.KHR_no_config_context = EGL_TRUE;
268 disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
269 disp->Extensions.MESA_query_driver = EGL_TRUE;
270
271 /* Report back to EGL the bitmask of priorities supported */
272 disp->Extensions.IMG_context_priority = wgl_dpy->screen->caps.context_priority_mask;
273 disp->Extensions.NV_context_priority_realtime =
274 disp->Extensions.IMG_context_priority &
275 (1 << __EGL_CONTEXT_PRIORITY_REALTIME_BIT);
276
277 disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
278
279 if (wgl_dpy->screen->is_format_supported(
280 wgl_dpy->screen, PIPE_FORMAT_B8G8R8A8_SRGB, PIPE_TEXTURE_2D, 0, 0,
281 PIPE_BIND_RENDER_TARGET))
282 disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
283
284 disp->Extensions.KHR_create_context = EGL_TRUE;
285
286 disp->Extensions.KHR_image_base = EGL_TRUE;
287 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
288 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
289 disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
290 disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
291
292 disp->Extensions.KHR_fence_sync = EGL_TRUE;
293 disp->Extensions.KHR_reusable_sync = EGL_TRUE;
294 disp->Extensions.KHR_wait_sync = EGL_TRUE;
295
296 if (!wgl_add_configs(disp)) {
297 err = "wgl: failed to add configs";
298 goto cleanup;
299 }
300
301 return EGL_TRUE;
302
303 cleanup:
304 wgl_display_destroy(disp);
305 return _eglError(EGL_NOT_INITIALIZED, err);
306 }
307
308 static EGLBoolean
wgl_initialize(_EGLDisplay * disp)309 wgl_initialize(_EGLDisplay *disp)
310 {
311 EGLBoolean ret = EGL_FALSE;
312 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
313
314 /* In the case where the application calls eglMakeCurrent(context1),
315 * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
316 * or eglMakeCurrent(NULL) before that), wgl_dpy structure is still
317 * initialized, as we need it to be able to free context1 correctly.
318 *
319 * It would probably be safest to forcibly release the display with
320 * wgl_display_release, to make sure the display is reinitialized correctly.
321 * However, the EGL spec states that we need to keep a reference to the
322 * current context (so we cannot call wgl_make_current(NULL)), and therefore
323 * we would leak context1 as we would be missing the old display connection
324 * to free it up correctly.
325 */
326 if (wgl_dpy) {
327 p_atomic_inc(&wgl_dpy->ref_count);
328 return EGL_TRUE;
329 }
330
331 switch (disp->Platform) {
332 case _EGL_PLATFORM_SURFACELESS:
333 ret = wgl_initialize_impl(disp, NULL);
334 break;
335 case _EGL_PLATFORM_WINDOWS:
336 ret = wgl_initialize_impl(disp, disp->PlatformDisplay);
337 break;
338 default:
339 unreachable("Callers ensure we cannot get here.");
340 return EGL_FALSE;
341 }
342
343 if (!ret)
344 return EGL_FALSE;
345
346 wgl_dpy = wgl_egl_display(disp);
347 p_atomic_inc(&wgl_dpy->ref_count);
348
349 return EGL_TRUE;
350 }
351
352 /**
353 * Decrement display reference count, and free up display if necessary.
354 */
355 static void
wgl_display_release(_EGLDisplay * disp)356 wgl_display_release(_EGLDisplay *disp)
357 {
358 struct wgl_egl_display *wgl_dpy;
359
360 if (!disp)
361 return;
362
363 wgl_dpy = wgl_egl_display(disp);
364
365 assert(wgl_dpy->ref_count > 0);
366 if (!p_atomic_dec_zero(&wgl_dpy->ref_count))
367 return;
368
369 _eglCleanupDisplay(disp);
370 wgl_display_destroy(disp);
371 }
372
373 /**
374 * Called via eglTerminate(), drv->Terminate().
375 *
376 * This must be guaranteed to be called exactly once, even if eglTerminate is
377 * called many times (without a eglInitialize in between).
378 */
379 static EGLBoolean
wgl_terminate(_EGLDisplay * disp)380 wgl_terminate(_EGLDisplay *disp)
381 {
382 /* Release all non-current Context/Surfaces. */
383 _eglReleaseDisplayResources(disp);
384
385 wgl_display_release(disp);
386
387 return EGL_TRUE;
388 }
389
390 /**
391 * Called via eglCreateContext(), drv->CreateContext().
392 */
393 static _EGLContext *
wgl_create_context(_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)394 wgl_create_context(_EGLDisplay *disp, _EGLConfig *conf, _EGLContext *share_list,
395 const EGLint *attrib_list)
396 {
397 struct wgl_egl_context *wgl_ctx;
398 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
399 struct wgl_egl_context *wgl_ctx_shared = wgl_egl_context(share_list);
400 struct stw_context *shared = wgl_ctx_shared ? wgl_ctx_shared->ctx : NULL;
401 struct wgl_egl_config *wgl_config = wgl_egl_config(conf);
402 const struct stw_pixelformat_info *stw_config;
403
404 wgl_ctx = malloc(sizeof(*wgl_ctx));
405 if (!wgl_ctx) {
406 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
407 return NULL;
408 }
409
410 if (!_eglInitContext(&wgl_ctx->base, disp, conf, share_list, attrib_list))
411 goto cleanup;
412
413 unsigned profile_mask = 0;
414 switch (wgl_ctx->base.ClientAPI) {
415 case EGL_OPENGL_ES_API:
416 profile_mask = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
417 break;
418 case EGL_OPENGL_API:
419 if ((wgl_ctx->base.ClientMajorVersion >= 4 ||
420 (wgl_ctx->base.ClientMajorVersion == 3 &&
421 wgl_ctx->base.ClientMinorVersion >= 2)) &&
422 wgl_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
423 profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
424 else if (wgl_ctx->base.ClientMajorVersion == 3 &&
425 wgl_ctx->base.ClientMinorVersion == 1)
426 profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
427 else
428 profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
429 break;
430 default:
431 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
432 free(wgl_ctx);
433 return NULL;
434 }
435
436 if (conf != NULL) {
437 /* The config chosen here isn't necessarily
438 * used for surfaces later.
439 * A pixmap surface will use the single config.
440 * This opportunity depends on disabling the
441 * doubleBufferMode check in
442 * src/mesa/main/context.c:check_compatible()
443 */
444 if (wgl_config->stw_config[1])
445 stw_config = wgl_config->stw_config[1];
446 else
447 stw_config = wgl_config->stw_config[0];
448 } else
449 stw_config = NULL;
450
451 unsigned flags = 0;
452 if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)
453 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
454 if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR)
455 flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
456 unsigned resetStrategy = WGL_NO_RESET_NOTIFICATION_ARB;
457 if (wgl_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION)
458 resetStrategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;
459 wgl_ctx->ctx = stw_create_context_attribs(
460 disp->PlatformDisplay, 0, shared, &wgl_dpy->base,
461 wgl_ctx->base.ClientMajorVersion, wgl_ctx->base.ClientMinorVersion, flags,
462 profile_mask, stw_config, resetStrategy);
463
464 if (!wgl_ctx->ctx)
465 goto cleanup;
466
467 return &wgl_ctx->base;
468
469 cleanup:
470 free(wgl_ctx);
471 return NULL;
472 }
473
474 /**
475 * Called via eglDestroyContext(), drv->DestroyContext().
476 */
477 static EGLBoolean
wgl_destroy_context(_EGLDisplay * disp,_EGLContext * ctx)478 wgl_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
479 {
480 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
481
482 if (_eglPutContext(ctx)) {
483 stw_destroy_context(wgl_ctx->ctx);
484 free(wgl_ctx);
485 }
486
487 return EGL_TRUE;
488 }
489
490 static EGLBoolean
wgl_destroy_surface(_EGLDisplay * disp,_EGLSurface * surf)491 wgl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
492 {
493 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
494
495 if (!_eglPutSurface(surf))
496 return EGL_TRUE;
497
498 if (wgl_surf->fb->owner == STW_FRAMEBUFFER_PBUFFER) {
499 DestroyWindow(wgl_surf->fb->hWnd);
500 } else {
501 struct stw_context *ctx = stw_current_context();
502 stw_framebuffer_lock(wgl_surf->fb);
503 stw_framebuffer_release_locked(wgl_surf->fb, ctx ? ctx->st : NULL);
504 }
505 return EGL_TRUE;
506 }
507
508 static void
wgl_gl_flush_get(_glapi_proc * glFlush)509 wgl_gl_flush_get(_glapi_proc *glFlush)
510 {
511 *glFlush = _glapi_get_proc_address("glFlush");
512 }
513
514 static void
wgl_gl_flush()515 wgl_gl_flush()
516 {
517 static void (*glFlush)(void);
518 static util_once_flag once = UTIL_ONCE_FLAG_INIT;
519
520 util_call_once_data(&once, (util_call_once_data_func)wgl_gl_flush_get,
521 &glFlush);
522
523 /* if glFlush is not available things are horribly broken */
524 if (!glFlush) {
525 _eglLog(_EGL_WARNING, "wgl: failed to find glFlush entry point");
526 return;
527 }
528
529 glFlush();
530 }
531
532 /**
533 * Called via eglMakeCurrent(), drv->MakeCurrent().
534 */
535 static EGLBoolean
wgl_make_current(_EGLDisplay * disp,_EGLSurface * dsurf,_EGLSurface * rsurf,_EGLContext * ctx)536 wgl_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, _EGLSurface *rsurf,
537 _EGLContext *ctx)
538 {
539 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
540 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
541 _EGLDisplay *old_disp = NULL;
542 _EGLContext *old_ctx;
543 _EGLSurface *old_dsurf, *old_rsurf;
544 _EGLSurface *tmp_dsurf, *tmp_rsurf;
545 struct stw_framebuffer *ddraw, *rdraw;
546 struct stw_context *cctx;
547 EGLint egl_error = EGL_SUCCESS;
548
549 if (!wgl_dpy)
550 return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
551
552 /* make new bindings, set the EGL error otherwise */
553 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
554 return EGL_FALSE;
555
556 if (old_ctx) {
557 struct stw_context *old_cctx = wgl_egl_context(old_ctx)->ctx;
558 old_disp = old_ctx->Resource.Display;
559
560 /* flush before context switch */
561 wgl_gl_flush();
562
563 stw_unbind_context(old_cctx);
564 }
565
566 ddraw = (dsurf) ? wgl_egl_surface(dsurf)->fb : NULL;
567 rdraw = (rsurf) ? wgl_egl_surface(rsurf)->fb : NULL;
568 cctx = (wgl_ctx) ? wgl_ctx->ctx : NULL;
569
570 if (cctx || ddraw || rdraw) {
571 if (!stw_make_current(ddraw, rdraw, cctx)) {
572 _EGLContext *tmp_ctx;
573
574 /* stw_make_current failed. We cannot tell for sure why, but
575 * setting the error to EGL_BAD_MATCH is surely better than leaving it
576 * as EGL_SUCCESS.
577 */
578 egl_error = EGL_BAD_MATCH;
579
580 /* undo the previous _eglBindContext */
581 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf,
582 &tmp_rsurf);
583 assert(&wgl_ctx->base == ctx && tmp_dsurf == dsurf &&
584 tmp_rsurf == rsurf);
585
586 _eglPutSurface(dsurf);
587 _eglPutSurface(rsurf);
588 _eglPutContext(ctx);
589
590 _eglPutSurface(old_dsurf);
591 _eglPutSurface(old_rsurf);
592 _eglPutContext(old_ctx);
593
594 ddraw = (old_dsurf) ? wgl_egl_surface(old_dsurf)->fb : NULL;
595 rdraw = (old_rsurf) ? wgl_egl_surface(old_rsurf)->fb : NULL;
596 cctx = (old_ctx) ? wgl_egl_context(old_ctx)->ctx : NULL;
597
598 /* undo the previous _eglBindContext */
599 if (stw_make_current(ddraw, rdraw, cctx)) {
600 return _eglError(egl_error, "eglMakeCurrent");
601 }
602
603 /* We cannot restore the same state as it was before calling
604 * eglMakeCurrent() and the spec isn't clear about what to do. We
605 * can prevent EGL from calling into the DRI driver with no DRI
606 * context bound.
607 */
608 dsurf = rsurf = NULL;
609 ctx = NULL;
610
611 _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
612 assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
613 tmp_rsurf == old_rsurf);
614
615 _eglLog(_EGL_WARNING, "wgl: failed to rebind the previous context");
616 } else {
617 /* _eglBindContext succeeded, so take a reference on the
618 * wgl_dpy. This prevents wgl_dpy from being reinitialized when a
619 * EGLDisplay is terminated and then initialized again while a
620 * context is still bound. See wgl_initialize() for a more in depth
621 * explanation. */
622 p_atomic_inc(&wgl_dpy->ref_count);
623 }
624 }
625
626 wgl_destroy_surface(disp, old_dsurf);
627 wgl_destroy_surface(disp, old_rsurf);
628
629 if (old_ctx) {
630 wgl_destroy_context(disp, old_ctx);
631 wgl_display_release(old_disp);
632 }
633
634 if (egl_error != EGL_SUCCESS)
635 return _eglError(egl_error, "eglMakeCurrent");
636
637 return EGL_TRUE;
638 }
639
640 static _EGLSurface *
wgl_create_window_surface(_EGLDisplay * disp,_EGLConfig * conf,void * native_window,const EGLint * attrib_list)641 wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
642 void *native_window, const EGLint *attrib_list)
643 {
644 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
645 struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
646
647 struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
648 if (!wgl_surf)
649 return NULL;
650
651 if (!_eglInitSurface(&wgl_surf->base, disp, EGL_WINDOW_BIT, conf,
652 attrib_list, native_window)) {
653 free(wgl_surf);
654 return NULL;
655 }
656
657 const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
658 ? wgl_conf->stw_config[1]
659 : wgl_conf->stw_config[0];
660 wgl_surf->fb = stw_framebuffer_create(
661 native_window, stw_conf, STW_FRAMEBUFFER_EGL_WINDOW, &wgl_dpy->base);
662 if (!wgl_surf->fb) {
663 free(wgl_surf);
664 return NULL;
665 }
666
667 wgl_surf->fb->swap_interval = 1;
668 stw_framebuffer_unlock(wgl_surf->fb);
669
670 return &wgl_surf->base;
671 }
672
673 static _EGLSurface *
wgl_create_pbuffer_surface(_EGLDisplay * disp,_EGLConfig * conf,const EGLint * attrib_list)674 wgl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
675 const EGLint *attrib_list)
676 {
677 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
678 struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
679
680 struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
681 if (!wgl_surf)
682 return NULL;
683
684 if (!_eglInitSurface(&wgl_surf->base, disp, EGL_PBUFFER_BIT, conf,
685 attrib_list, NULL)) {
686 free(wgl_surf);
687 return NULL;
688 }
689
690 const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
691 ? wgl_conf->stw_config[1]
692 : wgl_conf->stw_config[0];
693 wgl_surf->fb = stw_pbuffer_create(stw_conf, wgl_surf->base.Width,
694 wgl_surf->base.Height, &wgl_dpy->base);
695 if (!wgl_surf->fb) {
696 free(wgl_surf);
697 return NULL;
698 }
699
700 wgl_surf->fb->swap_interval = 1;
701 stw_framebuffer_unlock(wgl_surf->fb);
702
703 return &wgl_surf->base;
704 }
705
706 static EGLBoolean
wgl_query_surface(_EGLDisplay * disp,_EGLSurface * surf,EGLint attribute,EGLint * value)707 wgl_query_surface(_EGLDisplay *disp, _EGLSurface *surf, EGLint attribute,
708 EGLint *value)
709 {
710 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
711 RECT client_rect;
712
713 switch (attribute) {
714 case EGL_WIDTH:
715 case EGL_HEIGHT:
716 if (GetClientRect(wgl_surf->fb->hWnd, &client_rect)) {
717 surf->Width = client_rect.right;
718 surf->Height = client_rect.bottom;
719 }
720 break;
721 default:
722 break;
723 }
724 return _eglQuerySurface(disp, surf, attribute, value);
725 }
726
727 static EGLBoolean
wgl_bind_tex_image(_EGLDisplay * disp,_EGLSurface * surf,EGLint buffer)728 wgl_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
729 {
730 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
731
732 _EGLContext *ctx = _eglGetCurrentContext();
733 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
734
735 if (!_eglBindTexImage(disp, surf, buffer))
736 return EGL_FALSE;
737
738 struct pipe_resource *pres = stw_get_framebuffer_resource(
739 wgl_surf->fb->drawable, ST_ATTACHMENT_FRONT_LEFT);
740 enum pipe_format format = pres->format;
741
742 switch (surf->TextureFormat) {
743 case EGL_TEXTURE_RGB:
744 switch (format) {
745 case PIPE_FORMAT_R16G16B16A16_FLOAT:
746 format = PIPE_FORMAT_R16G16B16X16_FLOAT;
747 break;
748 case PIPE_FORMAT_B10G10R10A2_UNORM:
749 format = PIPE_FORMAT_B10G10R10X2_UNORM;
750 break;
751 case PIPE_FORMAT_R10G10B10A2_UNORM:
752 format = PIPE_FORMAT_R10G10B10X2_UNORM;
753 break;
754 case PIPE_FORMAT_BGRA8888_UNORM:
755 format = PIPE_FORMAT_BGRX8888_UNORM;
756 break;
757 case PIPE_FORMAT_ARGB8888_UNORM:
758 format = PIPE_FORMAT_XRGB8888_UNORM;
759 break;
760 default:
761 break;
762 }
763 break;
764 case EGL_TEXTURE_RGBA:
765 break;
766 default:
767 assert(!"Unexpected texture format in wgl_bind_tex_image()");
768 }
769
770 switch (surf->TextureTarget) {
771 case EGL_TEXTURE_2D:
772 break;
773 default:
774 assert(!"Unexpected texture target in wgl_bind_tex_image()");
775 }
776
777 st_context_teximage(wgl_ctx->ctx->st, GL_TEXTURE_2D, 0, format, pres, false);
778
779 return EGL_TRUE;
780 }
781
782 static EGLBoolean
wgl_swap_interval(_EGLDisplay * disp,_EGLSurface * surf,EGLint interval)783 wgl_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
784 {
785 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
786 wgl_surf->fb->swap_interval = interval;
787 return EGL_TRUE;
788 }
789
790 static EGLBoolean
wgl_swap_buffers(_EGLDisplay * disp,_EGLSurface * draw)791 wgl_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
792 {
793 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(draw);
794
795 stw_framebuffer_lock(wgl_surf->fb);
796 HDC hdc = GetDC(wgl_surf->fb->hWnd);
797 BOOL ret = stw_framebuffer_swap_locked(hdc, wgl_surf->fb);
798 ReleaseDC(wgl_surf->fb->hWnd, hdc);
799
800 return ret;
801 }
802
803 static EGLBoolean
wgl_wait_client(_EGLDisplay * disp,_EGLContext * ctx)804 wgl_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
805 {
806 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
807 struct pipe_fence_handle *fence = NULL;
808 st_context_flush(wgl_ctx->ctx->st, ST_FLUSH_END_OF_FRAME | ST_FLUSH_WAIT,
809 &fence, NULL, NULL);
810 return EGL_TRUE;
811 }
812
813 static EGLBoolean
wgl_wait_native(EGLint engine)814 wgl_wait_native(EGLint engine)
815 {
816 if (engine != EGL_CORE_NATIVE_ENGINE)
817 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
818 /* It's unclear what "native" means, but GDI is as good a guess as any */
819 GdiFlush();
820 return EGL_TRUE;
821 }
822
823 static EGLint
egl_error_from_stw_image_error(enum stw_image_error err)824 egl_error_from_stw_image_error(enum stw_image_error err)
825 {
826 switch (err) {
827 case STW_IMAGE_ERROR_SUCCESS:
828 return EGL_SUCCESS;
829 case STW_IMAGE_ERROR_BAD_ALLOC:
830 return EGL_BAD_ALLOC;
831 case STW_IMAGE_ERROR_BAD_MATCH:
832 return EGL_BAD_MATCH;
833 case STW_IMAGE_ERROR_BAD_PARAMETER:
834 return EGL_BAD_PARAMETER;
835 case STW_IMAGE_ERROR_BAD_ACCESS:
836 return EGL_BAD_ACCESS;
837 default:
838 assert(!"unknown stw_image_error code");
839 return EGL_BAD_ALLOC;
840 }
841 }
842
843 static _EGLImage *
wgl_create_image_khr_texture(_EGLDisplay * disp,_EGLContext * ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)844 wgl_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
845 EGLenum target, EGLClientBuffer buffer,
846 const EGLint *attr_list)
847 {
848 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
849 struct wgl_egl_image *wgl_img;
850 GLuint texture = (GLuint)(uintptr_t)buffer;
851 _EGLImageAttribs attrs;
852 GLuint depth;
853 GLenum gl_target;
854 enum stw_image_error error;
855
856 if (texture == 0) {
857 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
858 return EGL_NO_IMAGE_KHR;
859 }
860
861 if (!_eglParseImageAttribList(&attrs, disp, attr_list))
862 return EGL_NO_IMAGE_KHR;
863
864 switch (target) {
865 case EGL_GL_TEXTURE_2D_KHR:
866 depth = 0;
867 gl_target = GL_TEXTURE_2D;
868 break;
869 case EGL_GL_TEXTURE_3D_KHR:
870 depth = attrs.GLTextureZOffset;
871 gl_target = GL_TEXTURE_3D;
872 break;
873 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
874 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
875 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
876 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
877 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
878 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
879 depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
880 gl_target = GL_TEXTURE_CUBE_MAP;
881 break;
882 default:
883 unreachable("Unexpected target in wgl_create_image_khr_texture()");
884 return EGL_NO_IMAGE_KHR;
885 }
886
887 wgl_img = malloc(sizeof *wgl_img);
888 if (!wgl_img) {
889 _eglError(EGL_BAD_ALLOC, "wgl_create_image_khr");
890 return EGL_NO_IMAGE_KHR;
891 }
892
893 _eglInitImage(&wgl_img->base, disp);
894
895 wgl_img->img = stw_create_image_from_texture(
896 wgl_ctx->ctx, gl_target, texture, depth, attrs.GLTextureLevel, &error);
897 assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
898
899 if (!wgl_img->img) {
900 free(wgl_img);
901 _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
902 return EGL_NO_IMAGE_KHR;
903 }
904 return &wgl_img->base;
905 }
906
907 static _EGLImage *
wgl_create_image_khr_renderbuffer(_EGLDisplay * disp,_EGLContext * ctx,EGLClientBuffer buffer,const EGLint * attr_list)908 wgl_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
909 EGLClientBuffer buffer,
910 const EGLint *attr_list)
911 {
912 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
913 struct wgl_egl_image *wgl_img;
914 GLuint renderbuffer = (GLuint)(uintptr_t)buffer;
915 enum stw_image_error error;
916
917 if (renderbuffer == 0) {
918 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
919 return EGL_NO_IMAGE_KHR;
920 }
921
922 wgl_img = malloc(sizeof(*wgl_img));
923 if (!wgl_img) {
924 _eglError(EGL_BAD_ALLOC, "wgl_create_image");
925 return NULL;
926 }
927
928 _eglInitImage(&wgl_img->base, disp);
929
930 wgl_img->img =
931 stw_create_image_from_renderbuffer(wgl_ctx->ctx, renderbuffer, &error);
932 assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
933
934 if (!wgl_img->img) {
935 free(wgl_img);
936 _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
937 return EGL_NO_IMAGE_KHR;
938 }
939
940 return &wgl_img->base;
941 }
942
943 static _EGLImage *
wgl_create_image_khr(_EGLDisplay * disp,_EGLContext * ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)944 wgl_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
945 EGLClientBuffer buffer, const EGLint *attr_list)
946 {
947 switch (target) {
948 case EGL_GL_TEXTURE_2D_KHR:
949 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
950 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
951 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
952 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
953 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
954 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
955 case EGL_GL_TEXTURE_3D_KHR:
956 return wgl_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
957 case EGL_GL_RENDERBUFFER_KHR:
958 return wgl_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
959 default:
960 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
961 return EGL_NO_IMAGE_KHR;
962 }
963 }
964
965 static EGLBoolean
wgl_destroy_image_khr(_EGLDisplay * disp,_EGLImage * img)966 wgl_destroy_image_khr(_EGLDisplay *disp, _EGLImage *img)
967 {
968 struct wgl_egl_image *wgl_img = wgl_egl_image(img);
969 stw_destroy_image(wgl_img->img);
970 free(wgl_img);
971 return EGL_TRUE;
972 }
973
974 static _EGLSync *
wgl_create_sync_khr(_EGLDisplay * disp,EGLenum type,const EGLAttrib * attrib_list)975 wgl_create_sync_khr(_EGLDisplay *disp, EGLenum type,
976 const EGLAttrib *attrib_list)
977 {
978
979 _EGLContext *ctx = _eglGetCurrentContext();
980 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
981 struct wgl_egl_sync *wgl_sync;
982
983 struct st_context *st = wgl_ctx ? wgl_ctx->ctx->st : NULL;
984
985 wgl_sync = calloc(1, sizeof(struct wgl_egl_sync));
986 if (!wgl_sync) {
987 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
988 return NULL;
989 }
990
991 if (!_eglInitSync(&wgl_sync->base, disp, type, attrib_list)) {
992 free(wgl_sync);
993 return NULL;
994 }
995
996 switch (type) {
997 case EGL_SYNC_FENCE_KHR:
998 st_context_flush(st, 0, &wgl_sync->fence, NULL, NULL);
999 if (!wgl_sync->fence) {
1000 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
1001 free(wgl_sync);
1002 return NULL;
1003 }
1004 break;
1005
1006 case EGL_SYNC_REUSABLE_KHR:
1007 wgl_sync->event = CreateEvent(NULL, true, false, NULL);
1008 if (!wgl_sync->event) {
1009 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
1010 free(wgl_sync);
1011 return NULL;
1012 }
1013 }
1014
1015 wgl_sync->refcount = 1;
1016 return &wgl_sync->base;
1017 }
1018
1019 static void
wgl_egl_unref_sync(struct wgl_egl_display * wgl_dpy,struct wgl_egl_sync * wgl_sync)1020 wgl_egl_unref_sync(struct wgl_egl_display *wgl_dpy,
1021 struct wgl_egl_sync *wgl_sync)
1022 {
1023 if (InterlockedDecrement((volatile LONG *)&wgl_sync->refcount) > 0)
1024 return;
1025
1026 if (wgl_sync->fence)
1027 wgl_dpy->screen->fence_reference(wgl_dpy->screen, &wgl_sync->fence, NULL);
1028 if (wgl_sync->event)
1029 CloseHandle(wgl_sync->event);
1030 free(wgl_sync);
1031 }
1032
1033 static EGLBoolean
wgl_destroy_sync_khr(_EGLDisplay * disp,_EGLSync * sync)1034 wgl_destroy_sync_khr(_EGLDisplay *disp, _EGLSync *sync)
1035 {
1036 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
1037 struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1038 wgl_egl_unref_sync(wgl_dpy, wgl_sync);
1039 return EGL_TRUE;
1040 }
1041
1042 static EGLint
wgl_client_wait_sync_khr(_EGLDisplay * disp,_EGLSync * sync,EGLint flags,EGLTime timeout)1043 wgl_client_wait_sync_khr(_EGLDisplay *disp, _EGLSync *sync, EGLint flags,
1044 EGLTime timeout)
1045 {
1046 _EGLContext *ctx = _eglGetCurrentContext();
1047 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
1048 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1049 struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1050
1051 EGLint ret = EGL_CONDITION_SATISFIED_KHR;
1052
1053 /* the sync object should take a reference while waiting */
1054 InterlockedIncrement((volatile LONG *)&wgl_sync->refcount);
1055
1056 switch (sync->Type) {
1057 case EGL_SYNC_FENCE_KHR:
1058 if (wgl_dpy->screen->fence_finish(wgl_dpy->screen, NULL, wgl_sync->fence,
1059 timeout))
1060 wgl_sync->base.SyncStatus = EGL_SIGNALED_KHR;
1061 else
1062 ret = EGL_TIMEOUT_EXPIRED_KHR;
1063 break;
1064
1065 case EGL_SYNC_REUSABLE_KHR:
1066 if (wgl_ctx && wgl_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
1067 (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
1068 /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
1069 wgl_gl_flush();
1070 }
1071
1072 DWORD wait_milliseconds = (timeout == EGL_FOREVER_KHR)
1073 ? INFINITE
1074 : (DWORD)(timeout / 1000000ull);
1075 DWORD wait_ret = WaitForSingleObject(wgl_sync->event, wait_milliseconds);
1076 switch (wait_ret) {
1077 case WAIT_OBJECT_0:
1078 assert(wgl_sync->base.SyncStatus == EGL_SIGNALED_KHR);
1079 break;
1080 case WAIT_TIMEOUT:
1081 assert(wgl_sync->base.SyncStatus == EGL_UNSIGNALED_KHR);
1082 ret = EGL_TIMEOUT_EXPIRED_KHR;
1083 break;
1084 default:
1085 _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
1086 ret = EGL_FALSE;
1087 break;
1088 }
1089 break;
1090 }
1091 wgl_egl_unref_sync(wgl_dpy, wgl_sync);
1092
1093 return ret;
1094 }
1095
1096 static EGLint
wgl_wait_sync_khr(_EGLDisplay * disp,_EGLSync * sync)1097 wgl_wait_sync_khr(_EGLDisplay *disp, _EGLSync *sync)
1098 {
1099 _EGLContext *ctx = _eglGetCurrentContext();
1100 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1101 struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1102
1103 if (!wgl_sync->fence)
1104 return EGL_TRUE;
1105
1106 struct pipe_context *pipe = wgl_ctx->ctx->st->pipe;
1107 if (pipe->fence_server_sync)
1108 pipe->fence_server_sync(pipe, wgl_sync->fence);
1109
1110 return EGL_TRUE;
1111 }
1112
1113 static EGLBoolean
wgl_signal_sync_khr(_EGLDisplay * disp,_EGLSync * sync,EGLenum mode)1114 wgl_signal_sync_khr(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode)
1115 {
1116 struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1117
1118 if (sync->Type != EGL_SYNC_REUSABLE_KHR)
1119 return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
1120
1121 if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
1122 return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
1123
1124 wgl_sync->base.SyncStatus = mode;
1125
1126 if (mode == EGL_SIGNALED_KHR) {
1127 if (!SetEvent(wgl_sync->event))
1128 return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
1129 } else {
1130 if (!ResetEvent(wgl_sync->event))
1131 return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
1132 }
1133
1134 return EGL_TRUE;
1135 }
1136
1137 static const char *
wgl_query_driver_name(_EGLDisplay * disp)1138 wgl_query_driver_name(_EGLDisplay *disp)
1139 {
1140 return stw_get_device()->stw_winsys->get_name();
1141 }
1142
1143 static char *
wgl_query_driver_config(_EGLDisplay * disp)1144 wgl_query_driver_config(_EGLDisplay *disp)
1145 {
1146 return stw_get_config_xml();
1147 }
1148
1149 static int
wgl_interop_query_device_info(_EGLDisplay * disp,_EGLContext * ctx,struct mesa_glinterop_device_info * out)1150 wgl_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx,
1151 struct mesa_glinterop_device_info *out)
1152 {
1153 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1154 return stw_interop_query_device_info(wgl_ctx->ctx, out);
1155 }
1156
1157 static int
wgl_interop_export_object(_EGLDisplay * disp,_EGLContext * ctx,struct mesa_glinterop_export_in * in,struct mesa_glinterop_export_out * out)1158 wgl_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
1159 struct mesa_glinterop_export_in *in,
1160 struct mesa_glinterop_export_out *out)
1161 {
1162 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1163 return stw_interop_export_object(wgl_ctx->ctx, in, out);
1164 }
1165
1166 static int
wgl_interop_flush_objects(_EGLDisplay * disp,_EGLContext * ctx,unsigned count,struct mesa_glinterop_export_in * objects,struct mesa_glinterop_flush_out * out)1167 wgl_interop_flush_objects(_EGLDisplay *disp, _EGLContext *ctx, unsigned count,
1168 struct mesa_glinterop_export_in *objects,
1169 struct mesa_glinterop_flush_out *out)
1170 {
1171 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1172 return stw_interop_flush_objects(wgl_ctx->ctx, count, objects, out);
1173 }
1174
1175 struct _egl_driver _eglDriver = {
1176 .Initialize = wgl_initialize,
1177 .Terminate = wgl_terminate,
1178 .CreateContext = wgl_create_context,
1179 .DestroyContext = wgl_destroy_context,
1180 .MakeCurrent = wgl_make_current,
1181 .CreateWindowSurface = wgl_create_window_surface,
1182 .CreatePbufferSurface = wgl_create_pbuffer_surface,
1183 .DestroySurface = wgl_destroy_surface,
1184 .QuerySurface = wgl_query_surface,
1185 .BindTexImage = wgl_bind_tex_image,
1186 .ReleaseTexImage = _eglReleaseTexImage,
1187 .SwapInterval = wgl_swap_interval,
1188 .SwapBuffers = wgl_swap_buffers,
1189 .WaitClient = wgl_wait_client,
1190 .WaitNative = wgl_wait_native,
1191 .CreateImageKHR = wgl_create_image_khr,
1192 .DestroyImageKHR = wgl_destroy_image_khr,
1193 .CreateSyncKHR = wgl_create_sync_khr,
1194 .DestroySyncKHR = wgl_destroy_sync_khr,
1195 .ClientWaitSyncKHR = wgl_client_wait_sync_khr,
1196 .WaitSyncKHR = wgl_wait_sync_khr,
1197 .SignalSyncKHR = wgl_signal_sync_khr,
1198 .QueryDriverName = wgl_query_driver_name,
1199 .QueryDriverConfig = wgl_query_driver_config,
1200 .GLInteropQueryDeviceInfo = wgl_interop_query_device_info,
1201 .GLInteropExportObject = wgl_interop_export_object,
1202 .GLInteropFlushObjects = wgl_interop_flush_objects,
1203 };
1204