diff options
-rw-r--r-- | configure.ac | 10 | ||||
-rw-r--r-- | src/glx/Makefile.am | 14 | ||||
-rw-r--r-- | src/glx/driwindows_glx.c | 609 | ||||
-rw-r--r-- | src/glx/glxclient.h | 11 | ||||
-rw-r--r-- | src/glx/glxext.c | 19 | ||||
-rw-r--r-- | src/glx/windows/Makefile.am | 31 | ||||
-rw-r--r-- | src/glx/windows/wgl.c | 108 | ||||
-rw-r--r-- | src/glx/windows/wgl.h | 44 | ||||
-rw-r--r-- | src/glx/windows/windows_drawable.c | 192 | ||||
-rw-r--r-- | src/glx/windows/windowsdriconst.h | 45 | ||||
-rw-r--r-- | src/glx/windows/windowsdriproto.pc.in | 9 | ||||
-rw-r--r-- | src/glx/windows/windowsdristr.h | 152 | ||||
-rw-r--r-- | src/glx/windows/windowsgl.c | 403 | ||||
-rw-r--r-- | src/glx/windows/windowsgl.h | 52 | ||||
-rw-r--r-- | src/glx/windows/windowsgl_internal.h | 67 | ||||
-rw-r--r-- | src/glx/windows/xwindowsdri.c | 237 | ||||
-rw-r--r-- | src/glx/windows/xwindowsdri.h | 59 | ||||
-rw-r--r-- | src/mapi/Makefile.am | 3 | ||||
-rw-r--r-- | src/mapi/glapi/gen/Makefile.am | 3 | ||||
-rw-r--r-- | src/mapi/glapi/glapi.h | 2 |
20 files changed, 2066 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac index b81171b0ca4..0604ad9ad20 100644 --- a/configure.ac +++ b/configure.ac @@ -1106,7 +1106,9 @@ fi case "$host_os" in darwin*) dri_platform='apple' ;; -gnu*|cygwin*) +cygwin*) + dri_platform='windows' ;; +gnu*) dri_platform='none' ;; *) dri_platform='drm' ;; @@ -1122,6 +1124,7 @@ AM_CONDITIONAL(HAVE_DRISW_KMS, test "x$have_drisw_kms" = xyes ) AM_CONDITIONAL(HAVE_DRI2, test "x$enable_dri" = xyes -a "x$dri_platform" = xdrm -a "x$have_libdrm" = xyes ) AM_CONDITIONAL(HAVE_DRI3, test "x$enable_dri3" = xyes -a "x$dri_platform" = xdrm -a "x$have_libdrm" = xyes ) AM_CONDITIONAL(HAVE_APPLEDRI, test "x$enable_dri" = xyes -a "x$dri_platform" = xapple ) +AM_CONDITIONAL(HAVE_WINDOWSDRI, test "x$enable_dri" = xyes -a "x$dri_platform" = xwindows ) AC_ARG_ENABLE([shared-glapi], [AS_HELP_STRING([--enable-shared-glapi], @@ -1386,6 +1389,9 @@ xdri) if test x"$dri_platform" = xapple ; then DEFINES="$DEFINES -DGLX_USE_APPLEGL" fi + if test x"$dri_platform" = xwindows ; then + DEFINES="$DEFINES -DGLX_USE_WINDOWSGL" + fi fi # add xf86vidmode if available @@ -2745,6 +2751,8 @@ AC_CONFIG_FILES([Makefile src/glx/Makefile src/glx/apple/Makefile src/glx/tests/Makefile + src/glx/windows/Makefile + src/glx/windows/windowsdriproto.pc src/gtest/Makefile src/intel/Makefile src/intel/tools/Makefile diff --git a/src/glx/Makefile.am b/src/glx/Makefile.am index 3c0cb5f04d6..5884e33f802 100644 --- a/src/glx/Makefile.am +++ b/src/glx/Makefile.am @@ -145,6 +145,16 @@ SUBDIRS += apple libglx_la_LIBADD += $(builddir)/apple/libappleglx.la endif +if HAVE_WINDOWSDRI +libglx_la_SOURCES += \ + driwindows_glx.c + +SUBDIRS += windows +libglx_la_LIBADD += \ + $(builddir)/windows/libwindowsdri.la \ + $(builddir)/windows/libwindowsglx.la +endif + if USE_LIBGLVND_GLX AM_CFLAGS += \ -DGL_LIB_NAME=\"lib@[email protected]\" \ @@ -181,6 +191,10 @@ lib@GL_LIB@_la_SOURCES = lib@GL_LIB@_la_LIBADD = $(GL_LIBS) lib@GL_LIB@_la_LDFLAGS = $(GL_LDFLAGS) +if HAVE_WINDOWSDRI +lib@GL_LIB@_la_LDFLAGS += -lgdi32 -lopengl32 -Wl,--disable-stdcall-fixup +endif + SUBDIRS += . tests include $(top_srcdir)/install-lib-links.mk diff --git a/src/glx/driwindows_glx.c b/src/glx/driwindows_glx.c new file mode 100644 index 00000000000..02d95e7bfd2 --- /dev/null +++ b/src/glx/driwindows_glx.c @@ -0,0 +1,609 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "glxclient.h" +#include "glx_error.h" +#include "dri_common.h" +#include "windows/xwindowsdri.h" +#include "windows/windowsgl.h" + +struct driwindows_display +{ + __GLXDRIdisplay base; + int event_base; +}; + +struct driwindows_context +{ + struct glx_context base; + windowsContext *windowsContext; +}; + +struct driwindows_config +{ + struct glx_config base; + int pxfi; +}; + +struct driwindows_screen +{ + struct glx_screen base; + __DRIscreen *driScreen; + __GLXDRIscreen vtable; + Bool copySubBuffer; +}; + +struct driwindows_drawable +{ + __GLXDRIdrawable base; + windowsDrawable *windowsDrawable; +}; + +/** + * GLXDRI functions + */ + +static void +driwindows_destroy_context(struct glx_context *context) +{ + struct driwindows_context *pcp = (struct driwindows_context *) context; + + driReleaseDrawables(&pcp->base); + + free((char *) context->extensions); + + windows_destroy_context(pcp->windowsContext); + + free(pcp); +} + +static int +driwindows_bind_context(struct glx_context *context, struct glx_context *old, + GLXDrawable draw, GLXDrawable read) +{ + struct driwindows_context *pcp = (struct driwindows_context *) context; + struct driwindows_drawable *pdraw, *pread; + + pdraw = (struct driwindows_drawable *) driFetchDrawable(context, draw); + pread = (struct driwindows_drawable *) driFetchDrawable(context, read); + + driReleaseDrawables(&pcp->base); + + if (pdraw == NULL || pread == NULL) + return GLXBadDrawable; + + if (windows_bind_context(pcp->windowsContext, + pdraw->windowsDrawable, pread->windowsDrawable)) + return Success; + + return GLXBadContext; +} + +static void +driwindows_unbind_context(struct glx_context *context, struct glx_context *new) +{ + struct driwindows_context *pcp = (struct driwindows_context *) context; + + windows_unbind_context(pcp->windowsContext); +} + +static void +driwindows_bind_tex_image(Display * dpy, + GLXDrawable drawable, + int buffer, const int *attrib_list) +{ + struct glx_context *gc = __glXGetCurrentContext(); + struct driwindows_context *pcp = (struct driwindows_context *) gc; + __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); + struct driwindows_drawable *pdraw = (struct driwindows_drawable *) base; + + __glXInitialize(dpy); + + if (pdraw != NULL) { + windows_setTexBuffer(pcp->windowsContext, + pdraw->base.textureTarget, + pdraw->base.textureFormat, + pdraw->windowsDrawable); + } +} + +static void +driwindows_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) +{ + struct glx_context *gc = __glXGetCurrentContext(); + struct driwindows_context *pcp = (struct driwindows_context *) gc; + __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); + struct glx_display *dpyPriv = __glXInitialize(dpy); + struct driwindows_drawable *pdraw = (struct driwindows_drawable *) base; + + if (dpyPriv != NULL && pdraw != NULL) { + windows_releaseTexBuffer(pcp->windowsContext, + pdraw->base.textureTarget, + pdraw->windowsDrawable); + } +} + +static const struct glx_context_vtable driwindows_context_vtable = { + .destroy = driwindows_destroy_context, + .bind = driwindows_bind_context, + .unbind = driwindows_unbind_context, + .wait_gl = NULL, + .wait_x = NULL, + .use_x_font = DRI_glXUseXFont, + .bind_tex_image = driwindows_bind_tex_image, + .release_tex_image = driwindows_release_tex_image, + .get_proc_address = NULL, +}; + +static struct glx_context * +driwindows_create_context(struct glx_screen *base, + struct glx_config *config_base, + struct glx_context *shareList, int renderType) +{ + struct driwindows_context *pcp, *pcp_shared; + struct driwindows_config *config = (struct driwindows_config *) config_base; + struct driwindows_screen *psc = (struct driwindows_screen *) base; + windowsContext *shared = NULL; + + if (!psc->base.driScreen) + return NULL; + + /* Check the renderType value */ + if (!validate_renderType_against_config(config_base, renderType)) + return NULL; + + if (shareList) { + /* If the shareList context is not on this renderer, we cannot possibly + * create a context that shares with it. + */ + if (shareList->vtable->destroy != driwindows_destroy_context) { + return NULL; + } + + pcp_shared = (struct driwindows_context *) shareList; + shared = pcp_shared->windowsContext; + } + + pcp = calloc(1, sizeof *pcp); + if (pcp == NULL) + return NULL; + + if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { + free(pcp); + return NULL; + } + + pcp->base.renderType = renderType; + + InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi); + + pcp->windowsContext = windows_create_context(config->pxfi, shared); + + if (!pcp->windowsContext) { + free(pcp); + return NULL; + } + + pcp->base.vtable = &driwindows_context_vtable; + + return &pcp->base; +} + +static struct glx_context * +driwindows_create_context_attribs(struct glx_screen *base, + struct glx_config *config_base, + struct glx_context *shareList, + unsigned num_attribs, + const uint32_t *attribs, + unsigned *error) +{ + struct driwindows_context *pcp, *pcp_shared; + struct driwindows_config *config = (struct driwindows_config *) config_base; + struct driwindows_screen *psc = (struct driwindows_screen *) base; + windowsContext *shared = NULL; + + int i; + uint32_t renderType = GLX_RGBA_TYPE; + + /* Extract renderType from attribs */ + for (i = 0; i < num_attribs; i++) { + switch (attribs[i * 2]) { + case GLX_RENDER_TYPE: + renderType = attribs[i * 2 + 1]; + break; + } + } + + /* + Perhaps we should map GLX tokens to WGL tokens, but they appear to have + identical values, so far + */ + + if (!psc->base.driScreen) + return NULL; + + /* Check the renderType value */ + if (!validate_renderType_against_config(config_base, renderType)) { + return NULL; + } + + if (shareList) { + /* If the shareList context is not on this renderer, we cannot possibly + * create a context that shares with it. + */ + if (shareList->vtable->destroy != driwindows_destroy_context) { + return NULL; + } + + pcp_shared = (struct driwindows_context *) shareList; + shared = pcp_shared->windowsContext; + } + + pcp = calloc(1, sizeof *pcp); + if (pcp == NULL) + return NULL; + + if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { + free(pcp); + return NULL; + } + + pcp->base.renderType = renderType; + + InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi); + + pcp->windowsContext = windows_create_context_attribs(config->pxfi, + shared, + (const int *)attribs); + if (pcp->windowsContext == NULL) { + free(pcp); + return NULL; + } + + pcp->base.vtable = &driwindows_context_vtable; + + return &pcp->base; +} + +static void +driwindowsDestroyDrawable(__GLXDRIdrawable * pdraw) +{ + struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw; + + windows_destroy_drawable(pdp->windowsDrawable); + + free(pdp); +} + +static __GLXDRIdrawable * +driwindowsCreateDrawable(struct glx_screen *base, XID xDrawable, + GLXDrawable drawable, struct glx_config *modes) +{ + struct driwindows_drawable *pdp; + struct driwindows_screen *psc = (struct driwindows_screen *) base; + + pdp = calloc(1, sizeof(*pdp)); + if (!pdp) + return NULL; + + pdp->base.xDrawable = xDrawable; + pdp->base.drawable = drawable; + pdp->base.psc = &psc->base; + + /* + By this stage, the X drawable already exists, but the GLX drawable may + not. + + Query the server with the XID to find the correct HWND, HPBUFFERARB or + HBITMAP + */ + + unsigned int type; + void *handle; + + if (!XWindowsDRIQueryDrawable(psc->base.dpy, base->scr, drawable, &type, &handle)) + { + free(pdp); + return NULL; + } + + /* No handle found is a failure */ + if (!handle) { + free(pdp); + return NULL; + } + + /* Create a new drawable */ + pdp->windowsDrawable = windows_create_drawable(type, handle); + + if (!pdp->windowsDrawable) { + free(pdp); + return NULL; + } + + pdp->base.destroyDrawable = driwindowsDestroyDrawable; + + return &pdp->base; +} + +static int64_t +driwindowsSwapBuffers(__GLXDRIdrawable * pdraw, + int64_t target_msc, int64_t divisor, int64_t remainder, + Bool flush) +{ + struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw; + + (void) target_msc; + (void) divisor; + (void) remainder; + + if (flush) { + glFlush(); + } + + windows_swap_buffers(pdp->windowsDrawable); + + return 0; +} + +static void +driwindowsCopySubBuffer(__GLXDRIdrawable * pdraw, + int x, int y, int width, int height, Bool flush) +{ + struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw; + + if (flush) { + glFlush(); + } + + windows_copy_subbuffer(pdp->windowsDrawable, x, y, width, height); +} + +static void +driwindowsDestroyScreen(struct glx_screen *base) +{ + struct driwindows_screen *psc = (struct driwindows_screen *) base; + + /* Free the direct rendering per screen data */ + psc->driScreen = NULL; + free(psc); +} + +static const struct glx_screen_vtable driwindows_screen_vtable = { + .create_context = driwindows_create_context, + .create_context_attribs = driwindows_create_context_attribs, + .query_renderer_integer = NULL, + .query_renderer_string = NULL, +}; + +static Bool +driwindowsBindExtensions(struct driwindows_screen *psc) +{ + Bool result = 1; + + const struct + { + char *wglext; + char *glxext; + Bool mandatory; + } extensionMap[] = { + { "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 0 }, + { "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 }, + { "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 }, +// { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 }, +// Not exactly equivalent, needs some more glue to be written + { "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 }, + { "WGL_ARB_multisample", "GLX_ARB_multisample", 1 }, + { "WGL_ARB_multisample", "GLX_SGIS_multisample", 1 }, + { "WGL_ARB_create_context", "GLX_ARB_create_context", 0 }, + { "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 }, + { "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 }, + { "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 }, + }; + + char *wgl_extensions; + char *gl_extensions; + int i; + + windows_extensions(&gl_extensions, &wgl_extensions); + + for (i = 0; i < sizeof(extensionMap)/sizeof(extensionMap[0]); i++) { + if (strstr(wgl_extensions, extensionMap[i].wglext)) { + __glXEnableDirectExtension(&psc->base, extensionMap[i].glxext); + InfoMessageF("enabled %s\n", extensionMap[i].glxext); + } + else if (extensionMap[i].mandatory) { + ErrorMessageF("required WGL extension %s is missing\n", extensionMap[i].wglext); + result = 0; + } + } + + /* + Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might + only be in GL_EXTENSIONS + */ + if (strstr(gl_extensions, "GL_WIN_swap_hint")) { + psc->copySubBuffer = 1; + __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); + InfoMessageF("enabled GLX_MESA_copy_sub_buffer\n"); + } + + free(gl_extensions); + free(wgl_extensions); + + return result; +} + +static struct glx_config * +driwindowsMapConfigs(struct glx_display *priv, int screen, struct glx_config *configs, struct glx_config *fbconfigs) +{ + struct glx_config head, *tail, *m; + + tail = &head; + head.next = NULL; + + for (m = configs; m; m = m->next) { + int fbconfigID = GLX_DONT_CARE; + if (fbconfigs) { + /* + visuals have fbconfigID of GLX_DONT_CARE, so search for a fbconfig + with matching visualID and get the fbconfigID from there + */ + struct glx_config *f; + for (f = fbconfigs; f; f = f->next) { + if (f->visualID == m->visualID) + fbconfigID = f->fbconfigID; + } + } + else { + fbconfigID = m->fbconfigID; + } + + int pxfi; + XWindowsDRIFBConfigToPixelFormat(priv->dpy, screen, fbconfigID, &pxfi); + if (pxfi == 0) + continue; + + struct driwindows_config *config = malloc(sizeof(*config)); + + tail->next = &config->base; + if (tail->next == NULL) + continue; + + config->base = *m; + config->pxfi = pxfi; + + tail = tail->next; + } + + return head.next; +} + +static struct glx_screen * +driwindowsCreateScreen(int screen, struct glx_display *priv) +{ + __GLXDRIscreen *psp; + struct driwindows_screen *psc; + struct glx_config *configs = NULL, *visuals = NULL; + int directCapable; + + psc = calloc(1, sizeof *psc); + if (psc == NULL) + return NULL; + + if (!glx_screen_init(&psc->base, screen, priv)) { + free(psc); + return NULL; + } + + if (!XWindowsDRIQueryDirectRenderingCapable(psc->base.dpy, screen, &directCapable) || + !directCapable) { + ErrorMessageF("Screen is not Windows-DRI capable\n"); + goto handle_error; + } + + /* discover native supported extensions */ + if (!driwindowsBindExtensions(psc)) { + goto handle_error; + } + + /* Augment configs with pxfi information */ + configs = driwindowsMapConfigs(priv, screen, psc->base.configs, NULL); + visuals = driwindowsMapConfigs(priv, screen, psc->base.visuals, configs); + + if (!configs || !visuals) { + ErrorMessageF("No fbConfigs or visuals found\n"); + goto handle_error; + } + + glx_config_destroy_list(psc->base.configs); + psc->base.configs = configs; + glx_config_destroy_list(psc->base.visuals); + psc->base.visuals = visuals; + + psc->base.vtable = &driwindows_screen_vtable; + psp = &psc->vtable; + psc->base.driScreen = psp; + psp->destroyScreen = driwindowsDestroyScreen; + psp->createDrawable = driwindowsCreateDrawable; + psp->swapBuffers = driwindowsSwapBuffers; + + if (psc->copySubBuffer) + psp->copySubBuffer = driwindowsCopySubBuffer; + + return &psc->base; + +handle_error: + glx_screen_cleanup(&psc->base); + + return NULL; +} + +/* Called from __glXFreeDisplayPrivate. + */ +static void +driwindowsDestroyDisplay(__GLXDRIdisplay * dpy) +{ + free(dpy); +} + +/* + * Allocate, initialize and return a __GLXDRIdisplay object. + * This is called from __glXInitialize() when we are given a new + * display pointer. + */ +_X_HIDDEN __GLXDRIdisplay * +driwindowsCreateDisplay(Display * dpy) +{ + struct driwindows_display *pdpyp; + + int eventBase, errorBase; + int major, minor, patch; + + /* Verify server has Windows-DRI extension */ + if (!XWindowsDRIQueryExtension(dpy, &eventBase, &errorBase)) { + ErrorMessageF("Windows-DRI extension not available\n"); + return NULL; + } + + if (!XWindowsDRIQueryVersion(dpy, &major, &minor, &patch)) { + ErrorMessageF("Fetching Windows-DRI extension version failed\n"); + return NULL; + } + + if (!windows_check_renderer()) { + ErrorMessageF("Windows-DRI extension disabled for GDI Generic renderer\n"); + return NULL; + } + + pdpyp = malloc(sizeof *pdpyp); + if (pdpyp == NULL) + return NULL; + + pdpyp->base.destroyDisplay = driwindowsDestroyDisplay; + pdpyp->base.createScreen = driwindowsCreateScreen; + + pdpyp->event_base = eventBase; + + return &pdpyp->base; +} diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h index ed57a296800..70733acb23f 100644 --- a/src/glx/glxclient.h +++ b/src/glx/glxclient.h @@ -154,11 +154,15 @@ struct __GLXDRIdrawableRec extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy); extern __GLXDRIdisplay *driCreateDisplay(Display * dpy); extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy); +extern __GLXDRIdisplay *dri3_create_display(Display * dpy); +extern __GLXDRIdisplay *driwindowsCreateDisplay(Display * dpy); + +/* +** +*/ extern void dri2InvalidateBuffers(Display *dpy, XID drawable); extern unsigned dri2GetSwapEventType(Display *dpy, XID drawable); -extern __GLXDRIdisplay *dri3_create_display(Display * dpy); - /* ** Functions to obtain driver configuration information from a direct ** rendering client application @@ -606,6 +610,9 @@ struct glx_display __GLXDRIdisplay *dri2Display; __GLXDRIdisplay *dri3Display; #endif +#ifdef GLX_USE_WINDOWSGL + __GLXDRIdisplay *windowsdriDisplay; +#endif }; struct glx_drawable { diff --git a/src/glx/glxext.c b/src/glx/glxext.c index dc87fb9e16c..0c2f73fea00 100644 --- a/src/glx/glxext.c +++ b/src/glx/glxext.c @@ -264,6 +264,13 @@ glx_display_free(struct glx_display *priv) (*priv->dri3Display->destroyDisplay) (priv->dri3Display); priv->dri3Display = NULL; #endif /* GLX_USE_DRM */ + +#if defined(GLX_USE_WINDOWSGL) + if (priv->windowsdriDisplay) + (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay); + priv->windowsdriDisplay = NULL; +#endif /* GLX_USE_WINDOWSGL */ + #endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ free((char *) priv); @@ -800,6 +807,12 @@ AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv) if (psc == NULL && priv->driDisplay) psc = (*priv->driDisplay->createScreen) (i, priv); #endif /* GLX_USE_DRM */ + +#ifdef GLX_USE_WINDOWSGL + if (psc == NULL && priv->windowsdriDisplay) + psc = (*priv->windowsdriDisplay->createScreen) (i, priv); +#endif + if (psc == NULL && priv->driswDisplay) psc = (*priv->driswDisplay->createScreen) (i, priv); #endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ @@ -907,6 +920,12 @@ __glXInitialize(Display * dpy) return NULL; } #endif + +#ifdef GLX_USE_WINDOWSGL + if (glx_direct && glx_accel) + dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy); +#endif + if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { free(dpyPriv); return NULL; diff --git a/src/glx/windows/Makefile.am b/src/glx/windows/Makefile.am new file mode 100644 index 00000000000..c76af8156a2 --- /dev/null +++ b/src/glx/windows/Makefile.am @@ -0,0 +1,31 @@ +noinst_LTLIBRARIES = libwindowsdri.la libwindowsglx.la + +# protocol defines for the Windows-DRI server extension +windowsdriincludedir = $(includedir)/X11/extensions +windowsdriinclude_HEADERS = windowsdriconst.h windowsdristr.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = windowsdriproto.pc + +# library for using the Windows-DRI server extension +libwindowsdri_la_SOURCES = xwindowsdri.c xwindowsdri.h + +# native rendering GL for windows +libwindowsglx_la_SOURCES = \ + windowsgl.c \ + windowsgl.h \ + windowsgl_internal.h \ + windows_drawable.c \ + wgl.c + +libwindowsglx_la_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/glx \ + -I$(top_srcdir)/src/mapi \ + -I$(top_srcdir)/src/mapi/glapi \ + -I$(top_builddir)/src/mapi/glapi \ + $(VISIBILITY_CFLAGS) \ + $(SHARED_GLAPI_CFLAGS) \ + $(DEFINES) \ + $(X11_INCLUDES) diff --git a/src/glx/windows/wgl.c b/src/glx/windows/wgl.c new file mode 100644 index 00000000000..ffc97675072 --- /dev/null +++ b/src/glx/windows/wgl.c @@ -0,0 +1,108 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + Wrapper functions for calling WGL extension functions + */ + +#include "wgl.h" + +#include <stdio.h> + +#define RESOLVE_DECL(type) \ + static type type##proc = NULL; + +#define PRERESOLVE(type, symbol) \ + type##proc = (type)wglGetProcAddress(symbol); \ + if (type##proc == NULL) \ + printf("Can't resolve \"%s\"\n", symbol); + +#define CHECK_RESOLVED(type, retval) \ + if (type##proc == NULL) { \ + return retval; \ + } + +#define RESOLVED_PROC(type) type##proc + +RESOLVE_DECL(PFNWGLGETEXTENSIONSSTRINGARBPROC); +RESOLVE_DECL(PFNWGLCREATECONTEXTATTRIBSARBPROC); +RESOLVE_DECL(PFNWGLMAKECONTEXTCURRENTARBPROC); +RESOLVE_DECL(PFNWGLCREATEPBUFFERARBPROC); +RESOLVE_DECL(PFNWGLGETPBUFFERDCARBPROC); +RESOLVE_DECL(PFNWGLRELEASEPBUFFERDCARBPROC); +RESOLVE_DECL(PFNWGLDESTROYPBUFFERARBPROC); + +void wglResolveExtensionProcs(void) +{ + PRERESOLVE(PFNWGLGETEXTENSIONSSTRINGARBPROC, "wglGetExtensionsStringARB"); + PRERESOLVE(PFNWGLCREATECONTEXTATTRIBSARBPROC, "wglCreateContextAttribsARB"); + PRERESOLVE(PFNWGLMAKECONTEXTCURRENTARBPROC, "wglMakeContextCurrentARB"); + PRERESOLVE(PFNWGLCREATEPBUFFERARBPROC, "wglCreatePbufferARB"); + PRERESOLVE(PFNWGLGETPBUFFERDCARBPROC, "wglGetPbufferDCARB"); + PRERESOLVE(PFNWGLRELEASEPBUFFERDCARBPROC, "wglReleasePbufferDCARB"); + PRERESOLVE(PFNWGLDESTROYPBUFFERARBPROC, "wglDestroyPbufferARB"); +} + +const char *wglGetExtensionsStringARB(HDC hdc_) +{ + CHECK_RESOLVED(PFNWGLGETEXTENSIONSSTRINGARBPROC, ""); + return RESOLVED_PROC(PFNWGLGETEXTENSIONSSTRINGARBPROC)(hdc_); +} + +HGLRC wglCreateContextAttribsARB(HDC hdc_, HGLRC hShareContext_, + const int *attribList_) +{ + CHECK_RESOLVED(PFNWGLCREATECONTEXTATTRIBSARBPROC, NULL); + return RESOLVED_PROC(PFNWGLCREATECONTEXTATTRIBSARBPROC)(hdc_, hShareContext_, attribList_); +} + +BOOL wglMakeContextCurrentARB(HDC hDrawDC_, HDC hReadDC_, HGLRC hglrc_) +{ + CHECK_RESOLVED(PFNWGLMAKECONTEXTCURRENTARBPROC, FALSE); + return RESOLVED_PROC(PFNWGLMAKECONTEXTCURRENTARBPROC)(hDrawDC_, hReadDC_, hglrc_); +} + +HPBUFFERARB wglCreatePbufferARB(HDC hDC_, int iPixelFormat_, int iWidth_, + int iHeight_, const int *piAttribList_) +{ + CHECK_RESOLVED(PFNWGLCREATEPBUFFERARBPROC, NULL); + return RESOLVED_PROC(PFNWGLCREATEPBUFFERARBPROC)(hDC_, iPixelFormat_, iWidth_, iHeight_, piAttribList_); +} + +HDC wglGetPbufferDCARB(HPBUFFERARB hPbuffer_) +{ + CHECK_RESOLVED(PFNWGLGETPBUFFERDCARBPROC, NULL); + return RESOLVED_PROC(PFNWGLGETPBUFFERDCARBPROC)(hPbuffer_); +} + +int wglReleasePbufferDCARB(HPBUFFERARB hPbuffer_, HDC hDC_) +{ + CHECK_RESOLVED(PFNWGLRELEASEPBUFFERDCARBPROC, 0) + return RESOLVED_PROC(PFNWGLRELEASEPBUFFERDCARBPROC)(hPbuffer_, hDC_); +} + +BOOL wglDestroyPbufferARB(HPBUFFERARB hPbuffer_) +{ + CHECK_RESOLVED(PFNWGLDESTROYPBUFFERARBPROC, FALSE); + return RESOLVED_PROC(PFNWGLDESTROYPBUFFERARBPROC)(hPbuffer_); +} diff --git a/src/glx/windows/wgl.h b/src/glx/windows/wgl.h new file mode 100644 index 00000000000..b4cb2fcbd70 --- /dev/null +++ b/src/glx/windows/wgl.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef wgl_h +#define wgl_h + +#include <X11/Xmd.h> // for BOOL +#include <X11/Xwindows.h> // as this doesn't provide one +#include <GL/gl.h> +#include <GL/wglext.h> + +void wglResolveExtensionProcs(void); + +const char *wglGetExtensionsStringARB(HDC hdc_); +HGLRC wglCreateContextAttribsARB(HDC hdc_, HGLRC hShareContext_, + const int *attribList_); +BOOL wglMakeContextCurrentARB(HDC hDrawDC_, HDC hReadDC_, HGLRC hglrc_); +HPBUFFERARB wglCreatePbufferARB(HDC hDC_, int iPixelFormat_, int iWidth_, + int iHeight_, const int *piAttribList_); +HDC wglGetPbufferDCARB(HPBUFFERARB hPbuffer_); +int wglReleasePbufferDCARB(HPBUFFERARB hPbuffer_, HDC hDC_); +BOOL wglDestroyPbufferARB(HPBUFFERARB hPbuffer_); + +#endif /* wgl_h */ diff --git a/src/glx/windows/windows_drawable.c b/src/glx/windows/windows_drawable.c new file mode 100644 index 00000000000..3d8227d3b7d --- /dev/null +++ b/src/glx/windows/windows_drawable.c @@ -0,0 +1,192 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "windowsgl.h" +#include "windowsgl_internal.h" +#include "windowsdriconst.h" +#include "wgl.h" + +#include <stdio.h> + +/* + * Window drawable + */ + +static +HDC window_getdc(windowsDrawable *d) +{ + return GetDC(d->hWnd); +} + +static +void window_releasedc(windowsDrawable *d, HDC dc) +{ + ReleaseDC(d->hWnd, dc); +} + +static struct windowsdrawable_callbacks window_callbacks = { + .type = WindowsDRIDrawableWindow, + .getdc = window_getdc, + .releasedc = window_releasedc +}; + +/* + * Pixmap drawable + */ + +static +HDC pixmap_getdc(windowsDrawable *d) +{ + return d->dibDC; +} + +static +void pixmap_releasedc(windowsDrawable *d, HDC dc) +{ + GdiFlush(); +} + +static struct windowsdrawable_callbacks pixmap_callbacks = { + .type = WindowsDRIDrawablePixmap, + .getdc = pixmap_getdc, + .releasedc = pixmap_releasedc +}; + +/* + * Pbuffer drawable + */ + +static +HDC pbuffer_getdc(windowsDrawable *d) +{ + return wglGetPbufferDCARB(d->hPbuffer); +} + +static +void pbuffer_releasedc(windowsDrawable *d, HDC dc) +{ + wglReleasePbufferDCARB(d->hPbuffer, dc); +} + +static struct windowsdrawable_callbacks pbuffer_callbacks = { + .type = WindowsDRIDrawablePbuffer, + .getdc = pbuffer_getdc, + .releasedc = pbuffer_releasedc +}; + +/* + * + */ + +windowsDrawable * +windows_create_drawable(int type, void *handle) +{ + windowsDrawable *d; + + d = calloc(1, sizeof *d); + if (d == NULL) + return NULL; + + switch (type) + { + case WindowsDRIDrawableWindow: + d->hWnd = handle; + d->callbacks = &window_callbacks; + break; + + case WindowsDRIDrawablePixmap: + { + BITMAPINFOHEADER *pBmpHeader; + void *pBits; + + char name[MAX_PATH]; + + d->callbacks = &pixmap_callbacks; + + // Access file mapping object by a name + snprintf(name, sizeof(name), "Local\\CYGWINX_WINDOWSDRI_%08lx", (uintptr_t)handle); + d->hSection = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name); + if (!d->hSection) + printf("OpenFileMapping failed %x\n", GetLastError()); + + // Create a screen-compatible DC + d->dibDC = CreateCompatibleDC(NULL); + + // Map the shared memory section to access the BITMAPINFOHEADER + pBmpHeader = (BITMAPINFOHEADER *)MapViewOfFile(d->hSection, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(BITMAPINFOHEADER)); + if (!pBmpHeader) + printf("MapViewOfFile failed %x\n", GetLastError()); + + // Create a DIB using the file mapping + d->hDIB = CreateDIBSection(d->dibDC, (BITMAPINFO *) pBmpHeader, + DIB_RGB_COLORS, &pBits, d->hSection, + sizeof(BITMAPINFOHEADER)); + + // Done with the BITMAPINFOHEADER + UnmapViewOfFile(pBmpHeader); + + // Select the DIB into the DC + d->hOldDIB = SelectObject(d->dibDC, d->hDIB); + } + break; + + case WindowsDRIDrawablePbuffer: + d->hPbuffer = handle; + d->callbacks = &pbuffer_callbacks; + break; + } + + return d; +} + +void +windows_destroy_drawable(windowsDrawable *drawable) +{ + switch (drawable->callbacks->type) + { + case WindowsDRIDrawableWindow: + break; + + case WindowsDRIDrawablePixmap: + { + // Select the default DIB into the DC + SelectObject(drawable->dibDC, drawable->hOldDIB); + + // delete the screen-compatible DC + DeleteDC(drawable->dibDC); + + // Delete the DIB + DeleteObject(drawable->hDIB); + + // Close the file mapping object + CloseHandle(drawable->hSection); + } + break; + + case WindowsDRIDrawablePbuffer: + + break; + } + + free(drawable); +} diff --git a/src/glx/windows/windowsdriconst.h b/src/glx/windows/windowsdriconst.h new file mode 100644 index 00000000000..b9b28226fe2 --- /dev/null +++ b/src/glx/windows/windowsdriconst.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef WINDOWSDRICONST_H +#define WINDOWSDRICONST_H + +/* Requests */ +#define X_WindowsDRIQueryVersion 0 +#define X_WindowsDRIQueryDirectRenderingCapable 1 +#define X_WindowsDRIQueryDrawable 9 +#define X_WindowsDRIFBConfigToPixelFormat 10 + +/* Events */ +#define WindowsDRINumberEvents 0 + +/* Errors */ +#define WindowsDRIClientNotLocal 0 +#define WindowsDRINumberErrors (WindowsDRIClientNotLocal + 1) + +/* Kinds of Drawables */ +#define WindowsDRIDrawableWindow 0 +#define WindowsDRIDrawablePixmap 1 +#define WindowsDRIDrawablePbuffer 2 + +#endif /* WINDOWSDRICONST_H */ diff --git a/src/glx/windows/windowsdriproto.pc.in b/src/glx/windows/windowsdriproto.pc.in new file mode 100644 index 00000000000..224923d1fcb --- /dev/null +++ b/src/glx/windows/windowsdriproto.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: windowsdriproto +Description: Windows-DRI extension headers +Version: 1.0.0 +Cflags: -I${includedir} diff --git a/src/glx/windows/windowsdristr.h b/src/glx/windows/windowsdristr.h new file mode 100644 index 00000000000..07ab2310c82 --- /dev/null +++ b/src/glx/windows/windowsdristr.h @@ -0,0 +1,152 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef WINDOWSDRISTR_H +#define WINDOWSDRISTR_H + +#include "windowsdriconst.h" + +#define WINDOWSDRINAME "Windows-DRI" + +#define WINDOWS_DRI_MAJOR_VERSION 1 /* current version numbers */ +#define WINDOWS_DRI_MINOR_VERSION 0 +#define WINDOWS_DRI_PATCH_VERSION 0 + +typedef struct _WindowsDRIQueryVersion +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIQueryVersion */ + CARD16 length B16; +} xWindowsDRIQueryVersionReq; +#define sz_xWindowsDRIQueryVersionReq 4 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DRI protocol */ + CARD16 minorVersion B16; /* minor version of DRI protocol */ + CARD32 patchVersion B32; /* patch version of DRI protocol */ + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xWindowsDRIQueryVersionReply; +#define sz_xWindowsDRIQueryVersionReply 32 + +typedef struct _WindowsDRIQueryDirectRenderingCapable +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */ + CARD16 length B16; + CARD32 screen B32; +} xWindowsDRIQueryDirectRenderingCapableReq; +#define sz_xWindowsDRIQueryDirectRenderingCapableReq 8 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + BOOL isCapable; + BOOL pad2; + BOOL pad3; + BOOL pad4; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; + CARD32 pad8 B32; + CARD32 pad9 B32; +} xWindowsDRIQueryDirectRenderingCapableReply; +#define sz_xWindowsDRIQueryDirectRenderingCapableReply 32 + +typedef struct _WindowsDRINotify +{ + BYTE type; /* always eventBase + event type */ + BYTE kind; + CARD16 sequenceNumber B16; + CARD32 time B32; /* time of change */ + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xWindowsDRINotifyEvent; +#define sz_xWindowsDRINotifyEvent 32 + +typedef struct _WindowsDRIQueryDrawable +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIQueryDrawable */ + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; +} xWindowsDRIQueryDrawableReq; +#define sz_xWindowsDRIQueryDrawableReq 12 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 drawable_type B32; + CARD32 handle B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xWindowsDRIQueryDrawableReply; +#define sz_xWindowsDRIQueryDrawableReply 32 + +typedef struct _WindowsDRIFBConfigToPixelFormat +{ + CARD8 reqType; /* always DRIReqCode */ + CARD8 driReqType; /* always X_DRIFBConfigToPixelFormat */ + CARD16 length B16; + CARD32 screen B32; + CARD32 fbConfigID B32; +} xWindowsDRIFBConfigToPixelFormatReq; + +#define sz_xWindowsDRIFBConfigToPixelFormatReq 12 + +typedef struct +{ + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 pixelFormatIndex B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xWindowsDRIFBConfigToPixelFormatReply; +#define sz_xWindowsDRIFBConfigToPixelFormatReply 32 + +#endif /* WINDOWSDRISTR_H */ diff --git a/src/glx/windows/windowsgl.c b/src/glx/windows/windowsgl.c new file mode 100644 index 00000000000..56849da8371 --- /dev/null +++ b/src/glx/windows/windowsgl.c @@ -0,0 +1,403 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "windowsgl.h" +#include "windowsgl_internal.h" + +#include "glapi.h" +#include "wgl.h" + +#include <dlfcn.h> +#include <assert.h> +#include <stdio.h> +#include <strings.h> + +static struct _glapi_table *windows_api = NULL; + +static void * +windows_get_dl_handle(void) +{ + static void *dl_handle = NULL; + + if (!dl_handle) + dl_handle = dlopen("cygnativeGLthunk.dll", RTLD_NOW); + + return dl_handle; +} + +static void +windows_glapi_create_table(void) +{ + if (windows_api) + return; + + windows_api = _glapi_create_table_from_handle(windows_get_dl_handle(), "gl"); + assert(windows_api); +} + +static void windows_glapi_set_dispatch(void) +{ + windows_glapi_create_table(); + _glapi_set_dispatch(windows_api); +} + +windowsContext * +windows_create_context(int pxfi, windowsContext *shared) +{ + windowsContext *gc; + + gc = calloc(1, sizeof *gc); + if (gc == NULL) + return NULL; + + // create a temporary, invisible window +#define GL_TEMP_WINDOW_CLASS "glTempWndClass" + { + static wATOM glTempWndClass = 0; + + if (glTempWndClass == 0) { + WNDCLASSEX wc; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = DefWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(NULL); + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = GL_TEMP_WINDOW_CLASS; + wc.hIconSm = 0; + RegisterClassEx(&wc); + } + } + + HWND hwnd = CreateWindowExA(0, + GL_TEMP_WINDOW_CLASS, + "glWindow", + 0, + 0, 0, 0, 0, + NULL, NULL, GetModuleHandle(NULL), NULL); + HDC hdc = GetDC(hwnd); + + // We must set the windows pixel format before we can create a WGL context + gc->pxfi = pxfi; + SetPixelFormat(hdc, gc->pxfi, NULL); + + gc->ctx = wglCreateContext(hdc); + + if (shared && gc->ctx) + wglShareLists(shared->ctx, gc->ctx); + + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); + + if (!gc->ctx) + { + free(gc); + return NULL; + } + + return gc; +} + +windowsContext * +windows_create_context_attribs(int pxfi, windowsContext *shared, const int *attribList) +{ + windowsContext *gc; + + gc = calloc(1, sizeof *gc); + if (gc == NULL) + return NULL; + + // create a temporary, invisible window +#define GL_TEMP_WINDOW_CLASS "glTempWndClass" + { + static wATOM glTempWndClass = 0; + + if (glTempWndClass == 0) { + WNDCLASSEX wc; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = DefWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(NULL); + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = GL_TEMP_WINDOW_CLASS; + wc.hIconSm = 0; + RegisterClassEx(&wc); + } + } + + HWND hwnd = CreateWindowExA(0, + GL_TEMP_WINDOW_CLASS, + "glWindow", + 0, + 0, 0, 0, 0, + NULL, NULL, GetModuleHandle(NULL), NULL); + HDC hdc = GetDC(hwnd); + HGLRC shareContext = NULL; + if (shared) + shareContext = shared->ctx; + + // We must set the windows pixel format before we can create a WGL context + gc->pxfi = pxfi; + SetPixelFormat(hdc, gc->pxfi, NULL); + + gc->ctx = wglCreateContextAttribsARB(hdc, shareContext, attribList); + + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); + + if (!gc->ctx) + { + free(gc); + return NULL; + } + + return gc; +} + +void +windows_destroy_context(windowsContext *context) +{ + wglDeleteContext(context->ctx); + context->ctx = NULL; + free(context); +} + +int windows_bind_context(windowsContext *context, windowsDrawable *draw, windowsDrawable *read) +{ + HDC drawDc = draw->callbacks->getdc(draw); + + if (!draw->pxfi) + { + SetPixelFormat(drawDc, context->pxfi, NULL); + draw->pxfi = context->pxfi; + } + + if ((read != NULL) && (read != draw)) + { + /* + If there is a separate read drawable, create a separate read DC, and + use the wglMakeContextCurrent extension to make the context current + drawing to one DC and reading from the other + + Should only occur when WGL_ARB_make_current_read extension is present + */ + HDC readDc = read->callbacks->getdc(read); + + BOOL ret = wglMakeContextCurrentARB(drawDc, readDc, context->ctx); + + read->callbacks->releasedc(read, readDc); + + if (!ret) { + printf("wglMakeContextCurrentARB error: %08x\n", GetLastError()); + return FALSE; + } + } + else + { + /* Otherwise, just use wglMakeCurrent */ + BOOL ret = wglMakeCurrent(drawDc, context->ctx); + if (!ret) { + printf("wglMakeCurrent error: %08x\n", GetLastError()); + return FALSE; + } + } + + draw->callbacks->releasedc(draw, drawDc); + + windows_glapi_set_dispatch(); + + return TRUE; +} + +void windows_unbind_context(windowsContext * context) +{ + wglMakeCurrent(NULL, NULL); +} + +/* + * + */ + +void +windows_swap_buffers(windowsDrawable *draw) +{ + HDC drawDc = GetDC(draw->hWnd); + SwapBuffers(drawDc); + ReleaseDC(draw->hWnd, drawDc); +} + + +typedef void (__stdcall * PFNGLADDSWAPHINTRECTWIN) (GLint x, GLint y, + GLsizei width, + GLsizei height); + +static void +glAddSwapHintRectWIN(GLint x, GLint y, GLsizei width, + GLsizei height) +{ + PFNGLADDSWAPHINTRECTWIN proc = (PFNGLADDSWAPHINTRECTWIN)wglGetProcAddress("glAddSwapHintRectWIN"); + if (proc) + proc(x, y, width, height); +} + +void +windows_copy_subbuffer(windowsDrawable *draw, + int x, int y, int width, int height) +{ + glAddSwapHintRectWIN(x, y, width, height); + windows_swap_buffers(draw); +} + +/* + * Helper function for calling a test function on an initial context + */ +static void +windows_call_with_context(void (*proc)(HDC, void *), void *args) +{ + // create window class +#define WIN_GL_TEST_WINDOW_CLASS "GLTest" + { + static wATOM glTestWndClass = 0; + + if (glTestWndClass == 0) { + WNDCLASSEX wc; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = DefWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(NULL); + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = WIN_GL_TEST_WINDOW_CLASS; + wc.hIconSm = 0; + glTestWndClass = RegisterClassEx(&wc); + } + } + + // create an invisible window for a scratch DC + HWND hwnd = CreateWindowExA(0, + WIN_GL_TEST_WINDOW_CLASS, + "GL Renderer Capabilities Test Window", + 0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), + NULL); + if (hwnd) { + HDC hdc = GetDC(hwnd); + + // we must set a pixel format before we can create a context, just use the first one... + SetPixelFormat(hdc, 1, NULL); + HGLRC hglrc = wglCreateContext(hdc); + wglMakeCurrent(hdc, hglrc); + + // call the test function + proc(hdc, args); + + // clean up + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hglrc); + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); + } +} + +static void +windows_check_render_test(HDC hdc, void *args) +{ + int *result = (int *)args; + + /* Rather than play linkage games using stdcall to ensure we get + glGetString from opengl32.dll here, use dlsym */ + void *dlhandle = windows_get_dl_handle(); + const char *(*proc)(int) = dlsym(dlhandle, "glGetString"); + const char *gl_renderer = (const char *)proc(GL_RENDERER); + + if ((!gl_renderer) || (strcasecmp(gl_renderer, "GDI Generic") == 0)) + *result = FALSE; + else + *result = TRUE; +} + +int +windows_check_renderer(void) +{ + int result; + windows_call_with_context(windows_check_render_test, &result); + return result; +} + +typedef struct { + char *gl_extensions; + char *wgl_extensions; +} windows_extensions_result; + +static void +windows_extensions_test(HDC hdc, void *args) +{ + windows_extensions_result *r = (windows_extensions_result *)args; + + void *dlhandle = windows_get_dl_handle(); + const char *(*proc)(int) = dlsym(dlhandle, "glGetString"); + + r->gl_extensions = strdup(proc(GL_EXTENSIONS)); + + wglResolveExtensionProcs(); + r->wgl_extensions = strdup(wglGetExtensionsStringARB(hdc)); +} + +void +windows_extensions(char **gl_extensions, char **wgl_extensions) +{ + windows_extensions_result result; + + *gl_extensions = ""; + *wgl_extensions = ""; + + windows_call_with_context(windows_extensions_test, &result); + + *gl_extensions = result.gl_extensions; + *wgl_extensions = result.wgl_extensions; +} + +void windows_setTexBuffer(windowsContext *context, int textureTarget, + int textureFormat, windowsDrawable *drawable) +{ + // not yet implemented +} + +void windows_releaseTexBuffer(windowsContext *context, int textureTarget, + windowsDrawable *drawable) +{ + // not yet implemented +} diff --git a/src/glx/windows/windowsgl.h b/src/glx/windows/windowsgl.h new file mode 100644 index 00000000000..bb30f1a391f --- /dev/null +++ b/src/glx/windows/windowsgl.h @@ -0,0 +1,52 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef windowsgl_h +#define windowsgh_h + +struct _windowsContext; +struct _windowsDrawable; + +typedef struct _windowsContext windowsContext; +typedef struct _windowsDrawable windowsDrawable; + +windowsContext *windows_create_context(int pxfi, windowsContext *shared); +windowsContext *windows_create_context_attribs(int pxfi, windowsContext *shared, const int *attribList); +void windows_destroy_context(windowsContext *contex); +int windows_bind_context(windowsContext *context, windowsDrawable *, windowsDrawable *); +void windows_unbind_context(windowsContext *context); + +windowsDrawable *windows_create_drawable(int type, void *handle); +void windows_destroy_drawable(windowsDrawable *); +void windows_swap_buffers(windowsDrawable *); +void windows_copy_subbuffer(windowsDrawable *windowsDrawable, int x, int y, int width, int height); + +int windows_check_renderer(void); +void windows_extensions(char **gl_extensions, char **wgl_extensions); + +void windows_setTexBuffer(windowsContext *context, int textureTarget, + int textureFormat, windowsDrawable *drawable); +void windows_releaseTexBuffer(windowsContext *context, int textureTarget, + windowsDrawable *drawable); + +#endif /* windowsgl_h */ diff --git a/src/glx/windows/windowsgl_internal.h b/src/glx/windows/windowsgl_internal.h new file mode 100644 index 00000000000..89ed53efe9b --- /dev/null +++ b/src/glx/windows/windowsgl_internal.h @@ -0,0 +1,67 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef windowsgl_internal_h +#define windowsgl_internal_h + +#include "windowsgl.h" + +#include <X11/Xmd.h> // for BOOL +#include <X11/Xwindows.h> // as this doesn't provide one +#include <GL/gl.h> +#include <GL/wglext.h> + +struct _windowsContext +{ + struct glx_config *config; + windowsContext *shareContext; + HGLRC ctx; + int pxfi; +}; + +struct windowsdrawable_callbacks +{ + int type; // WINDOW, PIXMAP, PBUFFER + HDC (*getdc) (windowsDrawable *d); + void (*releasedc) (windowsDrawable *d, HDC dc); +}; + +struct _windowsDrawable +{ + int pxfi; // 0 if not yet set + struct windowsdrawable_callbacks *callbacks; + + // for type WINDOW + HWND hWnd; + + // for type PIXMAP + HANDLE hSection; + HDC dibDC; + HBITMAP hDIB; + HBITMAP hOldDIB; + + // for type PBUFFER + HPBUFFERARB hPbuffer; +}; + +#endif /* windowsgl_internal_h */ diff --git a/src/glx/windows/xwindowsdri.c b/src/glx/windows/xwindowsdri.c new file mode 100644 index 00000000000..90884fa6a17 --- /dev/null +++ b/src/glx/windows/xwindowsdri.c @@ -0,0 +1,237 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#include <X11/Xlibint.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include "windowsdristr.h" +#include "xwindowsdri.h" +#include <stdio.h> + +static XExtensionInfo _windowsdri_info_data; +static XExtensionInfo *windowsdri_info = &_windowsdri_info_data; +static char *windowsdri_extension_name = WINDOWSDRINAME; + +#define WindowsDRICheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, windowsdri_extension_name, val) + +/***************************************************************************** + * * + * private utility routines * + * * + *****************************************************************************/ + +static int close_display(Display * dpy, XExtCodes * extCodes); + +static /* const */ XExtensionHooks windowsdri_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static +XEXT_GENERATE_FIND_DISPLAY(find_display, windowsdri_info, + windowsdri_extension_name, + &windowsdri_extension_hooks, + WindowsDRINumberEvents, NULL) + +static +XEXT_GENERATE_CLOSE_DISPLAY(close_display, windowsdri_info) + +/***************************************************************************** + * * + * public Windows-DRI Extension routines * + * * + *****************************************************************************/ + +#if 0 +#include <stdio.h> +#define TRACE(msg, ...) fprintf(stderr, "WindowsDRI" msg "\n", ##__VA_ARGS__); +#else +#define TRACE(msg, ...) +#endif + +Bool +XWindowsDRIQueryExtension(dpy, event_basep, error_basep) + Display *dpy; + int *event_basep, *error_basep; +{ + XExtDisplayInfo *info = find_display(dpy); + + TRACE("QueryExtension:"); + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + TRACE("QueryExtension: return True"); + return True; + } + else { + TRACE("QueryExtension: return False"); + return False; + } +} + +Bool +XWindowsDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion) + Display *dpy; + int *majorVersion; + int *minorVersion; + int *patchVersion; +{ + XExtDisplayInfo *info = find_display(dpy); + xWindowsDRIQueryVersionReply rep; + xWindowsDRIQueryVersionReq *req; + + TRACE("QueryVersion:"); + WindowsDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(WindowsDRIQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_WindowsDRIQueryVersion; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryVersion: return False"); + return False; + } + *majorVersion = rep.majorVersion; + *minorVersion = rep.minorVersion; + *patchVersion = rep.patchVersion; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryVersion: %d.%d.%d", *majorVersion, *minorVersion, *patchVersion); + return True; +} + +Bool +XWindowsDRIQueryDirectRenderingCapable(dpy, screen, isCapable) + Display *dpy; + int screen; + Bool *isCapable; +{ + XExtDisplayInfo *info = find_display(dpy); + xWindowsDRIQueryDirectRenderingCapableReply rep; + xWindowsDRIQueryDirectRenderingCapableReq *req; + + TRACE("QueryDirectRenderingCapable:"); + WindowsDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(WindowsDRIQueryDirectRenderingCapable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_WindowsDRIQueryDirectRenderingCapable; + req->screen = screen; + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryDirectRenderingCapable: return False"); + return False; + } + *isCapable = rep.isCapable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryDirectRenderingCapable:return True"); + return True; +} + +Bool +XWindowsDRIQueryDrawable(Display *dpy, int screen, Drawable drawable, + unsigned int * type, void ** handle) +{ + XExtDisplayInfo *info = find_display(dpy); + xWindowsDRIQueryDrawableReply rep; + xWindowsDRIQueryDrawableReq *req; + + TRACE("QueryDrawable: XID %lx", drawable); + WindowsDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(WindowsDRIQueryDrawable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_WindowsDRIQueryDrawable; + req->screen = screen; + req->drawable = drawable; + + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryDrawable: return False"); + return False; + } + + *type = rep.drawable_type; + + // Note that despite being a derived type of void *, HANDLEs are defined to + // be a sign-extended 32 bit value (so they can be passed to 32-bit + // processes safely) + *handle = (void *)(intptr_t)rep.handle; + + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryDrawable: type %d, handle %p", *type, *handle); + return True; +} + +Bool +XWindowsDRIFBConfigToPixelFormat(Display *dpy, int screen, int fbConfigID, + int *pxfi) +{ + XExtDisplayInfo *info = find_display(dpy); + xWindowsDRIFBConfigToPixelFormatReply rep; + xWindowsDRIFBConfigToPixelFormatReq *req; + + TRACE("FBConfigToPixelFormat: fbConfigID 0x%x", fbConfigID); + WindowsDRICheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(WindowsDRIFBConfigToPixelFormat, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_WindowsDRIFBConfigToPixelFormat; + req->screen = screen; + req->fbConfigID = fbConfigID; + + if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("FBConfigToPixelFormat: return False"); + return False; + } + + *pxfi = rep.pixelFormatIndex; + + UnlockDisplay(dpy); + SyncHandle(); + TRACE("FBConfigToPixelFormat: pixelformatindex %d", *pxfi); + return True; +} diff --git a/src/glx/windows/xwindowsdri.h b/src/glx/windows/xwindowsdri.h new file mode 100644 index 00000000000..499af26de7a --- /dev/null +++ b/src/glx/windows/xwindowsdri.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2014 Jon Turney + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef XWINDOWSDRI_H +#define XWINDOWSDRI_H + +#include <X11/Xfuncproto.h> +#include <X11/Xlib.h> + +typedef struct +{ + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came frome a SendEvent request */ + Display *display; /* Display the event was read from */ + Window window; /* window of event */ + Time time; /* server timestamp when event happened */ + int kind; /* subtype of event */ + int arg; +} XWindowsDRINotifyEvent; + +_XFUNCPROTOBEGIN +Bool XWindowsDRIQueryExtension(Display * dpy, int *event_base, + int *error_base); + +Bool XWindowsDRIQueryVersion(Display * dpy, int *majorVersion, + int *minorVersion, int *patchVersion); + +Bool XWindowsDRIQueryDirectRenderingCapable(Display * dpy, int screen, + Bool *isCapable); + +Bool XWindowsDRIQueryDrawable(Display * dpy, int screen, Drawable drawable, + unsigned int *type, void ** handle); + +Bool XWindowsDRIFBConfigToPixelFormat(Display *dpy, int screen, int fbConfigID, + int *pxfi); +_XFUNCPROTOEND + +#endif /* XWINDOWSDRI_H */ diff --git a/src/mapi/Makefile.am b/src/mapi/Makefile.am index 3b0a9de5e77..d6bf5d81a3a 100644 --- a/src/mapi/Makefile.am +++ b/src/mapi/Makefile.am @@ -116,6 +116,9 @@ glapi_libglapi_la_CPPFLAGS = \ if HAVE_APPLEDRI glapi_libglapi_la_SOURCES += glapi/glapi_gentable.c endif +if HAVE_WINDOWSDRI +glapi_libglapi_la_SOURCES += glapi/glapi_gentable.c +endif if HAVE_SHARED_GLAPI glapi_libglapi_la_SOURCES += $(MAPI_BRIDGE_FILES) glapi/glapi_mapi_tmp.h diff --git a/src/mapi/glapi/gen/Makefile.am b/src/mapi/glapi/gen/Makefile.am index 0d7c3385d2e..ba5d1442cda 100644 --- a/src/mapi/glapi/gen/Makefile.am +++ b/src/mapi/glapi/gen/Makefile.am @@ -32,6 +32,9 @@ MESA_GLAPI_OUTPUTS = \ if HAVE_APPLEDRI MESA_GLAPI_OUTPUTS += $(MESA_GLAPI_DIR)/glapi_gentable.c endif +if HAVE_WINDOWSDRI +MESA_GLAPI_OUTPUTS += $(MESA_GLAPI_DIR)/glapi_gentable.c +endif MESA_GLAPI_ASM_OUTPUTS = if HAVE_X86_ASM diff --git a/src/mapi/glapi/glapi.h b/src/mapi/glapi/glapi.h index 3593c88bbc1..f1ad4c1b5e8 100644 --- a/src/mapi/glapi/glapi.h +++ b/src/mapi/glapi/glapi.h @@ -158,7 +158,7 @@ _GLAPI_EXPORT const char * _glapi_get_proc_name(unsigned int offset); -#ifdef GLX_USE_APPLEGL +#if defined(GLX_USE_APPLEGL) || defined(GLX_USE_WINDOWSGL) _GLAPI_EXPORT struct _glapi_table * _glapi_create_table_from_handle(void *handle, const char *symbol_prefix); #endif |