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->get_param(
273 wgl_dpy->screen, PIPE_CAP_CONTEXT_PRIORITY_MASK);
274
275 disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
276
277 if (wgl_dpy->screen->is_format_supported(
278 wgl_dpy->screen, PIPE_FORMAT_B8G8R8A8_SRGB, PIPE_TEXTURE_2D, 0, 0,
279 PIPE_BIND_RENDER_TARGET))
280 disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
281
282 disp->Extensions.KHR_create_context = EGL_TRUE;
283
284 disp->Extensions.KHR_image_base = EGL_TRUE;
285 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
286 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
287 disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
288 disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
289
290 disp->Extensions.KHR_fence_sync = EGL_TRUE;
291 disp->Extensions.KHR_reusable_sync = EGL_TRUE;
292 disp->Extensions.KHR_wait_sync = EGL_TRUE;
293
294 if (!wgl_add_configs(disp)) {
295 err = "wgl: failed to add configs";
296 goto cleanup;
297 }
298
299 return EGL_TRUE;
300
301 cleanup:
302 wgl_display_destroy(disp);
303 return _eglError(EGL_NOT_INITIALIZED, err);
304 }
305
306 static EGLBoolean
wgl_initialize(_EGLDisplay * disp)307 wgl_initialize(_EGLDisplay *disp)
308 {
309 EGLBoolean ret = EGL_FALSE;
310 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
311
312 /* In the case where the application calls eglMakeCurrent(context1),
313 * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
314 * or eglMakeCurrent(NULL) before that), wgl_dpy structure is still
315 * initialized, as we need it to be able to free context1 correctly.
316 *
317 * It would probably be safest to forcibly release the display with
318 * wgl_display_release, to make sure the display is reinitialized correctly.
319 * However, the EGL spec states that we need to keep a reference to the
320 * current context (so we cannot call wgl_make_current(NULL)), and therefore
321 * we would leak context1 as we would be missing the old display connection
322 * to free it up correctly.
323 */
324 if (wgl_dpy) {
325 p_atomic_inc(&wgl_dpy->ref_count);
326 return EGL_TRUE;
327 }
328
329 switch (disp->Platform) {
330 case _EGL_PLATFORM_SURFACELESS:
331 ret = wgl_initialize_impl(disp, NULL);
332 break;
333 case _EGL_PLATFORM_WINDOWS:
334 ret = wgl_initialize_impl(disp, disp->PlatformDisplay);
335 break;
336 default:
337 unreachable("Callers ensure we cannot get here.");
338 return EGL_FALSE;
339 }
340
341 if (!ret)
342 return EGL_FALSE;
343
344 wgl_dpy = wgl_egl_display(disp);
345 p_atomic_inc(&wgl_dpy->ref_count);
346
347 return EGL_TRUE;
348 }
349
350 /**
351 * Decrement display reference count, and free up display if necessary.
352 */
353 static void
wgl_display_release(_EGLDisplay * disp)354 wgl_display_release(_EGLDisplay *disp)
355 {
356 struct wgl_egl_display *wgl_dpy;
357
358 if (!disp)
359 return;
360
361 wgl_dpy = wgl_egl_display(disp);
362
363 assert(wgl_dpy->ref_count > 0);
364 if (!p_atomic_dec_zero(&wgl_dpy->ref_count))
365 return;
366
367 _eglCleanupDisplay(disp);
368 wgl_display_destroy(disp);
369 }
370
371 /**
372 * Called via eglTerminate(), drv->Terminate().
373 *
374 * This must be guaranteed to be called exactly once, even if eglTerminate is
375 * called many times (without a eglInitialize in between).
376 */
377 static EGLBoolean
wgl_terminate(_EGLDisplay * disp)378 wgl_terminate(_EGLDisplay *disp)
379 {
380 /* Release all non-current Context/Surfaces. */
381 _eglReleaseDisplayResources(disp);
382
383 wgl_display_release(disp);
384
385 return EGL_TRUE;
386 }
387
388 /**
389 * Called via eglCreateContext(), drv->CreateContext().
390 */
391 static _EGLContext *
wgl_create_context(_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)392 wgl_create_context(_EGLDisplay *disp, _EGLConfig *conf, _EGLContext *share_list,
393 const EGLint *attrib_list)
394 {
395 struct wgl_egl_context *wgl_ctx;
396 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
397 struct wgl_egl_context *wgl_ctx_shared = wgl_egl_context(share_list);
398 struct stw_context *shared = wgl_ctx_shared ? wgl_ctx_shared->ctx : NULL;
399 struct wgl_egl_config *wgl_config = wgl_egl_config(conf);
400 const struct stw_pixelformat_info *stw_config;
401
402 wgl_ctx = malloc(sizeof(*wgl_ctx));
403 if (!wgl_ctx) {
404 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
405 return NULL;
406 }
407
408 if (!_eglInitContext(&wgl_ctx->base, disp, conf, share_list, attrib_list))
409 goto cleanup;
410
411 unsigned profile_mask = 0;
412 switch (wgl_ctx->base.ClientAPI) {
413 case EGL_OPENGL_ES_API:
414 profile_mask = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
415 break;
416 case EGL_OPENGL_API:
417 if ((wgl_ctx->base.ClientMajorVersion >= 4 ||
418 (wgl_ctx->base.ClientMajorVersion == 3 &&
419 wgl_ctx->base.ClientMinorVersion >= 2)) &&
420 wgl_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
421 profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
422 else if (wgl_ctx->base.ClientMajorVersion == 3 &&
423 wgl_ctx->base.ClientMinorVersion == 1)
424 profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
425 else
426 profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
427 break;
428 default:
429 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
430 free(wgl_ctx);
431 return NULL;
432 }
433
434 if (conf != NULL) {
435 /* The config chosen here isn't necessarily
436 * used for surfaces later.
437 * A pixmap surface will use the single config.
438 * This opportunity depends on disabling the
439 * doubleBufferMode check in
440 * src/mesa/main/context.c:check_compatible()
441 */
442 if (wgl_config->stw_config[1])
443 stw_config = wgl_config->stw_config[1];
444 else
445 stw_config = wgl_config->stw_config[0];
446 } else
447 stw_config = NULL;
448
449 unsigned flags = 0;
450 if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)
451 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
452 if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR)
453 flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
454 unsigned resetStrategy = WGL_NO_RESET_NOTIFICATION_ARB;
455 if (wgl_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION)
456 resetStrategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;
457 wgl_ctx->ctx = stw_create_context_attribs(
458 disp->PlatformDisplay, 0, shared, &wgl_dpy->base,
459 wgl_ctx->base.ClientMajorVersion, wgl_ctx->base.ClientMinorVersion, flags,
460 profile_mask, stw_config, resetStrategy);
461
462 if (!wgl_ctx->ctx)
463 goto cleanup;
464
465 return &wgl_ctx->base;
466
467 cleanup:
468 free(wgl_ctx);
469 return NULL;
470 }
471
472 /**
473 * Called via eglDestroyContext(), drv->DestroyContext().
474 */
475 static EGLBoolean
wgl_destroy_context(_EGLDisplay * disp,_EGLContext * ctx)476 wgl_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
477 {
478 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
479
480 if (_eglPutContext(ctx)) {
481 stw_destroy_context(wgl_ctx->ctx);
482 free(wgl_ctx);
483 }
484
485 return EGL_TRUE;
486 }
487
488 static EGLBoolean
wgl_destroy_surface(_EGLDisplay * disp,_EGLSurface * surf)489 wgl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
490 {
491 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
492
493 if (!_eglPutSurface(surf))
494 return EGL_TRUE;
495
496 if (wgl_surf->fb->owner == STW_FRAMEBUFFER_PBUFFER) {
497 DestroyWindow(wgl_surf->fb->hWnd);
498 } else {
499 struct stw_context *ctx = stw_current_context();
500 stw_framebuffer_lock(wgl_surf->fb);
501 stw_framebuffer_release_locked(wgl_surf->fb, ctx ? ctx->st : NULL);
502 }
503 return EGL_TRUE;
504 }
505
506 static void
wgl_gl_flush_get(_glapi_proc * glFlush)507 wgl_gl_flush_get(_glapi_proc *glFlush)
508 {
509 *glFlush = _glapi_get_proc_address("glFlush");
510 }
511
512 static void
wgl_gl_flush()513 wgl_gl_flush()
514 {
515 static void (*glFlush)(void);
516 static util_once_flag once = UTIL_ONCE_FLAG_INIT;
517
518 util_call_once_data(&once, (util_call_once_data_func)wgl_gl_flush_get,
519 &glFlush);
520
521 /* if glFlush is not available things are horribly broken */
522 if (!glFlush) {
523 _eglLog(_EGL_WARNING, "wgl: failed to find glFlush entry point");
524 return;
525 }
526
527 glFlush();
528 }
529
530 /**
531 * Called via eglMakeCurrent(), drv->MakeCurrent().
532 */
533 static EGLBoolean
wgl_make_current(_EGLDisplay * disp,_EGLSurface * dsurf,_EGLSurface * rsurf,_EGLContext * ctx)534 wgl_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, _EGLSurface *rsurf,
535 _EGLContext *ctx)
536 {
537 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
538 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
539 _EGLDisplay *old_disp = NULL;
540 _EGLContext *old_ctx;
541 _EGLSurface *old_dsurf, *old_rsurf;
542 _EGLSurface *tmp_dsurf, *tmp_rsurf;
543 struct stw_framebuffer *ddraw, *rdraw;
544 struct stw_context *cctx;
545 EGLint egl_error = EGL_SUCCESS;
546
547 if (!wgl_dpy)
548 return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
549
550 /* make new bindings, set the EGL error otherwise */
551 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
552 return EGL_FALSE;
553
554 if (old_ctx) {
555 struct stw_context *old_cctx = wgl_egl_context(old_ctx)->ctx;
556 old_disp = old_ctx->Resource.Display;
557
558 /* flush before context switch */
559 wgl_gl_flush();
560
561 stw_unbind_context(old_cctx);
562 }
563
564 ddraw = (dsurf) ? wgl_egl_surface(dsurf)->fb : NULL;
565 rdraw = (rsurf) ? wgl_egl_surface(rsurf)->fb : NULL;
566 cctx = (wgl_ctx) ? wgl_ctx->ctx : NULL;
567
568 if (cctx || ddraw || rdraw) {
569 if (!stw_make_current(ddraw, rdraw, cctx)) {
570 _EGLContext *tmp_ctx;
571
572 /* stw_make_current failed. We cannot tell for sure why, but
573 * setting the error to EGL_BAD_MATCH is surely better than leaving it
574 * as EGL_SUCCESS.
575 */
576 egl_error = EGL_BAD_MATCH;
577
578 /* undo the previous _eglBindContext */
579 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf,
580 &tmp_rsurf);
581 assert(&wgl_ctx->base == ctx && tmp_dsurf == dsurf &&
582 tmp_rsurf == rsurf);
583
584 _eglPutSurface(dsurf);
585 _eglPutSurface(rsurf);
586 _eglPutContext(ctx);
587
588 _eglPutSurface(old_dsurf);
589 _eglPutSurface(old_rsurf);
590 _eglPutContext(old_ctx);
591
592 ddraw = (old_dsurf) ? wgl_egl_surface(old_dsurf)->fb : NULL;
593 rdraw = (old_rsurf) ? wgl_egl_surface(old_rsurf)->fb : NULL;
594 cctx = (old_ctx) ? wgl_egl_context(old_ctx)->ctx : NULL;
595
596 /* undo the previous _eglBindContext */
597 if (stw_make_current(ddraw, rdraw, cctx)) {
598 return _eglError(egl_error, "eglMakeCurrent");
599 }
600
601 /* We cannot restore the same state as it was before calling
602 * eglMakeCurrent() and the spec isn't clear about what to do. We
603 * can prevent EGL from calling into the DRI driver with no DRI
604 * context bound.
605 */
606 dsurf = rsurf = NULL;
607 ctx = NULL;
608
609 _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
610 assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
611 tmp_rsurf == old_rsurf);
612
613 _eglLog(_EGL_WARNING, "wgl: failed to rebind the previous context");
614 } else {
615 /* _eglBindContext succeeded, so take a reference on the
616 * wgl_dpy. This prevents wgl_dpy from being reinitialized when a
617 * EGLDisplay is terminated and then initialized again while a
618 * context is still bound. See wgl_initialize() for a more in depth
619 * explanation. */
620 p_atomic_inc(&wgl_dpy->ref_count);
621 }
622 }
623
624 wgl_destroy_surface(disp, old_dsurf);
625 wgl_destroy_surface(disp, old_rsurf);
626
627 if (old_ctx) {
628 wgl_destroy_context(disp, old_ctx);
629 wgl_display_release(old_disp);
630 }
631
632 if (egl_error != EGL_SUCCESS)
633 return _eglError(egl_error, "eglMakeCurrent");
634
635 return EGL_TRUE;
636 }
637
638 static _EGLSurface *
wgl_create_window_surface(_EGLDisplay * disp,_EGLConfig * conf,void * native_window,const EGLint * attrib_list)639 wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
640 void *native_window, const EGLint *attrib_list)
641 {
642 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
643 struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
644
645 struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
646 if (!wgl_surf)
647 return NULL;
648
649 if (!_eglInitSurface(&wgl_surf->base, disp, EGL_WINDOW_BIT, conf,
650 attrib_list, native_window)) {
651 free(wgl_surf);
652 return NULL;
653 }
654
655 const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
656 ? wgl_conf->stw_config[1]
657 : wgl_conf->stw_config[0];
658 wgl_surf->fb = stw_framebuffer_create(
659 native_window, stw_conf, STW_FRAMEBUFFER_EGL_WINDOW, &wgl_dpy->base);
660 if (!wgl_surf->fb) {
661 free(wgl_surf);
662 return NULL;
663 }
664
665 wgl_surf->fb->swap_interval = 1;
666 stw_framebuffer_unlock(wgl_surf->fb);
667
668 return &wgl_surf->base;
669 }
670
671 static _EGLSurface *
wgl_create_pbuffer_surface(_EGLDisplay * disp,_EGLConfig * conf,const EGLint * attrib_list)672 wgl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
673 const EGLint *attrib_list)
674 {
675 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
676 struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
677
678 struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
679 if (!wgl_surf)
680 return NULL;
681
682 if (!_eglInitSurface(&wgl_surf->base, disp, EGL_PBUFFER_BIT, conf,
683 attrib_list, NULL)) {
684 free(wgl_surf);
685 return NULL;
686 }
687
688 const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
689 ? wgl_conf->stw_config[1]
690 : wgl_conf->stw_config[0];
691 wgl_surf->fb = stw_pbuffer_create(stw_conf, wgl_surf->base.Width,
692 wgl_surf->base.Height, &wgl_dpy->base);
693 if (!wgl_surf->fb) {
694 free(wgl_surf);
695 return NULL;
696 }
697
698 wgl_surf->fb->swap_interval = 1;
699 stw_framebuffer_unlock(wgl_surf->fb);
700
701 return &wgl_surf->base;
702 }
703
704 static EGLBoolean
wgl_query_surface(_EGLDisplay * disp,_EGLSurface * surf,EGLint attribute,EGLint * value)705 wgl_query_surface(_EGLDisplay *disp, _EGLSurface *surf, EGLint attribute,
706 EGLint *value)
707 {
708 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
709 RECT client_rect;
710
711 switch (attribute) {
712 case EGL_WIDTH:
713 case EGL_HEIGHT:
714 if (GetClientRect(wgl_surf->fb->hWnd, &client_rect)) {
715 surf->Width = client_rect.right;
716 surf->Height = client_rect.bottom;
717 }
718 break;
719 default:
720 break;
721 }
722 return _eglQuerySurface(disp, surf, attribute, value);
723 }
724
725 static EGLBoolean
wgl_bind_tex_image(_EGLDisplay * disp,_EGLSurface * surf,EGLint buffer)726 wgl_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
727 {
728 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
729
730 _EGLContext *ctx = _eglGetCurrentContext();
731 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
732
733 if (!_eglBindTexImage(disp, surf, buffer))
734 return EGL_FALSE;
735
736 struct pipe_resource *pres = stw_get_framebuffer_resource(
737 wgl_surf->fb->drawable, ST_ATTACHMENT_FRONT_LEFT);
738 enum pipe_format format = pres->format;
739
740 switch (surf->TextureFormat) {
741 case EGL_TEXTURE_RGB:
742 switch (format) {
743 case PIPE_FORMAT_R16G16B16A16_FLOAT:
744 format = PIPE_FORMAT_R16G16B16X16_FLOAT;
745 break;
746 case PIPE_FORMAT_B10G10R10A2_UNORM:
747 format = PIPE_FORMAT_B10G10R10X2_UNORM;
748 break;
749 case PIPE_FORMAT_R10G10B10A2_UNORM:
750 format = PIPE_FORMAT_R10G10B10X2_UNORM;
751 break;
752 case PIPE_FORMAT_BGRA8888_UNORM:
753 format = PIPE_FORMAT_BGRX8888_UNORM;
754 break;
755 case PIPE_FORMAT_ARGB8888_UNORM:
756 format = PIPE_FORMAT_XRGB8888_UNORM;
757 break;
758 default:
759 break;
760 }
761 break;
762 case EGL_TEXTURE_RGBA:
763 break;
764 default:
765 assert(!"Unexpected texture format in wgl_bind_tex_image()");
766 }
767
768 switch (surf->TextureTarget) {
769 case EGL_TEXTURE_2D:
770 break;
771 default:
772 assert(!"Unexpected texture target in wgl_bind_tex_image()");
773 }
774
775 st_context_teximage(wgl_ctx->ctx->st, GL_TEXTURE_2D, 0, format, pres, false);
776
777 return EGL_TRUE;
778 }
779
780 static EGLBoolean
wgl_swap_interval(_EGLDisplay * disp,_EGLSurface * surf,EGLint interval)781 wgl_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
782 {
783 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
784 wgl_surf->fb->swap_interval = interval;
785 return EGL_TRUE;
786 }
787
788 static EGLBoolean
wgl_swap_buffers(_EGLDisplay * disp,_EGLSurface * draw)789 wgl_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
790 {
791 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(draw);
792
793 stw_framebuffer_lock(wgl_surf->fb);
794 HDC hdc = GetDC(wgl_surf->fb->hWnd);
795 BOOL ret = stw_framebuffer_swap_locked(hdc, wgl_surf->fb);
796 ReleaseDC(wgl_surf->fb->hWnd, hdc);
797
798 return ret;
799 }
800
801 static EGLBoolean
wgl_wait_client(_EGLDisplay * disp,_EGLContext * ctx)802 wgl_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
803 {
804 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
805 struct pipe_fence_handle *fence = NULL;
806 st_context_flush(wgl_ctx->ctx->st, ST_FLUSH_END_OF_FRAME | ST_FLUSH_WAIT,
807 &fence, NULL, NULL);
808 return EGL_TRUE;
809 }
810
811 static EGLBoolean
wgl_wait_native(EGLint engine)812 wgl_wait_native(EGLint engine)
813 {
814 if (engine != EGL_CORE_NATIVE_ENGINE)
815 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
816 /* It's unclear what "native" means, but GDI is as good a guess as any */
817 GdiFlush();
818 return EGL_TRUE;
819 }
820
821 static EGLint
egl_error_from_stw_image_error(enum stw_image_error err)822 egl_error_from_stw_image_error(enum stw_image_error err)
823 {
824 switch (err) {
825 case STW_IMAGE_ERROR_SUCCESS:
826 return EGL_SUCCESS;
827 case STW_IMAGE_ERROR_BAD_ALLOC:
828 return EGL_BAD_ALLOC;
829 case STW_IMAGE_ERROR_BAD_MATCH:
830 return EGL_BAD_MATCH;
831 case STW_IMAGE_ERROR_BAD_PARAMETER:
832 return EGL_BAD_PARAMETER;
833 case STW_IMAGE_ERROR_BAD_ACCESS:
834 return EGL_BAD_ACCESS;
835 default:
836 assert(!"unknown stw_image_error code");
837 return EGL_BAD_ALLOC;
838 }
839 }
840
841 static _EGLImage *
wgl_create_image_khr_texture(_EGLDisplay * disp,_EGLContext * ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)842 wgl_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
843 EGLenum target, EGLClientBuffer buffer,
844 const EGLint *attr_list)
845 {
846 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
847 struct wgl_egl_image *wgl_img;
848 GLuint texture = (GLuint)(uintptr_t)buffer;
849 _EGLImageAttribs attrs;
850 GLuint depth;
851 GLenum gl_target;
852 enum stw_image_error error;
853
854 if (texture == 0) {
855 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
856 return EGL_NO_IMAGE_KHR;
857 }
858
859 if (!_eglParseImageAttribList(&attrs, disp, attr_list))
860 return EGL_NO_IMAGE_KHR;
861
862 switch (target) {
863 case EGL_GL_TEXTURE_2D_KHR:
864 depth = 0;
865 gl_target = GL_TEXTURE_2D;
866 break;
867 case EGL_GL_TEXTURE_3D_KHR:
868 depth = attrs.GLTextureZOffset;
869 gl_target = GL_TEXTURE_3D;
870 break;
871 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
872 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
873 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
874 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
875 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
876 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
877 depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
878 gl_target = GL_TEXTURE_CUBE_MAP;
879 break;
880 default:
881 unreachable("Unexpected target in wgl_create_image_khr_texture()");
882 return EGL_NO_IMAGE_KHR;
883 }
884
885 wgl_img = malloc(sizeof *wgl_img);
886 if (!wgl_img) {
887 _eglError(EGL_BAD_ALLOC, "wgl_create_image_khr");
888 return EGL_NO_IMAGE_KHR;
889 }
890
891 _eglInitImage(&wgl_img->base, disp);
892
893 wgl_img->img = stw_create_image_from_texture(
894 wgl_ctx->ctx, gl_target, texture, depth, attrs.GLTextureLevel, &error);
895 assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
896
897 if (!wgl_img->img) {
898 free(wgl_img);
899 _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
900 return EGL_NO_IMAGE_KHR;
901 }
902 return &wgl_img->base;
903 }
904
905 static _EGLImage *
wgl_create_image_khr_renderbuffer(_EGLDisplay * disp,_EGLContext * ctx,EGLClientBuffer buffer,const EGLint * attr_list)906 wgl_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
907 EGLClientBuffer buffer,
908 const EGLint *attr_list)
909 {
910 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
911 struct wgl_egl_image *wgl_img;
912 GLuint renderbuffer = (GLuint)(uintptr_t)buffer;
913 enum stw_image_error error;
914
915 if (renderbuffer == 0) {
916 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
917 return EGL_NO_IMAGE_KHR;
918 }
919
920 wgl_img = malloc(sizeof(*wgl_img));
921 if (!wgl_img) {
922 _eglError(EGL_BAD_ALLOC, "wgl_create_image");
923 return NULL;
924 }
925
926 _eglInitImage(&wgl_img->base, disp);
927
928 wgl_img->img =
929 stw_create_image_from_renderbuffer(wgl_ctx->ctx, renderbuffer, &error);
930 assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
931
932 if (!wgl_img->img) {
933 free(wgl_img);
934 _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
935 return EGL_NO_IMAGE_KHR;
936 }
937
938 return &wgl_img->base;
939 }
940
941 static _EGLImage *
wgl_create_image_khr(_EGLDisplay * disp,_EGLContext * ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)942 wgl_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
943 EGLClientBuffer buffer, const EGLint *attr_list)
944 {
945 switch (target) {
946 case EGL_GL_TEXTURE_2D_KHR:
947 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
948 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
949 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
950 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
951 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
952 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
953 case EGL_GL_TEXTURE_3D_KHR:
954 return wgl_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
955 case EGL_GL_RENDERBUFFER_KHR:
956 return wgl_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
957 default:
958 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
959 return EGL_NO_IMAGE_KHR;
960 }
961 }
962
963 static EGLBoolean
wgl_destroy_image_khr(_EGLDisplay * disp,_EGLImage * img)964 wgl_destroy_image_khr(_EGLDisplay *disp, _EGLImage *img)
965 {
966 struct wgl_egl_image *wgl_img = wgl_egl_image(img);
967 stw_destroy_image(wgl_img->img);
968 free(wgl_img);
969 return EGL_TRUE;
970 }
971
972 static _EGLSync *
wgl_create_sync_khr(_EGLDisplay * disp,EGLenum type,const EGLAttrib * attrib_list)973 wgl_create_sync_khr(_EGLDisplay *disp, EGLenum type,
974 const EGLAttrib *attrib_list)
975 {
976
977 _EGLContext *ctx = _eglGetCurrentContext();
978 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
979 struct wgl_egl_sync *wgl_sync;
980
981 struct st_context *st = wgl_ctx ? wgl_ctx->ctx->st : NULL;
982
983 wgl_sync = calloc(1, sizeof(struct wgl_egl_sync));
984 if (!wgl_sync) {
985 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
986 return NULL;
987 }
988
989 if (!_eglInitSync(&wgl_sync->base, disp, type, attrib_list)) {
990 free(wgl_sync);
991 return NULL;
992 }
993
994 switch (type) {
995 case EGL_SYNC_FENCE_KHR:
996 st_context_flush(st, 0, &wgl_sync->fence, NULL, NULL);
997 if (!wgl_sync->fence) {
998 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
999 free(wgl_sync);
1000 return NULL;
1001 }
1002 break;
1003
1004 case EGL_SYNC_REUSABLE_KHR:
1005 wgl_sync->event = CreateEvent(NULL, true, false, NULL);
1006 if (!wgl_sync->event) {
1007 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
1008 free(wgl_sync);
1009 return NULL;
1010 }
1011 }
1012
1013 wgl_sync->refcount = 1;
1014 return &wgl_sync->base;
1015 }
1016
1017 static void
wgl_egl_unref_sync(struct wgl_egl_display * wgl_dpy,struct wgl_egl_sync * wgl_sync)1018 wgl_egl_unref_sync(struct wgl_egl_display *wgl_dpy,
1019 struct wgl_egl_sync *wgl_sync)
1020 {
1021 if (InterlockedDecrement((volatile LONG *)&wgl_sync->refcount) > 0)
1022 return;
1023
1024 if (wgl_sync->fence)
1025 wgl_dpy->screen->fence_reference(wgl_dpy->screen, &wgl_sync->fence, NULL);
1026 if (wgl_sync->event)
1027 CloseHandle(wgl_sync->event);
1028 free(wgl_sync);
1029 }
1030
1031 static EGLBoolean
wgl_destroy_sync_khr(_EGLDisplay * disp,_EGLSync * sync)1032 wgl_destroy_sync_khr(_EGLDisplay *disp, _EGLSync *sync)
1033 {
1034 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
1035 struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1036 wgl_egl_unref_sync(wgl_dpy, wgl_sync);
1037 return EGL_TRUE;
1038 }
1039
1040 static EGLint
wgl_client_wait_sync_khr(_EGLDisplay * disp,_EGLSync * sync,EGLint flags,EGLTime timeout)1041 wgl_client_wait_sync_khr(_EGLDisplay *disp, _EGLSync *sync, EGLint flags,
1042 EGLTime timeout)
1043 {
1044 _EGLContext *ctx = _eglGetCurrentContext();
1045 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
1046 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1047 struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1048
1049 EGLint ret = EGL_CONDITION_SATISFIED_KHR;
1050
1051 /* the sync object should take a reference while waiting */
1052 InterlockedIncrement((volatile LONG *)&wgl_sync->refcount);
1053
1054 switch (sync->Type) {
1055 case EGL_SYNC_FENCE_KHR:
1056 if (wgl_dpy->screen->fence_finish(wgl_dpy->screen, NULL, wgl_sync->fence,
1057 timeout))
1058 wgl_sync->base.SyncStatus = EGL_SIGNALED_KHR;
1059 else
1060 ret = EGL_TIMEOUT_EXPIRED_KHR;
1061 break;
1062
1063 case EGL_SYNC_REUSABLE_KHR:
1064 if (wgl_ctx && wgl_sync->base.SyncStatus == EGL_UNSIGNALED_KHR &&
1065 (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) {
1066 /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */
1067 wgl_gl_flush();
1068 }
1069
1070 DWORD wait_milliseconds = (timeout == EGL_FOREVER_KHR)
1071 ? INFINITE
1072 : (DWORD)(timeout / 1000000ull);
1073 DWORD wait_ret = WaitForSingleObject(wgl_sync->event, wait_milliseconds);
1074 switch (wait_ret) {
1075 case WAIT_OBJECT_0:
1076 assert(wgl_sync->base.SyncStatus == EGL_SIGNALED_KHR);
1077 break;
1078 case WAIT_TIMEOUT:
1079 assert(wgl_sync->base.SyncStatus == EGL_UNSIGNALED_KHR);
1080 ret = EGL_TIMEOUT_EXPIRED_KHR;
1081 break;
1082 default:
1083 _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR");
1084 ret = EGL_FALSE;
1085 break;
1086 }
1087 break;
1088 }
1089 wgl_egl_unref_sync(wgl_dpy, wgl_sync);
1090
1091 return ret;
1092 }
1093
1094 static EGLint
wgl_wait_sync_khr(_EGLDisplay * disp,_EGLSync * sync)1095 wgl_wait_sync_khr(_EGLDisplay *disp, _EGLSync *sync)
1096 {
1097 _EGLContext *ctx = _eglGetCurrentContext();
1098 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1099 struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1100
1101 if (!wgl_sync->fence)
1102 return EGL_TRUE;
1103
1104 struct pipe_context *pipe = wgl_ctx->ctx->st->pipe;
1105 if (pipe->fence_server_sync)
1106 pipe->fence_server_sync(pipe, wgl_sync->fence);
1107
1108 return EGL_TRUE;
1109 }
1110
1111 static EGLBoolean
wgl_signal_sync_khr(_EGLDisplay * disp,_EGLSync * sync,EGLenum mode)1112 wgl_signal_sync_khr(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode)
1113 {
1114 struct wgl_egl_sync *wgl_sync = wgl_egl_sync(sync);
1115
1116 if (sync->Type != EGL_SYNC_REUSABLE_KHR)
1117 return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
1118
1119 if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR)
1120 return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR");
1121
1122 wgl_sync->base.SyncStatus = mode;
1123
1124 if (mode == EGL_SIGNALED_KHR) {
1125 if (!SetEvent(wgl_sync->event))
1126 return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
1127 } else {
1128 if (!ResetEvent(wgl_sync->event))
1129 return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR");
1130 }
1131
1132 return EGL_TRUE;
1133 }
1134
1135 static const char *
wgl_query_driver_name(_EGLDisplay * disp)1136 wgl_query_driver_name(_EGLDisplay *disp)
1137 {
1138 return stw_get_device()->stw_winsys->get_name();
1139 }
1140
1141 static char *
wgl_query_driver_config(_EGLDisplay * disp)1142 wgl_query_driver_config(_EGLDisplay *disp)
1143 {
1144 return stw_get_config_xml();
1145 }
1146
1147 static int
wgl_interop_query_device_info(_EGLDisplay * disp,_EGLContext * ctx,struct mesa_glinterop_device_info * out)1148 wgl_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx,
1149 struct mesa_glinterop_device_info *out)
1150 {
1151 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1152 return stw_interop_query_device_info(wgl_ctx->ctx, out);
1153 }
1154
1155 static int
wgl_interop_export_object(_EGLDisplay * disp,_EGLContext * ctx,struct mesa_glinterop_export_in * in,struct mesa_glinterop_export_out * out)1156 wgl_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx,
1157 struct mesa_glinterop_export_in *in,
1158 struct mesa_glinterop_export_out *out)
1159 {
1160 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1161 return stw_interop_export_object(wgl_ctx->ctx, in, out);
1162 }
1163
1164 static int
wgl_interop_flush_objects(_EGLDisplay * disp,_EGLContext * ctx,unsigned count,struct mesa_glinterop_export_in * objects,struct mesa_glinterop_flush_out * out)1165 wgl_interop_flush_objects(_EGLDisplay *disp, _EGLContext *ctx, unsigned count,
1166 struct mesa_glinterop_export_in *objects,
1167 struct mesa_glinterop_flush_out *out)
1168 {
1169 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
1170 return stw_interop_flush_objects(wgl_ctx->ctx, count, objects, out);
1171 }
1172
1173 struct _egl_driver _eglDriver = {
1174 .Initialize = wgl_initialize,
1175 .Terminate = wgl_terminate,
1176 .CreateContext = wgl_create_context,
1177 .DestroyContext = wgl_destroy_context,
1178 .MakeCurrent = wgl_make_current,
1179 .CreateWindowSurface = wgl_create_window_surface,
1180 .CreatePbufferSurface = wgl_create_pbuffer_surface,
1181 .DestroySurface = wgl_destroy_surface,
1182 .QuerySurface = wgl_query_surface,
1183 .BindTexImage = wgl_bind_tex_image,
1184 .ReleaseTexImage = _eglReleaseTexImage,
1185 .SwapInterval = wgl_swap_interval,
1186 .SwapBuffers = wgl_swap_buffers,
1187 .WaitClient = wgl_wait_client,
1188 .WaitNative = wgl_wait_native,
1189 .CreateImageKHR = wgl_create_image_khr,
1190 .DestroyImageKHR = wgl_destroy_image_khr,
1191 .CreateSyncKHR = wgl_create_sync_khr,
1192 .DestroySyncKHR = wgl_destroy_sync_khr,
1193 .ClientWaitSyncKHR = wgl_client_wait_sync_khr,
1194 .WaitSyncKHR = wgl_wait_sync_khr,
1195 .SignalSyncKHR = wgl_signal_sync_khr,
1196 .QueryDriverName = wgl_query_driver_name,
1197 .QueryDriverConfig = wgl_query_driver_config,
1198 .GLInteropQueryDeviceInfo = wgl_interop_query_device_info,
1199 .GLInteropExportObject = wgl_interop_export_object,
1200 .GLInteropFlushObjects = wgl_interop_flush_objects,
1201 };
1202