aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xwin/glx/indirect.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xwin/glx/indirect.c')
-rw-r--r--xorg-server/hw/xwin/glx/indirect.c3136
1 files changed, 1872 insertions, 1264 deletions
diff --git a/xorg-server/hw/xwin/glx/indirect.c b/xorg-server/hw/xwin/glx/indirect.c
index 5e12022f4..ba995c007 100644
--- a/xorg-server/hw/xwin/glx/indirect.c
+++ b/xorg-server/hw/xwin/glx/indirect.c
@@ -1,22 +1,27 @@
/*
- * GLX implementation that uses Windows OpenGL library
- * (Indirect rendering path)
+ * File: indirect.c
+ * Purpose: A GLX implementation that uses Windows OpenGL library
+ *
+ * Authors: Alexander Gottwald
+ * Jon TURNEY
+ *
+ * Copyright (c) Jon TURNEY 2009
+ * Copyright (c) Alexander Gottwald 2004
*
- * Authors: Alexander Gottwald
- */
-/*
* Portions of this file are copied from GL/apple/indirect.c,
* which contains the following copyright:
- *
+ *
+ * Copyright (c) 2007, 2008, 2009 Apple Inc.
+ * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
* Copyright (c) 2002 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002 Apple Computer, Inc.
*
- * Portions of this file are copied from xf86glx.c,
+ * Portions of this file are copied from Mesa's xf86glx.c,
* which contains the following copyright:
*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
+ *
* 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
@@ -34,636 +39,1479 @@
* 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.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
*/
+/*
+ TODO:
+ - hook up remaining unimplemented extensions
+ - research what guarantees glXWaitX, glXWaitGL are supposed to offer, and implement then
+ using GdiFlush and/or glFinish
+ - pbuffer clobbering: we don't get async notification, but can we arrange to emit the
+ event when we notice it's been clobbered? at the very least, check if it's been clobbered
+ before using it?
+ - are the __GLXConfig * we get handed back ones we are made (so we can extend the structure
+ with privates?) Or are they created inside the GLX core as well?
+*/
+
+/*
+ MSDN clarifications:
+ It says SetPixelFormat()'s PIXELFORMATDESCRIPTOR pointer argument has no effect
+ except on metafiles, this seems to mean that as it's ok to supply NULL if the DC
+ is not for a metafile
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
+ wglMakeCurrent ignores the hdc if hglrc is NULL, so wglMakeCurrent(NULL, NULL)
+ is used to make no context current
+
+*/
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
#endif
#include "glwindows.h"
-#include <glcontextmodes.h>
-#include <stdint.h>
+#include <glx/glxserver.h>
+#include <glx/glxutil.h>
+#include <glx/extension_string.h>
+#include <GL/internal/glcore.h>
+#include <GL/glxtokens.h>
#include <winpriv.h>
+#include <wgl_ext_api.h>
+
+#define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1]))
+
+/* ---------------------------------------------------------------------- */
+/*
+ * 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;
+};
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Various debug helpers
+ */
#define GLWIN_DEBUG_HWND(hwnd) \
- if (glWinDebugSettings.dumpHWND) { \
+ if (glxWinDebugSettings.dumpHWND) { \
char buffer[1024]; \
if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; \
- GLWIN_DEBUG_MSG("Got HWND %s (%p)\n", buffer, hwnd); \
+ GLWIN_DEBUG_MSG("Got HWND %p for window '%s'", hwnd, buffer); \
}
+glxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0};
-/* ggs: needed to call back to glx with visual configs */
-extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, void **configprivs);
-
-glWinDebugSettingsRec glWinDebugSettings = { 1, 0, 0, 0, 0};
-
-static void glWinInitDebugSettings(void)
+static void glxWinInitDebugSettings(void)
{
char *envptr;
envptr = getenv("GLWIN_ENABLE_DEBUG");
if (envptr != NULL)
- glWinDebugSettings.enableDebug = (atoi(envptr) == 1);
+ glxWinDebugSettings.enableDebug = (atoi(envptr) == 1);
envptr = getenv("GLWIN_ENABLE_TRACE");
if (envptr != NULL)
- glWinDebugSettings.enableTrace = (atoi(envptr) == 1);
+ glxWinDebugSettings.enableTrace = (atoi(envptr) == 1);
envptr = getenv("GLWIN_DUMP_PFD");
if (envptr != NULL)
- glWinDebugSettings.dumpPFD = (atoi(envptr) == 1);
-
+ glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1);
+
envptr = getenv("GLWIN_DUMP_HWND");
if (envptr != NULL)
- glWinDebugSettings.dumpHWND = (atoi(envptr) == 1);
+ glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1);
envptr = getenv("GLWIN_DUMP_DC");
if (envptr != NULL)
- glWinDebugSettings.dumpDC = (atoi(envptr) == 1);
+ glxWinDebugSettings.dumpDC = (atoi(envptr) == 1);
+
+ envptr = getenv("GLWIN_ENABLE_GLCALL_TRACE");
+ if (envptr != NULL)
+ glxWinDebugSettings.enableGLcallTrace = (atoi(envptr) == 1);
+
+ envptr = getenv("GLWIN_ENABLE_WGLCALL_TRACE");
+ if (envptr != NULL)
+ glxWinDebugSettings.enableWGLcallTrace = (atoi(envptr) == 1);
+
+ envptr = getenv("GLWIN_DEBUG_ALL");
+ if (envptr != NULL)
+ {
+ glxWinDebugSettings.enableDebug = 1;
+ glxWinDebugSettings.enableTrace = 1;
+ glxWinDebugSettings.dumpPFD = 1;
+ glxWinDebugSettings.dumpHWND = 1;
+ glxWinDebugSettings.dumpDC = 1;
+ glxWinDebugSettings.enableGLcallTrace = 1;
+ glxWinDebugSettings.enableWGLcallTrace = 1;
+ }
}
-static char errorbuffer[1024];
-const char *glWinErrorMessage(void)
+static
+const char *glxWinErrorMessage(void)
{
- if (!FormatMessage(
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &errorbuffer,
- sizeof(errorbuffer),
- NULL ))
+ static char errorbuffer[1024];
+
+ if (!FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &errorbuffer,
+ sizeof(errorbuffer),
+ NULL ))
{
- snprintf(errorbuffer, sizeof(errorbuffer), "Unknown error in FormatMessage: %08x!\n", (unsigned)GetLastError());
+ snprintf(errorbuffer, sizeof(errorbuffer), "Unknown error in FormatMessage: %08x!", (unsigned)GetLastError());
}
- return errorbuffer;
+
+ if (errorbuffer[strlen(errorbuffer)-1] == '\n')
+ errorbuffer[strlen(errorbuffer)-1] = 0;
+
+ return errorbuffer;
}
+static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd);
+
+#define DUMP_PFD_FLAG(flag) \
+ if (pfd->dwFlags & flag) { \
+ ErrorF("%s%s", pipesym, #flag); \
+ pipesym = " | "; \
+ }
+
+static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd)
+{
+ const char *pipesym = ""; /* will be set after first flag dump */
+ ErrorF("PIXELFORMATDESCRIPTOR:\n");
+ ErrorF("nSize = %u\n", pfd->nSize);
+ ErrorF("nVersion = %u\n", pfd->nVersion);
+ ErrorF("dwFlags = %lu = {", pfd->dwFlags);
+ DUMP_PFD_FLAG(PFD_DOUBLEBUFFER);
+ DUMP_PFD_FLAG(PFD_STEREO);
+ DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW);
+ DUMP_PFD_FLAG(PFD_DRAW_TO_BITMAP);
+ DUMP_PFD_FLAG(PFD_SUPPORT_GDI);
+ DUMP_PFD_FLAG(PFD_SUPPORT_OPENGL);
+ DUMP_PFD_FLAG(PFD_GENERIC_FORMAT);
+ DUMP_PFD_FLAG(PFD_NEED_PALETTE);
+ DUMP_PFD_FLAG(PFD_NEED_SYSTEM_PALETTE);
+ DUMP_PFD_FLAG(PFD_SWAP_EXCHANGE);
+ DUMP_PFD_FLAG(PFD_SWAP_COPY);
+ DUMP_PFD_FLAG(PFD_SWAP_LAYER_BUFFERS);
+ DUMP_PFD_FLAG(PFD_GENERIC_ACCELERATED);
+ DUMP_PFD_FLAG(PFD_DEPTH_DONTCARE);
+ DUMP_PFD_FLAG(PFD_DOUBLEBUFFER_DONTCARE);
+ DUMP_PFD_FLAG(PFD_STEREO_DONTCARE);
+ ErrorF("}\n");
+
+ ErrorF("iPixelType = %hu = %s\n", pfd->iPixelType,
+ (pfd->iPixelType == PFD_TYPE_RGBA ? "PFD_TYPE_RGBA" : "PFD_TYPE_COLORINDEX"));
+ ErrorF("cColorBits = %hhu\n", pfd->cColorBits);
+ ErrorF("cRedBits = %hhu\n", pfd->cRedBits);
+ ErrorF("cRedShift = %hhu\n", pfd->cRedShift);
+ ErrorF("cGreenBits = %hhu\n", pfd->cGreenBits);
+ ErrorF("cGreenShift = %hhu\n", pfd->cGreenShift);
+ ErrorF("cBlueBits = %hhu\n", pfd->cBlueBits);
+ ErrorF("cBlueShift = %hhu\n", pfd->cBlueShift);
+ ErrorF("cAlphaBits = %hhu\n", pfd->cAlphaBits);
+ ErrorF("cAlphaShift = %hhu\n", pfd->cAlphaShift);
+ ErrorF("cAccumBits = %hhu\n", pfd->cAccumBits);
+ ErrorF("cAccumRedBits = %hhu\n", pfd->cAccumRedBits);
+ ErrorF("cAccumGreenBits = %hhu\n", pfd->cAccumGreenBits);
+ ErrorF("cAccumBlueBits = %hhu\n", pfd->cAccumBlueBits);
+ ErrorF("cAccumAlphaBits = %hhu\n", pfd->cAccumAlphaBits);
+ ErrorF("cDepthBits = %hhu\n", pfd->cDepthBits);
+ ErrorF("cStencilBits = %hhu\n", pfd->cStencilBits);
+ ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers);
+ ErrorF("iLayerType = %hhu\n", pfd->iLayerType);
+ ErrorF("bReserved = %hhu\n", pfd->bReserved);
+ ErrorF("dwLayerMask = %lu\n", pfd->dwLayerMask);
+ ErrorF("dwVisibleMask = %lu\n", pfd->dwVisibleMask);
+ ErrorF("dwDamageMask = %lu\n", pfd->dwDamageMask);
+ ErrorF("\n");
+}
+
+static const char *
+visual_class_name(int cls)
+{
+ switch (cls) {
+ case GLX_STATIC_COLOR:
+ return "StaticColor";
+ case GLX_PSEUDO_COLOR:
+ return "PseudoColor";
+ case GLX_STATIC_GRAY:
+ return "StaticGray";
+ case GLX_GRAY_SCALE:
+ return "GrayScale";
+ case GLX_TRUE_COLOR:
+ return "TrueColor";
+ case GLX_DIRECT_COLOR:
+ return "DirectColor";
+ default:
+ return "-none-";
+ }
+}
+
+static const char *
+swap_method_name(int mthd)
+{
+ switch (mthd)
+ {
+ case GLX_SWAP_EXCHANGE_OML:
+ return "xchg";
+ case GLX_SWAP_COPY_OML:
+ return "copy";
+ case GLX_SWAP_UNDEFINED_OML:
+ return " ";
+ default:
+ return "????";
+ }
+}
+
+static void
+fbConfigsDump(unsigned int n, __GLXconfig *c)
+{
+ ErrorF("%d fbConfigs\n", n);
+ ErrorF("pxf vis fb render Ste aux accum MS drawable Group/\n");
+ ErrorF("idx ID ID VisualType Depth Lvl RGB CI DB Swap reo R G B A Z S buf AR AG AB AA bufs num W P Pb Float Trans Caveat\n");
+ ErrorF("-----------------------------------------------------------------------------------------------------------------------------\n");
+
+ while (c != NULL)
+ {
+ unsigned int i = ((GLXWinConfig *)c)->pixelFormatIndex;
+
+ ErrorF("%3d %2x %2x "
+ "%-11s"
+ " %3d %3d %s %s %s %s %s "
+ "%2d %2d %2d %2d "
+ "%2d %2d "
+ "%2d "
+ "%2d %2d %2d %2d"
+ " %2d %2d"
+ " %s %s %s "
+ " %s "
+ " %s "
+ " %d %s"
+ "\n",
+ i, c->visualID, c->fbconfigID,
+ visual_class_name(c->visualType),
+ c->rgbBits ? c->rgbBits : c->indexBits,
+ c->level,
+ (c->renderType & GLX_RGBA_BIT) ? "y" : ".",
+ (c->renderType & GLX_COLOR_INDEX_BIT) ? "y" : ".",
+ c->doubleBufferMode ? "y" : ".",
+ swap_method_name(c->swapMethod),
+ c->stereoMode ? "y" : ".",
+ c->redBits, c->greenBits, c->blueBits, c->alphaBits,
+ c->depthBits, c->stencilBits,
+ c->numAuxBuffers,
+ c->accumRedBits, c->accumGreenBits, c->accumBlueBits, c->accumAlphaBits,
+ c->sampleBuffers, c->samples,
+ (c->drawableType & GLX_WINDOW_BIT) ? "y" : ".",
+ (c->drawableType & GLX_PIXMAP_BIT) ? "y" : ".",
+ (c->drawableType & GLX_PBUFFER_BIT) ? "y" : ".",
+ ".",
+ (c->transparentPixel != GLX_NONE_EXT) ? "y" : ".",
+ c->visualSelectGroup, (c->visualRating == GLX_SLOW_VISUAL_EXT) ? "*" : " ");
+
+ c = c->next;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
/*
- * GLX implementation that uses Win32's OpenGL
+ * Forward declarations
*/
+static __GLXscreen *glxWinScreenProbe(ScreenPtr pScreen);
+static __GLXcontext *glxWinCreateContext(__GLXscreen *screen,
+ __GLXconfig *modes,
+ __GLXcontext *baseShareContext);
+static __GLXdrawable *glxWinCreateDrawable(__GLXscreen *screen,
+ DrawablePtr pDraw,
+ int type,
+ XID drawId,
+ __GLXconfig *conf);
+
+static Bool glxWinRealizeWindow(WindowPtr pWin);
+static Bool glxWinUnrealizeWindow(WindowPtr pWin);
+static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+
+static HDC glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HDC *hdc, HWND *hwnd);
+static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable *draw);
+
+static void glxWinCreateConfigs(HDC dc, glxWinScreen *screen);
+static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen);
+static int fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride);
+static int fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen);
+
+/* ---------------------------------------------------------------------- */
/*
- * Server-side GLX uses these functions which are normally defined
- * in the OpenGL SI.
+ * The GLX provider
*/
-GLuint __glFloorLog2(GLuint val)
+__GLXprovider __glXWGLProvider = {
+ glxWinScreenProbe,
+ "Win32 native WGL",
+ NULL
+};
+
+void
+glxWinPushNativeProvider(void)
{
- int c = 0;
+ GlxPushProvider(&__glXWGLProvider);
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Screen functions
+ */
- while (val > 1) {
- c++;
- val >>= 1;
+static void
+glxWinScreenDestroy(__GLXscreen *screen)
+{
+ GLWIN_DEBUG_MSG("glxWinScreenDestroy(%p)", screen);
+ __glXScreenDestroy(screen);
+ xfree(screen);
+}
+
+static int
+glxWinScreenSwapInterval(__GLXdrawable *drawable, int interval)
+{
+ BOOL ret = wglSwapIntervalEXTWrapper(interval);
+ if (!ret)
+ {
+ ErrorF("wglSwapIntervalEXT interval %d failed:%s\n", interval, glxWinErrorMessage());
}
- return c;
+ return ret;
}
-/* some prototypes */
-static Bool glWinScreenProbe(int screen);
-static Bool glWinInitVisuals(VisualPtr *visualp, DepthPtr *depthp,
- int *nvisualp, int *ndepthp,
- int *rootDepthp, VisualID *defaultVisp,
- unsigned long sizes, int bitsPerRGB);
-static void glWinSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
- void **privates);
-static __GLinterface *glWinCreateContext(__GLimports *imports,
- __GLcontextModes *mode,
- __GLinterface *shareGC);
-static void glWinCreateBuffer(__GLXdrawablePrivate *glxPriv);
-static void glWinResetExtension(void);
+/* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */
+static __GLXscreen *
+glxWinScreenProbe(ScreenPtr pScreen)
+{
+ glxWinScreen *screen;
+ const char *gl_extensions;
+ const char *wgl_extensions;
+ HWND hwnd;
+ HDC hdc;
+ HGLRC hglrc;
+
+ GLWIN_DEBUG_MSG("glxWinScreenProbe");
+
+ glxWinInitDebugSettings();
+
+ if (pScreen == NULL)
+ return NULL;
+
+ if (!winCheckScreenAiglxIsSupported(pScreen))
+ {
+ LogMessage(X_ERROR,"AIGLX: No native OpenGL in modes with a root window\n");
+ return NULL;
+ }
+ screen = xcalloc(1, sizeof(glxWinScreen));
+
+ if (NULL == screen)
+ return NULL;
+
+ /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */
+ screen->RealizeWindow = pScreen->RealizeWindow;
+ pScreen->RealizeWindow = glxWinRealizeWindow;
+ screen->UnrealizeWindow = pScreen->UnrealizeWindow;
+ pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
+ screen->CopyWindow = pScreen->CopyWindow;
+ pScreen->CopyWindow = glxWinCopyWindow;
+
+ /* Dump out some useful information about the native renderer */
+
+ // create window class
+#define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest"
+ {
+ 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;
+ RegisterClassEx (&wc);
+ }
+ }
+
+ // create an invisible window for a scratch DC
+ hwnd = CreateWindowExA(0,
+ WIN_GL_TEST_WINDOW_CLASS,
+ "XWin GL Renderer Capabilities Test Window",
+ 0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
+ if (hwnd == NULL)
+ LogMessage(X_ERROR,"AIGLX: Couldn't create a window for render capabilities testing\n");
+
+ 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 = wglCreateContext(hdc);
+ wglMakeCurrent(hdc, hglrc);
+
+ // initialize wgl extension proc pointers (don't call them before here...)
+ // (but we need to have a current context for them to be resolvable)
+ wglResolveExtensionProcs();
+
+ ErrorF("GL_VERSION: %s\n", glGetStringWrapperNonstatic(GL_VERSION));
+ ErrorF("GL_VENDOR: %s\n", glGetStringWrapperNonstatic(GL_VENDOR));
+ ErrorF("GL_RENDERER: %s\n", glGetStringWrapperNonstatic(GL_RENDERER));
+ gl_extensions = (const char *)glGetStringWrapperNonstatic(GL_EXTENSIONS);
+ ErrorF("GL_EXTENSIONS: %s\n", gl_extensions);
+ wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
+ ErrorF("WGL_EXTENSIONS:%s\n", wgl_extensions);
+
+ // Can you see the problem here? The extensions string is DC specific
+ // Different DCs for windows on a multimonitor system driven by multiple cards
+ // might have completely different capabilities. Of course, good luck getting
+ // those screens to be accelerated in XP and earlier...
+
+ {
+ // testing facility to not use any WGL extensions
+ char *envptr = getenv("GLWIN_NO_WGL_EXTENSIONS");
+ if ((envptr != NULL) && (atoi(envptr) != 0))
+ {
+ ErrorF("GLWIN_NO_WGL_EXTENSIONS is set, ignoring WGL_EXTENSIONS\n");
+ wgl_extensions = "";
+ }
+ }
+
+ {
+ Bool glx_sgi_make_current_read = FALSE;
+
+ //
+ // Based on the WGL extensions available, enable various GLX extensions
+ // XXX: make this table-driven ?
+ //
+ memset(screen->glx_enable_bits, 0, __GLX_EXT_BYTES);
+
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_visual_info");
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_visual_rating");
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_import_context");
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_OML_swap_method");
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIX_fbconfig");
+
+ if (strstr(wgl_extensions, "WGL_ARB_make_current_read"))
+ {
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_make_current_read");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
+ glx_sgi_make_current_read = TRUE;
+ }
+
+ if (strstr(gl_extensions, "GL_WIN_swap_hint"))
+ {
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
+ }
+
+ if (strstr(wgl_extensions, "WGL_EXT_swap_control"))
+ {
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control");
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_swap_control");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
+ }
+
+/* // Hmm? screen->texOffset */
+/* if (strstr(wgl_extensions, "WGL_ARB_render_texture")) */
+/* { */
+/* __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_texture_from_pixmap"); */
+/* LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); */
+/* screen->has_WGL_ARB_render_texture = TRUE; */
+/* } */
+
+ if (strstr(wgl_extensions, "WGL_ARB_pbuffer"))
+ {
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIX_pbuffer");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGIX_pbuffer\n");
+ screen->has_WGL_ARB_pbuffer = TRUE;
+ }
+
+ if (strstr(wgl_extensions, "WGL_ARB_multisample"))
+ {
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_multisample");
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIS_multisample");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_multisample and GLX_SGIS_multisample\n");
+ screen->has_WGL_ARB_multisample = TRUE;
+ }
+
+ screen->base.destroy = glxWinScreenDestroy;
+ screen->base.createContext = glxWinCreateContext;
+ screen->base.createDrawable = glxWinCreateDrawable;
+ screen->base.swapInterval = glxWinScreenSwapInterval;
+ screen->base.hyperpipeFuncs = NULL;
+ screen->base.swapBarrierFuncs = NULL;
+ screen->base.pScreen = pScreen;
+
+ if (strstr(wgl_extensions, "WGL_ARB_pixel_format"))
+ {
+ glxWinCreateConfigsExt(hdc, screen);
+ screen->has_WGL_ARB_pixel_format = TRUE;
+ }
+ else
+ {
+ glxWinCreateConfigs(hdc, screen);
+ screen->has_WGL_ARB_pixel_format = FALSE;
+ }
+ // Initializes screen->base.fbconfigs and screen->base.numFBConfigs
+
+ /* These will be set by __glXScreenInit */
+ screen->base.visuals = NULL;
+ screen->base.numVisuals = 0;
+
+ __glXScreenInit(&screen->base, pScreen);
+
+ // dump out fbConfigs now fbConfigIds and visualIDs have been assigned
+ fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs);
+
+ // Override the GL extensions string set by __glXScreenInit()
+ screen->base.GLextensions = xstrdup(gl_extensions);
+
+ // Generate the GLX extensions string (overrides that set by __glXScreenInit())
+ {
+ unsigned int buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
+ if (buffer_size > 0)
+ {
+ if (screen->base.GLXextensions != NULL)
+ {
+ xfree(screen->base.GLXextensions);
+ }
+
+ screen->base.GLXextensions = xnfalloc(buffer_size);
+ __glXGetExtensionString(screen->glx_enable_bits, screen->base.GLXextensions);
+ }
+ }
+
+ //
+ // Override the GLX version (__glXScreenInit() sets it to "1.2")
+ // if we have all the needed extensionsto operate as a higher version
+ //
+ // SGIX_fbconfig && SGIX_pbuffer && SGI_make_current_read -> 1.3
+ // ARB_multisample -> 1.4
+ //
+ if (screen->has_WGL_ARB_pbuffer && glx_sgi_make_current_read)
+ {
+ xfree(screen->base.GLXversion);
+
+ if (screen->has_WGL_ARB_multisample)
+ {
+ screen->base.GLXversion = xstrdup("1.4");
+ /*
+ XXX: this just controls the version string returned to glXQueryServerString()
+ there is currently no way to control the version number the server returns to
+ glXQueryVersion()...
+ */
+ }
+ else
+ {
+ screen->base.GLXversion = xstrdup("1.3");
+ }
+ LogMessage(X_INFO, "AIGLX: Set GLX version to %s\n", screen->base.GLXversion);
+ }
+ }
+
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(hglrc);
+ ReleaseDC(hwnd, hdc);
+ DestroyWindow(hwnd);
+
+ return &screen->base;
+}
+
+/* ---------------------------------------------------------------------- */
/*
- * This structure is statically allocated in the __glXScreens[]
- * structure. This struct is not used anywhere other than in
- * __glXScreenInit to initialize each of the active screens
- * (__glXActiveScreens[]). Several of the fields must be initialized by
- * the screenProbe routine before they are copied to the active screens
- * struct. In particular, the contextCreate, pGlxVisual, numVisuals,
- * and numUsableVisuals fields must be initialized.
+ * Window functions
*/
-static __GLXscreenInfo __glDDXScreenInfo = {
- glWinScreenProbe, /* Must be generic and handle all screens */
- glWinCreateContext, /* Substitute screen's createContext routine */
- glWinCreateBuffer, /* Substitute screen's createBuffer routine */
- NULL, /* Set up pGlxVisual in probe */
- NULL, /* Set up pVisualPriv in probe */
- 0, /* Set up numVisuals in probe */
- 0, /* Set up numUsableVisuals in probe */
- "Vendor String", /* GLXvendor is overwritten by __glXScreenInit */
- "Version String", /* GLXversion is overwritten by __glXScreenInit */
- "Extensions String", /* GLXextensions is overwritten by __glXScreenInit */
- NULL /* WrappedPositionWindow is overwritten */
-};
-void *__glXglDDXScreenInfo(void) {
- return &__glDDXScreenInfo;
-}
+static Bool
+glxWinRealizeWindow(WindowPtr pWin)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
-static __GLXextensionInfo __glDDXExtensionInfo = {
- GL_CORE_WINDOWS,
- glWinResetExtension,
- glWinInitVisuals,
- glWinSetVisualConfigs
-};
+ GLWIN_DEBUG_MSG("glxWinRealizeWindow");
-void *__glXglDDXExtensionInfo(void) {
- return &__glDDXExtensionInfo;
+ /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */
+ pScreen->RealizeWindow = screenPriv->RealizeWindow;
+ result = pScreen->RealizeWindow(pWin);
+ pScreen->RealizeWindow = glxWinRealizeWindow;
+
+ return result;
}
-/* prototypes */
-static GLboolean glWinDestroyContext(__GLcontext *gc);
-static GLboolean glWinLoseCurrent(__GLcontext *gc);
-static GLboolean glWinMakeCurrent(__GLcontext *gc);
-static GLboolean glWinShareContext(__GLcontext *gc, __GLcontext *gcShare);
-static GLboolean glWinCopyContext(__GLcontext *dst, const __GLcontext *src,
- GLuint mask);
-static GLboolean glWinForceCurrent(__GLcontext *gc);
+static void
+glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ __GLXWinDrawable *pGlxDraw;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
-/* Drawing surface notification callbacks */
-static GLboolean glWinNotifyResize(__GLcontext *gc);
-static void glWinNotifyDestroy(__GLcontext *gc);
-static void glWinNotifySwapBuffers(__GLcontext *gc);
+ GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow);
-/* Dispatch table override control for external agents like libGLS */
-static struct __GLdispatchStateRec* glWinDispatchExec(__GLcontext *gc);
-static void glWinBeginDispatchOverride(__GLcontext *gc);
-static void glWinEndDispatchOverride(__GLcontext *gc);
+ dixLookupResourceByType((pointer) &pGlxDraw, pWindow->drawable.id, __glXDrawableRes,
+ NullClient, DixUnknownAccess);
-/* Debug output */
-static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd);
-static __GLexports glWinExports = {
- glWinDestroyContext,
- glWinLoseCurrent,
- glWinMakeCurrent,
- glWinShareContext,
- glWinCopyContext,
- glWinForceCurrent,
-
- glWinNotifyResize,
- glWinNotifyDestroy,
- glWinNotifySwapBuffers,
-
- glWinDispatchExec,
- glWinBeginDispatchOverride,
- glWinEndDispatchOverride
-};
+ /*
+ Discard any CopyWindow requests if a GL drawing context is pointing at the window
-glWinScreenRec glWinScreens[MAXSCREENS];
+ For regions which are being drawn by GL, the shadow framebuffer doesn't have the
+ correct bits, so we wish to avoid shadow framebuffer damage occuring, which will
+ cause those incorrect bits to be transferred to the display....
+ */
+ if (pGlxDraw && pGlxDraw->drawContext)
+ {
+ GLWIN_DEBUG_MSG("glxWinCopyWindow: discarding");
+ return;
+ }
-/* __GLdrawablePrivate->private */
-typedef struct {
- DrawablePtr pDraw;
- /* xp_surface_id sid; */
-} GLWinDrawableRec;
+ GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer");
-struct __GLcontextRec {
- struct __GLinterfaceRec interface; /* required to be first */
+ pScreen->CopyWindow = screenPriv->CopyWindow;
+ pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
+ pScreen->CopyWindow = glxWinCopyWindow;
+}
- HGLRC ctx; /* Windows GL Context */
-
- HDC dc; /* Windows Device Context */
- winWindowInfoRec winInfo; /* Window info from XWin */
-
- PIXELFORMATDESCRIPTOR pfd; /* Pixelformat flags */
- int pixelFormat; /* Pixelformat index */
-
- unsigned isAttached :1; /* Flag to track if context is attached */
-};
+static Bool
+glxWinUnrealizeWindow(WindowPtr pWin)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ glxWinScreen *screenPriv = (glxWinScreen *)glxGetScreen(pScreen);
+
+ GLWIN_DEBUG_MSG("glxWinUnrealizeWindow");
-static HDC glWinMakeDC(__GLcontext *gc)
+ pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow;
+ result = pScreen->UnrealizeWindow(pWin);
+ pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
+
+ return result;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Drawable functions
+ */
+
+static GLboolean
+glxWinDrawableSwapBuffers(__GLXdrawable *base)
{
HDC dc;
+ HWND hwnd;
+ BOOL ret;
+ __GLXWinDrawable *draw = (__GLXWinDrawable *)base;
- /*if (gc->winInfo.hrgn == NULL)
- {
- GLWIN_DEBUG_MSG("Creating region from RECT(%ld,%ld,%ld,%ld):",
- gc->winInfo.rect.left,
- gc->winInfo.rect.top,
- gc->winInfo.rect.right,
- gc->winInfo.rect.bottom);
- gc->winInfo.hrgn = CreateRectRgnIndirect(&gc->winInfo.rect);
- GLWIN_DEBUG_MSG2("%p\n", gc->winInfo.hrgn);
- }*/
-
- if (glWinDebugSettings.enableTrace)
- GLWIN_DEBUG_HWND(gc->winInfo.hwnd);
-
- dc = GetDC(gc->winInfo.hwnd);
- /*dc = GetDCEx(gc->winInfo.hwnd, gc->winInfo.hrgn,
- DCX_WINDOW | DCX_NORESETATTRS ); */
+ /* Swap buffers on the last active context for drawing on the drawable */
+ if (draw->drawContext == NULL)
+ {
+ GLWIN_TRACE_MSG("glxWinSwapBuffers - no context for drawable");
+ return GL_FALSE;
+ }
+ GLWIN_TRACE_MSG("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)", base, draw->drawContext, draw->drawContext->ctx);
+
+ /*
+ draw->drawContext->base.drawPriv will not be set if the context is not current anymore,
+ but if it is, it should point to this drawable....
+ */
+ assert((draw->drawContext->base.drawPriv == NULL) || (draw->drawContext->base.drawPriv == base));
+
+ dc = glxWinMakeDC(draw->drawContext, draw, &dc, &hwnd);
if (dc == NULL)
- ErrorF("GetDC error: %s\n", glWinErrorMessage());
- return dc;
+ return GL_FALSE;
+
+ ret = wglSwapLayerBuffers(dc, WGL_SWAP_MAIN_PLANE);
+
+ glxWinReleaseDC(hwnd, dc, draw);
+
+ if (!ret)
+ {
+ ErrorF("wglSwapBuffers failed: %s\n", glxWinErrorMessage());
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
}
-static void unattach(__GLcontext *gc)
+static void
+glxWinDrawableCopySubBuffer(__GLXdrawable *drawable,
+ int x, int y, int w, int h)
{
- BOOL ret;
- GLWIN_DEBUG_MSG("unattach (ctx %p)\n", gc->ctx);
- if (!gc->isAttached)
+ glAddSwapHintRectWINWrapperNonstatic(x, y, w, h);
+ glxWinDrawableSwapBuffers(drawable);
+}
+
+static void
+glxWinDrawableDestroy(__GLXdrawable *base)
+{
+ __GLXWinDrawable *glxPriv = (__GLXWinDrawable *)base;
+
+ if (glxPriv->drawContext && (__glXLastContext == &((glxPriv->drawContext)->base)))
{
- ErrorF("called unattach on an unattached context\n");
- return;
+ // if this context is current and has unflushed commands, say we have flushed them
+ // (don't actually flush them, the window is going away anyhow, and an implict flush occurs
+ // on the next context change)
+ // (GLX core considers it an error when we try to select a new current context if the old one
+ // has unflushed commands, but the window has disappeared..)
+ __GLX_NOTE_FLUSHED_CMDS(__glXLastContext);
+ __glXLastContext = NULL;
}
- if (gc->ctx)
+ if (glxPriv->hPbuffer)
+ if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer))
+ {
+ ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage());
+ }
+
+ if (glxPriv->dibDC)
{
- ret = wglDeleteContext(gc->ctx);
- if (!ret)
- ErrorF("wglDeleteContext error: %s\n", glWinErrorMessage());
- gc->ctx = NULL;
+ // restore the default DIB
+ SelectObject(glxPriv->dibDC, glxPriv->hOldDIB);
+
+ if (!DeleteDC(glxPriv->dibDC))
+ {
+ ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage());
+ }
}
- if (gc->winInfo.hrgn)
+ if (glxPriv->hDIB)
{
- ret = DeleteObject(gc->winInfo.hrgn);
- if (!ret)
- ErrorF("DeleteObject error: %s\n", glWinErrorMessage());
- gc->winInfo.hrgn = NULL;
+ if (!DeleteObject(glxPriv->hDIB))
+ {
+ ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
+ }
+
+ ((PixmapPtr)glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits;
}
- gc->isAttached = 0;
+ GLWIN_DEBUG_MSG("glxWinDestroyDrawable");
+ xfree(glxPriv);
}
-static BOOL glWinAdjustHWND(__GLcontext *gc, WindowPtr pWin)
+static __GLXdrawable *
+glxWinCreateDrawable(__GLXscreen *screen,
+ DrawablePtr pDraw,
+ int type,
+ XID drawId,
+ __GLXconfig *conf)
{
- HDC dc;
- BOOL ret;
- HGLRC newctx;
- HWND oldhwnd;
+ __GLXWinDrawable *glxPriv;
- GLWIN_DEBUG_MSG("glWinAdjustHWND (ctx %p, pWin %p)\n", gc->ctx, pWin);
+ glxPriv = xalloc(sizeof *glxPriv);
- if (pWin == NULL)
- {
- GLWIN_DEBUG_MSG("Deferring until window is created\n");
- return FALSE;
- }
+ if (glxPriv == NULL)
+ return NULL;
- oldhwnd = gc->winInfo.hwnd;
- winGetWindowInfo(pWin, &gc->winInfo);
-
- GLWIN_DEBUG_HWND(gc->winInfo.hwnd);
- if (gc->winInfo.hwnd == NULL)
- {
- GLWIN_DEBUG_MSG("Deferring until window is created\n");
- return FALSE;
- }
+ memset(glxPriv, 0, sizeof *glxPriv);
+
+ if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, drawId, conf)) {
+ xfree(glxPriv);
+ return NULL;
+ }
+
+ glxPriv->base.destroy = glxWinDrawableDestroy;
+ glxPriv->base.swapBuffers = glxWinDrawableSwapBuffers;
+ glxPriv->base.copySubBuffer = glxWinDrawableCopySubBuffer;
+ // glxPriv->base.waitX what are these for?
+ // glxPriv->base.waitGL
+
+ GLWIN_DEBUG_MSG("glxWinCreateDrawable %p", glxPriv);
+
+ return &glxPriv->base;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Texture functions
+ */
+
+static
+int glxWinBindTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *pixmap)
+{
+ ErrorF("glxWinBindTexImage: not implemented\n");
+ return FALSE;
+}
- dc = glWinMakeDC(gc);
-
- if (glWinDebugSettings.dumpDC)
- GLWIN_DEBUG_MSG("Got HDC %p\n", dc);
-
- gc->pixelFormat = ChoosePixelFormat(dc, &gc->pfd);
- if (gc->pixelFormat == 0)
+static
+int glxWinReleaseTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *pixmap)
+{
+ ErrorF(" glxWinReleaseTexImage: not implemented\n");
+ return FALSE;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Lazy update context implementation
+ *
+ * WGL contexts are created for a specific HDC, so we cannot create the WGL
+ * context in glxWinCreateContext(), we must defer creation until the context
+ * is actually used on a specifc drawable which is connected to a native window,
+ * pbuffer or DIB
+ *
+ * The WGL context may be used on other, compatible HDCs, so we don't need to
+ * recreate it for every new native window
+ *
+ * XXX: I wonder why we can't create the WGL context on the screen HDC ?
+ * Basically we assume all HDCs are compatible at the moment: if they are not
+ * we are in a muddle, there was some code in the old implementation to attempt
+ * to transparently migrate a context to a new DC by copying state and sharing
+ * lists with the old one...
+ */
+
+static void
+glxWinSetPixelFormat(__GLXWinContext *gc, HDC hdc, int bppOverride, int drawableTypeOverride)
+{
+ __GLXscreen *screen = gc->base.pGlxScreen;
+ glxWinScreen *winScreen = (glxWinScreen *)screen;
+
+ __GLXconfig *config = gc->base.config;
+ GLXWinConfig *winConfig = (GLXWinConfig *)config;
+
+ GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d", winConfig->pixelFormatIndex);
+
+ /*
+ Normally, we can just use the the pixelFormatIndex corresponding
+ to the fbconfig which has been specified by the client
+ */
+
+ if (!((bppOverride && (bppOverride != (config->redBits + config->greenBits + config->blueBits) ))
+ || ((config->drawableType & drawableTypeOverride) == 0)))
{
- ErrorF("ChoosePixelFormat error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
- }
-
- ret = SetPixelFormat(dc, gc->pixelFormat, &gc->pfd);
- if (!ret) {
- ErrorF("SetPixelFormat error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
- }
-
- newctx = wglCreateContext(dc);
- if (newctx == NULL) {
- ErrorF("wglCreateContext error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
+ if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL))
+ {
+ ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ return;
}
-
- GLWIN_DEBUG_MSG("wglCreateContext (ctx %p)\n", newctx);
- if (!wglShareLists(gc->ctx, newctx))
+ /*
+ However, in certain special cases this pixel format will be incompatible with the
+ use we are going to put it to, so we need to re-evaluate the pixel format to use:
+
+ 1) When PFD_DRAW_TO_BITMAP is set, ChoosePixelFormat() always returns a format with
+ the cColorBits we asked for, so we need to ensure it matches the bpp of the bitmap
+
+ 2) Applications may assume that visuals selected with glXChooseVisual() work with
+ pixmap drawables (there is no attribute to explicitly query for pixmap drawable
+ support as there is for glXChooseFBConfig())
+ (it's arguable this is an error in the application, but we try to make it work)
+
+ pixmap rendering is always slow for us, so we don't want to choose those visuals
+ by default, but if the actual drawable type we're trying to select the context
+ on (drawableTypeOverride) isn't supported by the selected fbConfig, reconsider
+ and see if we can find a suitable one...
+ */
+ ErrorF("glxWinSetPixelFormat: having second thoughts: cColorbits %d, bppOveride %d; config->drawableType %d, drawableTypeOverride %d\n",
+ (config->redBits + config->greenBits + config->blueBits), bppOverride, config->drawableType, drawableTypeOverride);
+
+ if (!winScreen->has_WGL_ARB_pixel_format)
{
- ErrorF("wglShareLists error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
+ PIXELFORMATDESCRIPTOR pfd;
+ int pixelFormat;
+
+ /* convert fbConfig to PFD */
+ if (fbConfigToPixelFormat(gc->base.config, &pfd, drawableTypeOverride))
+ {
+ ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n");
+ return;
+ }
+
+ if (glxWinDebugSettings.dumpPFD)
+ pfdOut(&pfd);
+
+ if (bppOverride)
+ {
+ GLWIN_DEBUG_MSG("glxWinSetPixelFormat: Forcing bpp from %d to %d\n", pfd.cColorBits, bppOverride);
+ pfd.cColorBits = bppOverride;
+ }
+
+ pixelFormat = ChoosePixelFormat(hdc, &pfd);
+ if (pixelFormat == 0)
+ {
+ ErrorF("ChoosePixelFormat error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ GLWIN_DEBUG_MSG("ChoosePixelFormat: chose pixelFormatIndex %d", pixelFormat);
+ ErrorF("ChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", pixelFormat, winConfig->pixelFormatIndex);
+
+ if (!SetPixelFormat(hdc, pixelFormat, &pfd))
+ {
+ ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
+ return;
+ }
}
-
- if (oldhwnd != gc->winInfo.hwnd)
+ else
{
- GLWIN_DEBUG_MSG("Trying wglCopyContext\n");
- if (!wglCopyContext(gc->ctx, newctx, GL_ALL_ATTRIB_BITS))
+ int pixelFormat = fbConfigToPixelFormatIndex(hdc, gc->base.config, drawableTypeOverride, winScreen);
+ if (pixelFormat == 0)
{
- ErrorF("wglCopyContext error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
+ ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ 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;
}
}
+}
+
+static HDC
+glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HDC *hdc, HWND *hwnd)
+{
+ *hdc = NULL;
+ *hwnd = NULL;
- if (!wglDeleteContext(gc->ctx))
+ if (draw == NULL)
{
- ErrorF("wglDeleteContext error: %s\n", glWinErrorMessage());
+ GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc, gc->ctx);
+ return NULL;
}
- gc->ctx = newctx;
+ switch (draw->base.type)
+ {
+ case GLX_DRAWABLE_WINDOW:
+ {
+ winWindowInfoRec winInfo;
+ WindowPtr pWin;
- if (!wglMakeCurrent(dc, gc->ctx)) {
- ErrorF("glMakeCurrent error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
- }
+ pWin = (WindowPtr) draw->base.pDraw;
+ if (pWin == NULL)
+ {
+ GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin);
+ return NULL;
+ }
- ReleaseDC(gc->winInfo.hwnd, dc);
+ winGetWindowInfo(pWin, &winInfo);
+ *hwnd = winInfo.hwnd;
- return TRUE;
-}
+ if (winInfo.hwnd == NULL)
+ {
+ ErrorF("No HWND error: %s\n", glxWinErrorMessage());
+ return NULL;
+ }
-static BOOL glWinCreateContextReal(__GLcontext *gc, WindowPtr pWin)
-{
- HDC dc;
- BOOL ret;
+ *hdc = GetDC(winInfo.hwnd);
- GLWIN_DEBUG_MSG("glWinCreateContextReal (pWin %p)\n", pWin);
+ if (*hdc == NULL)
+ ErrorF("GetDC error: %s\n", glxWinErrorMessage());
- if (pWin == NULL)
+ /* Check if the hwnd has changed... */
+ if (winInfo.hwnd != gc->hwnd)
+ {
+ if (glxWinDebugSettings.enableTrace)
+ GLWIN_DEBUG_HWND(winInfo.hwnd);
+
+ GLWIN_TRACE_MSG("for context %p (native ctx %p), hWnd changed from %p to %p", gc, gc->ctx, gc->hwnd, winInfo.hwnd);
+ gc->hwnd = winInfo.hwnd;
+
+ /* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */
+ glxWinSetPixelFormat(gc, *hdc, 0, GLX_WINDOW_BIT);
+ }
+ }
+ break;
+
+ case GLX_DRAWABLE_PBUFFER:
{
- GLWIN_DEBUG_MSG("Deferring until window is created\n");
- return FALSE;
+ *hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer);
+
+ if (*hdc == NULL)
+ ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage());
}
+ break;
- winGetWindowInfo(pWin, &gc->winInfo);
-
- GLWIN_DEBUG_HWND(gc->winInfo.hwnd);
- if (gc->winInfo.hwnd == NULL)
+ case GLX_DRAWABLE_PIXMAP:
{
- GLWIN_DEBUG_MSG("Deferring until window is created\n");
- return FALSE;
+ *hdc = draw->dibDC;
}
+ break;
-
- dc = glWinMakeDC(gc);
-
- if (glWinDebugSettings.dumpDC)
- GLWIN_DEBUG_MSG("Got HDC %p\n", dc);
-
- gc->pixelFormat = ChoosePixelFormat(dc, &gc->pfd);
- if (gc->pixelFormat == 0)
+ default:
{
- ErrorF("ChoosePixelFormat error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
+ ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n", draw->base.type);
}
-
- ret = SetPixelFormat(dc, gc->pixelFormat, &gc->pfd);
- if (!ret) {
- ErrorF("SetPixelFormat error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
+ }
+
+ if (glxWinDebugSettings.dumpDC)
+ GLWIN_DEBUG_MSG("Got HDC %p", *hdc);
+
+ return *hdc;
+}
+
+static void
+glxWinReleaseDC(HWND hwnd, HDC hdc,__GLXWinDrawable *draw)
+{
+ switch (draw->base.type)
+ {
+ case GLX_DRAWABLE_WINDOW:
+ {
+ ReleaseDC(hwnd, hdc);
}
-
- gc->ctx = wglCreateContext(dc);
- if (gc->ctx == NULL) {
- ErrorF("wglCreateContext error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
+ break;
+
+ case GLX_DRAWABLE_PBUFFER:
+ {
+ if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc))
+ {
+ ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage());
+ }
}
+ break;
- GLWIN_DEBUG_MSG("glWinCreateContextReal (ctx %p)\n", gc->ctx);
+ case GLX_DRAWABLE_PIXMAP:
+ {
+ // don't release DC, the memory DC lives as long as the bitmap
- if (!wglMakeCurrent(dc, gc->ctx)) {
- ErrorF("glMakeCurrent error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
- return FALSE;
+ // We must ensure that all GDI drawing into the bitmap has completed
+ // in case we subsequently access the bits from it
+ GdiFlush();
}
+ break;
- ReleaseDC(gc->winInfo.hwnd, dc);
-
- return TRUE;
+ default:
+ {
+ ErrorF("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n", draw->base.type);
+ }
+ }
}
-static void attach(__GLcontext *gc, __GLdrawablePrivate *glPriv)
+static void
+glxWinDeferredCreateContext(__GLXWinContext *gc, __GLXWinDrawable *draw)
{
- __GLXdrawablePrivate *glxPriv = (__GLXdrawablePrivate *)glPriv->other;
+ HDC dc;
+ HWND hwnd;
+ GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attach context %p to drawable %p", gc, draw);
- GLWIN_DEBUG_MSG("attach (ctx %p)\n", gc->ctx);
-
- if (gc->isAttached)
+ switch (draw->base.type)
+ {
+ case GLX_DRAWABLE_WINDOW:
{
- ErrorF("called attach on an attached context\n");
- return;
+ winWindowInfoRec winInfo;
+ 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);
+
+ winGetWindowInfo(pWin, &winInfo);
+ if (winInfo.hwnd == NULL)
+ {
+ GLWIN_DEBUG_MSG("Deferring until native window is created");
+ return;
+ }
}
+ break;
- if (glxPriv->type == DRAWABLE_WINDOW)
+ case GLX_DRAWABLE_PBUFFER:
{
- WindowPtr pWin = (WindowPtr) glxPriv->pDraw;
- if (pWin == NULL)
- {
- GLWIN_DEBUG_MSG("Deferring ChoosePixelFormat until window is created\n");
- } else
+ if (draw->hPbuffer == NULL)
{
- if (glWinCreateContextReal(gc, pWin))
+ // XXX: which DC are 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");
+ }
+
+ __GLXscreen *screen = gc->base.pGlxScreen;
+ glxWinScreen *winScreen = (glxWinScreen *)screen;
+
+ int pixelFormat = fbConfigToPixelFormatIndex(screenDC, gc->base.config, GLX_DRAWABLE_PBUFFER, winScreen);
+ if (pixelFormat == 0)
{
- gc->isAttached = TRUE;
- GLWIN_DEBUG_MSG("attached\n");
+ ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
+ 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;
-static GLboolean glWinLoseCurrent(__GLcontext *gc)
-{
- GLWIN_TRACE_MSG("glWinLoseCurrent (ctx %p)\n", gc->ctx);
+ case GLX_DRAWABLE_PIXMAP:
+ {
+ if (draw->dibDC == NULL)
+ {
+ BITMAPINFOHEADER bmpHeader = { sizeof(bmpHeader),
+ draw->base.pDraw->width, draw->base.pDraw->height,
+ 1, draw->base.pDraw->bitsPerPixel,
+ BI_RGB};
+ void *pBits;
- __glXLastContext = NULL; /* Mesa does this; why? */
+ 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");
+ }
- return GL_TRUE;
-}
+ draw->dibDC = CreateCompatibleDC(NULL);
+ if (draw->dibDC == NULL)
+ {
+ ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
+ return;
+ }
-/* Context manipulation; return GL_FALSE on failure */
-static GLboolean glWinDestroyContext(__GLcontext *gc)
-{
- GLWIN_DEBUG_MSG("glWinDestroyContext (ctx %p)\n", gc->ctx);
+ draw->hDIB = CreateDIBSection(draw->dibDC, (BITMAPINFO *)&bmpHeader, DIB_RGB_COLORS, &pBits, 0, 0);
+ if (draw->dibDC == NULL)
+ {
+ ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage());
+ return;
+ }
- if (gc != NULL)
+ // 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:
{
- if (gc->isAttached)
- unattach(gc);
- if (gc->dc != NULL)
- DeleteDC(gc->dc);
- free(gc);
+ ErrorF("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", draw->base.type);
+ return;
}
+ }
- return GL_TRUE;
-}
+ dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
+ gc->ctx = wglCreateContext(dc);
+ glxWinReleaseDC(hwnd, dc, draw);
-static GLboolean glWinMakeCurrent(__GLcontext *gc)
-{
- __GLdrawablePrivate *glPriv = gc->interface.imports.getDrawablePrivate(gc);
- BOOL ret;
- HDC dc;
+ if (gc->ctx == NULL)
+ {
+ ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage());
+ return;
+ }
- GLWIN_TRACE_MSG(" (ctx %p)\n", gc->ctx);
+ GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p", gc, gc->ctx, draw);
- if (!gc->isAttached)
- attach(gc, glPriv);
+ // if the native context was created successfully, shareLists if needed
+ if (gc->ctx && gc->shareContext)
+ {
+ GLWIN_DEBUG_MSG("glxWinCreateContextReal shareLists with context %p (native ctx %p)", gc->shareContext, gc->shareContext->ctx);
- if (gc->ctx == NULL) {
- ErrorF("Context is NULL\n");
- return GL_FALSE;
+ if (!wglShareLists(gc->shareContext->ctx, gc->ctx))
+ {
+ ErrorF("wglShareLists error: %s\n", glxWinErrorMessage());
+ }
}
+}
- dc = glWinMakeDC(gc);
- ret = wglMakeCurrent(dc, gc->ctx);
- if (!ret)
- ErrorF("glMakeCurrent error: %s\n", glWinErrorMessage());
- ReleaseDC(gc->winInfo.hwnd, dc);
+/* ---------------------------------------------------------------------- */
+/*
+ * Context functions
+ */
- return ret?GL_TRUE:GL_FALSE;
-}
-static GLboolean glWinShareContext(__GLcontext *gc, __GLcontext *gcShare)
+/* Context manipulation routines should return TRUE on success, FALSE on failure */
+static int
+glxWinContextMakeCurrent(__GLXcontext *base)
{
- GLWIN_DEBUG_MSG("glWinShareContext unimplemented\n");
+ __GLXWinContext *gc = (__GLXWinContext *)base;
+ BOOL ret;
+ HDC drawDC;
+ HDC readDC = NULL;
+ __GLXdrawable *drawPriv;
+ __GLXdrawable *readPriv;
+ HWND hwnd;
+
+ GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc, gc->ctx);
+ glWinCallDelta();
+
+ /* Keep a note of the last active context in the drawable */
+ drawPriv = gc->base.drawPriv;
+ ((__GLXWinDrawable *)drawPriv)->drawContext = gc;
+
+ if (gc->ctx == NULL)
+ {
+ glxWinDeferredCreateContext(gc, (__GLXWinDrawable *)drawPriv);
+ }
- return GL_TRUE;
-}
+ if (gc->ctx == NULL)
+ {
+ ErrorF("glxWinContextMakeCurrent: Native context is NULL\n");
+ return FALSE;
+ }
-static GLboolean glWinCopyContext(__GLcontext *dst, const __GLcontext *src,
- GLuint mask)
-{
- BOOL ret;
+ drawDC = glxWinMakeDC(gc, (__GLXWinDrawable *)drawPriv, &drawDC, &hwnd);
+ if (drawDC == NULL)
+ {
+ ErrorF("glxWinMakeDC failed for drawDC\n");
+ return FALSE;
+ }
- GLWIN_DEBUG_MSG("glWinCopyContext\n");
-
- ret = wglCopyContext(src->ctx, dst->ctx, mask);
- if (!ret)
+ if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv))
{
- ErrorF("wglCopyContext error: %s\n", glWinErrorMessage());
- return GL_FALSE;
+ // XXX: should only occur with WGL_ARB_make_current_read
+ /*
+ 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
+ */
+ readPriv = gc->base.readPriv;
+ readDC = glxWinMakeDC(gc, (__GLXWinDrawable *)readPriv, &readDC, &hwnd);
+ if (readDC == NULL)
+ {
+ ErrorF("glxWinMakeDC failed for readDC\n");
+ glxWinReleaseDC(hwnd, drawDC, (__GLXWinDrawable *)readPriv);
+ return FALSE;
+ }
+
+ ret = wglMakeContextCurrentARBWrapper(drawDC, readDC, gc->ctx);
+ if (!ret)
+ {
+ ErrorF("wglMakeContextCurrent error: %s\n", glxWinErrorMessage());
+ }
+ }
+ else
+ {
+ /* Otherwise, just use wglMakeCurrent */
+ ret = wglMakeCurrent(drawDC, gc->ctx);
+ if (!ret)
+ {
+ ErrorF("wglMakeCurrent error: %s\n", glxWinErrorMessage());
+ }
}
- return GL_TRUE;
+ // apparently make current could fail if the context is current in a different thread,
+ // but that shouldn't be able to happen in the current server...
+
+ glxWinReleaseDC(hwnd, drawDC, (__GLXWinDrawable *)drawPriv);
+ if (readDC)
+ glxWinReleaseDC(hwnd, drawDC, (__GLXWinDrawable *)readPriv);
+
+ return ret;
}
-static GLboolean glWinForceCurrent(__GLcontext *gc)
+static int
+glxWinContextLoseCurrent(__GLXcontext *base)
{
- GLWIN_TRACE_MSG(" (ctx %p)\n", gc->ctx);
+ BOOL ret;
+ __GLXWinContext *gc = (__GLXWinContext *)base;
- return GL_TRUE;
-}
+ GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc, gc->ctx);
+ glWinCallDelta();
-/* Drawing surface notification callbacks */
+ ret = wglMakeCurrent(NULL, NULL); /* We don't need a DC when setting no current context */
+ if (!ret)
+ ErrorF("glxWinContextLoseCurrent error: %s\n", glxWinErrorMessage());
-static GLboolean glWinNotifyResize(__GLcontext *gc)
-{
- GLWIN_DEBUG_MSG("unimplemented glWinNotifyResize");
- return GL_TRUE;
-}
+ __glXLastContext = NULL; /* Mesa does this; why? */
+ // __glXFlushContextCache()
-static void glWinNotifyDestroy(__GLcontext *gc)
-{
- GLWIN_DEBUG_MSG("unimplemented glWinNotifyDestroy");
+ return TRUE;
}
-static void glWinNotifySwapBuffers(__GLcontext *gc)
+static int
+glxWinContextCopy(__GLXcontext *dst_base, __GLXcontext *src_base, unsigned long mask)
{
- GLWIN_DEBUG_MSG("unimplemented glWinNotifySwapBuffers");
+ __GLXWinContext *dst = (__GLXWinContext *)dst_base;
+ __GLXWinContext *src = (__GLXWinContext *)src_base;
+ BOOL ret;
+
+ GLWIN_DEBUG_MSG("glxWinContextCopy");
+
+ ret = wglCopyContext(src->ctx, dst->ctx, mask);
+ if (!ret)
+ {
+ ErrorF("wglCopyContext error: %s\n", glxWinErrorMessage());
+ }
+
+ return ret;
}
-/* Dispatch table override control for external agents like libGLS */
-static struct __GLdispatchStateRec* glWinDispatchExec(__GLcontext *gc)
+static int
+glxWinContextForceCurrent(__GLXcontext *base)
{
- GLWIN_DEBUG_MSG("unimplemented glWinDispatchExec");
- return NULL;
+ /* wglMakeCurrent always flushes the previous context, so this is equivalent to glxWinContextMakeCurrent */
+ return glxWinContextMakeCurrent(base);
}
-static void glWinBeginDispatchOverride(__GLcontext *gc)
+static void
+glxWinContextDestroy(__GLXcontext *base)
{
- GLWIN_DEBUG_MSG("unimplemented glWinBeginDispatchOverride");
+ __GLXWinContext *gc = (__GLXWinContext *)base;
+
+ if (gc != NULL)
+ {
+ GLWIN_DEBUG_MSG("GLXcontext %p destroyed (native ctx %p)", base, gc->ctx);
+
+ if (gc->ctx)
+ {
+ /* It's bad style to delete the context while it's still current */
+ if (wglGetCurrentContext() == gc->ctx)
+ {
+ wglMakeCurrent(NULL, NULL);
+ }
+
+ BOOL ret = wglDeleteContext(gc->ctx);
+ if (!ret)
+ ErrorF("wglDeleteContext error: %s\n", glxWinErrorMessage());
+ gc->ctx = NULL;
+ }
+
+ xfree(gc);
+ }
}
-static void glWinEndDispatchOverride(__GLcontext *gc)
+static __GLXcontext *
+glxWinCreateContext(__GLXscreen *screen,
+ __GLXconfig *modes,
+ __GLXcontext *baseShareContext)
{
- GLWIN_DEBUG_MSG("unimplemented glWinEndDispatchOverride");
+ __GLXWinContext *context;
+ __GLXWinContext *shareContext = (__GLXWinContext *)baseShareContext;
+
+ static __GLXtextureFromPixmap glxWinTextureFromPixmap =
+ {
+ glxWinBindTexImage,
+ glxWinReleaseTexImage
+ };
+
+ context = (__GLXWinContext *)xcalloc(1, sizeof(__GLXWinContext));
+
+ if (!context)
+ return NULL;
+
+ memset(context, 0, sizeof *context);
+ context->base.destroy = glxWinContextDestroy;
+ context->base.makeCurrent = glxWinContextMakeCurrent;
+ context->base.loseCurrent = glxWinContextLoseCurrent;
+ context->base.copy = glxWinContextCopy;
+ context->base.forceCurrent = glxWinContextForceCurrent;
+ context->base.textureFromPixmap = &glxWinTextureFromPixmap;
+ context->base.config = modes;
+ context->base.pGlxScreen = screen;
+
+ // actual native GL context creation is deferred until attach()
+ context->ctx = NULL;
+ context->shareContext = shareContext;
+
+ glWinSetupDispatchTable();
+
+ GLWIN_DEBUG_MSG("GLXcontext %p created", context);
+
+ return &(context->base);
}
-#define DUMP_PFD_FLAG(flag) \
- if (pfd->dwFlags & flag) { \
- ErrorF("%s%s", pipesym, #flag); \
- pipesym = " | "; \
- }
-
-static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd)
-{
- const char *pipesym = ""; /* will be set after first flag dump */
- ErrorF("PIXELFORMATDESCRIPTOR:\n");
- ErrorF("nSize = %u\n", pfd->nSize);
- ErrorF("nVersion = %u\n", pfd->nVersion);
- ErrorF("dwFlags = %lu = {", pfd->dwFlags);
- DUMP_PFD_FLAG(PFD_MAIN_PLANE);
- DUMP_PFD_FLAG(PFD_OVERLAY_PLANE);
- DUMP_PFD_FLAG(PFD_UNDERLAY_PLANE);
- DUMP_PFD_FLAG(PFD_DOUBLEBUFFER);
- DUMP_PFD_FLAG(PFD_STEREO);
- DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW);
- DUMP_PFD_FLAG(PFD_DRAW_TO_BITMAP);
- DUMP_PFD_FLAG(PFD_SUPPORT_GDI);
- DUMP_PFD_FLAG(PFD_SUPPORT_OPENGL);
- DUMP_PFD_FLAG(PFD_GENERIC_FORMAT);
- DUMP_PFD_FLAG(PFD_NEED_PALETTE);
- DUMP_PFD_FLAG(PFD_NEED_SYSTEM_PALETTE);
- DUMP_PFD_FLAG(PFD_SWAP_EXCHANGE);
- DUMP_PFD_FLAG(PFD_SWAP_COPY);
- DUMP_PFD_FLAG(PFD_SWAP_LAYER_BUFFERS);
- DUMP_PFD_FLAG(PFD_GENERIC_ACCELERATED);
- DUMP_PFD_FLAG(PFD_DEPTH_DONTCARE);
- DUMP_PFD_FLAG(PFD_DOUBLEBUFFER_DONTCARE);
- DUMP_PFD_FLAG(PFD_STEREO_DONTCARE);
- ErrorF("}\n");
-
- ErrorF("iPixelType = %hu = %s\n", pfd->iPixelType,
- (pfd->iPixelType == PFD_TYPE_RGBA ? "PFD_TYPE_RGBA" : "PFD_TYPE_COLORINDEX"));
- ErrorF("cColorBits = %hhu\n", pfd->cColorBits);
- ErrorF("cRedBits = %hhu\n", pfd->cRedBits);
- ErrorF("cRedShift = %hhu\n", pfd->cRedShift);
- ErrorF("cGreenBits = %hhu\n", pfd->cGreenBits);
- ErrorF("cGreenShift = %hhu\n", pfd->cGreenShift);
- ErrorF("cBlueBits = %hhu\n", pfd->cBlueBits);
- ErrorF("cBlueShift = %hhu\n", pfd->cBlueShift);
- ErrorF("cAlphaBits = %hhu\n", pfd->cAlphaBits);
- ErrorF("cAlphaShift = %hhu\n", pfd->cAlphaShift);
- ErrorF("cAccumBits = %hhu\n", pfd->cAccumBits);
- ErrorF("cAccumRedBits = %hhu\n", pfd->cAccumRedBits);
- ErrorF("cAccumGreenBits = %hhu\n", pfd->cAccumGreenBits);
- ErrorF("cAccumBlueBits = %hhu\n", pfd->cAccumBlueBits);
- ErrorF("cAccumAlphaBits = %hhu\n", pfd->cAccumAlphaBits);
- ErrorF("cDepthBits = %hhu\n", pfd->cDepthBits);
- ErrorF("cStencilBits = %hhu\n", pfd->cStencilBits);
- ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers);
- ErrorF("iLayerType = %hhu\n", pfd->iLayerType);
- ErrorF("bReserved = %hhu\n", pfd->bReserved);
- ErrorF("dwLayerMask = %lu\n", pfd->dwLayerMask);
- ErrorF("dwVisibleMask = %lu\n", pfd->dwVisibleMask);
- ErrorF("dwDamageMask = %lu\n", pfd->dwDamageMask);
- ErrorF("\n");
-}
+/* ---------------------------------------------------------------------- */
+/*
+ * Utility functions
+ */
-static int makeFormat(__GLcontextModes *mode, PIXELFORMATDESCRIPTOR *pfdret)
+static int
+fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride)
{
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
1, /* version number */
- PFD_DRAW_TO_WINDOW | /* support window */
PFD_SUPPORT_OPENGL, /* support OpenGL */
PFD_TYPE_RGBA, /* RGBA type */
24, /* 24-bit color depth */
@@ -672,72 +1520,49 @@ static int makeFormat(__GLcontextModes *mode, PIXELFORMATDESCRIPTOR *pfdret)
0, /* shift bit ignored */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits ignored */
- 0, /* 32-bit z-buffer */
+ 32, /* 32-bit z-buffer */
0, /* no stencil buffer */
0, /* no auxiliary buffer */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
0, 0, 0 /* layer masks ignored */
- }, *result = &pfd;
+ };
- /* disable anything but rgba. must get rgba to work first */
- if (!mode->rgbMode)
- return -1;
-
- if (mode->stereoMode) {
- result->dwFlags |= PFD_STEREO;
- }
- if (mode->doubleBufferMode) {
- result->dwFlags |= PFD_DOUBLEBUFFER;
- }
+ if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
+ pfd.dwFlags |= PFD_DRAW_TO_WINDOW; /* support window */
- if (mode->colorIndexMode) {
- /* ignored, see above */
- result->iPixelType = PFD_TYPE_COLORINDEX;
- result->cColorBits = mode->redBits + mode->greenBits + mode->blueBits;
- result->cRedBits = mode->redBits;
- result->cRedShift = 0; /* FIXME */
- result->cGreenBits = mode->greenBits;
- result->cGreenShift = 0; /* FIXME */
- result->cBlueBits = mode->blueBits;
- result->cBlueShift = 0; /* FIXME */
- result->cAlphaBits = mode->alphaBits;
- result->cAlphaShift = 0; /* FIXME */
- }
-
- if (mode->rgbMode) {
- result->iPixelType = PFD_TYPE_RGBA;
- result->cColorBits = mode->redBits + mode->greenBits + mode->blueBits;
- result->cRedBits = mode->redBits;
- result->cRedShift = 0; /* FIXME */
- result->cGreenBits = mode->greenBits;
- result->cGreenShift = 0; /* FIXME */
- result->cBlueBits = mode->blueBits;
- result->cBlueShift = 0; /* FIXME */
- result->cAlphaBits = mode->alphaBits;
- result->cAlphaShift = 0; /* FIXME */
- }
+ if ((mode->drawableType | drawableTypeOverride) & GLX_PIXMAP_BIT)
+ pfd.dwFlags |= (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI); /* supports software rendering to bitmap */
- if (mode->haveAccumBuffer) {
- result->cAccumBits = mode->accumRedBits + mode->accumGreenBits
- + mode->accumBlueBits + mode->accumAlphaBits;
- result->cAccumRedBits = mode->accumRedBits;
- result->cAccumGreenBits = mode->accumGreenBits;
- result->cAccumBlueBits = mode->accumBlueBits;
- result->cAccumAlphaBits = mode->accumAlphaBits;
- }
-
- if (mode->haveDepthBuffer) {
- result->cDepthBits = mode->depthBits;
+ if (mode->stereoMode) {
+ pfd.dwFlags |= PFD_STEREO;
}
- if (mode->haveStencilBuffer) {
- result->cStencilBits = mode->stencilBits;
+ if (mode->doubleBufferMode) {
+ pfd.dwFlags |= PFD_DOUBLEBUFFER;
}
- /* result->cAuxBuffers = mode->numAuxBuffers; */
-
- /* mode->level ignored */
-
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = mode->redBits + mode->greenBits + mode->blueBits;
+ pfd.cRedBits = mode->redBits;
+ pfd.cRedShift = 0; /* FIXME */
+ pfd.cGreenBits = mode->greenBits;
+ pfd.cGreenShift = 0; /* FIXME */
+ pfd.cBlueBits = mode->blueBits;
+ pfd.cBlueShift = 0; /* FIXME */
+ pfd.cAlphaBits = mode->alphaBits;
+ pfd.cAlphaShift = 0; /* FIXME */
+
+ pfd.cAccumBits = mode->accumRedBits + mode->accumGreenBits + mode->accumBlueBits + mode->accumAlphaBits;
+ pfd.cAccumRedBits = mode->accumRedBits;
+ pfd.cAccumGreenBits = mode->accumGreenBits;
+ pfd.cAccumBlueBits = mode->accumBlueBits;
+ pfd.cAccumAlphaBits = mode->accumAlphaBits;
+
+ pfd.cDepthBits = mode->depthBits;
+ pfd.cStencilBits = mode->stencilBits;
+ pfd.cAuxBuffers = mode->numAuxBuffers;
+
+ /* mode->level ? */
/* mode->pixmapMode ? */
*pfdret = pfd;
@@ -745,861 +1570,644 @@ static int makeFormat(__GLcontextModes *mode, PIXELFORMATDESCRIPTOR *pfdret)
return 0;
}
-static __GLinterface *glWinCreateContext(__GLimports *imports,
- __GLcontextModes *mode,
- __GLinterface *shareGC)
+#define SET_ATTR_VALUE(attr, value) { attribList[i++] = attr; attribList[i++] = value; assert(i < NUM_ELEMENTS(attribList)); }
+
+static int
+fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen)
{
- __GLcontext *result;
+ UINT numFormats;
+ unsigned int i = 0;
+
+ /* convert fbConfig to attr-value list */
+ int attribList[60];
+
+ SET_ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, TRUE);
+ SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, (mode->visualType == GLX_TRUE_COLOR) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB);
+ SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, (mode->visualType == GLX_TRUE_COLOR) ? mode->rgbBits : mode->indexBits);
+ SET_ATTR_VALUE(WGL_RED_BITS_ARB, mode->redBits);
+ SET_ATTR_VALUE(WGL_GREEN_BITS_ARB, mode->greenBits);
+ SET_ATTR_VALUE(WGL_BLUE_BITS_ARB, mode->blueBits);
+ SET_ATTR_VALUE(WGL_ALPHA_BITS_ARB, mode->alphaBits);
+ SET_ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, mode->accumRedBits);
+ SET_ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, mode->accumGreenBits);
+ SET_ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, mode->accumBlueBits);
+ SET_ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, mode->accumAlphaBits);
+ SET_ATTR_VALUE(WGL_DEPTH_BITS_ARB, mode->depthBits);
+ SET_ATTR_VALUE(WGL_STENCIL_BITS_ARB, mode->stencilBits);
+ SET_ATTR_VALUE(WGL_AUX_BUFFERS_ARB, mode->numAuxBuffers);
+
+ if (mode->doubleBufferMode)
+ SET_ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, TRUE);
+
+ if (mode->stereoMode)
+ SET_ATTR_VALUE(WGL_STEREO_ARB, TRUE);
+
+ // Some attributes are only added to the list if the value requested is not 'don't care', as exactly matching that is daft..
+ if (mode->swapMethod == GLX_SWAP_EXCHANGE_OML)
+ SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB);
+
+ if (mode->swapMethod == GLX_SWAP_COPY_OML)
+ SET_ATTR_VALUE(WGL_SWAP_COPY_ARB, TRUE);
+
+ // XXX: this should probably be the other way around, but that messes up drawableTypeOverride
+ if (mode->visualRating == GLX_SLOW_VISUAL_EXT)
+ SET_ATTR_VALUE(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB);
+
+ // must support all the drawable types the mode supports
+ if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
+ SET_ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB,TRUE);
+
+ // XXX: this is a horrible hacky heuristic, in fact this whole drawableTypeOverride thing is a bad idea
+ // try to avoid asking for formats which don't exist (by not asking for all when adjusting the config to include the drawableTypeOverride)
+ if (drawableTypeOverride == GLX_WINDOW_BIT)
+ {
+ if (mode->drawableType & GLX_PIXMAP_BIT)
+ SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE);
- GLWIN_DEBUG_MSG("glWinCreateContext\n");
+ if (mode->drawableType & GLX_PBUFFER_BIT)
+ if (winScreen->has_WGL_ARB_pbuffer)
+ SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
+ }
+ else
+ {
+ if (drawableTypeOverride & GLX_PIXMAP_BIT)
+ SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE);
- result = (__GLcontext *)calloc(1, sizeof(__GLcontext));
- if (!result)
- return NULL;
+ if (drawableTypeOverride & GLX_PBUFFER_BIT)
+ if (winScreen->has_WGL_ARB_pbuffer)
+ SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
+ }
- result->interface.imports = *imports;
- result->interface.exports = glWinExports;
+ SET_ATTR_VALUE(0, 0); // terminator
- if (makeFormat(mode, &result->pfd))
- {
- ErrorF("makeFormat failed\n");
- free(result);
- return NULL;
- }
+ /* choose the first match */
+ {
+ int pixelFormatIndex;
- if (glWinDebugSettings.dumpPFD)
- pfdOut(&result->pfd);
+ if (!wglChoosePixelFormatARBWrapper(hdc, attribList, NULL, 1, &pixelFormatIndex, &numFormats))
+ {
+ ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage());
+ }
+ else
+ {
+ if (numFormats > 0)
+ {
+ GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d)", pixelFormatIndex);
+ return pixelFormatIndex;
+ }
+ else
+ ErrorF("wglChoosePixelFormat couldn't decide\n");
+ }
+ }
- GLWIN_DEBUG_MSG("glWinCreateContext done\n");
- return (__GLinterface *)result;
+ return 0;
}
-Bool
-glWinRealizeWindow(WindowPtr pWin)
-{
- /* If this window has GL contexts, tell them to reattach */
- /* reattaching is bad: display lists and parameters get lost */
- Bool result;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- glWinScreenRec *screenPriv = &glWinScreens[pScreen->myNum];
- __GLXdrawablePrivate *glxPriv;
+/* ---------------------------------------------------------------------- */
- GLWIN_DEBUG_MSG("glWinRealizeWindow\n");
+#define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask))
- /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */
- pScreen->RealizeWindow = screenPriv->RealizeWindow;
- result = pScreen->RealizeWindow(pWin);
- pScreen->RealizeWindow = glWinRealizeWindow;
-
- /* Re-attach this window's GL contexts, if any. */
- glxPriv = __glXFindDrawablePrivate(pWin->drawable.id);
- if (glxPriv) {
- __GLXcontext *gx;
- __GLcontext *gc;
- __GLdrawablePrivate *glPriv = &glxPriv->glPriv;
- GLWIN_DEBUG_MSG("glWinRealizeWindow is GL drawable!\n");
-
- /* GL contexts bound to this window for drawing */
- for (gx = glxPriv->drawGlxc; gx != NULL; gx = gx->next) {
- gc = (__GLcontext *)gx->gc;
- if (gc->isAttached)
-#if 1
- {
- GLWIN_DEBUG_MSG("context is already bound! Adjusting HWND.\n");
- glWinAdjustHWND(gc, pWin);
- continue;
- }
-#else
- unattach(gc);
-#endif
- attach(gc, glPriv);
- }
+//
+// Create the GLXconfigs using DescribePixelFormat()
+//
+static void
+glxWinCreateConfigs(HDC hdc, glxWinScreen *screen)
+{
+ GLXWinConfig *c, *result, *prev = NULL;
+ int numConfigs = 0;
+ int i = 0;
+ int n = 0;
+ PIXELFORMATDESCRIPTOR pfd;
- /* GL contexts bound to this window for reading */
- for (gx = glxPriv->readGlxc; gx != NULL; gx = gx->next) {
- gc = (__GLcontext *)gx->gc;
- if (gc->isAttached)
-#if 1
- {
- GLWIN_DEBUG_MSG("context is already bound! Adjusting HWND.\n");
- glWinAdjustHWND(gc, pWin);
- continue;
- }
-#else
- unattach(gc);
-#endif
- attach(gc, glPriv);
- }
- }
+ GLWIN_DEBUG_MSG("glxWinCreateConfigs");
- return result;
-}
+ screen->base.numFBConfigs = 0;
+ screen->base.fbconfigs = NULL;
+ // get the number of pixelformats
+ numConfigs = DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
+ GLWIN_DEBUG_MSG("DescribePixelFormat says %d possible pixel formats", numConfigs);
-void
-glWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- glWinScreenRec *screenPriv = &glWinScreens[pScreen->myNum];
- __GLXdrawablePrivate *glxPriv;
-
- GLWIN_TRACE_MSG(" (pWindow %p)\n", pWindow);
-
- /* Check if the window is attached and discard any drawing request */
- glxPriv = __glXFindDrawablePrivate(pWindow->drawable.id);
- if (glxPriv) {
- __GLXcontext *gx;
-
- /* GL contexts bound to this window for drawing */
- for (gx = glxPriv->drawGlxc; gx != NULL; gx = gx->next) {
-/*
- GLWIN_DEBUG_MSG("glWinCopyWindow - calling glDrawBuffer\n");
- glDrawBuffer(GL_FRONT);
- */
-
- return;
- }
+ /* alloc */
+ result = xalloc(sizeof(GLXWinConfig) * numConfigs);
- /* GL contexts bound to this window for reading */
- for (gx = glxPriv->readGlxc; gx != NULL; gx = gx->next) {
- return;
- }
+ if (NULL == result)
+ {
+ return;
}
- GLWIN_DEBUG_MSG("glWinCopyWindow - passing to hw layer\n");
+ memset(result, 0, sizeof(GLXWinConfig) * numConfigs);
+ n = 0;
- pScreen->CopyWindow = screenPriv->CopyWindow;
- pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
- pScreen->CopyWindow = glWinCopyWindow;
-}
+ /* fill in configs */
+ for (i = 0; i < numConfigs; i++)
+ {
+ int rc;
-Bool
-glWinUnrealizeWindow(WindowPtr pWin)
-{
- /* If this window has GL contexts, tell them to unattach */
- Bool result;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- glWinScreenRec *screenPriv = &glWinScreens[pScreen->myNum];
- __GLXdrawablePrivate *glxPriv;
-
- GLWIN_DEBUG_MSG("glWinUnrealizeWindow\n");
-
- /* The Aqua window may have already been destroyed (windows
- * are unrealized from top down)
- */
-
- /* Unattach this window's GL contexts, if any. */
- glxPriv = __glXFindDrawablePrivate(pWin->drawable.id);
- if (glxPriv) {
- __GLXcontext *gx;
- __GLcontext *gc;
- GLWIN_DEBUG_MSG("glWinUnealizeWindow is GL drawable!\n");
-
- /* GL contexts bound to this window for drawing */
- for (gx = glxPriv->drawGlxc; gx != NULL; gx = gx->next) {
- gc = (__GLcontext *)gx->gc;
- unattach(gc);
- }
+ c = &(result[i]);
+ c->base.next = NULL;
+ c->pixelFormatIndex = i+1;
+
+ rc = DescribePixelFormat(hdc, i+1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
- /* GL contexts bound to this window for reading */
- for (gx = glxPriv->readGlxc; gx != NULL; gx = gx->next) {
- gc = (__GLcontext *)gx->gc;
- unattach(gc);
+ if (!rc)
+ {
+ ErrorF("DescribePixelFormat failed for index %d, error %s\n", i+1, glxWinErrorMessage());
+ break;
}
- }
- pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow;
- result = pScreen->UnrealizeWindow(pWin);
- pScreen->UnrealizeWindow = glWinUnrealizeWindow;
+ if (glxWinDebugSettings.dumpPFD)
+ pfdOut(&pfd);
- return result;
-}
+ if (!(pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP)) || !(pfd.dwFlags & PFD_SUPPORT_OPENGL))
+ {
+ GLWIN_DEBUG_MSG("pixelFormat %d has unsuitable flags 0x%08lx, skipping", i+1, pfd.dwFlags);
+ continue;
+ }
+ c->base.doubleBufferMode = (pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
+ c->base.stereoMode = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE;
-/*
- * In the case the driver has no GLX visuals we'll use these.
- * [0] = RGB, double buffered
- * [1] = RGB, double buffered, stencil, accum
- */
-/* Originally copied from Mesa */
+ c->base.redBits = pfd.cRedBits;
+ c->base.greenBits = pfd.cGreenBits;
+ c->base.blueBits = pfd.cBlueBits;
+ c->base.alphaBits = pfd.cAlphaBits;
-static int numConfigs = 0;
-static __GLXvisualConfig *visualConfigs = NULL;
-static void **visualPrivates = NULL;
+ c->base.redMask = BITS_AND_SHIFT_TO_MASK(pfd.cRedBits, pfd.cRedShift);
+ c->base.greenMask = BITS_AND_SHIFT_TO_MASK(pfd.cGreenBits, pfd.cGreenShift);
+ c->base.blueMask = BITS_AND_SHIFT_TO_MASK(pfd.cBlueBits, pfd.cBlueShift);
+ c->base.alphaMask = BITS_AND_SHIFT_TO_MASK(pfd.cAlphaBits, pfd.cAlphaShift);
-#define NUM_FALLBACK_CONFIGS 2
-static __GLXvisualConfig FallbackConfigs[NUM_FALLBACK_CONFIGS] = {
- {
- -1, /* vid */
- -1, /* class */
- True, /* rgba */
- -1, -1, -1, 0, /* rgba sizes */
- -1, -1, -1, 0, /* rgba masks */
- 0, 0, 0, 0, /* rgba accum sizes */
- True, /* doubleBuffer */
- False, /* stereo */
- -1, /* bufferSize */
- 16, /* depthSize */
- 0, /* stencilSize */
- 0, /* auxBuffers */
- 0, /* level */
- GLX_NONE_EXT, /* visualRating */
- 0, /* transparentPixel */
- 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */
- 0 /* transparentIndex */
- },
- {
- -1, /* vid */
- -1, /* class */
- True, /* rgba */
- -1, -1, -1, 0, /* rgba sizes */
- -1, -1, -1, 0, /* rgba masks */
- 16, 16, 16, 0, /* rgba accum sizes */
- True, /* doubleBuffer */
- False, /* stereo */
- -1, /* bufferSize */
- 16, /* depthSize */
- 8, /* stencilSize */
- 0, /* auxBuffers */
- 0, /* level */
- GLX_NONE_EXT, /* visualRating */
- 0, /* transparentPixel */
- 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */
- 0 /* transparentIndex */
- }
-};
+ c->base.rgbBits = pfd.cColorBits;
-static __GLXvisualConfig NullConfig = {
- -1, /* vid */
- -1, /* class */
- False, /* rgba */
- -1, -1, -1, 0, /* rgba sizes */
- -1, -1, -1, 0, /* rgba masks */
- 0, 0, 0, 0, /* rgba accum sizes */
- False, /* doubleBuffer */
- False, /* stereo */
- -1, /* bufferSize */
- 16, /* depthSize */
- 0, /* stencilSize */
- 0, /* auxBuffers */
- 0, /* level */
- GLX_NONE_EXT, /* visualRating */
- 0, /* transparentPixel */
- 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */
- 0 /* transparentIndex */
-};
+ if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
+ {
+ c->base.indexBits = pfd.cColorBits;
+ }
+ else
+ {
+ c->base.indexBits = 0;
+ }
-static inline int count_bits(uint32_t x)
-{
- x = x - ((x >> 1) & 0x55555555);
- x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
- x = (x + (x >> 4)) & 0x0f0f0f0f;
- x = x + (x >> 8);
- x = x + (x >> 16);
- return x & 63;
-}
+ c->base.accumRedBits = pfd.cAccumRedBits;
+ c->base.accumGreenBits = pfd.cAccumGreenBits;
+ c->base.accumBlueBits = pfd.cAccumBlueBits;
+ c->base.accumAlphaBits = pfd.cAccumAlphaBits;
+ // pfd.cAccumBits;
-/* Mostly copied from Mesa's xf86glx.c */
-static Bool init_visuals(int *nvisualp, VisualPtr *visualp,
- VisualID *defaultVisp,
- int ndepth, DepthPtr pdepth,
- int rootDepth)
-{
- int numRGBconfigs;
- int numCIconfigs;
- int numVisuals = *nvisualp;
- int numNewVisuals;
- int numNewConfigs;
- VisualPtr pVisual = *visualp;
- VisualPtr pVisualNew = NULL;
- VisualID *orig_vid = NULL;
- __GLcontextModes *modes = NULL;
- __GLXvisualConfig *pNewVisualConfigs = NULL;
- void **glXVisualPriv;
- void **pNewVisualPriv;
- int found_default;
- int i, j, k;
-
- GLWIN_DEBUG_MSG("init_visuals\n");
-
- if (numConfigs > 0)
- numNewConfigs = numConfigs;
- else
- numNewConfigs = NUM_FALLBACK_CONFIGS;
+ c->base.depthBits = pfd.cDepthBits;
+ c->base.stencilBits = pfd.cStencilBits;
+ c->base.numAuxBuffers = pfd.cAuxBuffers;
- /* Alloc space for the list of new GLX visuals */
- pNewVisualConfigs = (__GLXvisualConfig *)
- __glXMalloc(numNewConfigs * sizeof(__GLXvisualConfig));
- if (!pNewVisualConfigs) {
- return FALSE;
- }
+ // pfd.iLayerType; // ignored
+ c->base.level = 0;
+ // pfd.dwLayerMask; // ignored
+ // pfd.dwDamageMask; // ignored
- /* Alloc space for the list of new GLX visual privates */
- pNewVisualPriv = (void **) __glXMalloc(numNewConfigs * sizeof(void *));
- if (!pNewVisualPriv) {
- __glXFree(pNewVisualConfigs);
- return FALSE;
- }
+ c->base.pixmapMode = 0;
+ c->base.visualID = -1; // will be set by __glXScreenInit()
- /*
- ** If SetVisualConfigs was not called, then use default GLX
- ** visual configs.
- */
- if (numConfigs == 0) {
- memcpy(pNewVisualConfigs, FallbackConfigs,
- NUM_FALLBACK_CONFIGS * sizeof(__GLXvisualConfig));
- memset(pNewVisualPriv, 0, NUM_FALLBACK_CONFIGS * sizeof(void *));
- }
- else {
- /* copy driver's visual config info */
- for (i = 0; i < numConfigs; i++) {
- pNewVisualConfigs[i] = visualConfigs[i];
- pNewVisualPriv[i] = visualPrivates[i];
+ /* EXT_visual_rating / GLX 1.2 */
+ if (pfd.dwFlags & PFD_GENERIC_FORMAT)
+ {
+ c->base.visualRating = GLX_SLOW_VISUAL_EXT;
+ }
+ else
+ {
+ // PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated...
+ c->base.visualRating = GLX_NONE_EXT;
}
- }
-
- /* Count the number of RGB and CI visual configs */
- numRGBconfigs = 0;
- numCIconfigs = 0;
- for (i = 0; i < numNewConfigs; i++) {
- if (pNewVisualConfigs[i].rgba)
- numRGBconfigs++;
- else
- numCIconfigs++;
- }
-
- /* Count the total number of visuals to compute */
- numNewVisuals = 0;
- for (i = 0; i < numVisuals; i++) {
- int count;
-
- count = ((pVisual[i].class == TrueColor
- || pVisual[i].class == DirectColor)
- ? numRGBconfigs : numCIconfigs);
- if (count == 0)
- count = 1; /* preserve the existing visual */
- numNewVisuals += count;
- }
+ /* EXT_visual_info / GLX 1.2 */
+ if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
+ {
+ c->base.visualType = GLX_STATIC_COLOR;
+ }
+ else
+ {
+ c->base.visualType = GLX_TRUE_COLOR;
+ }
- /* Reset variables for use with the next screen/driver's visual configs */
- visualConfigs = NULL;
- numConfigs = 0;
+ // pfd.dwVisibleMask; ???
+ c->base.transparentPixel = GLX_NONE;
+ c->base.transparentRed = GLX_NONE;
+ c->base.transparentGreen = GLX_NONE;
+ c->base.transparentBlue = GLX_NONE;
+ c->base.transparentAlpha = GLX_NONE;
+ c->base.transparentIndex = GLX_NONE;
+
+ /* ARB_multisample / SGIS_multisample */
+ c->base.sampleBuffers = 0;
+ c->base.samples = 0;
+
+ /* SGIX_fbconfig / GLX 1.3 */
+ c->base.drawableType = (((pfd.dwFlags & PFD_DRAW_TO_WINDOW) ? GLX_WINDOW_BIT : 0)
+ | ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) ? GLX_PIXMAP_BIT : 0));
+ c->base.renderType = GLX_RGBA_BIT;
+ c->base.xRenderable = GL_TRUE;
+ c->base.fbconfigID = -1; // will be set by __glXScreenInit()
+
+ /* SGIX_pbuffer / GLX 1.3 */
+ // XXX: How can we find these values out ???
+ c->base.maxPbufferWidth = -1;
+ c->base.maxPbufferHeight = -1;
+ c->base.maxPbufferPixels = -1;
+ c->base.optimalPbufferWidth = 0; // there is no optimal value
+ c->base.optimalPbufferHeight = 0;
+
+ /* SGIX_visual_select_group */
+ // arrange for visuals with the best acceleration to be preferred in selection
+ switch (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
+ {
+ case 0:
+ c->base.visualSelectGroup = 2;
+ break;
- /* Alloc temp space for the list of orig VisualIDs for each new visual */
- orig_vid = (VisualID *)__glXMalloc(numNewVisuals * sizeof(VisualID));
- if (!orig_vid) {
- __glXFree(pNewVisualPriv);
- __glXFree(pNewVisualConfigs);
- return FALSE;
- }
+ case PFD_GENERIC_ACCELERATED:
+ c->base.visualSelectGroup = 1;
+ break;
- /* Alloc space for the list of glXVisuals */
- modes = _gl_context_modes_create(numNewVisuals, sizeof(__GLcontextModes));
- if (modes == NULL) {
- __glXFree(orig_vid);
- __glXFree(pNewVisualPriv);
- __glXFree(pNewVisualConfigs);
- return FALSE;
- }
+ case PFD_GENERIC_FORMAT:
+ c->base.visualSelectGroup = 0;
+ break;
- /* Alloc space for the list of glXVisualPrivates */
- glXVisualPriv = (void **)__glXMalloc(numNewVisuals * sizeof(void *));
- if (!glXVisualPriv) {
- _gl_context_modes_destroy( modes );
- __glXFree(orig_vid);
- __glXFree(pNewVisualPriv);
- __glXFree(pNewVisualConfigs);
- return FALSE;
- }
+ default:
+ ;
+ // "can't happen"
+ }
- /* Alloc space for the new list of the X server's visuals */
- pVisualNew = (VisualPtr)__glXMalloc(numNewVisuals * sizeof(VisualRec));
- if (!pVisualNew) {
- __glXFree(glXVisualPriv);
- _gl_context_modes_destroy( modes );
- __glXFree(orig_vid);
- __glXFree(pNewVisualPriv);
- __glXFree(pNewVisualConfigs);
- return FALSE;
- }
+ /* OML_swap_method */
+ if (pfd.dwFlags & PFD_SWAP_EXCHANGE)
+ c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
+ else if (pfd.dwFlags & PFD_SWAP_COPY)
+ c->base.swapMethod = GLX_SWAP_COPY_OML;
+ else
+ c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
- /* Initialize the new visuals */
- found_default = FALSE;
- glWinScreens[screenInfo.numScreens-1].modes = modes;
- for (i = j = 0; i < numVisuals; i++) {
- int is_rgb = (pVisual[i].class == TrueColor ||
- pVisual[i].class == DirectColor);
+ /* EXT_import_context */
+ c->base.screen = screen->base.pScreen->myNum;
- if (!is_rgb)
- {
- /* We don't support non-rgb visuals for GL. But we don't
- want to remove them either, so just pass them through
- with null glX configs */
+ /* EXT_texture_from_pixmap */
+ c->base.bindToTextureRgb = -1;
+ c->base.bindToTextureRgba = -1;
+ c->base.bindToMipmapTexture = -1;
+ c->base.bindToTextureTargets = -1;
+ c->base.yInverted = -1;
- pVisualNew[j] = pVisual[i];
- pVisualNew[j].vid = FakeClientID(0);
+ n++;
- /* Check for the default visual */
- if (!found_default && pVisual[i].vid == *defaultVisp) {
- *defaultVisp = pVisualNew[j].vid;
- found_default = TRUE;
- }
+ // update previous config to point to this config
+ if (prev)
+ prev->base.next = &(c->base);
- /* Save the old VisualID */
- orig_vid[j] = pVisual[i].vid;
+ prev = c;
+ }
- /* Initialize the glXVisual */
- _gl_copy_visual_to_context_mode( modes, & NullConfig );
- modes->visualID = pVisualNew[j].vid;
+ GLWIN_DEBUG_MSG("found %d pixelFormats suitable for conversion to fbConfigs", n);
- j++;
+ screen->base.numFBConfigs = n;
+ screen->base.fbconfigs = &(result->base);
+}
- continue;
+// helper function to access an attribute value from an attribute value array by attribute
+static
+int getAttrValue(const int attrs[], int values[], unsigned int num, int attr, int fallback)
+{
+ unsigned int i;
+ for (i = 0; i < num; i++)
+ {
+ if (attrs[i] == attr)
+ {
+ GLWIN_TRACE_MSG("getAttrValue attr 0x%x, value %d", attr, values[i]);
+ return values[i];
}
+ }
- for (k = 0; k < numNewConfigs; k++) {
- if (pNewVisualConfigs[k].rgba != is_rgb)
- continue;
-
- assert( modes != NULL );
+ ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n", attr, fallback);
+ return fallback;
+}
- /* Initialize the new visual */
- pVisualNew[j] = pVisual[i];
- pVisualNew[j].vid = FakeClientID(0);
+//
+// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
+//
+static void
+glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen)
+{
+ GLXWinConfig *c, *result, *prev = NULL;
+ int i = 0;
+ int n = 0;
- /* Check for the default visual */
- if (!found_default && pVisual[i].vid == *defaultVisp) {
- *defaultVisp = pVisualNew[j].vid;
- found_default = TRUE;
- }
+ const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB;
+ int numConfigs;
- /* Save the old VisualID */
- orig_vid[j] = pVisual[i].vid;
-
- /* Initialize the glXVisual */
- _gl_copy_visual_to_context_mode( modes, & pNewVisualConfigs[k] );
- modes->visualID = pVisualNew[j].vid;
-
- /*
- * If the class is -1, then assume the X visual information
- * is identical to what GLX needs, and take them from the X
- * visual. NOTE: if class != -1, then all other fields MUST
- * be initialized.
- */
- if (modes->visualType == GLX_NONE) {
- modes->visualType = _gl_convert_from_x_visual_type( pVisual[i].class );
- modes->redBits = count_bits(pVisual[i].redMask);
- modes->greenBits = count_bits(pVisual[i].greenMask);
- modes->blueBits = count_bits(pVisual[i].blueMask);
- modes->alphaBits = modes->alphaBits;
- modes->redMask = pVisual[i].redMask;
- modes->greenMask = pVisual[i].greenMask;
- modes->blueMask = pVisual[i].blueMask;
- modes->alphaMask = modes->alphaMask;
- modes->rgbBits = (is_rgb)
- ? (modes->redBits + modes->greenBits +
- modes->blueBits + modes->alphaBits)
- : rootDepth;
- }
+ int attrs[50];
+ unsigned int num_attrs = 0;
- /* Save the device-dependent private for this visual */
- glXVisualPriv[j] = pNewVisualPriv[k];
+ GLWIN_DEBUG_MSG("glxWinCreateConfigsExt");
- j++;
- modes = modes->next;
- }
- }
+ screen->base.numFBConfigs = 0;
+ screen->base.fbconfigs = NULL;
- assert(j <= numNewVisuals);
-
- /* Save the GLX visuals in the screen structure */
- glWinScreens[screenInfo.numScreens-1].num_vis = numNewVisuals;
- glWinScreens[screenInfo.numScreens-1].priv = glXVisualPriv;
-
- /* Set up depth's VisualIDs */
- for (i = 0; i < ndepth; i++) {
- int numVids = 0;
- VisualID *pVids = NULL;
- int k, n = 0;
-
- /* Count the new number of VisualIDs at this depth */
- for (j = 0; j < pdepth[i].numVids; j++)
- for (k = 0; k < numNewVisuals; k++)
- if (pdepth[i].vids[j] == orig_vid[k])
- numVids++;
-
- /* Allocate a new list of VisualIDs for this depth */
- pVids = (VisualID *)__glXMalloc(numVids * sizeof(VisualID));
-
- /* Initialize the new list of VisualIDs for this depth */
- for (j = 0; j < pdepth[i].numVids; j++)
- for (k = 0; k < numNewVisuals; k++)
- if (pdepth[i].vids[j] == orig_vid[k])
- pVids[n++] = pVisualNew[k].vid;
-
- /* Update this depth's list of VisualIDs */
- __glXFree(pdepth[i].vids);
- pdepth[i].vids = pVids;
- pdepth[i].numVids = numVids;
+ if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs))
+ {
+ ErrorF("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n", glxWinErrorMessage());
+ return;
}
- /* Update the X server's visuals */
- *nvisualp = numNewVisuals;
- *visualp = pVisualNew;
+ GLWIN_DEBUG_MSG("wglGetPixelFormatAttribivARB says %d possible pixel formats", numConfigs);
- /* Free the old list of the X server's visuals */
- __glXFree(pVisual);
+ /* alloc */
+ result = xalloc(sizeof(GLXWinConfig) * numConfigs);
- /* Clean up temporary allocations */
- __glXFree(orig_vid);
- __glXFree(pNewVisualPriv);
- __glXFree(pNewVisualConfigs);
-
- /* Free the private list created by DDX HW driver */
- if (visualPrivates)
- xfree(visualPrivates);
- visualPrivates = NULL;
+ if (NULL == result)
+ {
+ return;
+ }
- return TRUE;
-}
+ memset(result, 0, sizeof(GLXWinConfig) * numConfigs);
+ n = 0;
+
+#define ADD_ATTR(a) { attrs[num_attrs++] = a; assert(num_attrs < NUM_ELEMENTS(attrs)); }
+
+ ADD_ATTR(WGL_DRAW_TO_WINDOW_ARB);
+ ADD_ATTR(WGL_DRAW_TO_BITMAP_ARB);
+ ADD_ATTR(WGL_ACCELERATION_ARB);
+ ADD_ATTR(WGL_SWAP_LAYER_BUFFERS_ARB);
+ ADD_ATTR(WGL_NUMBER_OVERLAYS_ARB);
+ ADD_ATTR(WGL_NUMBER_UNDERLAYS_ARB);
+ ADD_ATTR(WGL_TRANSPARENT_ARB);
+ ADD_ATTR(WGL_TRANSPARENT_RED_VALUE_ARB);
+ ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB);
+ ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB);
+ ADD_ATTR(WGL_TRANSPARENT_ALPHA_VALUE_ARB);
+ ADD_ATTR(WGL_SUPPORT_OPENGL_ARB);
+ ADD_ATTR(WGL_DOUBLE_BUFFER_ARB);
+ ADD_ATTR(WGL_STEREO_ARB);
+ ADD_ATTR(WGL_PIXEL_TYPE_ARB);
+ ADD_ATTR(WGL_COLOR_BITS_ARB);
+ ADD_ATTR(WGL_RED_BITS_ARB);
+ ADD_ATTR(WGL_RED_SHIFT_ARB);
+ ADD_ATTR(WGL_GREEN_BITS_ARB);
+ ADD_ATTR(WGL_GREEN_SHIFT_ARB);
+ ADD_ATTR(WGL_BLUE_BITS_ARB);
+ ADD_ATTR(WGL_BLUE_SHIFT_ARB);
+ ADD_ATTR(WGL_ALPHA_BITS_ARB);
+ ADD_ATTR(WGL_ALPHA_SHIFT_ARB);
+ ADD_ATTR(WGL_ACCUM_RED_BITS_ARB);
+ ADD_ATTR(WGL_ACCUM_GREEN_BITS_ARB);
+ ADD_ATTR(WGL_ACCUM_BLUE_BITS_ARB);
+ ADD_ATTR(WGL_ACCUM_ALPHA_BITS_ARB);
+ ADD_ATTR(WGL_DEPTH_BITS_ARB);
+ ADD_ATTR(WGL_STENCIL_BITS_ARB);
+ ADD_ATTR(WGL_AUX_BUFFERS_ARB);
+ ADD_ATTR(WGL_SWAP_METHOD_ARB);
+
+ if (screen->has_WGL_ARB_multisample)
+ {
+ // we may not query these attrs if WGL_ARB_multisample is not offered
+ ADD_ATTR(WGL_SAMPLE_BUFFERS_ARB);
+ ADD_ATTR(WGL_SAMPLES_ARB);
+ }
+ if (screen->has_WGL_ARB_render_texture)
+ {
+ // we may not query these attrs if WGL_ARB_render_texture is not offered
+ ADD_ATTR(WGL_BIND_TO_TEXTURE_RGB_ARB);
+ ADD_ATTR(WGL_BIND_TO_TEXTURE_RGBA_ARB);
+ }
-static void fixup_visuals(int screen)
-{
- ScreenPtr pScreen = screenInfo.screens[screen];
- glWinScreenRec *pScr = &glWinScreens[screen];
- __GLcontextModes *modes;
- int j;
-
- GLWIN_DEBUG_MSG("fixup_visuals\n");
-
- for (modes = pScr->modes; modes != NULL; modes = modes->next ) {
- const int vis_class = _gl_convert_to_x_visual_type( modes->visualType );
- const int nplanes = (modes->rgbBits - modes->alphaBits);
- VisualPtr pVis = pScreen->visuals;
-
- /* Find a visual that matches the GLX visual's class and size */
- for (j = 0; j < pScreen->numVisuals; j++) {
- if (pVis[j].class == vis_class &&
- pVis[j].nplanes == nplanes) {
-
- /* Fixup the masks */
- modes->redMask = pVis[j].redMask;
- modes->greenMask = pVis[j].greenMask;
- modes->blueMask = pVis[j].blueMask;
-
- /* Recalc the sizes */
- modes->redBits = count_bits(modes->redMask);
- modes->greenBits = count_bits(modes->greenMask);
- modes->blueBits = count_bits(modes->blueMask);
- }
- }
+ if (screen->has_WGL_ARB_pbuffer)
+ {
+ // we may not query these attrs if WGL_ARB_pbuffer is not offered
+ ADD_ATTR(WGL_DRAW_TO_PBUFFER_ARB);
+ ADD_ATTR(WGL_MAX_PBUFFER_PIXELS_ARB);
+ ADD_ATTR(WGL_MAX_PBUFFER_WIDTH_ARB);
+ ADD_ATTR(WGL_MAX_PBUFFER_HEIGHT_ARB);
}
-}
-static void init_screen_visuals(int screen)
-{
- ScreenPtr pScreen = screenInfo.screens[screen];
- __GLcontextModes *modes;
- int *used;
- int i, j;
-
- GLWIN_DEBUG_MSG("init_screen_visuals\n");
-
- used = (int *)__glXMalloc(pScreen->numVisuals * sizeof(int));
- __glXMemset(used, 0, pScreen->numVisuals * sizeof(int));
-
- i = 0;
- for ( modes = glWinScreens[screen].modes
- ; modes != NULL
- ; modes = modes->next) {
- const int vis_class = _gl_convert_to_x_visual_type( modes->visualType );
- const int nplanes = (modes->rgbBits - modes->alphaBits);
- const VisualPtr pVis = pScreen->visuals;
-
- for (j = 0; j < pScreen->numVisuals; j++) {
-
- if (pVis[j].class == vis_class &&
- pVis[j].nplanes == nplanes &&
- pVis[j].redMask == modes->redMask &&
- pVis[j].greenMask == modes->greenMask &&
- pVis[j].blueMask == modes->blueMask &&
- !used[j]) {
-
-#if 0
- /* Create the XMesa visual */
- pXMesaVisual[i] =
- XMesaCreateVisual(pScreen,
- pVis,
- modes->rgbMode,
- (modes->alphaBits > 0),
- modes->doubleBufferMode,
- modes->stereoMode,
- GL_TRUE, /* ximage_flag */
- modes->depthBits,
- modes->stencilBits,
- modes->accumRedBits,
- modes->accumGreenBits,
- modes->accumBlueBits,
- modes->accumAlphaBits,
- modes->samples,
- modes->level,
- modes->visualRating);
-#endif
-
- /* Set the VisualID */
- modes->visualID = pVis[j].vid;
+ /* fill in configs */
+ for (i = 0; i < numConfigs; i++)
+ {
+ c = &(result[i]);
+ c->base.next = NULL;
+ c->pixelFormatIndex = i+1;
- /* Mark this visual used */
- used[j] = 1;
- break;
- }
- }
+ int values[num_attrs];
- if ( j == pScreen->numVisuals ) {
- ErrorF("No matching visual for __GLcontextMode with "
- "visual class = %d (%d), nplanes = %u\n",
- vis_class,
- modes->visualType,
- (modes->rgbBits - modes->alphaBits) );
- }
- else if ( modes->visualID == -1 ) {
- FatalError( "Matching visual found, but visualID still -1!\n" );
+ if (!wglGetPixelFormatAttribivARBWrapper(hdc, i+1, 0, num_attrs, attrs, values))
+ {
+ ErrorF("wglGetPixelFormatAttribivARB failed for index %d, error %s\n", i+1, glxWinErrorMessage());
+ break;
}
- i++;
-
- }
+#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
- __glXFree(used);
+ if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0))
+ {
+ GLWIN_DEBUG_MSG("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping", i+1);
+ continue;
+ }
- /* glWinScreens[screen].xm_vis = pXMesaVisual; */
-}
+ c->base.doubleBufferMode = ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, 0) ? GL_TRUE : GL_FALSE;
+ c->base.stereoMode = ATTR_VALUE(WGL_STEREO_ARB, 0) ? GL_TRUE : GL_FALSE;
-static Bool glWinScreenProbe(int screen)
-{
- ScreenPtr pScreen;
- glWinScreenRec *screenPriv;
+ c->base.redBits = ATTR_VALUE(WGL_RED_BITS_ARB, 0);
+ c->base.greenBits = ATTR_VALUE(WGL_GREEN_BITS_ARB, 0);
+ c->base.blueBits = ATTR_VALUE(WGL_BLUE_BITS_ARB, 0);
+ c->base.alphaBits = ATTR_VALUE(WGL_ALPHA_BITS_ARB, 0);
- GLWIN_DEBUG_MSG("glWinScreenProbe\n");
+ c->base.redMask = BITS_AND_SHIFT_TO_MASK(c->base.redBits, ATTR_VALUE(WGL_RED_SHIFT_ARB, 0));
+ c->base.greenMask = BITS_AND_SHIFT_TO_MASK(c->base.greenBits, ATTR_VALUE(WGL_GREEN_SHIFT_ARB, 0));
+ c->base.blueMask = BITS_AND_SHIFT_TO_MASK(c->base.blueBits, ATTR_VALUE(WGL_BLUE_SHIFT_ARB, 0));
+ c->base.alphaMask = BITS_AND_SHIFT_TO_MASK(c->base.alphaBits, ATTR_VALUE(WGL_ALPHA_SHIFT_ARB, 0));
- /*
- * Set up the current screen's visuals.
- */
- __glDDXScreenInfo.modes = glWinScreens[screen].modes;
- __glDDXScreenInfo.pVisualPriv = glWinScreens[screen].priv;
- __glDDXScreenInfo.numVisuals =
- __glDDXScreenInfo.numUsableVisuals = glWinScreens[screen].num_vis;
+ switch (ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0))
+ {
+ case WGL_TYPE_COLORINDEX_ARB:
+ c->base.indexBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
+ c->base.rgbBits = 0;
+ c->base.visualType = GLX_STATIC_COLOR;
+ break;
+
+ case WGL_TYPE_RGBA_FLOAT_ARB:
+ GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i+1);
+ continue;
+
+ case WGL_TYPE_RGBA_ARB:
+ c->base.indexBits = 0;
+ c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0);
+ c->base.visualType = GLX_TRUE_COLOR;
+ break;
+
+ default:
+ ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n", ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0));
+ continue;
+ }
- /*
- * Set the current screen's createContext routine. This could be
- * wrapped by a DDX GLX context creation routine.
- */
- __glDDXScreenInfo.createContext = glWinCreateContext;
+ c->base.accumRedBits = ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, 0);
+ c->base.accumGreenBits = ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, 0);
+ c->base.accumBlueBits = ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, 0);
+ c->base.accumAlphaBits = ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, 0);
- /*
- * The ordering of the rgb compenents might have been changed by the
- * driver after mi initialized them.
- */
- fixup_visuals(screen);
+ c->base.depthBits = ATTR_VALUE(WGL_DEPTH_BITS_ARB, 0);
+ c->base.stencilBits = ATTR_VALUE(WGL_STENCIL_BITS_ARB, 0);
+ c->base.numAuxBuffers = ATTR_VALUE(WGL_AUX_BUFFERS_ARB, 0);
- /*
- * Find the GLX visuals that are supported by this screen and create
- * XMesa's visuals.
- */
- init_screen_visuals(screen);
-
- /* Wrap RealizeWindow and UnrealizeWindow on this screen */
- pScreen = screenInfo.screens[screen];
- screenPriv = &glWinScreens[screen];
- screenPriv->RealizeWindow = pScreen->RealizeWindow;
- pScreen->RealizeWindow = glWinRealizeWindow;
- screenPriv->UnrealizeWindow = pScreen->UnrealizeWindow;
- pScreen->UnrealizeWindow = glWinUnrealizeWindow;
- screenPriv->CopyWindow = pScreen->CopyWindow;
- pScreen->CopyWindow = glWinCopyWindow;
-
- return TRUE;
-}
+ {
+ int layers = ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0);
-static GLboolean glWinSwapBuffers(__GLXdrawablePrivate *glxPriv)
-{
- /* swap buffers on only *one* of the contexts
- * (e.g. the last one for drawing)
- */
- __GLcontext *gc = (__GLcontext *)glxPriv->drawGlxc->gc;
- HDC dc;
- BOOL ret;
-
- GLWIN_TRACE_MSG("glWinSwapBuffers (ctx %p)\n", (gc!=NULL?gc->ctx:NULL));
+ if (layers > 0)
+ {
+ ErrorF("pixelFormat %d: has %d overlay, %d underlays which aren't currently handled", i, ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0), ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0));
+ // XXX: need to iterate over layers?
+ }
+ }
+ c->base.level = 0;
- if (gc != NULL && gc->ctx != NULL)
- {
- dc = glWinMakeDC(gc);
- if (dc == NULL)
- return GL_FALSE;
-
- ret = SwapBuffers(dc);
- if (!ret)
- ErrorF("SwapBuffers failed: %s\n", glWinErrorMessage());
-
- ReleaseDC(gc->winInfo.hwnd, dc);
- if (!ret)
- return GL_FALSE;
- }
+ c->base.pixmapMode = 0; // ???
+ c->base.visualID = -1; // will be set by __glXScreenInit()
- return GL_TRUE;
-}
+ /* EXT_visual_rating / GLX 1.2 */
+ switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0))
+ {
+ default:
+ ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_ACCELERATION_ARB\n", ATTR_VALUE(WGL_ACCELERATION_ARB, 0));
-static void glWinDestroyDrawablePrivate(__GLdrawablePrivate *glPriv)
-{
- GLWIN_DEBUG_MSG("glWinDestroyDrawablePrivate\n");
+ case WGL_NO_ACCELERATION_ARB:
+ c->base.visualRating = GLX_SLOW_VISUAL_EXT;
+ break;
- /* It doesn't work to call DRIDestroySurface here, the drawable's
- already gone.. But dri.c notices the window destruction and
- frees the surface itself. */
+ case WGL_GENERIC_ACCELERATION_ARB:
+ case WGL_FULL_ACCELERATION_ARB:
+ c->base.visualRating = GLX_NONE_EXT;
+ break;
+ }
- free(glPriv->private);
- glPriv->private = NULL;
-}
+ /* EXT_visual_info / GLX 1.2 */
+ // c->base.visualType is set above
+ if (ATTR_VALUE(WGL_TRANSPARENT_ARB, 0))
+ {
+ c->base.transparentPixel = (c->base.visualType == GLX_TRUE_COLOR) ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
+ c->base.transparentRed = ATTR_VALUE(WGL_TRANSPARENT_RED_VALUE_ARB, 0);
+ c->base.transparentGreen = ATTR_VALUE(WGL_TRANSPARENT_GREEN_VALUE_ARB, 0);
+ c->base.transparentBlue = ATTR_VALUE(WGL_TRANSPARENT_BLUE_VALUE_ARB, 0);
+ c->base.transparentAlpha = ATTR_VALUE(WGL_TRANSPARENT_ALPHA_VALUE_ARB, 0);
+ c->base.transparentIndex = ATTR_VALUE(WGL_TRANSPARENT_INDEX_VALUE_ARB, 0);
+ }
+ else
+ {
+ c->base.transparentPixel = GLX_NONE_EXT;
+ c->base.transparentRed = GLX_NONE;
+ c->base.transparentGreen = GLX_NONE;
+ c->base.transparentBlue = GLX_NONE;
+ c->base.transparentAlpha = GLX_NONE;
+ c->base.transparentIndex = GLX_NONE;
+ }
+ /* ARB_multisample / SGIS_multisample */
+ if (screen->has_WGL_ARB_multisample)
+ {
+ c->base.sampleBuffers = ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, 0);
+ c->base.samples = ATTR_VALUE(WGL_SAMPLES_ARB, 0);
+ }
+ else
+ {
+ c->base.sampleBuffers = 0;
+ c->base.samples = 0;
+ }
-static void glWinCreateBuffer(__GLXdrawablePrivate *glxPriv)
-{
- GLWinDrawableRec *winPriv = malloc(sizeof(GLWinDrawableRec));
- __GLdrawablePrivate *glPriv = &glxPriv->glPriv;
+ /* SGIX_fbconfig / GLX 1.3 */
+ c->base.drawableType = ((ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, 0) ? GLX_WINDOW_BIT : 0)
+ | (ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, 0) ? GLX_PIXMAP_BIT : 0)
+ | (ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, 0) ? GLX_PBUFFER_BIT : 0));
+ c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT; // Hmmm ???
+ c->base.xRenderable = GL_TRUE;
+ c->base.fbconfigID = -1; // will be set by __glXScreenInit()
- /*winPriv->sid = 0; */
- winPriv->pDraw = NULL;
+ /* SGIX_pbuffer / GLX 1.3 */
+ if (screen->has_WGL_ARB_pbuffer)
+ {
+ c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1);
+ c->base.maxPbufferHeight = ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1);
+ c->base.maxPbufferPixels = ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1);
+ }
+ else
+ {
+ c->base.maxPbufferWidth = -1;
+ c->base.maxPbufferHeight = -1;
+ c->base.maxPbufferPixels = -1;
+ }
+ c->base.optimalPbufferWidth = 0; // there is no optimal value
+ c->base.optimalPbufferHeight = 0;
- GLWIN_DEBUG_MSG("glWinCreateBuffer\n");
+ /* SGIX_visual_select_group */
+ // arrange for visuals with the best acceleration to be preferred in selection
+ switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0))
+ {
+ case WGL_FULL_ACCELERATION_ARB:
+ c->base.visualSelectGroup = 2;
+ break;
+
+ case WGL_GENERIC_ACCELERATION_ARB:
+ c->base.visualSelectGroup = 1;
+ break;
+
+ default:
+ case WGL_NO_ACCELERATION_ARB:
+ c->base.visualSelectGroup = 0;
+ break;
+ }
- /* replace swapBuffers (original is never called) */
- glxPriv->swapBuffers = glWinSwapBuffers;
+ /* OML_swap_method */
+ switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0))
+ {
+ case WGL_SWAP_EXCHANGE_ARB:
+ c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
+ break;
- /* stash private data */
- glPriv->private = winPriv;
- glPriv->freePrivate = glWinDestroyDrawablePrivate;
-}
+ case WGL_SWAP_COPY_ARB:
+ c->base.swapMethod = GLX_SWAP_COPY_OML;
+ break;
-static void glWinResetExtension(void)
-{
- GLWIN_DEBUG_MSG("glWinResetExtension\n");
-}
+ default:
+ ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n", ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0));
-/* based on code in apples/indirect.c which is based on i830_dri.c */
-static void
-glWinInitVisualConfigs(void)
-{
- int lclNumConfigs = 0;
- __GLXvisualConfig *lclVisualConfigs = NULL;
- void **lclVisualPrivates = NULL;
-
- int depth, aux, buffers, stencil, accum;
- int i = 0;
-
- GLWIN_DEBUG_MSG("glWinInitVisualConfigs ");
-
- /* count num configs:
- 2 Z buffer (0, 24 bit)
- 2 AUX buffer (0, 2)
- 2 buffers (single, double)
- 2 stencil (0, 8 bit)
- 2 accum (0, 64 bit)
- = 32 configs */
-
- lclNumConfigs = 2 * 2 * 2 * 2 * 2; /* 32 */
-
- /* alloc */
- lclVisualConfigs = xcalloc(sizeof(__GLXvisualConfig), lclNumConfigs);
- lclVisualPrivates = xcalloc(sizeof(void *), lclNumConfigs);
-
- /* fill in configs */
- if (NULL != lclVisualConfigs) {
- i = 0; /* current buffer */
- for (depth = 0; depth < 2; depth++) {
- for (aux = 0; aux < 2; aux++) {
- for (buffers = 0; buffers < 2; buffers++) {
- for (stencil = 0; stencil < 2; stencil++) {
- for (accum = 0; accum < 2; accum++) {
- lclVisualConfigs[i].vid = -1;
- lclVisualConfigs[i].class = -1;
- lclVisualConfigs[i].rgba = TRUE;
- lclVisualConfigs[i].redSize = -1;
- lclVisualConfigs[i].greenSize = -1;
- lclVisualConfigs[i].blueSize = -1;
- lclVisualConfigs[i].redMask = -1;
- lclVisualConfigs[i].greenMask = -1;
- lclVisualConfigs[i].blueMask = -1;
- lclVisualConfigs[i].alphaMask = 0;
- if (accum) {
- lclVisualConfigs[i].accumRedSize = 16;
- lclVisualConfigs[i].accumGreenSize = 16;
- lclVisualConfigs[i].accumBlueSize = 16;
- lclVisualConfigs[i].accumAlphaSize = 16;
- }
- else {
- lclVisualConfigs[i].accumRedSize = 0;
- lclVisualConfigs[i].accumGreenSize = 0;
- lclVisualConfigs[i].accumBlueSize = 0;
- lclVisualConfigs[i].accumAlphaSize = 0;
- }
- lclVisualConfigs[i].doubleBuffer = buffers ? TRUE : FALSE;
- lclVisualConfigs[i].stereo = FALSE;
- lclVisualConfigs[i].bufferSize = -1;
-
- lclVisualConfigs[i].depthSize = depth? 24 : 0;
- lclVisualConfigs[i].stencilSize = stencil ? 8 : 0;
- lclVisualConfigs[i].auxBuffers = aux ? 2 : 0;
- lclVisualConfigs[i].level = 0;
- lclVisualConfigs[i].visualRating = GLX_NONE_EXT;
- lclVisualConfigs[i].transparentPixel = 0;
- lclVisualConfigs[i].transparentRed = 0;
- lclVisualConfigs[i].transparentGreen = 0;
- lclVisualConfigs[i].transparentBlue = 0;
- lclVisualConfigs[i].transparentAlpha = 0;
- lclVisualConfigs[i].transparentIndex = 0;
- i++;
- }
- }
- }
- }
+ case WGL_SWAP_UNDEFINED_ARB:
+ c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
}
- }
- if (i != lclNumConfigs)
- GLWIN_DEBUG_MSG("glWinInitVisualConfigs failed to alloc visual configs");
- GlxSetVisualConfigs(lclNumConfigs, lclVisualConfigs, lclVisualPrivates);
-}
-
-/* Copied from Mesa */
-static void glWinSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
- void **privates)
-{
- GLWIN_DEBUG_MSG("glWinSetVisualConfigs\n");
+ /* EXT_import_context */
+ c->base.screen = screen->base.pScreen->myNum;
- numConfigs = nconfigs;
- visualConfigs = configs;
- visualPrivates = privates;
-}
+ /* EXT_texture_from_pixmap */
+ /*
+ Mesa's DRI configs always have bindToTextureRgb/Rgba TRUE (see driCreateConfigs(), so setting
+ bindToTextureRgb/bindToTextureRgba to FALSE means that swrast can't find any fbConfigs to use,
+ so setting these to 0, even if we know bindToTexture isn't available, isn't a good idea...
+ */
+ if (screen->has_WGL_ARB_render_texture)
+ {
+ c->base.bindToTextureRgb = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGB_ARB, -1);
+ c->base.bindToTextureRgba = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGBA_ARB, -1);
+ }
+ else
+ {
+ c->base.bindToTextureRgb = -1;
+ c->base.bindToTextureRgba = -1;
+ }
+ c->base.bindToMipmapTexture = -1;
+ c->base.bindToTextureTargets = GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | GLX_TEXTURE_RECTANGLE_BIT_EXT;
+ c->base.yInverted = -1;
-/* Copied from Mesa */
-static Bool glWinInitVisuals(VisualPtr *visualp, DepthPtr *depthp,
- int *nvisualp, int *ndepthp,
- int *rootDepthp, VisualID *defaultVisp,
- unsigned long sizes, int bitsPerRGB)
-{
- glWinInitDebugSettings();
+ n++;
- GLWIN_DEBUG_MSG("glWinInitVisuals\n");
+ // update previous config to point to this config
+ if (prev)
+ prev->base.next = &(c->base);
- if (0 == numConfigs) /* if no configs */
- glWinInitVisualConfigs(); /* ensure the visula configs are setup */
+ prev = c;
+ }
- /*
- * Setup the visuals supported by this particular screen.
- */
- return init_visuals(nvisualp, visualp, defaultVisp,
- *ndepthp, *depthp, *rootDepthp);
+ screen->base.numFBConfigs = n;
+ screen->base.fbconfigs = &(result->base);
}