diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xwin/InitOutput.c | 4 | ||||
-rw-r--r-- | hw/xwin/Makefile.am | 14 | ||||
-rw-r--r-- | hw/xwin/dri/Makefile.am | 8 | ||||
-rw-r--r-- | hw/xwin/dri/windowsdri.c | 274 | ||||
-rw-r--r-- | hw/xwin/dri/windowsdri.h | 30 | ||||
-rw-r--r-- | hw/xwin/glx/Makefile.am | 7 | ||||
-rw-r--r-- | hw/xwin/glx/dri_helpers.c | 118 | ||||
-rw-r--r-- | hw/xwin/glx/dri_helpers.h | 38 | ||||
-rw-r--r-- | hw/xwin/glx/indirect.c | 429 | ||||
-rw-r--r-- | hw/xwin/glx/indirect.h | 94 | ||||
-rw-r--r-- | hw/xwin/glx/winpriv.c | 7 | ||||
-rw-r--r-- | hw/xwin/glx/winpriv.h | 1 | ||||
-rw-r--r-- | hw/xwin/win.h | 1 |
13 files changed, 805 insertions, 220 deletions
diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c index 6a75723c5..6ca2b3fa3 100644 --- a/hw/xwin/InitOutput.c +++ b/hw/xwin/InitOutput.c @@ -63,6 +63,7 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner, #include "dixmain.h" #ifdef XWIN_GLX_WINDOWS #include "glx/glwindows.h" +#include "dri/windowsdri.h" #endif /* @@ -120,6 +121,9 @@ const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]); static const ExtensionModule xwinExtensions[] = { #ifdef GLXEXT { GlxExtensionInit, "GLX", &noGlxExtension }, +#ifdef XWIN_WINDOWS_DRI + { WindowsDRIExtensionInit, "Windows-DRI", &noDriExtension }, +#endif #endif }; diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am index 7c1375714..aa58c79f8 100644 --- a/hw/xwin/Makefile.am +++ b/hw/xwin/Makefile.am @@ -9,9 +9,17 @@ CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la endif if XWIN_GLX_WINDOWS -GLX_DIR = glx -DEFS_GLX_WINDOWS = -DXWIN_GLX_WINDOWS -XWIN_GLX_LIBS = $(top_builddir)/hw/xwin/glx/libXwinGLX.la +GLX_DIR = +DEFS_GLX_WINDOWS = +XWIN_GLX_LIBS = +if XWIN_WINDOWS_DRI +GLX_DIR += dri +DEFS_GLX_WINDOWS += -DXWIN_WINDOWS_DRI +XWIN_GLX_LIBS += $(top_builddir)/hw/xwin/dri/libWindowsDRI.la +endif +GLX_DIR += glx +DEFS_GLX_WINDOWS += -DXWIN_GLX_WINDOWS +XWIN_GLX_LIBS += $(top_builddir)/hw/xwin/glx/libXwinGLX.la XWIN_GLX_SYS_LIBS = -lopengl32 endif diff --git a/hw/xwin/dri/Makefile.am b/hw/xwin/dri/Makefile.am new file mode 100644 index 000000000..bdcd48aae --- /dev/null +++ b/hw/xwin/dri/Makefile.am @@ -0,0 +1,8 @@ +noinst_LTLIBRARIES = libWindowsDRI.la + +libWindowsDRI_la_SOURCES = \ + windowsdri.c \ + windowsdri.h + +AM_CFLAGS = $(DIX_CFLAGS) \ + -I$(top_srcdir)/hw/xwin/ diff --git a/hw/xwin/dri/windowsdri.c b/hw/xwin/dri/windowsdri.c new file mode 100644 index 000000000..ab18a4691 --- /dev/null +++ b/hw/xwin/dri/windowsdri.c @@ -0,0 +1,274 @@ +/* + * 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/extensions/windowsdristr.h> + +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "swaprep.h" +#include "protocol-versions.h" +#include "windowsdri.h" +#include "glx/dri_helpers.h" + +static int WindowsDRIErrorBase = 0; +static unsigned char WindowsDRIReqCode = 0; +static int WindowsDRIEventBase = 0; + +static void +WindowsDRIResetProc(ExtensionEntry* extEntry) +{ +} + +static int +ProcWindowsDRIQueryVersion(ClientPtr client) +{ + xWindowsDRIQueryVersionReply rep; + + REQUEST_SIZE_MATCH(xWindowsDRIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_WINDOWSDRI_MAJOR_VERSION; + rep.minorVersion = SERVER_WINDOWSDRI_MINOR_VERSION; + rep.patchVersion = SERVER_WINDOWSDRI_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swaps(&rep.majorVersion); + swaps(&rep.minorVersion); + swapl(&rep.patchVersion); + } + WriteToClient(client, sizeof(xWindowsDRIQueryVersionReply), &rep); + return Success; +} + +static int +ProcWindowsDRIQueryDirectRenderingCapable(ClientPtr client) +{ + xWindowsDRIQueryDirectRenderingCapableReply rep; + + REQUEST(xWindowsDRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xWindowsDRIQueryDirectRenderingCapableReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!client->local) + rep.isCapable = 0; + else + rep.isCapable = glxWinGetScreenAiglxIsActive(screenInfo.screens[stuff->screen]); + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + + WriteToClient(client, + sizeof(xWindowsDRIQueryDirectRenderingCapableReply), + &rep); + return Success; +} + +static int +ProcWindowsDRIQueryDrawable(ClientPtr client) +{ + xWindowsDRIQueryDrawableReply rep; + int rc; + + REQUEST(xWindowsDRIQueryDrawableReq); + REQUEST_SIZE_MATCH(xWindowsDRIQueryDrawableReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = glxWinQueryDrawable(client, stuff->drawable, &(rep.drawable_type), &(rep.handle)); + + if (rc) + return rc; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.handle); + swapl(&rep.drawable_type); + } + + WriteToClient(client, sizeof(xWindowsDRIQueryDrawableReply), &rep); + return Success; +} + +static int +ProcWindowsDRIFBConfigToPixelFormat(ClientPtr client) +{ + xWindowsDRIFBConfigToPixelFormatReply rep; + + REQUEST(xWindowsDRIFBConfigToPixelFormatReq); + REQUEST_SIZE_MATCH(xWindowsDRIFBConfigToPixelFormatReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.pixelFormatIndex = glxWinFBConfigIDToPixelFormatIndex(stuff->screen, stuff->fbConfigID); + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.pixelFormatIndex); + } + + WriteToClient(client, sizeof(xWindowsDRIFBConfigToPixelFormatReply), &rep); + return Success; +} + +/* dispatch */ + +static int +ProcWindowsDRIDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_WindowsDRIQueryVersion: + return ProcWindowsDRIQueryVersion(client); + + case X_WindowsDRIQueryDirectRenderingCapable: + return ProcWindowsDRIQueryDirectRenderingCapable(client); + } + + if (!client->local) + return WindowsDRIErrorBase + WindowsDRIClientNotLocal; + + switch (stuff->data) { + case X_WindowsDRIQueryDrawable: + return ProcWindowsDRIQueryDrawable(client); + + case X_WindowsDRIFBConfigToPixelFormat: + return ProcWindowsDRIFBConfigToPixelFormat(client); + + default: + return BadRequest; + } +} + +static void +SNotifyEvent(xWindowsDRINotifyEvent *from, + xWindowsDRINotifyEvent *to) +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->time, to->time); +} + +static int +SProcWindowsDRIQueryVersion(ClientPtr client) +{ + REQUEST(xWindowsDRIQueryVersionReq); + swaps(&stuff->length); + return ProcWindowsDRIQueryVersion(client); +} + +static int +SProcWindowsDRIQueryDirectRenderingCapable(ClientPtr client) +{ + REQUEST(xWindowsDRIQueryDirectRenderingCapableReq); + swaps(&stuff->length); + swapl(&stuff->screen); + return ProcWindowsDRIQueryDirectRenderingCapable(client); +} + +static int +SProcWindowsDRIQueryDrawable(ClientPtr client) +{ + REQUEST(xWindowsDRIQueryDrawableReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->drawable); + return ProcWindowsDRIQueryDrawable(client); +} + +static int +SProcWindowsDRIFBConfigToPixelFormat(ClientPtr client) +{ + REQUEST(xWindowsDRIFBConfigToPixelFormatReq); + swaps(&stuff->length); + swapl(&stuff->screen); + swapl(&stuff->fbConfigID); + return ProcWindowsDRIFBConfigToPixelFormat(client); +} + +static int +SProcWindowsDRIDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_WindowsDRIQueryVersion: + return SProcWindowsDRIQueryVersion(client); + + case X_WindowsDRIQueryDirectRenderingCapable: + return SProcWindowsDRIQueryDirectRenderingCapable(client); + } + + if (!client->local) + return WindowsDRIErrorBase + WindowsDRIClientNotLocal; + + switch (stuff->data) { + case X_WindowsDRIQueryDrawable: + return SProcWindowsDRIQueryDrawable(client); + + case X_WindowsDRIFBConfigToPixelFormat: + return SProcWindowsDRIFBConfigToPixelFormat(client); + + default: + return BadRequest; + } +} + +void +WindowsDRIExtensionInit(void) +{ + ExtensionEntry* extEntry; + + if ((extEntry = AddExtension(WINDOWSDRINAME, + WindowsDRINumberEvents, + WindowsDRINumberErrors, + ProcWindowsDRIDispatch, + SProcWindowsDRIDispatch, + WindowsDRIResetProc, + StandardMinorOpcode))) { + size_t i; + WindowsDRIReqCode = (unsigned char)extEntry->base; + WindowsDRIErrorBase = extEntry->errorBase; + WindowsDRIEventBase = extEntry->eventBase; + for (i = 0; i < WindowsDRINumberEvents; i++) + EventSwapVector[WindowsDRIEventBase + i] = (EventSwapPtr)SNotifyEvent; + } +} diff --git a/hw/xwin/dri/windowsdri.h b/hw/xwin/dri/windowsdri.h new file mode 100644 index 000000000..a48c72b04 --- /dev/null +++ b/hw/xwin/dri/windowsdri.h @@ -0,0 +1,30 @@ +/* + * 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 windowsdri_h +#define windowsdri_h + +void WindowsDRIExtensionInit(void); +Bool noDriExtension; + +#endif /* windowsdri_h */ diff --git a/hw/xwin/glx/Makefile.am b/hw/xwin/glx/Makefile.am index f2dffbffb..599ec37cc 100644 --- a/hw/xwin/glx/Makefile.am +++ b/hw/xwin/glx/Makefile.am @@ -7,9 +7,16 @@ libXwinGLX_la_SOURCES = \ glwindows.h \ glshim.c \ indirect.c \ + indirect.h \ wgl_ext_api.c \ wgl_ext_api.h +if XWIN_WINDOWS_DRI +libXwinGLX_la_SOURCES += \ + dri_helpers.c \ + dri_helpers.h +endif + libnativeGLthunk_la_SOURCES = \ glthunk.c diff --git a/hw/xwin/glx/dri_helpers.c b/hw/xwin/glx/dri_helpers.c new file mode 100644 index 000000000..d69802ffd --- /dev/null +++ b/hw/xwin/glx/dri_helpers.c @@ -0,0 +1,118 @@ +/* + * 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. + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include <glx/glxserver.h> +#include <glx/glxutil.h> +#include <X11/extensions/windowsdriconst.h> + +#include "indirect.h" +#include "winpriv.h" +#include "dri_helpers.h" +#include "win.h" + +extern int validGlxDrawable(ClientPtr client, XID id, int type, int access_mode, + __GLXdrawable ** drawable, int *err); + +int +glxWinQueryDrawable(ClientPtr client, XID drawId, unsigned int *type, unsigned int *handle) +{ + __GLXWinDrawable *pDrawable; + int err; + + if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY, + DixReadAccess, (__GLXdrawable **)&pDrawable, &err)) { + + switch (pDrawable->base.type) + { + case GLX_DRAWABLE_WINDOW: + { + HWND h = winGetWindowInfo((WindowPtr)(pDrawable->base.pDraw)); + *handle = (uintptr_t)h; + *type = WindowsDRIDrawableWindow; + } + break; + + case GLX_DRAWABLE_PIXMAP: + glxWinDeferredCreateDrawable(pDrawable, pDrawable->base.config); + *handle = pDrawable->base.pDraw->id; + // XXX: We could use DuplicateHandle to make pDrawble->hSection + // available to the requesting process... ? + *type = WindowsDRIDrawablePixmap; + break; + + case GLX_DRAWABLE_PBUFFER: + glxWinDeferredCreateDrawable(pDrawable, pDrawable->base.config); + *handle = (uintptr_t)(pDrawable->hPbuffer); + *type = WindowsDRIDrawablePbuffer; + break; + + default: + assert(FALSE); + *handle = 0; + } + } + else { + HWND h; + /* The drawId XID doesn't identify a GLX drawable. The only other valid + alternative is that it is the XID of a window drawable that is being + used by the pre-GLX 1.3 interface */ + DrawablePtr pDraw; + int rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess); + if (rc != Success || pDraw->type != DRAWABLE_WINDOW) { + return err; + } + + h = winGetWindowInfo((WindowPtr)(pDraw)); + *handle = (uintptr_t)h; + *type = WindowsDRIDrawableWindow; + } + + winDebug("glxWinQueryDrawable: type %d, handle %p\n", *type, *handle); + return Success; +} + +int +glxWinFBConfigIDToPixelFormatIndex(int scr, int fbConfigID) +{ + __GLXscreen *screen = glxGetScreen(screenInfo.screens[scr]); + + for (__GLXconfig *c = screen->fbconfigs; + c != NULL; + c = c->next) { + if (c->fbconfigID == fbConfigID) + return ((GLXWinConfig *)c)->pixelFormatIndex; + } + + return 0; +} + +Bool +glxWinGetScreenAiglxIsActive(ScreenPtr pScreen) +{ + winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen); + return pWinScreen->fNativeGlActive; +} diff --git a/hw/xwin/glx/dri_helpers.h b/hw/xwin/glx/dri_helpers.h new file mode 100644 index 000000000..05bc9bc93 --- /dev/null +++ b/hw/xwin/glx/dri_helpers.h @@ -0,0 +1,38 @@ +/* + * 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 dri_helpers_h +#define dri_helpers_h + +#include "dixstruct.h" + +int +glxWinQueryDrawable(ClientPtr client, XID drawId, unsigned int *type, unsigned int *handle); + +int +glxWinFBConfigIDToPixelFormatIndex(int scr, int fbConfigID); + +Bool +glxWinGetScreenAiglxIsActive(ScreenPtr pScreen); + +#endif /* dri_helpers_h */ diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c index 454173666..6db6a48c4 100644 --- a/hw/xwin/glx/indirect.c +++ b/hw/xwin/glx/indirect.c @@ -81,12 +81,12 @@ #include "glwindows.h" #include <glx/glxserver.h> #include <glx/glxutil.h> -#include <glx/extension_string.h> #include <GL/glxtokens.h> #include <winpriv.h> #include <wgl_ext_api.h> #include <winglobals.h> +#include <indirect.h> #define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1])) @@ -101,60 +101,6 @@ #define PFD_SUPPORT_COMPOSITION 0x00008000 #endif -/* ---------------------------------------------------------------------- */ -/* - * structure definitions - */ - -typedef struct __GLXWinContext __GLXWinContext; -typedef struct __GLXWinDrawable __GLXWinDrawable; -typedef struct __GLXWinScreen glxWinScreen; -typedef struct __GLXWinConfig GLXWinConfig; - -struct __GLXWinContext { - __GLXcontext base; - HGLRC ctx; /* Windows GL Context */ - __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */ - HWND hwnd; /* For detecting when HWND has changed */ -}; - -struct __GLXWinDrawable { - __GLXdrawable base; - __GLXWinContext *drawContext; - __GLXWinContext *readContext; - - /* If this drawable is GLX_DRAWABLE_PBUFFER */ - HPBUFFERARB hPbuffer; - - /* If this drawable is GLX_DRAWABLE_PIXMAP */ - HDC dibDC; - HBITMAP hDIB; - HBITMAP hOldDIB; /* original DIB for DC */ - void *pOldBits; /* original pBits for this drawable's pixmap */ -}; - -struct __GLXWinScreen { - __GLXscreen base; - - /* Supported GLX extensions */ - unsigned char glx_enable_bits[__GLX_EXT_BYTES]; - - Bool has_WGL_ARB_multisample; - Bool has_WGL_ARB_pixel_format; - Bool has_WGL_ARB_pbuffer; - Bool has_WGL_ARB_render_texture; - - /* wrapped screen functions */ - RealizeWindowProcPtr RealizeWindow; - UnrealizeWindowProcPtr UnrealizeWindow; - CopyWindowProcPtr CopyWindow; -}; - -struct __GLXWinConfig { - __GLXconfig base; - int pixelFormatIndex; -}; - typedef struct { int notOpenGL; int rgbaFloat; @@ -430,7 +376,8 @@ static Bool glxWinRealizeWindow(WindowPtr pWin); static Bool glxWinUnrealizeWindow(WindowPtr pWin); static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc); - +static Bool glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride, + __GLXscreen *screen, __GLXconfig *config); static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, HDC * hdc, HWND * hwnd); static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw); @@ -803,6 +750,9 @@ glxWinScreenProbe(ScreenPtr pScreen) screen->CopyWindow = pScreen->CopyWindow; pScreen->CopyWindow = glxWinCopyWindow; + // Note that WGL is active on this screen + winSetScreenAiglxIsActive(pScreen); + return &screen->base; error: @@ -949,6 +899,10 @@ glxWinDrawableDestroy(__GLXdrawable * base) } if (glxPriv->hDIB) { + if (!CloseHandle(glxPriv->hSection)) { + ErrorF("CloseHandle failed: %s\n", glxWinErrorMessage()); + } + if (!DeleteObject(glxPriv->hDIB)) { ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage()); } @@ -992,6 +946,179 @@ glxWinCreateDrawable(ClientPtr client, return &glxPriv->base; } +void +glxWinDeferredCreateDrawable(__GLXWinDrawable *draw, __GLXconfig *config) +{ + switch (draw->base.type) { + case GLX_DRAWABLE_WINDOW: + { + WindowPtr pWin = (WindowPtr) draw->base.pDraw; + + if (!(config->drawableType & GLX_WINDOW_BIT)) { + ErrorF + ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_WINDOW drawable with a fbConfig which doesn't have drawableType GLX_WINDOW_BIT\n"); + } + + if (pWin == NULL) { + GLWIN_DEBUG_MSG("Deferring until X window is created"); + return; + } + + GLWIN_DEBUG_MSG("glxWinDeferredCreateDrawable: pWin %p", pWin); + + if (winGetWindowInfo(pWin) == NULL) { + GLWIN_DEBUG_MSG("Deferring until native window is created"); + return; + } + } + break; + + case GLX_DRAWABLE_PBUFFER: + { + if (draw->hPbuffer == NULL) { + __GLXscreen *screen; + glxWinScreen *winScreen; + int pixelFormat; + + // XXX: which DC are we supposed to use??? + HDC screenDC = GetDC(NULL); + + if (!(config->drawableType & GLX_PBUFFER_BIT)) { + ErrorF + ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PBUFFER drawable with a fbConfig which doesn't have drawableType GLX_PBUFFER_BIT\n"); + } + + screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]); + winScreen = (glxWinScreen *) screen; + + pixelFormat = + fbConfigToPixelFormatIndex(screenDC, config, + GLX_PBUFFER_BIT, winScreen); + if (pixelFormat == 0) { + return; + } + + draw->hPbuffer = + wglCreatePbufferARBWrapper(screenDC, pixelFormat, + draw->base.pDraw->width, + draw->base.pDraw->height, NULL); + ReleaseDC(NULL, screenDC); + + if (draw->hPbuffer == NULL) { + ErrorF("wglCreatePbufferARBWrapper error: %s\n", + glxWinErrorMessage()); + return; + } + + GLWIN_DEBUG_MSG + ("glxWinDeferredCreateDrawable: pBuffer %p created for drawable %p", + draw->hPbuffer, draw); + } + } + break; + + case GLX_DRAWABLE_PIXMAP: + { + if (draw->dibDC == NULL) { + BITMAPINFOHEADER bmpHeader; + void *pBits; + __GLXscreen *screen; + DWORD size; + char name[MAX_PATH]; + + memset(&bmpHeader, 0, sizeof(BITMAPINFOHEADER)); + bmpHeader.biSize = sizeof(BITMAPINFOHEADER); + bmpHeader.biWidth = draw->base.pDraw->width; + bmpHeader.biHeight = draw->base.pDraw->height; + bmpHeader.biPlanes = 1; + bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel; + bmpHeader.biCompression = BI_RGB; + + if (!(config->drawableType & GLX_PIXMAP_BIT)) { + ErrorF + ("glxWinDeferredCreateDrawable: tried to create a GLX_DRAWABLE_PIXMAP drawable with a fbConfig which doesn't have drawableType GLX_PIXMAP_BIT\n"); + } + + draw->dibDC = CreateCompatibleDC(NULL); + if (draw->dibDC == NULL) { + ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage()); + return; + } + +#define RASTERWIDTHBYTES(bmi) (((((bmi)->biWidth*(bmi)->biBitCount)+31)&~31)>>3) + size = bmpHeader.biHeight * RASTERWIDTHBYTES(&bmpHeader); + ErrorF("shared memory region size %d + %d\n", sizeof(BITMAPINFOHEADER), size); + + // Create unique name for mapping based on XID + // + // XXX: not quite unique as potentially this name could be used in + // another server instance. Not sure how to deal with that. + snprintf(name, sizeof(name), "Local\\CYGWINX_WINDOWSDRI_%08x", draw->base.pDraw->id); + ErrorF("shared memory region name %s\n", name); + + // Create a file mapping backed by the pagefile + draw->hSection = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE, 0, sizeof(BITMAPINFOHEADER) + size, name); + if (draw->hSection == NULL) { + ErrorF("CreateFileMapping error: %s\n", glxWinErrorMessage()); + return; + } + + draw->hDIB = + CreateDIBSection(draw->dibDC, (BITMAPINFO *) &bmpHeader, + DIB_RGB_COLORS, &pBits, draw->hSection, sizeof(BITMAPINFOHEADER)); + if (draw->dibDC == NULL) { + ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage()); + return; + } + + // Store a copy of the BITMAPINFOHEADER at the start of the shared + // memory for the information of the receiving process + { + LPVOID pData = MapViewOfFile(draw->hSection, FILE_MAP_WRITE, 0, 0, 0); + memcpy(pData, (void *)&bmpHeader, sizeof(BITMAPINFOHEADER)); + UnmapViewOfFile(pData); + } + + // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to + // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits + // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are + // even compatible ... + draw->pOldBits = ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr; + ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr = pBits; + + // Select the DIB into the DC + draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB); + if (!draw->hOldDIB) { + ErrorF("SelectObject error: %s\n", glxWinErrorMessage()); + } + + screen = glxGetScreen(screenInfo.screens[draw->base.pDraw->pScreen->myNum]); + + // Set the pixel format of the bitmap + glxWinSetPixelFormat(draw->dibDC, + draw->base.pDraw->bitsPerPixel, + GLX_PIXMAP_BIT, + screen, + config); + + GLWIN_DEBUG_MSG + ("glxWinDeferredCreateDrawable: DIB bitmap %p created for drawable %p", + draw->hDIB, draw); + } + } + break; + + default: + { + ErrorF + ("glxWinDeferredCreateDrawable: tried to attach unhandled drawable type %d\n", + draw->base.type); + return; + } + } +} + /* ---------------------------------------------------------------------- */ /* * Texture functions @@ -1035,13 +1162,10 @@ glxWinReleaseTexImage(__GLXcontext * baseContext, */ static Bool -glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride, - int drawableTypeOverride) +glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride, + __GLXscreen *screen, __GLXconfig *config) { - __GLXscreen *screen = gc->base.pGlxScreen; glxWinScreen *winScreen = (glxWinScreen *) screen; - - __GLXconfig *config = gc->base.config; GLXWinConfig *winConfig = (GLXWinConfig *) config; GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d", @@ -1087,12 +1211,35 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride, (config->redBits + config->greenBits + config->blueBits), bppOverride, config->drawableType, drawableTypeOverride); - if (!winScreen->has_WGL_ARB_pixel_format) { + if (winScreen->has_WGL_ARB_pixel_format) { + int pixelFormat = + fbConfigToPixelFormatIndex(hdc, config, + drawableTypeOverride, winScreen); + if (pixelFormat != 0) { + GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d", + pixelFormat); + ErrorF + ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", + pixelFormat, winConfig->pixelFormatIndex); + + if (!SetPixelFormat(hdc, pixelFormat, NULL)) { + ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); + return FALSE; + } + } + } + + /* + For some drivers, wglChoosePixelFormatARB() can fail when the provided + DC doesn't belong to the driver (e.g. it's a compatible DC for a bitmap, + so allow fallback to ChoosePixelFormat() + */ + { PIXELFORMATDESCRIPTOR pfd; int pixelFormat; /* convert fbConfig to PFD */ - if (fbConfigToPixelFormat(gc->base.config, &pfd, drawableTypeOverride)) { + if (fbConfigToPixelFormat(config, &pfd, drawableTypeOverride)) { ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n"); return FALSE; } @@ -1123,25 +1270,6 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride, return FALSE; } } - else { - int pixelFormat = - fbConfigToPixelFormatIndex(hdc, gc->base.config, - drawableTypeOverride, winScreen); - if (pixelFormat == 0) { - return FALSE; - } - - GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d", - pixelFormat); - ErrorF - ("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", - pixelFormat, winConfig->pixelFormatIndex); - - if (!SetPixelFormat(hdc, pixelFormat, NULL)) { - ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); - return FALSE; - } - } return TRUE; } @@ -1193,7 +1321,7 @@ glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, HDC * hdc, gc->hwnd = *hwnd; /* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */ - if (!glxWinSetPixelFormat(gc, *hdc, 0, GLX_WINDOW_BIT)) { + if (!glxWinSetPixelFormat(*hdc, 0, GLX_WINDOW_BIT, gc->base.pGlxScreen, gc->base.config)) { ErrorF("glxWinSetPixelFormat error: %s\n", glxWinErrorMessage()); ReleaseDC(*hwnd, *hdc); @@ -1279,140 +1407,7 @@ glxWinDeferredCreateContext(__GLXWinContext * gc, __GLXWinDrawable * draw) ("glxWinDeferredCreateContext: attach context %p to drawable %p", gc, draw); - switch (draw->base.type) { - case GLX_DRAWABLE_WINDOW: - { - WindowPtr pWin = (WindowPtr) draw->base.pDraw; - - if (!(gc->base.config->drawableType & GLX_WINDOW_BIT)) { - ErrorF - ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable\n"); - } - - if (pWin == NULL) { - GLWIN_DEBUG_MSG("Deferring until X window is created"); - return; - } - - GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pWin %p", pWin); - - if (winGetWindowInfo(pWin) == NULL) { - GLWIN_DEBUG_MSG("Deferring until native window is created"); - return; - } - } - break; - - case GLX_DRAWABLE_PBUFFER: - { - if (draw->hPbuffer == NULL) { - __GLXscreen *screen; - glxWinScreen *winScreen; - int pixelFormat; - - // XXX: which DC are we supposed to use??? - HDC screenDC = GetDC(NULL); - - if (!(gc->base.config->drawableType & GLX_PBUFFER_BIT)) { - ErrorF - ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable\n"); - } - - screen = gc->base.pGlxScreen; - winScreen = (glxWinScreen *) screen; - - pixelFormat = - fbConfigToPixelFormatIndex(screenDC, gc->base.config, - GLX_PBUFFER_BIT, winScreen); - if (pixelFormat == 0) { - return; - } - - draw->hPbuffer = - wglCreatePbufferARBWrapper(screenDC, pixelFormat, - draw->base.pDraw->width, - draw->base.pDraw->height, NULL); - ReleaseDC(NULL, screenDC); - - if (draw->hPbuffer == NULL) { - ErrorF("wglCreatePbufferARBWrapper error: %s\n", - glxWinErrorMessage()); - return; - } - - GLWIN_DEBUG_MSG - ("glxWinDeferredCreateContext: pBuffer %p created for drawable %p", - draw->hPbuffer, draw); - } - } - break; - - case GLX_DRAWABLE_PIXMAP: - { - if (draw->dibDC == NULL) { - BITMAPINFOHEADER bmpHeader; - void *pBits; - - memset(&bmpHeader, 0, sizeof(BITMAPINFOHEADER)); - bmpHeader.biSize = sizeof(BITMAPINFOHEADER); - bmpHeader.biWidth = draw->base.pDraw->width; - bmpHeader.biHeight = draw->base.pDraw->height; - bmpHeader.biPlanes = 1; - bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel; - bmpHeader.biCompression = BI_RGB; - - if (!(gc->base.config->drawableType & GLX_PIXMAP_BIT)) { - ErrorF - ("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n"); - } - - draw->dibDC = CreateCompatibleDC(NULL); - if (draw->dibDC == NULL) { - ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage()); - return; - } - - draw->hDIB = - CreateDIBSection(draw->dibDC, (BITMAPINFO *) &bmpHeader, - DIB_RGB_COLORS, &pBits, 0, 0); - if (draw->dibDC == NULL) { - ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage()); - return; - } - - // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to - // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits - // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are - // even compatible ... - draw->pOldBits = ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr; - ((PixmapPtr) draw->base.pDraw)->devPrivate.ptr = pBits; - - // Select the DIB into the DC - draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB); - if (!draw->hOldDIB) { - ErrorF("SelectObject error: %s\n", glxWinErrorMessage()); - } - - // Set the pixel format of the bitmap - glxWinSetPixelFormat(gc, draw->dibDC, - draw->base.pDraw->bitsPerPixel, - GLX_PIXMAP_BIT); - - GLWIN_DEBUG_MSG - ("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p", - draw->hDIB, draw); - } - } - break; - - default: - { - ErrorF - ("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", - draw->base.type); - return; - } - } + glxWinDeferredCreateDrawable(draw, gc->base.config); dc = glxWinMakeDC(gc, draw, &dc, &hwnd); gc->ctx = wglCreateContext(dc); diff --git a/hw/xwin/glx/indirect.h b/hw/xwin/glx/indirect.h new file mode 100644 index 000000000..163375556 --- /dev/null +++ b/hw/xwin/glx/indirect.h @@ -0,0 +1,94 @@ +/* + * 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 indirect_h +#define indirect_h + +#include <X11/Xwindows.h> +#include <GL/wglext.h> +#include <glx/extension_string.h> + +/* ---------------------------------------------------------------------- */ +/* + * structure definitions + */ + +typedef struct __GLXWinContext __GLXWinContext; +typedef struct __GLXWinDrawable __GLXWinDrawable; +typedef struct __GLXWinScreen glxWinScreen; +typedef struct __GLXWinConfig GLXWinConfig; + +struct __GLXWinContext { + __GLXcontext base; + HGLRC ctx; /* Windows GL Context */ + __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */ + HWND hwnd; /* For detecting when HWND has changed */ +}; + +struct __GLXWinDrawable { + __GLXdrawable base; + __GLXWinContext *drawContext; + __GLXWinContext *readContext; + + /* If this drawable is GLX_DRAWABLE_PBUFFER */ + HPBUFFERARB hPbuffer; + + /* If this drawable is GLX_DRAWABLE_PIXMAP */ + HDC dibDC; + HANDLE hSection; /* file mapping handle */ + HBITMAP hDIB; + HBITMAP hOldDIB; /* original DIB for DC */ + void *pOldBits; /* original pBits for this drawable's pixmap */ +}; + +struct __GLXWinScreen { + __GLXscreen base; + + /* Supported GLX extensions */ + unsigned char glx_enable_bits[__GLX_EXT_BYTES]; + + Bool has_WGL_ARB_multisample; + Bool has_WGL_ARB_pixel_format; + Bool has_WGL_ARB_pbuffer; + Bool has_WGL_ARB_render_texture; + + /* wrapped screen functions */ + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + CopyWindowProcPtr CopyWindow; +}; + +struct __GLXWinConfig { + __GLXconfig base; + int pixelFormatIndex; +}; + +/* ---------------------------------------------------------------------- */ +/* + * function prototypes + */ + +void +glxWinDeferredCreateDrawable(__GLXWinDrawable *draw, __GLXconfig *config); + +#endif /* indirect_h */ diff --git a/hw/xwin/glx/winpriv.c b/hw/xwin/glx/winpriv.c index 4604f4495..f27c7e56a 100644 --- a/hw/xwin/glx/winpriv.c +++ b/hw/xwin/glx/winpriv.c @@ -154,3 +154,10 @@ winCheckScreenAiglxIsSupported(ScreenPtr pScreen) return FALSE; } + +void +winSetScreenAiglxIsActive(ScreenPtr pScreen) +{ + winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen); + pWinScreen->fNativeGlActive = TRUE; +} diff --git a/hw/xwin/glx/winpriv.h b/hw/xwin/glx/winpriv.h index dce1edf48..6f695a971 100644 --- a/hw/xwin/glx/winpriv.h +++ b/hw/xwin/glx/winpriv.h @@ -9,3 +9,4 @@ HWND winGetWindowInfo(WindowPtr pWin); Bool winCheckScreenAiglxIsSupported(ScreenPtr pScreen); +void winSetScreenAiglxIsActive(ScreenPtr pScreen); diff --git a/hw/xwin/win.h b/hw/xwin/win.h index 24e58490b..5c1ce32f1 100644 --- a/hw/xwin/win.h +++ b/hw/xwin/win.h @@ -588,6 +588,7 @@ typedef struct _winPrivScreenRec { UnrealizeFontPtr UnrealizeFont; #endif + Bool fNativeGlActive; } winPrivScreenRec; #ifdef XWIN_MULTIWINDOWEXTWM |