diff options
Diffstat (limited to 'GL/glx/glxglcore.c')
-rw-r--r-- | GL/glx/glxglcore.c | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/GL/glx/glxglcore.c b/GL/glx/glxglcore.c new file mode 100644 index 000000000..b50740c3c --- /dev/null +++ b/GL/glx/glxglcore.c @@ -0,0 +1,411 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Brian E. Paul <brian@precisioninsight.com> + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <string.h> + +#include <GL/xmesa.h> +#include <GL/internal/glcore.h> +#include <glxserver.h> +#include <glxscreens.h> +#include <glxdrawable.h> +#include <glxcontext.h> +#include <glxutil.h> + +#include "glcontextmodes.h" +#include "os.h" + +typedef struct __GLXMESAscreen __GLXMESAscreen; +typedef struct __GLXMESAcontext __GLXMESAcontext; +typedef struct __GLXMESAdrawable __GLXMESAdrawable; + +struct __GLXMESAscreen { + __GLXscreen base; + int index; + int num_vis; + XMesaVisual *xm_vis; +}; + +struct __GLXMESAcontext { + __GLXcontext base; + XMesaContext xmesa; +}; + +struct __GLXMESAdrawable { + __GLXdrawable base; + XMesaBuffer xm_buf; +}; + +static XMesaVisual find_mesa_visual(__GLXscreen *screen, VisualID vid); + + +static void +__glXMesaDrawableDestroy(__GLXdrawable *base) +{ + __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base; + + if (glxPriv->xm_buf != NULL) + XMesaDestroyBuffer(glxPriv->xm_buf); + xfree(glxPriv); +} + +static GLboolean +__glXMesaDrawableResize(__GLXdrawable *base) +{ + __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base; + + XMesaResizeBuffers(glxPriv->xm_buf); + + return GL_TRUE; +} + +static GLboolean +__glXMesaDrawableSwapBuffers(__GLXdrawable *base) +{ + __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base; + + /* This is terrifying: XMesaSwapBuffers() ends up calling CopyArea + * to do the buffer swap, but this assumes that the server holds + * the lock and has its context visible. If another screen uses a + * DRI driver, that will have installed the DRI enter/leave server + * functions, which lifts the lock during GLX dispatch. This is + * why we need to re-take the lock and swap in the server context + * before calling XMesaSwapBuffers() here. /me shakes head. */ + + __glXenterServer(); + + XMesaSwapBuffers(glxPriv->xm_buf); + + __glXleaveServer(); + + return GL_TRUE; +} + + +static __GLXdrawable * +__glXMesaScreenCreateDrawable(__GLXscreen *screen, + DrawablePtr pDraw, + XID drawId, + __GLcontextModes *modes) +{ + __GLXMESAdrawable *glxPriv; + XMesaVisual xm_vis; + + glxPriv = xalloc(sizeof *glxPriv); + if (glxPriv == NULL) + return NULL; + + memset(glxPriv, 0, sizeof *glxPriv); + + if (!__glXDrawableInit(&glxPriv->base, screen, pDraw, drawId, modes)) { + xfree(glxPriv); + return NULL; + } + + glxPriv->base.destroy = __glXMesaDrawableDestroy; + glxPriv->base.resize = __glXMesaDrawableResize; + glxPriv->base.swapBuffers = __glXMesaDrawableSwapBuffers; + + xm_vis = find_mesa_visual(screen, modes->visualID); + if (xm_vis == NULL) { + ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n", + modes->visualID); + xfree(glxPriv); + return NULL; + } + + if (glxPriv->base.type == DRAWABLE_WINDOW) { + glxPriv->xm_buf = XMesaCreateWindowBuffer(xm_vis, (WindowPtr)pDraw); + } else { + glxPriv->xm_buf = XMesaCreatePixmapBuffer(xm_vis, (PixmapPtr)pDraw, 0); + } + + return &glxPriv->base; +} + +static void +__glXMesaContextDestroy(__GLXcontext *baseContext) +{ + __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext; + + XMesaDestroyContext(context->xmesa); + __glXContextDestroy(&context->base); + xfree(context); +} + +static int +__glXMesaContextMakeCurrent(__GLXcontext *baseContext) + +{ + __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext; + __GLXMESAdrawable *drawPriv = (__GLXMESAdrawable *) context->base.drawPriv; + __GLXMESAdrawable *readPriv = (__GLXMESAdrawable *) context->base.readPriv; + + return XMesaMakeCurrent2(context->xmesa, + drawPriv->xm_buf, + readPriv->xm_buf); +} + +static int +__glXMesaContextLoseCurrent(__GLXcontext *baseContext) +{ + __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext; + + return XMesaLoseCurrent(context->xmesa); +} + +static int +__glXMesaContextCopy(__GLXcontext *baseDst, + __GLXcontext *baseSrc, + unsigned long mask) +{ + __GLXMESAcontext *dst = (__GLXMESAcontext *) baseDst; + __GLXMESAcontext *src = (__GLXMESAcontext *) baseSrc; + + return XMesaCopyContext(src->xmesa, dst->xmesa, mask); +} + +static int +__glXMesaContextForceCurrent(__GLXcontext *baseContext) +{ + __GLXMESAcontext *context = (__GLXMESAcontext *) baseContext; + + /* GlxSetRenderTables() call for XGL moved in XMesaForceCurrent() */ + + return XMesaForceCurrent(context->xmesa); +} + +static __GLXcontext * +__glXMesaScreenCreateContext(__GLXscreen *screen, + __GLcontextModes *modes, + __GLXcontext *baseShareContext) +{ + __GLXMESAcontext *context; + __GLXMESAcontext *shareContext = (__GLXMESAcontext *) baseShareContext; + XMesaVisual xm_vis; + XMesaContext xm_share; + + context = xalloc (sizeof (__GLXMESAcontext)); + if (context == NULL) + return NULL; + + memset(context, 0, sizeof *context); + + context->base.pGlxScreen = screen; + context->base.modes = modes; + + context->base.destroy = __glXMesaContextDestroy; + context->base.makeCurrent = __glXMesaContextMakeCurrent; + context->base.loseCurrent = __glXMesaContextLoseCurrent; + context->base.copy = __glXMesaContextCopy; + context->base.forceCurrent = __glXMesaContextForceCurrent; + + xm_vis = find_mesa_visual(screen, modes->visualID); + if (!xm_vis) { + ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n", + modes->visualID); + xfree(context); + return NULL; + } + + xm_share = shareContext ? shareContext->xmesa : NULL; + context->xmesa = XMesaCreateContext(xm_vis, xm_share); + if (!context->xmesa) { + xfree(context); + return NULL; + } + + return &context->base; +} + +static void +__glXMesaScreenDestroy(__GLXscreen *screen) +{ + __GLXMESAscreen *mesaScreen = (__GLXMESAscreen *) screen; + int i; + + if (mesaScreen->xm_vis) { + for (i = 0; i < mesaScreen->num_vis; i++) { + if (mesaScreen->xm_vis[i]) + XMesaDestroyVisual(mesaScreen->xm_vis[i]); + } + + xfree(mesaScreen->xm_vis); + } + + __glXScreenDestroy(screen); + + xfree(screen); +} + +static XMesaVisual +find_mesa_visual(__GLXscreen *screen, VisualID vid) +{ + __GLXMESAscreen *mesaScreen = (__GLXMESAscreen *) screen; + const __GLcontextModes *modes; + unsigned i = 0; + + for ( modes = screen->modes ; modes != NULL ; modes = modes->next ) { + if ( modes->visualID == vid ) { + break; + } + + i++; + } + + return (modes != NULL) ? mesaScreen->xm_vis[i] : NULL; +} + +static void init_screen_visuals(__GLXMESAscreen *screen) +{ + ScreenPtr pScreen = screen->base.pScreen; + __GLcontextModes *modes; + XMesaVisual *pXMesaVisual; + int *used; + int i, j, size; + + /* Alloc space for the list of XMesa visuals */ + size = screen->base.numVisuals * sizeof(XMesaVisual); + pXMesaVisual = (XMesaVisual *) xalloc(size); + memset(pXMesaVisual, 0, size); + + /* FIXME: Change 'used' to be a array of bits (rather than of ints), + * FIXME: create a stack array of 8 or 16 bytes. If 'numVisuals' is less + * FIXME: than 64 or 128 the stack array can be used instead of calling + * FIXME: __glXMalloc / __glXFree. If nothing else, convert 'used' to + * FIXME: array of bytes instead of ints! + */ + used = (int *) xalloc(pScreen->numVisuals * sizeof(int)); + memset(used, 0, pScreen->numVisuals * sizeof(int)); + + i = 0; + for ( modes = screen->base.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]) { + + /* Create the XMesa visual */ + pXMesaVisual[i] = + XMesaCreateVisual(pScreen, + &pVis[j], + 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); + /* Set the VisualID */ + modes->visualID = pVis[j].vid; + + /* Mark this visual used */ + used[j] = 1; + break; + } + } + + 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" ); + } + + i++; + } + + xfree(used); + + screen->num_vis = pScreen->numVisuals; + screen->xm_vis = pXMesaVisual; +} + +static __GLXscreen * +__glXMesaScreenProbe(ScreenPtr pScreen) +{ + __GLXMESAscreen *screen; + + screen = xalloc(sizeof *screen); + if (screen == NULL) + return NULL; + + __glXScreenInit(&screen->base, pScreen); + + screen->base.destroy = __glXMesaScreenDestroy; + screen->base.createContext = __glXMesaScreenCreateContext; + screen->base.createDrawable = __glXMesaScreenCreateDrawable; + screen->base.pScreen = pScreen; + + /* + * Find the GLX visuals that are supported by this screen and create + * XMesa's visuals. + */ + init_screen_visuals(screen); + + return &screen->base; +} + +__GLXprovider __glXMesaProvider = { + __glXMesaScreenProbe, + "MESA", + NULL +}; + +__GLXprovider * +GlxGetMesaProvider (void) +{ + return &__glXMesaProvider; +} |