summaryrefslogtreecommitdiffstats
path: root/src/glx
diff options
context:
space:
mode:
Diffstat (limited to 'src/glx')
-rw-r--r--src/glx/Makefile.am14
-rw-r--r--src/glx/driwindows_glx.c609
-rw-r--r--src/glx/glxclient.h11
-rw-r--r--src/glx/glxext.c19
-rw-r--r--src/glx/windows/Makefile.am31
-rw-r--r--src/glx/windows/wgl.c108
-rw-r--r--src/glx/windows/wgl.h44
-rw-r--r--src/glx/windows/windows_drawable.c192
-rw-r--r--src/glx/windows/windowsdriconst.h45
-rw-r--r--src/glx/windows/windowsdriproto.pc.in9
-rw-r--r--src/glx/windows/windowsdristr.h152
-rw-r--r--src/glx/windows/windowsgl.c403
-rw-r--r--src/glx/windows/windowsgl.h52
-rw-r--r--src/glx/windows/windowsgl_internal.h67
-rw-r--r--src/glx/windows/xwindowsdri.c237
-rw-r--r--src/glx/windows/xwindowsdri.h59
16 files changed, 2050 insertions, 2 deletions
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 */