diff options
33 files changed, 3089 insertions, 4582 deletions
diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c index 96eb8f9e1..d5965c2d0 100644 --- a/Xext/panoramiX.c +++ b/Xext/panoramiX.c @@ -476,7 +476,8 @@ void PanoramiXExtensionInit(int argc, char *argv[]) panoramiXdataPtr = (PanoramiXData *) xcalloc(PanoramiXNumScreens, sizeof(PanoramiXData)); - BREAK_IF(!panoramiXdataPtr); + if (!panoramiXdataPtr) + break; if (!dixRequestPrivate(PanoramiXGCKey, sizeof(PanoramiXGCRec))) { noPanoramiXExtension = TRUE; diff --git a/Xext/panoramiX.h b/Xext/panoramiX.h index 463a99441..35de17951 100644 --- a/Xext/panoramiX.h +++ b/Xext/panoramiX.h @@ -80,19 +80,6 @@ typedef struct { #define FOR_NSCREENS_BACKWARD(j) for(j = PanoramiXNumScreens - 1; j >= 0; j--) #define FOR_NSCREENS(j) FOR_NSCREENS_FORWARD(j) -#define BREAK_IF(a) if ((a)) break -#define IF_RETURN(a,b) if ((a)) return (b) - -#define FORCE_ROOT(a) { \ - int _j; \ - for (_j = PanoramiXNumScreens - 1; _j; _j--) \ - if ((a).root == WindowTable[_j]->drawable.id) \ - break; \ - (a).rootX += panoramiXdataPtr[_j].x; \ - (a).rootY += panoramiXdataPtr[_j].y; \ - (a).root = WindowTable[0]->drawable.id; \ -} - #define IS_SHARED_PIXMAP(r) (((r)->type == XRT_PIXMAP) && (r)->u.pix.shared) #endif /* _PANORAMIX_H_ */ diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c index 6834efb71..6635db905 100644 --- a/Xext/panoramiXprocs.c +++ b/Xext/panoramiXprocs.c @@ -1728,7 +1728,7 @@ int PanoramiXPolyFillArc(ClientPtr client) isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); - IF_RETURN((narcs % sizeof(xArc)), BadLength); + if (narcs % sizeof(xArc)) return BadLength; narcs /= sizeof(xArc); if (narcs > 0) { origArcs = xalloc(narcs * sizeof(xArc)); diff --git a/Xext/shape.c b/Xext/shape.c index cb4126b44..58b5c23c0 100644 --- a/Xext/shape.c +++ b/Xext/shape.c @@ -365,7 +365,7 @@ ProcPanoramiXShapeRectangles( FOR_NSCREENS(j) { stuff->dest = win->info[j].id; result = ProcShapeRectangles (client); - BREAK_IF(result != Success); + if (result != Success) break; } return (result); } @@ -474,7 +474,7 @@ ProcPanoramiXShapeMask( if(pmap) stuff->src = pmap->info[j].id; result = ProcShapeMask (client); - BREAK_IF(result != Success); + if (result != Success) break; } return (result); } @@ -600,7 +600,7 @@ ProcPanoramiXShapeCombine( stuff->dest = win->info[j].id; stuff->src = win2->info[j].id; result = ProcShapeCombine (client); - BREAK_IF(result != Success); + if (result != Success) break; } return (result); } diff --git a/configure.ac b/configure.ac index b48d3a9c5..65d18c49f 100644 --- a/configure.ac +++ b/configure.ac @@ -2220,6 +2220,7 @@ hw/dmx/Makefile hw/vfb/Makefile hw/xnest/Makefile hw/xwin/Makefile +hw/xwin/glx/Makefile hw/xquartz/Makefile hw/xquartz/GL/Makefile hw/xquartz/bundle/Makefile diff --git a/dix/events.c b/dix/events.c index 6d0137da4..b26e28af7 100644 --- a/dix/events.c +++ b/dix/events.c @@ -5355,7 +5355,6 @@ ProcGrabButton(ClientPtr client) rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR, client, DixUseAccess); if (rc != Success) - if (!cursor) { client->errorValue = stuff->cursor; return (rc == BadValue) ? BadCursor : rc; diff --git a/dix/main.c b/dix/main.c index e5667a611..2cff59c8e 100644 --- a/dix/main.c +++ b/dix/main.c @@ -161,9 +161,7 @@ int main(int argc, char *argv[], char *envp[]) ScreenSaverBlanking = defaultScreenSaverBlanking; ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; #ifdef DPMSExtension - DPMSStandbyTime = DEFAULT_SCREEN_SAVER_TIME; - DPMSSuspendTime = DEFAULT_SCREEN_SAVER_TIME; - DPMSOffTime = DEFAULT_SCREEN_SAVER_TIME; + DPMSStandbyTime = DPMSSuspendTime = DPMSOffTime = ScreenSaverTime; DPMSEnabled = TRUE; DPMSPowerLevel = 0; #endif diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index db9ce9f56..2f8c4622d 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -462,9 +462,11 @@ ExaSrcValidate(DrawablePtr pDrawable, REGION_UNION(pScreen, dst, dst, ®); REGION_UNINIT(pScreen, ®); - swap(pExaScr, pScreen, SourceValidate); - pScreen->SourceValidate(pDrawable, x, y, width, height); - swap(pExaScr, pScreen, SourceValidate); + if (pExaScr->SavedSourceValidate) { + swap(pExaScr, pScreen, SourceValidate); + pScreen->SourceValidate(pDrawable, x, y, width, height); + swap(pExaScr, pScreen, SourceValidate); + } } static Bool diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c index 949d4fcfa..5d30a782c 100644 --- a/hw/xfree86/common/xf86Mode.c +++ b/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/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c index 02dcc34b4..86c7bde79 100644 --- a/hw/xfree86/common/xf86RandR.c +++ b/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" @@ -163,7 +162,7 @@ xf86RandRSetMode (ScreenPtr pScreen, WindowPtr pRoot = WindowTable[pScreen->myNum]; Bool ret = TRUE; - if (pRoot) + if (pRoot && scrp->vtSema) (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); if (useVirtual) { @@ -229,7 +228,7 @@ xf86RandRSetMode (ScreenPtr pScreen, */ xf86SetViewport (pScreen, pScreen->width, pScreen->height); xf86SetViewport (pScreen, 0, 0); - if (pRoot) + if (pRoot && scrp->vtSema) (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); return ret; } diff --git a/hw/xfree86/loader/sdksyms.sh b/hw/xfree86/loader/sdksyms.sh index eea024063..13c5ae5f8 100755 --- a/hw/xfree86/loader/sdksyms.sh +++ b/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/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c index 7ba09b6fe..8898f4dad 100644 --- a/hw/xfree86/modes/xf86RandR12.c +++ b/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/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c index 0ab692987..1ab059f72 100644 --- a/hw/xwin/InitOutput.c +++ b/hw/xwin/InitOutput.c @@ -98,8 +98,8 @@ extern HMODULE g_hmodCommonControls; extern FARPROC g_fpTrackMouseEvent; extern Bool g_fNoHelpMessageBox; extern Bool g_fSilentDupError; - - +extern Bool g_fNativeGl; + /* * Function prototypes */ @@ -183,6 +183,17 @@ winClipboardShutdown (void) } #endif +void +ddxPushProviders(void) +{ +#ifdef XWIN_GLX_WINDOWS + if (g_fNativeGl) + { + /* install the native GL provider */ + glxWinPushNativeProvider(); + } +#endif +} #if defined(DDXBEFORERESET) /* @@ -880,6 +891,11 @@ winUseMsg (void) ErrorF ("-[no]unixkill\n" "\tCtrl+Alt+Backspace exits the X Server.\n"); +#ifdef XWIN_GLX_WINDOWS + ErrorF ("-[no]wgl\n" + "\tEnable the GLX extension to use the native Windows WGL interface for accelerated OpenGL\n"); +#endif + ErrorF ("-[no]winkill\n" "\tAlt+F4 exits the X Server.\n"); diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am index 89b021b22..7544cd3da 100644 --- a/hw/xwin/Makefile.am +++ b/hw/xwin/Makefile.am @@ -13,9 +13,10 @@ DEFS_CLIPBOARD = -DXWIN_CLIPBOARD endif if XWIN_GLX_WINDOWS -SRCS_GLX_WINDOWS = \ - winpriv.c +GLX_DIR = glx DEFS_GLX_WINDOWS = -DXWIN_GLX_WINDOWS +XWIN_GLX_LIBS = $(top_builddir)/hw/xwin/glx/libXwinGLX.la +XWIN_GLX_LINK_FLAGS = -lopengl32 endif if XWIN_MULTIWINDOW @@ -125,7 +126,6 @@ SRCS = InitInput.c \ $(top_srcdir)/mi/miinitext.c \ $(top_srcdir)/fb/fbcmap_mi.c \ $(SRCS_CLIPBOARD) \ - $(SRCS_GLX_WINDOWS) \ $(SRCS_MULTIWINDOW) \ $(SRCS_MULTIWINDOWEXTWM) \ $(SRCS_NATIVEGDI) \ @@ -146,14 +146,13 @@ XWin_SOURCES = $(SRCS) INCLUDES = -I$(top_srcdir)/miext/rootless -XWin_DEPENDENCIES = $(XWIN_LIBS) -XWin_LDADD = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) +XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) +XWin_LDADD = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS) +XWin_LDFLAGS = -mwindows -static .rc.o: $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include -XWin_LDFLAGS = -mwindows -static - winprefsyacc.h: winprefsyacc.c winprefslex.c: winprefslex.l winprefsyacc.c winprefsyacc.h @@ -164,12 +163,8 @@ AM_YFLAGS = -d AM_LFLAGS = -i AM_CFLAGS = -DHAVE_XWIN_CONFIG_H $(DIX_CFLAGS) \ $(XWINMODULES_CFLAGS) \ - -DXFree86Server - -GLX_EXTRAS = \ - glx/glwindows.h \ - glx/glwrap.c \ - glx/indirect.c + -DXFree86Server \ + -I$(top_srcdir) MAN_SRCS = XWin.man.pre XWinrc.man.pre @@ -198,7 +193,6 @@ install-exec-hook: (cd $(DESTDIR)$(bindir) && rm -f X && $(LN_S) XWin$(EXEEXT) X) EXTRA_DIST = \ - $(GLX_EXTRAS) \ $(MAN_SRCS) \ $(xwinconfig_DATA) \ X.ico \ @@ -226,3 +220,6 @@ EXTRA_DIST = \ relink: $(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT) + +SUBDIRS = $(GLX_DIR) . +DIST_SUBDIRS = glx . diff --git a/hw/xwin/glx/.gitignore b/hw/xwin/glx/.gitignore new file mode 100644 index 000000000..e7c7617e9 --- /dev/null +++ b/hw/xwin/glx/.gitignore @@ -0,0 +1,8 @@ +# ignore downloaded and generated files +generated_gl_wrappers.c +generated_wgl_wrappers.c +gl.spec +gl.tm +wgl.tm +wglext.spec +wglext.h diff --git a/hw/xwin/glx/Makefile.am b/hw/xwin/glx/Makefile.am new file mode 100644 index 000000000..aadd44268 --- /dev/null +++ b/hw/xwin/glx/Makefile.am @@ -0,0 +1,59 @@ +noinst_LTLIBRARIES = libXwinGLX.la + +libXwinGLX_la_SOURCES = \ + winpriv.c \ + glwindows.h \ + glwrap.c \ + indirect.c \ + wgl_ext_api.c + +if XWIN_MULTIWINDOW +DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW +endif + +if XWIN_MULTIWINDOWEXTWM +DEFS_MULTIWINDOWEXTWM = -DXWIN_MULTIWINDOWEXTWM +endif + +DEFS = $(DEFS_MULTIWINDOW) $(DEFS_MULTIWINDOWEXTWM) + +INCLUDES = -I$(top_srcdir)/miext/rootless + +AM_CFLAGS = -DHAVE_XWIN_CONFIG_H $(DIX_CFLAGS) \ + $(XWINMODULES_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/hw/xwin/ + +glwrap.c: generated_gl_wrappers.c +wgl_ext_api.c: generated_wgl_wrappers.c wglext.h +wgl_ext_api.h: wglext.h +indirect.c: wgl_ext_api.h + +SPEC_FILES = gl.spec gl.tm wglext.spec wgl.tm + +gl.spec: + wget http://www.opengl.org/registry/api/gl.spec + +gl.tm: + wget http://www.opengl.org/registry/api/gl.tm + +wglext.spec: + wget http://www.opengl.org/registry/api/wglext.spec + +wgl.tm: + wget http://www.opengl.org/registry/api/wgl.tm + +generated_gl_wrappers.c: gen_gl_wrappers.py gl.spec gl.tm + ./gen_gl_wrappers.py --spec=gl.spec --typemap=gl.tm --dispatch-header=$(top_srcdir)/glx/dispatch.h --staticwrappers >generated_gl_wrappers.c + +generated_wgl_wrappers.c: gen_gl_wrappers.py wglext.spec wgl.tm + ./gen_gl_wrappers.py --spec=wglext.spec --typemap=wgl.tm --prefix=wgl --preresolve >generated_wgl_wrappers.c + +wglext.h: + wget http://www.opengl.org/registry/api/wglext.h + +BUILT_SOURCES = generated_gl_wrappers.c generated_wgl_wrappers.c +CLEANFILES = $(BUILT_SOURCES) +DISTCLEANFILES = $(SPEC_FILES) wglext.h + +EXTRA_DIST = gen_gl_wrappers.py $(SPEC_FILES) wglext.h diff --git a/hw/xwin/glx/gen_gl_wrappers.py b/hw/xwin/glx/gen_gl_wrappers.py new file mode 100755 index 000000000..d7fe98dec --- /dev/null +++ b/hw/xwin/glx/gen_gl_wrappers.py @@ -0,0 +1,319 @@ +#!/usr/bin/python +# +# Comedy python script to generate cdecl to stdcall wrappers for GL functions +# +# This is designed to operate on OpenGL spec files from +# http://www.opengl.org/registry/api/ +# +# +# Copyright (c) Jon TURNEY 2009 +# +# 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. +# +# Except as contained in this notice, the name(s) of the above copyright +# holders shall not be used in advertising or otherwise to promote the sale, +# use or other dealings in this Software without prior written authorization. +# + +import sys +import re +import getopt + +dispatchheader = '' +prefix = 'gl' +preresolve = False +staticwrappers = False + +opts, args = getopt.getopt(sys.argv[1:], "", ['spec=', 'typemap=', 'dispatch-header=', 'prefix=', 'preresolve', 'staticwrappers' ]) + +for o,a in opts: + if o == '--typemap' : + typemapfile = a + elif o == '--dispatch-header' : + dispatchheader = a + elif o == '--spec' : + specfile = a + elif o == '--prefix' : + prefix = a + elif o == '--preresolve' : + preresolve = True + elif o == '--staticwrappers' : + staticwrappers = True + +# +# look for all the SET_ macros in dispatch.h, this is the set of functions +# we need to generate +# + +dispatch = {} + +if dispatchheader : + fh = open(dispatchheader) + dispatchh = fh.readlines() + + dispatch_regex = re.compile(r'#define\sSET_(\S*)\(') + + for line in dispatchh : + line = line.strip() + m1 = dispatch_regex.search(line) + + if m1 : + dispatch[m1.group(1)] = 1 + + del dispatch['by_offset'] + +# +# read the typemap .tm file +# + +typemap = {} + +fh = open(typemapfile) +tm = fh.readlines() + +typemap_regex = re.compile(r'#define\sSET_(\S*)\(') + +for line in tm : + # ignore everything after a '#' as a comment + hash = line.find('#') + if hash != -1 : + line = line[:hash-1] + + # ignore blank lines + if line.startswith('#') or len(line) == 0 : + continue + + l = line.split(',') + typemap[l[0]] = l[3].strip() + +# interestingly, * is not a C type +if typemap['void'] == '*' : + typemap['void'] = 'void' + +# +# crudely parse the .spec file +# + +r1 = re.compile(r'\t(\S*)\s+(\S*.*)') +r2 = re.compile(r'(.*)\((.*)\)') +r3 = re.compile(r'glWindowPos.*MESA') +r4 = re.compile(r'gl.*Program(s|)NV') +r5 = re.compile(r'glGetVertexAttribfvNV') + +wrappers = {} + +fh = open(specfile) +glspec = fh.readlines() +param_count = 0 + +for line in glspec : + line = line.rstrip() + + # ignore everything after a '#' as a comment + hash = line.find('#') + if hash != -1 : + line = line[:hash-1] + + # ignore blank lines + if line.startswith('#') or len(line) == 0 : + continue + + # lines containing ':' aren't intersting to us + if line.count(':') != 0 : + continue + + # attributes of each function follow the name, indented by a tab + if not line.startswith('\t') : + m1 = r2.search(line) + if m1 : + function = m1.group(1) + arglist_use = m1.group(2) + wrappers[function] = {} + + # near and far might be reserved words or macros so can't be used as formal parameter names + arglist_use = arglist_use.replace('near','zNear') + arglist_use = arglist_use.replace('far','zFar') + + wrappers[function]['arglist_use'] = arglist_use + param_count = 0 + else : + m1 = r1.search(line) + if m1 : + attribute = m1.group(1) + value = m1.group(2) + + # make param attributes unique and ordered + if attribute == 'param' : + attribute = 'param' + '%02d' % param_count + param_count += 1 + + wrappers[function][attribute] = value + +# +# now emit code +# + +print '/* Automatically generated by ' + sys.argv[0] + ' DO NOT EDIT */' +print '/* from ' + specfile + ' and typemap ' + typemapfile + ' */' +print '' + +# +# if required, emit code for non-lazy function resolving +# + +if preresolve : + for w in sorted(wrappers.keys()) : + funcname = prefix + w + print 'RESOLVE_DECL(PFN' + funcname.upper() + 'PROC);' + + print '' + print 'void ' + prefix + 'ResolveExtensionProcs(void)' + print '{' + + for w in sorted(wrappers.keys()) : + funcname = prefix + w + print ' PRERESOLVE(PFN' + funcname.upper() + 'PROC, "' + funcname + '");' + + print '}\n' + +# +# now emit the wrappers +# for GL 1.0 and 1.1 functions, generate stdcall wrappers which call the function directly +# for GL 1.2+ functions, generate wrappers which use wglGetProcAddress() +# + +for w in sorted(wrappers.keys()) : + + funcname = prefix + w + returntype = wrappers[w]['return'] + if returntype != 'void' : + returntype = typemap[returntype] + + # Avoid generating wrappers which aren't referenced by the dispatch table + if dispatchheader and not dispatch.has_key(w) : + print '/* No wrapper for ' + funcname + ', not in dispatch table */' + continue + + # manufacture arglist + # if no param attributes were found, it should be 'void' + al = [] + for k in sorted(wrappers[w].keys()) : + if k.startswith('param') : + l = wrappers[w][k].split() + + # near and far might be reserved words or macros so can't be used as formal parameter names + l[0] = l[0].replace('near','zNear') + l[0] = l[0].replace('far','zFar') + + if l[2] == 'in' : + if l[3] == 'array' : + arg = 'const ' + typemap[l[1]] + ' *' + l[0] + else : + arg = typemap[l[1]] + ' ' + l[0] + elif l[2] == 'out' : + arg = typemap[l[1]] + ' *' + l[0] + + al.append(arg) + + if len(al) == 0 : + arglist = 'void' + else: + arglist = ', '.join(al) + + if wrappers[w]['category'].startswith('VERSION_1_0') or wrappers[w]['category'].startswith('VERSION_1_1') : + if staticwrappers : + print 'static', + print returntype + ' ' + funcname + 'Wrapper(' + arglist + ')' + print '{' + print ' if (glxWinDebugSettings.enable' + prefix.upper() + 'callTrace) ErrorF("'+ funcname + '\\n");' + print ' glWinDirectProcCalls++;' + if returntype.lower() == 'void' : + print ' ' + funcname + '(', + else : + print ' /* returntype was ' + returntype.lower() + '*/' + print ' return ' + funcname + '(', + + if arglist != 'void' : + print wrappers[w]['arglist_use'], + + print ');' + print "}\n" + else: + if staticwrappers : + print 'static', + print returntype + ' ' + funcname + 'Wrapper(' + arglist + ')' + print '{' + + stringname = funcname + +# +# special case: Windows OpenGL implementations are far more likely to have GL_ARB_window_pos than GL_MESA_window_pos, +# so arrange for the wrapper to use the ARB strings to find functions... +# + + m2 = r3.search(funcname) + if m2 : + stringname = stringname.replace('MESA','ARB') + +# +# special case: likewise, implementations are more likely to have GL_ARB_vertex_program than GL_NV_vertex_program, +# especially if they are not NV implementations, so arrange for the wrapper to use ARB strings to find functions +# + + m3 = r4.search(funcname) + if m3 : + stringname = stringname.replace('NV','ARB') + m4 = r5.search(funcname) + if m4 : + stringname = stringname.replace('NV','ARB') + + pfntypename = 'PFN' + funcname.upper() + 'PROC' + + if returntype.lower() == 'void' : + print ' RESOLVE(' + pfntypename + ', "' + stringname + '");' + print ' if (glxWinDebugSettings.enable' + prefix.upper() + 'callTrace) ErrorF("'+ funcname + '\\n");' + print ' RESOLVED_PROC(' + pfntypename + ')(', + else : + print ' RESOLVE_RET(' + pfntypename + ', "' + stringname + '", FALSE);' + print ' if (glxWinDebugSettings.enable' + prefix.upper() + 'callTrace) ErrorF("'+ funcname + '\\n");' + print ' return RESOLVED_PROC(' + pfntypename + ')(', + + if arglist != 'void' : + print wrappers[w]['arglist_use'], + + print ');' + print "}\n" + + +# generate function to setup the dispatch table, which sets each +# dispatch table entry to point to it's wrapper function +# (assuming we were able to make one) + +if dispatchheader : + print 'void glWinSetupDispatchTable(void)' + print '{' + print ' struct _glapi_table *disp = _glapi_get_dispatch();' + + for d in sorted(dispatch.keys()) : + if wrappers.has_key(d) : + print ' SET_'+ d + '(disp, ' + prefix + d + 'Wrapper);' + else : + print '#warning No wrapper for ' + prefix + d + ' !' + + print '}' diff --git a/hw/xwin/glx/glwindows.h b/hw/xwin/glx/glwindows.h index 74e81f24f..cc3f2e6ee 100644 --- a/hw/xwin/glx/glwindows.h +++ b/hw/xwin/glx/glwindows.h @@ -1,64 +1,58 @@ -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/Xwindows.h> -#include <GL/gl.h> -#include <GL/glext.h> +/* + * File: glwindows.h + * Purpose: Header for GLX implementation using native Windows OpenGL library + * + * Authors: Alexander Gottwald + * Jon TURNEY + * + * Copyright (c) Jon TURNEY 2009 + * Copyright (c) Alexander Gottwald 2004 + * + * + * 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. + */ -#include <glxserver.h> -#include <glxext.h> -#include <windowstr.h> -#include <resource.h> -#include <GL/glxint.h> -#include <GL/glxtokens.h> -#include <scrnintstr.h> -#include <glxserver.h> -#include <glxscreens.h> -#include <glxdrawable.h> -#include <glxcontext.h> -#include <glxext.h> -#include <glxutil.h> -#include <glxscreens.h> -#include <GL/internal/glcore.h> -#include <stdlib.h> - - -typedef struct { - unsigned enableDebug : 1; - unsigned enableTrace : 1; - unsigned dumpPFD : 1; - unsigned dumpHWND : 1; - unsigned dumpDC : 1; -} glWinDebugSettingsRec, *glWinDebugSettingsPtr; -extern glWinDebugSettingsRec glWinDebugSettings; +#include <GL/gl.h> typedef struct { - int num_vis; - __GLcontextModes *modes; - void **priv; - - /* wrapped screen functions */ - RealizeWindowProcPtr RealizeWindow; - UnrealizeWindowProcPtr UnrealizeWindow; - CopyWindowProcPtr CopyWindow; -} glWinScreenRec; - -extern glWinScreenRec glWinScreens[MAXSCREENS]; - -#define glWinGetScreenPriv(pScreen) &glWinScreens[pScreen->myNum] -#define glWinScreenPriv(pScreen) glWinScreenRec *pScreenPriv = glWinGetScreenPriv(pScreen); + unsigned int enableDebug : 1; + unsigned int enableTrace : 1; + unsigned int dumpPFD : 1; + unsigned int dumpHWND : 1; + unsigned int dumpDC : 1; + unsigned int enableGLcallTrace : 1; + unsigned int enableWGLcallTrace :1; +} glxWinDebugSettingsRec; + +extern glxWinDebugSettingsRec glxWinDebugSettings; + +void glWinCallDelta(void); +void glxWinPushNativeProvider(void); +const GLubyte* glGetStringWrapperNonstatic(GLenum name); +void glAddSwapHintRectWINWrapperNonstatic(GLint x, GLint y, GLsizei width, GLsizei height); +void glWinSetupDispatchTable(void); #if 1 -#define GLWIN_TRACE() if (glWinDebugSettings.enableTrace) ErrorF("%s:%d: Trace\n", __FUNCTION__, __LINE__ ) -#define GLWIN_TRACE_MSG(msg, args...) if (glWinDebugSettings.enableTrace) ErrorF("%s:%d: " msg, __FUNCTION__, __LINE__, ##args ) -#define GLWIN_DEBUG_MSG(msg, args...) if (glWinDebugSettings.enableDebug) ErrorF("%s:%d: " msg, __FUNCTION__, __LINE__, ##args ) -#define GLWIN_DEBUG_MSG2(msg, args...) if (glWinDebugSettings.enableDebug) ErrorF(msg, ##args ) +#define GLWIN_TRACE_MSG(msg, args...) if (glxWinDebugSettings.enableTrace) ErrorF(msg " [%s:%d]\n" , ##args , __FUNCTION__, __LINE__ ) +#define GLWIN_DEBUG_MSG(msg, args...) if (glxWinDebugSettings.enableDebug) ErrorF(msg " [%s:%d]\n" , ##args , __FUNCTION__, __LINE__ ) #else -#define GLWIN_TRACE() #define GLWIN_TRACE_MSG(a, ...) #define GLWIN_DEBUG_MSG(a, ...) -#define GLWIN_DEBUG_MSG2(a, ...) #endif - diff --git a/hw/xwin/glx/glwrap.c b/hw/xwin/glx/glwrap.c index f0b38b228..5190d36f7 100755 --- a/hw/xwin/glx/glwrap.c +++ b/hw/xwin/glx/glwrap.c @@ -1,583 +1,148 @@ /* - * GLX implementation that uses Win32's OpenGL - * Wrapper functions for Win32's OpenGL + * File: glwrap.c + * Purpose: Wrapper functions for Win32 OpenGL functions * * Authors: Alexander Gottwald + * Jon TURNEY + * + * Copyright (c) Jon TURNEY 2009 + * Copyright (c) Alexander Gottwald 2004 + * + * + * 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. */ -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> +// define USE_OPENGL32 makes gl.h declare gl*() function prototypes with stdcall linkage, +// so our generated wrappers will correctly link with the functions in opengl32.dll +#define USE_OPENGL32 + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> #endif #include <X11/Xwindows.h> #include <GL/gl.h> #include <GL/glext.h> -#include <glxserver.h> -#include <glxext.h> - -#define RESOLVE_RET(procname, symbol, retval) \ - static Bool init = TRUE; \ - static procname proc = NULL; \ - if (init) { \ - proc = (procname)wglGetProcAddress(symbol); \ - init = FALSE; \ - if (proc == NULL) { \ - ErrorF("glwrap: Can't resolve \"%s\"\n", symbol); \ - } else \ - ErrorF("glwrap: resolved \"%s\"\n", symbol); \ - } \ - if (proc == NULL) { \ - __glXErrorCallBack(NULL, 0); \ - return retval; \ +#include <glx/glxserver.h> +#include <glx/glxext.h> +#include <glx/glapi.h> +#include <glx/dispatch.h> +#include <glwindows.h> + +static unsigned int glWinIndirectProcCalls = 0; +static unsigned int glWinDirectProcCalls = 0; + +void +glWinCallDelta(void) +{ + static unsigned int glWinIndirectProcCallsLast = 0; + static unsigned int glWinDirectProcCallsLast = 0; + if ((glWinIndirectProcCalls != glWinIndirectProcCallsLast) || + (glWinDirectProcCalls != glWinDirectProcCallsLast)) + { + if (glxWinDebugSettings.enableTrace) + { + ErrorF("after %d direct and %d indirect GL calls\n", + glWinDirectProcCalls - glWinDirectProcCallsLast, + glWinIndirectProcCalls - glWinIndirectProcCallsLast); + } + glWinDirectProcCallsLast = glWinDirectProcCalls; + glWinIndirectProcCallsLast = glWinIndirectProcCalls; } -#define RESOLVE(procname, symbol) RESOLVE_RET(procname, symbol,) - - -/* - * GL_ARB_imaging - */ - - -GLAPI void GLAPIENTRY glColorTable( GLenum target, GLenum internalformat, - GLsizei width, GLenum format, - GLenum type, const GLvoid *table ) -{ - RESOLVE(PFNGLCOLORTABLEPROC, "glColorTable"); - proc(target, internalformat, width, format, type, table); -} - -GLAPI void GLAPIENTRY glColorSubTable( GLenum target, - GLsizei start, GLsizei count, - GLenum format, GLenum type, - const GLvoid *data ) -{ - RESOLVE(PFNGLCOLORSUBTABLEPROC, "glColorSubTable"); - proc(target, start, count, format, type, data); -} - -GLAPI void GLAPIENTRY glColorTableParameteriv(GLenum target, GLenum pname, - const GLint *params) -{ - RESOLVE(PFNGLCOLORTABLEPARAMETERIVPROC, "glColorTableParameteriv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glColorTableParameterfv(GLenum target, GLenum pname, - const GLfloat *params) -{ - RESOLVE(PFNGLCOLORTABLEPARAMETERFVPROC, "glColorTableParameterfv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glCopyColorSubTable( GLenum target, GLsizei start, - GLint x, GLint y, GLsizei width ) -{ - RESOLVE(PFNGLCOPYCOLORSUBTABLEPROC, "glCopyColorSubTable"); - proc(target, start, x, y, width); -} - -GLAPI void GLAPIENTRY glCopyColorTable( GLenum target, GLenum internalformat, - GLint x, GLint y, GLsizei width ) -{ - RESOLVE(PFNGLCOPYCOLORTABLEPROC, "glCopyColorTable"); - proc(target, internalformat, x, y, width); -} - - -GLAPI void GLAPIENTRY glGetColorTable( GLenum target, GLenum format, - GLenum type, GLvoid *table ) -{ - RESOLVE(PFNGLGETCOLORTABLEPROC, "glGetColorTable"); - proc(target, format, type, table); -} - -GLAPI void GLAPIENTRY glGetColorTableParameterfv( GLenum target, GLenum pname, - GLfloat *params ) -{ - RESOLVE(PFNGLGETCOLORTABLEPARAMETERFVPROC, "glGetColorTableParameterfv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glGetColorTableParameteriv( GLenum target, GLenum pname, - GLint *params ) -{ - RESOLVE(PFNGLGETCOLORTABLEPARAMETERIVPROC, "glGetColorTableParameteriv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glBlendEquation( GLenum mode ) -{ - RESOLVE(PFNGLBLENDEQUATIONPROC, "glBlendEquation"); - proc(mode); -} - -GLAPI void GLAPIENTRY glBlendColor( GLclampf red, GLclampf green, - GLclampf blue, GLclampf alpha ) -{ - RESOLVE(PFNGLBLENDCOLORPROC, "glBlendColor"); - proc(red, green, blue, alpha); -} - -GLAPI void GLAPIENTRY glHistogram( GLenum target, GLsizei width, - GLenum internalformat, GLboolean sink ) -{ - RESOLVE(PFNGLHISTOGRAMPROC, "glHistogram"); - proc(target, width, internalformat, sink); -} - -GLAPI void GLAPIENTRY glResetHistogram( GLenum target ) -{ - RESOLVE(PFNGLRESETHISTOGRAMPROC, "glResetHistogram"); - proc(target); -} - -GLAPI void GLAPIENTRY glGetHistogram( GLenum target, GLboolean reset, - GLenum format, GLenum type, - GLvoid *values ) -{ - RESOLVE(PFNGLGETHISTOGRAMPROC, "glGetHistogram"); - proc(target, reset, format, type, values); -}; - -GLAPI void GLAPIENTRY glGetHistogramParameterfv( GLenum target, GLenum pname, - GLfloat *params ) -{ - RESOLVE(PFNGLGETHISTOGRAMPARAMETERFVPROC, "glGetHistogramParameterfv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glGetHistogramParameteriv( GLenum target, GLenum pname, - GLint *params ) -{ - RESOLVE(PFNGLGETHISTOGRAMPARAMETERIVPROC, "glGetHistogramParameteriv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glMinmax( GLenum target, GLenum internalformat, - GLboolean sink ) -{ - RESOLVE(PFNGLMINMAXPROC, "glMinmax"); - proc(target, internalformat, sink); -} - -GLAPI void GLAPIENTRY glResetMinmax( GLenum target ) -{ - RESOLVE(PFNGLRESETMINMAXPROC, "glResetMinmax"); - proc(target); -} - -GLAPI void GLAPIENTRY glGetMinmax( GLenum target, GLboolean reset, - GLenum format, GLenum types, - GLvoid *values ) -{ - RESOLVE(PFNGLGETMINMAXPROC, "glGetMinmax"); - proc(target, reset, format, types, values); -} - -GLAPI void GLAPIENTRY glGetMinmaxParameterfv( GLenum target, GLenum pname, - GLfloat *params ) -{ - RESOLVE(PFNGLGETMINMAXPARAMETERFVPROC, "glGetMinmaxParameterfv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glGetMinmaxParameteriv( GLenum target, GLenum pname, - GLint *params ) -{ - RESOLVE(PFNGLGETMINMAXPARAMETERIVPROC, "glGetMinmaxParameteriv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glConvolutionFilter1D( GLenum target, - GLenum internalformat, GLsizei width, GLenum format, GLenum type, - const GLvoid *image ) -{ - RESOLVE(PFNGLCONVOLUTIONFILTER1DPROC, "glConvolutionFilter1D"); - proc(target, internalformat, width, format, type, image); } -GLAPI void GLAPIENTRY glConvolutionFilter2D( GLenum target, - GLenum internalformat, GLsizei width, GLsizei height, GLenum format, - GLenum type, const GLvoid *image ) -{ - RESOLVE(PFNGLCONVOLUTIONFILTER2DPROC, "glConvolutionFilter2D"); - proc(target, internalformat, width, height, format, type, image); -} - -GLAPI void GLAPIENTRY glConvolutionParameterf( GLenum target, GLenum pname, - GLfloat params ) -{ - RESOLVE(PFNGLCONVOLUTIONPARAMETERFPROC, "glConvolutionParameterf"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glConvolutionParameterfv( GLenum target, GLenum pname, - const GLfloat *params ) -{ - RESOLVE(PFNGLCONVOLUTIONPARAMETERFVPROC, "glConvolutionParameterfv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glConvolutionParameteri( GLenum target, GLenum pname, - GLint params ) -{ - RESOLVE(PFNGLCONVOLUTIONPARAMETERIPROC, "glConvolutionParameteri"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glConvolutionParameteriv( GLenum target, GLenum pname, - const GLint *params ) -{ - RESOLVE(PFNGLCONVOLUTIONPARAMETERIVPROC, "glConvolutionParameteriv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glCopyConvolutionFilter1D( GLenum target, - GLenum internalformat, GLint x, GLint y, GLsizei width ) -{ - RESOLVE(PFNGLCOPYCONVOLUTIONFILTER1DPROC, "glCopyConvolutionFilter1D"); - proc(target, internalformat, x, y, width); -} - -GLAPI void GLAPIENTRY glCopyConvolutionFilter2D( GLenum target, - GLenum internalformat, GLint x, GLint y, GLsizei width, - GLsizei height) -{ - RESOLVE(PFNGLCOPYCONVOLUTIONFILTER2DPROC, "glCopyConvolutionFilter2D"); - proc(target, internalformat, x, y, width, height); -} +static PROC +glWinResolveHelper(PROC *cache, char *symbol) +{ + PROC proc = NULL; + + /* If not yet cached, call wglGetProcAddress */ + if ((*cache) == NULL) + { + proc = wglGetProcAddress(symbol); + if (proc == NULL) + { + ErrorF("glwrap: Can't resolve \"%s\"\n", symbol); + (*cache) = (PROC)-1; + } + else + { + ErrorF("glwrap: Resolved \"%s\"\n", symbol); + (*cache) = proc; + } + } + /* Cached wglGetProcAddress failure */ + else if ((*cache) == (PROC)-1) + { + proc = 0; + } + /* Cached wglGetProcAddress result */ + else + { + proc = (*cache); + } -GLAPI void GLAPIENTRY glGetConvolutionFilter( GLenum target, GLenum format, - GLenum type, GLvoid *image ) -{ - RESOLVE(PFNGLGETCONVOLUTIONFILTERPROC, "glGetConvolutionFilter"); - proc(target, format, type, image); + return proc; } -GLAPI void GLAPIENTRY glGetConvolutionParameterfv( GLenum target, GLenum pname, - GLfloat *params ) -{ - RESOLVE(PFNGLGETCONVOLUTIONPARAMETERFVPROC, "glGetConvolutionParameterfv"); - proc(target, pname, params); -} - -GLAPI void GLAPIENTRY glGetConvolutionParameteriv( GLenum target, GLenum pname, - GLint *params ) -{ - RESOLVE(PFNGLGETCONVOLUTIONPARAMETERIVPROC, "glGetConvolutionParameteriv"); - proc(target, pname, params); -} +#define RESOLVE_RET(proctype, symbol, retval) \ + static PROC cache = NULL; \ + __stdcall proctype proc = (proctype)glWinResolveHelper(&cache, symbol); \ + if (proc == NULL) { \ + __glXErrorCallBack(0); \ + return retval; \ + } \ + glWinIndirectProcCalls++; -GLAPI void GLAPIENTRY glSeparableFilter2D( GLenum target, - GLenum internalformat, GLsizei width, GLsizei height, GLenum format, - GLenum type, const GLvoid *row, const GLvoid *column ) -{ - RESOLVE(PFNGLSEPARABLEFILTER2DPROC, "glSeparableFilter2D"); - proc(target, internalformat, width, height, format, type, row, column); -} +#define RESOLVE(proctype, symbol) RESOLVE_RET(proctype, symbol,) -GLAPI void GLAPIENTRY glGetSeparableFilter( GLenum target, GLenum format, - GLenum type, GLvoid *row, GLvoid *column, GLvoid *span ) -{ - RESOLVE(PFNGLGETSEPARABLEFILTERPROC, "glGetSeparableFilter"); - proc(target, format, type, row, column, span); -} +#define RESOLVED_PROC(proctype) proc /* - * OpenGL 1.2 - */ + Include generated cdecl wrappers for stdcall gl*() functions in opengl32.dll -GLAPI void GLAPIENTRY glTexImage3D( GLenum target, GLint level, - GLint internalFormat, - GLsizei width, GLsizei height, - GLsizei depth, GLint border, - GLenum format, GLenum type, - const GLvoid *pixels ) -{ - RESOLVE(PFNGLTEXIMAGE3DPROC, "glTexImage3D"); - proc(target, level, internalFormat, width, height, depth, border, format, type, pixels); -} + OpenGL 1.2 and upward is treated as extensions, function address must + found using wglGetProcAddress(), but also stdcall so still need wrappers... -GLAPI void GLAPIENTRY glTexSubImage3D( GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint zoffset, GLsizei width, - GLsizei height, GLsizei depth, - GLenum format, - GLenum type, const GLvoid *pixels) -{ - RESOLVE(PFNGLTEXSUBIMAGE3DPROC, "glTexSubImage3D"); - proc(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); -} - -GLAPI void GLAPIENTRY glCopyTexSubImage3D( GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint zoffset, GLint x, - GLint y, GLsizei width, - GLsizei height ) -{ - RESOLVE(PFNGLCOPYTEXSUBIMAGE3DPROC, "glCopyTexSubImage3D"); - proc(target, level, xoffset, yoffset, zoffset, x, y, width, height); -} + Include generated dispatch table setup function +*/ +#include "generated_gl_wrappers.c" /* - * 20. GL_EXT_texture_object - */ -GLAPI void GLAPIENTRY glGenTexturesEXT( GLsizei n, GLuint *textures ) -{ - glGenTextures(n, textures); -} - -GLAPI void GLAPIENTRY glDeleteTexturesEXT( GLsizei n, const GLuint *textures) -{ - glDeleteTextures(n, textures); -} - -GLAPI void GLAPIENTRY glBindTextureEXT( GLenum target, GLuint texture ) -{ - glBindTexture(target, target); -} - -GLAPI void GLAPIENTRY glPrioritizeTexturesEXT( GLsizei n, const GLuint *textures, const GLclampf *priorities ) -{ - glPrioritizeTextures(n, textures, priorities); -} - -GLAPI GLboolean GLAPIENTRY glAreTexturesResidentEXT( GLsizei n, const GLuint *textures, GLboolean *residences ) -{ - return glAreTexturesResident(n, textures, residences); -} + Special non-static wrapper for glGetString for debug output +*/ -GLAPI GLboolean GLAPIENTRY glIsTextureEXT( GLuint texture ) +const GLubyte* glGetStringWrapperNonstatic(GLenum name) { - return glIsTexture(texture); + return glGetString(name); } /* - * GL_ARB_multitexture (ARB extension 1 and OpenGL 1.2.1) - */ - -GLAPI void GLAPIENTRY glActiveTextureARB(GLenum texture) -{ - RESOLVE(PFNGLACTIVETEXTUREARBPROC, "glActiveTextureARB"); - proc(texture); -} - -GLAPI void GLAPIENTRY glMultiTexCoord1dvARB(GLenum target, const GLdouble *v) -{ - RESOLVE(PFNGLMULTITEXCOORD1DVARBPROC, "glMultiTexCoord1dvARB"); - proc(target, v); -} - -GLAPI void GLAPIENTRY glMultiTexCoord1fvARB(GLenum target, const GLfloat *v) -{ - RESOLVE(PFNGLMULTITEXCOORD1FVARBPROC, "glMultiTexCoord1fvARB"); - proc(target, v); -} - -GLAPI void GLAPIENTRY glMultiTexCoord1ivARB(GLenum target, const GLint *v) -{ - RESOLVE(PFNGLMULTITEXCOORD1IVARBPROC, "glMultiTexCoord1ivARB"); - proc(target, v); -} - -GLAPI void GLAPIENTRY glMultiTexCoord1svARB(GLenum target, const GLshort *v) -{ - RESOLVE(PFNGLMULTITEXCOORD1SVARBPROC, "glMultiTexCoord1svARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord2dvARB(GLenum target, const GLdouble *v) -{ - RESOLVE(PFNGLMULTITEXCOORD2DVARBPROC, "glMultiTexCoord2dvARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord2fvARB(GLenum target, const GLfloat *v) -{ - RESOLVE(PFNGLMULTITEXCOORD2FVARBPROC, "glMultiTexCoord2fvARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord2ivARB(GLenum target, const GLint *v) -{ - RESOLVE(PFNGLMULTITEXCOORD2IVARBPROC, "glMultiTexCoord2ivARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord2svARB(GLenum target, const GLshort *v) -{ - RESOLVE(PFNGLMULTITEXCOORD1SVARBPROC, "glMultiTexCoord1svARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord3dvARB(GLenum target, const GLdouble *v) -{ - RESOLVE(PFNGLMULTITEXCOORD3DVARBPROC, "glMultiTexCoord3dvARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord3fvARB(GLenum target, const GLfloat *v) -{ - RESOLVE(PFNGLMULTITEXCOORD3FVARBPROC, "glMultiTexCoord3fvARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord3ivARB(GLenum target, const GLint *v) -{ - RESOLVE(PFNGLMULTITEXCOORD3IVARBPROC, "glMultiTexCoord3ivARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord3svARB(GLenum target, const GLshort *v) -{ - RESOLVE(PFNGLMULTITEXCOORD1SVARBPROC, "glMultiTexCoord1svARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord4dvARB(GLenum target, const GLdouble *v) -{ - RESOLVE(PFNGLMULTITEXCOORD4DVARBPROC, "glMultiTexCoord4dvARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord4fvARB(GLenum target, const GLfloat *v) -{ - RESOLVE(PFNGLMULTITEXCOORD4FVARBPROC, "glMultiTexCoord4fvARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord4ivARB(GLenum target, const GLint *v) -{ - RESOLVE(PFNGLMULTITEXCOORD4IVARBPROC, "glMultiTexCoord4ivARB"); - proc(target, v); -} -GLAPI void GLAPIENTRY glMultiTexCoord4svARB(GLenum target, const GLshort *v) -{ - RESOLVE(PFNGLMULTITEXCOORD1SVARBPROC, "glMultiTexCoord1svARB"); - proc(target, v); -} + Special non-static wrapper for glAddSwapHintRectWIN for copySubBuffers +*/ +typedef void (__stdcall *PFNGLADDSWAPHINTRECTWIN)(GLint x, GLint y, GLsizei width, GLsizei height); -GLAPI void GLAPIENTRY glActiveStencilFaceEXT(GLenum face) +void glAddSwapHintRectWINWrapperNonstatic(GLint x, GLint y, GLsizei width, GLsizei height) { - RESOLVE(PFNGLACTIVESTENCILFACEEXTPROC, "glActiveStencilFaceEXT"); - proc(face); + RESOLVE(PFNGLADDSWAPHINTRECTWIN, "glAddSwapHintRectWIN"); + proc(x, y, width, height); } -GLAPI void APIENTRY glPointParameterfARB(GLenum pname, GLfloat param) -{ - RESOLVE(PFNGLPOINTPARAMETERFARBPROC, "glPointParameterfARB"); - proc(pname, param); -} - -GLAPI void APIENTRY glPointParameterfvARB(GLenum pname, const GLfloat *params) -{ - RESOLVE(PFNGLPOINTPARAMETERFVARBPROC, "glPointParameterfvARB"); - proc(pname, params); -} - - -GLAPI void APIENTRY glWindowPos3fARB(GLfloat x, GLfloat y, GLfloat z) -{ - RESOLVE(PFNGLWINDOWPOS3FARBPROC, "glWindowPos3fARB"); - proc(x, y, z); -} - -GLAPI void APIENTRY glPointParameteri(GLenum pname, GLint param) -{ - RESOLVE(PFNGLPOINTPARAMETERIPROC, "glPointParameteri"); - proc(pname, param); -} - -GLAPI void APIENTRY glPointParameteriv(GLenum pname, const GLint *params) -{ - RESOLVE(PFNGLPOINTPARAMETERIVPROC, "glPointParameteriv"); - proc(pname, params); -} - -GLAPI void APIENTRY glPointParameteriNV(GLenum pname, GLint param) -{ - RESOLVE(PFNGLPOINTPARAMETERINVPROC, "glPointParameteriNV"); - proc(pname, param); -} - -GLAPI void APIENTRY glPointParameterivNV(GLenum pname, const GLint *params) -{ - RESOLVE(PFNGLPOINTPARAMETERIVNVPROC, "glPointParameterivNV"); - proc(pname, params); -} - -GLAPI void APIENTRY glSecondaryColor3bv(const GLbyte *v) -{ - RESOLVE(PFNGLSECONDARYCOLOR3BVPROC, "glSecondaryColor3bv"); - proc(v); -} -GLAPI void APIENTRY glSecondaryColor3dv(const GLdouble *v) -{ - RESOLVE(PFNGLSECONDARYCOLOR3DVPROC, "glSecondaryColor3dv"); - proc(v); -} -GLAPI void APIENTRY glSecondaryColor3fv(const GLfloat *v) -{ - RESOLVE(PFNGLSECONDARYCOLOR3FVPROC, "glSecondaryColor3fv"); - proc(v); -} -GLAPI void APIENTRY glSecondaryColor3iv(const GLint *v) -{ - RESOLVE(PFNGLSECONDARYCOLOR3IVPROC, "glSecondaryColor3iv"); - proc(v); -} -GLAPI void APIENTRY glSecondaryColor3sv(const GLshort *v) -{ - RESOLVE(PFNGLSECONDARYCOLOR3SVPROC, "glSecondaryColor3sv"); - proc(v); -} -GLAPI void APIENTRY glSecondaryColor3ubv(const GLubyte *v) -{ - RESOLVE(PFNGLSECONDARYCOLOR3UBVPROC, "glSecondaryColor3ubv"); - proc(v); -} -GLAPI void APIENTRY glSecondaryColor3uiv(const GLuint *v) -{ - RESOLVE(PFNGLSECONDARYCOLOR3UIVPROC, "glSecondaryColor3uiv"); - proc(v); -} -GLAPI void APIENTRY glSecondaryColor3usv(const GLushort *v) -{ - RESOLVE(PFNGLSECONDARYCOLOR3USVPROC, "glSecondaryColor3usv"); - proc(v); -} -GLAPI void APIENTRY glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) -{ - RESOLVE(PFNGLSECONDARYCOLORPOINTERPROC, "glSecondaryColorPointer"); - proc(size, type, stride, pointer); -} - - -GLAPI void APIENTRY glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) -{ - RESOLVE(PFNGLBLENDFUNCSEPARATEPROC, "glBlendFuncSeparate"); - proc(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); -} -GLAPI void APIENTRY glFogCoordfv(const GLfloat *coord) -{ - RESOLVE(PFNGLFOGCOORDFVPROC, "glFogCoordfv"); - proc(coord); -} -GLAPI void APIENTRY glFogCoorddv(const GLdouble *coord) -{ - RESOLVE(PFNGLFOGCOORDDVPROC, "glFogCoorddv"); - proc(coord); -} -GLAPI void APIENTRY glFogCoordPointer(GLenum type, GLsizei stride, const GLvoid *pointer) -{ - RESOLVE(PFNGLFOGCOORDPOINTERPROC, "glFogCoordPointer"); - proc(type, stride, pointer); -} - - -GLAPI void APIENTRY glSampleCoverageARB(GLclampf value, GLboolean invert) -{ - RESOLVE(PFNGLSAMPLECOVERAGEARBPROC, "glSampleCoverageARB"); - proc(value, invert); -} -GLAPI void APIENTRY glSampleMaskSGIS(GLclampf value, GLboolean invert) -{ - RESOLVE(PFNGLSAMPLEMASKSGISPROC, "glSampleMaskSGIS"); - proc(value, invert); -} -GLAPI void APIENTRY glSamplePatternSGIS(GLenum pattern) -{ - RESOLVE(PFNGLSAMPLEPATTERNSGISPROC, "glSamplePatternSGIS"); - proc(pattern); -} diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c index 5e12022f4..c12cd1fbf 100755 --- a/hw/xwin/glx/indirect.c +++ b/hw/xwin/glx/indirect.c @@ -1,22 +1,27 @@ /* - * GLX implementation that uses Windows OpenGL library - * (Indirect rendering path) + * File: indirect.c + * Purpose: A GLX implementation that uses Windows OpenGL library + * + * Authors: Alexander Gottwald + * Jon TURNEY + * + * Copyright (c) Jon TURNEY 2009 + * Copyright (c) Alexander Gottwald 2004 * - * Authors: Alexander Gottwald - */ -/* * Portions of this file are copied from GL/apple/indirect.c, * which contains the following copyright: - * + * + * Copyright (c) 2007, 2008, 2009 Apple Inc. + * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved. * Copyright (c) 2002 Greg Parker. All Rights Reserved. - * Copyright (c) 2002 Apple Computer, Inc. * - * Portions of this file are copied from xf86glx.c, + * Portions of this file are copied from Mesa's xf86glx.c, * which contains the following copyright: * * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. * All Rights Reserved. * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation @@ -34,636 +39,1539 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. */ +/* + TODO: + - hook up remaining unimplemented extensions + - research what guarantees glXWaitX, glXWaitGL are supposed to offer, and implement then + using GdiFlush and/or glFinish + - pbuffer clobbering: we don't get async notification, but can we arrange to emit the + event when we notice it's been clobbered? at the very least, check if it's been clobbered + before using it? + - are the __GLXConfig * we get handed back ones we are made (so we can extend the structure + with privates?) Or are they created inside the GLX core as well? +*/ + +/* + MSDN clarifications: + It says SetPixelFormat()'s PIXELFORMATDESCRIPTOR pointer argument has no effect + except on metafiles, this seems to mean that as it's ok to supply NULL if the DC + is not for a metafile -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> + wglMakeCurrent ignores the hdc if hglrc is NULL, so wglMakeCurrent(NULL, NULL) + is used to make no context current + +*/ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> #endif #include "glwindows.h" -#include <glcontextmodes.h> -#include <stdint.h> +#include <glx/glxserver.h> +#include <glx/glxutil.h> +#include <glx/extension_string.h> +#include <GL/glxtokens.h> #include <winpriv.h> +#include <wgl_ext_api.h> + +#define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1])) + +/* ---------------------------------------------------------------------- */ +/* + * structure definitions + */ + +typedef struct __GLXWinContext __GLXWinContext; +typedef struct __GLXWinDrawable __GLXWinDrawable; +typedef struct __GLXWinScreen glxWinScreen; +typedef struct __GLXWinConfig GLXWinConfig; + +struct __GLXWinContext { + __GLXcontext base; + HGLRC ctx; /* Windows GL Context */ + __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */ + HWND hwnd; /* For detecting when HWND has changed */ +}; + +struct __GLXWinDrawable +{ + __GLXdrawable base; + __GLXWinContext *drawContext; + __GLXWinContext *readContext; + + /* If this drawable is GLX_DRAWABLE_PBUFFER */ + HPBUFFERARB hPbuffer; + + /* If this drawable is GLX_DRAWABLE_PIXMAP */ + HDC dibDC; + HBITMAP hDIB; + HBITMAP hOldDIB; /* original DIB for DC */ + void *pOldBits; /* original pBits for this drawable's pixmap */ +}; + +struct __GLXWinScreen +{ + __GLXscreen base; + + /* Supported GLX extensions */ + unsigned char glx_enable_bits[__GLX_EXT_BYTES]; + + Bool has_WGL_ARB_multisample; + Bool has_WGL_ARB_pixel_format; + Bool has_WGL_ARB_pbuffer; + Bool has_WGL_ARB_render_texture; + + /* wrapped screen functions */ + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + CopyWindowProcPtr CopyWindow; +}; + +struct __GLXWinConfig +{ + __GLXconfig base; + int pixelFormatIndex; +}; + +/* ---------------------------------------------------------------------- */ +/* + * Various debug helpers + */ #define GLWIN_DEBUG_HWND(hwnd) \ - if (glWinDebugSettings.dumpHWND) { \ + if (glxWinDebugSettings.dumpHWND) { \ char buffer[1024]; \ if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; \ - GLWIN_DEBUG_MSG("Got HWND %s (%p)\n", buffer, hwnd); \ + GLWIN_DEBUG_MSG("Got HWND %p for window '%s'", hwnd, buffer); \ } +glxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0}; -/* ggs: needed to call back to glx with visual configs */ -extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, void **configprivs); - -glWinDebugSettingsRec glWinDebugSettings = { 1, 0, 0, 0, 0}; - -static void glWinInitDebugSettings(void) +static void glxWinInitDebugSettings(void) { char *envptr; envptr = getenv("GLWIN_ENABLE_DEBUG"); if (envptr != NULL) - glWinDebugSettings.enableDebug = (atoi(envptr) == 1); + glxWinDebugSettings.enableDebug = (atoi(envptr) == 1); envptr = getenv("GLWIN_ENABLE_TRACE"); if (envptr != NULL) - glWinDebugSettings.enableTrace = (atoi(envptr) == 1); + glxWinDebugSettings.enableTrace = (atoi(envptr) == 1); envptr = getenv("GLWIN_DUMP_PFD"); if (envptr != NULL) - glWinDebugSettings.dumpPFD = (atoi(envptr) == 1); - + glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1); + envptr = getenv("GLWIN_DUMP_HWND"); if (envptr != NULL) - glWinDebugSettings.dumpHWND = (atoi(envptr) == 1); + glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1); envptr = getenv("GLWIN_DUMP_DC"); if (envptr != NULL) - glWinDebugSettings.dumpDC = (atoi(envptr) == 1); + glxWinDebugSettings.dumpDC = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_ENABLE_GLCALL_TRACE"); + if (envptr != NULL) + glxWinDebugSettings.enableGLcallTrace = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_ENABLE_WGLCALL_TRACE"); + if (envptr != NULL) + glxWinDebugSettings.enableWGLcallTrace = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_DEBUG_ALL"); + if (envptr != NULL) + { + glxWinDebugSettings.enableDebug = 1; + glxWinDebugSettings.enableTrace = 1; + glxWinDebugSettings.dumpPFD = 1; + glxWinDebugSettings.dumpHWND = 1; + glxWinDebugSettings.dumpDC = 1; + glxWinDebugSettings.enableGLcallTrace = 1; + glxWinDebugSettings.enableWGLcallTrace = 1; + } +} + +static +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 char errorbuffer[1024]; -const char *glWinErrorMessage(void) +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) { - if (!FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &errorbuffer, - sizeof(errorbuffer), - NULL )) + 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) { - snprintf(errorbuffer, sizeof(errorbuffer), "Unknown error in FormatMessage: %08x!\n", (unsigned)GetLastError()); + 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; } - return errorbuffer; } +/* ---------------------------------------------------------------------- */ /* - * GLX implementation that uses Win32's OpenGL + * Forward declarations */ +static __GLXscreen *glxWinScreenProbe(ScreenPtr pScreen); +static __GLXcontext *glxWinCreateContext(__GLXscreen *screen, + __GLXconfig *modes, + __GLXcontext *baseShareContext); +static __GLXdrawable *glxWinCreateDrawable(__GLXscreen *screen, + DrawablePtr pDraw, + int type, + XID drawId, + __GLXconfig *conf); + +static Bool glxWinRealizeWindow(WindowPtr pWin); +static Bool glxWinUnrealizeWindow(WindowPtr pWin); +static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +static HDC glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HDC *hdc, HWND *hwnd); +static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable *draw); + +static void glxWinCreateConfigs(HDC dc, glxWinScreen *screen); +static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen); +static int fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride); +static int fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen); + +/* ---------------------------------------------------------------------- */ /* - * Server-side GLX uses these functions which are normally defined - * in the OpenGL SI. + * The GLX provider */ -GLuint __glFloorLog2(GLuint val) +__GLXprovider __glXWGLProvider = { + glxWinScreenProbe, + "Win32 native WGL", + NULL +}; + +void +glxWinPushNativeProvider(void) { - int c = 0; + GlxPushProvider(&__glXWGLProvider); +} - while (val > 1) { - c++; - val >>= 1; - } - return c; +/* ---------------------------------------------------------------------- */ +/* + * Screen functions + */ + +static void +glxWinScreenDestroy(__GLXscreen *screen) +{ + GLWIN_DEBUG_MSG("glxWinScreenDestroy(%p)", screen); + __glXScreenDestroy(screen); + xfree(screen); } -/* some prototypes */ -static Bool glWinScreenProbe(int screen); -static Bool glWinInitVisuals(VisualPtr *visualp, DepthPtr *depthp, - int *nvisualp, int *ndepthp, - int *rootDepthp, VisualID *defaultVisp, - unsigned long sizes, int bitsPerRGB); -static void glWinSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, - void **privates); -static __GLinterface *glWinCreateContext(__GLimports *imports, - __GLcontextModes *mode, - __GLinterface *shareGC); -static void glWinCreateBuffer(__GLXdrawablePrivate *glxPriv); -static void glWinResetExtension(void); +static int +glxWinScreenSwapInterval(__GLXdrawable *drawable, int interval) +{ + BOOL ret = wglSwapIntervalEXTWrapper(interval); + if (!ret) + { + ErrorF("wglSwapIntervalEXT interval %d failed:%s\n", interval, glxWinErrorMessage()); + } + return ret; +} /* - * This structure is statically allocated in the __glXScreens[] - * structure. This struct is not used anywhere other than in - * __glXScreenInit to initialize each of the active screens - * (__glXActiveScreens[]). Several of the fields must be initialized by - * the screenProbe routine before they are copied to the active screens - * struct. In particular, the contextCreate, pGlxVisual, numVisuals, - * and numUsableVisuals fields must be initialized. + Report the extensions split and formatted to avoid overflowing a line */ -static __GLXscreenInfo __glDDXScreenInfo = { - glWinScreenProbe, /* Must be generic and handle all screens */ - glWinCreateContext, /* Substitute screen's createContext routine */ - glWinCreateBuffer, /* Substitute screen's createBuffer routine */ - NULL, /* Set up pGlxVisual in probe */ - NULL, /* Set up pVisualPriv in probe */ - 0, /* Set up numVisuals in probe */ - 0, /* Set up numUsableVisuals in probe */ - "Vendor String", /* GLXvendor is overwritten by __glXScreenInit */ - "Version String", /* GLXversion is overwritten by __glXScreenInit */ - "Extensions String", /* GLXextensions is overwritten by __glXScreenInit */ - NULL /* WrappedPositionWindow is overwritten */ -}; +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; -void *__glXglDDXScreenInfo(void) { - return &__glDDXScreenInfo; + 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); } -static __GLXextensionInfo __glDDXExtensionInfo = { - GL_CORE_WINDOWS, - glWinResetExtension, - glWinInitVisuals, - glWinSetVisualConfigs -}; +/* 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... -void *__glXglDDXExtensionInfo(void) { - return &__glDDXExtensionInfo; + { + // 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; } -/* prototypes */ +/* ---------------------------------------------------------------------- */ +/* + * Window functions + */ + +static Bool +glxWinRealizeWindow(WindowPtr pWin) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen); + + GLWIN_DEBUG_MSG("glxWinRealizeWindow"); -static GLboolean glWinDestroyContext(__GLcontext *gc); -static GLboolean glWinLoseCurrent(__GLcontext *gc); -static GLboolean glWinMakeCurrent(__GLcontext *gc); -static GLboolean glWinShareContext(__GLcontext *gc, __GLcontext *gcShare); -static GLboolean glWinCopyContext(__GLcontext *dst, const __GLcontext *src, - GLuint mask); -static GLboolean glWinForceCurrent(__GLcontext *gc); + /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */ + pScreen->RealizeWindow = screenPriv->RealizeWindow; + result = pScreen->RealizeWindow(pWin); + pScreen->RealizeWindow = glxWinRealizeWindow; -/* Drawing surface notification callbacks */ -static GLboolean glWinNotifyResize(__GLcontext *gc); -static void glWinNotifyDestroy(__GLcontext *gc); -static void glWinNotifySwapBuffers(__GLcontext *gc); + return result; +} -/* Dispatch table override control for external agents like libGLS */ -static struct __GLdispatchStateRec* glWinDispatchExec(__GLcontext *gc); -static void glWinBeginDispatchOverride(__GLcontext *gc); -static void glWinEndDispatchOverride(__GLcontext *gc); -/* Debug output */ -static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd); +static void +glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + __GLXWinDrawable *pGlxDraw; + ScreenPtr pScreen = pWindow->drawable.pScreen; + glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen); -static __GLexports glWinExports = { - glWinDestroyContext, - glWinLoseCurrent, - glWinMakeCurrent, - glWinShareContext, - glWinCopyContext, - glWinForceCurrent, - - glWinNotifyResize, - glWinNotifyDestroy, - glWinNotifySwapBuffers, - - glWinDispatchExec, - glWinBeginDispatchOverride, - glWinEndDispatchOverride -}; + GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow); -glWinScreenRec glWinScreens[MAXSCREENS]; + dixLookupResourceByType((pointer) &pGlxDraw, pWindow->drawable.id, __glXDrawableRes, + NullClient, DixUnknownAccess); -/* __GLdrawablePrivate->private */ -typedef struct { - DrawablePtr pDraw; - /* xp_surface_id sid; */ -} GLWinDrawableRec; -struct __GLcontextRec { - struct __GLinterfaceRec interface; /* required to be first */ + /* + Discard any CopyWindow requests if a GL drawing context is pointing at the window - HGLRC ctx; /* Windows GL Context */ - - HDC dc; /* Windows Device Context */ - winWindowInfoRec winInfo; /* Window info from XWin */ - - PIXELFORMATDESCRIPTOR pfd; /* Pixelformat flags */ - int pixelFormat; /* Pixelformat index */ - - unsigned isAttached :1; /* Flag to track if context is attached */ -}; + 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 HDC glWinMakeDC(__GLcontext *gc) +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; - /*if (gc->winInfo.hrgn == NULL) - { - GLWIN_DEBUG_MSG("Creating region from RECT(%ld,%ld,%ld,%ld):", - gc->winInfo.rect.left, - gc->winInfo.rect.top, - gc->winInfo.rect.right, - gc->winInfo.rect.bottom); - gc->winInfo.hrgn = CreateRectRgnIndirect(&gc->winInfo.rect); - GLWIN_DEBUG_MSG2("%p\n", gc->winInfo.hrgn); - }*/ - - if (glWinDebugSettings.enableTrace) - GLWIN_DEBUG_HWND(gc->winInfo.hwnd); - - dc = GetDC(gc->winInfo.hwnd); - /*dc = GetDCEx(gc->winInfo.hwnd, gc->winInfo.hrgn, - DCX_WINDOW | DCX_NORESETATTRS ); */ + /* Swap buffers on the last active context for drawing on the drawable */ + if (draw->drawContext == NULL) + { + GLWIN_TRACE_MSG("glxWinSwapBuffers - no context for drawable"); + return GL_FALSE; + } + + GLWIN_TRACE_MSG("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)", base, draw->drawContext, draw->drawContext->ctx); + + /* + draw->drawContext->base.drawPriv will not be set if the context is not current anymore, + but if it is, it should point to this drawable.... + */ + assert((draw->drawContext->base.drawPriv == NULL) || (draw->drawContext->base.drawPriv == base)); + dc = glxWinMakeDC(draw->drawContext, draw, &dc, &hwnd); if (dc == NULL) - ErrorF("GetDC error: %s\n", glWinErrorMessage()); - return dc; + return GL_FALSE; + + ret = wglSwapLayerBuffers(dc, WGL_SWAP_MAIN_PLANE); + + glxWinReleaseDC(hwnd, dc, draw); + + if (!ret) + { + ErrorF("wglSwapBuffers failed: %s\n", glxWinErrorMessage()); + return GL_FALSE; + } + + return GL_TRUE; } -static void unattach(__GLcontext *gc) +static void +glxWinDrawableCopySubBuffer(__GLXdrawable *drawable, + int x, int y, int w, int h) { - BOOL ret; - GLWIN_DEBUG_MSG("unattach (ctx %p)\n", gc->ctx); - if (!gc->isAttached) + glAddSwapHintRectWINWrapperNonstatic(x, y, w, h); + glxWinDrawableSwapBuffers(NULL, drawable); +} + +static void +glxWinDrawableDestroy(__GLXdrawable *base) +{ + __GLXWinDrawable *glxPriv = (__GLXWinDrawable *)base; + + if (glxPriv->drawContext && (__glXLastContext == &((glxPriv->drawContext)->base))) { - ErrorF("called unattach on an unattached context\n"); - return; + // if this context is current and has unflushed commands, say we have flushed them + // (don't actually flush them, the window is going away anyhow, and an implict flush occurs + // on the next context change) + // (GLX core considers it an error when we try to select a new current context if the old one + // has unflushed commands, but the window has disappeared..) + __GLX_NOTE_FLUSHED_CMDS(__glXLastContext); + __glXLastContext = NULL; } - if (gc->ctx) + if (glxPriv->hPbuffer) + if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer)) + { + ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage()); + } + + if (glxPriv->dibDC) { - ret = wglDeleteContext(gc->ctx); - if (!ret) - ErrorF("wglDeleteContext error: %s\n", glWinErrorMessage()); - gc->ctx = NULL; + // restore the default DIB + SelectObject(glxPriv->dibDC, glxPriv->hOldDIB); + + if (!DeleteDC(glxPriv->dibDC)) + { + ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage()); + } } - if (gc->winInfo.hrgn) + if (glxPriv->hDIB) { - ret = DeleteObject(gc->winInfo.hrgn); - if (!ret) - ErrorF("DeleteObject error: %s\n", glWinErrorMessage()); - gc->winInfo.hrgn = NULL; + if (!DeleteObject(glxPriv->hDIB)) + { + ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage()); + } + + ((PixmapPtr)glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits; } - gc->isAttached = 0; + GLWIN_DEBUG_MSG("glxWinDestroyDrawable"); + xfree(glxPriv); } -static BOOL glWinAdjustHWND(__GLcontext *gc, WindowPtr pWin) +static __GLXdrawable * +glxWinCreateDrawable(__GLXscreen *screen, + DrawablePtr pDraw, + int type, + XID drawId, + __GLXconfig *conf) { - HDC dc; - BOOL ret; - HGLRC newctx; - HWND oldhwnd; + __GLXWinDrawable *glxPriv; - GLWIN_DEBUG_MSG("glWinAdjustHWND (ctx %p, pWin %p)\n", gc->ctx, pWin); + glxPriv = xalloc(sizeof *glxPriv); - if (pWin == NULL) - { - GLWIN_DEBUG_MSG("Deferring until window is created\n"); - return FALSE; - } + if (glxPriv == NULL) + return NULL; + + memset(glxPriv, 0, sizeof *glxPriv); + + if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, drawId, conf)) { + xfree(glxPriv); + return NULL; + } - oldhwnd = gc->winInfo.hwnd; - winGetWindowInfo(pWin, &gc->winInfo); - - GLWIN_DEBUG_HWND(gc->winInfo.hwnd); - if (gc->winInfo.hwnd == 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))) { - GLWIN_DEBUG_MSG("Deferring until window is created\n"); - return FALSE; + if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL)) + { + ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); + return; + } + + return; } - dc = glWinMakeDC(gc); - - if (glWinDebugSettings.dumpDC) - GLWIN_DEBUG_MSG("Got HDC %p\n", dc); - - gc->pixelFormat = ChoosePixelFormat(dc, &gc->pfd); - if (gc->pixelFormat == 0) + /* + However, in certain special cases this pixel format will be incompatible with the + use we are going to put it to, so we need to re-evaluate the pixel format to use: + + 1) When PFD_DRAW_TO_BITMAP is set, ChoosePixelFormat() always returns a format with + the cColorBits we asked for, so we need to ensure it matches the bpp of the bitmap + + 2) Applications may assume that visuals selected with glXChooseVisual() work with + pixmap drawables (there is no attribute to explicitly query for pixmap drawable + support as there is for glXChooseFBConfig()) + (it's arguable this is an error in the application, but we try to make it work) + + pixmap rendering is always slow for us, so we don't want to choose those visuals + by default, but if the actual drawable type we're trying to select the context + on (drawableTypeOverride) isn't supported by the selected fbConfig, reconsider + and see if we can find a suitable one... + */ + ErrorF("glxWinSetPixelFormat: having second thoughts: cColorbits %d, bppOveride %d; config->drawableType %d, drawableTypeOverride %d\n", + (config->redBits + config->greenBits + config->blueBits), bppOverride, config->drawableType, drawableTypeOverride); + + if (!winScreen->has_WGL_ARB_pixel_format) { - ErrorF("ChoosePixelFormat error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; - } - - ret = SetPixelFormat(dc, gc->pixelFormat, &gc->pfd); - if (!ret) { - ErrorF("SetPixelFormat error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + 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; + } } - - newctx = wglCreateContext(dc); - if (newctx == NULL) { - ErrorF("wglCreateContext error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + 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; + } } - - GLWIN_DEBUG_MSG("wglCreateContext (ctx %p)\n", newctx); +} - if (!wglShareLists(gc->ctx, newctx)) +static HDC +glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HDC *hdc, HWND *hwnd) +{ + *hdc = NULL; + *hwnd = NULL; + + if (draw == NULL) { - ErrorF("wglShareLists error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc, gc->ctx); + return NULL; } - - if (oldhwnd != gc->winInfo.hwnd) + + switch (draw->base.type) + { + case GLX_DRAWABLE_WINDOW: { - GLWIN_DEBUG_MSG("Trying wglCopyContext\n"); - if (!wglCopyContext(gc->ctx, newctx, GL_ALL_ATTRIB_BITS)) + 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("wglCopyContext error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + 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; - if (!wglDeleteContext(gc->ctx)) + case GLX_DRAWABLE_PBUFFER: { - ErrorF("wglDeleteContext error: %s\n", glWinErrorMessage()); + *hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer); + + if (*hdc == NULL) + ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage()); } + break; - gc->ctx = newctx; + case GLX_DRAWABLE_PIXMAP: + { + *hdc = draw->dibDC; + } + break; - if (!wglMakeCurrent(dc, gc->ctx)) { - ErrorF("glMakeCurrent error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + default: + { + ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n", draw->base.type); } + } - ReleaseDC(gc->winInfo.hwnd, dc); + if (glxWinDebugSettings.dumpDC) + GLWIN_DEBUG_MSG("Got HDC %p", *hdc); - return TRUE; + return *hdc; } -static BOOL glWinCreateContextReal(__GLcontext *gc, WindowPtr pWin) +static void +glxWinReleaseDC(HWND hwnd, HDC hdc,__GLXWinDrawable *draw) { - HDC dc; - BOOL ret; + switch (draw->base.type) + { + case GLX_DRAWABLE_WINDOW: + { + ReleaseDC(hwnd, hdc); + } + break; - GLWIN_DEBUG_MSG("glWinCreateContextReal (pWin %p)\n", pWin); + case GLX_DRAWABLE_PBUFFER: + { + if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc)) + { + ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage()); + } + } + break; - if (pWin == NULL) + case GLX_DRAWABLE_PIXMAP: { - GLWIN_DEBUG_MSG("Deferring until window is created\n"); - return FALSE; + // 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; - winGetWindowInfo(pWin, &gc->winInfo); - - GLWIN_DEBUG_HWND(gc->winInfo.hwnd); - if (gc->winInfo.hwnd == NULL) + default: { - GLWIN_DEBUG_MSG("Deferring until window is created\n"); - return FALSE; + ErrorF("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n", draw->base.type); } + } +} - - dc = glWinMakeDC(gc); - - if (glWinDebugSettings.dumpDC) - GLWIN_DEBUG_MSG("Got HDC %p\n", dc); - - gc->pixelFormat = ChoosePixelFormat(dc, &gc->pfd); - if (gc->pixelFormat == 0) +static 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: { - ErrorF("ChoosePixelFormat error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + 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); + } } - - ret = SetPixelFormat(dc, gc->pixelFormat, &gc->pfd); - if (!ret) { - ErrorF("SetPixelFormat error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + 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); + } } - - gc->ctx = wglCreateContext(dc); - if (gc->ctx == NULL) { - ErrorF("wglCreateContext error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + break; + + default: + { + ErrorF("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", draw->base.type); + return; } + } - GLWIN_DEBUG_MSG("glWinCreateContextReal (ctx %p)\n", gc->ctx); + dc = glxWinMakeDC(gc, draw, &dc, &hwnd); + gc->ctx = wglCreateContext(dc); + glxWinReleaseDC(hwnd, dc, draw); - if (!wglMakeCurrent(dc, gc->ctx)) { - ErrorF("glMakeCurrent error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - return FALSE; + if (gc->ctx == NULL) + { + ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage()); + return; } - ReleaseDC(gc->winInfo.hwnd, dc); + 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); - return TRUE; + if (!wglShareLists(gc->shareContext->ctx, gc->ctx)) + { + ErrorF("wglShareLists error: %s\n", glxWinErrorMessage()); + } + } } -static void attach(__GLcontext *gc, __GLdrawablePrivate *glPriv) +/* ---------------------------------------------------------------------- */ +/* + * Context functions + */ + + +/* Context manipulation routines should return TRUE on success, FALSE on failure */ +static int +glxWinContextMakeCurrent(__GLXcontext *base) { - __GLXdrawablePrivate *glxPriv = (__GLXdrawablePrivate *)glPriv->other; + __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); + } - GLWIN_DEBUG_MSG("attach (ctx %p)\n", gc->ctx); + if (gc->ctx == NULL) + { + ErrorF("glxWinContextMakeCurrent: Native context is NULL\n"); + return FALSE; + } - if (gc->isAttached) + drawDC = glxWinMakeDC(gc, (__GLXWinDrawable *)drawPriv, &drawDC, &hDrawWnd); + if (drawDC == NULL) { - ErrorF("called attach on an attached context\n"); - return; + ErrorF("glxWinMakeDC failed for drawDC\n"); + return FALSE; } - if (glxPriv->type == DRAWABLE_WINDOW) + if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv)) { - WindowPtr pWin = (WindowPtr) glxPriv->pDraw; - if (pWin == NULL) + // 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) { - GLWIN_DEBUG_MSG("Deferring ChoosePixelFormat until window is created\n"); - } else + ErrorF("glxWinMakeDC failed for readDC\n"); + glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *)drawPriv); + return FALSE; + } + + ret = wglMakeContextCurrentARBWrapper(drawDC, readDC, gc->ctx); + if (!ret) { - if (glWinCreateContextReal(gc, pWin)) - { - gc->isAttached = TRUE; - GLWIN_DEBUG_MSG("attached\n"); - } + ErrorF("wglMakeContextCurrentARBWrapper error: %s\n", glxWinErrorMessage()); + } + } + else + { + /* Otherwise, just use wglMakeCurrent */ + ret = wglMakeCurrent(drawDC, gc->ctx); + if (!ret) + { + ErrorF("wglMakeCurrent error: %s\n", glxWinErrorMessage()); } } -} -static GLboolean glWinLoseCurrent(__GLcontext *gc) -{ - GLWIN_TRACE_MSG("glWinLoseCurrent (ctx %p)\n", gc->ctx); + // 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... - __glXLastContext = NULL; /* Mesa does this; why? */ + glxWinReleaseDC(hDrawWnd, drawDC, (__GLXWinDrawable *)drawPriv); + if (readDC) + glxWinReleaseDC(hReadWnd, readDC, (__GLXWinDrawable *)readPriv); - return GL_TRUE; + return ret; } -/* Context manipulation; return GL_FALSE on failure */ -static GLboolean glWinDestroyContext(__GLcontext *gc) +static int +glxWinContextLoseCurrent(__GLXcontext *base) { - GLWIN_DEBUG_MSG("glWinDestroyContext (ctx %p)\n", gc->ctx); + BOOL ret; + __GLXWinContext *gc = (__GLXWinContext *)base; + + GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc, gc->ctx); + glWinCallDelta(); - if (gc != NULL) + /* + 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) { - if (gc->isAttached) - unattach(gc); - if (gc->dc != NULL) - DeleteDC(gc->dc); - free(gc); + ret = wglMakeCurrent(NULL, NULL); /* We don't need a DC when setting no current context */ + if (!ret) + ErrorF("glxWinContextLoseCurrent error: %s\n", glxWinErrorMessage()); } - return GL_TRUE; + return TRUE; } -static GLboolean glWinMakeCurrent(__GLcontext *gc) +static int +glxWinContextCopy(__GLXcontext *dst_base, __GLXcontext *src_base, unsigned long mask) { - __GLdrawablePrivate *glPriv = gc->interface.imports.getDrawablePrivate(gc); - BOOL ret; - HDC dc; + __GLXWinContext *dst = (__GLXWinContext *)dst_base; + __GLXWinContext *src = (__GLXWinContext *)src_base; + BOOL ret; - GLWIN_TRACE_MSG(" (ctx %p)\n", gc->ctx); + GLWIN_DEBUG_MSG("glxWinContextCopy"); - if (!gc->isAttached) - attach(gc, glPriv); - - if (gc->ctx == NULL) { - ErrorF("Context is NULL\n"); - return GL_FALSE; + ret = wglCopyContext(src->ctx, dst->ctx, mask); + if (!ret) + { + ErrorF("wglCopyContext error: %s\n", glxWinErrorMessage()); } - dc = glWinMakeDC(gc); - ret = wglMakeCurrent(dc, gc->ctx); - if (!ret) - ErrorF("glMakeCurrent error: %s\n", glWinErrorMessage()); - ReleaseDC(gc->winInfo.hwnd, dc); - - return ret?GL_TRUE:GL_FALSE; + return ret; } -static GLboolean glWinShareContext(__GLcontext *gc, __GLcontext *gcShare) +static int +glxWinContextForceCurrent(__GLXcontext *base) { - GLWIN_DEBUG_MSG("glWinShareContext unimplemented\n"); - - return GL_TRUE; + /* wglMakeCurrent always flushes the previous context, so this is equivalent to glxWinContextMakeCurrent */ + return glxWinContextMakeCurrent(base); } -static GLboolean glWinCopyContext(__GLcontext *dst, const __GLcontext *src, - GLuint mask) +static void +glxWinContextDestroy(__GLXcontext *base) { - BOOL ret; + __GLXWinContext *gc = (__GLXWinContext *)base; - GLWIN_DEBUG_MSG("glWinCopyContext\n"); - - ret = wglCopyContext(src->ctx, dst->ctx, mask); - if (!ret) + if (gc != NULL) { - ErrorF("wglCopyContext error: %s\n", glWinErrorMessage()); - return GL_FALSE; - } + GLWIN_DEBUG_MSG("GLXcontext %p destroyed (native ctx %p)", base, gc->ctx); - return GL_TRUE; + 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 GLboolean glWinForceCurrent(__GLcontext *gc) +static __GLXcontext * +glxWinCreateContext(__GLXscreen *screen, + __GLXconfig *modes, + __GLXcontext *baseShareContext) { - GLWIN_TRACE_MSG(" (ctx %p)\n", gc->ctx); + __GLXWinContext *context; + __GLXWinContext *shareContext = (__GLXWinContext *)baseShareContext; - return GL_TRUE; -} + static __GLXtextureFromPixmap glxWinTextureFromPixmap = + { + glxWinBindTexImage, + glxWinReleaseTexImage + }; -/* Drawing surface notification callbacks */ + context = (__GLXWinContext *)xcalloc(1, sizeof(__GLXWinContext)); -static GLboolean glWinNotifyResize(__GLcontext *gc) -{ - GLWIN_DEBUG_MSG("unimplemented glWinNotifyResize"); - return GL_TRUE; -} + if (!context) + return NULL; -static void glWinNotifyDestroy(__GLcontext *gc) -{ - GLWIN_DEBUG_MSG("unimplemented glWinNotifyDestroy"); -} + 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; -static void glWinNotifySwapBuffers(__GLcontext *gc) -{ - GLWIN_DEBUG_MSG("unimplemented glWinNotifySwapBuffers"); -} + // actual native GL context creation is deferred until attach() + context->ctx = NULL; + context->shareContext = shareContext; -/* Dispatch table override control for external agents like libGLS */ -static struct __GLdispatchStateRec* glWinDispatchExec(__GLcontext *gc) -{ - GLWIN_DEBUG_MSG("unimplemented glWinDispatchExec"); - return NULL; -} + glWinSetupDispatchTable(); -static void glWinBeginDispatchOverride(__GLcontext *gc) -{ - GLWIN_DEBUG_MSG("unimplemented glWinBeginDispatchOverride"); -} + GLWIN_DEBUG_MSG("GLXcontext %p created", context); -static void glWinEndDispatchOverride(__GLcontext *gc) -{ - GLWIN_DEBUG_MSG("unimplemented glWinEndDispatchOverride"); + return &(context->base); } -#define DUMP_PFD_FLAG(flag) \ - if (pfd->dwFlags & flag) { \ - ErrorF("%s%s", pipesym, #flag); \ - pipesym = " | "; \ - } - -static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd) -{ - const char *pipesym = ""; /* will be set after first flag dump */ - ErrorF("PIXELFORMATDESCRIPTOR:\n"); - ErrorF("nSize = %u\n", pfd->nSize); - ErrorF("nVersion = %u\n", pfd->nVersion); - ErrorF("dwFlags = %lu = {", pfd->dwFlags); - DUMP_PFD_FLAG(PFD_MAIN_PLANE); - DUMP_PFD_FLAG(PFD_OVERLAY_PLANE); - DUMP_PFD_FLAG(PFD_UNDERLAY_PLANE); - DUMP_PFD_FLAG(PFD_DOUBLEBUFFER); - DUMP_PFD_FLAG(PFD_STEREO); - DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW); - DUMP_PFD_FLAG(PFD_DRAW_TO_BITMAP); - DUMP_PFD_FLAG(PFD_SUPPORT_GDI); - DUMP_PFD_FLAG(PFD_SUPPORT_OPENGL); - DUMP_PFD_FLAG(PFD_GENERIC_FORMAT); - DUMP_PFD_FLAG(PFD_NEED_PALETTE); - DUMP_PFD_FLAG(PFD_NEED_SYSTEM_PALETTE); - DUMP_PFD_FLAG(PFD_SWAP_EXCHANGE); - DUMP_PFD_FLAG(PFD_SWAP_COPY); - DUMP_PFD_FLAG(PFD_SWAP_LAYER_BUFFERS); - DUMP_PFD_FLAG(PFD_GENERIC_ACCELERATED); - DUMP_PFD_FLAG(PFD_DEPTH_DONTCARE); - DUMP_PFD_FLAG(PFD_DOUBLEBUFFER_DONTCARE); - DUMP_PFD_FLAG(PFD_STEREO_DONTCARE); - ErrorF("}\n"); - - ErrorF("iPixelType = %hu = %s\n", pfd->iPixelType, - (pfd->iPixelType == PFD_TYPE_RGBA ? "PFD_TYPE_RGBA" : "PFD_TYPE_COLORINDEX")); - ErrorF("cColorBits = %hhu\n", pfd->cColorBits); - ErrorF("cRedBits = %hhu\n", pfd->cRedBits); - ErrorF("cRedShift = %hhu\n", pfd->cRedShift); - ErrorF("cGreenBits = %hhu\n", pfd->cGreenBits); - ErrorF("cGreenShift = %hhu\n", pfd->cGreenShift); - ErrorF("cBlueBits = %hhu\n", pfd->cBlueBits); - ErrorF("cBlueShift = %hhu\n", pfd->cBlueShift); - ErrorF("cAlphaBits = %hhu\n", pfd->cAlphaBits); - ErrorF("cAlphaShift = %hhu\n", pfd->cAlphaShift); - ErrorF("cAccumBits = %hhu\n", pfd->cAccumBits); - ErrorF("cAccumRedBits = %hhu\n", pfd->cAccumRedBits); - ErrorF("cAccumGreenBits = %hhu\n", pfd->cAccumGreenBits); - ErrorF("cAccumBlueBits = %hhu\n", pfd->cAccumBlueBits); - ErrorF("cAccumAlphaBits = %hhu\n", pfd->cAccumAlphaBits); - ErrorF("cDepthBits = %hhu\n", pfd->cDepthBits); - ErrorF("cStencilBits = %hhu\n", pfd->cStencilBits); - ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers); - ErrorF("iLayerType = %hhu\n", pfd->iLayerType); - ErrorF("bReserved = %hhu\n", pfd->bReserved); - ErrorF("dwLayerMask = %lu\n", pfd->dwLayerMask); - ErrorF("dwVisibleMask = %lu\n", pfd->dwVisibleMask); - ErrorF("dwDamageMask = %lu\n", pfd->dwDamageMask); - ErrorF("\n"); -} +/* ---------------------------------------------------------------------- */ +/* + * Utility functions + */ -static int makeFormat(__GLcontextModes *mode, PIXELFORMATDESCRIPTOR *pfdret) +static int +fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride) { PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ 1, /* version number */ - PFD_DRAW_TO_WINDOW | /* support window */ PFD_SUPPORT_OPENGL, /* support OpenGL */ PFD_TYPE_RGBA, /* RGBA type */ 24, /* 24-bit color depth */ @@ -672,934 +1580,737 @@ static int makeFormat(__GLcontextModes *mode, PIXELFORMATDESCRIPTOR *pfdret) 0, /* shift bit ignored */ 0, /* no accumulation buffer */ 0, 0, 0, 0, /* accum bits ignored */ - 0, /* 32-bit z-buffer */ + 32, /* 32-bit z-buffer */ 0, /* no stencil buffer */ 0, /* no auxiliary buffer */ PFD_MAIN_PLANE, /* main layer */ 0, /* reserved */ 0, 0, 0 /* layer masks ignored */ - }, *result = &pfd; + }; + + 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 */ - /* disable anything but rgba. must get rgba to work first */ - if (!mode->rgbMode) - return -1; - if (mode->stereoMode) { - result->dwFlags |= PFD_STEREO; + pfd.dwFlags |= PFD_STEREO; } if (mode->doubleBufferMode) { - result->dwFlags |= PFD_DOUBLEBUFFER; + pfd.dwFlags |= PFD_DOUBLEBUFFER; } - if (mode->colorIndexMode) { - /* ignored, see above */ - result->iPixelType = PFD_TYPE_COLORINDEX; - result->cColorBits = mode->redBits + mode->greenBits + mode->blueBits; - result->cRedBits = mode->redBits; - result->cRedShift = 0; /* FIXME */ - result->cGreenBits = mode->greenBits; - result->cGreenShift = 0; /* FIXME */ - result->cBlueBits = mode->blueBits; - result->cBlueShift = 0; /* FIXME */ - result->cAlphaBits = mode->alphaBits; - result->cAlphaShift = 0; /* FIXME */ - } + 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 ? */ - if (mode->rgbMode) { - result->iPixelType = PFD_TYPE_RGBA; - result->cColorBits = mode->redBits + mode->greenBits + mode->blueBits; - result->cRedBits = mode->redBits; - result->cRedShift = 0; /* FIXME */ - result->cGreenBits = mode->greenBits; - result->cGreenShift = 0; /* FIXME */ - result->cBlueBits = mode->blueBits; - result->cBlueShift = 0; /* FIXME */ - result->cAlphaBits = mode->alphaBits; - result->cAlphaShift = 0; /* FIXME */ - } + *pfdret = pfd; - if (mode->haveAccumBuffer) { - result->cAccumBits = mode->accumRedBits + mode->accumGreenBits - + mode->accumBlueBits + mode->accumAlphaBits; - result->cAccumRedBits = mode->accumRedBits; - result->cAccumGreenBits = mode->accumGreenBits; - result->cAccumBlueBits = mode->accumBlueBits; - result->cAccumAlphaBits = mode->accumAlphaBits; - } - - if (mode->haveDepthBuffer) { - result->cDepthBits = mode->depthBits; - } - if (mode->haveStencilBuffer) { - result->cStencilBits = mode->stencilBits; + 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); - /* result->cAuxBuffers = mode->numAuxBuffers; */ + if (drawableTypeOverride & GLX_PBUFFER_BIT) + if (winScreen->has_WGL_ARB_pbuffer) + SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE); + } - /* mode->level ignored */ + SET_ATTR_VALUE(0, 0); // terminator - /* mode->pixmapMode ? */ + /* choose the first match */ + { + int pixelFormatIndex; - *pfdret = pfd; + if (!wglChoosePixelFormatARBWrapper(hdc, attribList, NULL, 1, &pixelFormatIndex, &numFormats)) + { + ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage()); + } + else + { + if (numFormats > 0) + { + GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d)", pixelFormatIndex); + return pixelFormatIndex; + } + else + ErrorF("wglChoosePixelFormat couldn't decide\n"); + } + } - return 0; + return 0; } -static __GLinterface *glWinCreateContext(__GLimports *imports, - __GLcontextModes *mode, - __GLinterface *shareGC) +/* ---------------------------------------------------------------------- */ + +#define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask)) + +// +// Create the GLXconfigs using DescribePixelFormat() +// +static void +glxWinCreateConfigs(HDC hdc, glxWinScreen *screen) { - __GLcontext *result; + GLXWinConfig *c, *result, *prev = NULL; + int numConfigs = 0; + int i = 0; + int n = 0; + PIXELFORMATDESCRIPTOR pfd; - GLWIN_DEBUG_MSG("glWinCreateContext\n"); + GLWIN_DEBUG_MSG("glxWinCreateConfigs"); - result = (__GLcontext *)calloc(1, sizeof(__GLcontext)); - if (!result) - return NULL; + 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); - result->interface.imports = *imports; - result->interface.exports = glWinExports; + /* alloc */ + result = xalloc(sizeof(GLXWinConfig) * numConfigs); - if (makeFormat(mode, &result->pfd)) + if (NULL == result) { - ErrorF("makeFormat failed\n"); - free(result); - return NULL; + return; } - if (glWinDebugSettings.dumpPFD) - pfdOut(&result->pfd); + memset(result, 0, sizeof(GLXWinConfig) * numConfigs); + n = 0; - GLWIN_DEBUG_MSG("glWinCreateContext done\n"); - return (__GLinterface *)result; -} + /* fill in configs */ + for (i = 0; i < numConfigs; i++) + { + int rc; -Bool -glWinRealizeWindow(WindowPtr pWin) -{ - /* If this window has GL contexts, tell them to reattach */ - /* reattaching is bad: display lists and parameters get lost */ - Bool result; - ScreenPtr pScreen = pWin->drawable.pScreen; - glWinScreenRec *screenPriv = &glWinScreens[pScreen->myNum]; - __GLXdrawablePrivate *glxPriv; + c = &(result[i]); + c->base.next = NULL; + c->pixelFormatIndex = i+1; - GLWIN_DEBUG_MSG("glWinRealizeWindow\n"); + rc = DescribePixelFormat(hdc, i+1, sizeof(PIXELFORMATDESCRIPTOR), &pfd); - /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */ - pScreen->RealizeWindow = screenPriv->RealizeWindow; - result = pScreen->RealizeWindow(pWin); - pScreen->RealizeWindow = glWinRealizeWindow; - - /* Re-attach this window's GL contexts, if any. */ - glxPriv = __glXFindDrawablePrivate(pWin->drawable.id); - if (glxPriv) { - __GLXcontext *gx; - __GLcontext *gc; - __GLdrawablePrivate *glPriv = &glxPriv->glPriv; - GLWIN_DEBUG_MSG("glWinRealizeWindow is GL drawable!\n"); - - /* GL contexts bound to this window for drawing */ - for (gx = glxPriv->drawGlxc; gx != NULL; gx = gx->next) { - gc = (__GLcontext *)gx->gc; - if (gc->isAttached) -#if 1 - { - GLWIN_DEBUG_MSG("context is already bound! Adjusting HWND.\n"); - glWinAdjustHWND(gc, pWin); - continue; - } -#else - unattach(gc); -#endif - attach(gc, glPriv); + if (!rc) + { + ErrorF("DescribePixelFormat failed for index %d, error %s\n", i+1, glxWinErrorMessage()); + break; } - /* GL contexts bound to this window for reading */ - for (gx = glxPriv->readGlxc; gx != NULL; gx = gx->next) { - gc = (__GLcontext *)gx->gc; - if (gc->isAttached) -#if 1 - { - GLWIN_DEBUG_MSG("context is already bound! Adjusting HWND.\n"); - glWinAdjustHWND(gc, pWin); - continue; - } -#else - unattach(gc); -#endif - attach(gc, glPriv); + 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; } - } - return result; -} + 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; -void -glWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - glWinScreenRec *screenPriv = &glWinScreens[pScreen->myNum]; - __GLXdrawablePrivate *glxPriv; - - GLWIN_TRACE_MSG(" (pWindow %p)\n", pWindow); - - /* Check if the window is attached and discard any drawing request */ - glxPriv = __glXFindDrawablePrivate(pWindow->drawable.id); - if (glxPriv) { - __GLXcontext *gx; - - /* GL contexts bound to this window for drawing */ - for (gx = glxPriv->drawGlxc; gx != NULL; gx = gx->next) { -/* - GLWIN_DEBUG_MSG("glWinCopyWindow - calling glDrawBuffer\n"); - glDrawBuffer(GL_FRONT); - */ - - return; - } + 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; - /* GL contexts bound to this window for reading */ - for (gx = glxPriv->readGlxc; gx != NULL; gx = gx->next) { - return; + if (pfd.iPixelType == PFD_TYPE_COLORINDEX) + { + c->base.indexBits = pfd.cColorBits; + } + else + { + c->base.indexBits = 0; } - } - GLWIN_DEBUG_MSG("glWinCopyWindow - passing to hw layer\n"); + c->base.accumRedBits = pfd.cAccumRedBits; + c->base.accumGreenBits = pfd.cAccumGreenBits; + c->base.accumBlueBits = pfd.cAccumBlueBits; + c->base.accumAlphaBits = pfd.cAccumAlphaBits; + // pfd.cAccumBits; - pScreen->CopyWindow = screenPriv->CopyWindow; - pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc); - pScreen->CopyWindow = glWinCopyWindow; -} + c->base.depthBits = pfd.cDepthBits; + c->base.stencilBits = pfd.cStencilBits; + c->base.numAuxBuffers = pfd.cAuxBuffers; -Bool -glWinUnrealizeWindow(WindowPtr pWin) -{ - /* If this window has GL contexts, tell them to unattach */ - Bool result; - ScreenPtr pScreen = pWin->drawable.pScreen; - glWinScreenRec *screenPriv = &glWinScreens[pScreen->myNum]; - __GLXdrawablePrivate *glxPriv; - - GLWIN_DEBUG_MSG("glWinUnrealizeWindow\n"); - - /* The Aqua window may have already been destroyed (windows - * are unrealized from top down) - */ - - /* Unattach this window's GL contexts, if any. */ - glxPriv = __glXFindDrawablePrivate(pWin->drawable.id); - if (glxPriv) { - __GLXcontext *gx; - __GLcontext *gc; - GLWIN_DEBUG_MSG("glWinUnealizeWindow is GL drawable!\n"); - - /* GL contexts bound to this window for drawing */ - for (gx = glxPriv->drawGlxc; gx != NULL; gx = gx->next) { - gc = (__GLcontext *)gx->gc; - unattach(gc); - } + // 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() - /* GL contexts bound to this window for reading */ - for (gx = glxPriv->readGlxc; gx != NULL; gx = gx->next) { - gc = (__GLcontext *)gx->gc; - unattach(gc); + /* 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; } - } - pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow; - result = pScreen->UnrealizeWindow(pWin); - pScreen->UnrealizeWindow = glWinUnrealizeWindow; + /* EXT_visual_info / GLX 1.2 */ + if (pfd.iPixelType == PFD_TYPE_COLORINDEX) + { + c->base.visualType = GLX_STATIC_COLOR; - return result; -} + 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; -/* - * In the case the driver has no GLX visuals we'll use these. - * [0] = RGB, double buffered - * [1] = RGB, double buffered, stencil, accum - */ -/* Originally copied from Mesa */ + /* ARB_multisample / SGIS_multisample */ + c->base.sampleBuffers = 0; + c->base.samples = 0; -static int numConfigs = 0; -static __GLXvisualConfig *visualConfigs = NULL; -static void **visualPrivates = NULL; + /* 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)); -#define NUM_FALLBACK_CONFIGS 2 -static __GLXvisualConfig FallbackConfigs[NUM_FALLBACK_CONFIGS] = { - { - -1, /* vid */ - -1, /* class */ - True, /* rgba */ - -1, -1, -1, 0, /* rgba sizes */ - -1, -1, -1, 0, /* rgba masks */ - 0, 0, 0, 0, /* rgba accum sizes */ - True, /* doubleBuffer */ - False, /* stereo */ - -1, /* bufferSize */ - 16, /* depthSize */ - 0, /* stencilSize */ - 0, /* auxBuffers */ - 0, /* level */ - GLX_NONE_EXT, /* visualRating */ - 0, /* transparentPixel */ - 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */ - 0 /* transparentIndex */ - }, - { - -1, /* vid */ - -1, /* class */ - True, /* rgba */ - -1, -1, -1, 0, /* rgba sizes */ - -1, -1, -1, 0, /* rgba masks */ - 16, 16, 16, 0, /* rgba accum sizes */ - True, /* doubleBuffer */ - False, /* stereo */ - -1, /* bufferSize */ - 16, /* depthSize */ - 8, /* stencilSize */ - 0, /* auxBuffers */ - 0, /* level */ - GLX_NONE_EXT, /* visualRating */ - 0, /* transparentPixel */ - 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */ - 0 /* transparentIndex */ - } -}; + if (pfd.iPixelType == PFD_TYPE_COLORINDEX) + { + c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT; + } + else + { + c->base.renderType = GLX_RGBA_BIT; + } -static __GLXvisualConfig NullConfig = { - -1, /* vid */ - -1, /* class */ - False, /* rgba */ - -1, -1, -1, 0, /* rgba sizes */ - -1, -1, -1, 0, /* rgba masks */ - 0, 0, 0, 0, /* rgba accum sizes */ - False, /* doubleBuffer */ - False, /* stereo */ - -1, /* bufferSize */ - 16, /* depthSize */ - 0, /* stencilSize */ - 0, /* auxBuffers */ - 0, /* level */ - GLX_NONE_EXT, /* visualRating */ - 0, /* transparentPixel */ - 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */ - 0 /* transparentIndex */ -}; + c->base.xRenderable = GL_TRUE; + c->base.fbconfigID = -1; // will be set by __glXScreenInit() -static inline int count_bits(uint32_t x) -{ - x = x - ((x >> 1) & 0x55555555); - x = (x & 0x33333333) + ((x >> 2) & 0x33333333); - x = (x + (x >> 4)) & 0x0f0f0f0f; - x = x + (x >> 8); - x = x + (x >> 16); - return x & 63; -} + /* 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; -/* Mostly copied from Mesa's xf86glx.c */ -static Bool init_visuals(int *nvisualp, VisualPtr *visualp, - VisualID *defaultVisp, - int ndepth, DepthPtr pdepth, - int rootDepth) -{ - int numRGBconfigs; - int numCIconfigs; - int numVisuals = *nvisualp; - int numNewVisuals; - int numNewConfigs; - VisualPtr pVisual = *visualp; - VisualPtr pVisualNew = NULL; - VisualID *orig_vid = NULL; - __GLcontextModes *modes = NULL; - __GLXvisualConfig *pNewVisualConfigs = NULL; - void **glXVisualPriv; - void **pNewVisualPriv; - int found_default; - int i, j, k; - - GLWIN_DEBUG_MSG("init_visuals\n"); - - if (numConfigs > 0) - numNewConfigs = numConfigs; - else - numNewConfigs = NUM_FALLBACK_CONFIGS; + /* SGIX_visual_select_group */ + // arrange for visuals with the best acceleration to be preferred in selection + switch (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) + { + case 0: + c->base.visualSelectGroup = 2; + break; - /* Alloc space for the list of new GLX visuals */ - pNewVisualConfigs = (__GLXvisualConfig *) - __glXMalloc(numNewConfigs * sizeof(__GLXvisualConfig)); - if (!pNewVisualConfigs) { - return FALSE; - } + case PFD_GENERIC_ACCELERATED: + c->base.visualSelectGroup = 1; + break; - /* Alloc space for the list of new GLX visual privates */ - pNewVisualPriv = (void **) __glXMalloc(numNewConfigs * sizeof(void *)); - if (!pNewVisualPriv) { - __glXFree(pNewVisualConfigs); - return FALSE; - } + case PFD_GENERIC_FORMAT: + c->base.visualSelectGroup = 0; + break; - /* - ** If SetVisualConfigs was not called, then use default GLX - ** visual configs. - */ - if (numConfigs == 0) { - memcpy(pNewVisualConfigs, FallbackConfigs, - NUM_FALLBACK_CONFIGS * sizeof(__GLXvisualConfig)); - memset(pNewVisualPriv, 0, NUM_FALLBACK_CONFIGS * sizeof(void *)); - } - else { - /* copy driver's visual config info */ - for (i = 0; i < numConfigs; i++) { - pNewVisualConfigs[i] = visualConfigs[i]; - pNewVisualPriv[i] = visualPrivates[i]; + default: + ; + // "can't happen" } - } - /* Count the number of RGB and CI visual configs */ - numRGBconfigs = 0; - numCIconfigs = 0; - for (i = 0; i < numNewConfigs; i++) { - if (pNewVisualConfigs[i].rgba) - numRGBconfigs++; - else - numCIconfigs++; - } + /* 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; - /* Count the total number of visuals to compute */ - numNewVisuals = 0; - for (i = 0; i < numVisuals; i++) { - int count; + /* EXT_import_context */ + c->base.screen = screen->base.pScreen->myNum; - count = ((pVisual[i].class == TrueColor - || pVisual[i].class == DirectColor) - ? numRGBconfigs : numCIconfigs); - if (count == 0) - count = 1; /* preserve the existing visual */ + /* EXT_texture_from_pixmap */ + c->base.bindToTextureRgb = -1; + c->base.bindToTextureRgba = -1; + c->base.bindToMipmapTexture = -1; + c->base.bindToTextureTargets = -1; + c->base.yInverted = -1; - numNewVisuals += count; - } + n++; - /* Reset variables for use with the next screen/driver's visual configs */ - visualConfigs = NULL; - numConfigs = 0; + // update previous config to point to this config + if (prev) + prev->base.next = &(c->base); - /* Alloc temp space for the list of orig VisualIDs for each new visual */ - orig_vid = (VisualID *)__glXMalloc(numNewVisuals * sizeof(VisualID)); - if (!orig_vid) { - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - return FALSE; + prev = c; } - /* Alloc space for the list of glXVisuals */ - modes = _gl_context_modes_create(numNewVisuals, sizeof(__GLcontextModes)); - if (modes == NULL) { - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - return FALSE; - } - - /* Alloc space for the list of glXVisualPrivates */ - glXVisualPriv = (void **)__glXMalloc(numNewVisuals * sizeof(void *)); - if (!glXVisualPriv) { - _gl_context_modes_destroy( modes ); - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - return FALSE; - } + GLWIN_DEBUG_MSG("found %d pixelFormats suitable for conversion to fbConfigs", n); - /* Alloc space for the new list of the X server's visuals */ - pVisualNew = (VisualPtr)__glXMalloc(numNewVisuals * sizeof(VisualRec)); - if (!pVisualNew) { - __glXFree(glXVisualPriv); - _gl_context_modes_destroy( modes ); - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - return FALSE; - } - - /* Initialize the new visuals */ - found_default = FALSE; - glWinScreens[screenInfo.numScreens-1].modes = modes; - for (i = j = 0; i < numVisuals; i++) { - int is_rgb = (pVisual[i].class == TrueColor || - pVisual[i].class == DirectColor); + screen->base.numFBConfigs = n; + screen->base.fbconfigs = &(result->base); +} - if (!is_rgb) +// 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) { - /* We don't support non-rgb visuals for GL. But we don't - want to remove them either, so just pass them through - with null glX configs */ - - pVisualNew[j] = pVisual[i]; - pVisualNew[j].vid = FakeClientID(0); + GLWIN_TRACE_MSG("getAttrValue attr 0x%x, value %d", attr, values[i]); + return values[i]; + } + } - /* Check for the default visual */ - if (!found_default && pVisual[i].vid == *defaultVisp) { - *defaultVisp = pVisualNew[j].vid; - found_default = TRUE; - } + ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n", attr, fallback); + return fallback; +} - /* Save the old VisualID */ - orig_vid[j] = pVisual[i].vid; +// +// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension +// +static void +glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen) +{ + GLXWinConfig *c, *result, *prev = NULL; + int i = 0; + int n = 0; - /* Initialize the glXVisual */ - _gl_copy_visual_to_context_mode( modes, & NullConfig ); - modes->visualID = pVisualNew[j].vid; + const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB; + int numConfigs; - j++; + int attrs[50]; + unsigned int num_attrs = 0; - continue; - } + GLWIN_DEBUG_MSG("glxWinCreateConfigsExt"); - for (k = 0; k < numNewConfigs; k++) { - if (pNewVisualConfigs[k].rgba != is_rgb) - continue; + screen->base.numFBConfigs = 0; + screen->base.fbconfigs = NULL; - assert( modes != NULL ); + if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs)) + { + ErrorF("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n", glxWinErrorMessage()); + return; + } - /* Initialize the new visual */ - pVisualNew[j] = pVisual[i]; - pVisualNew[j].vid = FakeClientID(0); + GLWIN_DEBUG_MSG("wglGetPixelFormatAttribivARB says %d possible pixel formats", numConfigs); - /* Check for the default visual */ - if (!found_default && pVisual[i].vid == *defaultVisp) { - *defaultVisp = pVisualNew[j].vid; - found_default = TRUE; - } + /* alloc */ + result = xalloc(sizeof(GLXWinConfig) * numConfigs); - /* Save the old VisualID */ - orig_vid[j] = pVisual[i].vid; - - /* Initialize the glXVisual */ - _gl_copy_visual_to_context_mode( modes, & pNewVisualConfigs[k] ); - modes->visualID = pVisualNew[j].vid; - - /* - * If the class is -1, then assume the X visual information - * is identical to what GLX needs, and take them from the X - * visual. NOTE: if class != -1, then all other fields MUST - * be initialized. - */ - if (modes->visualType == GLX_NONE) { - modes->visualType = _gl_convert_from_x_visual_type( pVisual[i].class ); - modes->redBits = count_bits(pVisual[i].redMask); - modes->greenBits = count_bits(pVisual[i].greenMask); - modes->blueBits = count_bits(pVisual[i].blueMask); - modes->alphaBits = modes->alphaBits; - modes->redMask = pVisual[i].redMask; - modes->greenMask = pVisual[i].greenMask; - modes->blueMask = pVisual[i].blueMask; - modes->alphaMask = modes->alphaMask; - modes->rgbBits = (is_rgb) - ? (modes->redBits + modes->greenBits + - modes->blueBits + modes->alphaBits) - : rootDepth; - } + if (NULL == result) + { + return; + } - /* Save the device-dependent private for this visual */ - glXVisualPriv[j] = pNewVisualPriv[k]; + 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); + } - j++; - modes = modes->next; - } + 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); } - assert(j <= numNewVisuals); - - /* Save the GLX visuals in the screen structure */ - glWinScreens[screenInfo.numScreens-1].num_vis = numNewVisuals; - glWinScreens[screenInfo.numScreens-1].priv = glXVisualPriv; - - /* Set up depth's VisualIDs */ - for (i = 0; i < ndepth; i++) { - int numVids = 0; - VisualID *pVids = NULL; - int k, n = 0; - - /* Count the new number of VisualIDs at this depth */ - for (j = 0; j < pdepth[i].numVids; j++) - for (k = 0; k < numNewVisuals; k++) - if (pdepth[i].vids[j] == orig_vid[k]) - numVids++; - - /* Allocate a new list of VisualIDs for this depth */ - pVids = (VisualID *)__glXMalloc(numVids * sizeof(VisualID)); - - /* Initialize the new list of VisualIDs for this depth */ - for (j = 0; j < pdepth[i].numVids; j++) - for (k = 0; k < numNewVisuals; k++) - if (pdepth[i].vids[j] == orig_vid[k]) - pVids[n++] = pVisualNew[k].vid; - - /* Update this depth's list of VisualIDs */ - __glXFree(pdepth[i].vids); - pdepth[i].vids = pVids; - pdepth[i].numVids = numVids; + if (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); } - /* Update the X server's visuals */ - *nvisualp = numNewVisuals; - *visualp = pVisualNew; + /* fill in configs */ + for (i = 0; i < numConfigs; i++) + { + int values[num_attrs]; - /* Free the old list of the X server's visuals */ - __glXFree(pVisual); + c = &(result[i]); + c->base.next = NULL; + c->pixelFormatIndex = i+1; - /* Clean up temporary allocations */ - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); + if (!wglGetPixelFormatAttribivARBWrapper(hdc, i+1, 0, num_attrs, attrs, values)) + { + ErrorF("wglGetPixelFormatAttribivARB failed for index %d, error %s\n", i+1, glxWinErrorMessage()); + break; + } - /* Free the private list created by DDX HW driver */ - if (visualPrivates) - xfree(visualPrivates); - visualPrivates = NULL; +#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d)) - return TRUE; -} + 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; -static void fixup_visuals(int screen) -{ - ScreenPtr pScreen = screenInfo.screens[screen]; - glWinScreenRec *pScr = &glWinScreens[screen]; - __GLcontextModes *modes; - int j; - - GLWIN_DEBUG_MSG("fixup_visuals\n"); - - for (modes = pScr->modes; modes != NULL; modes = modes->next ) { - const int vis_class = _gl_convert_to_x_visual_type( modes->visualType ); - const int nplanes = (modes->rgbBits - modes->alphaBits); - VisualPtr pVis = pScreen->visuals; - - /* Find a visual that matches the GLX visual's class and size */ - for (j = 0; j < pScreen->numVisuals; j++) { - if (pVis[j].class == vis_class && - pVis[j].nplanes == nplanes) { - - /* Fixup the masks */ - modes->redMask = pVis[j].redMask; - modes->greenMask = pVis[j].greenMask; - modes->blueMask = pVis[j].blueMask; - - /* Recalc the sizes */ - modes->redBits = count_bits(modes->redMask); - modes->greenBits = count_bits(modes->greenMask); - modes->blueBits = count_bits(modes->blueMask); - } - } - } -} + 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); -static void init_screen_visuals(int screen) -{ - ScreenPtr pScreen = screenInfo.screens[screen]; - __GLcontextModes *modes; - int *used; - int i, j; - - GLWIN_DEBUG_MSG("init_screen_visuals\n"); - - used = (int *)__glXMalloc(pScreen->numVisuals * sizeof(int)); - __glXMemset(used, 0, pScreen->numVisuals * sizeof(int)); - - i = 0; - for ( modes = glWinScreens[screen].modes - ; modes != NULL - ; modes = modes->next) { - const int vis_class = _gl_convert_to_x_visual_type( modes->visualType ); - const int nplanes = (modes->rgbBits - modes->alphaBits); - const VisualPtr pVis = pScreen->visuals; - - for (j = 0; j < pScreen->numVisuals; j++) { - - if (pVis[j].class == vis_class && - pVis[j].nplanes == nplanes && - pVis[j].redMask == modes->redMask && - pVis[j].greenMask == modes->greenMask && - pVis[j].blueMask == modes->blueMask && - !used[j]) { - -#if 0 - /* Create the XMesa visual */ - pXMesaVisual[i] = - XMesaCreateVisual(pScreen, - pVis, - modes->rgbMode, - (modes->alphaBits > 0), - modes->doubleBufferMode, - modes->stereoMode, - GL_TRUE, /* ximage_flag */ - modes->depthBits, - modes->stencilBits, - modes->accumRedBits, - modes->accumGreenBits, - modes->accumBlueBits, - modes->accumAlphaBits, - modes->samples, - modes->level, - modes->visualRating); -#endif - - /* Set the VisualID */ - modes->visualID = pVis[j].vid; + 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; - /* Mark this visual used */ - used[j] = 1; - break; + if (!getenv("GLWIN_ENABLE_COLORINDEX_FBCONFIGS")) + { + GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_COLORINDEX_ARB, skipping", i+1); + continue; } - } - if ( j == pScreen->numVisuals ) { - ErrorF("No matching visual for __GLcontextMode with " - "visual class = %d (%d), nplanes = %u\n", - vis_class, - modes->visualType, - (modes->rgbBits - modes->alphaBits) ); - } - else if ( modes->visualID == -1 ) { - FatalError( "Matching visual found, but visualID still -1!\n" ); - } + break; - i++; - - } + case WGL_TYPE_RGBA_FLOAT_ARB: + GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i+1); + continue; - __glXFree(used); + case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: + GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping", i+1); + continue; - /* glWinScreens[screen].xm_vis = pXMesaVisual; */ -} + 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; -static Bool glWinScreenProbe(int screen) -{ - ScreenPtr pScreen; - glWinScreenRec *screenPriv; + default: + ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n", ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)); + continue; + } - GLWIN_DEBUG_MSG("glWinScreenProbe\n"); + 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); - /* - * Set up the current screen's visuals. - */ - __glDDXScreenInfo.modes = glWinScreens[screen].modes; - __glDDXScreenInfo.pVisualPriv = glWinScreens[screen].priv; - __glDDXScreenInfo.numVisuals = - __glDDXScreenInfo.numUsableVisuals = glWinScreens[screen].num_vis; + 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); - /* - * Set the current screen's createContext routine. This could be - * wrapped by a DDX GLX context creation routine. - */ - __glDDXScreenInfo.createContext = glWinCreateContext; + { + int layers = ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0); - /* - * The ordering of the rgb compenents might have been changed by the - * driver after mi initialized them. - */ - fixup_visuals(screen); + 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; - /* - * Find the GLX visuals that are supported by this screen and create - * XMesa's visuals. - */ - init_screen_visuals(screen); - - /* Wrap RealizeWindow and UnrealizeWindow on this screen */ - pScreen = screenInfo.screens[screen]; - screenPriv = &glWinScreens[screen]; - screenPriv->RealizeWindow = pScreen->RealizeWindow; - pScreen->RealizeWindow = glWinRealizeWindow; - screenPriv->UnrealizeWindow = pScreen->UnrealizeWindow; - pScreen->UnrealizeWindow = glWinUnrealizeWindow; - screenPriv->CopyWindow = pScreen->CopyWindow; - pScreen->CopyWindow = glWinCopyWindow; - - return TRUE; -} + c->base.pixmapMode = 0; // ??? + c->base.visualID = -1; // will be set by __glXScreenInit() -static GLboolean glWinSwapBuffers(__GLXdrawablePrivate *glxPriv) -{ - /* swap buffers on only *one* of the contexts - * (e.g. the last one for drawing) - */ - __GLcontext *gc = (__GLcontext *)glxPriv->drawGlxc->gc; - HDC dc; - BOOL ret; + /* 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)); - GLWIN_TRACE_MSG("glWinSwapBuffers (ctx %p)\n", (gc!=NULL?gc->ctx:NULL)); + case WGL_NO_ACCELERATION_ARB: + c->base.visualRating = GLX_SLOW_VISUAL_EXT; + break; - if (gc != NULL && gc->ctx != NULL) - { - dc = glWinMakeDC(gc); - if (dc == NULL) - return GL_FALSE; - - ret = SwapBuffers(dc); - if (!ret) - ErrorF("SwapBuffers failed: %s\n", glWinErrorMessage()); - - ReleaseDC(gc->winInfo.hwnd, dc); - if (!ret) - return GL_FALSE; - } + case WGL_GENERIC_ACCELERATION_ARB: + case WGL_FULL_ACCELERATION_ARB: + c->base.visualRating = GLX_NONE_EXT; + break; + } - return GL_TRUE; -} + /* 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; + } -static void glWinDestroyDrawablePrivate(__GLdrawablePrivate *glPriv) -{ - GLWIN_DEBUG_MSG("glWinDestroyDrawablePrivate\n"); + /* 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; + } - /* It doesn't work to call DRIDestroySurface here, the drawable's - already gone.. But dri.c notices the window destruction and - frees the surface itself. */ + /* 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)); - free(glPriv->private); - glPriv->private = NULL; -} + /* + 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; + } -static void glWinCreateBuffer(__GLXdrawablePrivate *glxPriv) -{ - GLWinDrawableRec *winPriv = malloc(sizeof(GLWinDrawableRec)); - __GLdrawablePrivate *glPriv = &glxPriv->glPriv; + c->base.xRenderable = GL_TRUE; + c->base.fbconfigID = -1; // will be set by __glXScreenInit() - /*winPriv->sid = 0; */ - winPriv->pDraw = NULL; + /* SGIX_pbuffer / GLX 1.3 */ + if (screen->has_WGL_ARB_pbuffer) + { + c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1); + c->base.maxPbufferHeight = ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1); + c->base.maxPbufferPixels = ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1); + } + else + { + c->base.maxPbufferWidth = -1; + c->base.maxPbufferHeight = -1; + c->base.maxPbufferPixels = -1; + } + c->base.optimalPbufferWidth = 0; // there is no optimal value + c->base.optimalPbufferHeight = 0; - GLWIN_DEBUG_MSG("glWinCreateBuffer\n"); + /* SGIX_visual_select_group */ + // arrange for visuals with the best acceleration to be preferred in selection + switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) + { + case WGL_FULL_ACCELERATION_ARB: + c->base.visualSelectGroup = 2; + break; + + case WGL_GENERIC_ACCELERATION_ARB: + c->base.visualSelectGroup = 1; + break; + + default: + case WGL_NO_ACCELERATION_ARB: + c->base.visualSelectGroup = 0; + break; + } - /* replace swapBuffers (original is never called) */ - glxPriv->swapBuffers = glWinSwapBuffers; + /* OML_swap_method */ + switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0)) + { + case WGL_SWAP_EXCHANGE_ARB: + c->base.swapMethod = GLX_SWAP_EXCHANGE_OML; + break; - /* stash private data */ - glPriv->private = winPriv; - glPriv->freePrivate = glWinDestroyDrawablePrivate; -} + case WGL_SWAP_COPY_ARB: + c->base.swapMethod = GLX_SWAP_COPY_OML; + break; -static void glWinResetExtension(void) -{ - GLWIN_DEBUG_MSG("glWinResetExtension\n"); -} + default: + ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n", ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0)); -/* based on code in apples/indirect.c which is based on i830_dri.c */ -static void -glWinInitVisualConfigs(void) -{ - int lclNumConfigs = 0; - __GLXvisualConfig *lclVisualConfigs = NULL; - void **lclVisualPrivates = NULL; - - int depth, aux, buffers, stencil, accum; - int i = 0; - - GLWIN_DEBUG_MSG("glWinInitVisualConfigs "); - - /* count num configs: - 2 Z buffer (0, 24 bit) - 2 AUX buffer (0, 2) - 2 buffers (single, double) - 2 stencil (0, 8 bit) - 2 accum (0, 64 bit) - = 32 configs */ - - lclNumConfigs = 2 * 2 * 2 * 2 * 2; /* 32 */ - - /* alloc */ - lclVisualConfigs = xcalloc(sizeof(__GLXvisualConfig), lclNumConfigs); - lclVisualPrivates = xcalloc(sizeof(void *), lclNumConfigs); - - /* fill in configs */ - if (NULL != lclVisualConfigs) { - i = 0; /* current buffer */ - for (depth = 0; depth < 2; depth++) { - for (aux = 0; aux < 2; aux++) { - for (buffers = 0; buffers < 2; buffers++) { - for (stencil = 0; stencil < 2; stencil++) { - for (accum = 0; accum < 2; accum++) { - lclVisualConfigs[i].vid = -1; - lclVisualConfigs[i].class = -1; - lclVisualConfigs[i].rgba = TRUE; - lclVisualConfigs[i].redSize = -1; - lclVisualConfigs[i].greenSize = -1; - lclVisualConfigs[i].blueSize = -1; - lclVisualConfigs[i].redMask = -1; - lclVisualConfigs[i].greenMask = -1; - lclVisualConfigs[i].blueMask = -1; - lclVisualConfigs[i].alphaMask = 0; - if (accum) { - lclVisualConfigs[i].accumRedSize = 16; - lclVisualConfigs[i].accumGreenSize = 16; - lclVisualConfigs[i].accumBlueSize = 16; - lclVisualConfigs[i].accumAlphaSize = 16; - } - else { - lclVisualConfigs[i].accumRedSize = 0; - lclVisualConfigs[i].accumGreenSize = 0; - lclVisualConfigs[i].accumBlueSize = 0; - lclVisualConfigs[i].accumAlphaSize = 0; - } - lclVisualConfigs[i].doubleBuffer = buffers ? TRUE : FALSE; - lclVisualConfigs[i].stereo = FALSE; - lclVisualConfigs[i].bufferSize = -1; - - lclVisualConfigs[i].depthSize = depth? 24 : 0; - lclVisualConfigs[i].stencilSize = stencil ? 8 : 0; - lclVisualConfigs[i].auxBuffers = aux ? 2 : 0; - lclVisualConfigs[i].level = 0; - lclVisualConfigs[i].visualRating = GLX_NONE_EXT; - lclVisualConfigs[i].transparentPixel = 0; - lclVisualConfigs[i].transparentRed = 0; - lclVisualConfigs[i].transparentGreen = 0; - lclVisualConfigs[i].transparentBlue = 0; - lclVisualConfigs[i].transparentAlpha = 0; - lclVisualConfigs[i].transparentIndex = 0; - i++; - } - } - } - } + case WGL_SWAP_UNDEFINED_ARB: + c->base.swapMethod = GLX_SWAP_UNDEFINED_OML; } - } - if (i != lclNumConfigs) - GLWIN_DEBUG_MSG("glWinInitVisualConfigs failed to alloc visual configs"); - GlxSetVisualConfigs(lclNumConfigs, lclVisualConfigs, lclVisualPrivates); -} - -/* Copied from Mesa */ -static void glWinSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, - void **privates) -{ - GLWIN_DEBUG_MSG("glWinSetVisualConfigs\n"); + /* EXT_import_context */ + c->base.screen = screen->base.pScreen->myNum; - numConfigs = nconfigs; - visualConfigs = configs; - visualPrivates = privates; -} + /* EXT_texture_from_pixmap */ + /* + Mesa's DRI configs always have bindToTextureRgb/Rgba TRUE (see driCreateConfigs(), so setting + bindToTextureRgb/bindToTextureRgba to FALSE means that swrast can't find any fbConfigs to use, + so setting these to 0, even if we know bindToTexture isn't available, isn't a good idea... + */ + if (screen->has_WGL_ARB_render_texture) + { + c->base.bindToTextureRgb = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGB_ARB, -1); + c->base.bindToTextureRgba = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGBA_ARB, -1); + } + else + { + c->base.bindToTextureRgb = -1; + c->base.bindToTextureRgba = -1; + } + c->base.bindToMipmapTexture = -1; + c->base.bindToTextureTargets = GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | GLX_TEXTURE_RECTANGLE_BIT_EXT; + c->base.yInverted = -1; -/* Copied from Mesa */ -static Bool glWinInitVisuals(VisualPtr *visualp, DepthPtr *depthp, - int *nvisualp, int *ndepthp, - int *rootDepthp, VisualID *defaultVisp, - unsigned long sizes, int bitsPerRGB) -{ - glWinInitDebugSettings(); + n++; - GLWIN_DEBUG_MSG("glWinInitVisuals\n"); + // update previous config to point to this config + if (prev) + prev->base.next = &(c->base); - if (0 == numConfigs) /* if no configs */ - glWinInitVisualConfigs(); /* ensure the visula configs are setup */ + prev = c; + } - /* - * Setup the visuals supported by this particular screen. - */ - return init_visuals(nvisualp, visualp, defaultVisp, - *ndepthp, *depthp, *rootDepthp); + screen->base.numFBConfigs = n; + screen->base.fbconfigs = &(result->base); } diff --git a/hw/xwin/glx/wgl_ext_api.c b/hw/xwin/glx/wgl_ext_api.c new file mode 100644 index 000000000..4b8359fb1 --- /dev/null +++ b/hw/xwin/glx/wgl_ext_api.c @@ -0,0 +1,75 @@ +/* + * File: wgl_ext_api.c + * Purpose: Wrapper functions for Win32 OpenGL wgl extension functions + * + * Authors: Jon TURNEY + * + * Copyright (c) Jon TURNEY 2009 + * + * + * 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. + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include <X11/Xwindows.h> +#include <GL/gl.h> +#include <GL/glext.h> +#include <glx/glxserver.h> +#include <glx/glxext.h> +#include "wglext.h" +#include <wgl_ext_api.h> +#include "glwindows.h" + +#define RESOLVE_DECL(type) \ + static type type##proc = NULL; + +#define PRERESOLVE(type, symbol) \ + type##proc = (type)wglGetProcAddress(symbol); \ + if (type##proc == NULL) \ + ErrorF("wglwrap: Can't resolve \"%s\"\n", symbol); \ + else \ + ErrorF("wglwrap: Resolved \"%s\"\n", symbol); + +#define RESOLVE_RET(type, symbol, retval) \ + if (type##proc == NULL) { \ + __glXErrorCallBack(0); \ + return retval; \ + } + +#define RESOLVE(procname, symbol) RESOLVE_RET(procname, symbol,) + +#define RESOLVED_PROC(type) type##proc + +/* + * Include generated cdecl wrappers for stdcall WGL functions + * + * There are extensions to the wgl*() API as well; again we call + * these functions by using wglGetProcAddress() to get a pointer + * to the function, and wrapping it for cdecl/stdcall conversion + * + * We arrange to resolve the functions up front, as they need a + * context to work, as we like to use them to be able to select + * a context. Again, this assumption fails badly on multimontor + * systems... + */ + +#include "generated_wgl_wrappers.c" diff --git a/hw/xwin/glx/wgl_ext_api.h b/hw/xwin/glx/wgl_ext_api.h new file mode 100644 index 000000000..e4462ac5c --- /dev/null +++ b/hw/xwin/glx/wgl_ext_api.h @@ -0,0 +1,87 @@ +/* + * File: wgl_ext_api.h + * Purpose: Wrapper functions for Win32 OpenGL wgl extension functions + * + * Authors: Jon TURNEY + * + * Copyright (c) Jon TURNEY 2009 + * + * + * 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. + */ + +#ifndef wgl_ext_api_h +#define wgl_ext_api_h + +#include "wglext.h" + +void wglResolveExtensionProcs(void); + +/* + Prototypes for wrapper functions we actually use + XXX: should be automatically generated as well +*/ + +const char *wglGetExtensionsStringARBWrapper(HDC hdc); +BOOL wglMakeContextCurrentARBWrapper(HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +HDC wglGetCurrentReadDCARBWrapper(VOID); + +BOOL wglGetPixelFormatAttribivARBWrapper(HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nAttributes, + const int *piAttributes, + int *piValues); + +BOOL wglGetPixelFormatAttribfvARBWrapper(HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nAttributes, + const int *piAttributes, + FLOAT *pfValues); + +BOOL wglChoosePixelFormatARBWrapper(HDC hdc, + const int *piAttribIList, + const FLOAT *pfAttribFList, + UINT nMaxFormats, + int *piFormats, + UINT *nNumFormats); + +HPBUFFERARB wglCreatePbufferARBWrapper(HDC hDC, + int iPixelFormat, + int iWidth, + int iHeight, + const int *piAttribList); + +HDC wglGetPbufferDCARBWrapper(HPBUFFERARB hPbuffer); + +int wglReleasePbufferDCARBWrapper(HPBUFFERARB hPbuffer, + HDC hDC); + +BOOL wglDestroyPbufferARBWrapper(HPBUFFERARB hPbuffer); + +BOOL wglQueryPbufferARBWrapper(HPBUFFERARB hPbuffer, + int iAttribute, + int *piValue); + +BOOL wglSwapIntervalEXTWrapper(int interval); + +int wglGetSwapIntervalEXTWrapper(void); + +#endif /* wgl_ext_api_h */ diff --git a/hw/xwin/winpriv.c b/hw/xwin/glx/winpriv.c index 29221cf2b..a35392b26 100644 --- a/hw/xwin/winpriv.c +++ b/hw/xwin/glx/winpriv.c @@ -16,43 +16,27 @@ winCreateWindowsWindow (WindowPtr pWin); /** * Return size and handles of a window. * If pWin is NULL, then the information for the root window is requested. - */ -extern 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) + if (pWin != NULL) { - /* Initialize the size information */ - RECT rect = { - pWin->drawable.x, - pWin->drawable.y, - pWin->drawable.x + pWin->drawable.width, - pWin->drawable.y + pWin->drawable.height - }, rect_extends; /* Get the window and screen privates */ ScreenPtr pScreen = pWin->drawable.pScreen; winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen); winScreenInfoPtr pScreenInfo = NULL; + HWND hwnd = NULL; - rect_extends = rect; - OffsetRect(&rect_extends, -pWin->drawable.x, -pWin->drawable.y); - - if (pWinScreen == NULL) + if (pWinScreen == NULL) { ErrorF("winGetWindowInfo: screen has no privates\n"); - return; + return NULL; } - - pWinInfo->hwnd = pWinScreen->hwndScreen; - pWinInfo->hrgn = NULL; - pWinInfo->rect = rect; - + + hwnd = pWinScreen->hwndScreen; pScreenInfo = pWinScreen->pScreenInfo; #ifdef XWIN_MULTIWINDOW @@ -64,28 +48,22 @@ extern void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo) if (pWinPriv == NULL) { ErrorF("winGetWindowInfo: window has no privates\n"); - return; + return hwnd; } if (pWinPriv->hWnd == NULL) { - winCreateWindowsWindow(pWin); - } - if (pWinPriv->hWnd != NULL) { - - /* copy size and window handle */ - pWinInfo->rect = rect_extends; - pWinInfo->hwnd = pWinPriv->hWnd; - - /* Copy window region */ - if (pWinInfo->hrgn) - DeleteObject(pWinInfo->hrgn); - pWinInfo->hrgn = CreateRectRgn(0,0,0,0); - CombineRgn(pWinInfo->hrgn, pWinPriv->hRgn, pWinPriv->hRgn, - RGN_COPY); + winCreateWindowsWindow(pWin); + ErrorF("winGetWindowInfo: forcing window to exist...\n"); } - - return; + + if (pWinPriv->hWnd != NULL) + { + /* copy window handle */ + hwnd = pWinPriv->hWnd; + } + + return hwnd; } #endif #ifdef XWIN_MULTIWINDOWEXTWM @@ -97,38 +75,52 @@ extern void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo) if (pRLWinPriv == NULL) { ErrorF("winGetWindowInfo: window has no privates\n"); - return; + return hwnd; } - + if (pRLWinPriv->hWnd != NULL) { - /* copy size and window handle */ - pWinInfo->rect = rect_extends; - pWinInfo->hwnd = pRLWinPriv->hWnd; + /* copy window handle */ + hwnd = pRLWinPriv->hWnd; } - return; + return hwnd; } #endif - } - else + } + else { - RECT rect = {0, 0, 0, 0}; ScreenPtr pScreen = g_ScreenInfo[0].pScreen; winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen); - pWinInfo->hwnd = NULL; - pWinInfo->hrgn = NULL; - pWinInfo->rect = rect; - 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 +winCheckScreenAiglxIsSupported(ScreenPtr pScreen) +{ + winPrivScreenPtr pWinScreen = winGetScreenPriv(pScreen); + winScreenInfoPtr pScreenInfo = pWinScreen->pScreenInfo; + +#ifdef XWIN_MULTIWINDOW + if (pScreenInfo->fMultiWindow) + return TRUE; +#endif + +#ifdef XWIN_MULTIWINDOWEXTWM + if (pScreenInfo->fMWExtWM) + return TRUE; +#endif + + return FALSE; } diff --git a/hw/xwin/glx/winpriv.h b/hw/xwin/glx/winpriv.h new file mode 100644 index 000000000..dce1edf48 --- /dev/null +++ b/hw/xwin/glx/winpriv.h @@ -0,0 +1,11 @@ +/* + * 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/hw/xwin/winglobals.c b/hw/xwin/winglobals.c index d74011cc7..2ef8a36ee 100644 --- a/hw/xwin/winglobals.c +++ b/hw/xwin/winglobals.c @@ -83,7 +83,7 @@ HWND g_hwndKeyboardFocus = NULL; Bool g_fNoHelpMessageBox = FALSE; Bool g_fSoftwareCursor = FALSE; Bool g_fSilentDupError = FALSE; - +Bool g_fNativeGl = FALSE; /* * Global variables for dynamically loaded libraries and diff --git a/hw/xwin/winmultiwindowwindow.c b/hw/xwin/winmultiwindowwindow.c index 87ffc6d6b..95d9d71fc 100644 --- a/hw/xwin/winmultiwindowwindow.c +++ b/hw/xwin/winmultiwindowwindow.c @@ -47,6 +47,7 @@ extern HICON g_hIconX; extern HICON g_hSmallIconX; extern HWND g_hDlgDepthChange; +extern Bool g_fNativeGl; /* * Prototypes for local functions @@ -74,7 +75,7 @@ void winInitMultiWindowClass(void) { /* Setup our window class */ wcx.cbSize=sizeof(WNDCLASSEX); - wcx.style = CS_HREDRAW | CS_VREDRAW; + wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0); wcx.lpfnWndProc = winTopLevelWindowProc; wcx.cbClsExtra = 0; wcx.cbWndExtra = 0; diff --git a/hw/xwin/winpriv.h b/hw/xwin/winpriv.h deleted file mode 100644 index d4505c83e..000000000 --- a/hw/xwin/winpriv.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Export window information for the Windows-OpenGL GLX implementation. - * - * Authors: Alexander Gottwald - */ -#include <windows.h> - -typedef struct -{ - HWND hwnd; - HRGN hrgn; - RECT rect; -} winWindowInfoRec, *winWindowInfoPtr; - -extern void winGetWindowInfo(WindowPtr pWin, winWindowInfoPtr pWinInfo); diff --git a/hw/xwin/winprocarg.c b/hw/xwin/winprocarg.c index ad4b7e913..66a0503f2 100755 --- a/hw/xwin/winprocarg.c +++ b/hw/xwin/winprocarg.c @@ -62,6 +62,7 @@ extern Bool g_fKeyboardHookLL; extern Bool g_fNoHelpMessageBox; extern Bool g_fSoftwareCursor; extern Bool g_fSilentDupError; +extern Bool g_fNativeGl; /* globals required by callback function for monitor information */ struct GetMonitorInfoData { @@ -1144,6 +1145,19 @@ ddxProcessArgument (int argc, char *argv[], int i) g_fSilentDupError = TRUE; return 1; } + + if (IS_OPTION("-wgl")) + { + g_fNativeGl = TRUE; + return 1; + } + + if (IS_OPTION("-nowgl")) + { + g_fNativeGl = FALSE; + return 1; + } + return 0; } diff --git a/mi/Makefile.am b/mi/Makefile.am index 9714a21ca..f22dde9a2 100644 --- a/mi/Makefile.am +++ b/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/mi/mibank.c b/mi/mibank.c deleted file mode 100644 index 9e4d63162..000000000 --- a/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/mi/mibank.h b/mi/mibank.h deleted file mode 100644 index 0c10540a7..000000000 --- a/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__ */ diff --git a/mi/midispcur.c b/mi/midispcur.c index 3fb7e02b5..904163091 100644 --- a/mi/midispcur.c +++ b/mi/midispcur.c @@ -59,9 +59,9 @@ static DevPrivateKey miDCScreenKey = &miDCScreenKeyIndex; static Bool miDCCloseScreen(int index, ScreenPtr pScreen); -/* per device private data */ -static int miDCSpriteKeyIndex; -static DevPrivateKey miDCSpriteKey = &miDCSpriteKeyIndex; +/* per device per-screen private data */ +static int miDCSpriteKeyIndex[MAXSCREENS]; +static DevPrivateKey miDCSpriteKey = miDCSpriteKeyIndex; typedef struct { GCPtr pSourceGC, pMaskGC; @@ -75,10 +75,10 @@ typedef struct { #endif } miDCBufferRec, *miDCBufferPtr; -#define MIDCBUFFER(dev) \ +#define MIDCBUFFER(dev, screen) \ ((DevHasCursor(dev)) ? \ - (miDCBufferPtr)dixLookupPrivate(&dev->devPrivates, miDCSpriteKey) : \ - (miDCBufferPtr)dixLookupPrivate(&dev->u.master->devPrivates, miDCSpriteKey)) + (miDCBufferPtr)dixLookupPrivate(&dev->devPrivates, miDCSpriteKey + (screen)->myNum) : \ + (miDCBufferPtr)dixLookupPrivate(&dev->u.master->devPrivates, miDCSpriteKey + (screen)->myNum)) /* * The core pointer buffer will point to the index of the virtual core pointer @@ -158,10 +158,6 @@ miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) return TRUE; } -#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0) -#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE) -#define tossPict(pict) (pict ? FreePicture (pict, 0) : 0) - static Bool miDCCloseScreen (int index, ScreenPtr pScreen) { @@ -183,7 +179,6 @@ miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) } #ifdef ARGB_CURSOR -#define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win)) static VisualPtr miDCGetWindowVisual (WindowPtr pWin) @@ -415,12 +410,8 @@ miDCPutBits ( (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); } -#define EnsureGC(gc,win) (gc || miDCMakeGC(&gc, win)) - static GCPtr -miDCMakeGC( - GCPtr *ppGC, - WindowPtr pWin) +miDCMakeGC(WindowPtr pWin) { GCPtr pGC; int status; @@ -431,7 +422,6 @@ miDCMakeGC( pGC = CreateGC((DrawablePtr)pWin, GCSubwindowMode|GCGraphicsExposures, gcvals, &status, (XID)0, serverClient); - *ppGC = pGC; return pGC; } @@ -456,22 +446,11 @@ miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); pWin = WindowTable[pScreen->myNum]; - pBuffer = MIDCBUFFER(pDev); + pBuffer = MIDCBUFFER(pDev, pScreen); #ifdef ARGB_CURSOR if (pPriv->pPicture) { - /* see comment in miDCPutUpCursor */ - if (pBuffer->pRootPicture && - pBuffer->pRootPicture->pDrawable && - pBuffer->pRootPicture->pDrawable->pScreen != pScreen) - { - tossPict(pBuffer->pRootPicture); - pBuffer->pRootPicture = NULL; - } - - if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin)) - return FALSE; CompositePicture (PictOpOver, pPriv->pPicture, NULL, @@ -484,33 +463,6 @@ miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, else #endif { - /** - * XXX: Before MPX, the sourceGC and maskGC were attached to the - * screen, and would switch as the screen switches. With mpx we have - * the GC's attached to the device now, so each time we switch screen - * we need to make sure the GC's are allocated on the new screen. - * This is ... not optimal. (whot) - */ - if (pBuffer->pSourceGC && pScreen != pBuffer->pSourceGC->pScreen) - { - tossGC(pBuffer->pSourceGC); - pBuffer->pSourceGC = NULL; - } - - if (pBuffer->pMaskGC && pScreen != pBuffer->pMaskGC->pScreen) - { - tossGC(pBuffer->pMaskGC); - pBuffer->pMaskGC = NULL; - } - - if (!EnsureGC(pBuffer->pSourceGC, pWin)) - return FALSE; - if (!EnsureGC(pBuffer->pMaskGC, pWin)) - { - FreeGC (pBuffer->pSourceGC, (GContext) 0); - pBuffer->pSourceGC = 0; - return FALSE; - } miDCPutBits ((DrawablePtr)pWin, pPriv, pBuffer->pSourceGC, pBuffer->pMaskGC, x, y, pCursor->bits->width, pCursor->bits->height, @@ -531,7 +483,7 @@ miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); - pBuffer = MIDCBUFFER(pDev); + pBuffer = MIDCBUFFER(pDev, pScreen); pSave = pBuffer->pSave; pWin = WindowTable[pScreen->myNum]; @@ -544,14 +496,7 @@ miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, if (!pSave) return FALSE; } - /* see comment in miDCPutUpCursor */ - if (pBuffer->pSaveGC && pBuffer->pSaveGC->pScreen != pScreen) - { - tossGC(pBuffer->pSaveGC); - pBuffer->pSaveGC = NULL; - } - if (!EnsureGC(pBuffer->pSaveGC, pWin)) - return FALSE; + pGC = pBuffer->pSaveGC; if (pSave->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pSave, pGC); @@ -572,20 +517,13 @@ miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); - pBuffer = MIDCBUFFER(pDev); + pBuffer = MIDCBUFFER(pDev, pScreen); pSave = pBuffer->pSave; pWin = WindowTable[pScreen->myNum]; if (!pSave) return FALSE; - /* see comment in miDCPutUpCursor */ - if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen) - { - tossGC(pBuffer->pRestoreGC); - pBuffer->pRestoreGC = NULL; - } - if (!EnsureGC(pBuffer->pRestoreGC, pWin)) - return FALSE; + pGC = pBuffer->pRestoreGC; if (pWin->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pWin, pGC); @@ -607,7 +545,7 @@ miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen, pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); - pBuffer = MIDCBUFFER(pDev); + pBuffer = MIDCBUFFER(pDev, pScreen); pSave = pBuffer->pSave; pWin = WindowTable[pScreen->myNum]; @@ -616,14 +554,7 @@ miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen, */ if (!pSave) return FALSE; - /* see comment in miDCPutUpCursor */ - if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen) - { - tossGC(pBuffer->pRestoreGC); - pBuffer->pRestoreGC = NULL; - } - if (!EnsureGC(pBuffer->pRestoreGC, pWin)) - return FALSE; + pGC = pBuffer->pRestoreGC; if (pWin->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pWin, pGC); @@ -662,14 +593,7 @@ miDCChangeSave (DeviceIntPtr pDev, ScreenPtr pScreen, (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, 0, sourcey, -dx, copyh, x + dx, desty); } - /* see comment in miDCPutUpCursor */ - if (pBuffer->pSaveGC && pBuffer->pSaveGC->pScreen != pScreen) - { - tossGC(pBuffer->pSaveGC); - pBuffer->pSaveGC = NULL; - } - if (!EnsureGC(pBuffer->pSaveGC, pWin)) - return FALSE; + pGC = pBuffer->pSaveGC; if (pSave->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pSave, pGC); @@ -766,7 +690,7 @@ miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); pWin = WindowTable[pScreen->myNum]; - pBuffer = MIDCBUFFER(pDev); + pBuffer = MIDCBUFFER(pDev, pScreen); pTemp = pBuffer->pTemp; if (!pTemp || @@ -809,17 +733,9 @@ miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, #ifdef ARGB_CURSOR if (pPriv->pPicture) { - /* see comment in miDCPutUpCursor */ - if (pBuffer->pTempPicture && - pBuffer->pTempPicture->pDrawable && - pBuffer->pTempPicture->pDrawable->pScreen != pScreen) - { - tossPict(pBuffer->pTempPicture); - pBuffer->pTempPicture = NULL; - } + if (!pBuffer->pTempPicture) + miDCMakePicture(&pBuffer->pTempPicture, &pTemp->drawable, pWin); - if (!EnsurePicture(pBuffer->pTempPicture, &pTemp->drawable, pWin)) - return FALSE; CompositePicture (PictOpOver, pPriv->pPicture, NULL, @@ -832,38 +748,12 @@ miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, else #endif { - if (!pBuffer->pPixSourceGC) - { - pBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pTemp, - GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pBuffer->pPixSourceGC) - return FALSE; - } - if (!pBuffer->pPixMaskGC) - { - pBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pTemp, - GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pBuffer->pPixMaskGC) - return FALSE; - } miDCPutBits ((DrawablePtr)pTemp, pPriv, pBuffer->pPixSourceGC, pBuffer->pPixMaskGC, dx, dy, pCursor->bits->width, pCursor->bits->height, source, mask); } - /* see comment in miDCPutUpCursor */ - if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen) - { - tossGC(pBuffer->pRestoreGC); - pBuffer->pRestoreGC = NULL; - } - /* - * copy the temporary pixmap onto the screen - */ - - if (!EnsureGC(pBuffer->pRestoreGC, pWin)) - return FALSE; pGC = pBuffer->pRestoreGC; if (pWin->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pWin, pGC); @@ -877,51 +767,108 @@ miDCMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, static Bool miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) { - miDCBufferPtr pBuffer; - - pBuffer = xalloc(sizeof(miDCBufferRec)); - dixSetPrivate(&pDev->devPrivates, miDCSpriteKey, pBuffer); - - pBuffer->pSourceGC = - pBuffer->pMaskGC = - pBuffer->pSaveGC = - pBuffer->pRestoreGC = - pBuffer->pMoveGC = - pBuffer->pPixSourceGC = - pBuffer->pPixMaskGC = NULL; + miDCBufferPtr pBuffer; + WindowPtr pWin; + XID gcval = FALSE; + int status; + int i; + + if (!DevHasCursor(pDev)) + return TRUE; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + + pBuffer = xalloc(sizeof(miDCBufferRec)); + if (!pBuffer) + goto failure; + + dixSetPrivate(&pDev->devPrivates, miDCSpriteKey + pScreen->myNum, pBuffer); + pWin = WindowTable[pScreen->myNum]; + + pBuffer->pSourceGC = miDCMakeGC(pWin); + if (!pBuffer->pSourceGC) + goto failure; + + pBuffer->pMaskGC = miDCMakeGC(pWin); + if (!pBuffer->pMaskGC) + goto failure; + + pBuffer->pSaveGC = miDCMakeGC(pWin); + if (!pBuffer->pSaveGC) + goto failure; + + pBuffer->pRestoreGC = miDCMakeGC(pWin); + if (!pBuffer->pRestoreGC) + goto failure; + + pBuffer->pMoveGC = CreateGC ((DrawablePtr)pWin, + GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); + if (!pBuffer->pMoveGC) + goto failure; + + pBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pWin, + GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); + if (!pBuffer->pPixSourceGC) + goto failure; + + pBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pWin, + GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); + if (!pBuffer->pPixMaskGC) + goto failure; + #ifdef ARGB_CURSOR - pBuffer->pRootPicture = NULL; - pBuffer->pTempPicture = NULL; + miDCMakePicture(&pBuffer->pRootPicture, &pWin->drawable, pWin); + if (!pBuffer->pRootPicture) + goto failure; + + pBuffer->pTempPicture = NULL; #endif - pBuffer->pSave = pBuffer->pTemp = NULL; + + // these get (re)allocated lazily depending on the cursor size + pBuffer->pSave = pBuffer->pTemp = NULL; + } return TRUE; + +failure: + + miDCDeviceCleanup(pDev, pScreen); + + return FALSE; } static void miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) { miDCBufferPtr pBuffer; + int i; if (DevHasCursor(pDev)) { - pBuffer = MIDCBUFFER(pDev); - tossGC (pBuffer->pSourceGC); - tossGC (pBuffer->pMaskGC); - tossGC (pBuffer->pSaveGC); - tossGC (pBuffer->pRestoreGC); - tossGC (pBuffer->pMoveGC); - tossGC (pBuffer->pPixSourceGC); - tossGC (pBuffer->pPixMaskGC); - tossPix (pBuffer->pSave); - tossPix (pBuffer->pTemp); -#ifdef ARGB_CURSOR -#if 0 /* This has been free()d before */ - tossPict (pScreenPriv->pRootPicture); -#endif - tossPict (pBuffer->pTempPicture); -#endif - xfree(pBuffer); - dixSetPrivate(&pDev->devPrivates, miDCSpriteKey, NULL); + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + + pBuffer = MIDCBUFFER(pDev, pScreen); + + if (pBuffer) + { + if (pBuffer->pSourceGC) FreeGC(pBuffer->pSourceGC, (GContext) 0); + if (pBuffer->pMaskGC) FreeGC(pBuffer->pMaskGC, (GContext) 0); + if (pBuffer->pSaveGC) FreeGC(pBuffer->pSaveGC, (GContext) 0); + if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0); + if (pBuffer->pMoveGC) FreeGC(pBuffer->pMoveGC, (GContext) 0); + if (pBuffer->pPixSourceGC) FreeGC(pBuffer->pPixSourceGC, (GContext) 0); + if (pBuffer->pPixMaskGC) FreeGC(pBuffer->pPixMaskGC, (GContext) 0); + + if (pBuffer->pSave) (*pScreen->DestroyPixmap)(pBuffer->pSave); + if (pBuffer->pTemp) (*pScreen->DestroyPixmap)(pBuffer->pTemp); + + xfree(pBuffer); + dixSetPrivate(&pDev->devPrivates, miDCSpriteKey + pScreen->myNum, NULL); + } + } } } diff --git a/mi/miinitext.c b/mi/miinitext.c index 844863a59..a7441c9a8 100644 --- a/mi/miinitext.c +++ b/mi/miinitext.c @@ -537,8 +537,7 @@ InitExtensions(int argc, char *argv[]) for (i = 0; ExtensionModuleList[i].name != NULL; i++) { ext = &ExtensionModuleList[i]; if (ext->initFunc != NULL && - (ext->disablePtr == NULL || - (ext->disablePtr != NULL && !*ext->disablePtr))) { + (ext->disablePtr == NULL || !*ext->disablePtr)) { (ext->initFunc)(); } } |