aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xorg-server/hw/xfree86/common/xf86Mode.c200
-rw-r--r--xorg-server/hw/xfree86/common/xf86RandR.c1
-rw-r--r--xorg-server/hw/xfree86/loader/sdksyms.sh1
-rw-r--r--xorg-server/hw/xfree86/modes/xf86RandR12.c1
-rw-r--r--xorg-server/hw/xwin/glx/gen_gl_wrappers.py1
-rw-r--r--xorg-server/hw/xwin/glx/glwrap.c21
-rw-r--r--xorg-server/hw/xwin/glx/indirect.c4594
-rw-r--r--xorg-server/hw/xwin/glx/winpriv.c34
-rw-r--r--xorg-server/hw/xwin/glx/winpriv.h27
-rw-r--r--xorg-server/mi/Makefile.am4
-rw-r--r--xorg-server/mi/mibank.c2314
-rw-r--r--xorg-server/mi/mibank.h112
12 files changed, 2528 insertions, 4782 deletions
diff --git a/xorg-server/hw/xfree86/common/xf86Mode.c b/xorg-server/hw/xfree86/common/xf86Mode.c
index 949d4fcfa..5d30a782c 100644
--- a/xorg-server/hw/xfree86/common/xf86Mode.c
+++ b/xorg-server/hw/xfree86/common/xf86Mode.c
@@ -26,6 +26,52 @@
*/
/*
+ * LCM() and scanLineWidth() are:
+ *
+ * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Copyright 1990,91,92,93 by Thomas Roell, Germany.
+ * Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation, and that the name of Thomas Roell nor
+ * SGCS be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Thomas Roell nor SGCS makes no representations about the suitability
+ * of this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ *
+ * THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
* Authors: Dirk Hohndel <hohndel@XFree86.Org>
* David Dawes <dawes@XFree86.Org>
* Marc La France <tsi@XFree86.Org>
@@ -42,7 +88,6 @@
#include "xf86Modes.h"
#include "os.h"
#include "servermd.h"
-#include "mibank.h"
#include "globals.h"
#include "xf86.h"
#include "xf86Priv.h"
@@ -1126,6 +1171,131 @@ found:
return 1;
}
+/* Least common multiple */
+static unsigned int
+LCM(unsigned int x, unsigned int y)
+{
+ unsigned int m = x, n = y, o;
+
+ while ((o = m % n))
+ {
+ m = n;
+ n = o;
+ }
+
+ return (x / n) * y;
+}
+
+/*
+ * Given various screen attributes, determine the minimum scanline width such
+ * that each scanline is server and DDX padded and any pixels with imbedded
+ * bank boundaries are off-screen. This function returns -1 if such a width
+ * cannot exist.
+ */
+static int
+scanLineWidth(
+ unsigned int xsize, /* pixels */
+ unsigned int ysize, /* pixels */
+ unsigned int width, /* pixels */
+ unsigned long BankSize, /* char's */
+ PixmapFormatRec *pBankFormat,
+ unsigned int nWidthUnit /* bits */
+)
+{
+ unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit;
+ unsigned long minBitsPerScanline, maxBitsPerScanline;
+
+ /* Sanity checks */
+
+ if (!nWidthUnit || !pBankFormat)
+ return -1;
+
+ nBitsPerBank = BankSize * 8;
+ if (nBitsPerBank % pBankFormat->scanlinePad)
+ return -1;
+
+ if (xsize > width)
+ width = xsize;
+ nBitsPerScanlinePadUnit = LCM(pBankFormat->scanlinePad, nWidthUnit);
+ nBitsPerScanline =
+ (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) /
+ nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit;
+ width = nBitsPerScanline / pBankFormat->bitsPerPixel;
+
+ if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel))
+ return (int)width;
+
+ /*
+ * Scanlines will be server-pad aligned at this point. They will also be
+ * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded
+ * bank boundaries are off-screen.
+ *
+ * It seems reasonable to limit total frame buffer size to 1/16 of the
+ * theoretical maximum address space size. On a machine with 32-bit
+ * addresses (to 8-bit quantities) this turns out to be 256MB. Not only
+ * does this provide a simple limiting condition for the loops below, but
+ * it also prevents unsigned long wraparounds.
+ */
+ if (!ysize)
+ return -1;
+
+ minBitsPerScanline = xsize * pBankFormat->bitsPerPixel;
+ if (minBitsPerScanline > nBitsPerBank)
+ return -1;
+
+ if (ysize == 1)
+ return (int)width;
+
+ maxBitsPerScanline =
+ (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1);
+ while (nBitsPerScanline <= maxBitsPerScanline)
+ {
+ unsigned long BankBase, BankUnit;
+
+ BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) *
+ nBitsPerBank;
+ if (!(BankUnit % nBitsPerScanline))
+ return (int)width;
+
+ for (BankBase = BankUnit; ; BankBase += nBitsPerBank)
+ {
+ unsigned long x, y;
+
+ y = BankBase / nBitsPerScanline;
+ if (y >= ysize)
+ return (int)width;
+
+ x = BankBase % nBitsPerScanline;
+ if (!(x % pBankFormat->bitsPerPixel))
+ continue;
+
+ if (x < minBitsPerScanline)
+ {
+ /*
+ * Skip ahead certain widths by dividing the excess scanline
+ * amongst the y's.
+ */
+ y *= nBitsPerScanlinePadUnit;
+ nBitsPerScanline +=
+ ((x + y - 1) / y) * nBitsPerScanlinePadUnit;
+ width = nBitsPerScanline / pBankFormat->bitsPerPixel;
+ break;
+ }
+
+ if (BankBase != BankUnit)
+ continue;
+
+ if (!(nBitsPerScanline % x))
+ return (int)width;
+
+ BankBase = ((nBitsPerScanline - minBitsPerScanline) /
+ (nBitsPerScanline - x)) * BankUnit;
+ }
+ }
+
+ return -1;
+}
+
/*
* xf86ValidateModes
*
@@ -1312,7 +1482,7 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
memcpy(storeClockRanges, cp, sizeof(ClockRange));
}
- /* Determine which pixmap format to pass to miScanLineWidth() */
+ /* Determine which pixmap format to pass to scanLineWidth() */
if (scrp->depth > 4)
BankFormat = &scrp->fbFormat;
else
@@ -1363,15 +1533,15 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
for (i = 0; linePitches[i] != 0; i++) {
if ((linePitches[i] >= virtualX) &&
(linePitches[i] ==
- miScanLineWidth(virtualX, virtualY, linePitches[i],
- apertureSize, BankFormat, pitchInc))) {
+ scanLineWidth(virtualX, virtualY, linePitches[i],
+ apertureSize, BankFormat, pitchInc))) {
linePitch = linePitches[i];
break;
}
}
} else {
- linePitch = miScanLineWidth(virtualX, virtualY, minPitch,
- apertureSize, BankFormat, pitchInc);
+ linePitch = scanLineWidth(virtualX, virtualY, minPitch,
+ apertureSize, BankFormat, pitchInc);
}
if ((linePitch < minPitch) || (linePitch > maxPitch)) {
@@ -1396,8 +1566,8 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
/* XXX this doesn't take m{in,ax}Pitch into account; oh well */
inferred_virtual = inferVirtualSize(scrp, availModes, &virtX, &virtY);
if (inferred_virtual)
- linePitch = miScanLineWidth(virtX, virtY, minPitch, apertureSize,
- BankFormat, pitchInc);
+ linePitch = scanLineWidth(virtX, virtY, minPitch, apertureSize,
+ BankFormat, pitchInc);
}
/* Print clock ranges and scaled clocks */
@@ -1609,8 +1779,8 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
if ((linePitches[i] >= newVirtX) &&
(linePitches[i] >= linePitch) &&
(linePitches[i] ==
- miScanLineWidth(newVirtX, newVirtY, linePitches[i],
- apertureSize, BankFormat, pitchInc))) {
+ scanLineWidth(newVirtX, newVirtY, linePitches[i],
+ apertureSize, BankFormat, pitchInc))) {
newLinePitch = linePitches[i];
break;
}
@@ -1618,9 +1788,9 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
} else {
if (linePitch < minPitch)
linePitch = minPitch;
- newLinePitch = miScanLineWidth(newVirtX, newVirtY, linePitch,
- apertureSize, BankFormat,
- pitchInc);
+ newLinePitch = scanLineWidth(newVirtX, newVirtY, linePitch,
+ apertureSize, BankFormat,
+ pitchInc);
}
if ((newLinePitch < minPitch) || (newLinePitch > maxPitch)) {
p->status = MODE_BAD_WIDTH;
@@ -1682,8 +1852,8 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
virtX, virtY, vx, vy);
virtX = vx;
virtY = vy;
- linePitch = miScanLineWidth(vx, vy, minPitch, apertureSize,
- BankFormat, pitchInc);
+ linePitch = scanLineWidth(vx, vy, minPitch, apertureSize,
+ BankFormat, pitchInc);
}
}
diff --git a/xorg-server/hw/xfree86/common/xf86RandR.c b/xorg-server/hw/xfree86/common/xf86RandR.c
index d4beb2ce2..86c7bde79 100644
--- a/xorg-server/hw/xfree86/common/xf86RandR.c
+++ b/xorg-server/hw/xfree86/common/xf86RandR.c
@@ -27,7 +27,6 @@
#include <X11/X.h>
#include "os.h"
-#include "mibank.h"
#include "globals.h"
#include "xf86.h"
#include "xf86str.h"
diff --git a/xorg-server/hw/xfree86/loader/sdksyms.sh b/xorg-server/hw/xfree86/loader/sdksyms.sh
index eea024063..13c5ae5f8 100644
--- a/xorg-server/hw/xfree86/loader/sdksyms.sh
+++ b/xorg-server/hw/xfree86/loader/sdksyms.sh
@@ -217,7 +217,6 @@ cat > sdksyms.c << EOF
/* mi/Makefile.am */
-#include "mibank.h"
#include "micmap.h"
#include "miline.h"
#include "mipointer.h"
diff --git a/xorg-server/hw/xfree86/modes/xf86RandR12.c b/xorg-server/hw/xfree86/modes/xf86RandR12.c
index 7ba09b6fe..8898f4dad 100644
--- a/xorg-server/hw/xfree86/modes/xf86RandR12.c
+++ b/xorg-server/hw/xfree86/modes/xf86RandR12.c
@@ -30,7 +30,6 @@
#include "xf86.h"
#include "os.h"
-#include "mibank.h"
#include "globals.h"
#include "xf86.h"
#include "xf86Priv.h"
diff --git a/xorg-server/hw/xwin/glx/gen_gl_wrappers.py b/xorg-server/hw/xwin/glx/gen_gl_wrappers.py
index 127e8b21d..d7fe98dec 100644
--- a/xorg-server/hw/xwin/glx/gen_gl_wrappers.py
+++ b/xorg-server/hw/xwin/glx/gen_gl_wrappers.py
@@ -309,7 +309,6 @@ if dispatchheader :
print 'void glWinSetupDispatchTable(void)'
print '{'
print ' struct _glapi_table *disp = _glapi_get_dispatch();'
- print ' gl_dispatch_debugging();\n'
for d in sorted(dispatch.keys()) :
if wrappers.has_key(d) :
diff --git a/xorg-server/hw/xwin/glx/glwrap.c b/xorg-server/hw/xwin/glx/glwrap.c
index fdb2c4aa6..5190d36f7 100644
--- a/xorg-server/hw/xwin/glx/glwrap.c
+++ b/xorg-server/hw/xwin/glx/glwrap.c
@@ -115,27 +115,6 @@ glWinResolveHelper(PROC *cache, char *symbol)
#define RESOLVED_PROC(proctype) proc
/*
- * GL dispatch table debugging
- */
-
-static void
-warn_func(void * ctx, const char *format, ...)
-{
- va_list v;
- va_start(v, format);
- VErrorF(format, v);
- va_end(v);
- ErrorF("\n");
-}
-
-static void
-gl_dispatch_debugging(void)
-{
- _glapi_set_warning_func(warn_func);
- _glapi_noop_enable_warnings(TRUE);
-}
-
-/*
Include generated cdecl wrappers for stdcall gl*() functions in opengl32.dll
OpenGL 1.2 and upward is treated as extensions, function address must
diff --git a/xorg-server/hw/xwin/glx/indirect.c b/xorg-server/hw/xwin/glx/indirect.c
index a5ea854b3..c12cd1fbf 100644
--- a/xorg-server/hw/xwin/glx/indirect.c
+++ b/xorg-server/hw/xwin/glx/indirect.c
@@ -1,2278 +1,2316 @@
-/*
- * 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
- *
- * 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.
- *
- * 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
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/*
- 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?
- - snap winWindowInfoRec, it's just the same as a HWND now...
-*/
-
-/*
- 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
-
- 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 <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 (glxWinDebugSettings.dumpHWND) { \
- char buffer[1024]; \
- if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; \
- GLWIN_DEBUG_MSG("Got HWND %p for window '%s'", hwnd, buffer); \
- }
-
-glxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0};
-
-static void glxWinInitDebugSettings(void)
-{
- char *envptr;
-
- envptr = getenv("GLWIN_ENABLE_DEBUG");
- if (envptr != NULL)
- glxWinDebugSettings.enableDebug = (atoi(envptr) == 1);
-
- envptr = getenv("GLWIN_ENABLE_TRACE");
- if (envptr != NULL)
- glxWinDebugSettings.enableTrace = (atoi(envptr) == 1);
-
- envptr = getenv("GLWIN_DUMP_PFD");
- if (envptr != NULL)
- glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1);
-
- envptr = getenv("GLWIN_DUMP_HWND");
- if (envptr != NULL)
- glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1);
-
- envptr = getenv("GLWIN_DUMP_DC");
- if (envptr != NULL)
- 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
-const char *glxWinErrorMessage(void)
-{
- 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!", (unsigned)GetLastError());
- }
-
- 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;
- }
-}
-
-/* ---------------------------------------------------------------------- */
-/*
- * 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);
-
-/* ---------------------------------------------------------------------- */
-/*
- * The GLX provider
- */
-
-__GLXprovider __glXWGLProvider = {
- glxWinScreenProbe,
- "Win32 native WGL",
- NULL
-};
-
-void
-glxWinPushNativeProvider(void)
-{
- GlxPushProvider(&__glXWGLProvider);
-}
-
-/* ---------------------------------------------------------------------- */
-/*
- * Screen functions
- */
-
-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 ret;
-}
-
-/*
- Report the extensions split and formatted to avoid overflowing a line
- */
-static void
-glxLogExtensions(const char *prefix, const char *extensions)
-{
- int length = 0;
- char *strl;
- char *str = xalloc(strlen(extensions) + 1);
-
- if (str == NULL)
- {
- ErrorF("glxLogExtensions: xalloc error\n");
- return;
- }
-
- str[strlen(extensions)] = '\0';
- strncpy (str, extensions, strlen(extensions));
-
- strl = strtok(str, " ");
- ErrorF("%s%s", prefix, strl);
- length = strlen(prefix) + strlen(strl);
-
- while (1)
- {
- strl = strtok(NULL, " ");
- if (strl == NULL) break;
-
- if (length + strlen(strl) + 1 > 120)
- {
- ErrorF("\n%s",prefix);
- length = strlen(prefix);
- }
- else
- {
- ErrorF(" ");
- length++;
- }
-
- ErrorF("%s", strl);
- length = length + strlen(strl);
- }
-
- ErrorF("\n");
-
- xfree(str);
-}
-
-/* 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);
- glxLogExtensions("GL_EXTENSIONS: ", gl_extensions);
- wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
- if (!wgl_extensions) wgl_extensions = "";
- glxLogExtensions("WGL_EXTENSIONS: ", 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");
- screen->base.GLXmajor = 1;
- screen->base.GLXminor = 4;
- }
- else
- {
- screen->base.GLXversion = xstrdup("1.3");
- screen->base.GLXmajor = 1;
- screen->base.GLXminor = 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;
-}
-
-/* ---------------------------------------------------------------------- */
-/*
- * Window functions
- */
-
-static Bool
-glxWinRealizeWindow(WindowPtr pWin)
-{
- Bool result;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
-
- GLWIN_DEBUG_MSG("glxWinRealizeWindow");
-
- /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */
- pScreen->RealizeWindow = screenPriv->RealizeWindow;
- result = pScreen->RealizeWindow(pWin);
- pScreen->RealizeWindow = glxWinRealizeWindow;
-
- return result;
-}
-
-
-static void
-glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- __GLXWinDrawable *pGlxDraw;
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
-
- GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow);
-
- dixLookupResourceByType((pointer) &pGlxDraw, pWindow->drawable.id, __glXDrawableRes,
- NullClient, DixUnknownAccess);
-
-
- /*
- Discard any CopyWindow requests if a GL drawing context is pointing at the window
-
- 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;
- }
-
- GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer");
-
- pScreen->CopyWindow = screenPriv->CopyWindow;
- pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
- pScreen->CopyWindow = glxWinCopyWindow;
-}
-
-static Bool
-glxWinUnrealizeWindow(WindowPtr pWin)
-{
- Bool result;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- glxWinScreen *screenPriv = (glxWinScreen *)glxGetScreen(pScreen);
-
- GLWIN_DEBUG_MSG("glxWinUnrealizeWindow");
-
- pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow;
- result = pScreen->UnrealizeWindow(pWin);
- pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
-
- return result;
-}
-
-/* ---------------------------------------------------------------------- */
-/*
- * Drawable functions
- */
-
-static GLboolean
-glxWinDrawableSwapBuffers(ClientPtr client, __GLXdrawable *base)
-{
- HDC dc;
- HWND hwnd;
- BOOL ret;
- __GLXWinDrawable *draw = (__GLXWinDrawable *)base;
-
- /* 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)
- 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
-glxWinDrawableCopySubBuffer(__GLXdrawable *drawable,
- int x, int y, int w, int h)
-{
- glAddSwapHintRectWINWrapperNonstatic(x, y, w, h);
- glxWinDrawableSwapBuffers(NULL, drawable);
-}
-
-static void
-glxWinDrawableDestroy(__GLXdrawable *base)
-{
- __GLXWinDrawable *glxPriv = (__GLXWinDrawable *)base;
-
- if (glxPriv->drawContext && (__glXLastContext == &((glxPriv->drawContext)->base)))
- {
- // 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 (glxPriv->hPbuffer)
- if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer))
- {
- ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage());
- }
-
- if (glxPriv->dibDC)
- {
- // restore the default DIB
- SelectObject(glxPriv->dibDC, glxPriv->hOldDIB);
-
- if (!DeleteDC(glxPriv->dibDC))
- {
- ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage());
- }
- }
-
- if (glxPriv->hDIB)
- {
- if (!DeleteObject(glxPriv->hDIB))
- {
- ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
- }
-
- ((PixmapPtr)glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits;
- }
-
- GLWIN_DEBUG_MSG("glxWinDestroyDrawable");
- xfree(glxPriv);
-}
-
-static __GLXdrawable *
-glxWinCreateDrawable(__GLXscreen *screen,
- DrawablePtr pDraw,
- int type,
- XID drawId,
- __GLXconfig *conf)
-{
- __GLXWinDrawable *glxPriv;
-
- glxPriv = xalloc(sizeof *glxPriv);
-
- if (glxPriv == NULL)
- return NULL;
-
- 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;
-}
-
-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)))
- {
- if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL))
- {
- ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
- return;
- }
-
- return;
- }
-
- /*
- 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)
- {
- 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;
- }
- }
- else
- {
- int pixelFormat = fbConfigToPixelFormatIndex(hdc, gc->base.config, drawableTypeOverride, winScreen);
- if (pixelFormat == 0)
- {
- 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 (draw == NULL)
- {
- GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc, gc->ctx);
- return NULL;
- }
-
- switch (draw->base.type)
- {
- case GLX_DRAWABLE_WINDOW:
- {
- winWindowInfoRec winInfo;
- WindowPtr pWin;
-
- pWin = (WindowPtr) draw->base.pDraw;
- if (pWin == NULL)
- {
- GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin);
- return NULL;
- }
-
- winGetWindowInfo(pWin, &winInfo);
- *hwnd = winInfo.hwnd;
-
- if (winInfo.hwnd == NULL)
- {
- ErrorF("No HWND error: %s\n", glxWinErrorMessage());
- return NULL;
- }
-
- *hdc = GetDC(winInfo.hwnd);
-
- if (*hdc == NULL)
- ErrorF("GetDC error: %s\n", glxWinErrorMessage());
-
- /* 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:
- {
- *hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer);
-
- if (*hdc == NULL)
- ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage());
- }
- break;
-
- case GLX_DRAWABLE_PIXMAP:
- {
- *hdc = draw->dibDC;
- }
- break;
-
- default:
- {
- ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n", draw->base.type);
- }
- }
-
- 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);
- }
- break;
-
- case GLX_DRAWABLE_PBUFFER:
- {
- if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc))
- {
- ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage());
- }
- }
- break;
-
- case GLX_DRAWABLE_PIXMAP:
- {
- // don't release DC, the memory DC lives as long as the bitmap
-
- // We must ensure that all GDI drawing into the bitmap has completed
- // in case we subsequently access the bits from it
- GdiFlush();
- }
- break;
-
- default:
- {
- ErrorF("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n", draw->base.type);
- }
- }
-}
-
-static void
-glxWinDeferredCreateContext(__GLXWinContext *gc, __GLXWinDrawable *draw)
-{
- HDC dc;
- HWND hwnd;
- GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attach context %p to drawable %p", gc, draw);
-
- switch (draw->base.type)
- {
- case GLX_DRAWABLE_WINDOW:
- {
- 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;
-
- case GLX_DRAWABLE_PBUFFER:
- {
- if (draw->hPbuffer == NULL)
- {
- __GLXscreen *screen;
- glxWinScreen *winScreen;
- int pixelFormat;
- // 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");
- }
-
- screen = gc->base.pGlxScreen;
- winScreen = (glxWinScreen *)screen;
-
- pixelFormat = fbConfigToPixelFormatIndex(screenDC, gc->base.config, GLX_DRAWABLE_PBUFFER, winScreen);
- if (pixelFormat == 0)
- {
- 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;
-
- case GLX_DRAWABLE_PIXMAP:
- {
- if (draw->dibDC == NULL)
- {
- BITMAPINFOHEADER bmpHeader;
- void *pBits;
-
- memset (&bmpHeader, 0, sizeof(BITMAPINFOHEADER));
- bmpHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmpHeader.biWidth = draw->base.pDraw->width;
- bmpHeader.biHeight = draw->base.pDraw->height;
- bmpHeader.biPlanes = 1;
- bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel;
- bmpHeader.biCompression = BI_RGB;
-
- if (!(gc->base.config->drawableType & GLX_PIXMAP_BIT))
- {
- ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n");
- }
-
- draw->dibDC = CreateCompatibleDC(NULL);
- if (draw->dibDC == NULL)
- {
- ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
- return;
- }
-
- draw->hDIB = CreateDIBSection(draw->dibDC, (BITMAPINFO *)&bmpHeader, DIB_RGB_COLORS, &pBits, 0, 0);
- if (draw->dibDC == NULL)
- {
- ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage());
- return;
- }
-
- // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to
- // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits
- // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are
- // even compatible ...
- draw->pOldBits = ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr;
- ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr = pBits;
-
- // Select the DIB into the DC
- draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB);
- if (!draw->hOldDIB)
- {
- ErrorF("SelectObject error: %s\n", glxWinErrorMessage());
- }
-
- // Set the pixel format of the bitmap
- glxWinSetPixelFormat(gc, draw->dibDC, draw->base.pDraw->bitsPerPixel, GLX_PIXMAP_BIT);
-
- GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p", draw->hDIB, draw);
- }
- }
- break;
-
- default:
- {
- ErrorF("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", draw->base.type);
- return;
- }
- }
-
- dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
- gc->ctx = wglCreateContext(dc);
- glxWinReleaseDC(hwnd, dc, draw);
-
- if (gc->ctx == NULL)
- {
- ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage());
- return;
- }
-
- GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p", gc, gc->ctx, draw);
-
- // 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 (!wglShareLists(gc->shareContext->ctx, gc->ctx))
- {
- ErrorF("wglShareLists error: %s\n", glxWinErrorMessage());
- }
- }
-}
-
-/* ---------------------------------------------------------------------- */
-/*
- * Context functions
- */
-
-
-/* Context manipulation routines should return TRUE on success, FALSE on failure */
-static int
-glxWinContextMakeCurrent(__GLXcontext *base)
-{
- __GLXWinContext *gc = (__GLXWinContext *)base;
- BOOL ret;
- HDC drawDC;
- HDC readDC = NULL;
- __GLXdrawable *drawPriv;
- __GLXdrawable *readPriv = NULL;
- HWND hDrawWnd;
- HWND hReadWnd;
-
- 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);
- }
-
- if (gc->ctx == NULL)
- {
- ErrorF("glxWinContextMakeCurrent: Native context is NULL\n");
- return FALSE;
- }
-
- drawDC = glxWinMakeDC(gc, (__GLXWinDrawable *)drawPriv, &drawDC, &hDrawWnd);
- if (drawDC == NULL)
- {
- ErrorF("glxWinMakeDC failed for drawDC\n");
- return FALSE;
- }
-
- if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv))
- {
- // 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, &hReadWnd);
- if (readDC == NULL)
- {
- ErrorF("glxWinMakeDC failed for readDC\n");
- glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *)drawPriv);
- return FALSE;
- }
-
- ret = wglMakeContextCurrentARBWrapper(drawDC, readDC, gc->ctx);
- if (!ret)
- {
- ErrorF("wglMakeContextCurrentARBWrapper error: %s\n", glxWinErrorMessage());
- }
- }
- else
- {
- /* Otherwise, just use wglMakeCurrent */
- ret = wglMakeCurrent(drawDC, gc->ctx);
- if (!ret)
- {
- ErrorF("wglMakeCurrent error: %s\n", glxWinErrorMessage());
- }
- }
-
- // 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(hDrawWnd, drawDC, (__GLXWinDrawable *)drawPriv);
- if (readDC)
- glxWinReleaseDC(hReadWnd, readDC, (__GLXWinDrawable *)readPriv);
-
- return ret;
-}
-
-static int
-glxWinContextLoseCurrent(__GLXcontext *base)
-{
- BOOL ret;
- __GLXWinContext *gc = (__GLXWinContext *)base;
-
- GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc, gc->ctx);
- glWinCallDelta();
-
- ret = wglMakeCurrent(NULL, NULL); /* We don't need a DC when setting no current context */
- if (!ret)
- ErrorF("glxWinContextLoseCurrent error: %s\n", glxWinErrorMessage());
-
- __glXLastContext = NULL; /* Mesa does this; why? */
- // __glXFlushContextCache()
-
- return TRUE;
-}
-
-static int
-glxWinContextCopy(__GLXcontext *dst_base, __GLXcontext *src_base, unsigned long mask)
-{
- __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;
-}
-
-static int
-glxWinContextForceCurrent(__GLXcontext *base)
-{
- /* wglMakeCurrent always flushes the previous context, so this is equivalent to glxWinContextMakeCurrent */
- return glxWinContextMakeCurrent(base);
-}
-
-static void
-glxWinContextDestroy(__GLXcontext *base)
-{
- __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 __GLXcontext *
-glxWinCreateContext(__GLXscreen *screen,
- __GLXconfig *modes,
- __GLXcontext *baseShareContext)
-{
- __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);
-}
-
-/* ---------------------------------------------------------------------- */
-/*
- * Utility functions
- */
-
-static int
-fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride)
-{
- PIXELFORMATDESCRIPTOR pfd = {
- sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
- 1, /* version number */
- PFD_SUPPORT_OPENGL, /* support OpenGL */
- PFD_TYPE_RGBA, /* RGBA type */
- 24, /* 24-bit color depth */
- 0, 0, 0, 0, 0, 0, /* color bits ignored */
- 0, /* no alpha buffer */
- 0, /* shift bit ignored */
- 0, /* no accumulation buffer */
- 0, 0, 0, 0, /* accum bits ignored */
- 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 */
- };
-
- if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
- pfd.dwFlags |= PFD_DRAW_TO_WINDOW; /* support window */
-
- if ((mode->drawableType | drawableTypeOverride) & GLX_PIXMAP_BIT)
- pfd.dwFlags |= (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI); /* supports software rendering to bitmap */
-
- if (mode->stereoMode) {
- pfd.dwFlags |= PFD_STEREO;
- }
- if (mode->doubleBufferMode) {
- pfd.dwFlags |= PFD_DOUBLEBUFFER;
- }
-
- 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;
-
- return 0;
-}
-
-#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)
-{
- 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);
-
- 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);
-
- if (drawableTypeOverride & GLX_PBUFFER_BIT)
- if (winScreen->has_WGL_ARB_pbuffer)
- SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
- }
-
- SET_ATTR_VALUE(0, 0); // terminator
-
- /* choose the first match */
- {
- int pixelFormatIndex;
-
- 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");
- }
- }
-
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-#define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask))
-
-//
-// 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;
-
- GLWIN_DEBUG_MSG("glxWinCreateConfigs");
-
- 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);
-
- /* alloc */
- result = xalloc(sizeof(GLXWinConfig) * numConfigs);
-
- if (NULL == result)
- {
- return;
- }
-
- memset(result, 0, sizeof(GLXWinConfig) * numConfigs);
- n = 0;
-
- /* fill in configs */
- for (i = 0; i < numConfigs; i++)
- {
- int rc;
-
- c = &(result[i]);
- c->base.next = NULL;
- c->pixelFormatIndex = i+1;
-
- rc = DescribePixelFormat(hdc, i+1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
-
- if (!rc)
- {
- ErrorF("DescribePixelFormat failed for index %d, error %s\n", i+1, glxWinErrorMessage());
- break;
- }
-
- if (glxWinDebugSettings.dumpPFD)
- pfdOut(&pfd);
-
- 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;
-
- c->base.redBits = pfd.cRedBits;
- c->base.greenBits = pfd.cGreenBits;
- c->base.blueBits = pfd.cBlueBits;
- c->base.alphaBits = pfd.cAlphaBits;
-
- 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);
-
- c->base.rgbBits = pfd.cColorBits;
-
- if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
- {
- c->base.indexBits = pfd.cColorBits;
- }
- else
- {
- c->base.indexBits = 0;
- }
-
- c->base.accumRedBits = pfd.cAccumRedBits;
- c->base.accumGreenBits = pfd.cAccumGreenBits;
- c->base.accumBlueBits = pfd.cAccumBlueBits;
- c->base.accumAlphaBits = pfd.cAccumAlphaBits;
- // pfd.cAccumBits;
-
- c->base.depthBits = pfd.cDepthBits;
- c->base.stencilBits = pfd.cStencilBits;
- c->base.numAuxBuffers = pfd.cAuxBuffers;
-
- // pfd.iLayerType; // ignored
- c->base.level = 0;
- // pfd.dwLayerMask; // ignored
- // pfd.dwDamageMask; // ignored
-
- c->base.pixmapMode = 0;
- c->base.visualID = -1; // will be set by __glXScreenInit()
-
- /* 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;
- }
-
- /* 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;
- }
-
- // 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;
-
- case PFD_GENERIC_ACCELERATED:
- c->base.visualSelectGroup = 1;
- break;
-
- case PFD_GENERIC_FORMAT:
- c->base.visualSelectGroup = 0;
- break;
-
- default:
- ;
- // "can't happen"
- }
-
- /* 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;
-
- /* EXT_import_context */
- c->base.screen = screen->base.pScreen->myNum;
-
- /* EXT_texture_from_pixmap */
- c->base.bindToTextureRgb = -1;
- c->base.bindToTextureRgba = -1;
- c->base.bindToMipmapTexture = -1;
- c->base.bindToTextureTargets = -1;
- c->base.yInverted = -1;
-
- n++;
-
- // update previous config to point to this config
- if (prev)
- prev->base.next = &(c->base);
-
- prev = c;
- }
-
- GLWIN_DEBUG_MSG("found %d pixelFormats suitable for conversion to fbConfigs", n);
-
- screen->base.numFBConfigs = n;
- screen->base.fbconfigs = &(result->base);
-}
-
-// 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];
- }
- }
-
- ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n", attr, fallback);
- return fallback;
-}
-
-//
-// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
-//
-static void
-glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen)
-{
- GLXWinConfig *c, *result, *prev = NULL;
- int i = 0;
- int n = 0;
-
- const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB;
- int numConfigs;
-
- int attrs[50];
- unsigned int num_attrs = 0;
-
- GLWIN_DEBUG_MSG("glxWinCreateConfigsExt");
-
- screen->base.numFBConfigs = 0;
- screen->base.fbconfigs = NULL;
-
- if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs))
- {
- ErrorF("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n", glxWinErrorMessage());
- return;
- }
-
- GLWIN_DEBUG_MSG("wglGetPixelFormatAttribivARB says %d possible pixel formats", numConfigs);
-
- /* alloc */
- result = xalloc(sizeof(GLXWinConfig) * numConfigs);
-
- if (NULL == result)
- {
- return;
- }
-
- 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);
- }
-
- 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);
- }
-
- /* fill in configs */
- for (i = 0; i < numConfigs; i++)
- {
- int values[num_attrs];
-
- c = &(result[i]);
- c->base.next = NULL;
- c->pixelFormatIndex = i+1;
-
- if (!wglGetPixelFormatAttribivARBWrapper(hdc, i+1, 0, num_attrs, attrs, values))
- {
- ErrorF("wglGetPixelFormatAttribivARB failed for index %d, error %s\n", i+1, glxWinErrorMessage());
- break;
- }
-
-#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
-
- if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0))
- {
- GLWIN_DEBUG_MSG("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping", i+1);
- continue;
- }
-
- 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;
-
- 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);
-
- 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));
-
- 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_UNSIGNED_FLOAT_EXT:
- GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, 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;
- }
-
- 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);
-
- 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);
-
- {
- int layers = ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0);
-
- 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;
-
- c->base.pixmapMode = 0; // ???
- c->base.visualID = -1; // will be set by __glXScreenInit()
-
- /* 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));
-
- case WGL_NO_ACCELERATION_ARB:
- c->base.visualRating = GLX_SLOW_VISUAL_EXT;
- break;
-
- case WGL_GENERIC_ACCELERATION_ARB:
- case WGL_FULL_ACCELERATION_ARB:
- c->base.visualRating = GLX_NONE_EXT;
- break;
- }
-
- /* 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;
- }
-
- /* 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()
-
- /* 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;
-
- /* 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;
- }
-
- /* OML_swap_method */
- switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0))
- {
- case WGL_SWAP_EXCHANGE_ARB:
- c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
- break;
-
- case WGL_SWAP_COPY_ARB:
- c->base.swapMethod = GLX_SWAP_COPY_OML;
- break;
-
- default:
- ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n", ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0));
-
- case WGL_SWAP_UNDEFINED_ARB:
- c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
- }
-
- /* EXT_import_context */
- c->base.screen = screen->base.pScreen->myNum;
-
- /* 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;
-
- n++;
-
- // update previous config to point to this config
- if (prev)
- prev->base.next = &(c->base);
-
- prev = c;
- }
-
- screen->base.numFBConfigs = n;
- screen->base.fbconfigs = &(result->base);
-}
+/*
+ * 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
+ *
+ * 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.
+ *
+ * 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
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ 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
+
+ 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 <glx/glxserver.h>
+#include <glx/glxutil.h>
+#include <glx/extension_string.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 (glxWinDebugSettings.dumpHWND) { \
+ char buffer[1024]; \
+ if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; \
+ GLWIN_DEBUG_MSG("Got HWND %p for window '%s'", hwnd, buffer); \
+ }
+
+glxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0};
+
+static void glxWinInitDebugSettings(void)
+{
+ char *envptr;
+
+ envptr = getenv("GLWIN_ENABLE_DEBUG");
+ if (envptr != NULL)
+ glxWinDebugSettings.enableDebug = (atoi(envptr) == 1);
+
+ envptr = getenv("GLWIN_ENABLE_TRACE");
+ if (envptr != NULL)
+ glxWinDebugSettings.enableTrace = (atoi(envptr) == 1);
+
+ envptr = getenv("GLWIN_DUMP_PFD");
+ if (envptr != NULL)
+ glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1);
+
+ envptr = getenv("GLWIN_DUMP_HWND");
+ if (envptr != NULL)
+ glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1);
+
+ envptr = getenv("GLWIN_DUMP_DC");
+ if (envptr != NULL)
+ 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
+const char *glxWinErrorMessage(void)
+{
+ 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!", (unsigned)GetLastError());
+ }
+
+ 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;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * 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);
+
+/* ---------------------------------------------------------------------- */
+/*
+ * The GLX provider
+ */
+
+__GLXprovider __glXWGLProvider = {
+ glxWinScreenProbe,
+ "Win32 native WGL",
+ NULL
+};
+
+void
+glxWinPushNativeProvider(void)
+{
+ GlxPushProvider(&__glXWGLProvider);
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Screen functions
+ */
+
+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 ret;
+}
+
+/*
+ Report the extensions split and formatted to avoid overflowing a line
+ */
+static void
+glxLogExtensions(const char *prefix, const char *extensions)
+{
+ int length = 0;
+ char *strl;
+ char *str = xalloc(strlen(extensions) + 1);
+
+ if (str == NULL)
+ {
+ ErrorF("glxLogExtensions: xalloc error\n");
+ return;
+ }
+
+ str[strlen(extensions)] = '\0';
+ strncpy (str, extensions, strlen(extensions));
+
+ strl = strtok(str, " ");
+ ErrorF("%s%s", prefix, strl);
+ length = strlen(prefix) + strlen(strl);
+
+ while (1)
+ {
+ strl = strtok(NULL, " ");
+ if (strl == NULL) break;
+
+ if (length + strlen(strl) + 1 > 120)
+ {
+ ErrorF("\n");
+ ErrorF("%s",prefix);
+ length = strlen(prefix);
+ }
+ else
+ {
+ ErrorF(" ");
+ length++;
+ }
+
+ ErrorF("%s", strl);
+ length = length + strlen(strl);
+ }
+
+ ErrorF("\n");
+
+ xfree(str);
+}
+
+/* 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);
+ glxLogExtensions("GL_EXTENSIONS: ", gl_extensions);
+ wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
+ if (!wgl_extensions) wgl_extensions = "";
+ glxLogExtensions("WGL_EXTENSIONS: ", 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");
+ screen->base.GLXmajor = 1;
+ screen->base.GLXminor = 4;
+ }
+ else
+ {
+ screen->base.GLXversion = xstrdup("1.3");
+ screen->base.GLXmajor = 1;
+ screen->base.GLXminor = 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;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Window functions
+ */
+
+static Bool
+glxWinRealizeWindow(WindowPtr pWin)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
+
+ GLWIN_DEBUG_MSG("glxWinRealizeWindow");
+
+ /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */
+ pScreen->RealizeWindow = screenPriv->RealizeWindow;
+ result = pScreen->RealizeWindow(pWin);
+ pScreen->RealizeWindow = glxWinRealizeWindow;
+
+ return result;
+}
+
+
+static void
+glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ __GLXWinDrawable *pGlxDraw;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen);
+
+ GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow);
+
+ dixLookupResourceByType((pointer) &pGlxDraw, pWindow->drawable.id, __glXDrawableRes,
+ NullClient, DixUnknownAccess);
+
+
+ /*
+ Discard any CopyWindow requests if a GL drawing context is pointing at the window
+
+ 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;
+ }
+
+ GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer");
+
+ pScreen->CopyWindow = screenPriv->CopyWindow;
+ pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
+ pScreen->CopyWindow = glxWinCopyWindow;
+}
+
+static Bool
+glxWinUnrealizeWindow(WindowPtr pWin)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ glxWinScreen *screenPriv = (glxWinScreen *)glxGetScreen(pScreen);
+
+ GLWIN_DEBUG_MSG("glxWinUnrealizeWindow");
+
+ pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow;
+ result = pScreen->UnrealizeWindow(pWin);
+ pScreen->UnrealizeWindow = glxWinUnrealizeWindow;
+
+ return result;
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Drawable functions
+ */
+
+static GLboolean
+glxWinDrawableSwapBuffers(ClientPtr client, __GLXdrawable *base)
+{
+ HDC dc;
+ HWND hwnd;
+ BOOL ret;
+ __GLXWinDrawable *draw = (__GLXWinDrawable *)base;
+
+ /* 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)
+ 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
+glxWinDrawableCopySubBuffer(__GLXdrawable *drawable,
+ int x, int y, int w, int h)
+{
+ glAddSwapHintRectWINWrapperNonstatic(x, y, w, h);
+ glxWinDrawableSwapBuffers(NULL, drawable);
+}
+
+static void
+glxWinDrawableDestroy(__GLXdrawable *base)
+{
+ __GLXWinDrawable *glxPriv = (__GLXWinDrawable *)base;
+
+ if (glxPriv->drawContext && (__glXLastContext == &((glxPriv->drawContext)->base)))
+ {
+ // 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 (glxPriv->hPbuffer)
+ if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer))
+ {
+ ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage());
+ }
+
+ if (glxPriv->dibDC)
+ {
+ // restore the default DIB
+ SelectObject(glxPriv->dibDC, glxPriv->hOldDIB);
+
+ if (!DeleteDC(glxPriv->dibDC))
+ {
+ ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage());
+ }
+ }
+
+ if (glxPriv->hDIB)
+ {
+ if (!DeleteObject(glxPriv->hDIB))
+ {
+ ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage());
+ }
+
+ ((PixmapPtr)glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits;
+ }
+
+ GLWIN_DEBUG_MSG("glxWinDestroyDrawable");
+ xfree(glxPriv);
+}
+
+static __GLXdrawable *
+glxWinCreateDrawable(__GLXscreen *screen,
+ DrawablePtr pDraw,
+ int type,
+ XID drawId,
+ __GLXconfig *conf)
+{
+ __GLXWinDrawable *glxPriv;
+
+ glxPriv = xalloc(sizeof *glxPriv);
+
+ if (glxPriv == NULL)
+ return NULL;
+
+ 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;
+}
+
+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)))
+ {
+ if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL))
+ {
+ ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ return;
+ }
+
+ /*
+ 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)
+ {
+ 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;
+ }
+ }
+ else
+ {
+ int pixelFormat = fbConfigToPixelFormatIndex(hdc, gc->base.config, drawableTypeOverride, winScreen);
+ if (pixelFormat == 0)
+ {
+ 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 (draw == NULL)
+ {
+ GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc, gc->ctx);
+ return NULL;
+ }
+
+ switch (draw->base.type)
+ {
+ case GLX_DRAWABLE_WINDOW:
+ {
+ WindowPtr pWin;
+
+ pWin = (WindowPtr) draw->base.pDraw;
+ if (pWin == NULL)
+ {
+ GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin);
+ return NULL;
+ }
+
+ *hwnd = winGetWindowInfo(pWin);
+
+ if (*hwnd == NULL)
+ {
+ ErrorF("No HWND error: %s\n", glxWinErrorMessage());
+ return NULL;
+ }
+
+ *hdc = GetDC(*hwnd);
+
+ if (*hdc == NULL)
+ ErrorF("GetDC error: %s\n", glxWinErrorMessage());
+
+ /* Check if the hwnd has changed... */
+ if (*hwnd != gc->hwnd)
+ {
+ if (glxWinDebugSettings.enableTrace)
+ GLWIN_DEBUG_HWND(*hwnd);
+
+ GLWIN_TRACE_MSG("for context %p (native ctx %p), hWnd changed from %p to %p", gc, gc->ctx, gc->hwnd, *hwnd);
+ gc->hwnd = *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:
+ {
+ *hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer);
+
+ if (*hdc == NULL)
+ ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage());
+ }
+ break;
+
+ case GLX_DRAWABLE_PIXMAP:
+ {
+ *hdc = draw->dibDC;
+ }
+ break;
+
+ default:
+ {
+ ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n", draw->base.type);
+ }
+ }
+
+ 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);
+ }
+ break;
+
+ case GLX_DRAWABLE_PBUFFER:
+ {
+ if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc))
+ {
+ ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage());
+ }
+ }
+ break;
+
+ case GLX_DRAWABLE_PIXMAP:
+ {
+ // don't release DC, the memory DC lives as long as the bitmap
+
+ // We must ensure that all GDI drawing into the bitmap has completed
+ // in case we subsequently access the bits from it
+ GdiFlush();
+ }
+ break;
+
+ default:
+ {
+ ErrorF("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n", draw->base.type);
+ }
+ }
+}
+
+static void
+glxWinDeferredCreateContext(__GLXWinContext *gc, __GLXWinDrawable *draw)
+{
+ HDC dc;
+ HWND hwnd;
+ GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attach context %p to drawable %p", gc, draw);
+
+ switch (draw->base.type)
+ {
+ case GLX_DRAWABLE_WINDOW:
+ {
+ WindowPtr pWin = (WindowPtr) draw->base.pDraw;
+
+ if (!(gc->base.config->drawableType & GLX_WINDOW_BIT))
+ {
+ ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable\n");
+ }
+
+ if (pWin == NULL)
+ {
+ GLWIN_DEBUG_MSG("Deferring until X window is created");
+ return;
+ }
+
+ GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pWin %p", pWin);
+
+ if (winGetWindowInfo(pWin) == NULL)
+ {
+ GLWIN_DEBUG_MSG("Deferring until native window is created");
+ return;
+ }
+ }
+ break;
+
+ case GLX_DRAWABLE_PBUFFER:
+ {
+ if (draw->hPbuffer == NULL)
+ {
+ __GLXscreen *screen;
+ glxWinScreen *winScreen;
+ int pixelFormat;
+ // XXX: which DC are supposed to use???
+ HDC screenDC = GetDC(NULL);
+
+ if (!(gc->base.config->drawableType & GLX_PBUFFER_BIT))
+ {
+ ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable\n");
+ }
+
+ screen = gc->base.pGlxScreen;
+ winScreen = (glxWinScreen *)screen;
+
+ pixelFormat = fbConfigToPixelFormatIndex(screenDC, gc->base.config, GLX_DRAWABLE_PBUFFER, winScreen);
+ if (pixelFormat == 0)
+ {
+ 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;
+
+ case GLX_DRAWABLE_PIXMAP:
+ {
+ if (draw->dibDC == NULL)
+ {
+ BITMAPINFOHEADER bmpHeader;
+ void *pBits;
+
+ memset (&bmpHeader, 0, sizeof(BITMAPINFOHEADER));
+ bmpHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmpHeader.biWidth = draw->base.pDraw->width;
+ bmpHeader.biHeight = draw->base.pDraw->height;
+ bmpHeader.biPlanes = 1;
+ bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel;
+ bmpHeader.biCompression = BI_RGB;
+
+ if (!(gc->base.config->drawableType & GLX_PIXMAP_BIT))
+ {
+ ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n");
+ }
+
+ draw->dibDC = CreateCompatibleDC(NULL);
+ if (draw->dibDC == NULL)
+ {
+ ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ draw->hDIB = CreateDIBSection(draw->dibDC, (BITMAPINFO *)&bmpHeader, DIB_RGB_COLORS, &pBits, 0, 0);
+ if (draw->dibDC == NULL)
+ {
+ ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to
+ // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits
+ // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are
+ // even compatible ...
+ draw->pOldBits = ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr;
+ ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr = pBits;
+
+ // Select the DIB into the DC
+ draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB);
+ if (!draw->hOldDIB)
+ {
+ ErrorF("SelectObject error: %s\n", glxWinErrorMessage());
+ }
+
+ // Set the pixel format of the bitmap
+ glxWinSetPixelFormat(gc, draw->dibDC, draw->base.pDraw->bitsPerPixel, GLX_PIXMAP_BIT);
+
+ GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p", draw->hDIB, draw);
+ }
+ }
+ break;
+
+ default:
+ {
+ ErrorF("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", draw->base.type);
+ return;
+ }
+ }
+
+ dc = glxWinMakeDC(gc, draw, &dc, &hwnd);
+ gc->ctx = wglCreateContext(dc);
+ glxWinReleaseDC(hwnd, dc, draw);
+
+ if (gc->ctx == NULL)
+ {
+ ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p", gc, gc->ctx, draw);
+
+ // 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 (!wglShareLists(gc->shareContext->ctx, gc->ctx))
+ {
+ ErrorF("wglShareLists error: %s\n", glxWinErrorMessage());
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Context functions
+ */
+
+
+/* Context manipulation routines should return TRUE on success, FALSE on failure */
+static int
+glxWinContextMakeCurrent(__GLXcontext *base)
+{
+ __GLXWinContext *gc = (__GLXWinContext *)base;
+ BOOL ret;
+ HDC drawDC;
+ HDC readDC = NULL;
+ __GLXdrawable *drawPriv;
+ __GLXdrawable *readPriv = NULL;
+ HWND hDrawWnd;
+ HWND hReadWnd;
+
+ 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);
+ }
+
+ if (gc->ctx == NULL)
+ {
+ ErrorF("glxWinContextMakeCurrent: Native context is NULL\n");
+ return FALSE;
+ }
+
+ drawDC = glxWinMakeDC(gc, (__GLXWinDrawable *)drawPriv, &drawDC, &hDrawWnd);
+ if (drawDC == NULL)
+ {
+ ErrorF("glxWinMakeDC failed for drawDC\n");
+ return FALSE;
+ }
+
+ if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv))
+ {
+ // 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, &hReadWnd);
+ if (readDC == NULL)
+ {
+ ErrorF("glxWinMakeDC failed for readDC\n");
+ glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *)drawPriv);
+ return FALSE;
+ }
+
+ ret = wglMakeContextCurrentARBWrapper(drawDC, readDC, gc->ctx);
+ if (!ret)
+ {
+ ErrorF("wglMakeContextCurrentARBWrapper error: %s\n", glxWinErrorMessage());
+ }
+ }
+ else
+ {
+ /* Otherwise, just use wglMakeCurrent */
+ ret = wglMakeCurrent(drawDC, gc->ctx);
+ if (!ret)
+ {
+ ErrorF("wglMakeCurrent error: %s\n", glxWinErrorMessage());
+ }
+ }
+
+ // 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(hDrawWnd, drawDC, (__GLXWinDrawable *)drawPriv);
+ if (readDC)
+ glxWinReleaseDC(hReadWnd, readDC, (__GLXWinDrawable *)readPriv);
+
+ return ret;
+}
+
+static int
+glxWinContextLoseCurrent(__GLXcontext *base)
+{
+ BOOL ret;
+ __GLXWinContext *gc = (__GLXWinContext *)base;
+
+ GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc, gc->ctx);
+ glWinCallDelta();
+
+ /*
+ An error seems to be reported if we try to make no context current
+ if there is already no current context, so avoid doing that...
+ */
+ if (__glXLastContext != NULL)
+ {
+ ret = wglMakeCurrent(NULL, NULL); /* We don't need a DC when setting no current context */
+ if (!ret)
+ ErrorF("glxWinContextLoseCurrent error: %s\n", glxWinErrorMessage());
+ }
+
+ return TRUE;
+}
+
+static int
+glxWinContextCopy(__GLXcontext *dst_base, __GLXcontext *src_base, unsigned long mask)
+{
+ __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;
+}
+
+static int
+glxWinContextForceCurrent(__GLXcontext *base)
+{
+ /* wglMakeCurrent always flushes the previous context, so this is equivalent to glxWinContextMakeCurrent */
+ return glxWinContextMakeCurrent(base);
+}
+
+static void
+glxWinContextDestroy(__GLXcontext *base)
+{
+ __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 __GLXcontext *
+glxWinCreateContext(__GLXscreen *screen,
+ __GLXconfig *modes,
+ __GLXcontext *baseShareContext)
+{
+ __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);
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * Utility functions
+ */
+
+static int
+fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride)
+{
+ PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
+ 1, /* version number */
+ PFD_SUPPORT_OPENGL, /* support OpenGL */
+ PFD_TYPE_RGBA, /* RGBA type */
+ 24, /* 24-bit color depth */
+ 0, 0, 0, 0, 0, 0, /* color bits ignored */
+ 0, /* no alpha buffer */
+ 0, /* shift bit ignored */
+ 0, /* no accumulation buffer */
+ 0, 0, 0, 0, /* accum bits ignored */
+ 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 */
+ };
+
+ if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT)
+ pfd.dwFlags |= PFD_DRAW_TO_WINDOW; /* support window */
+
+ if ((mode->drawableType | drawableTypeOverride) & GLX_PIXMAP_BIT)
+ pfd.dwFlags |= (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI); /* supports software rendering to bitmap */
+
+ if (mode->stereoMode) {
+ pfd.dwFlags |= PFD_STEREO;
+ }
+ if (mode->doubleBufferMode) {
+ pfd.dwFlags |= PFD_DOUBLEBUFFER;
+ }
+
+ 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;
+
+ return 0;
+}
+
+#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)
+{
+ 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);
+
+ 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);
+
+ if (drawableTypeOverride & GLX_PBUFFER_BIT)
+ if (winScreen->has_WGL_ARB_pbuffer)
+ SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE);
+ }
+
+ SET_ATTR_VALUE(0, 0); // terminator
+
+ /* choose the first match */
+ {
+ int pixelFormatIndex;
+
+ 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");
+ }
+ }
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask))
+
+//
+// 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;
+
+ GLWIN_DEBUG_MSG("glxWinCreateConfigs");
+
+ 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);
+
+ /* alloc */
+ result = xalloc(sizeof(GLXWinConfig) * numConfigs);
+
+ if (NULL == result)
+ {
+ return;
+ }
+
+ memset(result, 0, sizeof(GLXWinConfig) * numConfigs);
+ n = 0;
+
+ /* fill in configs */
+ for (i = 0; i < numConfigs; i++)
+ {
+ int rc;
+
+ c = &(result[i]);
+ c->base.next = NULL;
+ c->pixelFormatIndex = i+1;
+
+ rc = DescribePixelFormat(hdc, i+1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
+
+ if (!rc)
+ {
+ ErrorF("DescribePixelFormat failed for index %d, error %s\n", i+1, glxWinErrorMessage());
+ break;
+ }
+
+ if (glxWinDebugSettings.dumpPFD)
+ pfdOut(&pfd);
+
+ 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;
+
+ c->base.redBits = pfd.cRedBits;
+ c->base.greenBits = pfd.cGreenBits;
+ c->base.blueBits = pfd.cBlueBits;
+ c->base.alphaBits = pfd.cAlphaBits;
+
+ 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);
+
+ c->base.rgbBits = pfd.cColorBits;
+
+ if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
+ {
+ c->base.indexBits = pfd.cColorBits;
+ }
+ else
+ {
+ c->base.indexBits = 0;
+ }
+
+ c->base.accumRedBits = pfd.cAccumRedBits;
+ c->base.accumGreenBits = pfd.cAccumGreenBits;
+ c->base.accumBlueBits = pfd.cAccumBlueBits;
+ c->base.accumAlphaBits = pfd.cAccumAlphaBits;
+ // pfd.cAccumBits;
+
+ c->base.depthBits = pfd.cDepthBits;
+ c->base.stencilBits = pfd.cStencilBits;
+ c->base.numAuxBuffers = pfd.cAuxBuffers;
+
+ // pfd.iLayerType; // ignored
+ c->base.level = 0;
+ // pfd.dwLayerMask; // ignored
+ // pfd.dwDamageMask; // ignored
+
+ c->base.pixmapMode = 0;
+ c->base.visualID = -1; // will be set by __glXScreenInit()
+
+ /* 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;
+ }
+
+ /* EXT_visual_info / GLX 1.2 */
+ if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
+ {
+ c->base.visualType = GLX_STATIC_COLOR;
+
+ if (!getenv("GLWIN_ENABLE_COLORINDEX_FBCONFIGS"))
+ {
+ GLWIN_DEBUG_MSG("pixelFormat %d is PFD_TYPE_COLORINDEX, skipping", i+1);
+ continue;
+ }
+ }
+ else
+ {
+ c->base.visualType = GLX_TRUE_COLOR;
+ }
+
+ // 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));
+
+ if (pfd.iPixelType == PFD_TYPE_COLORINDEX)
+ {
+ c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT;
+ }
+ else
+ {
+ 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;
+
+ case PFD_GENERIC_ACCELERATED:
+ c->base.visualSelectGroup = 1;
+ break;
+
+ case PFD_GENERIC_FORMAT:
+ c->base.visualSelectGroup = 0;
+ break;
+
+ default:
+ ;
+ // "can't happen"
+ }
+
+ /* 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;
+
+ /* EXT_import_context */
+ c->base.screen = screen->base.pScreen->myNum;
+
+ /* EXT_texture_from_pixmap */
+ c->base.bindToTextureRgb = -1;
+ c->base.bindToTextureRgba = -1;
+ c->base.bindToMipmapTexture = -1;
+ c->base.bindToTextureTargets = -1;
+ c->base.yInverted = -1;
+
+ n++;
+
+ // update previous config to point to this config
+ if (prev)
+ prev->base.next = &(c->base);
+
+ prev = c;
+ }
+
+ GLWIN_DEBUG_MSG("found %d pixelFormats suitable for conversion to fbConfigs", n);
+
+ screen->base.numFBConfigs = n;
+ screen->base.fbconfigs = &(result->base);
+}
+
+// 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];
+ }
+ }
+
+ ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n", attr, fallback);
+ return fallback;
+}
+
+//
+// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension
+//
+static void
+glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen)
+{
+ GLXWinConfig *c, *result, *prev = NULL;
+ int i = 0;
+ int n = 0;
+
+ const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB;
+ int numConfigs;
+
+ int attrs[50];
+ unsigned int num_attrs = 0;
+
+ GLWIN_DEBUG_MSG("glxWinCreateConfigsExt");
+
+ screen->base.numFBConfigs = 0;
+ screen->base.fbconfigs = NULL;
+
+ if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs))
+ {
+ ErrorF("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n", glxWinErrorMessage());
+ return;
+ }
+
+ GLWIN_DEBUG_MSG("wglGetPixelFormatAttribivARB says %d possible pixel formats", numConfigs);
+
+ /* alloc */
+ result = xalloc(sizeof(GLXWinConfig) * numConfigs);
+
+ if (NULL == result)
+ {
+ return;
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ /* fill in configs */
+ for (i = 0; i < numConfigs; i++)
+ {
+ int values[num_attrs];
+
+ c = &(result[i]);
+ c->base.next = NULL;
+ c->pixelFormatIndex = i+1;
+
+ if (!wglGetPixelFormatAttribivARBWrapper(hdc, i+1, 0, num_attrs, attrs, values))
+ {
+ ErrorF("wglGetPixelFormatAttribivARB failed for index %d, error %s\n", i+1, glxWinErrorMessage());
+ break;
+ }
+
+#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d))
+
+ if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0))
+ {
+ GLWIN_DEBUG_MSG("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping", i+1);
+ continue;
+ }
+
+ 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;
+
+ 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);
+
+ 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));
+
+ 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;
+
+ if (!getenv("GLWIN_ENABLE_COLORINDEX_FBCONFIGS"))
+ {
+ GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_COLORINDEX_ARB, skipping", i+1);
+ continue;
+ }
+
+ 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_UNSIGNED_FLOAT_EXT:
+ GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, 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;
+ }
+
+ 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);
+
+ 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);
+
+ {
+ int layers = ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0);
+
+ 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;
+
+ c->base.pixmapMode = 0; // ???
+ c->base.visualID = -1; // will be set by __glXScreenInit()
+
+ /* 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));
+
+ case WGL_NO_ACCELERATION_ARB:
+ c->base.visualRating = GLX_SLOW_VISUAL_EXT;
+ break;
+
+ case WGL_GENERIC_ACCELERATION_ARB:
+ case WGL_FULL_ACCELERATION_ARB:
+ c->base.visualRating = GLX_NONE_EXT;
+ break;
+ }
+
+ /* 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;
+ }
+
+ /* 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));
+
+ /*
+ Assume OpenGL RGBA rendering is available on all visuals
+ (it is specified to render to red component in single-channel visuals,
+ if supported, but there doesn't seem to be any mechanism to check if it
+ is supported)
+
+ Color index rendering is only supported on single-channel visuals
+ */
+ if (c->base.visualType == GLX_STATIC_COLOR)
+ {
+ c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT;
+ }
+ else
+ {
+ 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 */
+ 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;
+
+ /* 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;
+ }
+
+ /* OML_swap_method */
+ switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0))
+ {
+ case WGL_SWAP_EXCHANGE_ARB:
+ c->base.swapMethod = GLX_SWAP_EXCHANGE_OML;
+ break;
+
+ case WGL_SWAP_COPY_ARB:
+ c->base.swapMethod = GLX_SWAP_COPY_OML;
+ break;
+
+ default:
+ ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n", ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0));
+
+ case WGL_SWAP_UNDEFINED_ARB:
+ c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
+ }
+
+ /* EXT_import_context */
+ c->base.screen = screen->base.pScreen->myNum;
+
+ /* 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;
+
+ n++;
+
+ // update previous config to point to this config
+ if (prev)
+ prev->base.next = &(c->base);
+
+ prev = c;
+ }
+
+ screen->base.numFBConfigs = n;
+ screen->base.fbconfigs = &(result->base);
+}
diff --git a/xorg-server/hw/xwin/glx/winpriv.c b/xorg-server/hw/xwin/glx/winpriv.c
index 3260ca95c..a35392b26 100644
--- a/xorg-server/hw/xwin/glx/winpriv.c
+++ b/xorg-server/hw/xwin/glx/winpriv.c
@@ -17,13 +17,9 @@ winCreateWindowsWindow (WindowPtr pWin);
* Return size and handles of a window.
* If pWin is NULL, then the information for the root window is requested.
*/
-void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo)
+HWND winGetWindowInfo(WindowPtr pWin)
{
- /* Sanity check */
- if (pWinInfo == NULL)
- return;
-
- winDebug("%s:%d pWin=%p\n", __FUNCTION__, __LINE__, pWin);
+ winDebug("%s: pWin=%p\n", __FUNCTION__, pWin);
/* a real window was requested */
if (pWin != NULL)
@@ -32,14 +28,15 @@ void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo)
ScreenPtr pScreen = pWin->drawable.pScreen;
winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen);
winScreenInfoPtr pScreenInfo = NULL;
+ HWND hwnd = NULL;
if (pWinScreen == NULL)
{
ErrorF("winGetWindowInfo: screen has no privates\n");
- return;
+ return NULL;
}
- pWinInfo->hwnd = pWinScreen->hwndScreen;
+ hwnd = pWinScreen->hwndScreen;
pScreenInfo = pWinScreen->pScreenInfo;
#ifdef XWIN_MULTIWINDOW
@@ -51,7 +48,7 @@ void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo)
if (pWinPriv == NULL)
{
ErrorF("winGetWindowInfo: window has no privates\n");
- return;
+ return hwnd;
}
if (pWinPriv->hWnd == NULL)
@@ -63,10 +60,10 @@ void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo)
if (pWinPriv->hWnd != NULL)
{
/* copy window handle */
- pWinInfo->hwnd = pWinPriv->hWnd;
+ hwnd = pWinPriv->hWnd;
}
- return;
+ return hwnd;
}
#endif
#ifdef XWIN_MULTIWINDOWEXTWM
@@ -78,15 +75,15 @@ void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo)
if (pRLWinPriv == NULL) {
ErrorF("winGetWindowInfo: window has no privates\n");
- return;
+ return hwnd;
}
if (pRLWinPriv->hWnd != NULL)
{
/* copy window handle */
- pWinInfo->hwnd = pRLWinPriv->hWnd;
+ hwnd = pRLWinPriv->hWnd;
}
- return;
+ return hwnd;
}
#endif
}
@@ -95,19 +92,18 @@ void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo)
ScreenPtr pScreen = g_ScreenInfo[0].pScreen;
winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen);
- pWinInfo->hwnd = NULL;
-
if (pWinScreen == NULL)
{
ErrorF("winGetWindowInfo: screen has no privates\n");
- return;
+ return NULL;
}
ErrorF("winGetWindowInfo: returning root window\n");
- pWinInfo->hwnd = pWinScreen->hwndScreen;
+ return pWinScreen->hwndScreen;
}
- return;
+
+ return NULL;
}
Bool
diff --git a/xorg-server/hw/xwin/glx/winpriv.h b/xorg-server/hw/xwin/glx/winpriv.h
index a2f3e5818..dce1edf48 100644
--- a/xorg-server/hw/xwin/glx/winpriv.h
+++ b/xorg-server/hw/xwin/glx/winpriv.h
@@ -1,16 +1,11 @@
-/*
- * Export window information for the Windows-OpenGL GLX implementation.
- *
- * Authors: Alexander Gottwald
- */
-
-#include <X11/Xwindows.h>
-#include <windowstr.h>
-
-typedef struct
-{
- HWND hwnd;
-} winWindowInfoRec, *winWindowInfoPtr;
-
-void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo);
-Bool winCheckScreenAiglxIsSupported(ScreenPtr pScreen);
+/*
+ * Export window information for the Windows-OpenGL GLX implementation.
+ *
+ * Authors: Alexander Gottwald
+ */
+
+#include <X11/Xwindows.h>
+#include <windowstr.h>
+
+HWND winGetWindowInfo(WindowPtr pWin);
+Bool winCheckScreenAiglxIsSupported(ScreenPtr pScreen);
diff --git a/xorg-server/mi/Makefile.am b/xorg-server/mi/Makefile.am
index 9714a21ca..f22dde9a2 100644
--- a/xorg-server/mi/Makefile.am
+++ b/xorg-server/mi/Makefile.am
@@ -1,7 +1,7 @@
noinst_LTLIBRARIES = libmi.la
if XORG
-sdk_HEADERS = mibank.h micmap.h miline.h mipointer.h mi.h mibstore.h \
+sdk_HEADERS = micmap.h miline.h mipointer.h mi.h mibstore.h \
migc.h mipointrst.h mizerarc.h micoord.h mifillarc.h \
mispans.h miwideline.h mistruct.h mifpoly.h mioverlay.h
endif
@@ -11,8 +11,6 @@ AM_CFLAGS = $(DIX_CFLAGS)
libmi_la_SOURCES = \
mi.h \
miarc.c \
- mibank.c \
- mibank.h \
mibitblt.c \
mibstore.c \
mibstore.h \
diff --git a/xorg-server/mi/mibank.c b/xorg-server/mi/mibank.c
deleted file mode 100644
index 9e4d63162..000000000
--- a/xorg-server/mi/mibank.c
+++ /dev/null
@@ -1,2314 +0,0 @@
-/*
- * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of Marc Aurele La France not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. Marc Aurele La France makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as-is" without express or implied warranty.
- *
- * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
- * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * Copyright 1990,91,92,93 by Thomas Roell, Germany.
- * Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA.
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation, and that the name of Thomas Roell nor
- * SGCS be used in advertising or publicity pertaining to distribution
- * of the software without specific, written prior permission.
- * Thomas Roell nor SGCS makes no representations about the suitability
- * of this software for any purpose. It is provided "as is" without
- * express or implied warranty.
- *
- * THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-/*
- * This thing originated from an idea of Edwin Goei and his bank switching
- * code for the DEC TX board.
- */
-
-/*
- * Heavily modified for the XFree86 Project to turn this into an mi wrapper.
- * --- Marc Aurele La France (tsi@xfree86.org)
- */
-
-/*
- * "Heavily modified", indeed! By the time this is finalized, there probably
- * won't be much left of Roell's code...
- *
- * Miscellaneous notes:
- * - Pixels with imbedded bank boundaries are required to be off-screen. There
- * >might< be a way to fool the underlying framebuffer into dealing with
- * partial pixels.
- * - Plans to generalise this to do (hardware) colour plane switching have been
- * dropped due to colour flashing concerns.
- *
- * TODO:
- * - Re-instate shared and double banking for framebuffers whose pixmap formats
- * don't describe how the server "sees" the screen.
- * - Remove remaining assumptions that a pixmap's devPrivate field points
- * directly to its pixel data.
- */
-
-/* #define NO_ALLOCA 1 */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "servermd.h"
-#include "gcstruct.h"
-#include "pixmapstr.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "mi.h"
-#include "mibank.h"
-
-#define BANK_SINGLE 0
-#define BANK_SHARED 1
-#define BANK_DOUBLE 2
-#define BANK_NOBANK 3
-
-typedef struct _miBankScreen
-{
- miBankInfoRec BankInfo;
- unsigned int nBankBPP;
- unsigned int type;
-
- unsigned long nBitsPerBank;
- unsigned long nBitsPerScanline;
- unsigned long nPixelsPerScanlinePadUnit;
-
- PixmapPtr pScreenPixmap;
- PixmapPtr pBankPixmap;
- GCPtr pBankGC;
-
- int nBanks, maxRects;
- RegionPtr *pBanks;
-
- pointer pbits;
-
- /*
- * Screen Wrappers
- */
- CreateScreenResourcesProcPtr CreateScreenResources;
- ModifyPixmapHeaderProcPtr ModifyPixmapHeader;
- CloseScreenProcPtr CloseScreen;
- GetImageProcPtr GetImage;
- GetSpansProcPtr GetSpans;
- CreateGCProcPtr CreateGC;
- CopyWindowProcPtr CopyWindow;
-} miBankScreenRec, *miBankScreenPtr;
-
-typedef struct _miBankGC
-{
- GCOps *wrappedOps, *unwrappedOps;
- GCFuncs *wrappedFuncs, *unwrappedFuncs;
-
- Bool fastCopy, fastPlane;
-
- RegionPtr pBankedClips[1];
-} miBankGCRec, *miBankGCPtr;
-
-typedef struct _miBankQueue
-{
- Bool fastBlit;
- unsigned short srcBankNo;
- unsigned short dstBankNo;
- short x;
- short y;
- short w;
- short h;
-} miBankQueue;
-
-/*
- * CAVEAT: This banking scheme requires that the DDX store Pixmap data in the
- * server's address space.
- */
-
-#define ModifyPixmap(_pPix, _width, _devKind, _pbits) \
- (*pScreen->ModifyPixmapHeader)((_pPix), \
- (_width), -1, -1, -1, (_devKind), (_pbits))
-
-#define SET_SINGLE_BANK(_pPix, _width, _devKind, _no) \
- ModifyPixmap(_pPix, _width, _devKind, \
- (char *)pScreenPriv->BankInfo.pBankA + \
- (*pScreenPriv->BankInfo.SetSourceAndDestinationBanks)(pScreen, (_no)) - \
- (pScreenPriv->BankInfo.BankSize * (_no)))
-
-#define SET_SOURCE_BANK(_pPix, _width, _devKind, _no) \
- ModifyPixmap(_pPix, _width, _devKind, \
- (char *)pScreenPriv->BankInfo.pBankA + \
- (*pScreenPriv->BankInfo.SetSourceBank)(pScreen, (_no)) - \
- (pScreenPriv->BankInfo.BankSize * (_no)))
-
-#define SET_DESTINATION_BANK(_pPix, _width, _devKind, _no) \
- ModifyPixmap(_pPix, _width, _devKind, \
- (char *)pScreenPriv->BankInfo.pBankB + \
- (*pScreenPriv->BankInfo.SetDestinationBank)(pScreen, (_no)) - \
- (pScreenPriv->BankInfo.BankSize * (_no)))
-
-#define xalloc_ARRAY(atype, ntype) xalloc((ntype) * sizeof(atype))
-
-static int miBankScreenKeyIndex;
-static DevPrivateKey miBankScreenKey = &miBankScreenKeyIndex;
-static int miBankGCKeyIndex;
-static DevPrivateKey miBankGCKey = &miBankGCKeyIndex;
-
-static unsigned long miBankGeneration = 0;
-
-#define BANK_SCRPRIVLVAL dixLookupPrivate(&pScreen->devPrivates, miBankScreenKey)
-
-#define BANK_SCRPRIVATE ((miBankScreenPtr)(BANK_SCRPRIVLVAL))
-
-#define BANK_GCPRIVLVAL(pGC) dixLookupPrivate(&(pGC)->devPrivates, miBankGCKey)
-
-#define BANK_GCPRIVATE(pGC) ((miBankGCPtr)(BANK_GCPRIVLVAL(pGC)))
-
-#define PIXMAP_STATUS(_pPix) \
- pointer pbits = (_pPix)->devPrivate.ptr
-
-#define PIXMAP_SAVE(_pPix) \
- PIXMAP_STATUS(_pPix); \
- if (pbits == (pointer)pScreenPriv) \
- (_pPix)->devPrivate.ptr = pScreenPriv->pbits
-
-#define PIXMAP_RESTORE(_pPix) \
- (_pPix)->devPrivate.ptr = pbits
-
-#define BANK_SAVE \
- int width = pScreenPriv->pBankPixmap->drawable.width; \
- int devKind = pScreenPriv->pBankPixmap->devKind; \
- PIXMAP_SAVE(pScreenPriv->pBankPixmap)
-
-#define BANK_RESTORE \
- pScreenPriv->pBankPixmap->drawable.width = width; \
- pScreenPriv->pBankPixmap->devKind = devKind; \
- PIXMAP_RESTORE(pScreenPriv->pBankPixmap)
-
-#define SCREEN_STATUS \
- PIXMAP_STATUS(pScreenPriv->pScreenPixmap)
-
-#define SCREEN_SAVE \
- PIXMAP_SAVE(pScreenPriv->pScreenPixmap)
-
-#define SCREEN_RESTORE \
- PIXMAP_RESTORE(pScreenPriv->pScreenPixmap)
-
-#define SCREEN_INIT \
- miBankScreenPtr pScreenPriv = BANK_SCRPRIVATE
-
-#define SCREEN_UNWRAP(field) \
- pScreen->field = pScreenPriv->field
-
-#define SCREEN_WRAP(field, wrapper) \
- pScreenPriv->field = pScreen->field; \
- pScreen->field = wrapper
-
-#define GC_INIT(pGC) \
- miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC)
-
-#define GC_UNWRAP(pGC) \
- pGCPriv->unwrappedOps = (pGC)->ops; \
- pGCPriv->unwrappedFuncs = (pGC)->funcs; \
- (pGC)->ops = pGCPriv->wrappedOps; \
- (pGC)->funcs = pGCPriv->wrappedFuncs
-
-#define GC_WRAP(pGC) \
- pGCPriv->wrappedOps = (pGC)->ops; \
- pGCPriv->wrappedFuncs = (pGC)->funcs; \
- (pGC)->ops = pGCPriv->unwrappedOps; \
- (pGC)->funcs = pGCPriv->unwrappedFuncs
-
-#define IS_BANKED(pDrawable) \
- ((pbits == (pointer)pScreenPriv) && \
- (((DrawablePtr)(pDrawable))->type == DRAWABLE_WINDOW))
-
-#define CLIP_SAVE \
- RegionPtr pOrigCompositeClip = pGC->pCompositeClip
-
-#define CLIP_RESTORE \
- pGC->pCompositeClip = pOrigCompositeClip
-
-#define GCOP_INIT \
- ScreenPtr pScreen = pGC->pScreen; \
- SCREEN_INIT; \
- GC_INIT(pGC)
-
-#define GCOP_UNWRAP \
- GC_UNWRAP(pGC)
-
-#define GCOP_WRAP \
- GC_WRAP(pGC)
-
-#define GCOP_TOP_PART \
- for (i = 0; i < pScreenPriv->nBanks; i++) \
- { \
- if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) \
- continue; \
- GCOP_UNWRAP; \
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i)
-
-#define GCOP_BOTTOM_PART \
- GCOP_WRAP; \
- }
-
-#define GCOP_SIMPLE(statement) \
- if (nArray > 0) \
- { \
- GCOP_INIT; \
- SCREEN_SAVE; \
- if (!IS_BANKED(pDrawable)) \
- { \
- GCOP_UNWRAP; \
- statement; \
- GCOP_WRAP; \
- } \
- else \
- { \
- int i; \
- CLIP_SAVE; \
- GCOP_TOP_PART; \
- statement; \
- GCOP_BOTTOM_PART; \
- CLIP_RESTORE; \
- } \
- SCREEN_RESTORE; \
- }
-
-#define GCOP_0D_ARGS mode,
-#define GCOP_1D_ARGS
-#define GCOP_2D_ARGS shape, mode,
-
-#define GCOP_COMPLEX(aop, atype) \
- if (nArray > 0) \
- { \
- GCOP_INIT; \
- SCREEN_SAVE; \
- if (!IS_BANKED(pDrawable)) \
- { \
- GCOP_UNWRAP; \
- (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, pArray); \
- GCOP_WRAP; \
- } \
- else \
- { \
- atype *aarg = pArray, *acopy; \
- int i; \
- CLIP_SAVE; \
- if ((acopy = xalloc_ARRAY(atype, nArray))) \
- aarg = acopy; \
- GCOP_TOP_PART; \
- if (acopy) \
- memcpy(acopy, pArray, nArray * sizeof(atype)); \
- (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, aarg); \
- GCOP_BOTTOM_PART; \
- xfree(acopy); \
- CLIP_RESTORE; \
- } \
- SCREEN_RESTORE; \
- }
-
-/*********************
- * Utility functions *
- *********************/
-
-static int
-miBankOf(
- miBankScreenPtr pScreenPriv,
- int x,
- int y
-)
-{
- int iBank = ((x * (int)pScreenPriv->nBankBPP) +
- (y * (long)pScreenPriv->nBitsPerScanline)) /
- (long)pScreenPriv->nBitsPerBank;
-
- if (iBank < 0)
- iBank = 0;
- else if (iBank >= pScreenPriv->nBanks)
- iBank = pScreenPriv->nBanks - 1;
-
- return iBank;
-}
-
-#define FirstBankOf(_x, _y) miBankOf(pScreenPriv, (_x), (_y))
-#define LastBankOf(_x, _y) miBankOf(pScreenPriv, (_x) - 1, (_y))
-
-/* Determine banking type from the BankInfoRec */
-static unsigned int
-miBankDeriveType(
- ScreenPtr pScreen,
- miBankInfoPtr pBankInfo
-)
-{
- unsigned int type;
-
- if (pBankInfo->pBankA == pBankInfo->pBankB)
- {
- if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
- {
- if (pBankInfo->SetSourceAndDestinationBanks !=
- pBankInfo->SetSourceBank)
- return BANK_NOBANK;
-
- type = BANK_SINGLE;
- }
- else
- {
- if (pBankInfo->SetSourceAndDestinationBanks ==
- pBankInfo->SetDestinationBank)
- return BANK_NOBANK;
- if (pBankInfo->SetSourceAndDestinationBanks ==
- pBankInfo->SetSourceBank)
- return BANK_NOBANK;
-
- type = BANK_SHARED;
- }
- }
- else
- {
- if ((unsigned long)abs((char *)pBankInfo->pBankA -
- (char *)pBankInfo->pBankB) < pBankInfo->BankSize)
- return BANK_NOBANK;
-
- if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
- {
- if (pBankInfo->SetSourceAndDestinationBanks !=
- pBankInfo->SetSourceBank)
- return BANK_NOBANK;
- }
- else
- {
- if (pBankInfo->SetSourceAndDestinationBanks ==
- pBankInfo->SetDestinationBank)
- return BANK_NOBANK;
- }
-
- type = BANK_DOUBLE;
- }
-
- /*
- * Internal limitation: Currently, only single banking is supported when
- * the pixmap format and the screen's pixel format are different. The
- * following test is only partially successful at detecting this condition.
- */
- if (pBankInfo->nBankDepth != pScreen->rootDepth)
- type = BANK_SINGLE;
-
- return type;
-}
-
-/* Least common multiple */
-static unsigned int
-miLCM(
- unsigned int x,
- unsigned int y
-)
-{
- unsigned int m = x, n = y, o;
-
- while ((o = m % n))
- {
- m = n;
- n = o;
- }
-
- return (x / n) * y;
-}
-
-/******************
- * GCOps wrappers *
- ******************/
-
-static void
-miBankFillSpans(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- DDXPointPtr pptInit,
- int *pwidthInit,
- int fSorted
-)
-{
- GCOP_SIMPLE((*pGC->ops->FillSpans)(pDrawable, pGC,
- nArray, pptInit, pwidthInit, fSorted));
-}
-
-static void
-miBankSetSpans(
- DrawablePtr pDrawable,
- GCPtr pGC,
- char *psrc,
- DDXPointPtr ppt,
- int *pwidth,
- int nArray,
- int fSorted
-)
-{
- GCOP_SIMPLE((*pGC->ops->SetSpans)(pDrawable, pGC, psrc,
- ppt, pwidth, nArray, fSorted));
-}
-
-static void
-miBankPutImage(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int depth,
- int x,
- int y,
- int w,
- int h,
- int leftPad,
- int format,
- char *pImage
-)
-{
- if ((w > 0) && (h > 0))
- {
- GCOP_INIT;
- SCREEN_SAVE;
-
- if (!IS_BANKED(pDrawable))
- {
- GCOP_UNWRAP;
-
- (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
- leftPad, format, pImage);
-
- GCOP_WRAP;
- }
- else
- {
- int i, j;
-
- CLIP_SAVE;
-
- i = FirstBankOf(x + pDrawable->x, y + pDrawable->y);
- j = LastBankOf(x + pDrawable->x + w, y + pDrawable->y + h);
- for (; i <= j; i++)
- {
- if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
- continue;
-
- GCOP_UNWRAP;
-
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
-
- (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
- leftPad, format, pImage);
-
- GCOP_WRAP;
- }
-
- CLIP_RESTORE;
- }
-
- SCREEN_RESTORE;
- }
-}
-
-/*
- * Here the CopyArea/CopyPlane wrappers. First off, we have to clip against
- * the source in order to make the minimal number of copies in case of slow
- * systems. Also the exposure handling is quite tricky. Special attention
- * is to be given to the way the copies are sequenced. The list of boxes after
- * the source clip is used to build a workqueue, that contains the atomic
- * copies (i.e. only from one bank to one bank). Doing so produces a minimal
- * list of things to do.
- */
-static RegionPtr
-miBankCopy(
- DrawablePtr pSrc,
- DrawablePtr pDst,
- GCPtr pGC,
- int srcx,
- int srcy,
- int w,
- int h,
- int dstx,
- int dsty,
- unsigned long plane,
- Bool SinglePlane
-)
-{
- int cx1, cy1, cx2, cy2;
- int ns, nd, nse, nde, dx, dy, xorg = 0, yorg = 0;
- int maxWidth = 0, maxHeight = 0, paddedWidth = 0;
- int nBox, nBoxClipSrc, nBoxClipDst, nQueue;
- BoxPtr pBox, pBoxClipSrc, pBoxClipDst;
- BoxRec fastBox, ccBox;
- RegionPtr ret = NULL, prgnSrcClip = NULL;
- RegionRec rgnDst;
- char *pImage = NULL;
- miBankQueue *pQueue, *pQueueNew, *Queue;
- miBankQueue *pQueueTmp, *pQueueNext, *pQueueBase;
- Bool fastBlit, freeSrcClip, fastClip;
- Bool fExpose = FALSE, fastExpose = FALSE;
-
- GCOP_INIT;
- SCREEN_SAVE;
-
- if (!IS_BANKED(pSrc) && !IS_BANKED(pDst))
- {
- GCOP_UNWRAP;
-
- if (SinglePlane)
- ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
- srcx, srcy, w, h, dstx, dsty, plane);
- else
- ret = (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
- srcx, srcy, w, h, dstx, dsty);
-
- GCOP_WRAP;
- }
- else if (!IS_BANKED(pDst))
- {
- fExpose = pGC->fExpose;
- pGC->fExpose = FALSE;
-
- xorg = pSrc->x;
- yorg = pSrc->y;
- dx = dstx - srcx;
- dy = dsty - srcy;
- srcx += xorg;
- srcy += yorg;
-
- ns = FirstBankOf(srcx, srcy);
- nse = LastBankOf(srcx + w, srcy + h);
- for (; ns <= nse; ns++)
- {
- if (!pScreenPriv->pBanks[ns])
- continue;
-
- nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
- pBox = REGION_RECTS(pScreenPriv->pBanks[ns]);
-
- for (; nBox--; pBox++)
- {
- cx1 = max(pBox->x1, srcx);
- cy1 = max(pBox->y1, srcy);
- cx2 = min(pBox->x2, srcx + w);
- cy2 = min(pBox->y2, srcy + h);
-
- if ((cx1 >= cx2) || (cy1 >= cy2))
- continue;
-
- GCOP_UNWRAP;
-
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, ns);
-
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
- cx1 - xorg, cy1 - yorg,
- cx2 - cx1, cy2 - cy1,
- cx1 + dx - xorg, cy1 + dy - yorg, plane);
- else
- (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
- cx1 - xorg, cy1 - yorg,
- cx2 - cx1, cy2 - cy1,
- cx1 + dx - xorg, cy1 + dy - yorg);
-
- GCOP_WRAP;
- }
- }
-
- pGC->fExpose = fExpose;
- srcx -= xorg;
- srcy -= yorg;
- }
- else if (!IS_BANKED(pSrc))
- {
- CLIP_SAVE;
-
- if (pGC->miTranslate)
- {
- xorg = pDst->x;
- yorg = pDst->y;
- }
- dx = srcx - dstx;
- dy = srcy - dsty;
- dstx += xorg;
- dsty += yorg;
-
- nd = FirstBankOf(dstx, dsty);
- nde = LastBankOf(dstx + w, dsty + h);
- for (; nd <= nde; nd++)
- {
- if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[nd]))
- continue;
-
- /*
- * It's faster to let the lower-level CopyArea do the clipping
- * within each bank.
- */
- nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
- pBox = REGION_RECTS(pScreenPriv->pBanks[nd]);
-
- for (; nBox--; pBox++)
- {
- cx1 = max(pBox->x1, dstx);
- cy1 = max(pBox->y1, dsty);
- cx2 = min(pBox->x2, dstx + w);
- cy2 = min(pBox->y2, dsty + h);
-
- if ((cx1 >= cx2) || (cy1 >= cy2))
- continue;
-
- GCOP_UNWRAP;
-
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, nd);
-
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
- cx1 + dx - xorg, cy1 + dy - yorg,
- cx2 - cx1, cy2 - cy1,
- cx1 - xorg, cy1 - yorg, plane);
- else
- (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
- cx1 + dx - xorg, cy1 + dy - yorg,
- cx2 - cx1, cy2 - cy1,
- cx1 - xorg, cy1 - yorg);
-
- GCOP_WRAP;
- }
- }
-
- CLIP_RESTORE;
- }
- else /* IS_BANKED(pSrc) && IS_BANKED(pDst) */
- {
- CLIP_SAVE;
-
- fExpose = pGC->fExpose;
-
- fastBox.x1 = srcx + pSrc->x;
- fastBox.y1 = srcy + pSrc->y;
- fastBox.x2 = fastBox.x1 + w;
- fastBox.y2 = fastBox.y1 + h;
-
- dx = dstx - fastBox.x1;
- dy = dsty - fastBox.y1;
- if (pGC->miTranslate)
- {
- xorg = pDst->x;
- yorg = pDst->y;
- }
-
- /*
- * Clip against the source. Otherwise we will blit too much for SINGLE
- * and SHARED banked systems.
- */
- freeSrcClip = FALSE;
- fastClip = FALSE;
- fastExpose = FALSE;
-
- if (pGC->subWindowMode != IncludeInferiors)
- prgnSrcClip = &((WindowPtr)pSrc)->clipList;
- else if (!((WindowPtr)pSrc)->parent)
- fastClip = TRUE;
- else if ((pSrc == pDst) && (pGC->clientClipType == CT_NONE))
- prgnSrcClip = pGC->pCompositeClip;
- else
- {
- prgnSrcClip = NotClippedByChildren((WindowPtr)pSrc);
- freeSrcClip = TRUE;
- }
-
- if (fastClip)
- {
- fastExpose = TRUE;
-
- /*
- * Clip the source. If regions extend beyond the source size, make
- * sure exposure events get sent.
- */
- if (fastBox.x1 < pSrc->x)
- {
- fastBox.x1 = pSrc->x;
- fastExpose = FALSE;
- }
- if (fastBox.y1 < pSrc->y)
- {
- fastBox.y1 = pSrc->y;
- fastExpose = FALSE;
- }
- if (fastBox.x2 > pSrc->x + (int) pSrc->width)
- {
- fastBox.x2 = pSrc->x + (int) pSrc->width;
- fastExpose = FALSE;
- }
- if (fastBox.y2 > pSrc->y + (int) pSrc->height)
- {
- fastBox.y2 = pSrc->y + (int) pSrc->height;
- fastExpose = FALSE;
- }
-
- nBox = 1;
- pBox = &fastBox;
- }
- else
- {
- REGION_INIT(pScreen, &rgnDst, &fastBox, 1);
- REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, prgnSrcClip);
- pBox = REGION_RECTS(&rgnDst);
- nBox = REGION_NUM_RECTS(&rgnDst);
- }
-
- /*
- * fastBlit can only be TRUE if we don't need to worry about attempts
- * to read partial pixels through the destination bank.
- */
- if (SinglePlane)
- fastBlit = pGCPriv->fastPlane;
- else
- fastBlit = pGCPriv->fastCopy;
-
- nQueue = nBox * pScreenPriv->maxRects * 2;
- pQueue = Queue = xalloc_ARRAY(miBankQueue, nQueue);
-
- if (Queue)
- {
- for (; nBox--; pBox++)
- {
- ns = FirstBankOf(pBox->x1, pBox->y1);
- nse = LastBankOf(pBox->x2, pBox->y2);
- for (; ns <= nse; ns++)
- {
- if (!pScreenPriv->pBanks[ns])
- continue;
-
- nBoxClipSrc = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
- pBoxClipSrc = REGION_RECTS(pScreenPriv->pBanks[ns]);
-
- for (; nBoxClipSrc--; pBoxClipSrc++)
- {
- cx1 = max(pBox->x1, pBoxClipSrc->x1);
- cy1 = max(pBox->y1, pBoxClipSrc->y1);
- cx2 = min(pBox->x2, pBoxClipSrc->x2);
- cy2 = min(pBox->y2, pBoxClipSrc->y2);
-
- /* Check to see if the region is empty */
- if ((cx1 >= cx2) || (cy1 >= cy2))
- continue;
-
- /* Translate c[xy]* to destination coordinates */
- cx1 += dx + xorg;
- cy1 += dy + yorg;
- cx2 += dx + xorg;
- cy2 += dy + yorg;
-
- nd = FirstBankOf(cx1, cy1);
- nde = LastBankOf(cx2, cy2);
- for (; nd <= nde; nd++)
- {
- if (!pGCPriv->pBankedClips[nd])
- continue;
-
- /*
- * Clients can send quite large clip descriptions,
- * so use the bank clips here instead.
- */
- nBoxClipDst =
- REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
- pBoxClipDst =
- REGION_RECTS(pScreenPriv->pBanks[nd]);
-
- for (; nBoxClipDst--; pBoxClipDst++)
- {
- ccBox.x1 = max(cx1, pBoxClipDst->x1);
- ccBox.y1 = max(cy1, pBoxClipDst->y1);
- ccBox.x2 = min(cx2, pBoxClipDst->x2);
- ccBox.y2 = min(cy2, pBoxClipDst->y2);
-
- /* Check to see if the region is empty */
- if ((ccBox.x1 >= ccBox.x2) ||
- (ccBox.y1 >= ccBox.y2))
- continue;
-
- pQueue->srcBankNo = ns;
- pQueue->dstBankNo = nd;
- pQueue->x = ccBox.x1 - xorg;
- pQueue->y = ccBox.y1 - yorg;
- pQueue->w = ccBox.x2 - ccBox.x1;
- pQueue->h = ccBox.y2 - ccBox.y1;
-
- if (maxWidth < pQueue->w)
- maxWidth = pQueue->w;
- if (maxHeight < pQueue->h)
- maxHeight = pQueue->h;
-
- /*
- * When shared banking is used and the source
- * and destination banks differ, prevent
- * attempts to fetch partial scanline pad units
- * through the destination bank.
- */
- pQueue->fastBlit = fastBlit;
- if (fastBlit &&
- (pScreenPriv->type == BANK_SHARED) &&
- (ns != nd) &&
- ((ccBox.x1 %
- pScreenPriv->nPixelsPerScanlinePadUnit) ||
- (ccBox.x2 %
- pScreenPriv->nPixelsPerScanlinePadUnit) ||
- (RECT_IN_REGION(pScreen,
- pGCPriv->pBankedClips[nd], &ccBox) !=
- rgnIN)))
- pQueue->fastBlit = FALSE;
- pQueue++;
- }
- }
- }
- }
- }
- }
-
- if (!fastClip)
- {
- REGION_UNINIT(pScreen, &rgnDst);
- if (freeSrcClip)
- REGION_DESTROY(pScreen, prgnSrcClip);
- }
-
- pQueueNew = pQueue;
- nQueue = pQueue - Queue;
-
- if (nQueue > 0)
- {
- BANK_SAVE;
-
- pQueue = Queue;
-
- if ((nQueue > 1) &&
- ((pSrc == pDst) || (pGC->subWindowMode == IncludeInferiors)))
- {
- if ((srcy + pSrc->y) < (dsty + yorg))
- {
- /* Sort from bottom to top */
- pQueueBase = pQueueNext = pQueue + nQueue - 1;
-
- while (pQueueBase >= pQueue)
- {
- while ((pQueueNext >= pQueue) &&
- (pQueueBase->y == pQueueNext->y))
- pQueueNext--;
-
- pQueueTmp = pQueueNext + 1;
- while (pQueueTmp <= pQueueBase)
- *pQueueNew++ = *pQueueTmp++;
-
- pQueueBase = pQueueNext;
- }
-
- pQueueNew -= nQueue;
- pQueue = pQueueNew;
- pQueueNew = Queue;
- }
-
- if ((srcx + pSrc->x) < (dstx + xorg))
- {
- /* Sort from right to left */
- pQueueBase = pQueueNext = pQueue;
-
- while (pQueueBase < pQueue + nQueue)
- {
- while ((pQueueNext < pQueue + nQueue) &&
- (pQueueNext->y == pQueueBase->y))
- pQueueNext++;
-
- pQueueTmp = pQueueNext;
- while (pQueueTmp != pQueueBase)
- *pQueueNew++ = *--pQueueTmp;
-
- pQueueBase = pQueueNext;
- }
-
- pQueueNew -= nQueue;
- pQueue = pQueueNew;
- }
- }
-
- paddedWidth = PixmapBytePad(maxWidth,
- pScreenPriv->pScreenPixmap->drawable.depth);
- pImage = xalloc(paddedWidth * maxHeight);
-
- pGC->fExpose = FALSE;
-
- while (nQueue--)
- {
- pGC->pCompositeClip = pGCPriv->pBankedClips[pQueue->dstBankNo];
-
- GCOP_UNWRAP;
-
- if (pQueue->srcBankNo == pQueue->dstBankNo)
- {
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
- -1, -1, pQueue->srcBankNo);
-
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
- pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
- pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane);
- else
- (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
- pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
- pQueue->w, pQueue->h, pQueue->x, pQueue->y);
- }
- else if (pQueue->fastBlit)
- {
- SET_SOURCE_BANK (pScreenPriv->pBankPixmap,
- pScreenPriv->pScreenPixmap->drawable.width,
- pScreenPriv->pScreenPixmap->devKind,
- pQueue->srcBankNo);
- SET_DESTINATION_BANK(pScreenPriv->pScreenPixmap,
- -1, -1, pQueue->dstBankNo);
-
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(
- (DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC,
- pQueue->x - dx, pQueue->y - dy,
- pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane);
- else
- (*pGC->ops->CopyArea)(
- (DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC,
- pQueue->x - dx, pQueue->y - dy,
- pQueue->w, pQueue->h, pQueue->x, pQueue->y);
- }
- else if (pImage)
- {
- ModifyPixmap(pScreenPriv->pBankPixmap,
- maxWidth, paddedWidth, pImage);
-
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
- -1, -1, pQueue->srcBankNo);
-
- (*pScreenPriv->pBankGC->ops->CopyArea)(
- pSrc, (DrawablePtr)pScreenPriv->pBankPixmap,
- pScreenPriv->pBankGC,
- pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
- pQueue->w, pQueue->h, 0, 0);
-
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
- -1, -1, pQueue->dstBankNo);
-
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(
- (DrawablePtr)pScreenPriv->pBankPixmap,
- pDst, pGC, 0, 0, pQueue->w, pQueue->h,
- pQueue->x, pQueue->y, plane);
- else
- (*pGC->ops->CopyArea)(
- (DrawablePtr)pScreenPriv->pBankPixmap,
- pDst, pGC, 0, 0, pQueue->w, pQueue->h,
- pQueue->x, pQueue->y);
- }
-
- GCOP_WRAP;
-
- pQueue++;
- }
-
- xfree(pImage);
-
- BANK_RESTORE;
- }
-
- CLIP_RESTORE;
-
- pGC->fExpose = fExpose;
-
- xfree(Queue);
- }
-
- SCREEN_RESTORE;
-
- if (!fExpose || fastExpose)
- return ret;
-
- return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0);
-}
-
-static RegionPtr
-miBankCopyArea(
- DrawablePtr pSrc,
- DrawablePtr pDst,
- GCPtr pGC,
- int srcx,
- int srcy,
- int w,
- int h,
- int dstx,
- int dsty
-)
-{
- return miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0, FALSE);
-}
-
-static RegionPtr
-miBankCopyPlane(
- DrawablePtr pSrc,
- DrawablePtr pDst,
- GCPtr pGC,
- int srcx,
- int srcy,
- int w,
- int h,
- int dstx,
- int dsty,
- unsigned long plane
-)
-{
- return
- miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane, TRUE);
-}
-
-static void
-miBankPolyPoint(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int mode,
- int nArray,
- xPoint *pArray
-)
-{
-# define GCOP_ARGS GCOP_0D_ARGS
- GCOP_COMPLEX(PolyPoint, xPoint);
-# undef GCOP_ARGS
-}
-
-static void
-miBankPolylines(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int mode,
- int nArray,
- DDXPointPtr pArray
-)
-{
-# define GCOP_ARGS GCOP_0D_ARGS
- GCOP_COMPLEX(Polylines, DDXPointRec);
-# undef GCOP_ARGS
-}
-
-static void
-miBankPolySegment(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xSegment *pArray
-)
-{
-# define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolySegment, xSegment);
-# undef GCOP_ARGS
-}
-
-static void
-miBankPolyRectangle(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xRectangle *pArray
-)
-{
-# define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolyRectangle, xRectangle);
-# undef GCOP_ARGS
-}
-
-static void
-miBankPolyArc(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xArc *pArray
-)
-{
-# define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolyArc, xArc);
-# undef GCOP_ARGS
-}
-
-static void
-miBankFillPolygon(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int shape,
- int mode,
- int nArray,
- DDXPointRec *pArray
-)
-{
-# define GCOP_ARGS GCOP_2D_ARGS
- GCOP_COMPLEX(FillPolygon, DDXPointRec);
-# undef GCOP_ARGS
-}
-
-static void
-miBankPolyFillRect(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xRectangle *pArray
-)
-{
-# define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolyFillRect, xRectangle);
-# undef GCOP_ARGS
-}
-
-static void
-miBankPolyFillArc(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xArc *pArray
-)
-{
-# define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolyFillArc, xArc);
-# undef GCOP_ARGS
-}
-
-static int
-miBankPolyText8(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int nArray,
- char *pchar
-)
-{
- int retval = x;
-
- GCOP_SIMPLE(retval =
- (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, nArray, pchar));
-
- return retval;
-}
-
-static int
-miBankPolyText16(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int nArray,
- unsigned short *pchar
-)
-{
- int retval = x;
-
- GCOP_SIMPLE(retval =
- (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, nArray, pchar));
-
- return retval;
-}
-
-static void
-miBankImageText8(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int nArray,
- char *pchar
-)
-{
- GCOP_SIMPLE((*pGC->ops->ImageText8)(pDrawable, pGC, x, y, nArray, pchar));
-}
-
-static void
-miBankImageText16(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int nArray,
- unsigned short *pchar
-)
-{
- GCOP_SIMPLE((*pGC->ops->ImageText16)(pDrawable, pGC, x, y, nArray, pchar));
-}
-
-static void
-miBankImageGlyphBlt(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- unsigned int nArray,
- CharInfoPtr *ppci,
- pointer pglyphBase
-)
-{
- GCOP_SIMPLE((*pGC->ops->ImageGlyphBlt)(pDrawable, pGC,
- x, y, nArray, ppci, pglyphBase));
-}
-
-static void
-miBankPolyGlyphBlt(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- unsigned int nArray,
- CharInfoPtr *ppci,
- pointer pglyphBase
-)
-{
- GCOP_SIMPLE((*pGC->ops->PolyGlyphBlt)(pDrawable, pGC,
- x, y, nArray, ppci, pglyphBase));
-}
-
-static void
-miBankPushPixels(
- GCPtr pGC,
- PixmapPtr pBitmap,
- DrawablePtr pDrawable,
- int w,
- int h,
- int x,
- int y
-)
-{
- if ((w > 0) && (h > 0))
- {
- GCOP_INIT;
- SCREEN_SAVE;
-
- if (!IS_BANKED(pDrawable))
- {
- GCOP_UNWRAP;
-
- (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
-
- GCOP_WRAP;
- }
- else
- {
- int i, j;
-
- CLIP_SAVE;
-
- i = FirstBankOf(x, y);
- j = LastBankOf(x + w, y + h);
- for (; i <= j; i++)
- {
- if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
- continue;
-
- GCOP_UNWRAP;
-
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
-
- (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
-
- GCOP_WRAP;
- }
-
- CLIP_RESTORE;
- }
-
- SCREEN_RESTORE;
- }
-}
-
-static GCOps miBankGCOps =
-{
- miBankFillSpans,
- miBankSetSpans,
- miBankPutImage,
- miBankCopyArea,
- miBankCopyPlane,
- miBankPolyPoint,
- miBankPolylines,
- miBankPolySegment,
- miBankPolyRectangle,
- miBankPolyArc,
- miBankFillPolygon,
- miBankPolyFillRect,
- miBankPolyFillArc,
- miBankPolyText8,
- miBankPolyText16,
- miBankImageText8,
- miBankImageText16,
- miBankImageGlyphBlt,
- miBankPolyGlyphBlt,
- miBankPushPixels,
- {NULL} /* devPrivate */
-};
-
-/********************
- * GCFuncs wrappers *
- ********************/
-
-static void
-miBankValidateGC(
- GCPtr pGC,
- unsigned long changes,
- DrawablePtr pDrawable
-)
-{
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
-
- (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
-
- if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
- (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)))
- {
- ScreenPtr pScreen = pGC->pScreen;
- RegionPtr prgnClip;
- unsigned long planemask;
- int i;
-
- SCREEN_INIT;
- SCREEN_SAVE;
-
- if (IS_BANKED(pDrawable))
- {
- for (i = 0; i < pScreenPriv->nBanks; i++)
- {
- if (!pScreenPriv->pBanks[i])
- continue;
-
- if (!(prgnClip = pGCPriv->pBankedClips[i]))
- prgnClip = REGION_CREATE(pScreen, NULL, 1);
-
- REGION_INTERSECT(pScreen, prgnClip,
- pScreenPriv->pBanks[i], pGC->pCompositeClip);
-
- if ((REGION_NUM_RECTS(prgnClip) <= 1) &&
- ((prgnClip->extents.x1 == prgnClip->extents.x2) ||
- (prgnClip->extents.y1 == prgnClip->extents.y2)))
- {
- REGION_DESTROY(pScreen, prgnClip);
- pGCPriv->pBankedClips[i] = NULL;
- }
- else
- pGCPriv->pBankedClips[i] = prgnClip;
- }
-
- /*
- * fastCopy and fastPlane can only be TRUE if we don't need to
- * worry about attempts to read partial pixels through the
- * destination bank.
- */
- switch (pScreenPriv->type)
- {
- case BANK_SHARED:
- pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
-
- if ((pGC->alu != GXclear) && (pGC->alu != GXcopy) &&
- (pGC->alu != GXcopyInverted) && (pGC->alu != GXset))
- break;
-
- if (pScreen->rootDepth == 1)
- pGCPriv->fastPlane = TRUE;
-
- /* This is probably paranoia */
- if ((pDrawable->depth != pScreen->rootDepth) ||
- (pDrawable->depth != pGC->depth))
- break;
-
- planemask = (1 << pGC->depth) - 1;
- if ((pGC->planemask & planemask) == planemask)
- pGCPriv->fastCopy = TRUE;
-
- break;
-
- case BANK_DOUBLE:
- pGCPriv->fastCopy = pGCPriv->fastPlane = TRUE;
- break;
-
- default:
- pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
- break;
- }
- }
- else
- {
- /*
- * Here we are on a pixmap and don't need all that special clipping
- * stuff, hence free it.
- */
- for (i = 0; i < pScreenPriv->nBanks; i++)
- {
- if (!pGCPriv->pBankedClips[i])
- continue;
-
- REGION_DESTROY(pScreen, pGCPriv->pBankedClips[i]);
- pGCPriv->pBankedClips[i] = NULL;
- }
- }
-
- SCREEN_RESTORE;
- }
-
- GC_WRAP(pGC);
-}
-
-static void
-miBankChangeGC(
- GCPtr pGC,
- unsigned long mask
-)
-{
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
-
- (*pGC->funcs->ChangeGC)(pGC, mask);
-
- GC_WRAP(pGC);
-}
-
-static void
-miBankCopyGC(
- GCPtr pGCSrc,
- unsigned long mask,
- GCPtr pGCDst
-)
-{
- GC_INIT(pGCDst);
- GC_UNWRAP(pGCDst);
-
- (*pGCDst->funcs->CopyGC)(pGCSrc, mask, pGCDst);
-
- GC_WRAP(pGCDst);
-}
-
-static void
-miBankDestroyGC(
- GCPtr pGC
-)
-{
- ScreenPtr pScreen = pGC->pScreen;
- int i;
-
- SCREEN_INIT;
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
-
- (*pGC->funcs->DestroyGC)(pGC);
-
- for (i = 0; i < pScreenPriv->nBanks; i++)
- {
- if (!pGCPriv->pBankedClips[i])
- continue;
-
- REGION_DESTROY(pScreen, pGCPriv->pBankedClips[i]);
- pGCPriv->pBankedClips[i] = NULL;
- }
-
- GC_WRAP(pGC);
-}
-
-static void
-miBankChangeClip(
- GCPtr pGC,
- int type,
- pointer pvalue,
- int nrects
-)
-{
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
-
- (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
-
- GC_WRAP(pGC);
-}
-
-static void
-miBankDestroyClip(
- GCPtr pGC
-)
-{
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
-
- (*pGC->funcs->DestroyClip)(pGC);
-
- GC_WRAP(pGC);
-}
-
-static void
-miBankCopyClip(
- GCPtr pGCDst,
- GCPtr pGCSrc
-)
-{
- GC_INIT(pGCDst);
- GC_UNWRAP(pGCDst);
-
- (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc);
-
- GC_WRAP(pGCDst);
-}
-
-static GCFuncs miBankGCFuncs =
-{
- miBankValidateGC,
- miBankChangeGC,
- miBankCopyGC,
- miBankDestroyGC,
- miBankChangeClip,
- miBankDestroyClip,
- miBankCopyClip
-};
-
-/*******************
- * Screen Wrappers *
- *******************/
-
-static Bool
-miBankCreateScreenResources(
- ScreenPtr pScreen
-)
-{
- Bool retval;
-
- SCREEN_INIT;
- SCREEN_UNWRAP(CreateScreenResources);
-
- if ((retval = (*pScreen->CreateScreenResources)(pScreen)))
- {
- /* Set screen buffer address to something recognizable */
- pScreenPriv->pScreenPixmap = (*pScreen->GetScreenPixmap)(pScreen);
- pScreenPriv->pbits = pScreenPriv->pScreenPixmap->devPrivate.ptr;
- pScreenPriv->pScreenPixmap->devPrivate.ptr = (pointer)pScreenPriv;
-
- /* Get shadow pixmap; width & height of 0 means no pixmap data */
- pScreenPriv->pBankPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0,
- pScreenPriv->pScreenPixmap->drawable.depth, 0);
- if (!pScreenPriv->pBankPixmap)
- retval = FALSE;
- }
-
- /* Shadow the screen */
- if (retval)
- retval = (*pScreen->ModifyPixmapHeader)(pScreenPriv->pBankPixmap,
- pScreenPriv->pScreenPixmap->drawable.width,
- pScreenPriv->pScreenPixmap->drawable.height,
- pScreenPriv->pScreenPixmap->drawable.depth,
- pScreenPriv->pScreenPixmap->drawable.bitsPerPixel,
- pScreenPriv->pScreenPixmap->devKind, NULL);
-
- /* Create shadow GC */
- if (retval)
- {
- pScreenPriv->pBankGC = CreateScratchGC(pScreen,
- pScreenPriv->pBankPixmap->drawable.depth);
- if (!pScreenPriv->pBankGC)
- retval = FALSE;
- }
-
- /* Validate shadow GC */
- if (retval)
- {
- pScreenPriv->pBankGC->graphicsExposures = FALSE;
- pScreenPriv->pBankGC->subWindowMode = IncludeInferiors;
- ValidateGC((DrawablePtr)pScreenPriv->pBankPixmap,
- pScreenPriv->pBankGC);
- }
-
- SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
-
- return retval;
-}
-
-static Bool
-miBankModifyPixmapHeader(
- PixmapPtr pPixmap,
- int width,
- int height,
- int depth,
- int bitsPerPixel,
- int devKind,
- pointer pPixData
-)
-{
- Bool retval = FALSE;
-
- if (pPixmap)
- {
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
-
- SCREEN_INIT;
- PIXMAP_SAVE(pPixmap);
- SCREEN_UNWRAP(ModifyPixmapHeader);
-
- retval = (*pScreen->ModifyPixmapHeader)(pPixmap, width, height,
- depth, bitsPerPixel, devKind, pPixData);
-
- SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
-
- if (pbits == (pointer)pScreenPriv)
- {
- pScreenPriv->pbits = pPixmap->devPrivate.ptr;
- pPixmap->devPrivate.ptr = pbits;
- }
- }
-
- return retval;
-}
-
-static Bool
-miBankCloseScreen(
- int nIndex,
- ScreenPtr pScreen
-)
-{
- int i;
-
- SCREEN_INIT;
-
- /* Free shadow GC */
- FreeScratchGC(pScreenPriv->pBankGC);
-
- /* Free shadow pixmap */
- (*pScreen->DestroyPixmap)(pScreenPriv->pBankPixmap);
-
- /* Restore screen pixmap devPrivate pointer */
- pScreenPriv->pScreenPixmap->devPrivate.ptr = pScreenPriv->pbits;
-
- /* Delete bank clips */
- for (i = 0; i < pScreenPriv->nBanks; i++)
- if (pScreenPriv->pBanks[i])
- REGION_DESTROY(pScreen, pScreenPriv->pBanks[i]);
-
- Xfree(pScreenPriv->pBanks);
-
- SCREEN_UNWRAP(CreateScreenResources);
- SCREEN_UNWRAP(ModifyPixmapHeader);
- SCREEN_UNWRAP(CloseScreen);
- SCREEN_UNWRAP(GetImage);
- SCREEN_UNWRAP(GetSpans);
- SCREEN_UNWRAP(CreateGC);
- SCREEN_UNWRAP(CopyWindow);
-
- Xfree(pScreenPriv);
- return (*pScreen->CloseScreen)(nIndex, pScreen);
-}
-
-static void
-miBankGetImage(
- DrawablePtr pDrawable,
- int sx,
- int sy,
- int w,
- int h,
- unsigned int format,
- unsigned long planemask,
- char *pImage
-)
-{
- if ((w > 0) && (h > 0))
- {
- ScreenPtr pScreen = pDrawable->pScreen;
-
- SCREEN_INIT;
- SCREEN_STATUS;
- SCREEN_UNWRAP(GetImage);
-
- if (!IS_BANKED(pDrawable))
- {
- (*pScreen->GetImage)(pDrawable, sx, sy, w, h,
- format, planemask, pImage);
- }
- else
- {
- int paddedWidth;
- char *pBankImage;
-
- paddedWidth = PixmapBytePad(w,
- pScreenPriv->pScreenPixmap->drawable.depth);
- pBankImage = xalloc(paddedWidth * h);
-
- if (pBankImage)
- {
- BANK_SAVE;
-
- ModifyPixmap(pScreenPriv->pBankPixmap, w, paddedWidth,
- pBankImage);
-
- (*pScreenPriv->pBankGC->ops->CopyArea)(
- (DrawablePtr)WindowTable[pScreen->myNum],
- (DrawablePtr)pScreenPriv->pBankPixmap,
- pScreenPriv->pBankGC,
- sx + pDrawable->x, sy + pDrawable->y, w, h, 0, 0);
-
- (*pScreen->GetImage)((DrawablePtr)pScreenPriv->pBankPixmap,
- 0, 0, w, h, format, planemask, pImage);
-
- BANK_RESTORE;
-
- xfree(pBankImage);
- }
- }
-
- SCREEN_WRAP(GetImage, miBankGetImage);
- }
-}
-
-static void
-miBankGetSpans(
- DrawablePtr pDrawable,
- int wMax,
- DDXPointPtr ppt,
- int *pwidth,
- int nspans,
- char *pImage
-)
-{
- if (nspans > 0)
- {
- ScreenPtr pScreen = pDrawable->pScreen;
-
- SCREEN_INIT;
- SCREEN_STATUS;
- SCREEN_UNWRAP(GetSpans);
-
- if (!IS_BANKED(pDrawable))
- {
- (*pScreen->GetSpans)(pDrawable, wMax, ppt, pwidth, nspans, pImage);
- }
- else
- {
- char *pBankImage;
- int paddedWidth;
- DDXPointRec pt;
-
- pt.x = pt.y = 0;
-
- paddedWidth =
- PixmapBytePad(pScreenPriv->pScreenPixmap->drawable.width,
- pScreenPriv->pScreenPixmap->drawable.depth);
- pBankImage = xalloc(paddedWidth);
-
- if (pBankImage)
- {
- BANK_SAVE;
-
- ModifyPixmap(pScreenPriv->pBankPixmap,
- pScreenPriv->pScreenPixmap->drawable.width,
- paddedWidth, pBankImage);
-
- for (; nspans--; ppt++, pwidth++)
- {
- if (*pwidth <= 0)
- continue;
-
- (*pScreenPriv->pBankGC->ops->CopyArea)(
- (DrawablePtr)WindowTable[pScreen->myNum],
- (DrawablePtr)pScreenPriv->pBankPixmap,
- pScreenPriv->pBankGC,
- ppt->x, ppt->y, *pwidth, 1, 0, 0);
-
- (*pScreen->GetSpans)((DrawablePtr)pScreenPriv->pBankPixmap,
- wMax, &pt, pwidth, 1, pImage);
-
- pImage = pImage + PixmapBytePad(*pwidth, pDrawable->depth);
- }
-
- BANK_RESTORE;
-
- xfree(pBankImage);
- }
- }
-
- SCREEN_WRAP(GetSpans, miBankGetSpans);
- }
-}
-
-static Bool
-miBankCreateGC(
- GCPtr pGC
-)
-{
- ScreenPtr pScreen = pGC->pScreen;
- miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC);
- Bool ret;
-
- SCREEN_INIT;
- SCREEN_UNWRAP(CreateGC);
-
- if ((ret = (*pScreen->CreateGC)(pGC)))
- {
- pGCPriv->unwrappedOps = &miBankGCOps;
- pGCPriv->unwrappedFuncs = &miBankGCFuncs;
- GC_WRAP(pGC);
-
- memset(&pGCPriv->pBankedClips, 0,
- pScreenPriv->nBanks * sizeof(pGCPriv->pBankedClips));
- }
-
- SCREEN_WRAP(CreateGC, miBankCreateGC);
-
- return ret;
-}
-
-static void
-miBankCopyWindow(
- WindowPtr pWindow,
- DDXPointRec ptOldOrg,
- RegionPtr pRgnSrc
-)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- GCPtr pGC;
- int dx, dy, nBox;
- DrawablePtr pDrawable = (DrawablePtr)WindowTable[pScreen->myNum];
- RegionPtr pRgnDst;
- BoxPtr pBox, pBoxTmp, pBoxNext, pBoxBase, pBoxNew1, pBoxNew2;
- XID subWindowMode = IncludeInferiors;
-
- pGC = GetScratchGC(pDrawable->depth, pScreen);
-
- ChangeGC(pGC, GCSubwindowMode, &subWindowMode);
- ValidateGC(pDrawable, pGC);
-
- pRgnDst = REGION_CREATE(pScreen, NULL, 1);
-
- dx = ptOldOrg.x - pWindow->drawable.x;
- dy = ptOldOrg.y - pWindow->drawable.y;
- REGION_TRANSLATE(pScreen, pRgnSrc, -dx, -dy);
- REGION_INTERSECT(pScreen, pRgnDst, &pWindow->borderClip, pRgnSrc);
-
- pBox = REGION_RECTS(pRgnDst);
- nBox = REGION_NUM_RECTS(pRgnDst);
-
- pBoxNew1 = NULL;
- pBoxNew2 = NULL;
-
- if (nBox > 1)
- {
- if (dy < 0)
- {
- /* Sort boxes from bottom to top */
- pBoxNew1 = xalloc_ARRAY(BoxRec, nBox);
-
- if (pBoxNew1)
- {
- pBoxBase = pBoxNext = pBox + nBox - 1;
-
- while (pBoxBase >= pBox)
- {
- while ((pBoxNext >= pBox) &&
- (pBoxBase->y1 == pBoxNext->y1))
- pBoxNext--;
-
- pBoxTmp = pBoxNext + 1;
-
- while (pBoxTmp <= pBoxBase)
- *pBoxNew1++ = *pBoxTmp++;
-
- pBoxBase = pBoxNext;
- }
-
- pBoxNew1 -= nBox;
- pBox = pBoxNew1;
- }
- }
-
- if (dx < 0)
- {
- /* Sort boxes from right to left */
- pBoxNew2 = xalloc_ARRAY(BoxRec, nBox);
-
- if (pBoxNew2)
- {
- pBoxBase = pBoxNext = pBox;
-
- while (pBoxBase < pBox + nBox)
- {
- while ((pBoxNext < pBox + nBox) &&
- (pBoxNext->y1 == pBoxBase->y1))
- pBoxNext++;
-
- pBoxTmp = pBoxNext;
-
- while (pBoxTmp != pBoxBase)
- *pBoxNew2++ = *--pBoxTmp;
-
- pBoxBase = pBoxNext;
- }
-
- pBoxNew2 -= nBox;
- pBox = pBoxNew2;
- }
- }
- }
-
- while (nBox--)
- {
- (*pGC->ops->CopyArea)(pDrawable, pDrawable, pGC,
- pBox->x1 + dx, pBox->y1 + dy,
- pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
- pBox->x1, pBox->y1);
-
- pBox++;
- }
-
- FreeScratchGC(pGC);
-
- REGION_DESTROY(pScreen, pRgnDst);
-
- xfree(pBoxNew2);
- xfree(pBoxNew1);
-}
-
-Bool
-miInitializeBanking(
- ScreenPtr pScreen,
- unsigned int xsize,
- unsigned int ysize,
- unsigned int width,
- miBankInfoPtr pBankInfo
-)
-{
- miBankScreenPtr pScreenPriv;
- unsigned long nBitsPerBank, nBitsPerScanline, nPixelsPerScanlinePadUnit;
- unsigned long BankBase, ServerPad;
- unsigned int type, iBank, nBanks, maxRects, we, nBankBPP;
- int i;
-
- if (!pBankInfo || !pBankInfo->BankSize)
- return TRUE; /* No banking required */
-
- /* Sanity checks */
-
- if (!pScreen || !xsize || !ysize || (xsize > width) ||
- !pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
- !pBankInfo->SetSourceAndDestinationBanks ||
- !pBankInfo->pBankA || !pBankInfo->pBankB ||
- !pBankInfo->nBankDepth)
- return FALSE;
-
- /*
- * DDX *must* have registered a pixmap format whose depth is
- * pBankInfo->nBankDepth. This is not necessarily the rootDepth
- * pixmap format.
- */
- i = 0;
- while (screenInfo.formats[i].depth != pBankInfo->nBankDepth)
- if (++i >= screenInfo.numPixmapFormats)
- return FALSE;
- nBankBPP = screenInfo.formats[i].bitsPerPixel;
-
- i = 0;
- while (screenInfo.formats[i].depth != pScreen->rootDepth)
- if (++i >= screenInfo.numPixmapFormats)
- return FALSE;
-
- if (nBankBPP > screenInfo.formats[i].bitsPerPixel)
- return FALSE;
-
- /* Determine banking type */
- if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
- return FALSE;
-
- /* Internal data */
-
- nBitsPerBank = pBankInfo->BankSize * 8;
- ServerPad = PixmapBytePad(1, pBankInfo->nBankDepth) * 8;
- if (nBitsPerBank % ServerPad)
- return FALSE;
- nBitsPerScanline = PixmapBytePad(width, pBankInfo->nBankDepth) * 8;
- nBanks = ((nBitsPerScanline * (ysize - 1)) +
- (nBankBPP * xsize) + nBitsPerBank - 1) / nBitsPerBank;
- nPixelsPerScanlinePadUnit = miLCM(ServerPad, nBankBPP) / nBankBPP;
-
- /* Private areas */
-
- if (miBankGeneration != serverGeneration)
- miBankGeneration = serverGeneration;
-
- if (!dixRequestPrivate(miBankGCKey,
- (nBanks * sizeof(RegionPtr)) +
- (sizeof(miBankGCRec) - sizeof(RegionPtr))))
- return FALSE;
-
- if (!(pScreenPriv = (miBankScreenPtr)Xcalloc(sizeof(miBankScreenRec))))
- return FALSE;
-
- if (!(pScreenPriv->pBanks = /* Allocate and clear */
- (RegionPtr *)Xcalloc(nBanks * sizeof(RegionPtr))))
- {
- Xfree(pScreenPriv);
- return FALSE;
- }
-
- /*
- * Translate banks into clipping regions which are themselves clipped
- * against the screen. This also ensures that pixels with imbedded bank
- * boundaries are off-screen.
- */
-
- BankBase = 0;
- maxRects = 0;
- we = 0;
- for (iBank = 0; iBank < nBanks; iBank++)
- {
- xRectangle pRects[3], *pRect = pRects;
- unsigned int xb, yb, xe, ye;
-
- xb = ((BankBase + nBankBPP - 1) % nBitsPerScanline) / nBankBPP;
- yb = (BankBase + nBankBPP - 1) / nBitsPerScanline;
- if (xb >= xsize)
- {
- xb = we = 0;
- yb++;
- }
- if (yb >= ysize)
- {
- we = 0;
- break;
- }
-
- if (we)
- break;
-
- BankBase += nBitsPerBank;
-
- we = (BankBase % nBitsPerScanline) % nBankBPP;
- xe = (BankBase % nBitsPerScanline) / nBankBPP;
- ye = BankBase / nBitsPerScanline;
- if (xe >= xsize)
- {
- we = xe = 0;
- ye++;
- }
- if (ye >= ysize)
- {
- we = xe = 0;
- ye = ysize;
- }
-
- if (yb == ye)
- {
- if (xb >= xe)
- continue;
-
- pRect->x = xb;
- pRect->y = yb;
- pRect->width = xe - xb;
- pRect->height = 1;
- maxRects += 2;
- pRect++;
- }
- else
- {
- if (xb)
- {
- pRect->x = xb;
- pRect->y = yb++;
- pRect->width = xsize - xb;
- pRect->height = 1;
- maxRects += 2;
- pRect++;
- }
-
- if (yb < ye)
- {
- pRect->x = 0;
- pRect->y = yb;
- pRect->width = xsize;
- pRect->height = ye - yb;
- maxRects += min(pRect->height, 3) + 1;
- pRect++;
- }
-
- if (xe)
- {
- pRect->x = 0;
- pRect->y = ye;
- pRect->width = xe;
- pRect->height = 1;
- maxRects += 2;
- pRect++;
- }
- }
-
- pScreenPriv->pBanks[iBank] =
- RECTS_TO_REGION(pScreen, pRect - pRects, pRects, 0);
- if (!pScreenPriv->pBanks[iBank] ||
- REGION_NAR(pScreenPriv->pBanks[iBank]))
- {
- we = 1;
- break;
- }
- }
-
- if (we && (iBank < nBanks))
- {
- for (i = iBank; i >= 0; i--)
- if (pScreenPriv->pBanks[i])
- REGION_DESTROY(pScreen, pScreenPriv->pBanks[i]);
-
- Xfree(pScreenPriv->pBanks);
- Xfree(pScreenPriv);
-
- return FALSE;
- }
-
- /* Open for business */
-
- pScreenPriv->type = type;
- pScreenPriv->nBanks = nBanks;
- pScreenPriv->maxRects = maxRects;
- pScreenPriv->nBankBPP = nBankBPP;
- pScreenPriv->BankInfo = *pBankInfo;
- pScreenPriv->nBitsPerBank = nBitsPerBank;
- pScreenPriv->nBitsPerScanline = nBitsPerScanline;
- pScreenPriv->nPixelsPerScanlinePadUnit = nPixelsPerScanlinePadUnit;
-
- SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
- SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
- SCREEN_WRAP(CloseScreen, miBankCloseScreen);
- SCREEN_WRAP(GetImage, miBankGetImage);
- SCREEN_WRAP(GetSpans, miBankGetSpans);
- SCREEN_WRAP(CreateGC, miBankCreateGC);
- SCREEN_WRAP(CopyWindow, miBankCopyWindow);
-
- dixSetPrivate(&pScreen->devPrivates, miBankScreenKey, pScreenPriv);
-
- return TRUE;
-}
-
-/*
- * Given various screen attributes, determine the minimum scanline width such
- * that each scanline is server and DDX padded and any pixels with imbedded
- * bank boundaries are off-screen. This function returns -1 if such a width
- * cannot exist. This function exists because the DDX needs to be able to
- * determine this width before initializing a frame buffer.
- */
-int
-miScanLineWidth(
- unsigned int xsize, /* pixels */
- unsigned int ysize, /* pixels */
- unsigned int width, /* pixels */
- unsigned long BankSize, /* char's */
- PixmapFormatRec *pBankFormat,
- unsigned int nWidthUnit /* bits */
-)
-{
- unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit;
- unsigned long minBitsPerScanline, maxBitsPerScanline;
-
- /* Sanity checks */
-
- if (!nWidthUnit || !pBankFormat)
- return -1;
-
- nBitsPerBank = BankSize * 8;
- if (nBitsPerBank % pBankFormat->scanlinePad)
- return -1;
-
- if (xsize > width)
- width = xsize;
- nBitsPerScanlinePadUnit = miLCM(pBankFormat->scanlinePad, nWidthUnit);
- nBitsPerScanline =
- (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) /
- nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit;
- width = nBitsPerScanline / pBankFormat->bitsPerPixel;
-
- if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel))
- return (int)width;
-
- /*
- * Scanlines will be server-pad aligned at this point. They will also be
- * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded
- * bank boundaries are off-screen.
- *
- * It seems reasonable to limit total frame buffer size to 1/16 of the
- * theoretical maximum address space size. On a machine with 32-bit
- * addresses (to 8-bit quantities) this turns out to be 256MB. Not only
- * does this provide a simple limiting condition for the loops below, but
- * it also prevents unsigned long wraparounds.
- */
- if (!ysize)
- return -1;
-
- minBitsPerScanline = xsize * pBankFormat->bitsPerPixel;
- if (minBitsPerScanline > nBitsPerBank)
- return -1;
-
- if (ysize == 1)
- return (int)width;
-
- maxBitsPerScanline =
- (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1);
- while (nBitsPerScanline <= maxBitsPerScanline)
- {
- unsigned long BankBase, BankUnit;
-
- BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) *
- nBitsPerBank;
- if (!(BankUnit % nBitsPerScanline))
- return (int)width;
-
- for (BankBase = BankUnit; ; BankBase += nBitsPerBank)
- {
- unsigned long x, y;
-
- y = BankBase / nBitsPerScanline;
- if (y >= ysize)
- return (int)width;
-
- x = BankBase % nBitsPerScanline;
- if (!(x % pBankFormat->bitsPerPixel))
- continue;
-
- if (x < minBitsPerScanline)
- {
- /*
- * Skip ahead certain widths by dividing the excess scanline
- * amongst the y's.
- */
- y *= nBitsPerScanlinePadUnit;
- nBitsPerScanline +=
- ((x + y - 1) / y) * nBitsPerScanlinePadUnit;
- width = nBitsPerScanline / pBankFormat->bitsPerPixel;
- break;
- }
-
- if (BankBase != BankUnit)
- continue;
-
- if (!(nBitsPerScanline % x))
- return (int)width;
-
- BankBase = ((nBitsPerScanline - minBitsPerScanline) /
- (nBitsPerScanline - x)) * BankUnit;
- }
- }
-
- return -1;
-}
diff --git a/xorg-server/mi/mibank.h b/xorg-server/mi/mibank.h
deleted file mode 100644
index 0c10540a7..000000000
--- a/xorg-server/mi/mibank.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of Marc Aurele La France not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. Marc Aurele La France makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as-is" without express or implied warranty.
- *
- * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
- * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-#ifndef __MIBANK_H__
-#define __MIBANK_H__ 1
-
-#include "scrnintstr.h"
-
-/*
- * Banking external interface.
- */
-
-/*
- * This is the banking function type. The return value is normally zero.
- * Non-zero returns can be used to implement the likes of scanline interleave,
- * etc.
- */
-typedef int miBankProc(
- ScreenPtr /*pScreen*/,
- unsigned int /*iBank*/
-);
-
-typedef miBankProc *miBankProcPtr;
-
-typedef struct _miBankInfo
-{
- /*
- * Banking refers to the use of one or more apertures (in the server's
- * address space) to access various parts of a potentially larger hardware
- * frame buffer.
- *
- * Three different banking schemes are supported:
- *
- * Single banking is indicated when pBankA and pBankB are equal and all
- * three miBankProcPtr's point to the same function. Here, both reads and
- * writes through the aperture access the same hardware location.
- *
- * Shared banking is indicated when pBankA and pBankB are equal but the
- * source and destination functions differ. Here reads through the
- * aperture do not necessarily access the same hardware location as writes.
- *
- * Double banking is indicated when pBankA and pBankB differ. Here two
- * independent apertures are used to provide read/write access to
- * potentially different hardware locations.
- *
- * Any other combination will result in no banking.
- */
- miBankProcPtr SetSourceBank; /* Set pBankA bank number */
- miBankProcPtr SetDestinationBank; /* Set pBankB bank number */
- miBankProcPtr SetSourceAndDestinationBanks; /* Set both bank numbers */
-
- pointer pBankA; /* First aperture location */
- pointer pBankB; /* First or second aperture location */
-
- /*
- * BankSize is in units of sizeof(char) and is the size of each bank.
- */
- unsigned long BankSize;
-
- /*
- * nBankDepth is the colour depth associated with the maximum number of a
- * pixel's bits that are simultaneously accessible through the frame buffer
- * aperture.
- */
- unsigned int nBankDepth;
-} miBankInfoRec, *miBankInfoPtr;
-
-extern _X_EXPORT Bool
-miInitializeBanking(
- ScreenPtr /*pScreen*/,
- unsigned int /*xsize*/,
- unsigned int /*ysize*/,
- unsigned int /*width*/,
- miBankInfoPtr /*pBankInfo*/
-);
-
-/*
- * This function determines the minimum screen width, given a initial estimate
- * and various screen attributes. DDX needs to determine this width before
- * initializing the screen.
- */
-extern _X_EXPORT int
-miScanLineWidth(
- unsigned int /*xsize*/,
- unsigned int /*ysize*/,
- unsigned int /*width*/,
- unsigned long /*BankSize*/,
- PixmapFormatRec * /*pBankFormat*/,
- unsigned int /*nWidthUnit*/
-);
-
-#endif /* __MIBANK_H__ */