Merge remote-tracking branch 'jturney/master'
This commit is contained in:
commit
265c4e6653
10
configure.ac
10
configure.ac
|
@ -637,6 +637,7 @@ AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with
|
||||||
AC_ARG_ENABLE(vbe, AS_HELP_STRING([--enable-vbe], [Build Xorg with VBE module (default: enabled)]), [VBE=$enableval], [VBE=yes])
|
AC_ARG_ENABLE(vbe, AS_HELP_STRING([--enable-vbe], [Build Xorg with VBE module (default: enabled)]), [VBE=$enableval], [VBE=yes])
|
||||||
AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes])
|
AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes])
|
||||||
AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no])
|
AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no])
|
||||||
|
AC_ARG_ENABLE(windowsdri, AS_HELP_STRING([--enable-windowsdri], [Build XWin with WindowsDRI extension (default: auto)]), [WINDOWSDRI=$enableval], [WINDOWSDRI=auto])
|
||||||
AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes])
|
AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes])
|
||||||
AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
|
AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
|
||||||
AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
|
AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
|
||||||
|
@ -2230,6 +2231,13 @@ if test "x$XWIN" = xyes; then
|
||||||
AC_DEFINE(ROOTLESS,1,[Build Rootless code])
|
AC_DEFINE(ROOTLESS,1,[Build Rootless code])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "x$WINDOWSDRI" = xauto; then
|
||||||
|
PKG_CHECK_EXISTS([windowsdriproto], [WINDOWSDRI=yes], [WINDOWSDRI=no])
|
||||||
|
fi
|
||||||
|
if test "x$WINDOWSDRI" = xyes ; then
|
||||||
|
PKG_CHECK_MODULES(WINDOWSDRI, [windowsdriproto])
|
||||||
|
fi
|
||||||
|
|
||||||
case $host_os in
|
case $host_os in
|
||||||
cygwin*)
|
cygwin*)
|
||||||
XWIN_SERVER_NAME=XWin
|
XWIN_SERVER_NAME=XWin
|
||||||
|
@ -2283,6 +2291,7 @@ AM_CONDITIONAL(XWIN_MULTIWINDOW, [test "x$XWIN" = xyes])
|
||||||
AM_CONDITIONAL(XWIN_MULTIWINDOWEXTWM, [test "x$XWIN" = xyes && test "x$WINDOWSWM" = xyes])
|
AM_CONDITIONAL(XWIN_MULTIWINDOWEXTWM, [test "x$XWIN" = xyes && test "x$WINDOWSWM" = xyes])
|
||||||
AM_CONDITIONAL(XWIN_CLIPBOARD, [test "x$XWIN" = xyes])
|
AM_CONDITIONAL(XWIN_CLIPBOARD, [test "x$XWIN" = xyes])
|
||||||
AM_CONDITIONAL(XWIN_GLX_WINDOWS, [test "x$XWIN" = xyes && test "x$AIGLX" = xyes])
|
AM_CONDITIONAL(XWIN_GLX_WINDOWS, [test "x$XWIN" = xyes && test "x$AIGLX" = xyes])
|
||||||
|
AM_CONDITIONAL(XWIN_WINDOWS_DRI, [test "x$XWIN" = xyes && test "x$WINDOWSDRI" = xyes])
|
||||||
AM_CONDITIONAL(XWIN_RANDR, [test "x$XWIN" = xyes])
|
AM_CONDITIONAL(XWIN_RANDR, [test "x$XWIN" = xyes])
|
||||||
AM_CONDITIONAL(XWIN_XV, [test "x$XWIN" = xyes && test "x$XV" = xyes])
|
AM_CONDITIONAL(XWIN_XV, [test "x$XWIN" = xyes && test "x$XV" = xyes])
|
||||||
|
|
||||||
|
@ -2685,6 +2694,7 @@ hw/vfb/man/Makefile
|
||||||
hw/xnest/Makefile
|
hw/xnest/Makefile
|
||||||
hw/xnest/man/Makefile
|
hw/xnest/man/Makefile
|
||||||
hw/xwin/Makefile
|
hw/xwin/Makefile
|
||||||
|
hw/xwin/dri/Makefile
|
||||||
hw/xwin/glx/Makefile
|
hw/xwin/glx/Makefile
|
||||||
hw/xwin/man/Makefile
|
hw/xwin/man/Makefile
|
||||||
hw/xwin/winclipboard/Makefile
|
hw/xwin/winclipboard/Makefile
|
||||||
|
|
|
@ -146,7 +146,7 @@ validGlxContext(ClientPtr client, XID id, int access_mode,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
|
validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
|
||||||
__GLXdrawable ** drawable, int *err)
|
__GLXdrawable ** drawable, int *err)
|
||||||
{
|
{
|
||||||
|
|
|
@ -74,4 +74,7 @@ struct __GLXdrawable {
|
||||||
unsigned long eventMask;
|
unsigned long eventMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
|
||||||
|
__GLXdrawable **drawable, int *err);
|
||||||
|
|
||||||
#endif /* !__GLX_drawable_h__ */
|
#endif /* !__GLX_drawable_h__ */
|
||||||
|
|
|
@ -66,6 +66,7 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
|
||||||
#include "glx_extinit.h"
|
#include "glx_extinit.h"
|
||||||
#ifdef XWIN_GLX_WINDOWS
|
#ifdef XWIN_GLX_WINDOWS
|
||||||
#include "glx/glwindows.h"
|
#include "glx/glwindows.h"
|
||||||
|
#include "dri/windowsdri.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -117,6 +118,9 @@ const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]);
|
||||||
static const ExtensionModule xwinExtensions[] = {
|
static const ExtensionModule xwinExtensions[] = {
|
||||||
#ifdef GLXEXT
|
#ifdef GLXEXT
|
||||||
{ GlxExtensionInit, "GLX", &noGlxExtension },
|
{ GlxExtensionInit, "GLX", &noGlxExtension },
|
||||||
|
#ifdef XWIN_WINDOWS_DRI
|
||||||
|
{ WindowsDRIExtensionInit, "Windows-DRI", &noDriExtension },
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,17 @@ CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if XWIN_GLX_WINDOWS
|
if XWIN_GLX_WINDOWS
|
||||||
GLX_DIR = glx
|
GLX_DIR =
|
||||||
DEFS_GLX_WINDOWS = -DXWIN_GLX_WINDOWS
|
DEFS_GLX_WINDOWS =
|
||||||
XWIN_GLX_LIBS = $(top_builddir)/hw/xwin/glx/libXwinGLX.la
|
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
|
XWIN_GLX_SYS_LIBS = -lopengl32
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
noinst_LTLIBRARIES = libWindowsDRI.la
|
||||||
|
|
||||||
|
libWindowsDRI_la_SOURCES = \
|
||||||
|
windowsdri.c \
|
||||||
|
windowsdri.h
|
||||||
|
|
||||||
|
AM_CFLAGS = $(DIX_CFLAGS) \
|
||||||
|
@WINDOWSDRI_CFLAGS@ \
|
||||||
|
-I$(top_srcdir)/hw/xwin/
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 */
|
|
@ -7,9 +7,16 @@ libXwinGLX_la_SOURCES = \
|
||||||
glwindows.h \
|
glwindows.h \
|
||||||
glshim.c \
|
glshim.c \
|
||||||
indirect.c \
|
indirect.c \
|
||||||
|
indirect.h \
|
||||||
wgl_ext_api.c \
|
wgl_ext_api.c \
|
||||||
wgl_ext_api.h
|
wgl_ext_api.h
|
||||||
|
|
||||||
|
if XWIN_WINDOWS_DRI
|
||||||
|
libXwinGLX_la_SOURCES += \
|
||||||
|
dri_helpers.c \
|
||||||
|
dri_helpers.h
|
||||||
|
endif
|
||||||
|
|
||||||
libnativeGLthunk_la_SOURCES = \
|
libnativeGLthunk_la_SOURCES = \
|
||||||
glthunk.c
|
glthunk.c
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
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;
|
||||||
|
// The XID is used to create a unique name for a file mapping
|
||||||
|
// shared with the requesting process
|
||||||
|
//
|
||||||
|
// XXX: Alternatively, we could use an anonymous file mapping
|
||||||
|
// and use DuplicateHandle to make pDrawable->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, (void *)(uintptr_t)*handle);
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
glxWinFBConfigIDToPixelFormatIndex(int scr, int fbConfigID)
|
||||||
|
{
|
||||||
|
__GLXscreen *screen = glxGetScreen(screenInfo.screens[scr]);
|
||||||
|
__GLXconfig *c;
|
||||||
|
|
||||||
|
for (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;
|
||||||
|
}
|
|
@ -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 */
|
|
@ -81,12 +81,12 @@
|
||||||
#include "glwindows.h"
|
#include "glwindows.h"
|
||||||
#include <glx/glxserver.h>
|
#include <glx/glxserver.h>
|
||||||
#include <glx/glxutil.h>
|
#include <glx/glxutil.h>
|
||||||
#include <glx/extension_string.h>
|
|
||||||
#include <GL/glxtokens.h>
|
#include <GL/glxtokens.h>
|
||||||
|
|
||||||
#include <winpriv.h>
|
#include <winpriv.h>
|
||||||
#include <wgl_ext_api.h>
|
#include <wgl_ext_api.h>
|
||||||
#include <winglobals.h>
|
#include <winglobals.h>
|
||||||
|
#include <indirect.h>
|
||||||
|
|
||||||
#define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1]))
|
#define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1]))
|
||||||
|
|
||||||
|
@ -101,57 +101,6 @@
|
||||||
#define PFD_SUPPORT_COMPOSITION 0x00008000
|
#define PFD_SUPPORT_COMPOSITION 0x00008000
|
||||||
#endif
|
#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;
|
|
||||||
|
|
||||||
Bool has_WGL_ARB_multisample;
|
|
||||||
Bool has_WGL_ARB_pixel_format;
|
|
||||||
Bool has_WGL_ARB_pbuffer;
|
|
||||||
Bool has_WGL_ARB_render_texture;
|
|
||||||
Bool has_WGL_ARB_make_current_read;
|
|
||||||
|
|
||||||
/* wrapped screen functions */
|
|
||||||
RealizeWindowProcPtr RealizeWindow;
|
|
||||||
UnrealizeWindowProcPtr UnrealizeWindow;
|
|
||||||
CopyWindowProcPtr CopyWindow;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct __GLXWinConfig {
|
|
||||||
__GLXconfig base;
|
|
||||||
int pixelFormatIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/*
|
/*
|
||||||
|
@ -417,7 +366,8 @@ static Bool glxWinRealizeWindow(WindowPtr pWin);
|
||||||
static Bool glxWinUnrealizeWindow(WindowPtr pWin);
|
static Bool glxWinUnrealizeWindow(WindowPtr pWin);
|
||||||
static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg,
|
static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg,
|
||||||
RegionPtr prgnSrc);
|
RegionPtr prgnSrc);
|
||||||
|
static Bool glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride,
|
||||||
|
__GLXscreen *screen, __GLXconfig *config);
|
||||||
static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw,
|
static HDC glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw,
|
||||||
HDC * hdc, HWND * hwnd);
|
HDC * hdc, HWND * hwnd);
|
||||||
static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw);
|
static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable * draw);
|
||||||
|
@ -724,6 +674,9 @@ glxWinScreenProbe(ScreenPtr pScreen)
|
||||||
screen->CopyWindow = pScreen->CopyWindow;
|
screen->CopyWindow = pScreen->CopyWindow;
|
||||||
pScreen->CopyWindow = glxWinCopyWindow;
|
pScreen->CopyWindow = glxWinCopyWindow;
|
||||||
|
|
||||||
|
// Note that WGL is active on this screen
|
||||||
|
winSetScreenAiglxIsActive(pScreen);
|
||||||
|
|
||||||
return &screen->base;
|
return &screen->base;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -870,6 +823,10 @@ glxWinDrawableDestroy(__GLXdrawable * base)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glxPriv->hDIB) {
|
if (glxPriv->hDIB) {
|
||||||
|
if (!CloseHandle(glxPriv->hSection)) {
|
||||||
|
ErrorF("CloseHandle failed: %s\n", glxWinErrorMessage());
|
||||||
|
}
|
||||||
|
|
||||||
if (!DeleteObject(glxPriv->hDIB)) {
|
if (!DeleteObject(glxPriv->hDIB)) {
|
||||||
ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
|
ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
|
||||||
}
|
}
|
||||||
|
@ -913,6 +870,179 @@ glxWinCreateDrawable(ClientPtr client,
|
||||||
return &glxPriv->base;
|
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);
|
||||||
|
GLWIN_DEBUG_MSG("shared memory region size %zu + %u\n", sizeof(BITMAPINFOHEADER), (unsigned int)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", (unsigned int)draw->base.pDraw->id);
|
||||||
|
GLWIN_DEBUG_MSG("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
|
* Texture functions
|
||||||
|
@ -956,13 +1086,10 @@ glxWinReleaseTexImage(__GLXcontext * baseContext,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride,
|
glxWinSetPixelFormat(HDC hdc, int bppOverride, int drawableTypeOverride,
|
||||||
int drawableTypeOverride)
|
__GLXscreen *screen, __GLXconfig *config)
|
||||||
{
|
{
|
||||||
__GLXscreen *screen = gc->base.pGlxScreen;
|
|
||||||
glxWinScreen *winScreen = (glxWinScreen *) screen;
|
glxWinScreen *winScreen = (glxWinScreen *) screen;
|
||||||
|
|
||||||
__GLXconfig *config = gc->base.config;
|
|
||||||
GLXWinConfig *winConfig = (GLXWinConfig *) config;
|
GLXWinConfig *winConfig = (GLXWinConfig *) config;
|
||||||
|
|
||||||
GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d",
|
GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d",
|
||||||
|
@ -1013,7 +1140,7 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride,
|
||||||
int pixelFormat;
|
int pixelFormat;
|
||||||
|
|
||||||
/* convert fbConfig to PFD */
|
/* convert fbConfig to PFD */
|
||||||
if (fbConfigToPixelFormat(gc->base.config, &pfd, drawableTypeOverride)) {
|
if (fbConfigToPixelFormat(config, &pfd, drawableTypeOverride)) {
|
||||||
ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n");
|
ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1045,9 +1172,9 @@ glxWinSetPixelFormat(__GLXWinContext * gc, HDC hdc, int bppOverride,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int pixelFormat =
|
int pixelFormat = fbConfigToPixelFormatIndex(hdc, config,
|
||||||
fbConfigToPixelFormatIndex(hdc, gc->base.config,
|
drawableTypeOverride,
|
||||||
drawableTypeOverride, winScreen);
|
winScreen);
|
||||||
if (pixelFormat == 0) {
|
if (pixelFormat == 0) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1241,7 @@ glxWinMakeDC(__GLXWinContext * gc, __GLXWinDrawable * draw, HDC * hdc,
|
||||||
gc->hwnd = *hwnd;
|
gc->hwnd = *hwnd;
|
||||||
|
|
||||||
/* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */
|
/* 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",
|
ErrorF("glxWinSetPixelFormat error: %s\n",
|
||||||
glxWinErrorMessage());
|
glxWinErrorMessage());
|
||||||
ReleaseDC(*hwnd, *hdc);
|
ReleaseDC(*hwnd, *hdc);
|
||||||
|
@ -1200,140 +1327,7 @@ glxWinDeferredCreateContext(__GLXWinContext * gc, __GLXWinDrawable * draw)
|
||||||
("glxWinDeferredCreateContext: attach context %p to drawable %p", gc,
|
("glxWinDeferredCreateContext: attach context %p to drawable %p", gc,
|
||||||
draw);
|
draw);
|
||||||
|
|
||||||
switch (draw->base.type) {
|
glxWinDeferredCreateDrawable(draw, gc->base.config);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
|
dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
|
||||||
gc->ctx = wglCreateContext(dc);
|
gc->ctx = wglCreateContext(dc);
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
Bool has_WGL_ARB_make_current_read;
|
||||||
|
|
||||||
|
/* 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 */
|
|
@ -119,3 +119,10 @@ winCheckScreenAiglxIsSupported(ScreenPtr pScreen)
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
winSetScreenAiglxIsActive(ScreenPtr pScreen)
|
||||||
|
{
|
||||||
|
winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen);
|
||||||
|
pWinScreen->fNativeGlActive = TRUE;
|
||||||
|
}
|
||||||
|
|
|
@ -9,3 +9,4 @@
|
||||||
|
|
||||||
HWND winGetWindowInfo(WindowPtr pWin);
|
HWND winGetWindowInfo(WindowPtr pWin);
|
||||||
Bool winCheckScreenAiglxIsSupported(ScreenPtr pScreen);
|
Bool winCheckScreenAiglxIsSupported(ScreenPtr pScreen);
|
||||||
|
void winSetScreenAiglxIsActive(ScreenPtr pScreen);
|
||||||
|
|
|
@ -533,6 +533,8 @@ typedef struct _winPrivScreenRec {
|
||||||
SetShapeProcPtr SetShape;
|
SetShapeProcPtr SetShape;
|
||||||
|
|
||||||
winCursorRec cursor;
|
winCursorRec cursor;
|
||||||
|
|
||||||
|
Bool fNativeGlActive;
|
||||||
} winPrivScreenRec;
|
} winPrivScreenRec;
|
||||||
|
|
||||||
#ifdef XWIN_MULTIWINDOWEXTWM
|
#ifdef XWIN_MULTIWINDOWEXTWM
|
||||||
|
|
|
@ -111,6 +111,11 @@
|
||||||
#define SERVER_SYNC_MAJOR_VERSION 3
|
#define SERVER_SYNC_MAJOR_VERSION 3
|
||||||
#define SERVER_SYNC_MINOR_VERSION 1
|
#define SERVER_SYNC_MINOR_VERSION 1
|
||||||
|
|
||||||
|
/* Windows DRI */
|
||||||
|
#define SERVER_WINDOWSDRI_MAJOR_VERSION 1
|
||||||
|
#define SERVER_WINDOWSDRI_MINOR_VERSION 0
|
||||||
|
#define SERVER_WINDOWSDRI_PATCH_VERSION 0
|
||||||
|
|
||||||
/* Windows WM */
|
/* Windows WM */
|
||||||
#define SERVER_WINDOWSWM_MAJOR_VERSION 1
|
#define SERVER_WINDOWSWM_MAJOR_VERSION 1
|
||||||
#define SERVER_WINDOWSWM_MINOR_VERSION 0
|
#define SERVER_WINDOWSWM_MINOR_VERSION 0
|
||||||
|
|
Loading…
Reference in New Issue