2 * Copyright © Microsoft Corporation
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:
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
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
24 #include <egldriver.h>
26 #include <eglcurrent.h>
27 #include <eglcontext.h>
28 #include <eglsurface.h>
32 #include <stw_device.h>
33 #include <stw_pixelformat.h>
34 #include <stw_context.h>
35 #include <stw_framebuffer.h>
36 #include <stw_image.h>
38 #include <GL/wglext.h>
40 #include <pipe/p_screen.h>
41 #include <pipe/p_state.h>
43 #include <mapi/glapi/glapi.h>
46 wgl_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
48 if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
51 if (!_eglMatchConfig(conf, criteria))
57 static struct wgl_egl_config *
58 wgl_add_config(_EGLDisplay *disp, const struct stw_pixelformat_info *stw_config, int id, EGLint surface_type)
60 struct wgl_egl_config *conf;
61 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
63 unsigned int double_buffer;
64 int wgl_shifts[4] = { -1, -1, -1, -1 };
65 unsigned int wgl_sizes[4] = { 0, 0, 0, 0 };
66 _EGLConfig *matching_config;
67 EGLint num_configs = 0;
70 _eglInitConfig(&base, disp, id);
72 double_buffer = (stw_config->pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;
74 if (stw_config->pfd.iPixelType != PFD_TYPE_RGBA)
77 wgl_sizes[0] = stw_config->pfd.cRedBits;
78 wgl_sizes[1] = stw_config->pfd.cGreenBits;
79 wgl_sizes[2] = stw_config->pfd.cBlueBits;
80 wgl_sizes[3] = stw_config->pfd.cAlphaBits;
82 base.RedSize = stw_config->pfd.cRedBits;
83 base.GreenSize = stw_config->pfd.cGreenBits;
84 base.BlueSize = stw_config->pfd.cBlueBits;
85 base.AlphaSize = stw_config->pfd.cAlphaBits;
86 base.BufferSize = stw_config->pfd.cColorBits;
88 wgl_shifts[0] = stw_config->pfd.cRedShift;
89 wgl_shifts[1] = stw_config->pfd.cGreenShift;
90 wgl_shifts[2] = stw_config->pfd.cBlueShift;
91 wgl_shifts[3] = stw_config->pfd.cAlphaShift;
93 if (stw_config->pfd.cAccumBits) {
94 /* Don't expose visuals with the accumulation buffer. */
98 base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH;
99 base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT;
101 base.DepthSize = stw_config->pfd.cDepthBits;
102 base.StencilSize = stw_config->pfd.cStencilBits;
103 base.Samples = stw_config->stvis.samples;
104 base.SampleBuffers = base.Samples > 1;
106 base.NativeRenderable = EGL_TRUE;
108 if (surface_type & EGL_PBUFFER_BIT) {
109 base.BindToTextureRGB = stw_config->bindToTextureRGB;
110 if (base.AlphaSize > 0)
111 base.BindToTextureRGBA = stw_config->bindToTextureRGBA;
115 surface_type &= ~EGL_PIXMAP_BIT;
118 if (!(stw_config->pfd.dwFlags & PFD_DRAW_TO_WINDOW)) {
119 surface_type &= ~EGL_WINDOW_BIT;
125 base.SurfaceType = surface_type;
126 base.RenderableType = disp->ClientAPIs;
127 base.Conformant = disp->ClientAPIs;
129 base.MinSwapInterval = 0;
130 base.MaxSwapInterval = 4;
131 base.YInvertedNOK = EGL_TRUE;
133 if (!_eglValidateConfig(&base, EGL_FALSE)) {
134 _eglLog(_EGL_DEBUG, "wgl: failed to validate config %d", id);
138 config_id = base.ConfigID;
139 base.ConfigID = EGL_DONT_CARE;
140 base.SurfaceType = EGL_DONT_CARE;
141 num_configs = _eglFilterArray(disp->Configs, (void **)&matching_config, 1,
142 (_EGLArrayForEach)wgl_match_config, &base);
144 if (num_configs == 1) {
145 conf = (struct wgl_egl_config *)matching_config;
147 if (!conf->stw_config[double_buffer])
148 conf->stw_config[double_buffer] = stw_config;
150 /* a similar config type is already added (unlikely) => discard */
153 else if (num_configs == 0) {
154 conf = calloc(1, sizeof * conf);
158 conf->stw_config[double_buffer] = stw_config;
160 memcpy(&conf->base, &base, sizeof base);
161 conf->base.SurfaceType = 0;
162 conf->base.ConfigID = config_id;
164 _eglLinkConfig(&conf->base);
167 unreachable("duplicates should not be possible");
171 conf->base.SurfaceType |= surface_type;
177 wgl_add_configs(_EGLDisplay *disp)
179 unsigned int config_count = 0;
180 unsigned surface_type = EGL_PBUFFER_BIT | EGL_WINDOW_BIT;
182 // This is already a filtered set of what the driver supports,
183 // and there's no further filtering needed per-visual
184 for (unsigned i = 1; stw_pixelformat_get_info(i) != NULL; i++) {
186 struct wgl_egl_config *wgl_conf = wgl_add_config(disp, stw_pixelformat_get_info(i),
187 config_count + 1, surface_type);
190 if (wgl_conf->base.ConfigID == config_count + 1)
195 return (config_count != 0);
199 wgl_display_destroy(_EGLDisplay *disp)
205 wgl_initialize_impl(_EGLDisplay *disp, HDC hdc)
207 struct wgl_egl_display *wgl_dpy;
210 wgl_dpy = calloc(1, sizeof * wgl_dpy);
212 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
214 disp->DriverData = (void *)wgl_dpy;
216 if (!stw_init_screen(hdc)) {
217 err = "wgl: failed to initialize screen";
221 struct stw_device *stw_dev = stw_get_device();
222 wgl_dpy->screen = stw_dev->screen;
223 wgl_dpy->smapi = stw_dev->smapi;
225 disp->ClientAPIs = 0;
226 if (_eglIsApiValid(EGL_OPENGL_API))
227 disp->ClientAPIs |= EGL_OPENGL_BIT;
228 if (_eglIsApiValid(EGL_OPENGL_ES_API))
229 disp->ClientAPIs |= EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
231 disp->Extensions.KHR_no_config_context = EGL_TRUE;
232 disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
233 disp->Extensions.MESA_query_driver = EGL_TRUE;
235 /* Report back to EGL the bitmask of priorities supported */
236 disp->Extensions.IMG_context_priority =
237 wgl_dpy->screen->get_param(wgl_dpy->screen, PIPE_CAP_CONTEXT_PRIORITY_MASK);
239 disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
241 if (wgl_dpy->screen->is_format_supported(wgl_dpy->screen,
242 PIPE_FORMAT_B8G8R8A8_SRGB,
243 PIPE_TEXTURE_2D, 0, 0,
244 PIPE_BIND_RENDER_TARGET))
245 disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
247 disp->Extensions.KHR_create_context = EGL_TRUE;
249 disp->Extensions.KHR_image_base = EGL_TRUE;
250 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
251 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
252 disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
253 disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE;
255 if (!wgl_add_configs(disp)) {
256 err = "wgl: failed to add configs";
263 wgl_display_destroy(disp);
264 return _eglError(EGL_NOT_INITIALIZED, err);
268 wgl_initialize(_EGLDisplay *disp)
270 EGLBoolean ret = EGL_FALSE;
271 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
273 /* In the case where the application calls eglMakeCurrent(context1),
274 * eglTerminate, then eglInitialize again (without a call to eglReleaseThread
275 * or eglMakeCurrent(NULL) before that), wgl_dpy structure is still
276 * initialized, as we need it to be able to free context1 correctly.
278 * It would probably be safest to forcibly release the display with
279 * wgl_display_release, to make sure the display is reinitialized correctly.
280 * However, the EGL spec states that we need to keep a reference to the
281 * current context (so we cannot call wgl_make_current(NULL)), and therefore
282 * we would leak context1 as we would be missing the old display connection
283 * to free it up correctly.
286 wgl_dpy->ref_count++;
290 switch (disp->Platform) {
291 case _EGL_PLATFORM_SURFACELESS:
292 ret = wgl_initialize_impl(disp, NULL);
294 case _EGL_PLATFORM_WINDOWS:
295 ret = wgl_initialize_impl(disp, disp->PlatformDisplay);
298 unreachable("Callers ensure we cannot get here.");
305 wgl_dpy = wgl_egl_display(disp);
306 wgl_dpy->ref_count++;
312 * Decrement display reference count, and free up display if necessary.
315 wgl_display_release(_EGLDisplay *disp)
317 struct wgl_egl_display *wgl_dpy;
322 wgl_dpy = wgl_egl_display(disp);
324 assert(wgl_dpy->ref_count > 0);
325 wgl_dpy->ref_count--;
327 if (wgl_dpy->ref_count > 0)
330 _eglCleanupDisplay(disp);
331 wgl_display_destroy(disp);
335 * Called via eglTerminate(), drv->Terminate().
337 * This must be guaranteed to be called exactly once, even if eglTerminate is
338 * called many times (without a eglInitialize in between).
341 wgl_terminate(_EGLDisplay *disp)
343 /* Release all non-current Context/Surfaces. */
344 _eglReleaseDisplayResources(disp);
346 wgl_display_release(disp);
352 * Called via eglCreateContext(), drv->CreateContext().
355 wgl_create_context(_EGLDisplay *disp, _EGLConfig *conf,
356 _EGLContext *share_list, const EGLint *attrib_list)
358 struct wgl_egl_context *wgl_ctx;
359 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
360 struct wgl_egl_context *wgl_ctx_shared = wgl_egl_context(share_list);
361 struct stw_context *shared =
362 wgl_ctx_shared ? wgl_ctx_shared->ctx : NULL;
363 struct wgl_egl_config *wgl_config = wgl_egl_config(conf);
364 const struct stw_pixelformat_info *stw_config;
366 wgl_ctx = malloc(sizeof * wgl_ctx);
368 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
372 if (!_eglInitContext(&wgl_ctx->base, disp, conf, attrib_list))
375 /* The EGL_EXT_create_context_robustness spec says:
377 * "Add to the eglCreateContext context creation errors: [...]
379 * * If the reset notification behavior of <share_context> and the
380 * newly created context are different then an EGL_BAD_MATCH error is
383 if (share_list && share_list->ResetNotificationStrategy !=
384 wgl_ctx->base.ResetNotificationStrategy) {
385 _eglError(EGL_BAD_MATCH, "eglCreateContext");
389 /* The EGL_KHR_create_context_no_error spec says:
391 * "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
392 * used to create <share_context> does not match the value of
393 * EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
395 if (share_list && share_list->NoError != wgl_ctx->base.NoError) {
396 _eglError(EGL_BAD_MATCH, "eglCreateContext");
400 unsigned profile_mask = 0;
401 switch (wgl_ctx->base.ClientAPI) {
402 case EGL_OPENGL_ES_API:
403 profile_mask = WGL_CONTEXT_ES_PROFILE_BIT_EXT;
406 if ((wgl_ctx->base.ClientMajorVersion >= 4
407 || (wgl_ctx->base.ClientMajorVersion == 3
408 && wgl_ctx->base.ClientMinorVersion >= 2))
409 && wgl_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
410 profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
411 else if (wgl_ctx->base.ClientMajorVersion == 3 &&
412 wgl_ctx->base.ClientMinorVersion == 1)
413 profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
415 profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
418 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
424 /* The config chosen here isn't necessarily
425 * used for surfaces later.
426 * A pixmap surface will use the single config.
427 * This opportunity depends on disabling the
428 * doubleBufferMode check in
429 * src/mesa/main/context.c:check_compatible()
431 if (wgl_config->stw_config[1])
432 stw_config = wgl_config->stw_config[1];
434 stw_config = wgl_config->stw_config[0];
440 if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)
441 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
442 if (wgl_ctx->base.Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR)
443 flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
444 unsigned resetStrategy = WGL_NO_RESET_NOTIFICATION_ARB;
445 if (wgl_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION)
446 resetStrategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;
447 wgl_ctx->ctx = stw_create_context_attribs(disp->PlatformDisplay, 0, shared,
449 wgl_ctx->base.ClientMajorVersion,
450 wgl_ctx->base.ClientMinorVersion,
453 stw_config->iPixelFormat,
459 return &wgl_ctx->base;
467 * Called via eglDestroyContext(), drv->DestroyContext().
470 wgl_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
472 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
473 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
475 if (_eglPutContext(ctx)) {
476 stw_destroy_context(wgl_ctx->ctx);
484 wgl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
486 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
488 if (!_eglPutSurface(surf))
491 if (wgl_surf->fb->owner == STW_FRAMEBUFFER_PBUFFER) {
492 DestroyWindow(wgl_surf->fb->hWnd);
494 struct stw_context *ctx = stw_current_context();
495 stw_framebuffer_lock(wgl_surf->fb);
496 stw_framebuffer_release_locked(wgl_surf->fb, ctx ? ctx->st : NULL);
504 static void (*glFlush)(void);
505 static mtx_t glFlushMutex = _MTX_INITIALIZER_NP;
507 mtx_lock(&glFlushMutex);
509 glFlush = _glapi_get_proc_address("glFlush");
510 mtx_unlock(&glFlushMutex);
512 /* if glFlush is not available things are horribly broken */
514 _eglLog(_EGL_WARNING, "wgl: failed to find glFlush entry point");
522 * Called via eglMakeCurrent(), drv->MakeCurrent().
525 wgl_make_current(_EGLDisplay *disp, _EGLSurface *dsurf,
526 _EGLSurface *rsurf, _EGLContext *ctx)
528 struct wgl_egl_display *wgl_dpy = wgl_egl_display(disp);
529 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
530 _EGLDisplay *old_disp = NULL;
531 struct wgl_egl_display *old_wgl_dpy = NULL;
532 _EGLContext *old_ctx;
533 _EGLSurface *old_dsurf, *old_rsurf;
534 _EGLSurface *tmp_dsurf, *tmp_rsurf;
535 struct stw_framebuffer *ddraw, *rdraw;
536 struct stw_context *cctx;
537 EGLint egl_error = EGL_SUCCESS;
540 return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent");
542 /* make new bindings, set the EGL error otherwise */
543 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
547 struct stw_context *old_cctx = wgl_egl_context(old_ctx)->ctx;
548 old_disp = old_ctx->Resource.Display;
549 old_wgl_dpy = wgl_egl_display(old_disp);
551 /* flush before context switch */
556 wgl_surf_update_fence_fd(old_ctx, disp, old_dsurf);
558 /* Disable shared buffer mode */
559 if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
560 old_wgl_dpy->vtbl->set_shared_buffer_mode) {
561 old_wgl_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false);
565 stw_unbind_context(old_cctx);
568 ddraw = (dsurf) ? wgl_egl_surface(dsurf)->fb : NULL;
569 rdraw = (rsurf) ? wgl_egl_surface(rsurf)->fb : NULL;
570 cctx = (wgl_ctx) ? wgl_ctx->ctx : NULL;
572 if (cctx || ddraw || rdraw) {
573 if (!stw_make_current(ddraw, rdraw, cctx)) {
574 _EGLContext *tmp_ctx;
576 /* stw_make_current failed. We cannot tell for sure why, but
577 * setting the error to EGL_BAD_MATCH is surely better than leaving it
580 egl_error = EGL_BAD_MATCH;
582 /* undo the previous _eglBindContext */
583 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf);
584 assert(&wgl_ctx->base == ctx &&
585 tmp_dsurf == dsurf &&
588 _eglPutSurface(dsurf);
589 _eglPutSurface(rsurf);
592 _eglPutSurface(old_dsurf);
593 _eglPutSurface(old_rsurf);
594 _eglPutContext(old_ctx);
596 ddraw = (old_dsurf) ? wgl_egl_surface(old_dsurf)->fb : NULL;
597 rdraw = (old_rsurf) ? wgl_egl_surface(old_rsurf)->fb : NULL;
598 cctx = (old_ctx) ? wgl_egl_context(old_ctx)->ctx : NULL;
600 /* undo the previous wgl_dpy->core->unbindContext */
601 if (stw_make_current(ddraw, rdraw, cctx)) {
603 if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) &&
604 old_wgl_dpy->vtbl->set_shared_buffer_mode) {
605 old_wgl_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true);
609 return _eglError(egl_error, "eglMakeCurrent");
612 /* We cannot restore the same state as it was before calling
613 * eglMakeCurrent() and the spec isn't clear about what to do. We
614 * can prevent EGL from calling into the DRI driver with no DRI
617 dsurf = rsurf = NULL;
620 _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf);
621 assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf &&
622 tmp_rsurf == old_rsurf);
624 _eglLog(_EGL_WARNING, "wgl: failed to rebind the previous context");
627 /* wgl_dpy->core->bindContext succeeded, so take a reference on the
628 * wgl_dpy. This prevents wgl_dpy from being reinitialized when a
629 * EGLDisplay is terminated and then initialized again while a
630 * context is still bound. See wgl_intitialize() for a more in depth
632 wgl_dpy->ref_count++;
636 wgl_destroy_surface(disp, old_dsurf);
637 wgl_destroy_surface(disp, old_rsurf);
640 wgl_destroy_context(disp, old_ctx);
641 wgl_display_release(old_disp);
644 if (egl_error != EGL_SUCCESS)
645 return _eglError(egl_error, "eglMakeCurrent");
648 if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) &&
649 wgl_dpy->vtbl->set_shared_buffer_mode) {
650 /* Always update the shared buffer mode. This is obviously needed when
651 * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When
652 * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the
653 * case where external non-EGL API may have changed window's shared
654 * buffer mode since we last saw it.
656 bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER);
657 wgl_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode);
665 wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
666 void *native_window, const EGLint *attrib_list)
668 struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
670 struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
674 if (!_eglInitSurface(&wgl_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list, native_window)) {
679 const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1] ?
680 wgl_conf->stw_config[1] : wgl_conf->stw_config[0];
681 wgl_surf->fb = stw_framebuffer_create(native_window, stw_conf->iPixelFormat, STW_FRAMEBUFFER_EGL_WINDOW);
687 wgl_surf->fb->swap_interval = 1;
688 stw_framebuffer_unlock(wgl_surf->fb);
690 return &wgl_surf->base;
694 wgl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
695 const EGLint *attrib_list)
697 struct wgl_egl_config *wgl_conf = wgl_egl_config(conf);
699 struct wgl_egl_surface *wgl_surf = calloc(1, sizeof(*wgl_surf));
703 if (!_eglInitSurface(&wgl_surf->base, disp, EGL_PBUFFER_BIT, conf, attrib_list, NULL)) {
708 const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1] ?
709 wgl_conf->stw_config[1] : wgl_conf->stw_config[0];
710 wgl_surf->fb = stw_pbuffer_create(stw_conf->iPixelFormat, wgl_surf->base.Width, wgl_surf->base.Height);
716 wgl_surf->fb->swap_interval = 1;
717 stw_framebuffer_unlock(wgl_surf->fb);
719 return &wgl_surf->base;
723 wgl_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
724 EGLint attribute, EGLint *value)
726 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
732 if (GetClientRect(wgl_surf->fb->hWnd, &client_rect)) {
733 surf->Width = client_rect.right;
734 surf->Height = client_rect.bottom;
740 return _eglQuerySurface(disp, surf, attribute, value);
744 wgl_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
746 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
747 enum st_attachment_type target = ST_TEXTURE_2D;
749 _EGLContext *ctx = _eglGetCurrentContext();
750 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
752 if (!_eglBindTexImage(disp, surf, buffer))
755 struct pipe_resource *pres = stw_get_framebuffer_resource(wgl_surf->fb->stfb, ST_ATTACHMENT_FRONT_LEFT);
756 enum pipe_format format = pres->format;
758 switch (surf->TextureFormat) {
759 case EGL_TEXTURE_RGB:
761 case PIPE_FORMAT_R16G16B16A16_FLOAT:
762 format = PIPE_FORMAT_R16G16B16X16_FLOAT;
764 case PIPE_FORMAT_B10G10R10A2_UNORM:
765 format = PIPE_FORMAT_B10G10R10X2_UNORM;
767 case PIPE_FORMAT_R10G10B10A2_UNORM:
768 format = PIPE_FORMAT_R10G10B10X2_UNORM;
770 case PIPE_FORMAT_BGRA8888_UNORM:
771 format = PIPE_FORMAT_BGRX8888_UNORM;
773 case PIPE_FORMAT_ARGB8888_UNORM:
774 format = PIPE_FORMAT_XRGB8888_UNORM;
780 case EGL_TEXTURE_RGBA:
783 assert(!"Unexpected texture format in wgl_bind_tex_image()");
786 switch (surf->TextureTarget) {
790 assert(!"Unexpected texture target in wgl_bind_tex_image()");
793 wgl_ctx->ctx->st->teximage(wgl_ctx->ctx->st, target, 0, format, pres, false);
799 wgl_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
801 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(surf);
802 wgl_surf->fb->swap_interval = interval;
807 wgl_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
809 struct wgl_egl_display *wgl_disp = wgl_egl_display(disp);
810 struct wgl_egl_surface *wgl_surf = wgl_egl_surface(draw);
812 stw_framebuffer_lock(wgl_surf->fb);
813 HDC hdc = GetDC(wgl_surf->fb->hWnd);
814 BOOL ret = stw_framebuffer_swap_locked(hdc, wgl_surf->fb);
815 ReleaseDC(wgl_surf->fb->hWnd, hdc);
821 wgl_wait_client(_EGLDisplay *disp, _EGLContext *ctx)
823 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
824 struct pipe_fence_handle *fence = NULL;
825 wgl_ctx->ctx->st->flush(wgl_ctx->ctx->st, ST_FLUSH_END_OF_FRAME | ST_FLUSH_WAIT, &fence, NULL, NULL);
830 wgl_wait_native(EGLint engine)
832 if (engine != EGL_CORE_NATIVE_ENGINE)
833 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
834 /* It's unclear what "native" means, but GDI is as good a guess as any */
840 egl_error_from_stw_image_error(enum stw_image_error err)
843 case STW_IMAGE_ERROR_SUCCESS:
845 case STW_IMAGE_ERROR_BAD_ALLOC:
846 return EGL_BAD_ALLOC;
847 case STW_IMAGE_ERROR_BAD_MATCH:
848 return EGL_BAD_MATCH;
849 case STW_IMAGE_ERROR_BAD_PARAMETER:
850 return EGL_BAD_PARAMETER;
851 case STW_IMAGE_ERROR_BAD_ACCESS:
852 return EGL_BAD_ACCESS;
854 assert(!"unknown stw_image_error code");
855 return EGL_BAD_ALLOC;
860 wgl_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
862 EGLClientBuffer buffer,
863 const EGLint *attr_list)
865 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
866 struct wgl_egl_image *wgl_img;
867 GLuint texture = (GLuint) (uintptr_t) buffer;
868 _EGLImageAttribs attrs;
871 enum stw_image_error error;
874 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
875 return EGL_NO_IMAGE_KHR;
878 if (!_eglParseImageAttribList(&attrs, disp, attr_list))
879 return EGL_NO_IMAGE_KHR;
882 case EGL_GL_TEXTURE_2D_KHR:
884 gl_target = GL_TEXTURE_2D;
886 case EGL_GL_TEXTURE_3D_KHR:
887 depth = attrs.GLTextureZOffset;
888 gl_target = GL_TEXTURE_3D;
890 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
891 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
892 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
893 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
894 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
895 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
896 depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
897 gl_target = GL_TEXTURE_CUBE_MAP;
900 unreachable("Unexpected target in wgl_create_image_khr_texture()");
901 return EGL_NO_IMAGE_KHR;
904 wgl_img = malloc(sizeof *wgl_img);
906 _eglError(EGL_BAD_ALLOC, "wgl_create_image_khr");
907 return EGL_NO_IMAGE_KHR;
910 _eglInitImage(&wgl_img->base, disp);
912 wgl_img->img = stw_create_image_from_texture(wgl_ctx->ctx,
916 attrs.GLTextureLevel,
918 assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
922 _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
923 return EGL_NO_IMAGE_KHR;
925 return &wgl_img->base;
929 wgl_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
930 EGLClientBuffer buffer,
931 const EGLint *attr_list)
933 struct wgl_egl_context *wgl_ctx = wgl_egl_context(ctx);
934 struct wgl_egl_image *wgl_img;
935 GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
936 enum stw_image_error error;
938 if (renderbuffer == 0) {
939 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
940 return EGL_NO_IMAGE_KHR;
943 wgl_img = malloc(sizeof(*wgl_img));
945 _eglError(EGL_BAD_ALLOC, "wgl_create_image");
949 _eglInitImage(&wgl_img->base, disp);
951 wgl_img->img = stw_create_image_from_renderbuffer(wgl_ctx->ctx, renderbuffer, &error);
952 assert(!!wgl_img->img == (error == STW_IMAGE_ERROR_SUCCESS));
956 _eglError(egl_error_from_stw_image_error(error), "wgl_create_image_khr");
957 return EGL_NO_IMAGE_KHR;
960 return &wgl_img->base;
964 wgl_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
965 EGLClientBuffer buffer, const EGLint *attr_list)
968 case EGL_GL_TEXTURE_2D_KHR:
969 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
970 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
971 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
972 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
973 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
974 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
975 case EGL_GL_TEXTURE_3D_KHR:
976 return wgl_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
977 case EGL_GL_RENDERBUFFER_KHR:
978 return wgl_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
980 _eglError(EGL_BAD_PARAMETER, "wgl_create_image_khr");
981 return EGL_NO_IMAGE_KHR;
986 wgl_destroy_image_khr(_EGLDisplay *disp, _EGLImage *img)
988 struct wgl_egl_image *wgl_img = wgl_egl_image(img);
989 stw_destroy_image(wgl_img->img);
994 struct _egl_driver _eglDriver = {
995 .Initialize = wgl_initialize,
996 .Terminate = wgl_terminate,
997 .CreateContext = wgl_create_context,
998 .DestroyContext = wgl_destroy_context,
999 .MakeCurrent = wgl_make_current,
1000 .CreateWindowSurface = wgl_create_window_surface,
1001 .CreatePbufferSurface = wgl_create_pbuffer_surface,
1002 .DestroySurface = wgl_destroy_surface,
1003 .QuerySurface = wgl_query_surface,
1004 .BindTexImage = wgl_bind_tex_image,
1005 .ReleaseTexImage = _eglReleaseTexImage,
1006 .GetProcAddress = _glapi_get_proc_address,
1007 .SwapInterval = wgl_swap_interval,
1008 .SwapBuffers = wgl_swap_buffers,
1009 .WaitClient = wgl_wait_client,
1010 .WaitNative = wgl_wait_native,
1011 .CreateImageKHR = wgl_create_image_khr,
1012 .DestroyImageKHR = wgl_destroy_image_khr,