diff --git a/GL/glx/Makefile.am b/GL/glx/Makefile.am index 7c1730e39..8eda1531e 100644 --- a/GL/glx/Makefile.am +++ b/GL/glx/Makefile.am @@ -53,7 +53,6 @@ libglx_la_SOURCES = \ glxserver.h \ glxutil.c \ glxutil.h \ - glxvisuals.c \ indirect_dispatch.c \ indirect_dispatch.h \ indirect_dispatch_swap.c \ diff --git a/GL/glx/g_disptab.h b/GL/glx/g_disptab.h index f9a09ccd6..946e86ba6 100644 --- a/GL/glx/g_disptab.h +++ b/GL/glx/g_disptab.h @@ -34,7 +34,6 @@ ** version 1.2.1 Specification. */ -extern int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc); extern int __glXDisp_BindSwapBarrierSGIX(__GLXclientState *cl, GLbyte *pc); extern int __glXDisp_QueryMaxSwapBarriersSGIX(__GLXclientState *cl, GLbyte *pc); extern int __glXDisp_QueryHyperpipeNetworkSGIX(__GLXclientState *cl, GLbyte *pc); @@ -42,7 +41,6 @@ extern int __glXDisp_DestroyHyperpipeConfigSGIX (__GLXclientState *cl, GLbyte *p extern int __glXDisp_QueryHyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc); extern int __glXDisp_HyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc); -extern int __glXDispSwap_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc); extern int __glXDispSwap_BindSwapBarrierSGIX(__GLXclientState *cl, GLbyte *pc); extern int __glXDispSwap_QueryMaxSwapBarriersSGIX(__GLXclientState *cl, GLbyte *pc); extern int __glXDispSwap_QueryHyperpipeNetworkSGIX(__GLXclientState *cl, GLbyte *pc); diff --git a/GL/glx/glxcmds.c b/GL/glx/glxcmds.c index 900a34798..ac2393c3b 100644 --- a/GL/glx/glxcmds.c +++ b/GL/glx/glxcmds.c @@ -59,20 +59,97 @@ #include "indirect_table.h" #include "indirect_util.h" -/************************************************************************/ - void GlxSetRenderTables (struct _glapi_table *table) { _glapi_set_dispatch (table); } +static int +validGlxScreen(ClientPtr client, int screen, __GLXscreen **pGlxScreen, int *err) +{ + /* + ** Check if screen exists. + */ + if (screen >= screenInfo.numScreens) { + client->errorValue = screen; + *err = BadValue; + return FALSE; + } + *pGlxScreen = glxGetScreen(screenInfo.screens[screen]); -/************************************************************************/ + return TRUE; +} + +static int +validGlxFBConfig(ClientPtr client, __GLXscreen *pGlxScreen, XID id, + __GLcontextModes **config, int *err) +{ + __GLcontextModes *m; + + for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) + if (m->fbconfigID == id) { + *config = m; + return TRUE; + } + + client->errorValue = id; + *err = __glXError(GLXBadFBConfig); + + return FALSE; +} + +static int +validGlxVisual(ClientPtr client, __GLXscreen *pGlxScreen, XID id, + __GLcontextModes **config, int *err) +{ + int i; + + for (i = 0; i < pGlxScreen->numVisuals; i++) + if (pGlxScreen->visuals[i]->visualID == id) { + *config = pGlxScreen->visuals[i]; + return TRUE; + } + + client->errorValue = id; + *err = BadValue; + + return FALSE; +} + +static int +validGlxFBConfigForWindow(ClientPtr client, __GLcontextModes *config, + DrawablePtr pDraw, int *err) +{ + ScreenPtr pScreen = pDraw->pScreen; + VisualPtr pVisual = NULL; + XID vid; + int i; + + vid = wVisual((WindowPtr)pDraw); + for (i = 0; i < pScreen->numVisuals; i++) { + if (pScreen->visuals[i].vid == vid) { + pVisual = &pScreen->visuals[i]; + break; + } + } + + /* FIXME: What exactly should we check here... */ + if (pVisual->class != _gl_convert_to_x_visual_type(config->visualType) || + !(config->drawableType & GLX_WINDOW_BIT)) { + client->errorValue = pDraw->id; + *err = BadMatch; + return FALSE; + } + + return TRUE; +} void __glXContextDestroy(__GLXcontext *context) { + if (!context->isDirect) + __glXDeassociateContext(context); __glXFlushContextCache(); } @@ -107,59 +184,16 @@ static __GLXcontext *__glXdirectContextCreate(__GLXscreen *screen, * same as the VisualID. */ -int DoCreateContext(__GLXclientState *cl, GLXContextID gcId, - GLXContextID shareList, VisualID visual, - GLuint screen, GLboolean isDirect) +static int +DoCreateContext(__GLXclientState *cl, GLXContextID gcId, + GLXContextID shareList, __GLcontextModes *config, + __GLXscreen *pGlxScreen, GLboolean isDirect) { ClientPtr client = cl->client; VisualPtr pVisual; - ScreenPtr pScreen; __GLXcontext *glxc, *shareglxc; - __GLcontextModes *modes; - __GLXscreen *pGlxScreen; - GLint i; LEGAL_NEW_RESOURCE(gcId, client); - - /* - ** Check if screen exists. - */ - if (screen >= screenInfo.numScreens) { - client->errorValue = screen; - return BadValue; - } - pScreen = screenInfo.screens[screen]; - pGlxScreen = __glXActiveScreens[screen]; - - /* - ** Check if the visual ID is valid for this screen. - */ - pVisual = pScreen->visuals; - for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { - if (pVisual->vid == visual) { - break; - } - } - if (i == pScreen->numVisuals) { - client->errorValue = visual; - return BadValue; - } - - /* - ** Get configuration of the visual. This assumes that the - ** glXActiveScreens structure contains visual configurations only for the - ** subset of Visuals that are supported by this implementation of the - ** OpenGL. - */ - - modes = _gl_context_modes_find_visual( pGlxScreen->modes, visual ); - if (modes == NULL) { - /* - ** Visual not support on this screen by this OpenGL implementation. - */ - client->errorValue = visual; - return BadValue; - } /* ** Find the display list space that we want to share. @@ -203,9 +237,9 @@ int DoCreateContext(__GLXclientState *cl, GLXContextID gcId, ** Allocate memory for the new context */ if (!isDirect) - glxc = pGlxScreen->createContext(pGlxScreen, modes, shareglxc); + glxc = pGlxScreen->createContext(pGlxScreen, config, shareglxc); else - glxc = __glXdirectContextCreate(pGlxScreen, modes, shareglxc); + glxc = __glXdirectContextCreate(pGlxScreen, config, shareglxc); if (!glxc) { return BadAlloc; } @@ -214,10 +248,10 @@ int DoCreateContext(__GLXclientState *cl, GLXContextID gcId, ** Initially, setup the part of the context that could be used by ** a GL core that needs windowing information (e.g., Mesa). */ - glxc->pScreen = pScreen; + glxc->pScreen = pGlxScreen->pScreen; glxc->pGlxScreen = pGlxScreen; glxc->pVisual = pVisual; - glxc->modes = modes; + glxc->modes = config; /* ** Register this context as a resource. @@ -242,34 +276,54 @@ int DoCreateContext(__GLXclientState *cl, GLXContextID gcId, return Success; } - int __glXDisp_CreateContext(__GLXclientState *cl, GLbyte *pc) { xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; - return DoCreateContext( cl, req->context, req->shareList, req->visual, - req->screen, req->isDirect ); -} + __GLcontextModes *config; + __GLXscreen *pGlxScreen; + int err; + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) + return err; + if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err)) + return err; + + return DoCreateContext(cl, req->context, req->shareList, + config, pGlxScreen, req->isDirect); +} int __glXDisp_CreateNewContext(__GLXclientState *cl, GLbyte *pc) { xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; - return DoCreateContext( cl, req->context, req->shareList, req->fbconfig, - req->screen, req->isDirect ); -} + __GLcontextModes *config; + __GLXscreen *pGlxScreen; + int err; + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) + return err; + if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) + return err; + + return DoCreateContext(cl, req->context, req->shareList, + config, pGlxScreen, req->isDirect); +} int __glXDisp_CreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) { xGLXCreateContextWithConfigSGIXReq *req = (xGLXCreateContextWithConfigSGIXReq *) pc; - return DoCreateContext( cl, req->context, req->shareList, req->fbconfig, - req->screen, req->isDirect ); -} + __GLcontextModes *config; + __GLXscreen *pGlxScreen; + int err; -/* -** Destroy a GL context as an X resource. -*/ + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) + return err; + if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) + return err; + + return DoCreateContext(cl, req->context, req->shareList, + config, pGlxScreen, req->isDirect); +} int __glXDisp_DestroyContext(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; @@ -383,36 +437,6 @@ static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc) glxc->isCurrent = GL_TRUE; } -/*****************************************************************************/ -/* -** Make an OpenGL context and drawable current. -*/ - -int __glXDisp_MakeCurrent(__GLXclientState *cl, GLbyte *pc) -{ - xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc; - - return DoMakeCurrent( cl, req->drawable, req->drawable, - req->context, req->oldContextTag ); -} - -int __glXDisp_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc) -{ - xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc; - - return DoMakeCurrent( cl, req->drawable, req->readdrawable, - req->context, req->oldContextTag ); -} - -int __glXDisp_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) -{ - xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc; - - return DoMakeCurrent( cl, req->drawable, req->readable, - req->context, req->oldContextTag ); -} - - /** * Given a drawable ID, get the associated drawable and / or pixmap. * @@ -423,119 +447,88 @@ int __glXDisp_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) * * \param glxc Associated GLX context. * \param drawId ID of the drawable. - * \param ppDraw Location to store the pointer to the drawable. - * \param ppPixmap Location to store the pointer to the pixmap. * \param client Pointer to the client state. - * \return Zero is returned on success. Otherwise a GLX / X11 protocol error - * is returned. + * \return the __GLXdrawable is returned on success. Otherwise NULL. * * \notes This function will need some modification when support pbuffers * is added. */ -static int GetDrawableOrPixmap( __GLXcontext *glxc, GLXDrawable drawId, - __GLXdrawable **ppGlxDraw, - __GLXpixmap **ppPixmap, - ClientPtr client ) +static __GLXdrawable * +__glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client, + int *error) { DrawablePtr pDraw; - __GLcontextModes *modes; __GLXdrawable *pGlxDraw; - __GLXpixmap *drawPixmap = NULL; int rc; - /* This is the GLX 1.3 case - the client passes in a GLXWindow and - * we just return the __GLXdrawable. The first time a GLXPixmap - * comes in, it doesn't have a corresponding __GLXdrawable, so it - * falls through to the else-case below, but after that it'll have - * a __GLXdrawable and we'll handle it here. */ + /* This is the GLX 1.3 case - the client passes in a GLXWindow or + * GLXPixmap and we just return the __GLXdrawable. */ pGlxDraw = (__GLXdrawable *) LookupIDByType(drawId, __glXDrawableRes); if (pGlxDraw != NULL) { if (glxc != NULL && pGlxDraw->modes != glxc->modes) { client->errorValue = drawId; - return BadMatch; + *error = BadMatch; + return NULL; } - *ppGlxDraw = pGlxDraw; - *ppPixmap = pGlxDraw->pGlxPixmap; - return Success; + return pGlxDraw; } - /* The drawId wasn't a GLXWindow, so presumably it's a regular X - * window. In that case, we create a shadow GLXWindow for it on + /* The drawId wasn't a GLX drawable, so presumably it's a regular + * X window. In that case, we create a shadow GLXWindow for it on * demand here for pre GLX 1.3 compatibility and use the X Window * XID as its GLXWindow XID. The client can't explicitly create a * GLXWindow with the same XID as an X Window, so we wont get any * resource ID clashes. Effectively, the X Window is now also a * GLXWindow. */ - rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixUnknownAccess); - if (rc == Success) { - if (pDraw->type == DRAWABLE_WINDOW) { - VisualID vid = wVisual((WindowPtr)pDraw); - modes = _gl_context_modes_find_visual(glxc->pGlxScreen->modes, - vid); - } else { - /* - ** An X Pixmap is not allowed as a parameter (a GLX Pixmap - ** is, but it must first be created with glxCreateGLXPixmap). - */ - client->errorValue = drawId; - return __glXError(GLXBadDrawable); - } - } else { - drawPixmap = (__GLXpixmap *) LookupIDByType(drawId, __glXPixmapRes); - if (drawPixmap) { - pDraw = drawPixmap->pDraw; - modes = drawPixmap->modes; - } else { - /* - ** Drawable is neither a Window nor a GLXPixmap. - */ - client->errorValue = drawId; - return __glXError(GLXBadDrawable); - } + rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixUnknownAccess); + if (rc != Success || pDraw->type != DRAWABLE_WINDOW) { + client->errorValue = drawId; + *error = __glXError(GLXBadDrawable); + return NULL; } /* If we're not given a context, don't create the __GLXdrawable */ if (glxc == NULL) { - *ppPixmap = NULL; - *ppGlxDraw = NULL; - return Success; + *error = __glXError(GLXBadDrawable); + return NULL; } - /* We're binding an X Window or a GLX Pixmap for the first time - * and need to create a GLX drawable for it. First check that the - * drawable screen and fbconfig matches the context ditto. */ - if (pDraw->pScreen != glxc->pScreen || modes != glxc->modes) { - client->errorValue = drawId; - return BadMatch; - } + /* We're binding an X Window for the first time and need to create + * a GLX drawable for it. Check that the drawable screen matches + * the context screen and that the context fbconfig is compatible + * with the window visual. */ + if (pDraw->pScreen != glxc->pScreen || + !validGlxFBConfigForWindow(client, glxc->modes, pDraw, error)) + return NULL; - pGlxDraw = - glxc->pGlxScreen->createDrawable(glxc->pGlxScreen, - pDraw, drawId, modes); + pGlxDraw = glxc->pGlxScreen->createDrawable(glxc->pGlxScreen, + pDraw, GLX_DRAWABLE_WINDOW, + drawId, glxc->modes); /* since we are creating the drawablePrivate, drawId should be new */ if (!AddResource(drawId, __glXDrawableRes, pGlxDraw)) { pGlxDraw->destroy (pGlxDraw); - return BadAlloc; + *error = BadAlloc; + return NULL; } - *ppPixmap = drawPixmap; - *ppGlxDraw = pGlxDraw; - - return 0; + return pGlxDraw; } +/*****************************************************************************/ +/* +** Make an OpenGL context and drawable current. +*/ -int DoMakeCurrent( __GLXclientState *cl, - GLXDrawable drawId, GLXDrawable readId, - GLXContextID contextId, GLXContextTag tag ) +static int +DoMakeCurrent(__GLXclientState *cl, + GLXDrawable drawId, GLXDrawable readId, + GLXContextID contextId, GLXContextTag tag) { ClientPtr client = cl->client; xGLXMakeCurrentReply reply; - __GLXpixmap *drawPixmap = NULL; - __GLXpixmap *readPixmap = NULL; __GLXcontext *glxc, *prevglxc; __GLXdrawable *drawPriv = NULL; __GLXdrawable *readPriv = NULL; @@ -593,21 +586,13 @@ int DoMakeCurrent( __GLXclientState *cl, assert( drawId != None ); assert( readId != None ); - status = GetDrawableOrPixmap(glxc, drawId, &drawPriv, &drawPixmap, - client); - if ( status != 0 ) { + drawPriv = __glXGetDrawable(glxc, drawId, client, &status); + if (drawPriv == NULL) return status; - } - if ( readId != drawId ) { - status = GetDrawableOrPixmap(glxc, readId, &readPriv, &readPixmap, - client); - if ( status != 0 ) { - return status; - } - } else { - readPriv = drawPriv; - } + readPriv = __glXGetDrawable(glxc, readId, client, &status); + if (readPriv == NULL) + return status; } else { /* Switching to no context. Ignore new drawable. */ @@ -669,42 +654,6 @@ int DoMakeCurrent( __GLXclientState *cl, } if (prevglxc) { - if (prevglxc->drawPixmap) { - if (prevglxc->readPixmap && - prevglxc->drawPixmap != prevglxc->readPixmap) { - /* - ** The previous drawable was a glx pixmap, release it. - */ - prevglxc->readPixmap->refcnt--; - if (!prevglxc->readPixmap->idExists && - !prevglxc->readPixmap->refcnt) { - PixmapPtr pPixmap = (PixmapPtr) prevglxc->readPixmap->pDraw; - /* - ** The DestroyPixmap routine should decrement the - ** refcount of the X pixmap and free only if it's zero. - */ - (*prevglxc->readPixmap->pScreen->DestroyPixmap)(pPixmap); - xfree(prevglxc->readPixmap); - } - } - - /* - ** The previous drawable was a glx pixmap, release it. - */ - prevglxc->drawPixmap->refcnt--; - if (!prevglxc->drawPixmap->idExists && - !prevglxc->drawPixmap->refcnt) { - PixmapPtr pPixmap = (PixmapPtr) prevglxc->drawPixmap->pDraw; - /* - ** The DestroyPixmap routine should decrement the - ** refcount of the X pixmap and free only if it's zero. - */ - (*prevglxc->drawPixmap->pScreen->DestroyPixmap)(pPixmap); - xfree(prevglxc->drawPixmap); - } - - prevglxc->drawPixmap = NULL; - } ChangeCurrentContext(cl, glxc, tag); StopUsingContext(prevglxc); } else { @@ -712,16 +661,6 @@ int DoMakeCurrent( __GLXclientState *cl, } if (glxc) { - if (drawPixmap) { - drawPixmap->refcnt++; - glxc->drawPixmap = drawPixmap; - } - - if (readPixmap && (readPixmap != drawPixmap)) { - readPixmap->refcnt++; - glxc->readPixmap = readPixmap; - } - StartUsingContext(cl, glxc); reply.contextTag = tag; } else { @@ -740,6 +679,30 @@ int DoMakeCurrent( __GLXclientState *cl, return Success; } +int __glXDisp_MakeCurrent(__GLXclientState *cl, GLbyte *pc) +{ + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc; + + return DoMakeCurrent( cl, req->drawable, req->drawable, + req->context, req->oldContextTag ); +} + +int __glXDisp_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc) +{ + xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc; + + return DoMakeCurrent( cl, req->drawable, req->readdrawable, + req->context, req->oldContextTag ); +} + +int __glXDisp_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) +{ + xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc; + + return DoMakeCurrent( cl, req->drawable, req->readable, + req->context, req->oldContextTag ); +} + int __glXDisp_IsDirect(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; @@ -912,33 +875,28 @@ int __glXDisp_CopyContext(__GLXclientState *cl, GLbyte *pc) } -int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, - GLboolean do_swap) +int __glXDisp_GetVisualConfigs(__GLXclientState *cl, GLbyte *pc) { + xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc; ClientPtr client = cl->client; xGLXGetVisualConfigsReply reply; __GLXscreen *pGlxScreen; __GLcontextModes *modes; CARD32 buf[__GLX_TOTAL_CONFIG]; - int p; + int p, i, err; __GLX_DECLARE_SWAP_VARIABLES; __GLX_DECLARE_SWAP_ARRAY_VARIABLES; - if (screen >= screenInfo.numScreens) { - /* The client library must send a valid screen number. */ - client->errorValue = screen; - return BadValue; - } - pGlxScreen = __glXActiveScreens[screen]; + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) + return err; - reply.numVisuals = pGlxScreen->numUsableVisuals; + reply.numVisuals = pGlxScreen->numVisuals; reply.numProps = __GLX_TOTAL_CONFIG; - reply.length = (pGlxScreen->numUsableVisuals * __GLX_SIZE_CARD32 * - __GLX_TOTAL_CONFIG) >> 2; + reply.length = (reply.numVisuals * __GLX_SIZE_CARD32 * __GLX_TOTAL_CONFIG) >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; - if ( do_swap ) { + if (client->swapped) { __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.numVisuals); @@ -947,11 +905,9 @@ int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char *)&reply); - for ( modes = pGlxScreen->modes ; modes != NULL ; modes = modes->next ) { - if (modes->visualID == 0) { - /* not a usable visual */ - continue; - } + for (i = 0; i < pGlxScreen->numVisuals; i++) { + modes = pGlxScreen->visuals[i]; + p = 0; buf[p++] = modes->visualID; buf[p++] = _gl_convert_to_x_visual_type( modes->visualType ); @@ -992,7 +948,7 @@ int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, buf[p++] = GLX_TRANSPARENT_INDEX_VALUE; buf[p++] = modes->transparentIndex; - if ( do_swap ) { + if (client->swapped) { __GLX_SWAP_INT_ARRAY(buf, __GLX_TOTAL_CONFIG); } WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_TOTAL_CONFIG, @@ -1001,93 +957,6 @@ int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, return Success; } -int __glXDisp_GetVisualConfigs(__GLXclientState *cl, GLbyte *pc) -{ - xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc; - return DoGetVisualConfigs( cl, req->screen, GL_FALSE ); -} - - -/* Composite adds a 32 bit ARGB visual after glxvisuals.c have created - * the context modes for the screens. This visual is useful for GLX - * pixmaps, so we create a single mode for this visual with no extra - * buffers. */ -static void -__glXCreateARGBConfig(__GLXscreen *screen) -{ - __GLcontextModes *modes; - VisualPtr visual; - int i; - - /* search for a 32-bit visual */ - visual = NULL; - for (i = 0; i < screen->pScreen->numVisuals; i++) - if (screen->pScreen->visuals[i].nplanes == 32) { - visual = &screen->pScreen->visuals[i]; - break; - } - - if (visual == NULL || visual->class != TrueColor) - return; - - /* Stop now if we already added the mode. */ - if (_gl_context_modes_find_visual (screen->modes, visual->vid)) - return; - - modes = _gl_context_modes_create(1, sizeof(__GLcontextModes)); - if (modes == NULL) - return; - - /* Insert this new mode at the TAIL of the linked list. - * Previously, the mode was incorrectly inserted at the head of the - * list, causing find_mesa_visual() to be off by one. This would - * GLX clients to blow up if they attempted to use the last mode - * in the list! - */ - { - __GLcontextModes *prev = NULL, *m; - for (m = screen->modes; m; m = m->next) - prev = m; - if (prev) - prev->next = modes; - else - screen->modes = modes; - } - - screen->numUsableVisuals++; - screen->numVisuals++; - - modes->visualID = visual->vid; - modes->fbconfigID = visual->vid; - modes->visualType = GLX_TRUE_COLOR; - modes->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT; - modes->renderType = GLX_RGBA_BIT; - modes->xRenderable = GL_TRUE; - modes->rgbMode = TRUE; - modes->colorIndexMode = FALSE; - modes->doubleBufferMode = FALSE; - modes->stereoMode = FALSE; - modes->haveAccumBuffer = FALSE; - - modes->redBits = visual->bitsPerRGBValue;; - modes->greenBits = visual->bitsPerRGBValue; - modes->blueBits = visual->bitsPerRGBValue; - modes->alphaBits = visual->bitsPerRGBValue; - - modes->rgbBits = 4 * visual->bitsPerRGBValue; - modes->indexBits = 0; - modes->level = 0; - modes->numAuxBuffers = 0; - - modes->haveDepthBuffer = FALSE; - modes->depthBits = 0; - modes->haveStencilBuffer = FALSE; - modes->stencilBits = 0; - - modes->visualRating = GLX_NON_CONFORMANT_CONFIG; -} - - #define __GLX_TOTAL_FBCONFIG_ATTRIBS (28) #define __GLX_FBCONFIG_ATTRIBS_LENGTH (__GLX_TOTAL_FBCONFIG_ATTRIBS * 2) /** @@ -1100,37 +969,28 @@ __glXCreateARGBConfig(__GLXscreen *screen) * is the same, so this routine pulls double duty. */ -int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) +static int +DoGetFBConfigs(__GLXclientState *cl, unsigned screen) { ClientPtr client = cl->client; xGLXGetFBConfigsReply reply; __GLXscreen *pGlxScreen; CARD32 buf[__GLX_FBCONFIG_ATTRIBS_LENGTH]; - int p; + int p, err; __GLcontextModes *modes; __GLX_DECLARE_SWAP_VARIABLES; __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + if (!validGlxScreen(cl->client, screen, &pGlxScreen, &err)) + return err; - if (screen >= screenInfo.numScreens) { - /* The client library must send a valid screen number. */ - client->errorValue = screen; - return BadValue; - } - pGlxScreen = __glXActiveScreens[screen]; - - /* Create the "extra" 32bpp ARGB visual, if not already added. - * XXX This is questionable place to do so! Re-examine this someday. - */ - __glXCreateARGBConfig(pGlxScreen); - - reply.numFBConfigs = pGlxScreen->numUsableVisuals; + reply.numFBConfigs = pGlxScreen->numFBConfigs; reply.numAttribs = __GLX_TOTAL_FBCONFIG_ATTRIBS; reply.length = (__GLX_FBCONFIG_ATTRIBS_LENGTH * reply.numFBConfigs); reply.type = X_Reply; reply.sequenceNumber = client->sequence; - if ( do_swap ) { + if (client->swapped) { __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.numFBConfigs); @@ -1139,18 +999,14 @@ int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) WriteToClient(client, sz_xGLXGetFBConfigsReply, (char *)&reply); - for ( modes = pGlxScreen->modes ; modes != NULL ; modes = modes->next ) { - if (modes->visualID == 0) { - /* not a usable visual */ - continue; - } + for (modes = pGlxScreen->fbconfigs; modes != NULL; modes = modes->next) { p = 0; #define WRITE_PAIR(tag,value) \ do { buf[p++] = tag ; buf[p++] = value ; } while( 0 ) WRITE_PAIR( GLX_VISUAL_ID, modes->visualID ); - WRITE_PAIR( GLX_FBCONFIG_ID, modes->visualID ); + WRITE_PAIR( GLX_FBCONFIG_ID, modes->fbconfigID ); WRITE_PAIR( GLX_X_RENDERABLE, GL_TRUE ); WRITE_PAIR( GLX_RGBA, modes->rgbMode ); @@ -1170,12 +1026,7 @@ int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) WRITE_PAIR( GLX_ACCUM_ALPHA_SIZE, modes->accumAlphaBits ); WRITE_PAIR( GLX_DEPTH_SIZE, modes->depthBits ); WRITE_PAIR( GLX_STENCIL_SIZE, modes->stencilBits ); - WRITE_PAIR( GLX_X_VISUAL_TYPE, modes->visualType ); - - /* - ** Add token/value pairs for extensions. - */ WRITE_PAIR( GLX_CONFIG_CAVEAT, modes->visualRating ); WRITE_PAIR( GLX_TRANSPARENT_TYPE, modes->transparentPixel ); WRITE_PAIR( GLX_TRANSPARENT_RED_VALUE, modes->transparentRed ); @@ -1185,7 +1036,7 @@ int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) WRITE_PAIR( GLX_TRANSPARENT_INDEX_VALUE, modes->transparentIndex ); WRITE_PAIR( GLX_SWAP_METHOD_OML, modes->swapMethod ); - if ( do_swap ) { + if (client->swapped) { __GLX_SWAP_INT_ARRAY(buf, __GLX_FBCONFIG_ATTRIBS_LENGTH); } WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_FBCONFIG_ATTRIBS_LENGTH, @@ -1198,101 +1049,69 @@ int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) int __glXDisp_GetFBConfigs(__GLXclientState *cl, GLbyte *pc) { xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc; - return DoGetFBConfigs( cl, req->screen, GL_FALSE ); + return DoGetFBConfigs(cl, req->screen); } - int __glXDisp_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc) { xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc; - return DoGetFBConfigs( cl, req->screen, GL_FALSE ); + return DoGetFBConfigs(cl, req->screen); } -static int ValidateCreateDrawable(ClientPtr client, - int screenNum, XID fbconfigId, - XID drawablId, XID glxDrawableId, - int type, __GLcontextModes **modes, - DrawablePtr *ppDraw) +static int +DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLcontextModes *config, + DrawablePtr pDraw, XID glxDrawableId, int type) { - DrawablePtr pDraw; - ScreenPtr pScreen; - VisualPtr pVisual; - __GLXscreen *pGlxScreen; - int i, rc; + __GLXdrawable *pGlxDraw; LEGAL_NEW_RESOURCE(glxDrawableId, client); - rc = dixLookupDrawable(&pDraw, drawablId, client, 0, DixUnknownAccess); - if (rc != Success || pDraw->type != type) { - client->errorValue = drawablId; - return type == DRAWABLE_WINDOW ? BadWindow : BadPixmap; - } - - /* Check if screen of the fbconfig matches screen of drawable. */ - pScreen = pDraw->pScreen; - if (screenNum != pScreen->myNum) { + if (pGlxScreen->pScreen != pDraw->pScreen) return BadMatch; - } - /* If this fbconfig has a corresponding VisualRec the number of - * planes must match the drawable depth. */ - pVisual = pScreen->visuals; - for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { - if (pVisual->vid == fbconfigId && pVisual->nplanes != pDraw->depth) - return BadMatch; - } + pGlxDraw = pGlxScreen->createDrawable(pGlxScreen, pDraw, type, + glxDrawableId, config); + if (pGlxDraw == NULL) + return BadAlloc; - /* Get configuration of the visual. */ - pGlxScreen = __glXgetActiveScreen(screenNum); - *modes = _gl_context_modes_find_visual(pGlxScreen->modes, fbconfigId); - if (*modes == NULL) { - /* Visual not support on this screen by this OpenGL implementation. */ - client->errorValue = fbconfigId; - return BadValue; + if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) { + pGlxDraw->destroy (pGlxDraw); + return BadAlloc; } - *ppDraw = pDraw; - return Success; } -/* -** Create a GLX Pixmap from an X Pixmap. -*/ -int DoCreateGLXPixmap(__GLXclientState *cl, XID fbconfigId, - GLuint screenNum, XID pixmapId, XID glxPixmapId, - CARD32 *attribs, CARD32 numAttribs) +static int +DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLcontextModes *config, + XID drawableId, XID glxDrawableId) { - ClientPtr client = cl->client; DrawablePtr pDraw; - __GLXpixmap *pGlxPixmap; - __GLcontextModes *modes; + int err; + + err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixUnknownAccess); + if (err != Success || pDraw->type != DRAWABLE_PIXMAP) { + client->errorValue = drawableId; + return BadPixmap; + } + + err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, + glxDrawableId, GLX_DRAWABLE_PIXMAP); + + if (err == Success) + ((PixmapPtr) pDraw)->refcnt++; + + return err; +} + +static void +determineTextureTarget(XID glxDrawableID, CARD32 *attribs, CARD32 numAttribs) +{ GLenum target = 0; - int retval, i; + int i; + __GLXdrawable *pGlxDraw; - retval = ValidateCreateDrawable (client, screenNum, fbconfigId, - pixmapId, glxPixmapId, - DRAWABLE_PIXMAP, &modes, &pDraw); - if (retval != Success) - return retval; - - pGlxPixmap = (__GLXpixmap *) xalloc(sizeof(__GLXpixmap)); - if (!pGlxPixmap) { - return BadAlloc; - } - if (!(AddResource(glxPixmapId, __glXPixmapRes, pGlxPixmap))) { - return BadAlloc; - } - pGlxPixmap->pDraw = pDraw; - pGlxPixmap->pGlxScreen = __glXgetActiveScreen(screenNum); - pGlxPixmap->pScreen = pDraw->pScreen; - pGlxPixmap->idExists = True; -#ifdef XF86DRI - pGlxPixmap->pDamage = NULL; -#endif - pGlxPixmap->refcnt = 0; - - pGlxPixmap->modes = modes; + pGlxDraw = LookupIDByType(glxDrawableID, __glXDrawableRes); for (i = 0; i < numAttribs; i++) { if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) { @@ -1306,63 +1125,97 @@ int DoCreateGLXPixmap(__GLXclientState *cl, XID fbconfigId, } } } - + if (!target) { - int w = pDraw->width, h = pDraw->height; - + int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height; + if (h & (h - 1) || w & (w - 1)) target = GL_TEXTURE_RECTANGLE_ARB; else target = GL_TEXTURE_2D; } - pGlxPixmap->target = target; - - /* - ** Bump the ref count on the X pixmap so it won't disappear. - */ - ((PixmapPtr) pDraw)->refcnt++; - - return Success; + pGlxDraw->target = target; } int __glXDisp_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc) { xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc; - return DoCreateGLXPixmap( cl, req->visual, req->screen, - req->pixmap, req->glxpixmap, NULL, 0 ); + __GLcontextModes *config; + __GLXscreen *pGlxScreen; + int err; + + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) + return err; + if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err)) + return err; + + return DoCreateGLXPixmap(cl->client, pGlxScreen, config, + req->pixmap, req->glxpixmap); } int __glXDisp_CreatePixmap(__GLXclientState *cl, GLbyte *pc) { xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; - return DoCreateGLXPixmap( cl, req->fbconfig, req->screen, - req->pixmap, req->glxpixmap, - (CARD32*)(req + 1), - req->numAttribs ); + __GLcontextModes *config; + __GLXscreen *pGlxScreen; + int err; + + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) + return err; + if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) + return err; + + err = DoCreateGLXPixmap(cl->client, pGlxScreen, config, + req->pixmap, req->glxpixmap); + if (err != Success) + return err; + + determineTextureTarget(req->glxpixmap, + (CARD32*) (req + 1), req->numAttribs); + + return Success; } int __glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) { xGLXCreateGLXPixmapWithConfigSGIXReq *req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc; - return DoCreateGLXPixmap( cl, req->fbconfig, req->screen, - req->pixmap, req->glxpixmap, NULL, 0 ); + __GLcontextModes *config; + __GLXscreen *pGlxScreen; + int err; + + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) + return err; + if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) + return err; + + return DoCreateGLXPixmap(cl->client, pGlxScreen, + config, req->pixmap, req->glxpixmap); } -int DoDestroyPixmap(__GLXclientState *cl, XID glxpixmap) +static int DoDestroyDrawable(__GLXclientState *cl, XID glxdrawable, int type) { ClientPtr client = cl->client; + __GLXdrawable *pGlxDraw; /* - ** Check if it's a valid GLX pixmap. + ** Check it's the right type of drawable. */ - if (!LookupIDByType(glxpixmap, __glXPixmapRes)) { - client->errorValue = glxpixmap; - return __glXError(GLXBadPixmap); + pGlxDraw = LookupIDByType(glxdrawable, __glXDrawableRes); + if (pGlxDraw == NULL || pGlxDraw->type != type) { + client->errorValue = glxdrawable; + switch (type) { + case GLX_DRAWABLE_WINDOW: + return __glXError(GLXBadWindow); + case GLX_DRAWABLE_PIXMAP: + return __glXError(GLXBadDrawable); + case GLX_DRAWABLE_PBUFFER: + return __glXError(GLXBadPbuffer); + } } - FreeResource(glxpixmap, FALSE); + FreeResource(glxdrawable, FALSE); return Success; } @@ -1371,32 +1224,110 @@ int __glXDisp_DestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc) { xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc; - return DoDestroyPixmap(cl, req->glxpixmap); + return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); } int __glXDisp_DestroyPixmap(__GLXclientState *cl, GLbyte *pc) { xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc; - return DoDestroyPixmap(cl, req->glxpixmap); + return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); +} + +static int +DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId, + int width, int height, XID glxDrawableId) +{ + __GLcontextModes *config; + __GLXscreen *pGlxScreen; + PixmapPtr pPixmap; + int err; + + if (!validGlxScreen(client, screenNum, &pGlxScreen, &err)) + return err; + if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err)) + return err; + + __glXenterServer(GL_FALSE); + pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen, + width, height, config->rgbBits); + __glXleaveServer(GL_FALSE); + + return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable, + glxDrawableId, GLX_DRAWABLE_PBUFFER); } int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc) { - xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc; + xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc; + CARD32 *attrs; + int width, height, i; - (void) req; + attrs = (CARD32 *) (req + 1); + width = 0; + height = 0; - return BadRequest; + for (i = 0; i < req->numAttribs; i++) { + switch (attrs[i * 2]) { + case GLX_PBUFFER_WIDTH: + width = attrs[i * 2 + 1]; + break; + case GLX_PBUFFER_HEIGHT: + height = attrs[i * 2 + 1]; + break; + case GLX_LARGEST_PBUFFER: + case GLX_PRESERVED_CONTENTS: + /* FIXME: huh... */ + break; + } + } + + return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, + width, height, req->pbuffer); +} + +int __glXDisp_CreateGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc; + + return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, + req->width, req->height, req->pbuffer); } int __glXDisp_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc) { xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc; - (void) req; + return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); +} - return BadRequest; +int __glXDisp_DestroyGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc; + + return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); +} + +static int +DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable, + int numAttribs, CARD32 *attribs) +{ + __GLXdrawable *pGlxDraw; + int i; + + pGlxDraw = LookupIDByType(glxdrawable, __glXDrawableRes); + for (i = 0; i < numAttribs; i++) { + switch(attribs[i * 2]) { + case GLX_EVENT_MASK: + /* All we do is to record the event mask so we can send it + * back when queried. We never actually clobber the + * pbuffers, so we never need to send out the event. */ + pGlxDraw->eventMask = attribs[i * 2 + 1]; + break; + } + } + + return Success; } int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc) @@ -1404,58 +1335,51 @@ int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc) xGLXChangeDrawableAttributesReq *req = (xGLXChangeDrawableAttributesReq *) pc; - (void) req; + return DoChangeDrawableAttributes(cl->client, req->drawable, + req->numAttribs, (CARD32 *) (req + 1)); +} - return BadRequest; +int __glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXChangeDrawableAttributesSGIXReq *req = + (xGLXChangeDrawableAttributesSGIXReq *)pc; + + return DoChangeDrawableAttributes(cl->client, req->drawable, + req->numAttribs, (CARD32 *) (req + 1)); } int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) { - xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; - ClientPtr client = cl->client; - DrawablePtr pDraw; - __GLXdrawable *glxPriv; - __GLXscreen *screen; - __GLcontextModes *modes; - int retval; + xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; + __GLcontextModes *config; + __GLXscreen *pGlxScreen; + ClientPtr client = cl->client; + DrawablePtr pDraw; + int err; - retval = ValidateCreateDrawable (client, req->screen, req->fbconfig, - req->window, req->glxwindow, - DRAWABLE_WINDOW, &modes, &pDraw); - if (retval != Success) - return retval; + if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) + return err; + if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err)) + return err; - /* FIXME: We need to check that the window visual is compatible - * with the specified fbconfig. */ - - screen = __glXgetActiveScreen(req->screen); - glxPriv = screen->createDrawable(screen, pDraw, req->glxwindow, modes); - if (glxPriv == NULL) - return BadAlloc; - - if (!AddResource(req->glxwindow, __glXDrawableRes, glxPriv)) { - glxPriv->destroy (glxPriv); - return BadAlloc; + err = dixLookupDrawable(&pDraw, req->window, client, 0, DixUnknownAccess); + if (err != Success || pDraw->type != DRAWABLE_WINDOW) { + client->errorValue = req->window; + return BadWindow; } - return Success; + if (!validGlxFBConfigForWindow(client, config, pDraw, &err)) + return err; + + return DoCreateGLXDrawable(client, pGlxScreen, config, + pDraw, req->glxwindow, GLX_DRAWABLE_WINDOW); } int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc) { xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; - ClientPtr client = cl->client; - /* - ** Check if it's a valid GLX window. - */ - if (!LookupIDByType(req->glxwindow, __glXDrawableRes)) { - client->errorValue = req->glxwindow; - return __glXError(GLXBadWindow); - } - FreeResource(req->glxwindow, FALSE); - - return Success; + return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW); } @@ -1474,7 +1398,6 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc) XID drawId = req->drawable; __GLXcontext *glxc = NULL; __GLXdrawable *pGlxDraw; - __GLXpixmap *pPixmap; int error; if (tag) { @@ -1499,11 +1422,11 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc) } } - error = GetDrawableOrPixmap(glxc, drawId, &pGlxDraw, &pPixmap, client); - if (error != Success) + pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error); + if (pGlxDraw == NULL) return error; - if (pGlxDraw != NULL && pGlxDraw->type == DRAWABLE_WINDOW && + if (pGlxDraw->type == DRAWABLE_WINDOW && (*pGlxDraw->swapBuffers)(pGlxDraw) == GL_FALSE) return __glXError(GLXBadDrawable); @@ -1511,7 +1434,8 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc) } -int DoQueryContext(__GLXclientState *cl, GLXContextID gcId) +static int +DoQueryContext(__GLXclientState *cl, GLXContextID gcId) { ClientPtr client = cl->client; __GLXcontext *ctx; @@ -1574,8 +1498,8 @@ int __glXDisp_BindTexImageEXT(__GLXclientState *cl, GLbyte *pc) { xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; ClientPtr client = cl->client; - __GLXpixmap *pGlxPixmap; __GLXcontext *context; + __GLXdrawable *pGlxDraw; GLXDrawable drawId; int buffer; int error; @@ -1592,8 +1516,8 @@ int __glXDisp_BindTexImageEXT(__GLXclientState *cl, GLbyte *pc) if (!context) return error; - pGlxPixmap = (__GLXpixmap *)LookupIDByType(drawId, __glXPixmapRes); - if (!pGlxPixmap) { + pGlxDraw = __glXGetDrawable(NULL, drawId, client, &error); + if (!pGlxDraw || pGlxDraw->type != GLX_DRAWABLE_PIXMAP) { client->errorValue = drawId; return __glXError(GLXBadPixmap); } @@ -1603,14 +1527,14 @@ int __glXDisp_BindTexImageEXT(__GLXclientState *cl, GLbyte *pc) return context->textureFromPixmap->bindTexImage(context, buffer, - pGlxPixmap); + pGlxDraw); } int __glXDisp_ReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc) { xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; ClientPtr client = cl->client; - __GLXpixmap *pGlxPixmap; + __GLXdrawable *pGlxDraw; __GLXcontext *context; GLXDrawable drawId; int buffer; @@ -1625,10 +1549,10 @@ int __glXDisp_ReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc) if (!context) return error; - pGlxPixmap = (__GLXpixmap *)LookupIDByType(drawId, __glXPixmapRes); - if (!pGlxPixmap) { + pGlxDraw = __glXGetDrawable(NULL, drawId, client, &error); + if (!pGlxDraw || pGlxDraw->type != GLX_DRAWABLE_PIXMAP) { client->errorValue = drawId; - return __glXError(GLXBadDrawable); + return error; } if (!context->textureFromPixmap) @@ -1636,7 +1560,7 @@ int __glXDisp_ReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc) return context->textureFromPixmap->releaseTexImage(context, buffer, - pGlxPixmap); + pGlxDraw); } int __glXDisp_CopySubBufferMESA(__GLXclientState *cl, GLbyte *pc) @@ -1645,7 +1569,6 @@ int __glXDisp_CopySubBufferMESA(__GLXclientState *cl, GLbyte *pc) GLXContextTag tag = req->contextTag; __GLXcontext *glxc = NULL; __GLXdrawable *pGlxDraw; - __GLXpixmap *pPixmap; ClientPtr client = cl->client; GLXDrawable drawId; int error; @@ -1684,12 +1607,12 @@ int __glXDisp_CopySubBufferMESA(__GLXclientState *cl, GLbyte *pc) } } - error = GetDrawableOrPixmap(glxc, drawId, &pGlxDraw, &pPixmap, client); - if (error != Success) + pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error); + if (!pGlxDraw) return error; if (pGlxDraw == NULL || - pGlxDraw->type != DRAWABLE_WINDOW || + pGlxDraw->type != GLX_DRAWABLE_WINDOW || pGlxDraw->copySubBuffer == NULL) return __glXError(GLXBadDrawable); @@ -1705,28 +1628,30 @@ static int DoGetDrawableAttributes(__GLXclientState *cl, XID drawId) { ClientPtr client = cl->client; - __GLXpixmap *glxPixmap; xGLXGetDrawableAttributesReply reply; - CARD32 attributes[4]; - int numAttribs; + __GLXdrawable *pGlxDraw; + CARD32 attributes[6]; + int numAttribs, error; - glxPixmap = (__GLXpixmap *)LookupIDByType(drawId, __glXPixmapRes); - if (!glxPixmap) { + pGlxDraw = __glXGetDrawable(NULL, drawId, client, &error); + if (!pGlxDraw) { client->errorValue = drawId; - return __glXError(GLXBadPixmap); + return error; } - numAttribs = 2; + numAttribs = 3; reply.length = numAttribs << 1; reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.numAttribs = numAttribs; attributes[0] = GLX_TEXTURE_TARGET_EXT; - attributes[1] = glxPixmap->target == GL_TEXTURE_2D ? GLX_TEXTURE_2D_EXT : + attributes[1] = pGlxDraw->target == GL_TEXTURE_2D ? GLX_TEXTURE_2D_EXT : GLX_TEXTURE_RECTANGLE_EXT; attributes[2] = GLX_Y_INVERTED_EXT; attributes[3] = GL_FALSE; + attributes[4] = GLX_EVENT_MASK; + attributes[5] = pGlxDraw->eventMask; if (client->swapped) { __glXSwapGetDrawableAttributesReply(client, &reply, attributes); @@ -1740,18 +1665,6 @@ DoGetDrawableAttributes(__GLXclientState *cl, XID drawId) return Success; } -int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) -{ - xGLXVendorPrivateWithReplyReq *req = (xGLXVendorPrivateWithReplyReq *)pc; - CARD32 *data; - XID drawable; - - data = (CARD32 *) (req + 1); - drawable = data[0]; - - return DoGetDrawableAttributes(cl, drawable); -} - int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) { xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc; @@ -1759,6 +1672,14 @@ int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) return DoGetDrawableAttributes(cl, req->drawable); } +int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXGetDrawableAttributesSGIXReq *req = + (xGLXGetDrawableAttributesSGIXReq *)pc; + + return DoGetDrawableAttributes(cl, req->drawable); +} + /************************************************************************/ /* @@ -1766,7 +1687,10 @@ int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) ** client library to send batches of GL rendering commands. */ -int DoRender(__GLXclientState *cl, GLbyte *pc, int do_swap) +/* +** Execute all the drawing commands in a request. +*/ +int __glXDisp_Render(__GLXclientState *cl, GLbyte *pc) { xGLXRenderReq *req; ClientPtr client= cl->client; @@ -1777,9 +1701,8 @@ int DoRender(__GLXclientState *cl, GLbyte *pc, int do_swap) __GLXcontext *glxc; __GLX_DECLARE_SWAP_VARIABLES; - req = (xGLXRenderReq *) pc; - if (do_swap) { + if (client->swapped) { __GLX_SWAP_SHORT(&req->length); __GLX_SWAP_INT(&req->contextTag); } @@ -1803,7 +1726,7 @@ int DoRender(__GLXclientState *cl, GLbyte *pc, int do_swap) ** Also, each command must be word aligned. */ hdr = (__GLXrenderHeader *) pc; - if (do_swap) { + if (client->swapped) { __GLX_SWAP_SHORT(&hdr->length); __GLX_SWAP_SHORT(&hdr->opcode); } @@ -1815,7 +1738,8 @@ int DoRender(__GLXclientState *cl, GLbyte *pc, int do_swap) */ err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry); proc = (__GLXdispatchRenderProcPtr) - __glXGetProtocolDecodeFunction(& Render_dispatch_info, opcode, do_swap); + __glXGetProtocolDecodeFunction(& Render_dispatch_info, + opcode, client->swapped); if ((err < 0) || (proc == NULL)) { client->errorValue = commandsDone; @@ -1824,7 +1748,8 @@ int DoRender(__GLXclientState *cl, GLbyte *pc, int do_swap) if (entry.varsize) { /* variable size command */ - extra = (*entry.varsize)(pc + __GLX_RENDER_HDR_SIZE, do_swap); + extra = (*entry.varsize)(pc + __GLX_RENDER_HDR_SIZE, + client->swapped); if (extra < 0) { extra = 0; } @@ -1857,15 +1782,11 @@ int DoRender(__GLXclientState *cl, GLbyte *pc, int do_swap) return Success; } -/* -** Execute all the drawing commands in a request. -*/ -int __glXDisp_Render(__GLXclientState *cl, GLbyte *pc) -{ - return DoRender(cl, pc, False); -} -int DoRenderLarge(__GLXclientState *cl, GLbyte *pc, int do_swap) +/* +** Execute a large rendering request (one that spans multiple X requests). +*/ +int __glXDisp_RenderLarge(__GLXclientState *cl, GLbyte *pc) { xGLXRenderLargeReq *req; ClientPtr client= cl->client; @@ -1875,10 +1796,9 @@ int DoRenderLarge(__GLXclientState *cl, GLbyte *pc, int do_swap) int error; CARD16 opcode; __GLX_DECLARE_SWAP_VARIABLES; - req = (xGLXRenderLargeReq *) pc; - if (do_swap) { + if (client->swapped) { __GLX_SWAP_SHORT(&req->length); __GLX_SWAP_INT(&req->contextTag); __GLX_SWAP_INT(&req->dataBytes); @@ -1921,7 +1841,7 @@ int DoRenderLarge(__GLXclientState *cl, GLbyte *pc, int do_swap) } hdr = (__GLXrenderLargeHeader *) pc; - if (do_swap) { + if (client->swapped) { __GLX_SWAP_INT(&hdr->length); __GLX_SWAP_INT(&hdr->opcode); } @@ -1943,7 +1863,8 @@ int DoRenderLarge(__GLXclientState *cl, GLbyte *pc, int do_swap) ** be computed from its parameters), all the parameters needed ** will be in the 1st request, so it's okay to do this. */ - extra = (*entry.varsize)(pc + __GLX_RENDER_LARGE_HDR_SIZE, do_swap); + extra = (*entry.varsize)(pc + __GLX_RENDER_LARGE_HDR_SIZE, + client->swapped); if (extra < 0) { extra = 0; } @@ -2043,7 +1964,8 @@ int DoRenderLarge(__GLXclientState *cl, GLbyte *pc, int do_swap) opcode = hdr->opcode; proc = (__GLXdispatchRenderProcPtr) - __glXGetProtocolDecodeFunction(& Render_dispatch_info, opcode, do_swap); + __glXGetProtocolDecodeFunction(& Render_dispatch_info, opcode, + client->swapped); if (proc == NULL) { client->errorValue = opcode; return __glXError(GLXBadLargeRequest); @@ -2068,14 +1990,6 @@ int DoRenderLarge(__GLXclientState *cl, GLbyte *pc, int do_swap) } } -/* -** Execute a large rendering request (one that spans multiple X requests). -*/ -int __glXDisp_RenderLarge(__GLXclientState *cl, GLbyte *pc) -{ - return DoRenderLarge(cl, pc, False); -} - extern RESTYPE __glXSwapBarrierRes; int __glXDisp_BindSwapBarrierSGIX(__GLXclientState *cl, GLbyte *pc) @@ -2086,13 +2000,14 @@ int __glXDisp_BindSwapBarrierSGIX(__GLXclientState *cl, GLbyte *pc) int barrier = req->barrier; DrawablePtr pDraw; int screen, rc; + __GLXscreen *pGlxScreen; rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixUnknownAccess); + pGlxScreen = glxGetScreen(pDraw->pScreen); if (rc == Success && (pDraw->type == DRAWABLE_WINDOW)) { screen = pDraw->pScreen->myNum; - if (__glXSwapBarrierFuncs && - __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc) { - int ret = __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc(screen, drawable, barrier); + if (pGlxScreen->swapBarrierFuncs) { + int ret = pGlxScreen->swapBarrierFuncs->bindSwapBarrierFunc(screen, drawable, barrier); if (ret == Success) { if (barrier) /* add source for cleanup when drawable is gone */ @@ -2116,10 +2031,11 @@ int __glXDisp_QueryMaxSwapBarriersSGIX(__GLXclientState *cl, GLbyte *pc) (xGLXQueryMaxSwapBarriersSGIXReq *) pc; xGLXQueryMaxSwapBarriersSGIXReply reply; int screen = req->screen; + __GLXscreen *pGlxScreen; - if (__glXSwapBarrierFuncs && - __glXSwapBarrierFuncs[screen].queryMaxSwapBarriersFunc) - reply.max = __glXSwapBarrierFuncs[screen].queryMaxSwapBarriersFunc(screen); + pGlxScreen = glxGetScreen(screenInfo.screens[screen]); + if (pGlxScreen->swapBarrierFuncs) + reply.max = pGlxScreen->swapBarrierFuncs->queryMaxSwapBarriersFunc(screen); else reply.max = 0; @@ -2152,11 +2068,12 @@ int __glXDisp_QueryHyperpipeNetworkSGIX(__GLXclientState *cl, GLbyte *pc) int npipes=0; int n= 0; + __GLXscreen *pGlxScreen; - if (__glXHyperpipeFuncs && - __glXHyperpipeFuncs[screen].queryHyperpipeNetworkFunc != NULL) { + pGlxScreen = glxGetScreen(screenInfo.screens[screen]); + if (pGlxScreen->hyperpipeFuncs) { rdata = - (__glXHyperpipeFuncs[screen].queryHyperpipeNetworkFunc(screen, &npipes, &n)); + (pGlxScreen->hyperpipeFuncs->queryHyperpipeNetworkFunc(screen, &npipes, &n)); } length = __GLX_PAD(n) >> 2; reply.type = X_Reply; @@ -2189,13 +2106,13 @@ int __glXDisp_DestroyHyperpipeConfigSGIX (__GLXclientState *cl, GLbyte *pc) int screen = req->screen; int success = GLX_BAD_HYPERPIPE_SGIX; int hpId ; + __GLXscreen *pGlxScreen; hpId = req->hpId; - - if (__glXHyperpipeFuncs && - __glXHyperpipeFuncs[screen].destroyHyperpipeConfigFunc != NULL) { - success = __glXHyperpipeFuncs[screen].destroyHyperpipeConfigFunc(screen, hpId); + pGlxScreen = glxGetScreen(screenInfo.screens[screen]); + if (pGlxScreen->hyperpipeFuncs) { + success = pGlxScreen->hyperpipeFuncs->destroyHyperpipeConfigFunc(screen, hpId); } reply.type = X_Reply; @@ -2227,12 +2144,13 @@ int __glXDisp_QueryHyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc) int npipes=0; int n= 0; int hpId; + __GLXscreen *pGlxScreen; hpId = req->hpId; - if (__glXHyperpipeFuncs && - __glXHyperpipeFuncs[screen].queryHyperpipeConfigFunc != NULL) { - rdata = __glXHyperpipeFuncs[screen].queryHyperpipeConfigFunc(screen, hpId,&npipes, &n); + pGlxScreen = glxGetScreen(screenInfo.screens[screen]); + if (pGlxScreen->hyperpipeFuncs) { + rdata = pGlxScreen->hyperpipeFuncs->queryHyperpipeConfigFunc(screen, hpId,&npipes, &n); } length = __GLX_PAD(n) >> 2; @@ -2270,14 +2188,15 @@ int __glXDisp_HyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc) int npipes=0, networkId; int hpId=-1; + __GLXscreen *pGlxScreen; + pGlxScreen = glxGetScreen(screenInfo.screens[screen]); networkId = (int)req->networkId; npipes = (int)req->npipes; rdata = (void *)(req +1); - if (__glXHyperpipeFuncs && - __glXHyperpipeFuncs[screen].hyperpipeConfigFunc != NULL) { - __glXHyperpipeFuncs[screen].hyperpipeConfigFunc(screen,networkId, + if (pGlxScreen->hyperpipeFuncs) { + pGlxScreen->hyperpipeFuncs->hyperpipeConfigFunc(screen,networkId, &hpId, &npipes, (void *) rdata); } @@ -2352,23 +2271,15 @@ int __glXDisp_QueryExtensionsString(__GLXclientState *cl, GLbyte *pc) ClientPtr client = cl->client; xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc; xGLXQueryExtensionsStringReply reply; - GLuint screen; + __GLXscreen *pGlxScreen; size_t n, length; - const char *ptr; char *buf; + int err; - screen = req->screen; - /* - ** Check if screen exists. - */ - if (screen >= screenInfo.numScreens) { - client->errorValue = screen; - return BadValue; - } + if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) + return err; - ptr = __glXActiveScreens[screen]->GLXextensions; - - n = strlen(ptr) + 1; + n = strlen(pGlxScreen->GLXextensions) + 1; length = __GLX_PAD(n) >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; @@ -2379,7 +2290,7 @@ int __glXDisp_QueryExtensionsString(__GLXclientState *cl, GLbyte *pc) buf = (char *) xalloc(length << 2); if (buf == NULL) return BadAlloc; - memcpy(buf, ptr, n); + memcpy(buf, pGlxScreen->GLXextensions, n); if (client->swapped) { glxSwapQueryExtensionsStringReply(client, &reply, buf); @@ -2397,30 +2308,24 @@ int __glXDisp_QueryServerString(__GLXclientState *cl, GLbyte *pc) ClientPtr client = cl->client; xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc; xGLXQueryServerStringReply reply; - int name; - GLuint screen; size_t n, length; const char *ptr; char *buf; + __GLXscreen *pGlxScreen; + int err; - name = req->name; - screen = req->screen; - /* - ** Check if screen exists. - */ - if (screen >= screenInfo.numScreens) { - client->errorValue = screen; - return BadValue; - } - switch(name) { + if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) + return err; + + switch(req->name) { case GLX_VENDOR: - ptr = __glXActiveScreens[screen]->GLXvendor; + ptr = pGlxScreen->GLXvendor; break; case GLX_VERSION: - ptr = __glXActiveScreens[screen]->GLXversion; + ptr = pGlxScreen->GLXversion; break; case GLX_EXTENSIONS: - ptr = __glXActiveScreens[screen]->GLXextensions; + ptr = pGlxScreen->GLXextensions; break; default: return BadValue; diff --git a/GL/glx/glxcmdsswap.c b/GL/glx/glxcmdsswap.c index 12bc03037..7f17c263b 100644 --- a/GL/glx/glxcmdsswap.c +++ b/GL/glx/glxcmdsswap.c @@ -77,8 +77,7 @@ int __glXDispSwap_CreateContext(__GLXclientState *cl, GLbyte *pc) __GLX_SWAP_INT(&req->screen); __GLX_SWAP_INT(&req->shareList); - return DoCreateContext( cl, req->context, req->shareList, req->visual, - req->screen, req->isDirect ); + return __glXDisp_CreateContext(cl, pc); } int __glXDispSwap_CreateNewContext(__GLXclientState *cl, GLbyte *pc) @@ -93,8 +92,7 @@ int __glXDispSwap_CreateNewContext(__GLXclientState *cl, GLbyte *pc) __GLX_SWAP_INT(&req->renderType); __GLX_SWAP_INT(&req->shareList); - return DoCreateContext( cl, req->context, req->shareList, req->fbconfig, - req->screen, req->isDirect ); + return __glXDisp_CreateNewContext(cl, pc); } int __glXDispSwap_CreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) @@ -110,8 +108,7 @@ int __glXDispSwap_CreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) __GLX_SWAP_INT(&req->renderType); __GLX_SWAP_INT(&req->shareList); - return DoCreateContext( cl, req->context, req->shareList, req->fbconfig, - req->screen, req->isDirect ); + return __glXDisp_CreateContextWithConfigSGIX(cl, pc); } int __glXDispSwap_DestroyContext(__GLXclientState *cl, GLbyte *pc) @@ -135,8 +132,7 @@ int __glXDispSwap_MakeCurrent(__GLXclientState *cl, GLbyte *pc) __GLX_SWAP_INT(&req->context); __GLX_SWAP_INT(&req->oldContextTag); - return DoMakeCurrent( cl, req->drawable, req->drawable, - req->context, req->oldContextTag ); + return __glXDisp_MakeCurrent(cl, pc); } int __glXDispSwap_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc) @@ -150,8 +146,7 @@ int __glXDispSwap_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc) __GLX_SWAP_INT(&req->context); __GLX_SWAP_INT(&req->oldContextTag); - return DoMakeCurrent( cl, req->drawable, req->readdrawable, - req->context, req->oldContextTag ); + return __glXDisp_MakeContextCurrent(cl, pc); } int __glXDispSwap_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) @@ -165,8 +160,7 @@ int __glXDispSwap_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) __GLX_SWAP_INT(&req->context); __GLX_SWAP_INT(&req->oldContextTag); - return DoMakeCurrent( cl, req->drawable, req->readable, - req->context, req->oldContextTag ); + return __glXDisp_MakeCurrentReadSGI(cl, pc); } int __glXDispSwap_IsDirect(__GLXclientState *cl, GLbyte *pc) @@ -233,7 +227,7 @@ int __glXDispSwap_GetVisualConfigs(__GLXclientState *cl, GLbyte *pc) __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_INT(&req->screen); - return DoGetVisualConfigs( cl, req->screen, GL_TRUE ); + return __glXDisp_GetVisualConfigs(cl, pc); } int __glXDispSwap_GetFBConfigs(__GLXclientState *cl, GLbyte *pc) @@ -242,7 +236,7 @@ int __glXDispSwap_GetFBConfigs(__GLXclientState *cl, GLbyte *pc) __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_INT(&req->screen); - return DoGetFBConfigs( cl, req->screen, GL_TRUE ); + return __glXDisp_GetFBConfigs(cl, pc); } int __glXDispSwap_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc) @@ -251,7 +245,7 @@ int __glXDispSwap_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc) __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_INT(&req->screen); - return DoGetFBConfigs( cl, req->screen, GL_TRUE ); + return __glXDisp_GetFBConfigsSGIX(cl, pc); } int __glXDispSwap_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc) @@ -265,14 +259,15 @@ int __glXDispSwap_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc) __GLX_SWAP_INT(&req->pixmap); __GLX_SWAP_INT(&req->glxpixmap); - return DoCreateGLXPixmap( cl, req->visual, req->screen, - req->pixmap, req->glxpixmap, NULL, 0 ); + return __glXDisp_CreateGLXPixmap(cl, pc); } int __glXDispSwap_CreatePixmap(__GLXclientState *cl, GLbyte *pc) { xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; + CARD32 *attribs; __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; __GLX_SWAP_SHORT(&req->length); __GLX_SWAP_INT(&req->screen); @@ -280,11 +275,10 @@ int __glXDispSwap_CreatePixmap(__GLXclientState *cl, GLbyte *pc) __GLX_SWAP_INT(&req->pixmap); __GLX_SWAP_INT(&req->glxpixmap); __GLX_SWAP_INT(&req->numAttribs); + attribs = (CARD32*)(req + 1); + __GLX_SWAP_INT_ARRAY(attribs, req->numAttribs); - return DoCreateGLXPixmap( cl, req->fbconfig, req->screen, - req->pixmap, req->glxpixmap, - (CARD32*)(req + 1), - req->numAttribs ); + return __glXDisp_CreatePixmap(cl, pc); } int __glXDispSwap_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) @@ -299,8 +293,7 @@ int __glXDispSwap_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc __GLX_SWAP_INT(&req->pixmap); __GLX_SWAP_INT(&req->glxpixmap); - return DoCreateGLXPixmap( cl, req->fbconfig, req->screen, - req->pixmap, req->glxpixmap, NULL, 0 ); + return __glXDisp_CreateGLXPixmapWithConfigSGIX(cl, pc); } int __glXDispSwap_DestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc) @@ -328,52 +321,123 @@ int __glXDispSwap_DestroyPixmap(__GLXclientState *cl, GLbyte *pc) int __glXDispSwap_QueryContext(__GLXclientState *cl, GLbyte *pc) { xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc; + __GLX_DECLARE_SWAP_VARIABLES; - (void) req; + __GLX_SWAP_INT(&req->context); - return BadRequest; + return __glXDisp_QueryContext(cl, pc); } int __glXDispSwap_CreatePbuffer(__GLXclientState *cl, GLbyte *pc) { xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + CARD32 *attribs; - (void) req; + __GLX_SWAP_INT(&req->screen); + __GLX_SWAP_INT(&req->fbconfig); + __GLX_SWAP_INT(&req->pbuffer); + __GLX_SWAP_INT(&req->numAttribs); + attribs = (CARD32*)(req + 1); + __GLX_SWAP_INT_ARRAY(attribs, req->numAttribs); - return BadRequest; + return __glXDisp_CreatePbuffer(cl, pc); +} + +int __glXDispSwap_CreateGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_INT(&req->screen); + __GLX_SWAP_INT(&req->fbconfig); + __GLX_SWAP_INT(&req->pbuffer); + __GLX_SWAP_INT(&req->width); + __GLX_SWAP_INT(&req->height); + + return __glXDisp_CreateGLXPbufferSGIX(cl, pc); } int __glXDispSwap_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc) { xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) req; + __GLX_DECLARE_SWAP_VARIABLES; - return BadRequest; + __GLX_SWAP_INT(&req->pbuffer); + + return __glXDisp_DestroyPbuffer(cl, pc); +} + +int __glXDispSwap_DestroyGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) req; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_INT(&req->pbuffer); + + return __glXDisp_DestroyGLXPbufferSGIX(cl, pc); } int __glXDispSwap_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc) { xGLXChangeDrawableAttributesReq *req = (xGLXChangeDrawableAttributesReq *) req; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + CARD32 *attribs; - return BadRequest; + __GLX_SWAP_INT(&req->drawable); + __GLX_SWAP_INT(&req->numAttribs); + attribs = (CARD32*)(req + 1); + __GLX_SWAP_INT_ARRAY(attribs, req->numAttribs); + + return __glXDisp_ChangeDrawableAttributes(cl, pc); +} + +int __glXDispSwap_ChangeDrawableAttributesSGIX(__GLXclientState *cl, + GLbyte *pc) +{ + xGLXChangeDrawableAttributesSGIXReq *req = + (xGLXChangeDrawableAttributesSGIXReq *) req; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + CARD32 *attribs; + + __GLX_SWAP_INT(&req->drawable); + __GLX_SWAP_INT(&req->numAttribs); + attribs = (CARD32*)(req + 1); + __GLX_SWAP_INT_ARRAY(attribs, req->numAttribs); + + return __glXDisp_ChangeDrawableAttributesSGIX(cl, pc); } int __glXDispSwap_CreateWindow(__GLXclientState *cl, GLbyte *pc) { xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + CARD32 *attribs; - (void) req; + __GLX_SWAP_INT(&req->screen); + __GLX_SWAP_INT(&req->fbconfig); + __GLX_SWAP_INT(&req->window); + __GLX_SWAP_INT(&req->glxwindow); + __GLX_SWAP_INT(&req->numAttribs); + attribs = (CARD32*)(req + 1); + __GLX_SWAP_INT_ARRAY(attribs, req->numAttribs); - return BadRequest; + return __glXDisp_CreateWindow(cl, pc); } int __glXDispSwap_DestroyWindow(__GLXclientState *cl, GLbyte *pc) { xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; + __GLX_DECLARE_SWAP_VARIABLES; - (void) req; + __GLX_SWAP_INT(&req->glxwindow); - return BadRequest; + return __glXDisp_DestroyWindow(cl, pc); } int __glXDispSwap_SwapBuffers(__GLXclientState *cl, GLbyte *pc) @@ -643,7 +707,7 @@ void __glXSwapGetDrawableAttributesReply(ClientPtr client, int __glXDispSwap_Render(__GLXclientState *cl, GLbyte *pc) { - return DoRender(cl, pc, True); + return __glXDisp_Render(cl, pc); } /* @@ -651,7 +715,7 @@ int __glXDispSwap_Render(__GLXclientState *cl, GLbyte *pc) */ int __glXDispSwap_RenderLarge(__GLXclientState *cl, GLbyte *pc) { - return DoRenderLarge(cl, pc, True); + return __glXDisp_RenderLarge(cl, pc); } /************************************************************************/ diff --git a/GL/glx/glxcontext.h b/GL/glx/glxcontext.h index eb10ee2a8..712264729 100644 --- a/GL/glx/glxcontext.h +++ b/GL/glx/glxcontext.h @@ -44,12 +44,12 @@ typedef struct __GLXtextureFromPixmap __GLXtextureFromPixmap; struct __GLXtextureFromPixmap { - int (*bindTexImage) (__GLXcontext *baseContext, - int buffer, - __GLXpixmap *pixmap); - int (*releaseTexImage) (__GLXcontext *baseContext, - int buffer, - __GLXpixmap *pixmap); + int (*bindTexImage) (__GLXcontext *baseContext, + int buffer, + __GLXdrawable *pixmap); + int (*releaseTexImage) (__GLXcontext *baseContext, + int buffer, + __GLXdrawable *pixmap); }; @@ -151,12 +151,6 @@ struct __GLXcontext { GLuint *selectBuf; GLint selectBufSize; /* number of elements allocated */ - /* - ** Set only if current drawable is a glx pixmap. - */ - __GLXpixmap *drawPixmap; - __GLXpixmap *readPixmap; - /* ** The drawable private this context is bound to */ diff --git a/GL/glx/glxdrawable.h b/GL/glx/glxdrawable.h index b7ecad929..f62d1ee34 100644 --- a/GL/glx/glxdrawable.h +++ b/GL/glx/glxdrawable.h @@ -42,26 +42,12 @@ #include -#ifdef XF86DRI -#include -#endif - -typedef struct { - - DrawablePtr pDraw; - __GLcontextModes *modes; - __GLXscreen *pGlxScreen; - ScreenPtr pScreen; - Bool idExists; - int refcnt; - GLenum target; -#ifdef XF86DRI - DamagePtr pDamage; - __DRIcontext *pDRICtx; - GLint texname; - unsigned long offset; -#endif -} __GLXpixmap; +/* We just need to avoid clashing with DRAWABLE_{WINDOW,PIXMAP} */ +enum { + GLX_DRAWABLE_WINDOW, + GLX_DRAWABLE_PIXMAP, + GLX_DRAWABLE_PBUFFER +}; struct __GLXdrawable { void (*destroy)(__GLXdrawable *private); @@ -78,12 +64,10 @@ struct __GLXdrawable { DrawablePtr pDraw; XID drawId; - __GLXpixmap *pGlxPixmap; /* - ** Either DRAWABLE_PIXMAP or DRAWABLE_WINDOW, copied from pDraw above. - ** Needed by the resource freer because pDraw might already have been - ** freed. + ** Either GLX_DRAWABLE_PIXMAP, GLX_DRAWABLE_WINDOW or + ** GLX_DRAWABLE_PBUFFER. */ int type; @@ -105,6 +89,13 @@ struct __GLXdrawable { ** reference count */ int refCount; + + GLenum target; + + /* + ** Event mask + */ + unsigned long eventMask; }; #endif /* !__GLX_drawable_h__ */ diff --git a/GL/glx/glxdri.c b/GL/glx/glxdri.c index c1f3eb76b..3688d50a8 100644 --- a/GL/glx/glxdri.c +++ b/GL/glx/glxdri.c @@ -59,77 +59,55 @@ #include "dispatch.h" #include "extension_string.h" +#define containerOf(ptr, type, member) \ + (type *)( (char *)ptr - offsetof(type,member) ) -#define STRINGIFY(macro_or_string) STRINGIFY_ARG (macro_or_string) -#define STRINGIFY_ARG(contents) #contents - -typedef struct __GLXDRIscreen __GLXDRIscreen; -typedef struct __GLXDRIcontext __GLXDRIcontext; +typedef struct __GLXDRIscreen __GLXDRIscreen; +typedef struct __GLXDRIcontext __GLXDRIcontext; typedef struct __GLXDRIdrawable __GLXDRIdrawable; struct __GLXDRIscreen { __GLXscreen base; + __DRIscreen driScreen; + void *driver; - __DRIscreen driScreen; - void *driver; + xf86EnterVTProc *enterVT; + xf86LeaveVTProc *leaveVT; - xf86EnterVTProc *enterVT; - xf86LeaveVTProc *leaveVT; + __DRIcopySubBufferExtension *copySubBuffer; + __DRIswapControlExtension *swapControl; +#ifdef __DRI_TEX_OFFSET + __DRItexOffsetExtension *texOffset; DRITexOffsetStartProcPtr texOffsetStart; DRITexOffsetFinishProcPtr texOffsetFinish; - __GLXpixmap* texOffsetOverride[16]; + __GLXDRIdrawable *texOffsetOverride[16]; GLuint lastTexOffsetOverride; +#endif unsigned char glx_enable_bits[__GLX_EXT_BYTES]; }; struct __GLXDRIcontext { - __GLXcontext base; - - __DRIcontext driContext; + __GLXcontext base; + __DRIcontext driContext; + XID hwContextID; }; struct __GLXDRIdrawable { - __GLXdrawable base; + __GLXdrawable base; + __DRIdrawable driDrawable; - __DRIdrawable *driDrawable; + /* Pulled in from old __GLXpixmap */ +#ifdef __DRI_TEX_OFFSET + GLint texname; + __GLXDRIcontext *ctx; + unsigned long offset; + DamagePtr pDamage; +#endif }; -/* History: - * 20021121 - Initial version - * 20021128 - Added __glXWindowExists() function - * 20021207 - Added support for dynamic GLX extensions, - * GLX_SGI_swap_control, GLX_SGI_video_sync, - * GLX_OML_sync_control, and GLX_MESA_swap_control. - * Never officially released. Do NOT test against - * this version. Use 20030317 instead. - * 20030317 - Added support GLX_SGIX_fbconfig, - * GLX_MESA_swap_frame_usage, GLX_OML_swap_method, - * GLX_{ARB,SGIS}_multisample, and - * GLX_SGIX_visual_select_group. - * 20030606 - Added support for GLX_SGI_make_current_read. - * 20030813 - Made support for dynamic extensions multi-head aware. - * 20030818 - Added support for GLX_MESA_allocate_memory in place of the - * deprecated GLX_NV_vertex_array_range & GLX_MESA_agp_offset - * interfaces. - * 20031201 - Added support for the first round of DRI interface changes. - * Do NOT test against this version! It has binary - * compatibility bugs, use 20040317 instead. - * 20040317 - Added the 'mode' field to __DRIcontextRec. - * 20040415 - Added support for bindContext3 and unbindContext3. - * 20040602 - Add __glXGetDrawableInfo. I though that was there - * months ago. :( - * 20050727 - Gut all the old interfaces. This breaks compatability with - * any DRI driver built to any previous version. - * 20060314 - Added support for GLX_MESA_copy_sub_buffer. - */ - -#define INTERNAL_VERSION 20050727 - -static const char CREATE_NEW_SCREEN_FUNC[] = - "__driCreateNewScreen_" STRINGIFY (INTERNAL_VERSION); - +static const char CREATE_NEW_SCREEN_FUNC[] = __DRI_CREATE_NEW_SCREEN_STRING; static void __glXDRIleaveServer(GLboolean rendering) @@ -138,19 +116,19 @@ __glXDRIleaveServer(GLboolean rendering) for (i = 0; rendering && i < screenInfo.numScreens; i++) { __GLXDRIscreen * const screen = - (__GLXDRIscreen *) __glXgetActiveScreen(i); + (__GLXDRIscreen *) glxGetScreen(screenInfo.screens[i]); GLuint lastOverride = screen->lastTexOffsetOverride; if (lastOverride) { - __GLXpixmap **texOffsetOverride = screen->texOffsetOverride; + __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride; int j; for (j = 0; j < lastOverride; j++) { - __GLXpixmap *pGlxPix = texOffsetOverride[j]; + __GLXDRIdrawable *pGlxPix = texOffsetOverride[j]; if (pGlxPix && pGlxPix->texname) { pGlxPix->offset = - screen->texOffsetStart((PixmapPtr)pGlxPix->pDraw); + screen->texOffsetStart((PixmapPtr)pGlxPix->base.pDraw); } } } @@ -160,23 +138,22 @@ __glXDRIleaveServer(GLboolean rendering) for (i = 0; rendering && i < screenInfo.numScreens; i++) { __GLXDRIscreen * const screen = - (__GLXDRIscreen *) __glXgetActiveScreen(i); + (__GLXDRIscreen *) glxGetScreen(screenInfo.screens[i]); GLuint lastOverride = screen->lastTexOffsetOverride; if (lastOverride) { - __GLXpixmap **texOffsetOverride = screen->texOffsetOverride; + __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride; int j; for (j = 0; j < lastOverride; j++) { - __GLXpixmap *pGlxPix = texOffsetOverride[j]; + __GLXDRIdrawable *pGlxPix = texOffsetOverride[j]; if (pGlxPix && pGlxPix->texname) { - screen->driScreen.setTexOffset(pGlxPix->pDRICtx, - pGlxPix->texname, - pGlxPix->offset, - pGlxPix->pDraw->depth, - ((PixmapPtr)pGlxPix->pDraw)-> - devKind); + screen->texOffset->setTexOffset(&pGlxPix->ctx->driContext, + pGlxPix->texname, + pGlxPix->offset, + pGlxPix->base.pDraw->depth, + ((PixmapPtr)pGlxPix->base.pDraw)->devKind); } } } @@ -189,8 +166,8 @@ __glXDRIenterServer(GLboolean rendering) int i; for (i = 0; rendering && i < screenInfo.numScreens; i++) { - __GLXDRIscreen * const screen = - (__GLXDRIscreen *) __glXgetActiveScreen(i); + __GLXDRIscreen * const screen = (__GLXDRIscreen *) + glxGetScreen(screenInfo.screens[i]); if (screen->lastTexOffsetOverride) { CALL_Flush(GET_DISPATCH(), ()); @@ -201,29 +178,17 @@ __glXDRIenterServer(GLboolean rendering) DRIWakeupHandler(NULL, 0, NULL); } -/** - * \bug - * We're jumping through hoops here to get the DRIdrawable which the DRI - * driver tries to keep to it self... cf. FIXME in \c createDrawable. - */ static void -__glXDRIdrawableFoo(__GLXDRIdrawable *draw) +__glXDRIdrawableDestroy(__GLXdrawable *drawable) { - __GLXDRIscreen * const screen = - (__GLXDRIscreen *) __glXgetActiveScreen(draw->base.pDraw->pScreen->myNum); + __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; - draw->driDrawable = (*screen->driScreen.getDrawable)(NULL, - draw->base.drawId, - screen->driScreen.private); -} + (*private->driDrawable.destroyDrawable)(&private->driDrawable); -static void -__glXDRIdrawableDestroy(__GLXdrawable *private) -{ -#if 0 - (*glxPriv->driDrawable.destroyDrawable)(NULL, - glxPriv->driDrawable.private); -#endif + __glXenterServer(GL_FALSE); + DRIDestroyDrawable(drawable->pDraw->pScreen, + serverClient, drawable->pDraw); + __glXleaveServer(GL_FALSE); xfree(private); } @@ -242,10 +207,7 @@ __glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate) { __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate; - __glXDRIdrawableFoo(private); - - (*private->driDrawable->swapBuffers)(NULL, - private->driDrawable->private); + (*private->driDrawable.swapBuffers)(&private->driDrawable); return TRUE; } @@ -255,10 +217,12 @@ static int __glXDRIdrawableSwapInterval(__GLXdrawable *baseDrawable, int interval) { __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseDrawable; + __GLXDRIscreen *screen = (__GLXDRIscreen *) + glxGetScreen(baseDrawable->pDraw->pScreen); - __glXDRIdrawableFoo(draw); + if (screen->swapControl) + screen->swapControl->setSwapInterval(&draw->driDrawable, interval); - draw->driDrawable->swap_interval = interval; return 0; } @@ -268,22 +232,26 @@ __glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate, int x, int y, int w, int h) { __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate; + __GLXDRIscreen *screen = (__GLXDRIscreen *) + glxGetScreen(basePrivate->pDraw->pScreen); - __glXDRIdrawableFoo(private); - - (*private->driDrawable->copySubBuffer)(NULL, - private->driDrawable->private, - x, y, w, h); + if (screen->copySubBuffer) + screen->copySubBuffer->copySubBuffer(&private->driDrawable, + x, y, w, h); } static void __glXDRIcontextDestroy(__GLXcontext *baseContext) { __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; + Bool retval; + + context->driContext.destroyContext(&context->driContext); + + __glXenterServer(GL_FALSE); + retval = DRIDestroyContext(baseContext->pScreen, context->hwContextID); + __glXleaveServer(GL_FALSE); - context->driContext.destroyContext(NULL, - context->base.pScreen->myNum, - context->driContext.private); __glXContextDestroy(&context->base); xfree(context); } @@ -292,24 +260,20 @@ static int __glXDRIcontextMakeCurrent(__GLXcontext *baseContext) { __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; + __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv; + __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv; - return (*context->driContext.bindContext)(NULL, - context->base.pScreen->myNum, - baseContext->drawPriv->drawId, - baseContext->readPriv->drawId, - &context->driContext); -} + return (*context->driContext.bindContext)(&context->driContext, + &draw->driDrawable, + &read->driDrawable); +} static int __glXDRIcontextLoseCurrent(__GLXcontext *baseContext) { __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; - return (*context->driContext.unbindContext)(NULL, - context->base.pScreen->myNum, - baseContext->drawPriv->drawId, - baseContext->readPriv->drawId, - &context->driContext); + return (*context->driContext.unbindContext)(&context->driContext); } static int @@ -331,12 +295,12 @@ static int __glXDRIcontextForceCurrent(__GLXcontext *baseContext) { __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext; + __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv; + __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv; - return (*context->driContext.bindContext)(NULL, - context->base.pScreen->myNum, - baseContext->drawPriv->drawId, - baseContext->readPriv->drawId, - &context->driContext); + return (*context->driContext.bindContext)(&context->driContext, + &draw->driDrawable, + &read->driDrawable); } static void @@ -370,15 +334,17 @@ glxFillAlphaChannel (PixmapPtr pixmap, int x, int y, int width, int height) static int __glXDRIbindTexImage(__GLXcontext *baseContext, int buffer, - __GLXpixmap *glxPixmap) + __GLXdrawable *glxPixmap) { RegionPtr pRegion = NULL; PixmapPtr pixmap; int bpp, override = 0, texname; GLenum format, type; - ScreenPtr pScreen = glxPixmap->pScreen; + ScreenPtr pScreen = glxPixmap->pDraw->pScreen; + __GLXDRIdrawable *driDraw = + containerOf(glxPixmap, __GLXDRIdrawable, base); __GLXDRIscreen * const screen = - (__GLXDRIscreen *) __glXgetActiveScreen(pScreen->myNum); + (__GLXDRIscreen *) glxGetScreen(pScreen); CALL_GetIntegerv(GET_DISPATCH(), (glxPixmap->target == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : @@ -390,12 +356,12 @@ __glXDRIbindTexImage(__GLXcontext *baseContext, pixmap = (PixmapPtr) glxPixmap->pDraw; - if (screen->texOffsetStart && screen->driScreen.setTexOffset) { - __GLXpixmap **texOffsetOverride = screen->texOffsetOverride; + if (screen->texOffsetStart && screen->texOffset) { + __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride; int i, firstEmpty = 16; for (i = 0; i < 16; i++) { - if (texOffsetOverride[i] == glxPixmap) + if (texOffsetOverride[i] == driDraw) goto alreadyin; if (firstEmpty == 16 && !texOffsetOverride[i]) @@ -410,36 +376,37 @@ __glXDRIbindTexImage(__GLXcontext *baseContext, if (firstEmpty >= screen->lastTexOffsetOverride) screen->lastTexOffsetOverride = firstEmpty + 1; - texOffsetOverride[firstEmpty] = glxPixmap; + texOffsetOverride[firstEmpty] = driDraw; alreadyin: override = 1; - glxPixmap->pDRICtx = &((__GLXDRIcontext*)baseContext)->driContext; + driDraw->ctx = (__GLXDRIcontext*)baseContext; - if (texname == glxPixmap->texname) + if (texname == driDraw->texname) return Success; - glxPixmap->texname = texname; + driDraw->texname = texname; - screen->driScreen.setTexOffset(glxPixmap->pDRICtx, texname, 0, - pixmap->drawable.depth, pixmap->devKind); + screen->texOffset->setTexOffset(&driDraw->ctx->driContext, texname, 0, + pixmap->drawable.depth, + pixmap->devKind); } nooverride: - if (!glxPixmap->pDamage) { + if (!driDraw->pDamage) { if (!override) { - glxPixmap->pDamage = DamageCreate(NULL, NULL, DamageReportNone, - TRUE, pScreen, NULL); - if (!glxPixmap->pDamage) + driDraw->pDamage = DamageCreate(NULL, NULL, DamageReportNone, + TRUE, pScreen, NULL); + if (!driDraw->pDamage) return BadAlloc; - DamageRegister ((DrawablePtr) pixmap, glxPixmap->pDamage); + DamageRegister ((DrawablePtr) pixmap, driDraw->pDamage); } pRegion = NULL; } else { - pRegion = DamageRegion(glxPixmap->pDamage); + pRegion = DamageRegion(driDraw->pDamage); if (REGION_NIL(pRegion)) return Success; } @@ -518,7 +485,7 @@ nooverride: } if (!override) - DamageEmpty(glxPixmap->pDamage); + DamageEmpty(driDraw->pDamage); return Success; } @@ -526,19 +493,21 @@ nooverride: static int __glXDRIreleaseTexImage(__GLXcontext *baseContext, int buffer, - __GLXpixmap *pixmap) + __GLXdrawable *pixmap) { - ScreenPtr pScreen = pixmap->pScreen; + ScreenPtr pScreen = pixmap->pDraw->pScreen; + __GLXDRIdrawable *driDraw = + containerOf(pixmap, __GLXDRIdrawable, base); __GLXDRIscreen * const screen = - (__GLXDRIscreen *) __glXgetActiveScreen(pScreen->myNum); + (__GLXDRIscreen *) glxGetScreen(pScreen); GLuint lastOverride = screen->lastTexOffsetOverride; if (lastOverride) { - __GLXpixmap **texOffsetOverride = screen->texOffsetOverride; + __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride; int i; for (i = 0; i < lastOverride; i++) { - if (texOffsetOverride[i] == pixmap) { + if (texOffsetOverride[i] == driDraw) { if (screen->texOffsetFinish) screen->texOffsetFinish((PixmapPtr)pixmap->pDraw); @@ -575,9 +544,7 @@ __glXDRIscreenDestroy(__GLXscreen *baseScreen) { __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; - screen->driScreen.destroyScreen(NULL, - screen->base.pScreen->myNum, - screen->driScreen.private); + screen->driScreen.destroyScreen(&screen->driScreen); dlclose(screen->driver); @@ -593,13 +560,18 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen, { __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen; __GLXDRIcontext *context, *shareContext; - void *sharePrivate; + VisualPtr visual; + int i; + GLboolean retval; + __DRIcontext *driShare; + drm_context_t hwContext; + ScreenPtr pScreen = baseScreen->pScreen; shareContext = (__GLXDRIcontext *) baseShareContext; if (shareContext) - sharePrivate = shareContext->driContext.private; + driShare = &shareContext->driContext; else - sharePrivate = NULL; + driShare = NULL; context = xalloc(sizeof *context); if (context == NULL) @@ -614,25 +586,43 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen, context->base.pScreen = screen->base.pScreen; context->base.textureFromPixmap = &__glXDRItextureFromPixmap; + /* Find the requested X visual */ + visual = pScreen->visuals; + for (i = 0; i < pScreen->numVisuals; i++, visual++) + if (visual->vid == modes->visualID) + break; + if (i == pScreen->numVisuals) + return GL_FALSE; + + context->hwContextID = FakeClientID(0); + + __glXenterServer(GL_FALSE); + retval = DRICreateContext(baseScreen->pScreen, visual, + context->hwContextID, &hwContext); + __glXleaveServer(GL_FALSE); context->driContext.private = - screen->driScreen.createNewContext(NULL, modes, + screen->driScreen.createNewContext(&screen->driScreen, + modes, 0, /* render type */ - sharePrivate, + driShare, + hwContext, &context->driContext); - context->driContext.mode = modes; - return &context->base; } static __GLXdrawable * __glXDRIscreenCreateDrawable(__GLXscreen *screen, DrawablePtr pDraw, + int type, XID drawId, __GLcontextModes *modes) { + __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; __GLXDRIdrawable *private; + GLboolean retval; + drm_drawable_t hwDrawable; private = xalloc(sizeof *private); if (private == NULL) @@ -640,7 +630,8 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, memset(private, 0, sizeof *private); - if (!__glXDrawableInit(&private->base, screen, pDraw, drawId, modes)) { + if (!__glXDrawableInit(&private->base, screen, + pDraw, type, drawId, modes)) { xfree(private); return NULL; } @@ -650,238 +641,45 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, private->base.swapBuffers = __glXDRIdrawableSwapBuffers; private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer; -#if 0 - /* FIXME: It would only be natural that we called - * driScreen->createNewDrawable here but the DRI drivers manage - * them a little oddly. FIXME: describe this better.*/ + __glXenterServer(GL_FALSE); + retval = DRICreateDrawable(screen->pScreen, serverClient, + pDraw, &hwDrawable); + __glXleaveServer(GL_FALSE); /* The last argument is 'attrs', which is used with pbuffers which * we currently don't support. */ - glxPriv->driDrawable.private = - (screen->driScreen.createNewDrawable)(NULL, modes, - drawId, - &glxPriv->driDrawable, - 0, - NULL); -#endif + private->driDrawable.private = + (driScreen->driScreen.createNewDrawable)(&driScreen->driScreen, + modes, + &private->driDrawable, + hwDrawable, 0, NULL); return &private->base; } - -static unsigned -filter_modes(__GLcontextModes **server_modes, - const __GLcontextModes *driver_modes) -{ - __GLcontextModes * m; - __GLcontextModes ** prev_next; - const __GLcontextModes * check; - unsigned modes_count = 0; - - if ( driver_modes == NULL ) { - LogMessage(X_WARNING, - "AIGLX: 3D driver returned no fbconfigs.\n"); - return 0; - } - - /* For each mode in server_modes, check to see if a matching mode exists - * in driver_modes. If not, then the mode is not available. - */ - - prev_next = server_modes; - for ( m = *prev_next ; m != NULL ; m = *prev_next ) { - GLboolean do_delete = GL_TRUE; - - for ( check = driver_modes ; check != NULL ; check = check->next ) { - if ( _gl_context_modes_are_same( m, check ) ) { - do_delete = GL_FALSE; - break; - } - } - - /* The 3D has to support all the modes that match the GLX visuals - * sent from the X server. - */ - if ( do_delete && (m->visualID != 0) ) { - do_delete = GL_FALSE; - - LogMessage(X_WARNING, - "AIGLX: 3D driver claims to not support " - "visual 0x%02x\n", m->visualID); - } - - if ( do_delete ) { - *prev_next = m->next; - - m->next = NULL; - _gl_context_modes_destroy( m ); - } - else { - modes_count++; - prev_next = & m->next; - } - } - - return modes_count; -} - - -static void -enable_glx_extension(void *psc, const char *ext_name) -{ - __GLXDRIscreen * const screen = (__GLXDRIscreen *) psc; - - __glXEnableExtension(screen->glx_enable_bits, ext_name); -} - - -static __DRIfuncPtr getProcAddress(const char *proc_name) -{ - if (strcmp(proc_name, "glxEnableExtension") == 0) { - return (__DRIfuncPtr) enable_glx_extension; - } - - return NULL; -} - -static __DRIscreen *findScreen(__DRInativeDisplay *dpy, int scrn) -{ - __GLXDRIscreen *screen = (__GLXDRIscreen *) __glXgetActiveScreen(scrn); - - return &screen->driScreen; -} - -static GLboolean windowExists(__DRInativeDisplay *dpy, __DRIid draw) -{ - DrawablePtr pDrawable = (DrawablePtr) LookupIDByType(draw, RT_WINDOW); - int unused; - drm_clip_rect_t *pRects; - - return pDrawable ? DRIGetDrawableInfo(pDrawable->pScreen, pDrawable, - (unsigned*)&unused, (unsigned*)&unused, - &unused, &unused, &unused, &unused, - &unused, &pRects, &unused, &unused, - &unused, &pRects) - : GL_FALSE; -} - -static GLboolean createContext(__DRInativeDisplay *dpy, int screen, - int configID, void *contextID, - drm_context_t *hw_context) -{ - XID fakeID; - VisualPtr visual; - int i; - ScreenPtr pScreen; - GLboolean retval; - - pScreen = screenInfo.screens[screen]; - - /* Find the requested X visual */ - visual = pScreen->visuals; - for (i = 0; i < pScreen->numVisuals; i++, visual++) - if (visual->vid == configID) - break; - if (i == pScreen->numVisuals) - return GL_FALSE; - - fakeID = FakeClientID(0); - *(XID *) contextID = fakeID; - - __glXDRIenterServer(GL_FALSE); - retval = DRICreateContext(pScreen, visual, fakeID, hw_context); - __glXDRIleaveServer(GL_FALSE); - return retval; -} - -static GLboolean destroyContext(__DRInativeDisplay *dpy, int screen, - __DRIid context) -{ - GLboolean retval; - - __glXDRIenterServer(GL_FALSE); - retval = DRIDestroyContext(screenInfo.screens[screen], context); - __glXDRIleaveServer(GL_FALSE); - return retval; -} - static GLboolean -createDrawable(__DRInativeDisplay *dpy, int screen, - __DRIid drawable, drm_drawable_t *hHWDrawable) -{ - DrawablePtr pDrawable; - GLboolean retval; - - pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE); - if (!pDrawable) - return GL_FALSE; - - __glXDRIenterServer(GL_FALSE); - retval = DRICreateDrawable(screenInfo.screens[screen], __pGlxClient, - pDrawable, hHWDrawable); - __glXDRIleaveServer(GL_FALSE); - return retval; -} - -static GLboolean -destroyDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable) -{ - DrawablePtr pDrawable; - GLboolean retval; - - pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE); - if (!pDrawable) - return GL_FALSE; - - __glXDRIenterServer(GL_FALSE); - retval = DRIDestroyDrawable(screenInfo.screens[screen], __pGlxClient, - pDrawable); - __glXDRIleaveServer(GL_FALSE); - return retval; -} - -static GLboolean -getDrawableInfo(__DRInativeDisplay *dpy, int screen, - __DRIid drawable, unsigned int *index, unsigned int *stamp, +getDrawableInfo(__DRIdrawable *driDrawable, + unsigned int *index, unsigned int *stamp, int *x, int *y, int *width, int *height, int *numClipRects, drm_clip_rect_t **ppClipRects, int *backX, int *backY, int *numBackClipRects, drm_clip_rect_t **ppBackClipRects) { - DrawablePtr pDrawable; + __GLXDRIdrawable *drawable = containerOf(driDrawable, + __GLXDRIdrawable, driDrawable); + ScreenPtr pScreen = drawable->base.pDraw->pScreen; drm_clip_rect_t *pClipRects, *pBackClipRects; GLboolean retval; size_t size; - pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE); - if (!pDrawable) { - ErrorF("getDrawableInfo failed to look up window\n"); - - *index = 0; - *stamp = 0; - *x = 0; - *y = 0; - *width = 0; - *height = 0; - *numClipRects = 0; - *ppClipRects = NULL; - *backX = 0; - *backY = 0; - *numBackClipRects = 0; - *ppBackClipRects = NULL; - - return GL_FALSE; - } - - __glXDRIenterServer(GL_FALSE); - retval = DRIGetDrawableInfo(screenInfo.screens[screen], - pDrawable, index, stamp, + __glXenterServer(GL_FALSE); + retval = DRIGetDrawableInfo(pScreen, drawable->base.pDraw, index, stamp, x, y, width, height, numClipRects, &pClipRects, backX, backY, numBackClipRects, &pBackClipRects); - __glXDRIleaveServer(GL_FALSE); + __glXleaveServer(GL_FALSE); if (*numClipRects > 0) { size = sizeof (drm_clip_rect_t) * *numClipRects; @@ -889,7 +687,6 @@ getDrawableInfo(__DRInativeDisplay *dpy, int screen, /* Clip cliprects to screen dimensions (redirected windows) */ if (*ppClipRects != NULL) { - ScreenPtr pScreen = screenInfo.screens[screen]; int i, j; for (i = 0, j = 0; i < *numClipRects; i++) { @@ -946,25 +743,33 @@ getUST(int64_t *ust) } } +static void __glXReportDamage(__DRIdrawable *driDraw, + int x, int y, + drm_clip_rect_t *rects, int num_rects, + GLboolean front_buffer) +{ + __GLXDRIdrawable *drawable = + containerOf(driDraw, __GLXDRIdrawable, driDrawable); + DrawablePtr pDraw = drawable->base.pDraw; + RegionRec region; + + REGION_INIT(pDraw->pScreen, ®ion, (BoxPtr) rects, num_rects); + REGION_TRANSLATE(pScreen, ®ion, pDraw->x, pDraw->y); + DamageDamageRegion(pDraw, ®ion); + REGION_UNINIT(pDraw->pScreen, ®ion); +} + /* Table of functions that we export to the driver. */ static const __DRIinterfaceMethods interface_methods = { - getProcAddress, - _gl_context_modes_create, _gl_context_modes_destroy, - - findScreen, - windowExists, - - createContext, - destroyContext, - createDrawable, - destroyDrawable, getDrawableInfo, getUST, NULL, /* glXGetMscRateOML, */ + + __glXReportDamage, }; static const char dri_driver_path[] = DRI_DRIVER_PATH; @@ -972,7 +777,8 @@ static const char dri_driver_path[] = DRI_DRIVER_PATH; static Bool glxDRIEnterVT (int index, int flags) { - __GLXDRIscreen *screen = (__GLXDRIscreen *) __glXgetActiveScreen(index); + __GLXDRIscreen *screen = (__GLXDRIscreen *) + glxGetScreen(screenInfo.screens[index]); LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n"); @@ -987,7 +793,8 @@ glxDRIEnterVT (int index, int flags) static void glxDRILeaveVT (int index, int flags) { - __GLXDRIscreen *screen = (__GLXDRIscreen *) __glXgetActiveScreen(index); + __GLXDRIscreen *screen = (__GLXDRIscreen *) + glxGetScreen(screenInfo.screens[index]); LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n"); @@ -996,6 +803,48 @@ glxDRILeaveVT (int index, int flags) return (*screen->leaveVT) (index, flags); } +static void +initializeExtensions(__GLXDRIscreen *screen) +{ + const __DRIextension **extensions; + int i; + + extensions = screen->driScreen.getExtensions(&screen->driScreen); + for (i = 0; extensions[i]; i++) { +#ifdef __DRI_COPY_SUB_BUFFER + if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { + screen->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; + __glXEnableExtension(screen->glx_enable_bits, + "GLX_MESA_copy_sub_buffer"); + + LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n"); + } +#endif + +#ifdef __DRI_SWAP_CONTROL + if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) { + screen->swapControl = (__DRIswapControlExtension *) extensions[i]; + __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"); + } +#endif + +#ifdef __DRI_TEX_OFFSET + if (strcmp(extensions[i]->name, __DRI_TEX_OFFSET) == 0) { + screen->texOffset = (__DRItexOffsetExtension *) extensions[i]; + LogMessage(X_INFO, "AIGLX: enabled GLX_texture_from_pixmap with driver support\n"); + } +#endif + /* Ignore unknown extensions */ + } +} + +#define COPY_SUB_BUFFER_INTERNAL_VERSION 20060314 + static __GLXscreen * __glXDRIscreenProbe(ScreenPtr pScreen) { @@ -1016,7 +865,6 @@ __glXDRIscreenProbe(ScreenPtr pScreen) char *driverName; drm_handle_t hFB; int junk; - __GLcontextModes * driver_modes; __GLXDRIscreen *screen; void *dev_priv = NULL; char filename[128]; @@ -1044,8 +892,6 @@ __glXDRIscreenProbe(ScreenPtr pScreen) screen->base.pScreen = pScreen; __glXInitExtensionEnableBits(screen->glx_enable_bits); - screen->driScreen.screenConfigs = screen; - /* DRI protocol version. */ dri_version.major = XF86DRI_MAJOR_VERSION; @@ -1168,11 +1014,9 @@ __glXDRIscreenProbe(ScreenPtr pScreen) goto handle_error; } - driver_modes = NULL; screen->driScreen.private = - (*createNewScreen)(NULL, pScreen->myNum, + (*createNewScreen)(pScreen->myNum, &screen->driScreen, - screen->base.modes, &ddx_version, &dri_version, &drm_version, @@ -1181,7 +1025,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen) fd, api_ver, &interface_methods, - &driver_modes); + &screen->base.fbconfigs); if (screen->driScreen.private == NULL) { LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed"); @@ -1191,6 +1035,8 @@ __glXDRIscreenProbe(ScreenPtr pScreen) DRIGetTexOffsetFuncs(pScreen, &screen->texOffsetStart, &screen->texOffsetFinish); + initializeExtensions(screen); + __glXScreenInit(&screen->base, pScreen); buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL); @@ -1204,10 +1050,6 @@ __glXDRIscreenProbe(ScreenPtr pScreen) screen->base.GLXextensions); } - - filter_modes(&screen->base.modes, driver_modes); - _gl_context_modes_destroy(driver_modes); - __glXsetEnterLeaveServerFuncs(__glXDRIenterServer, __glXDRIleaveServer); screen->enterVT = pScrn->EnterVT; diff --git a/GL/glx/glxext.c b/GL/glx/glxext.c index b35175ed2..4d6bfd7c6 100644 --- a/GL/glx/glxext.c +++ b/GL/glx/glxext.c @@ -45,8 +45,6 @@ __GLXcontext *__glXLastContext; ** X resources. */ RESTYPE __glXContextRes; -RESTYPE __glXClientRes; -RESTYPE __glXPixmapRes; RESTYPE __glXDrawableRes; RESTYPE __glXSwapBarrierRes; @@ -55,11 +53,7 @@ RESTYPE __glXSwapBarrierRes; */ xGLXSingleReply __glXReply; -/* -** A set of state for each client. The 0th one is unused because client -** indices start at 1, not 0. -*/ -static __GLXclientState *__glXClients[MAXCLIENTS + 1]; +static int glxClientPrivateIndex; /* ** Client that called into GLX dispatch. @@ -77,29 +71,6 @@ static int __glXDispatch(ClientPtr); static void ResetExtension(ExtensionEntry* extEntry) { __glXFlushContextCache(); - __glXResetScreens(); -} - -/* -** Initialize the per-client context storage. -*/ -static void ResetClientState(int clientIndex) -{ - __GLXclientState *cl = __glXClients[clientIndex]; - - if (cl->returnBuf) xfree(cl->returnBuf); - if (cl->largeCmdBuf) xfree(cl->largeCmdBuf); - if (cl->currentContexts) xfree(cl->currentContexts); - memset(cl, 0, sizeof(__GLXclientState)); - /* - ** By default, assume that the client supports - ** GLX major version 1 minor version 0 protocol. - */ - cl->GLClientmajorVersion = 1; - cl->GLClientminorVersion = 0; - if (cl->GLClientextensions) - xfree(cl->GLClientextensions); - } /* @@ -129,66 +100,6 @@ static int ContextGone(__GLXcontext* cx, XID id) return True; } -/* -** Free a client's state. -*/ -static int ClientGone(int clientIndex, XID id) -{ - __GLXcontext *cx; - __GLXclientState *cl = __glXClients[clientIndex]; - int i; - - if (cl) { - /* - ** Free all the contexts that are current for this client. - */ - for (i=0; i < cl->numCurrentContexts; i++) { - cx = cl->currentContexts[i]; - if (cx) { - __glXDeassociateContext(cx); - cx->isCurrent = GL_FALSE; - if (!cx->idExists) { - __glXFreeContext(cx); - } - } - } - /* - ** Re-initialize the client state structure. Don't free it because - ** we'll probably get another client with this index and use the struct - ** again. There is a maximum of MAXCLIENTS of these structures. - */ - ResetClientState(clientIndex); - } - - return True; -} - -/* -** Free a GLX Pixmap. -*/ -static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) -{ - PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; - - pGlxPixmap->idExists = False; - if (!pGlxPixmap->refcnt) { -#ifdef XF86DRI - if (pGlxPixmap->pDamage) { - DamageUnregister (pGlxPixmap->pDraw, pGlxPixmap->pDamage); - DamageDestroy(pGlxPixmap->pDamage); - } -#endif - /* - ** The DestroyPixmap routine should decrement the refcount and free - ** only if it's zero. - */ - (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); - xfree(pGlxPixmap); - } - - return True; -} - /* ** Destroy routine that gets called when a drawable is freed. A drawable ** contains the ancillary buffers needed for rendering. @@ -198,24 +109,17 @@ static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid) __GLXcontext *cx, *cx1; /* - ** Use glxPriv->type to figure out what kind of drawable this is. Don't - ** use glxPriv->pDraw->type because by the time this routine is called, - ** the pDraw might already have been freed. + ** When a drawable is destroyed, notify all context bound to + ** it, that there are no longer bound to anything. */ - if (glxPriv->type == DRAWABLE_WINDOW) { - /* - ** When a window is destroyed, notify all context bound to - ** it, that there are no longer bound to anything. - */ - for (cx = glxPriv->drawGlxc; cx; cx = cx1) { - cx1 = cx->nextDrawPriv; - cx->pendingState |= __GLX_PENDING_DESTROY; - } + for (cx = glxPriv->drawGlxc; cx; cx = cx1) { + cx1 = cx->nextDrawPriv; + cx->pendingState |= __GLX_PENDING_DESTROY; + } - for (cx = glxPriv->readGlxc; cx; cx = cx1) { - cx1 = cx->nextReadPriv; - cx->pendingState |= __GLX_PENDING_DESTROY; - } + for (cx = glxPriv->readGlxc; cx; cx = cx1) { + cx1 = cx->nextReadPriv; + cx->pendingState |= __GLX_PENDING_DESTROY; } __glXUnrefDrawable(glxPriv); @@ -260,9 +164,10 @@ extern RESTYPE __glXSwapBarrierRes; static int SwapBarrierGone(int screen, XID drawable) { - if (__glXSwapBarrierFuncs && - __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc != NULL) { - __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc(screen, drawable, 0); + __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]); + + if (pGlxScreen->swapBarrierFuncs) { + pGlxScreen->swapBarrierFuncs->bindSwapBarrierFunc(screen, drawable, 0); } FreeResourceByType(drawable, __glXSwapBarrierRes, FALSE); return True; @@ -310,22 +215,86 @@ int __glXError(int error) return __glXErrorBase + error; } +__GLXclientState * +glxGetClient(ClientPtr pClient) +{ + return (__GLXclientState *) pClient->devPrivates[glxClientPrivateIndex].ptr; +} + +static void +glxClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + __GLXclientState *cl = glxGetClient(pClient); + __GLXcontext *cx; + int i; + + switch (pClient->clientState) { + case ClientStateRunning: + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + cl->client = pClient; + break; + + case ClientStateGone: + for (i = 0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + cx->isCurrent = GL_FALSE; + if (!cx->idExists) + __glXFreeContext(cx); + } + } + + if (cl->returnBuf) xfree(cl->returnBuf); + if (cl->largeCmdBuf) xfree(cl->largeCmdBuf); + if (cl->currentContexts) xfree(cl->currentContexts); + if (cl->GLClientextensions) xfree(cl->GLClientextensions); + break; + + default: + break; + } +} + /************************************************************************/ +static __GLXprovider *__glXProviderStack; + +void GlxPushProvider(__GLXprovider *provider) +{ + provider->next = __glXProviderStack; + __glXProviderStack = provider; +} + /* ** Initialize the GLX extension. */ void GlxExtensionInit(void) { ExtensionEntry *extEntry; + ScreenPtr pScreen; int i; + __GLXprovider *p; __glXContextRes = CreateNewResourceType((DeleteType)ContextGone); - __glXClientRes = CreateNewResourceType((DeleteType)ClientGone); - __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone); __glXDrawableRes = CreateNewResourceType((DeleteType)DrawableGone); __glXSwapBarrierRes = CreateNewResourceType((DeleteType)SwapBarrierGone); + glxClientPrivateIndex = AllocateClientPrivateIndex (); + if (!AllocateClientPrivate (glxClientPrivateIndex, + sizeof (__GLXclientState))) + return; + if (!AddCallback (&ClientStateCallback, glxClientCallback, 0)) + return; + /* ** Add extension to server extensions. */ @@ -344,17 +313,18 @@ void GlxExtensionInit(void) __glXErrorBase = extEntry->errorBase; - /* - ** Initialize table of client state. There is never a client 0. - */ - for (i = 1; i <= MAXCLIENTS; i++) { - __glXClients[i] = 0; - } + for (i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; - /* - ** Initialize screen specific data. - */ - __glXInitScreens(); + for (p = __glXProviderStack; p != NULL; p = p->next) { + if (p->screenProbe(pScreen) != NULL) { + LogMessage(X_INFO, + "GLX: Initialized %s GL provider for screen %d\n", + p->name, i); + break; + } + } + } } /************************************************************************/ @@ -422,11 +392,9 @@ void glxSuspendClients(void) { int i; - for (i = 1; i <= MAXCLIENTS; i++) { - if (__glXClients[i] == NULL || !__glXClients[i]->inUse) - continue; - - IgnoreClient(__glXClients[i]->client); + for (i = 1; i < currentMaxClients; i++) { + if (glxGetClient(clients[i])->inUse) + IgnoreClient(clients[i]); } glxBlockClients = TRUE; @@ -439,11 +407,9 @@ void glxResumeClients(void) glxBlockClients = FALSE; - for (i = 1; i <= MAXCLIENTS; i++) { - if (__glXClients[i] == NULL || !__glXClients[i]->inUse) - continue; - - AttendClient(__glXClients[i]->client); + for (i = 1; i < currentMaxClients; i++) { + if (glxGetClient(clients[i])->inUse) + AttendClient(clients[i]); } __glXleaveServer(GL_FALSE); @@ -505,29 +471,9 @@ static int __glXDispatch(ClientPtr client) int retval; opcode = stuff->glxCode; - cl = __glXClients[client->index]; - if (!cl) { - cl = (__GLXclientState *) xalloc(sizeof(__GLXclientState)); - __glXClients[client->index] = cl; - if (!cl) { - return BadAlloc; - } - memset(cl, 0, sizeof(__GLXclientState)); - } - - if (!cl->inUse) { - /* - ** This is first request from this client. Associate a resource - ** with the client so we will be notified when the client dies. - */ - XID xid = FakeClientID(client->index); - if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { - return BadAlloc; - } - ResetClientState(client->index); - cl->inUse = GL_TRUE; - cl->client = client; - } + cl = glxGetClient(client); + /* Mark it in use so we suspend it on VT switch. */ + cl->inUse = TRUE; /* ** If we're expecting a glXRenderLarge request, this better be one. diff --git a/GL/glx/glxext.h b/GL/glx/glxext.h index 6774e4d4c..a81850cef 100644 --- a/GL/glx/glxext.h +++ b/GL/glx/glxext.h @@ -71,24 +71,6 @@ extern void __glXClearErrorOccured(void); extern GLboolean __glXErrorOccured(void); extern void __glXResetLargeCommandStatus(__GLXclientState*); -extern int DoMakeCurrent( __GLXclientState *cl, GLXDrawable drawId, - GLXDrawable readId, GLXContextID contextId, GLXContextTag tag ); -extern int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, - GLboolean do_swap); -extern int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, - GLboolean do_swap); -extern int DoCreateContext(__GLXclientState *cl, GLXContextID gcId, - GLXContextID shareList, VisualID visual, GLuint screen, GLboolean isDirect); -extern int DoCreateGLXPixmap(__GLXclientState *cl, XID fbconfigId, - GLuint screenNum, XID pixmapId, XID glxpixmapId, CARD32 *attribs, - CARD32 numAttribs); -extern int DoDestroyPixmap(__GLXclientState *cl, XID glxpixmapId); - -extern int DoQueryContext(__GLXclientState *cl, GLXContextID gcId); - -extern int DoRender(__GLXclientState *cl, GLbyte *pc, int do_swap); -extern int DoRenderLarge(__GLXclientState *cl, GLbyte *pc, int do_swap); - extern void GlxExtensionInit(void); extern const char GLServerVersion[]; @@ -106,25 +88,5 @@ extern int GlxInitVisuals( int preferredVis ); -typedef struct { - void * (* queryHyperpipeNetworkFunc)(int, int *, int *); - void * (* queryHyperpipeConfigFunc)(int, int, int *, int *); - int (* destroyHyperpipeConfigFunc)(int, int); - void * (* hyperpipeConfigFunc)(int, int, int *, int *, void *); -} __GLXHyperpipeExtensionFuncs; - -extern void __glXHyperpipeInit(int screen, __GLXHyperpipeExtensionFuncs *funcs); - -extern __GLXHyperpipeExtensionFuncs *__glXHyperpipeFuncs; - -typedef struct { - int (* bindSwapBarrierFunc)(int, XID, int); - int (* queryMaxSwapBarriersFunc)(int); -} __GLXSwapBarrierExtensionFuncs; - -extern void __glXSwapBarrierInit(int screen, __GLXSwapBarrierExtensionFuncs *funcs); - -extern __GLXSwapBarrierExtensionFuncs *__glXSwapBarrierFuncs; - #endif /* _glxext_h_ */ diff --git a/GL/glx/glxglcore.c b/GL/glx/glxglcore.c index 679d55c5d..6aa4e7f5c 100644 --- a/GL/glx/glxglcore.c +++ b/GL/glx/glxglcore.c @@ -70,7 +70,7 @@ struct __GLXMESAdrawable { XMesaBuffer xm_buf; }; -static XMesaVisual find_mesa_visual(__GLXscreen *screen, VisualID vid); +static XMesaVisual find_mesa_visual(__GLXscreen *screen, XID fbconfigID); static void @@ -118,7 +118,7 @@ __glXMesaDrawableSwapBuffers(__GLXdrawable *base) static __GLXdrawable * __glXMesaScreenCreateDrawable(__GLXscreen *screen, - DrawablePtr pDraw, + DrawablePtr pDraw, int type, XID drawId, __GLcontextModes *modes) { @@ -131,7 +131,8 @@ __glXMesaScreenCreateDrawable(__GLXscreen *screen, memset(glxPriv, 0, sizeof *glxPriv); - if (!__glXDrawableInit(&glxPriv->base, screen, pDraw, drawId, modes)) { + if (!__glXDrawableInit(&glxPriv->base, screen, + pDraw, type, drawId, modes)) { xfree(glxPriv); return NULL; } @@ -140,7 +141,7 @@ __glXMesaScreenCreateDrawable(__GLXscreen *screen, glxPriv->base.resize = __glXMesaDrawableResize; glxPriv->base.swapBuffers = __glXMesaDrawableSwapBuffers; - xm_vis = find_mesa_visual(screen, modes->visualID); + xm_vis = find_mesa_visual(screen, modes->fbconfigID); if (xm_vis == NULL) { ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n", modes->visualID); @@ -154,6 +155,11 @@ __glXMesaScreenCreateDrawable(__GLXscreen *screen, glxPriv->xm_buf = XMesaCreatePixmapBuffer(xm_vis, (PixmapPtr)pDraw, 0); } + if (glxPriv->xm_buf == NULL) { + xfree(glxPriv); + return NULL; + } + return &glxPriv->base; } @@ -234,7 +240,7 @@ __glXMesaScreenCreateContext(__GLXscreen *screen, context->base.copy = __glXMesaContextCopy; context->base.forceCurrent = __glXMesaContextForceCurrent; - xm_vis = find_mesa_visual(screen, modes->visualID); + xm_vis = find_mesa_visual(screen, modes->fbconfigID); if (!xm_vis) { ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n", modes->visualID); @@ -273,107 +279,122 @@ __glXMesaScreenDestroy(__GLXscreen *screen) } static XMesaVisual -find_mesa_visual(__GLXscreen *screen, VisualID vid) +find_mesa_visual(__GLXscreen *screen, XID fbconfigID) { __GLXMESAscreen *mesaScreen = (__GLXMESAscreen *) screen; const __GLcontextModes *modes; unsigned i = 0; - for ( modes = screen->modes ; modes != NULL ; modes = modes->next ) { - if ( modes->visualID == vid ) { - break; - } - + for (modes = screen->fbconfigs; modes != NULL; modes = modes->next) { + if (modes->fbconfigID == fbconfigID) + return mesaScreen->xm_vis[i]; i++; } - return (modes != NULL) ? mesaScreen->xm_vis[i] : NULL; + return NULL; } -static void init_screen_visuals(__GLXMESAscreen *screen) +const static int numBack = 2; +const static int numDepth = 2; +const static int numStencil = 2; + +static __GLcontextModes * +createFBConfigsForVisual(__GLXscreen *screen, ScreenPtr pScreen, + VisualPtr visual, __GLcontextModes *config) { - ScreenPtr pScreen = screen->base.pScreen; - __GLcontextModes *modes; - XMesaVisual *pXMesaVisual; - int *used; - int num_vis, j, size; + int back, depth, stencil; - /* Alloc space for the list of XMesa visuals */ - size = screen->base.numVisuals * sizeof(XMesaVisual); - pXMesaVisual = (XMesaVisual *) xalloc(size); - memset(pXMesaVisual, 0, size); + /* FIXME: Ok, I'm making all this up... anybody has a better idea? */ - /* 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)); + for (back = numBack - 1; back >= 0; back--) + for (depth = 0; depth < numDepth; depth++) + for (stencil = 0; stencil < numStencil; stencil++) { + config->visualType = _gl_convert_from_x_visual_type(visual->class); + config->xRenderable = GL_TRUE; + config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT; + config->rgbMode = (visual->class >= TrueColor); + config->colorIndexMode = !config->rgbMode; + config->renderType = + (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; + config->doubleBufferMode = back; + config->haveDepthBuffer = depth; + config->depthBits = depth ? visual->nplanes : 0; + config->haveStencilBuffer = stencil; + config->stencilBits = stencil ? visual->bitsPerRGBValue : 0; + config->haveAccumBuffer = 0; - num_vis = 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; + config->redBits = Ones(visual->redMask); + config->greenBits = Ones(visual->greenMask); + config->blueBits = Ones(visual->blueMask); + config->alphaBits = 0; + config->redMask = visual->redMask; + config->greenMask = visual->greenMask; + config->blueMask = visual->blueMask; + config->alphaMask = 0; + config->rgbBits = config->rgbMode ? visual->nplanes : 0; + config->indexBits = config->colorIndexMode ? visual->nplanes : 0; + config = config->next; + } - 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]) { + return config; +} - /* Create the XMesa visual */ - assert(num_vis < screen->base.numVisuals); - pXMesaVisual[num_vis] = - 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; +static void +createFBConfigs(__GLXscreen *pGlxScreen, ScreenPtr pScreen) +{ + __GLcontextModes *configs; + int i; - /* Mark this visual used */ - used[j] = 1; + /* We assume here that each existing visual correspond to a + * different visual class. Note, this runs before COMPOSITE adds + * its visual, so it's not entirely crazy. */ + pGlxScreen->numFBConfigs = pScreen->numVisuals * numBack * numDepth * numStencil; + pGlxScreen->fbconfigs = _gl_context_modes_create(pGlxScreen->numFBConfigs, + sizeof *configs); + + configs = pGlxScreen->fbconfigs; + for (i = 0; i < pScreen->numVisuals; i++) + configs = createFBConfigsForVisual(pGlxScreen, pScreen, + &pScreen->visuals[i], configs); +} + +static void +createMesaVisuals(__GLXMESAscreen *pMesaScreen) +{ + __GLcontextModes *config; + ScreenPtr pScreen; + VisualPtr visual; + int i, j; + + i = 0; + pScreen = pMesaScreen->base.pScreen; + pMesaScreen->xm_vis = + xcalloc(pMesaScreen->base.numFBConfigs, sizeof (XMesaVisual)); + for (config = pMesaScreen->base.fbconfigs; config != NULL; config = config->next) { + for (j = 0; j < pScreen->numVisuals; j++) + if (pScreen->visuals[j].vid == config->visualID) { + visual = &pScreen->visuals[j]; 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" ); - } - - num_vis++; + pMesaScreen->xm_vis[i++] = + XMesaCreateVisual(pScreen, + visual, + config->rgbMode, + (config->alphaBits > 0), + config->doubleBufferMode, + config->stereoMode, + GL_TRUE, /* ximage_flag */ + config->depthBits, + config->stencilBits, + config->accumRedBits, + config->accumGreenBits, + config->accumBlueBits, + config->accumAlphaBits, + config->samples, + config->level, + config->visualRating); } - - xfree(used); - - screen->num_vis = num_vis; - screen->xm_vis = pXMesaVisual; - - assert(screen->num_vis <= screen->base.numVisuals); } static __GLXscreen * @@ -385,19 +406,22 @@ __glXMesaScreenProbe(ScreenPtr pScreen) if (screen == NULL) return NULL; + /* + * Find the GLX visuals that are supported by this screen and create + * XMesa's visuals. + */ + createFBConfigs(&screen->base, pScreen); + __glXScreenInit(&screen->base, pScreen); + /* Now that GLX has created the corresponding X visual, create the mesa visuals. */ + createMesaVisuals(screen); + 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; } diff --git a/GL/glx/glxscreens.c b/GL/glx/glxscreens.c index 43447a4e4..2c8f810e6 100644 --- a/GL/glx/glxscreens.c +++ b/GL/glx/glxscreens.c @@ -40,10 +40,14 @@ #include #include #include +#include #include "glxserver.h" #include "glxutil.h" #include "glxext.h" +#include "glcontextmodes.h" + +static int glxScreenPrivateIndex; const char GLServerVersion[] = "1.4"; static const char GLServerExtensions[] = @@ -179,36 +183,25 @@ static char GLXServerExtensions[] = "GLX_MESA_copy_sub_buffer " ; -__GLXscreen **__glXActiveScreens; - -__GLXSwapBarrierExtensionFuncs *__glXSwapBarrierFuncs = NULL; -static int __glXNumSwapBarrierFuncs = 0; -__GLXHyperpipeExtensionFuncs *__glXHyperpipeFuncs = NULL; -static int __glXNumHyperpipeFuncs = 0; - -__GLXscreen *__glXgetActiveScreen(int num) { - return __glXActiveScreens[num]; -} - - /* ** This hook gets called when a window moves or changes size. */ -static Bool PositionWindow(WindowPtr pWin, int x, int y) +static Bool glxPositionWindow(WindowPtr pWin, int x, int y) { ScreenPtr pScreen; __GLXcontext *glxc; __GLXdrawable *glxPriv; Bool ret; + __GLXscreen *pGlxScreen; /* ** Call wrapped position window routine */ pScreen = pWin->drawable.pScreen; - pScreen->PositionWindow = - __glXActiveScreens[pScreen->myNum]->WrappedPositionWindow; + pGlxScreen = glxGetScreen(pScreen); + pScreen->PositionWindow = pGlxScreen->PositionWindow; ret = (*pScreen->PositionWindow)(pWin, x, y); - pScreen->PositionWindow = PositionWindow; + pScreen->PositionWindow = glxPositionWindow; /* ** Tell all contexts rendering into this window that the window size @@ -259,110 +252,299 @@ static Bool PositionWindow(WindowPtr pWin, int x, int y) void __glXHyperpipeInit(int screen, __GLXHyperpipeExtensionFuncs *funcs) { - if (__glXNumHyperpipeFuncs < screen + 1) { - __glXHyperpipeFuncs = xrealloc(__glXHyperpipeFuncs, - (screen+1) * sizeof(__GLXHyperpipeExtensionFuncs)); - __glXNumHyperpipeFuncs = screen + 1; - } + __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]); - __glXHyperpipeFuncs[screen].queryHyperpipeNetworkFunc = - *funcs->queryHyperpipeNetworkFunc; - __glXHyperpipeFuncs[screen].queryHyperpipeConfigFunc = - *funcs->queryHyperpipeConfigFunc; - __glXHyperpipeFuncs[screen].destroyHyperpipeConfigFunc = - *funcs->destroyHyperpipeConfigFunc; - __glXHyperpipeFuncs[screen].hyperpipeConfigFunc = - *funcs->hyperpipeConfigFunc; + pGlxScreen->hyperpipeFuncs = funcs; } void __glXSwapBarrierInit(int screen, __GLXSwapBarrierExtensionFuncs *funcs) { - if (__glXNumSwapBarrierFuncs < screen + 1) { - __glXSwapBarrierFuncs = xrealloc(__glXSwapBarrierFuncs, - (screen+1) * sizeof(__GLXSwapBarrierExtensionFuncs)); - __glXNumSwapBarrierFuncs = screen + 1; + __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]); + + pGlxScreen->swapBarrierFuncs = funcs; +} + +static Bool +glxCloseScreen (int index, ScreenPtr pScreen) +{ + __GLXscreen *pGlxScreen = glxGetScreen(pScreen); + + pScreen->CloseScreen = pGlxScreen->CloseScreen; + pScreen->PositionWindow = pGlxScreen->PositionWindow; + + pGlxScreen->destroy(pGlxScreen); + + return pScreen->CloseScreen(index, pScreen); +} + +__GLXscreen * +glxGetScreen(ScreenPtr pScreen) +{ + return (__GLXscreen *) pScreen->devPrivates[glxScreenPrivateIndex].ptr; +} + +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates) +{ + /* We keep this stub around for the DDX drivers that still + * call it. */ +} + +static XID +findVisualForConfig(ScreenPtr pScreen, __GLcontextModes *m) +{ + int i; + + for (i = 0; i < pScreen->numVisuals; i++) { + if (_gl_convert_to_x_visual_type(m->visualType) == pScreen->visuals[i].class) + return pScreen->visuals[i].vid; } - __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc = - funcs->bindSwapBarrierFunc; - __glXSwapBarrierFuncs[screen].queryMaxSwapBarriersFunc = - funcs->queryMaxSwapBarriersFunc; + return 0; } -static __GLXprovider *__glXProviderStack; +/* This code inspired by composite/compinit.c. We could move this to + * mi/ and share it with composite.*/ -void GlxPushProvider(__GLXprovider *provider) +static VisualPtr +AddScreenVisuals(ScreenPtr pScreen, int count, int d) { - provider->next = __glXProviderStack; - __glXProviderStack = provider; + XID *installedCmaps, *vids, vid; + int numInstalledCmaps, numVisuals, i, j; + VisualPtr visuals; + ColormapPtr installedCmap; + DepthPtr depth; + + depth = NULL; + for (i = 0; i < pScreen->numDepths; i++) { + if (pScreen->allowedDepths[i].depth == d) { + depth = &pScreen->allowedDepths[i]; + break; + } + } + if (depth == NULL) + return NULL; + + /* Find the installed colormaps */ + installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID)); + if (!installedCmaps) + return NULL; + + numInstalledCmaps = pScreen->ListInstalledColormaps(pScreen, installedCmaps); + + /* realloc the visual array to fit the new one in place */ + numVisuals = pScreen->numVisuals; + visuals = xrealloc(pScreen->visuals, (numVisuals + count) * sizeof(VisualRec)); + if (!visuals) { + xfree(installedCmaps); + return NULL; + } + + vids = xrealloc(depth->vids, (depth->numVids + count) * sizeof(XID)); + if (vids == NULL) { + xfree(installedCmaps); + xfree(visuals); + return NULL; + } + + /* + * Fix up any existing installed colormaps -- we'll assume that + * the only ones created so far have been installed. If this + * isn't true, we'll have to walk the resource database looking + * for all colormaps. + */ + for (i = 0; i < numInstalledCmaps; i++) { + installedCmap = LookupIDByType (installedCmaps[i], RT_COLORMAP); + if (!installedCmap) + continue; + j = installedCmap->pVisual - pScreen->visuals; + installedCmap->pVisual = &visuals[j]; + } + + xfree(installedCmaps); + + for (i = 0; i < count; i++) { + vid = FakeClientID(0); + visuals[pScreen->numVisuals + i].vid = vid; + vids[depth->numVids + i] = vid; + } + + pScreen->visuals = visuals; + pScreen->numVisuals += count; + depth->vids = vids; + depth->numVids += count; + + /* Return a pointer to the first of the added visuals. */ + return pScreen->visuals + pScreen->numVisuals - count; } -void __glXScreenInit(__GLXscreen *screen, ScreenPtr pScreen) +static int +findFirstSet(unsigned int v) { - screen->pScreen = pScreen; - screen->GLextensions = xstrdup(GLServerExtensions); - screen->GLXvendor = xstrdup(GLXServerVendorName); - screen->GLXversion = xstrdup(GLXServerVersion); - screen->GLXextensions = xstrdup(GLXServerExtensions); + int i; - screen->WrappedPositionWindow = pScreen->PositionWindow; - pScreen->PositionWindow = PositionWindow; + for (i = 0; i < 32; i++) + if (v & (1 << i)) + return i; - __glXScreenInitVisuals(screen); + return -1; } -void -__glXScreenDestroy(__GLXscreen *screen) +static void +initGlxVisual(VisualPtr visual, __GLcontextModes *config) +{ + config->visualID = visual->vid; + visual->class = _gl_convert_to_x_visual_type(config->visualType); + visual->bitsPerRGBValue = config->redBits; + visual->ColormapEntries = 1 << config->redBits; + visual->nplanes = config->redBits + config->greenBits + config->blueBits; + + visual->redMask = config->redMask; + visual->greenMask = config->greenMask; + visual->blueMask = config->blueMask; + visual->offsetRed = findFirstSet(config->redMask); + visual->offsetGreen = findFirstSet(config->greenMask); + visual->offsetBlue = findFirstSet(config->blueMask); +} + +static void +addMinimalSet(__GLXscreen *pGlxScreen) +{ + __GLcontextModes *config; + VisualPtr visuals; + int depth; + + for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { + if (config->visualRating != GLX_NONE) + continue; + if (config->doubleBufferMode && config->depthBits > 0) + break; + } + if (config == NULL) + config = pGlxScreen->fbconfigs; + + pGlxScreen->visuals = xcalloc(1, sizeof (__GLcontextModes *)); + if (pGlxScreen->visuals == NULL) { + ErrorF("Failed to allocate for minimal set of GLX visuals\n"); + return; + } + + depth = config->redBits + config->greenBits + config->blueBits; + visuals = AddScreenVisuals(pGlxScreen->pScreen, 1, depth); + if (visuals == NULL) { + xfree(pGlxScreen->visuals); + return; + } + + pGlxScreen->numVisuals = 1; + pGlxScreen->visuals[0] = config; + initGlxVisual(&visuals[0], config); +} + +static void +addTypicalSet(__GLXscreen *pGlxScreen) +{ + addMinimalSet(pGlxScreen); +} + +static void +addFullSet(__GLXscreen *pGlxScreen) +{ + __GLcontextModes *config; + VisualPtr visuals; + int i, depth; + + pGlxScreen->visuals = + xcalloc(pGlxScreen->numFBConfigs, sizeof (__GLcontextModes *)); + if (pGlxScreen->visuals == NULL) { + ErrorF("Failed to allocate for full set of GLX visuals\n"); + return; + } + + config = pGlxScreen->fbconfigs; + depth = config->redBits + config->greenBits + config->blueBits; + visuals = AddScreenVisuals(pGlxScreen->pScreen, pGlxScreen->numFBConfigs, depth); + if (visuals == NULL) { + xfree(pGlxScreen->visuals); + return; + } + + pGlxScreen->numVisuals = pGlxScreen->numFBConfigs; + for (i = 0, config = pGlxScreen->fbconfigs; config; config = config->next, i++) { + pGlxScreen->visuals[i] = config; + initGlxVisual(&visuals[i], config); + } +} + +static int glxVisualConfig = GLX_ALL_VISUALS; + +void GlxSetVisualConfig(int config) +{ + glxVisualConfig = config; +} + +void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen) +{ + static int glxGeneration; + __GLcontextModes *m; + int i; + + if (glxGeneration != serverGeneration) + { + glxScreenPrivateIndex = AllocateScreenPrivateIndex (); + if (glxScreenPrivateIndex == -1) + return; + + glxGeneration = serverGeneration; + } + + pGlxScreen->pScreen = pScreen; + pGlxScreen->GLextensions = xstrdup(GLServerExtensions); + pGlxScreen->GLXvendor = xstrdup(GLXServerVendorName); + pGlxScreen->GLXversion = xstrdup(GLXServerVersion); + pGlxScreen->GLXextensions = xstrdup(GLXServerExtensions); + + pGlxScreen->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = glxPositionWindow; + + pGlxScreen->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = glxCloseScreen; + + i = 0; + for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) { + m->fbconfigID = FakeClientID(0); + m->visualID = findVisualForConfig(pScreen, m); + ErrorF("mapping fbconfig id 0x%02lx to visual id 0x%02lx\n", + m->fbconfigID, m->visualID); + i++; + } + pGlxScreen->numFBConfigs = i; + + /* Select a subset of fbconfigs that we send to the client when it + * asks for the glx visuals. All the fbconfigs here have a valid + * value for visual ID and each visual ID is only present once. + * This runs before composite adds its extra visual so we have to + * remember the number of visuals here.*/ + + switch (glxVisualConfig) { + case GLX_MINIMAL_VISUALS: + addMinimalSet(pGlxScreen); + break; + case GLX_TYPICAL_VISUALS: + addTypicalSet(pGlxScreen); + break; + case GLX_ALL_VISUALS: + addFullSet(pGlxScreen); + break; + } + + pScreen->devPrivates[glxScreenPrivateIndex].ptr = (pointer) pGlxScreen; +} + +void __glXScreenDestroy(__GLXscreen *screen) { xfree(screen->GLXvendor); xfree(screen->GLXversion); xfree(screen->GLXextensions); xfree(screen->GLextensions); } - -void __glXInitScreens(void) -{ - GLint i; - ScreenPtr pScreen; - __GLXprovider *p; - size_t size; - - /* - ** This alloc has to work or else the server might as well core dump. - */ - size = screenInfo.numScreens * sizeof(__GLXscreen *); - __glXActiveScreens = xalloc(size); - memset(__glXActiveScreens, 0, size); - - for (i = 0; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - - for (p = __glXProviderStack; p != NULL; p = p->next) { - __glXActiveScreens[i] = p->screenProbe(pScreen); - if (__glXActiveScreens[i] != NULL) { - LogMessage(X_INFO, - "GLX: Initialized %s GL provider for screen %d\n", - p->name, i); - break; - } - } - } -} - -void __glXResetScreens(void) -{ - int i; - - for (i = 0; i < screenInfo.numScreens; i++) - if (__glXActiveScreens[i]) - __glXActiveScreens[i]->destroy(__glXActiveScreens[i]); - - xfree(__glXActiveScreens); - xfree(__glXHyperpipeFuncs); - xfree(__glXSwapBarrierFuncs); - __glXNumHyperpipeFuncs = 0; - __glXNumSwapBarrierFuncs = 0; - __glXHyperpipeFuncs = NULL; - __glXSwapBarrierFuncs = NULL; - __glXActiveScreens = NULL; -} diff --git a/GL/glx/glxscreens.h b/GL/glx/glxscreens.h index bba45572f..f1eef912c 100644 --- a/GL/glx/glxscreens.h +++ b/GL/glx/glxscreens.h @@ -42,6 +42,21 @@ #include "GL/internal/glcore.h" +typedef struct { + void * (* queryHyperpipeNetworkFunc)(int, int *, int *); + void * (* queryHyperpipeConfigFunc)(int, int, int *, int *); + int (* destroyHyperpipeConfigFunc)(int, int); + void * (* hyperpipeConfigFunc)(int, int, int *, int *, void *); +} __GLXHyperpipeExtensionFuncs; + +typedef struct { + int (* bindSwapBarrierFunc)(int, XID, int); + int (* queryMaxSwapBarriersFunc)(int); +} __GLXSwapBarrierExtensionFuncs; + +void __glXHyperpipeInit(int screen, __GLXHyperpipeExtensionFuncs *funcs); +void __glXSwapBarrierInit(int screen, __GLXSwapBarrierExtensionFuncs *funcs); + /* ** Screen dependent data. These methods are the interface between the DIX ** and DDX layers of the GLX server extension. The methods provide an @@ -57,21 +72,24 @@ struct __GLXscreen { __GLXdrawable *(*createDrawable)(__GLXscreen *context, DrawablePtr pDraw, + int type, XID drawId, __GLcontextModes *modes); int (*swapInterval) (__GLXdrawable *drawable, int interval); + __GLXHyperpipeExtensionFuncs *hyperpipeFuncs; + __GLXSwapBarrierExtensionFuncs *swapBarrierFuncs; + ScreenPtr pScreen; - /** - * Linked list of valid context modes for this screen. - */ - __GLcontextModes *modes; + /* Linked list of valid fbconfigs for this screen. */ + __GLcontextModes *fbconfigs; + int numFBConfigs; - void **pVisualPriv; + /* Subset of fbconfigs that are exposed as GLX visuals. */ + __GLcontextModes **visuals; GLint numVisuals; - GLint numUsableVisuals; char *GLextensions; @@ -79,18 +97,12 @@ struct __GLXscreen { char *GLXversion; char *GLXextensions; - /* - ** Things that are not statically set. - */ - Bool (*WrappedPositionWindow)(WindowPtr pWin, int x, int y); - + Bool (*PositionWindow)(WindowPtr pWin, int x, int y); + Bool (*CloseScreen)(int index, ScreenPtr pScreen); }; void __glXScreenInit(__GLXscreen *screen, ScreenPtr pScreen); void __glXScreenDestroy(__GLXscreen *screen); -void __glXInitScreens(void); -extern void __glXResetScreens(void); - #endif /* !__GLX_screens_h__ */ diff --git a/GL/glx/glxserver.h b/GL/glx/glxserver.h index b6b55927e..518868981 100644 --- a/GL/glx/glxserver.h +++ b/GL/glx/glxserver.h @@ -90,12 +90,13 @@ typedef XID GLXDrawable; typedef struct __GLXclientStateRec __GLXclientState; -extern __GLXscreen **__glXActiveScreens; -extern GLint __glXNumActiveScreens; -extern __GLXscreen *__glXgetActiveScreen(int num); +extern __GLXscreen *glxGetScreen(ScreenPtr pScreen); +extern __GLXclientState *glxGetClient(ClientPtr pClient); /************************************************************************/ +void GlxExtensionInit(void); + void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, void **privates); @@ -133,6 +134,14 @@ struct __GLXprovider { void GlxPushProvider(__GLXprovider *provider); +enum { + GLX_MINIMAL_VISUALS, + GLX_TYPICAL_VISUALS, + GLX_ALL_VISUALS +}; + +void GlxSetVisualConfig(int config); + void __glXsetEnterLeaveServerFuncs(void (*enter)(GLboolean), void (*leave)(GLboolean)); void __glXenterServer(GLboolean rendering); diff --git a/GL/glx/glxutil.c b/GL/glx/glxutil.c index 1f172929f..f531ed954 100644 --- a/GL/glx/glxutil.c +++ b/GL/glx/glxutil.c @@ -139,18 +139,15 @@ __glXUnrefDrawable(__GLXdrawable *glxPriv) GLboolean __glXDrawableInit(__GLXdrawable *drawable, - __GLXscreen *screen, DrawablePtr pDraw, XID drawId, - __GLcontextModes *modes) + __GLXscreen *screen, DrawablePtr pDraw, int type, + XID drawId, __GLcontextModes *modes) { - drawable->type = pDraw->type; drawable->pDraw = pDraw; + drawable->type = type; drawable->drawId = drawId; drawable->refCount = 1; drawable->modes = modes; - - /* if not a pixmap, lookup will fail, so pGlxPixmap will be NULL */ - drawable->pGlxPixmap = (__GLXpixmap *) - LookupIDByType(drawId, __glXPixmapRes); + drawable->eventMask = 0; return GL_TRUE; } diff --git a/GL/glx/glxutil.h b/GL/glx/glxutil.h index 1937ef2cf..6534c3f94 100644 --- a/GL/glx/glxutil.h +++ b/GL/glx/glxutil.h @@ -50,7 +50,7 @@ extern void __glXUnrefDrawable(__GLXdrawable *glxPriv); extern GLboolean __glXDrawableInit(__GLXdrawable *drawable, __GLXscreen *screen, - DrawablePtr pDraw, XID drawID, + DrawablePtr pDraw, int type, XID drawID, __GLcontextModes *modes); /* context helper routines */ diff --git a/GL/glx/glxvisuals.c b/GL/glx/glxvisuals.c deleted file mode 100644 index 0e9bdedec..000000000 --- a/GL/glx/glxvisuals.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright © 2006 Red Hat, Inc. - * (C) 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 - * RED HAT, INC, OR PRECISION INSIGHT AND/OR THEIR 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 - * Brian Paul - * Kristian Høgsberg - * - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void GlxWrapInitVisuals(miInitVisualsProcPtr *); - -#include "glcontextmodes.h" - -struct ScreenVisualsRec { - int num_vis; - void *private; - __GLcontextModes *modes; -}; -typedef struct ScreenVisualsRec ScreenVisuals; - -static ScreenVisuals screenVisuals[MAXSCREENS]; - -static int numConfigs = 0; -static __GLXvisualConfig *visualConfigs = NULL; -static void **visualPrivates = NULL; - -static int count_bits(unsigned int n) -{ - int bits = 0; - - while (n > 0) { - if (n & 1) bits++; - n >>= 1; - } - return bits; -} - -/* - * In the case the driver defines no GLX visuals we'll use these. - * Note that for TrueColor and DirectColor visuals, bufferSize is the - * sum of redSize, greenSize, blueSize and alphaSize, which may be larger - * than the nplanes/rootDepth of the server's X11 visuals - */ -#define NUM_FALLBACK_CONFIGS 5 -static __GLXvisualConfig FallbackConfigs[NUM_FALLBACK_CONFIGS] = { - /* [0] = RGB, double buffered, Z */ - { - -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, /* visualRating */ - GLX_NONE, /* transparentPixel */ - 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */ - 0 /* transparentIndex */ - }, - /* [1] = RGB, double buffered, Z, stencil, accum */ - { - -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, /* visualRating */ - GLX_NONE, /* transparentPixel */ - 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */ - 0 /* transparentIndex */ - }, - /* [2] = RGB+Alpha, double buffered, Z, stencil, accum */ - { - -1, /* vid */ - -1, /* class */ - True, /* rgba */ - -1, -1, -1, 8, /* rgba sizes */ - -1, -1, -1, -1, /* rgba masks */ - 16, 16, 16, 16, /* rgba accum sizes */ - True, /* doubleBuffer */ - False, /* stereo */ - -1, /* bufferSize */ - 16, /* depthSize */ - 8, /* stencilSize */ - 0, /* auxBuffers */ - 0, /* level */ - GLX_NONE, /* visualRating */ - GLX_NONE, /* transparentPixel */ - 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */ - 0 /* transparentIndex */ - }, - /* [3] = RGB+Alpha, single buffered, Z, stencil, accum */ - { - -1, /* vid */ - -1, /* class */ - True, /* rgba */ - -1, -1, -1, 8, /* rgba sizes */ - -1, -1, -1, -1, /* rgba masks */ - 16, 16, 16, 16, /* rgba accum sizes */ - False, /* doubleBuffer */ - False, /* stereo */ - -1, /* bufferSize */ - 16, /* depthSize */ - 8, /* stencilSize */ - 0, /* auxBuffers */ - 0, /* level */ - GLX_NONE, /* visualRating */ - GLX_NONE, /* transparentPixel */ - 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */ - 0 /* transparentIndex */ - }, - /* [4] = CI, double buffered, Z */ - { - -1, /* vid */ - -1, /* class */ - False, /* rgba? (false = color index) */ - -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, /* visualRating */ - GLX_NONE, /* transparentPixel */ - 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */ - 0 /* transparentIndex */ - }, -}; - - -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; - __GLXvisualConfig *pNewVisualConfigs = NULL; - void **glXVisualPriv; - void **pNewVisualPriv; - int found_default; - int i, j, k; - - if (numConfigs > 0) - numNewConfigs = numConfigs; - else - numNewConfigs = NUM_FALLBACK_CONFIGS; - - /* Alloc space for the list of new GLX visuals */ - pNewVisualConfigs = (__GLXvisualConfig *) - xalloc(numNewConfigs * sizeof(__GLXvisualConfig)); - if (!pNewVisualConfigs) { - return FALSE; - } - - /* Alloc space for the list of new GLX visual privates */ - pNewVisualPriv = (void **) xalloc(numNewConfigs * sizeof(void *)); - if (!pNewVisualPriv) { - xfree(pNewVisualConfigs); - return FALSE; - } - - /* - ** 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]; - } - } - - /* Count the number of RGB and CI visual configs */ - numRGBconfigs = 0; - numCIconfigs = 0; - for (i = 0; i < numNewConfigs; i++) { - if (pNewVisualConfigs[i].rgba) - numRGBconfigs++; - else - numCIconfigs++; - } - - /* Count the total number of visuals to compute */ - numNewVisuals = 0; - for (i = 0; i < numVisuals; i++) { - numNewVisuals += - (pVisual[i].class == TrueColor || pVisual[i].class == DirectColor) - ? numRGBconfigs : numCIconfigs; - } - - /* Reset variables for use with the next screen/driver's visual configs */ - visualConfigs = NULL; - numConfigs = 0; - - /* Alloc temp space for the list of orig VisualIDs for each new visual */ - orig_vid = (VisualID *) xalloc(numNewVisuals * sizeof(VisualID)); - if (!orig_vid) { - xfree(pNewVisualPriv); - xfree(pNewVisualConfigs); - return FALSE; - } - - /* Alloc space for the list of glXVisuals */ - modes = _gl_context_modes_create(numNewVisuals, sizeof(__GLcontextModes)); - if (modes == NULL) { - xfree(orig_vid); - xfree(pNewVisualPriv); - xfree(pNewVisualConfigs); - return FALSE; - } - - /* Alloc space for the list of glXVisualPrivates */ - glXVisualPriv = (void **)xalloc(numNewVisuals * sizeof(void *)); - if (!glXVisualPriv) { - _gl_context_modes_destroy( modes ); - xfree(orig_vid); - xfree(pNewVisualPriv); - xfree(pNewVisualConfigs); - return FALSE; - } - - /* Alloc space for the new list of the X server's visuals */ - pVisualNew = (VisualPtr)xalloc(numNewVisuals * sizeof(VisualRec)); - if (!pVisualNew) { - xfree(glXVisualPriv); - _gl_context_modes_destroy( modes ); - xfree(orig_vid); - xfree(pNewVisualPriv); - xfree(pNewVisualConfigs); - return FALSE; - } - - /* Initialize the new visuals */ - found_default = FALSE; - screenVisuals[screenInfo.numScreens-1].modes = modes; - for (i = j = 0; i < numVisuals; i++) { - int is_rgb = (pVisual[i].class == TrueColor || - pVisual[i].class == DirectColor); - - for (k = 0; k < numNewConfigs; k++) { - if (pNewVisualConfigs[k].rgba != is_rgb) - continue; - - assert( modes != NULL ); - - /* Initialize the new visual */ - pVisualNew[j] = pVisual[i]; - pVisualNew[j].vid = FakeClientID(0); - - /* Check for the default visual */ - if (!found_default && pVisual[i].vid == *defaultVisp) { - *defaultVisp = pVisualNew[j].vid; - found_default = TRUE; - } - - /* 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 (modes->fbconfigID == GLX_DONT_CARE) - modes->fbconfigID = modes->visualID; - - /* - * 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; - } - - /* Save the device-dependent private for this visual */ - glXVisualPriv[j] = pNewVisualPriv[k]; - - j++; - modes = modes->next; - } - } - - assert(j <= numNewVisuals); - - /* Save the GLX visuals in the screen structure */ - screenVisuals[screenInfo.numScreens-1].num_vis = numNewVisuals; - screenVisuals[screenInfo.numScreens-1].private = 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 *)xalloc(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 */ - xfree(pdepth[i].vids); - pdepth[i].vids = pVids; - pdepth[i].numVids = numVids; - } - - /* Update the X server's visuals */ - *nvisualp = numNewVisuals; - *visualp = pVisualNew; - - /* Free the old list of the X server's visuals */ - xfree(pVisual); - - /* Clean up temporary allocations */ - xfree(orig_vid); - xfree(pNewVisualPriv); - xfree(pNewVisualConfigs); - - /* Free the private list created by DDX HW driver */ - if (visualPrivates) - xfree(visualPrivates); - visualPrivates = NULL; - - return TRUE; -} - -void GlxSetVisualConfigs(int nconfigs, - __GLXvisualConfig *configs, void **privates) -{ - numConfigs = nconfigs; - visualConfigs = configs; - visualPrivates = privates; -} - -static miInitVisualsProcPtr saveInitVisualsProc; - -Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, - int *nvisualp, int *ndepthp, - int *rootDepthp, VisualID *defaultVisp, - unsigned long sizes, int bitsPerRGB, - int preferredVis) -{ - Bool ret; - - if (saveInitVisualsProc) { - ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, - rootDepthp, defaultVisp, sizes, bitsPerRGB, - preferredVis); - if (!ret) - return False; - } - - /* - * Setup the visuals supported by this particular screen. - */ - init_visuals(nvisualp, visualp, defaultVisp, - *ndepthp, *depthp, *rootDepthp); - - - return True; -} - - -/************************************************************************/ - - -void -GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) -{ - saveInitVisualsProc = *initVisProc; - *initVisProc = GlxInitVisuals; -} - -static void fixup_visuals(int screen) -{ - ScreenPtr pScreen = screenInfo.screens[screen]; - ScreenVisuals *psv = &screenVisuals[screen]; - int j; - __GLcontextModes *modes; - - for ( modes = psv->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; - - /* 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); - } - } - } -} - -void __glXScreenInitVisuals(__GLXscreen *screen) -{ - int index = screen->pScreen->myNum; - - screen->modes = screenVisuals[index].modes; - screen->pVisualPriv = screenVisuals[index].private; - screen->numVisuals = screenVisuals[index].num_vis; - screen->numUsableVisuals = screenVisuals[index].num_vis; - - /* - * The ordering of the rgb compenents might have been changed by the - * driver after mi initialized them. - */ - fixup_visuals(index); -} diff --git a/GL/glx/indirect_dispatch.h b/GL/glx/indirect_dispatch.h index 24f4bed43..bb39638fd 100644 --- a/GL/glx/indirect_dispatch.h +++ b/GL/glx/indirect_dispatch.h @@ -207,6 +207,8 @@ extern HIDDEN void __glXDisp_TexCoord2iv(GLbyte * pc); extern HIDDEN void __glXDispSwap_TexCoord2iv(GLbyte * pc); extern HIDDEN void __glXDisp_CompressedTexImage1DARB(GLbyte * pc); extern HIDDEN void __glXDispSwap_CompressedTexImage1DARB(GLbyte * pc); +extern HIDDEN void __glXDisp_Rotated(GLbyte * pc); +extern HIDDEN void __glXDispSwap_Rotated(GLbyte * pc); extern HIDDEN int __glXDisp_ReadPixels(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN int __glXDispSwap_ReadPixels(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN void __glXDisp_EdgeFlagv(GLbyte * pc); @@ -293,8 +295,8 @@ extern HIDDEN void __glXDisp_ClearIndex(GLbyte * pc); extern HIDDEN void __glXDispSwap_ClearIndex(GLbyte * pc); extern HIDDEN void __glXDisp_LoadMatrixd(GLbyte * pc); extern HIDDEN void __glXDispSwap_LoadMatrixd(GLbyte * pc); -extern HIDDEN void __glXDisp_RasterPos2dv(GLbyte * pc); -extern HIDDEN void __glXDispSwap_RasterPos2dv(GLbyte * pc); +extern HIDDEN void __glXDisp_PushMatrix(GLbyte * pc); +extern HIDDEN void __glXDispSwap_PushMatrix(GLbyte * pc); extern HIDDEN void __glXDisp_ConvolutionParameterfv(GLbyte * pc); extern HIDDEN void __glXDispSwap_ConvolutionParameterfv(GLbyte * pc); extern HIDDEN int __glXDisp_GetTexGendv(struct __GLXclientStateRec *, GLbyte *); @@ -371,14 +373,16 @@ extern HIDDEN void __glXDisp_ProgramNamedParameter4fvNV(GLbyte * pc); extern HIDDEN void __glXDispSwap_ProgramNamedParameter4fvNV(GLbyte * pc); extern HIDDEN void __glXDisp_VertexAttrib4fvARB(GLbyte * pc); extern HIDDEN void __glXDispSwap_VertexAttrib4fvARB(GLbyte * pc); +extern HIDDEN int __glXDisp_CreateGLXPbufferSGIX(struct __GLXclientStateRec *, GLbyte *); +extern HIDDEN int __glXDispSwap_CreateGLXPbufferSGIX(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN void __glXDisp_MultiTexCoord1svARB(GLbyte * pc); extern HIDDEN void __glXDispSwap_MultiTexCoord1svARB(GLbyte * pc); extern HIDDEN void __glXDisp_EndQueryARB(GLbyte * pc); extern HIDDEN void __glXDispSwap_EndQueryARB(GLbyte * pc); extern HIDDEN void __glXDisp_DepthMask(GLbyte * pc); extern HIDDEN void __glXDispSwap_DepthMask(GLbyte * pc); -extern HIDDEN void __glXDisp_Rotated(GLbyte * pc); -extern HIDDEN void __glXDispSwap_Rotated(GLbyte * pc); +extern HIDDEN void __glXDisp_Color4iv(GLbyte * pc); +extern HIDDEN void __glXDispSwap_Color4iv(GLbyte * pc); extern HIDDEN int __glXDisp_GetMaterialiv(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN int __glXDispSwap_GetMaterialiv(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN void __glXDisp_StencilOp(GLbyte * pc); @@ -619,8 +623,8 @@ extern HIDDEN int __glXDisp_PixelStorei(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN int __glXDispSwap_PixelStorei(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN void __glXDisp_VertexAttrib4usvARB(GLbyte * pc); extern HIDDEN void __glXDispSwap_VertexAttrib4usvARB(GLbyte * pc); -extern HIDDEN void __glXDisp_Color4iv(GLbyte * pc); -extern HIDDEN void __glXDispSwap_Color4iv(GLbyte * pc); +extern HIDDEN int __glXDisp_DestroyGLXPbufferSGIX(struct __GLXclientStateRec *, GLbyte *); +extern HIDDEN int __glXDispSwap_DestroyGLXPbufferSGIX(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN void __glXDisp_EvalCoord2dv(GLbyte * pc); extern HIDDEN void __glXDispSwap_EvalCoord2dv(GLbyte * pc); extern HIDDEN void __glXDisp_VertexAttrib3svARB(GLbyte * pc); @@ -669,6 +673,8 @@ extern HIDDEN void __glXDisp_Lighti(GLbyte * pc); extern HIDDEN void __glXDispSwap_Lighti(GLbyte * pc); extern HIDDEN int __glXDisp_GetFramebufferAttachmentParameterivEXT(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN int __glXDispSwap_GetFramebufferAttachmentParameterivEXT(struct __GLXclientStateRec *, GLbyte *); +extern HIDDEN int __glXDisp_ChangeDrawableAttributesSGIX(struct __GLXclientStateRec *, GLbyte *); +extern HIDDEN int __glXDispSwap_ChangeDrawableAttributesSGIX(struct __GLXclientStateRec *, GLbyte *); extern HIDDEN void __glXDisp_MultiTexCoord4dvARB(GLbyte * pc); extern HIDDEN void __glXDispSwap_MultiTexCoord4dvARB(GLbyte * pc); extern HIDDEN int __glXDisp_CreatePbuffer(struct __GLXclientStateRec *, GLbyte *); @@ -751,8 +757,8 @@ extern HIDDEN void __glXDisp_PixelTransferf(GLbyte * pc); extern HIDDEN void __glXDispSwap_PixelTransferf(GLbyte * pc); extern HIDDEN void __glXDisp_CopyTexImage1D(GLbyte * pc); extern HIDDEN void __glXDispSwap_CopyTexImage1D(GLbyte * pc); -extern HIDDEN void __glXDisp_PushMatrix(GLbyte * pc); -extern HIDDEN void __glXDispSwap_PushMatrix(GLbyte * pc); +extern HIDDEN void __glXDisp_RasterPos2dv(GLbyte * pc); +extern HIDDEN void __glXDispSwap_RasterPos2dv(GLbyte * pc); extern HIDDEN void __glXDisp_Fogiv(GLbyte * pc); extern HIDDEN void __glXDispSwap_Fogiv(GLbyte * pc); extern HIDDEN void __glXDisp_TexCoord1dv(GLbyte * pc); diff --git a/GL/glx/indirect_size_get.c b/GL/glx/indirect_size_get.c index f29ae474e..928571440 100644 --- a/GL/glx/indirect_size_get.c +++ b/GL/glx/indirect_size_get.c @@ -697,6 +697,7 @@ __glGetBooleanv_size(GLenum e) case GL_MATRIX_INDEX_ARRAY_SIZE_ARB: case GL_MATRIX_INDEX_ARRAY_TYPE_ARB: case GL_MATRIX_INDEX_ARRAY_STRIDE_ARB: + case GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT: case GL_POINT_SPRITE_ARB: /* case GL_POINT_SPRITE_NV:*/ case GL_POINT_SPRITE_R_MODE_NV: @@ -704,8 +705,11 @@ __glGetBooleanv_size(GLenum e) case GL_MAX_TEXTURE_COORDS_ARB: case GL_MAX_TEXTURE_IMAGE_UNITS_ARB: case GL_DEPTH_BOUNDS_TEST_EXT: + case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT: case GL_STENCIL_TEST_TWO_SIDE_EXT: case GL_ACTIVE_STENCIL_FACE_EXT: + case GL_TEXTURE_BINDING_1D_ARRAY_EXT: + case GL_TEXTURE_BINDING_2D_ARRAY_EXT: case GL_RASTER_POSITION_UNCLIPPED_IBM: return 1; case GL_SMOOTH_POINT_SIZE_RANGE: diff --git a/GL/glx/indirect_table.c b/GL/glx/indirect_table.c index 9d0383c83..3da1f437c 100644 --- a/GL/glx/indirect_table.c +++ b/GL/glx/indirect_table.c @@ -1575,9 +1575,9 @@ static const void *VendorPriv_function_table[104][2] = { /* [ 92] = 65540 */ {__glXDisp_GetFBConfigsSGIX, __glXDispSwap_GetFBConfigsSGIX}, /* [ 93] = 65541 */ {__glXDisp_CreateContextWithConfigSGIX, __glXDispSwap_CreateContextWithConfigSGIX}, /* [ 94] = 65542 */ {__glXDisp_CreateGLXPixmapWithConfigSGIX, __glXDispSwap_CreateGLXPixmapWithConfigSGIX}, - /* [ 95] = 65543 */ {NULL, NULL}, - /* [ 96] = 65544 */ {NULL, NULL}, - /* [ 97] = 65545 */ {NULL, NULL}, + /* [ 95] = 65543 */ {__glXDisp_CreateGLXPbufferSGIX, __glXDispSwap_CreateGLXPbufferSGIX}, + /* [ 96] = 65544 */ {__glXDisp_DestroyGLXPbufferSGIX, __glXDispSwap_DestroyGLXPbufferSGIX}, + /* [ 97] = 65545 */ {__glXDisp_ChangeDrawableAttributesSGIX, __glXDispSwap_ChangeDrawableAttributesSGIX}, /* [ 98] = 65546 */ {__glXDisp_GetDrawableAttributesSGIX, __glXDispSwap_GetDrawableAttributesSGIX}, /* [ 99] = 65547 */ {NULL, NULL}, /* [ 100] = 65548 */ {NULL, NULL}, diff --git a/Xext/shm.c b/Xext/shm.c index 7fa834952..a688aa8d9 100644 --- a/Xext/shm.c +++ b/Xext/shm.c @@ -62,6 +62,33 @@ in this Software without prior written authorization from The Open Group. #include #include +/* Needed for Solaris cross-zone shared memory extension */ +#ifdef HAVE_SHMCTL64 +#include +#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf) +#define SHMSTAT_TYPE struct shmid_ds64 +#define SHMPERM_TYPE struct ipc_perm64 +#define SHM_PERM(buf) buf.shmx_perm +#define SHM_SEGSZ(buf) buf.shmx_segsz +#define SHMPERM_UID(p) p->ipcx_uid +#define SHMPERM_CUID(p) p->ipcx_cuid +#define SHMPERM_GID(p) p->ipcx_gid +#define SHMPERM_CGID(p) p->ipcx_cgid +#define SHMPERM_MODE(p) p->ipcx_mode +#define SHMPERM_ZONEID(p) p->ipcx_zoneid +#else +#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf) +#define SHMSTAT_TYPE struct shmid_ds +#define SHMPERM_TYPE struct ipc_perm +#define SHM_PERM(buf) buf.shm_perm +#define SHM_SEGSZ(buf) buf.shm_segsz +#define SHMPERM_UID(p) p->uid +#define SHMPERM_CUID(p) p->cuid +#define SHMPERM_GID(p) p->gid +#define SHMPERM_CGID(p) p->cgid +#define SHMPERM_MODE(p) p->mode +#endif + #ifdef PANORAMIX #include "panoramiX.h" #include "panoramiXsrv.h" @@ -348,32 +375,57 @@ ProcShmQueryVersion(client) * using the credentials from the client if available */ static int -shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) +shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) { int uid, gid; mode_t mask; + int uidset = 0, gidset = 0; + LocalClientCredRec *lcc; + + if (GetLocalClientCreds(client, &lcc) != -1) { - if (LocalClientCred(client, &uid, &gid) != -1) { + if (lcc->fieldsSet & LCC_UID_SET) { + uid = lcc->euid; + uidset = 1; + } + if (lcc->fieldsSet & LCC_GID_SET) { + gid = lcc->egid; + gidset = 1; + } + +#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) + if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) + || (lcc->zoneid != SHMPERM_ZONEID(perm))) { + uidset = 0; + gidset = 0; + } +#endif + FreeLocalClientCreds(lcc); - /* User id 0 always gets access */ - if (uid == 0) { - return 0; - } - /* Check the owner */ - if (perm->uid == uid || perm->cuid == uid) { - mask = S_IRUSR; - if (!readonly) { - mask |= S_IWUSR; + if (uidset) { + /* User id 0 always gets access */ + if (uid == 0) { + return 0; } - return (perm->mode & mask) == mask ? 0 : -1; - } - /* Check the group */ - if (perm->gid == gid || perm->cgid == gid) { - mask = S_IRGRP; - if (!readonly) { - mask |= S_IWGRP; + /* Check the owner */ + if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; + } + } + + if (gidset) { + /* Check the group */ + if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; } - return (perm->mode & mask) == mask ? 0 : -1; } } /* Otherwise, check everyone else */ @@ -381,14 +433,14 @@ shm_access(ClientPtr client, struct ipc_perm *perm, int readonly) if (!readonly) { mask |= S_IWOTH; } - return (perm->mode & mask) == mask ? 0 : -1; + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; } static int ProcShmAttach(client) register ClientPtr client; { - struct shmid_ds buf; + SHMSTAT_TYPE buf; ShmDescPtr shmdesc; REQUEST(xShmAttachReq); @@ -417,7 +469,7 @@ ProcShmAttach(client) shmdesc->addr = shmat(stuff->shmid, 0, stuff->readOnly ? SHM_RDONLY : 0); if ((shmdesc->addr == ((char *)-1)) || - shmctl(stuff->shmid, IPC_STAT, &buf)) + SHMSTAT(stuff->shmid, &buf)) { xfree(shmdesc); return BadAccess; @@ -427,7 +479,7 @@ ProcShmAttach(client) * do manual checking of access rights for the credentials * of the client */ - if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { + if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { shmdt(shmdesc->addr); xfree(shmdesc); return BadAccess; @@ -436,7 +488,7 @@ ProcShmAttach(client) shmdesc->shmid = stuff->shmid; shmdesc->refcnt = 1; shmdesc->writable = !stuff->readOnly; - shmdesc->size = buf.shm_segsz; + shmdesc->size = SHM_SEGSZ(buf); shmdesc->next = Shmsegs; Shmsegs = shmdesc; } diff --git a/configure.ac b/configure.ac index ee631b1d1..e7d229c4f 100644 --- a/configure.ac +++ b/configure.ac @@ -179,7 +179,7 @@ dnl Checks for library functions. AC_FUNC_VPRINTF AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr \ strtol getopt getopt_long vsnprintf walkcontext backtrace \ - getisax getzoneid]) + getisax getzoneid shmctl64]) AC_FUNC_ALLOCA dnl Old HAS_* names used in os/*.c. AC_CHECK_FUNC([getdtablesize], @@ -290,6 +290,7 @@ case $host_cpu in alpha*) ALPHA_VIDEO=yes case $host_os in + *freebsd*) SYS_LIBS=-lio ;; *netbsd*) AC_DEFINE(USE_ALPHA_PIO, 1, [NetBSD PIO alpha IO]) ;; esac ;; @@ -723,6 +724,7 @@ if test "x$XV" = xyes; then AC_DEFINE(XV, 1, [Support Xv extension]) AC_DEFINE(XvExtension, 1, [Build Xv extension]) REQUIRED_MODULES="$REQUIRED_MODULES videoproto" + PKG_CHECK_MODULES(XV, [xv >= 0.22]) else XVMC=no fi @@ -774,7 +776,7 @@ fi if test "x$GLX" = xyes && ! test "x$MESA_SOURCE" = x; then PKG_CHECK_MODULES([XLIB], [x11]) - PKG_CHECK_MODULES([GL], [glproto >= 1.4.8]) + PKG_CHECK_MODULES([GL], [glproto >= 1.4.9]) AC_SUBST(XLIB_CFLAGS) AC_DEFINE(GLXEXT, 1, [Build GLX extension]) GLX_LIBS='$(top_builddir)/GL/glx/libglx.la $(top_builddir)/GL/mesa/libGLcore.la' @@ -1842,6 +1844,13 @@ if test "$KDRIVE" = yes; then if test "x$XEPHYR" = xauto; then XEPHYR=$xephyr fi + XEPHYR_DRI=no + if test x$XEPHYR = xyes -a x$DRI = xyes; then + XEPHYR_DRI=yes + fi + if test x$XEPHYR_DRI = xyes ; then + AC_DEFINE(XEPHYR_DRI,1,[enable DRI extension in xephyr]) + fi # Xephyr needs nanosleep() which is in librt on Solaris AC_CHECK_FUNC([nanosleep], [], @@ -1861,9 +1870,9 @@ if test "$KDRIVE" = yes; then KDRIVE_OS_INC='-I$(top_srcdir)/hw/kdrive/linux' KDRIVE_INCS="$KDRIVE_PURE_INCS $KDRIVE_OS_INC" - KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS" + KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS $XV_CFLAGS" - KDRIVE_PURE_LIBS="$FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB" + KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $OS_LIB" KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.a' case $host_os in *linux*) @@ -1875,7 +1884,7 @@ if test "$KDRIVE" = yes; then KDRIVE_LOCAL_LIBS="$TSLIB_LIBS $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB $CONFIG_LIB" KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS" KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB $OS_LIB" - KDRIVE_LIBS="$KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS" + KDRIVE_LIBS="$KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $XV_LIBS" # check if we can build Xephyr PKG_CHECK_MODULES(XEPHYR, x11 xext xfont xau xdmcp, [xephyr="yes"], [xephyr="no"]) diff --git a/dix/extension.c b/dix/extension.c index 186574d76..4c0c3d236 100644 --- a/dix/extension.c +++ b/dix/extension.c @@ -184,6 +184,8 @@ _X_EXPORT Bool AddExtensionAlias(char *alias, ExtensionEntry *ext) char *name; char **aliases; + if (!ext) + return FALSE ; aliases = (char **)xrealloc(ext->aliases, (ext->num_aliases + 1) * sizeof(char *)); if (!aliases) diff --git a/exa/exa.c b/exa/exa.c index 3e8054da9..7ad226fba 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -286,8 +286,9 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth) (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, paddedWidth, NULL); - pExaPixmap->driverPriv = driver_priv; - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; + pExaPixmap->driverPriv = driver_priv; + pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; + pExaPixmap->fb_ptr = NULL; } else { pExaPixmap->driverPriv = NULL; /* Glyphs have w/h equal to zero, and may not be migrated. See exaGlyphs. */ @@ -409,7 +410,7 @@ exaPixmapIsOffscreen(PixmapPtr p) save_ptr = p->devPrivate.ptr; - if (!save_ptr && pExaPixmap) + if (!save_ptr && pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) p->devPrivate.ptr = ExaGetPixmapAddress(p); if (pExaScr->info->PixmapIsOffscreen) @@ -459,7 +460,7 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index) Bool offscreen = exaPixmapIsOffscreen(pPixmap); /* Unhide pixmap pointer */ - if (pPixmap->devPrivate.ptr == NULL) { + if (pPixmap->devPrivate.ptr == NULL && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); } @@ -520,8 +521,7 @@ exaFinishAccess(DrawablePtr pDrawable, int index) ExaPixmapPriv (pPixmap); /* Rehide pixmap pointer if we're doing that. */ - if (pExaPixmap) - { + if (pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { pPixmap->devPrivate.ptr = NULL; } diff --git a/exa/exa.h b/exa/exa.h index f852df482..1ff0518e4 100644 --- a/exa/exa.h +++ b/exa/exa.h @@ -733,6 +733,13 @@ typedef struct _ExaDriver { * (right-to-left, bottom-to-top). */ #define EXA_TWO_BITBLT_DIRECTIONS (1 << 2) + +/** + * EXA_HANDLES_PIXMAPS indicates to EXA that the driver can handle + * all pixmap addressing and migration. + */ +#define EXA_HANDLES_PIXMAPS (1 << 3) + /** @} */ ExaDriverPtr diff --git a/exa/exa_accel.c b/exa/exa_accel.c index abe5c204f..52cc5c40a 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -152,6 +152,9 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int bpp = pDrawable->bitsPerPixel; Bool access_prepared = FALSE; + if (pExaPixmap->accel_blocked) + return FALSE; + /* Don't bother with under 8bpp, XYPixmaps. */ if (format != ZPixmap || bpp < 8) return FALSE; @@ -1134,7 +1137,8 @@ exaFillRegionSolid (DrawablePtr pDrawable, (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); - if (pDrawable->width == 1 && pDrawable->height == 1 && + if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && + pDrawable->width == 1 && pDrawable->height == 1 && pDrawable->bitsPerPixel != 24) { ExaPixmapPriv(pPixmap); diff --git a/exa/exa_migration.c b/exa/exa_migration.c index c0e022ca7..d69526b7f 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -299,6 +299,9 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate) if (pPixmap->drawable.bitsPerPixel < 8) return; + if (pExaPixmap->accel_blocked) + return; + if (pExaPixmap->area == NULL) { pExaPixmap->area = exaOffscreenAlloc (pScreen, pExaPixmap->fb_size, @@ -553,6 +556,9 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) ExaScreenPriv(pScreen); int i, j; + if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) + return; + /* If this debugging flag is set, check each pixmap for whether it is marked * as clean, and if so, actually check if that's the case. This should help * catch issues with failing to mark a drawable as dirty. While it will diff --git a/exa/exa_render.c b/exa/exa_render.c index 98fc884b6..847a36182 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -247,10 +247,24 @@ exaTryDriverSolidFill(PicturePtr pSrc, int nbox; int dst_off_x, dst_off_y; PixmapPtr pSrcPix, pDstPix; + ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; CARD32 pixel; CARD16 red, green, blue, alpha; ExaMigrationRec pixmaps[1]; + pDstPix = exaGetDrawablePixmap (pDst->pDrawable); + pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); + + pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + pDstExaPix = ExaGetPixmapPriv(pDstPix); + + /* Check whether the accelerator can use these pixmaps. + */ + if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked) + { + return -1; + } + xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; xSrc += pSrc->pDrawable->x; @@ -261,12 +275,10 @@ exaTryDriverSolidFill(PicturePtr pSrc, width, height)) return 1; - pDstPix = exaGetDrawablePixmap (pDst->pDrawable); exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); pixel = exaGetPixmapFirstPixel (pSrcPix); pixmaps[0].as_dst = TRUE; @@ -1202,6 +1214,7 @@ exaGlyphs (CARD8 op, y1 = y - glyph->info.y; if (x1 >= pCmpDrw->width || y1 >= pCmpDrw->height || + glyph->info.width == 0 || glyph->info.height == 0 || (x1 + glyph->info.width) <= 0 || (y1 + glyph->info.height) <= 0) goto nextglyph; diff --git a/fb/fbcmap_mi.c b/fb/fbcmap_mi.c index 58bcae3aa..188decd4c 100644 --- a/fb/fbcmap_mi.c +++ b/fb/fbcmap_mi.c @@ -103,6 +103,14 @@ fbSetVisualTypes (int depth, int visuals, int bitsPerRGB) return miSetVisualTypes(depth, visuals, bitsPerRGB, -1); } +Bool +fbSetVisualTypesAndMasks (int depth, int visuals, int bitsPerRGB, + Pixel redMask, Pixel greenMask, Pixel blueMask) +{ + return miSetVisualTypesAndMasks(depth, visuals, bitsPerRGB, -1, + redMask, greenMask, blueMask); +} + /* * Given a list of formats for a screen, create a list * of visuals and depths for the screen which coorespond to diff --git a/hw/kdrive/ephyr/GL/internal/dri_interface.h b/hw/kdrive/ephyr/GL/internal/dri_interface.h new file mode 100644 index 000000000..8d24e311f --- /dev/null +++ b/hw/kdrive/ephyr/GL/internal/dri_interface.h @@ -0,0 +1,517 @@ +/* + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * (C) Copyright IBM Corporation 2004 + * 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 + * on 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 + * THE COPYRIGHT HOLDERS AND/OR THEIR 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. + */ + +/** + * \file dri_interface.h + * + * This file contains all the types and functions that define the interface + * between a DRI driver and driver loader. Currently, the most common driver + * loader is the XFree86 libGL.so. However, other loaders do exist, and in + * the future the server-side libglx.a will also be a loader. + * + * \author Kevin E. Martin + * \author Ian Romanick + */ + +#ifndef DRI_INTERFACE_H +#define DRI_INTERFACE_H + +#include +#include + +/** + * \name DRI interface structures + * + * The following structures define the interface between the GLX client + * side library and the DRI (direct rendering infrastructure). + */ +/*@{*/ +typedef struct __DRIdisplayRec __DRIdisplay; +typedef struct __DRIscreenRec __DRIscreen; +typedef struct __DRIcontextRec __DRIcontext; +typedef struct __DRIdrawableRec __DRIdrawable; +typedef struct __DRIdriverRec __DRIdriver; +typedef struct __DRIframebufferRec __DRIframebuffer; +typedef struct __DRIversionRec __DRIversion; +typedef struct __DRIinterfaceMethodsRec __DRIinterfaceMethods; +typedef unsigned long __DRIid; +typedef void __DRInativeDisplay; +/*@}*/ + + +/** + * \name Functions provided by the driver loader. + */ +/*@{*/ +/** + * Type of a pointer to \c glXGetScreenDriver, as returned by + * \c glXGetProcAddress. This function is used to get the name of the DRI + * driver for the specified screen of the specified display. The driver + * name is typically used with \c glXGetDriverConfig. + * + * \sa glXGetScreenDriver, glXGetProcAddress, glXGetDriverConfig + */ +typedef const char * (* PFNGLXGETSCREENDRIVERPROC) (__DRInativeDisplay *dpy, int scrNum); + +/** + * Type of a pointer to \c glXGetDriverConfig, as returned by + * \c glXGetProcAddress. This function is used to get the XML document + * describing the configuration options available for the specified driver. + * + * \sa glXGetDriverConfig, glXGetProcAddress, glXGetScreenDriver + */ +typedef const char * (* PFNGLXGETDRIVERCONFIGPROC) (const char *driverName); + +/** + * Type of a pointer to \c glxEnableExtension, as returned by + * \c __DRIinterfaceMethods::getProcAddress. This function is used to enable + * a GLX extension on the specified screen. + */ +typedef void (* PFNGLXSCRENABLEEXTENSIONPROC) ( void *psc, const char * name ); +/*@}*/ + + +/** + * \name Functions and data provided by the driver. + */ +/*@{*/ + +typedef void *(CREATENEWSCREENFUNC)(__DRInativeDisplay *dpy, int scrn, + __DRIscreen *psc, const __GLcontextModes * modes, + const __DRIversion * ddx_version, const __DRIversion * dri_version, + const __DRIversion * drm_version, const __DRIframebuffer * frame_buffer, + void * pSAREA, int fd, int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes); +typedef CREATENEWSCREENFUNC* PFNCREATENEWSCREENFUNC; +extern CREATENEWSCREENFUNC __driCreateNewScreen_20050727; + + +/** + * XML document describing the configuration options supported by the + * driver. + */ +extern const char __driConfigOptions[]; + +/*@}*/ + + +/** + * Stored version of some component (i.e., server-side DRI module, kernel-side + * DRM, etc.). + * + * \todo + * There are several data structures that explicitly store a major version, + * minor version, and patch level. These structures should be modified to + * have a \c __DRIversionRec instead. + */ +struct __DRIversionRec { + int major; /**< Major version number. */ + int minor; /**< Minor version number. */ + int patch; /**< Patch-level. */ +}; + + +typedef void (*__DRIfuncPtr)(void); + +struct __DRIinterfaceMethodsRec { + /** + * Get pointer to named function. + */ + __DRIfuncPtr (*getProcAddress)( const char * proc_name ); + + /** + * Create a list of \c __GLcontextModes structures. + */ + __GLcontextModes * (*createContextModes)(unsigned count, + size_t minimum_bytes_per_struct); + + /** + * Destroy a list of \c __GLcontextModes structures. + * + * \todo + * Determine if the drivers actually need to call this. + */ + void (*destroyContextModes)( __GLcontextModes * modes ); + + /** + * Get the \c __DRIscreen for a given display and screen number. + */ + __DRIscreen *(*getScreen)(__DRInativeDisplay *dpy, int screenNum); + + + /** + * \name Client/server protocol functions. + * + * These functions implement the DRI client/server protocol for + * context and drawable operations. Platforms that do not implement + * the wire protocol (e.g., EGL) will implement glorified no-op functions. + */ + /*@{*/ + /** + * Determine if the specified window ID still exists. + * + * \note + * Implementations may assume that the driver will only pass an ID into + * this function that actually corresponds to a window. On + * implementations where windows can only be destroyed by the DRI driver + * (e.g., EGL), this function is allowed to always return \c GL_TRUE. + */ + GLboolean (*windowExists)(__DRInativeDisplay *dpy, __DRIid draw); + + /** + * Create the server-side portion of the GL context. + */ + GLboolean (* createContext)( __DRInativeDisplay *dpy, int screenNum, + int configID, void * contextID, drm_context_t * hw_context ); + + /** + * Destroy the server-side portion of the GL context. + */ + GLboolean (* destroyContext)( __DRInativeDisplay *dpy, int screenNum, + __DRIid context ); + + /** + * Create the server-side portion of the drawable. + */ + GLboolean (*createDrawable)( __DRInativeDisplay * ndpy, int screen, + __DRIid drawable, drm_drawable_t * hHWDrawable ); + + /** + * Destroy the server-side portion of the drawable. + */ + GLboolean (*destroyDrawable)( __DRInativeDisplay * ndpy, int screen, + __DRIid drawable ); + + /** + * This function is used to get information about the position, size, and + * clip rects of a drawable. + */ + GLboolean (* getDrawableInfo) ( __DRInativeDisplay *dpy, int scrn, + __DRIid draw, unsigned int * index, unsigned int * stamp, + int * x, int * y, int * width, int * height, + int * numClipRects, drm_clip_rect_t ** pClipRects, + int * backX, int * backY, + int * numBackClipRects, drm_clip_rect_t ** pBackClipRects ); + /*@}*/ + + + /** + * \name Timing related functions. + */ + /*@{*/ + /** + * Get the 64-bit unadjusted system time (UST). + */ + int (*getUST)(int64_t * ust); + + /** + * Get the media stream counter (MSC) rate. + * + * Matching the definition in GLX_OML_sync_control, this function returns + * the rate of the "media stream counter". In practical terms, this is + * the frame refresh rate of the display. + */ + GLboolean (*getMSCRate)(__DRInativeDisplay * dpy, __DRIid drawable, + int32_t * numerator, int32_t * denominator); + /*@}*/ + + /** + * Reports areas of the given drawable which have been modified by the + * driver. + * + * \param drawable which the drawing was done to. + * \param rects rectangles affected, with the drawable origin as the + * origin. + * \param x X offset of the drawable within the screen (used in the + * front_buffer case) + * \param y Y offset of the drawable within the screen. + * \param front_buffer boolean flag for whether the drawing to the + * drawable was actually done directly to the front buffer (instead + * of backing storage, for example) + */ + void (*reportDamage)(__DRInativeDisplay * dpy, int screen, + __DRIid drawable, + int x, int y, + drm_clip_rect_t *rects, int num_rects, + int front_buffer); +}; + + +/** + * Framebuffer information record. Used by libGL to communicate information + * about the framebuffer to the driver's \c __driCreateNewScreen function. + * + * In XFree86, most of this information is derrived from data returned by + * calling \c XF86DRIGetDeviceInfo. + * + * \sa XF86DRIGetDeviceInfo __DRIdisplayRec::createNewScreen + * __driUtilCreateNewScreen CallCreateNewScreen + * + * \bug This structure could be better named. + */ +struct __DRIframebufferRec { + unsigned char *base; /**< Framebuffer base address in the CPU's + * address space. This value is calculated by + * calling \c drmMap on the framebuffer handle + * returned by \c XF86DRIGetDeviceInfo (or a + * similar function). + */ + int size; /**< Framebuffer size, in bytes. */ + int stride; /**< Number of bytes from one line to the next. */ + int width; /**< Pixel width of the framebuffer. */ + int height; /**< Pixel height of the framebuffer. */ + int dev_priv_size; /**< Size of the driver's dev-priv structure. */ + void *dev_priv; /**< Pointer to the driver's dev-priv structure. */ +}; + + +/** + * Screen dependent methods. This structure is initialized during the + * \c __DRIdisplayRec::createScreen call. + */ +struct __DRIscreenRec { + /** + * Method to destroy the private DRI screen data. + */ + void (*destroyScreen)(__DRInativeDisplay *dpy, int scrn, void *screenPrivate); + + /** + * Method to create the private DRI drawable data and initialize the + * drawable dependent methods. + */ + void *(*createNewDrawable)(__DRInativeDisplay *dpy, const __GLcontextModes *modes, + __DRIid draw, __DRIdrawable *pdraw, + int renderType, const int *attrs); + + /** + * Method to return a pointer to the DRI drawable data. + */ + __DRIdrawable *(*getDrawable)(__DRInativeDisplay *dpy, __DRIid draw, + void *drawablePrivate); + + /** + * Opaque pointer to private per screen direct rendering data. \c NULL + * if direct rendering is not supported on this screen. Never + * dereferenced in libGL. + */ + void *private; + + /** + * Get the number of vertical refreshes since some point in time before + * this function was first called (i.e., system start up). + * + * \since Internal API version 20030317. + */ + int (*getMSC)( void *screenPrivate, int64_t *msc ); + + /** + * Opaque pointer that points back to the containing + * \c __GLXscreenConfigs. This data structure is shared with DRI drivers + * but \c __GLXscreenConfigs is not. However, they are needed by some GLX + * functions called by DRI drivers. + * + * \since Internal API version 20030813. + */ + void *screenConfigs; + + /** + * Functions associated with MESA_allocate_memory. + * + * \since Internal API version 20030815. + */ + /*@{*/ + void *(*allocateMemory)(__DRInativeDisplay *dpy, int scrn, GLsizei size, + GLfloat readfreq, GLfloat writefreq, + GLfloat priority); + + void (*freeMemory)(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer); + + GLuint (*memoryOffset)(__DRInativeDisplay *dpy, int scrn, const GLvoid *pointer); + /*@}*/ + + /** + * Method to create the private DRI context data and initialize the + * context dependent methods. + * + * \since Internal API version 20031201. + */ + void * (*createNewContext)(__DRInativeDisplay *dpy, const __GLcontextModes *modes, + int render_type, + void *sharedPrivate, __DRIcontext *pctx); + + /** + * Method to override base texture image with a driver specific 'offset'. + * The depth passed in allows e.g. to ignore the alpha channel of texture + * images where the non-alpha components don't occupy a whole texel. + * + * For GLX_EXT_texture_from_pixmap with AIGLX. + * + * \since Internal API version 20070121. + */ + void (*setTexOffset)(__DRIcontext *pDRICtx, GLint texname, + unsigned long long offset, GLint depth, GLuint pitch); +}; + +/** + * Context dependent methods. This structure is initialized during the + * \c __DRIscreenRec::createContext call. + */ +struct __DRIcontextRec { + /** + * Method to destroy the private DRI context data. + */ + void (*destroyContext)(__DRInativeDisplay *dpy, int scrn, void *contextPrivate); + + /** + * Opaque pointer to private per context direct rendering data. + * \c NULL if direct rendering is not supported on the display or + * screen used to create this context. Never dereferenced in libGL. + */ + void *private; + + /** + * Pointer to the mode used to create this context. + * + * \since Internal API version 20040317. + */ + const __GLcontextModes * mode; + + /** + * Method to bind a DRI drawable to a DRI graphics context. + * + * \since Internal API version 20050727. + */ + GLboolean (*bindContext)(__DRInativeDisplay *dpy, int scrn, __DRIid draw, + __DRIid read, __DRIcontext *ctx); + + /** + * Method to unbind a DRI drawable from a DRI graphics context. + * + * \since Internal API version 20050727. + */ + GLboolean (*unbindContext)(__DRInativeDisplay *dpy, int scrn, __DRIid draw, + __DRIid read, __DRIcontext *ctx); +}; + +/** + * Drawable dependent methods. This structure is initialized during the + * \c __DRIscreenRec::createDrawable call. \c createDrawable is not called + * by libGL at this time. It's currently used via the dri_util.c utility code + * instead. + */ +struct __DRIdrawableRec { + /** + * Method to destroy the private DRI drawable data. + */ + void (*destroyDrawable)(__DRInativeDisplay *dpy, void *drawablePrivate); + + /** + * Method to swap the front and back buffers. + */ + void (*swapBuffers)(__DRInativeDisplay *dpy, void *drawablePrivate); + + /** + * Opaque pointer to private per drawable direct rendering data. + * \c NULL if direct rendering is not supported on the display or + * screen used to create this drawable. Never dereferenced in libGL. + */ + void *private; + + /** + * Get the number of completed swap buffers for this drawable. + * + * \since Internal API version 20030317. + */ + int (*getSBC)(__DRInativeDisplay *dpy, void *drawablePrivate, int64_t *sbc ); + + /** + * Wait for the SBC to be greater than or equal target_sbc. + * + * \since Internal API version 20030317. + */ + int (*waitForSBC)( __DRInativeDisplay * dpy, void *drawablePriv, + int64_t target_sbc, + int64_t * msc, int64_t * sbc ); + + /** + * Wait for the MSC to equal target_msc, or, if that has already passed, + * the next time (MSC % divisor) is equal to remainder. If divisor is + * zero, the function will return as soon as MSC is greater than or equal + * to target_msc. + * + * \since Internal API version 20030317. + */ + int (*waitForMSC)( __DRInativeDisplay * dpy, void *drawablePriv, + int64_t target_msc, int64_t divisor, int64_t remainder, + int64_t * msc, int64_t * sbc ); + + /** + * Like \c swapBuffers, but does NOT have an implicit \c glFlush. Once + * rendering is complete, waits until MSC is equal to target_msc, or + * if that has already passed, waits until (MSC % divisor) is equal + * to remainder. If divisor is zero, the swap will happen as soon as + * MSC is greater than or equal to target_msc. + * + * \since Internal API version 20030317. + */ + int64_t (*swapBuffersMSC)(__DRInativeDisplay *dpy, void *drawablePrivate, + int64_t target_msc, + int64_t divisor, int64_t remainder); + + /** + * Enable or disable frame usage tracking. + * + * \since Internal API version 20030317. + */ + int (*frameTracking)(__DRInativeDisplay *dpy, void *drawablePrivate, GLboolean enable); + + /** + * Retrieve frame usage information. + * + * \since Internal API version 20030317. + */ + int (*queryFrameTracking)(__DRInativeDisplay *dpy, void *drawablePrivate, + int64_t * sbc, int64_t * missedFrames, + float * lastMissedUsage, float * usage ); + + /** + * Used by drivers that implement the GLX_SGI_swap_control or + * GLX_MESA_swap_control extension. + * + * \since Internal API version 20030317. + */ + unsigned swap_interval; + + /** + * Used by drivers that implement the GLX_MESA_copy_sub_buffer extension. + * + * \since Internal API version 20060314. + */ + void (*copySubBuffer)(__DRInativeDisplay *dpy, void *drawablePrivate, + int x, int y, int w, int h); +}; + +#endif diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am index cc3019fc7..604e22eaa 100644 --- a/hw/kdrive/ephyr/Makefile.am +++ b/hw/kdrive/ephyr/Makefile.am @@ -3,22 +3,47 @@ INCLUDES = \ @KDRIVE_CFLAGS@ \ -I$(srcdir)/../../../exa -noinst_LIBRARIES = libxephyr.a libxephyr-hostx.a +noinst_LIBRARIES = libxephyr-hostx.a libxephyr-hostxv.a libxephyr.a bin_PROGRAMS = Xephyr + +libxephyr_hostx_a_SOURCES = \ + hostx.c \ + hostx.h + +libxephyr_hostx_a_INCLUDES = @XEPHYR_INCS@ + +libxephyr_hostxv_a_SOURCES= \ + ephyrhostvideo.c \ + ephyrhostvideo.h + libxephyr_a_SOURCES = \ ephyr.c \ ephyr_draw.c \ + ephyrvideo.c \ + XF86dri.c \ + ephyrdriext.c \ + ephyrdri.c \ + ephyrdri.h \ + ephyrglxext.c \ + ephyrglxext.h \ + ephyrhostglx.c \ + ephyrhostglx.h \ + ephyrhostproxy.c \ + ephyrhostproxy.h \ + ephyrhostproxy.c \ + ephyrproxyext.c \ + ephyrproxyext.h \ os.c \ - hostx.h \ - ephyr.h + hostx.h \ + ephyr.h \ + ephyrlog.h -libxephyr_hostx_a_SOURCES = \ - hostx.c \ - hostx.h - -libxephyr_hostx_a_INCLUDES = @XEPHYR_INCS@ +libxephyr_a_CFLAGS = \ +@LIBDRM_CFLAGS@ \ +-I$(top_srcdir) \ +@DRIPROTO_CFLAGS@ Xephyr_SOURCES = \ ephyrinit.c @@ -26,13 +51,17 @@ Xephyr_SOURCES = \ Xephyr_LDADD = \ libxephyr.a \ libxephyr-hostx.a \ + libxephyr-hostxv.a \ ../../../exa/libexa.la \ @KDRIVE_LIBS@ \ - @XEPHYR_LIBS@ + @XEPHYR_LIBS@ \ + @LIBDRM_LIBS@ \ + -lGL Xephyr_DEPENDENCIES = \ libxephyr.a \ libxephyr-hostx.a \ + libxephyr-hostxv.a \ @KDRIVE_LOCAL_LIBS@ relink: diff --git a/hw/kdrive/ephyr/XF86dri.c b/hw/kdrive/ephyr/XF86dri.c new file mode 100644 index 000000000..ae2ec890f --- /dev/null +++ b/hw/kdrive/ephyr/XF86dri.c @@ -0,0 +1,622 @@ +/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.13 2002/10/30 12:51:25 alanh Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +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 + * Jens Owen + * Rickard E. (Rik) Faith + * + */ + +/* + * This file has been copied from the mesa source tree and a little bit + * modified by: + * + * Dodji Seketeli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef XEPHYR_DRI + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_REPLIES +#include +#include +#include +#include +#include +#include + +static XExtensionInfo _xf86dri_info_data; +static XExtensionInfo *xf86dri_info = &_xf86dri_info_data; +static char xf86dri_extension_name[] = XF86DRINAME; + +#define XF86DRICheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, xf86dri_extension_name, val) + +/***************************************************************************** + * * + * private utility routines * + * * + *****************************************************************************/ + +static int close_display(Display *dpy, XExtCodes *extCodes); +static /* const */ XExtensionHooks xf86dri_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info, + xf86dri_extension_name, + &xf86dri_extension_hooks, + 0, NULL) + +static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info) + + +/***************************************************************************** + * * + * public XFree86-DRI Extension routines * + * * + *****************************************************************************/ + +#if 0 +#include +#define TRACE(msg) fprintf(stderr,"XF86DRI%s\n", msg); +#else +#define TRACE(msg) +#endif + +Bool XF86DRIOpenFullScreen(Display *dpy, int screen, Drawable drawable); +Bool XF86DRICloseFullScreen(Display *dpy, int screen, Drawable drawable); + +Bool XF86DRIQueryExtension (Display *dpy, int *event_basep, int *error_basep) +{ + XExtDisplayInfo *info = find_display (dpy); + + TRACE("QueryExtension..."); + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + TRACE("QueryExtension... return True"); + return True; + } else { + TRACE("QueryExtension... return False"); + return False; + } +} + +Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion) + Display* dpy; + int* majorVersion; + int* minorVersion; + int* patchVersion; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIQueryVersionReply rep; + xXF86DRIQueryVersionReq *req; + + TRACE("QueryVersion..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIQueryVersion; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryVersion... return False"); + return False; + } + *majorVersion = rep.majorVersion; + *minorVersion = rep.minorVersion; + *patchVersion = rep.patchVersion; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryVersion... return True"); + return True; +} + +Bool +XF86DRIQueryDirectRenderingCapable (Display *dpy, int screen, Bool *isCapable) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIQueryDirectRenderingCapableReply rep; + xXF86DRIQueryDirectRenderingCapableReq *req; + + TRACE("QueryDirectRenderingCapable..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIQueryDirectRenderingCapable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIQueryDirectRenderingCapable; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryDirectRenderingCapable... return False"); + return False; + } + *isCapable = rep.isCapable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("QueryDirectRenderingCapable... return True"); + return True; +} + +Bool +XF86DRIOpenConnection (Display *dpy, int screen, + drm_handle_t *hSAREA, + char **busIdString) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIOpenConnectionReply rep; + xXF86DRIOpenConnectionReq *req; + + TRACE("OpenConnection..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIOpenConnection, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIOpenConnection; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("OpenConnection... return False"); + return False; + } + + *hSAREA = rep.hSAREALow; + if (sizeof(drm_handle_t) == 8) { + int shift = 32; /* var to prevent warning on next line */ + *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift; + } + + if (rep.length) { + if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) { + _XEatData(dpy, ((rep.busIdStringLength+3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("OpenConnection... return False"); + return False; + } + _XReadPad(dpy, *busIdString, rep.busIdStringLength); + } else { + *busIdString = NULL; + } + UnlockDisplay(dpy); + SyncHandle(); + TRACE("OpenConnection... return True"); + return True; +} + +Bool XF86DRIAuthConnection(dpy, screen, magic) + Display* dpy; + int screen; + drm_magic_t magic; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIAuthConnectionReq *req; + xXF86DRIAuthConnectionReply rep; + + TRACE("AuthConnection..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIAuthConnection, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIAuthConnection; + req->screen = screen; + req->magic = magic; + rep.authenticated = 0; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("AuthConnection... return False"); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + TRACE("AuthConnection... return True"); + return True; +} + +Bool XF86DRICloseConnection(dpy, screen) + Display* dpy; + int screen; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRICloseConnectionReq *req; + + TRACE("CloseConnection..."); + + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRICloseConnection, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRICloseConnection; + req->screen = screen; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CloseConnection... return True"); + return True; +} + +Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion, + ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName) + Display* dpy; + int screen; + int* ddxDriverMajorVersion; + int* ddxDriverMinorVersion; + int* ddxDriverPatchVersion; + char** clientDriverName; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIGetClientDriverNameReply rep; + xXF86DRIGetClientDriverNameReq *req; + + TRACE("GetClientDriverName..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIGetClientDriverName, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIGetClientDriverName; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetClientDriverName... return False"); + return False; + } + + *ddxDriverMajorVersion = rep.ddxDriverMajorVersion; + *ddxDriverMinorVersion = rep.ddxDriverMinorVersion; + *ddxDriverPatchVersion = rep.ddxDriverPatchVersion; + + if (rep.length) { + if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) { + _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetClientDriverName... return False"); + return False; + } + _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength); + } else { + *clientDriverName = NULL; + } + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetClientDriverName... return True"); + return True; +} + +Bool XF86DRICreateContextWithConfig(dpy, screen, configID, context, + hHWContext) + Display* dpy; + int screen; + int configID; + XID* context; + drm_context_t * hHWContext; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRICreateContextReply rep; + xXF86DRICreateContextReq *req; + + TRACE("CreateContext..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRICreateContext, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRICreateContext; + req->visual = configID; + req->screen = screen; + *context = XAllocID(dpy); + req->context = *context; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateContext... return False"); + return False; + } + *hHWContext = rep.hHWContext; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateContext... return True"); + return True; +} + +Bool XF86DRICreateContext(dpy, screen, visual, context, hHWContext) + Display* dpy; + int screen; + Visual* visual; + XID* context; + drm_context_t * hHWContext; +{ + return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid, + context, hHWContext ); +} + +GLboolean XF86DRIDestroyContext( __DRInativeDisplay * ndpy, int screen, + __DRIid context ) +{ + Display * const dpy = (Display *) ndpy; + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIDestroyContextReq *req; + + TRACE("DestroyContext..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIDestroyContext, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIDestroyContext; + req->screen = screen; + req->context = context; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("DestroyContext... return True"); + return True; +} + +GLboolean XF86DRICreateDrawable( __DRInativeDisplay * ndpy, int screen, + __DRIid drawable, drm_drawable_t * hHWDrawable ) +{ + Display * const dpy = (Display *) ndpy; + XExtDisplayInfo *info = find_display (dpy); + xXF86DRICreateDrawableReply rep; + xXF86DRICreateDrawableReq *req; + + TRACE("CreateDrawable..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRICreateDrawable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRICreateDrawable; + req->screen = screen; + req->drawable = drawable; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateDrawable... return False"); + return False; + } + *hHWDrawable = rep.hHWDrawable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("CreateDrawable... return True"); + return True; +} + +GLboolean XF86DRIDestroyDrawable( __DRInativeDisplay * ndpy, int screen, + __DRIid drawable ) +{ + Display * const dpy = (Display *) ndpy; + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIDestroyDrawableReq *req; + + TRACE("DestroyDrawable..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIDestroyDrawable, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIDestroyDrawable; + req->screen = screen; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); + TRACE("DestroyDrawable... return True"); + return True; +} + +Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable, + unsigned int* index, unsigned int* stamp, + int* X, int* Y, int* W, int* H, + int* numClipRects, drm_clip_rect_t ** pClipRects, + int* backX, int* backY, + int* numBackClipRects, drm_clip_rect_t ** pBackClipRects ) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIGetDrawableInfoReply rep; + xXF86DRIGetDrawableInfoReq *req=NULL; + int total_rects; + + TRACE("GetDrawableInfo..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIGetDrawableInfo, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIGetDrawableInfo; + req->screen = screen; + req->drawable = drawable; + + if (!_XReply(dpy, (xReply *)&rep, 1, xFalse)) + { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return False"); + return False; + } + *index = rep.drawableTableIndex; + *stamp = rep.drawableTableStamp; + *X = (int)rep.drawableX; + *Y = (int)rep.drawableY; + *W = (int)rep.drawableWidth; + *H = (int)rep.drawableHeight; + *numClipRects = rep.numClipRects; + total_rects = *numClipRects; + + *backX = rep.backX; + *backY = rep.backY; + *numBackClipRects = rep.numBackClipRects; + total_rects += *numBackClipRects; + +#if 0 + /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks + * backwards compatibility (Because of the >> 2 shift) but the fix + * enables multi-threaded apps to work. + */ + if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) - + SIZEOF(xGenericReply) + + total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) { + _XEatData(dpy, rep.length); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return False"); + return False; + } +#endif + + if (*numClipRects) { + int len = sizeof(drm_clip_rect_t) * (*numClipRects); + + *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1); + if (*pClipRects) + _XRead(dpy, (char*)*pClipRects, len); + } else { + *pClipRects = NULL; + } + + if (*numBackClipRects) { + int len = sizeof(drm_clip_rect_t) * (*numBackClipRects); + + *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1); + if (*pBackClipRects) + _XRead(dpy, (char*)*pBackClipRects, len); + } else { + *pBackClipRects = NULL; + } + + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDrawableInfo... return True"); + return True; +} + +Bool +XF86DRIGetDeviceInfo (Display *dpy, int screen, drm_handle_t *hFrameBuffer, + int *fbOrigin, int *fbSize, int *fbStride, + int *devPrivateSize, void **pDevPrivate) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86DRIGetDeviceInfoReply rep; + xXF86DRIGetDeviceInfoReq *req; + + TRACE("GetDeviceInfo..."); + XF86DRICheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DRIGetDeviceInfo, req); + req->reqType = info->codes->major_opcode; + req->driReqType = X_XF86DRIGetDeviceInfo; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return False"); + return False; + } + + *hFrameBuffer = rep.hFrameBufferLow; + if (sizeof(drm_handle_t) == 8) { + int shift = 32; /* var to prevent warning on next line */ + *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift; + } + + *fbOrigin = rep.framebufferOrigin; + *fbSize = rep.framebufferSize; + *fbStride = rep.framebufferStride; + *devPrivateSize = rep.devPrivateSize; + + if (rep.length) { + if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) { + _XEatData(dpy, ((rep.devPrivateSize+3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return False"); + return False; + } + _XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize); + } else { + *pDevPrivate = NULL; + } + + UnlockDisplay(dpy); + SyncHandle(); + TRACE("GetDeviceInfo... return True"); + return True; +} + +Bool +XF86DRIOpenFullScreen(Display *dpy, int screen, Drawable drawable) +{ + /* This function and the underlying X protocol are deprecated. + */ + (void) dpy; + (void) screen; + (void) drawable; + return False; +} + +Bool +XF86DRICloseFullScreen(Display *dpy, int screen, Drawable drawable) +{ + /* This function and the underlying X protocol are deprecated. + */ + (void) dpy; + (void) screen; + (void) drawable; + return True; +} +#endif /*EPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index c5cb21a64..f46a89d55 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -23,11 +23,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* TODO: - * - * o Support multiple screens, shouldn't be hard just alot of rejigging. - */ - #ifdef HAVE_CONFIG_H #include #endif @@ -35,11 +30,25 @@ #include "inputstr.h" #include "scrnintstr.h" +#include "ephyrlog.h" + +#ifdef XEPHYR_DRI +#include "ephyrdri.h" +#include "ephyrdriext.h" +#include "ephyrglxext.h" +#include "ephyrproxyext.h" +#endif /*XEPHYR_DRI*/ extern int KdTsPhyScreen; +#ifdef GLXEXT +extern Bool noGlxVisualInit; +#endif + KdKeyboardInfo *ephyrKbd; KdPointerInfo *ephyrMouse; EphyrKeySyms ephyrKeySyms; +Bool ephyrNoDRI=FALSE ; +Bool ephyrNoXV=FALSE ; static int mouseState = 0; @@ -49,6 +58,7 @@ typedef struct _EphyrInputPrivate { Bool EphyrWantGrayScale = 0; + Bool ephyrInitialize (KdCardInfo *card, EphyrPriv *priv) { @@ -209,7 +219,7 @@ ephyrMapFramebuffer (KdScreenInfo *screen) KdPointerMatrix m; int buffer_height; - EPHYR_DBG("screen->width: %d, screen->height: %d index=%d", + EPHYR_LOG("screen->width: %d, screen->height: %d index=%d", screen->width, screen->height, screen->mynum); KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); @@ -245,7 +255,7 @@ ephyrMapFramebuffer (KdScreenInfo *screen) /* Rotated/Reflected so we need to use shadow fb */ scrpriv->shadow = TRUE; - EPHYR_DBG("allocing shadow"); + EPHYR_LOG("allocing shadow"); KdShadowFbAlloc (screen, 0, scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)); @@ -296,7 +306,7 @@ ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - EPHYR_DBG("slow paint"); + EPHYR_LOG("slow paint"); /* FIXME: Slow Rotated/Reflected updates could be much * much faster efficiently updating via tranforming @@ -410,7 +420,7 @@ ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) Rotation randr; int n = 0; - EPHYR_DBG("mark"); + EPHYR_LOG("mark"); struct { int width, height; } sizes[] = { @@ -563,7 +573,7 @@ ephyrRandRSetConfig (ScreenPtr pScreen, return TRUE; bail4: - EPHYR_DBG("bailed"); + EPHYR_LOG("bailed"); ephyrUnmapFramebuffer (screen); *scrpriv = oldscr; @@ -606,10 +616,40 @@ ephyrInitScreen (ScreenPtr pScreen) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - EPHYR_DBG ("pScreen->myNum:%d\n", pScreen->myNum) ; + EPHYR_LOG ("pScreen->myNum:%d\n", pScreen->myNum) ; hostx_set_screen_number (screen, pScreen->myNum); hostx_set_win_title (screen, "(ctrl+shift grabs mouse and keyboard)") ; pScreen->CreateColormap = ephyrCreateColormap; + +#ifdef XV + if (!ephyrNoXV) { + if (!ephyrInitVideo (pScreen)) { + EPHYR_LOG_ERROR ("failed to initialize xvideo\n") ; + } else { + EPHYR_LOG ("initialized xvideo okay\n") ; + } + } +#endif /*XV*/ + +#ifdef XEPHYR_DRI + if (!ephyrNoDRI && !hostx_has_dri ()) { + EPHYR_LOG ("host x does not support DRI. Disabling DRI forwarding\n") ; + ephyrNoDRI = TRUE ; + noGlxVisualInit = FALSE ; + } + if (!ephyrNoDRI) { + ephyrDRIExtensionInit (pScreen) ; + ephyrHijackGLXExtension () ; + ephyrProxyExtensionInit ("ATIFGLRXDRI") ; + } +#endif + +#ifdef GLXEXT + if (ephyrNoDRI) { + noGlxVisualInit = FALSE ; + } +#endif + return TRUE; } @@ -621,12 +661,12 @@ ephyrFinishInitScreen (ScreenPtr pScreen) */ if (!shadowSetup (pScreen)) return FALSE; - + #ifdef RANDR if (!ephyrRandRInit (pScreen)) return FALSE; #endif - + return TRUE; } @@ -637,7 +677,7 @@ ephyrCreateResources (ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; EphyrScrPriv *scrpriv = screen->driver; - EPHYR_DBG("mark pScreen=%p mynum=%d shadow=%d", + EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d", pScreen, pScreen->myNum, scrpriv->shadow); if (scrpriv->shadow) @@ -809,20 +849,20 @@ ephyrPoll(void) case EPHYR_EV_MOUSE_MOTION: if (!ephyrMouse || !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) { - EPHYR_DBG ("skipping mouse motion:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("skipping mouse motion:%d\n", ephyrCurScreen) ; continue; } { if (ephyrCurScreen != ev.data.mouse_motion.screen) { - EPHYR_DBG ("warping mouse cursor:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("warping mouse cursor:%d\n", ephyrCurScreen) ; ephyrWarpCursor(screenInfo.screens[ev.data.mouse_motion.screen], ev.data.mouse_motion.x, ev.data.mouse_motion.y ); } else { - EPHYR_DBG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ; KdEnqueuePointerEvent(ephyrMouse, mouseState, ev.data.mouse_motion.x, ev.data.mouse_motion.y, @@ -834,10 +874,10 @@ ephyrPoll(void) case EPHYR_EV_MOUSE_PRESS: if (!ephyrMouse || !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) { - EPHYR_DBG ("skipping mouse press:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("skipping mouse press:%d\n", ephyrCurScreen) ; continue; } - EPHYR_DBG ("enqueuing mouse press:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("enqueuing mouse press:%d\n", ephyrCurScreen) ; ephyrUpdateModifierState(ev.key_state); mouseState |= ev.data.mouse_down.button_num; KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); @@ -849,7 +889,7 @@ ephyrPoll(void) continue; ephyrUpdateModifierState(ev.key_state); mouseState &= ~ev.data.mouse_up.button_num; - EPHYR_DBG ("enqueuing mouse release:%d\n", ephyrCurScreen) ; + EPHYR_LOG ("enqueuing mouse release:%d\n", ephyrCurScreen) ; KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); break; @@ -886,7 +926,7 @@ ephyrGetColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs) { /* XXX Not sure if this is right */ - EPHYR_DBG("mark"); + EPHYR_LOG("mark"); while (n--) { @@ -1025,6 +1065,7 @@ EphyrKeyboardBell (KdKeyboardInfo *ki, int volume, int frequency, int duration) { } + KdKeyboardDriver EphyrKeyboardDriver = { "ephyr", EphyrKeyboardInit, diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h index 1c9b4f859..8ed7e23dd 100644 --- a/hw/kdrive/ephyr/ephyr.h +++ b/hw/kdrive/ephyr/ephyr.h @@ -194,4 +194,8 @@ ephyrDrawDisable(ScreenPtr pScreen); void ephyrDrawFini(ScreenPtr pScreen); +/*ephyvideo.c*/ + +Bool ephyrInitVideo(ScreenPtr pScreen) ; + #endif diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c new file mode 100644 index 000000000..53a96ba11 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -0,0 +1,291 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef XEPHYR_DRI + +#include +#include +/*#define _XF86DRI_SERVER_*/ +#include +#include +#include "hostx.h" +#include "ephyrdri.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include "dixstruct.h" +#include "pixmapstr.h" + +#ifndef TRUE +#define TRUE 1 +#endif /*TRUE*/ + +#ifndef FALSE +#define FALSE 0 +#endif /*FALSE*/ + +Bool +ephyrDRIQueryDirectRenderingCapable (int a_screen, Bool *a_is_capable) +{ + Display *dpy=hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_is_capable, FALSE) ; + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIQueryDirectRenderingCapable (dpy, DefaultScreen (dpy), + a_is_capable) ; + EPHYR_LOG ("leave. is_capable:%d, is_ok=%d\n", *a_is_capable, is_ok) ; + + return is_ok ; +} + +Bool +ephyrDRIOpenConnection (int a_screen, + drm_handle_t *a_sarea, + char **a_bus_id_string) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_bus_id_string, FALSE) ; + EPHYR_LOG ("enter. screen:%d\n", a_screen) ; + is_ok = XF86DRIOpenConnection (dpy, DefaultScreen (dpy), + a_sarea, + a_bus_id_string) ; + if (*a_bus_id_string) { + EPHYR_LOG ("leave. bus_id_string:%s, is_ok:%d\n", + *a_bus_id_string, is_ok) ; + } else { + EPHYR_LOG ("leave. bus_id_string:null, is_ok:%d\n", + is_ok) ; + } + return is_ok ; +} + +Bool +ephyrDRIAuthConnection (int a_screen, drm_magic_t a_magic) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIAuthConnection (dpy, DefaultScreen (dpy), a_magic) ; + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + return is_ok ; +} + +Bool +ephyrDRICloseConnection (int a_screen) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRICloseConnection (dpy, DefaultScreen (dpy)) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrDRIGetClientDriverName (int a_screen, + int *a_ddx_driver_major_version, + int *a_ddx_driver_minor_version, + int *a_ddx_driver_patch_version, + char ** a_client_driver_name) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_ddx_driver_major_version + && a_ddx_driver_minor_version + && a_ddx_driver_patch_version + && a_client_driver_name, + FALSE); + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIGetClientDriverName (dpy, DefaultScreen (dpy), + a_ddx_driver_major_version, + a_ddx_driver_minor_version, + a_ddx_driver_patch_version, + a_client_driver_name) ; + EPHYR_LOG ("major:%d, minor:%d, patch:%d, name:%s\n", + *a_ddx_driver_major_version, + *a_ddx_driver_minor_version, + *a_ddx_driver_patch_version, + *a_client_driver_name) ; + EPHYR_LOG ("leave:%d\n", is_ok) ; + return is_ok ; +} + +Bool +ephyrDRICreateContext (int a_screen, + int a_visual_id, + unsigned long int *a_returned_ctxt_id, + drm_context_t *a_hw_ctxt) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + Visual v; + + EPHYR_LOG ("enter. screen:%d, visual:%d\n", a_screen, a_visual_id) ; + memset (&v, 0, sizeof (v)) ; + v.visualid = a_visual_id ; + is_ok = XF86DRICreateContext (dpy, + DefaultScreen (dpy), + &v, + a_returned_ctxt_id, + a_hw_ctxt) ; + EPHYR_LOG ("leave:%d\n", is_ok) ; + return is_ok ; +} + +Bool +ephyrDRIDestroyContext (int a_screen, + int a_context_id) +{ + Display *dpy = hostx_get_display () ; + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIDestroyContext (dpy, DefaultScreen (dpy), a_context_id) ; + EPHYR_LOG ("leave:%d\n", is_ok) ; + return is_ok ; +} + +Bool +ephyrDRICreateDrawable (int a_screen, + int a_drawable, + drm_drawable_t *a_hw_drawable) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; + + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRICreateDrawable (dpy, DefaultScreen (dpy), + a_drawable, a_hw_drawable) ; + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + return is_ok ; +} + +Bool +ephyrDRIDestroyDrawable (int a_screen, int a_drawable) +{ + EPHYR_LOG ("enter\n") ; + EPHYR_LOG_ERROR ("not implemented yet\n") ; + EPHYR_LOG ("leave\n") ; + return FALSE ; +} + +Bool +ephyrDRIGetDrawableInfo (int a_screen, + int a_drawable, + unsigned int *a_index, + unsigned int *a_stamp, + int *a_x, + int *a_y, + int *a_w, + int *a_h, + int *a_num_clip_rects, + drm_clip_rect_t **a_clip_rects, + int *a_back_x, + int *a_back_y, + int *a_num_back_clip_rects, + drm_clip_rect_t **a_back_clip_rects) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; + EphyrHostWindowAttributes attrs ; + + EPHYR_RETURN_VAL_IF_FAIL (a_x && a_y && a_w && a_h + && a_num_clip_rects, + FALSE) ; + + EPHYR_LOG ("enter\n") ; + memset (&attrs, 0, sizeof (attrs)) ; + if (!hostx_get_window_attributes (a_drawable, &attrs)) { + EPHYR_LOG_ERROR ("failed to query host window attributes\n") ; + goto out; + } + if (!XF86DRIGetDrawableInfo (dpy, DefaultScreen (dpy), a_drawable, + a_index, a_stamp, + a_x, a_y, + a_w, a_h, + a_num_clip_rects, a_clip_rects, + a_back_x, a_back_y, + a_num_back_clip_rects, + a_back_clip_rects)) { + EPHYR_LOG_ERROR ("XF86DRIGetDrawableInfo ()\n") ; + goto out ; + } + EPHYR_LOG ("host x,y,w,h: (%d,%d,%d,%d)\n", *a_x, *a_y, *a_w, *a_h) ; + if (*a_num_clip_rects) { + free (*a_back_clip_rects) ; + *a_back_clip_rects = calloc (*a_num_clip_rects, + sizeof (drm_clip_rect_t)) ; + memmove (*a_back_clip_rects, + *a_clip_rects, + *a_num_clip_rects * sizeof (drm_clip_rect_t)) ; + *a_num_back_clip_rects = *a_num_clip_rects; + } + EPHYR_LOG ("num back clip rects:%d, num clip rects:%d\n", + *a_num_clip_rects, *a_num_back_clip_rects) ; + *a_back_x = *a_x ; + *a_back_y = *a_y ; + *a_w = attrs.width; + *a_h = attrs.height; + + is_ok = TRUE ; +out: + EPHYR_LOG ("leave. index:%d, stamp:%d, x,y:(%d,%d), w,y:(%d,%d)\n", + *a_index, *a_stamp, *a_x, *a_y, *a_w, *a_h) ; + return is_ok ; +} + +Bool +ephyrDRIGetDeviceInfo (int a_screen, + drm_handle_t *a_frame_buffer, + int *a_fb_origin, + int *a_fb_size, + int *a_fb_stride, + int *a_dev_private_size, + void **a_dev_private) +{ + Bool is_ok = FALSE ; + Display *dpy = hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + EPHYR_LOG ("enter\n") ; + is_ok = XF86DRIGetDeviceInfo (dpy, DefaultScreen (dpy), a_frame_buffer, + a_fb_origin, a_fb_size, a_fb_stride, + a_dev_private_size, a_dev_private) ; + EPHYR_LOG ("leave:%d\n", is_ok) ; + return is_ok ; +} +#endif /*EPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/ephyrdri.h b/hw/kdrive/ephyr/ephyrdri.h new file mode 100644 index 000000000..af8bb11fd --- /dev/null +++ b/hw/kdrive/ephyr/ephyrdri.h @@ -0,0 +1,75 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ + +#ifndef __EPHYRDRI_H__ +#define __EPHYRDRI_H__ + +#include + +Bool ephyrDRIQueryDirectRenderingCapable (int a_screen, Bool *a_is_capable) ; +Bool ephyrDRIOpenConnection (int screen, drm_handle_t *a_sarea, char **a_bus_id_string) ; +Bool ephyrDRIAuthConnection (int a_screen, drm_magic_t a_magic) ; +Bool ephyrDRICloseConnection (int a_screen) ; +Bool ephyrDRIGetClientDriverName (int a_screen, + int *a_ddx_driver_major_version, + int *a_ddx_driver_minor_version, + int *a_ddx_driver_patch_version, + char ** a_client_driver_name) ; +Bool ephyrDRICreateContext (int a_screen, + int a_visual_id, + unsigned long int *a_returned_ctx_id, + drm_context_t *a_hw_ctx) ; +Bool ephyrDRIDestroyContext (int a_screen, + int a_context_id) ; +Bool ephyrDRICreateDrawable (int a_screen, + int a_drawable, + drm_drawable_t *a_hw_drawable) ; +Bool ephyrDRIDestroyDrawable (int a_screen, int a_drawable) ; +Bool ephyrDRIGetDrawableInfo (int a_screen, + int /*Drawable*/a_drawable, + unsigned int *a_index, + unsigned int *a_stamp, + int *a_x, + int *a_y, + int *a_w, + int *a_h, + int *a_num_clip_rects, + drm_clip_rect_t **a_clip_rects, + int *a_back_x, + int *a_back_y, + int *num_back_clip_rects, + drm_clip_rect_t **a_back_clip_rects) ; +Bool ephyrDRIGetDeviceInfo (int a_screen, + drm_handle_t *a_frame_buffer, + int *a_fb_origin, + int *a_fb_size, + int *a_fb_stride, + int *a_dev_private_size, + void **a_dev_private) ; +#endif /*__EPHYRDRI_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c new file mode 100644 index 000000000..e3d0cfbb4 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -0,0 +1,1448 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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 file is heavily copied from hw/xfree86/dri/xf86dri.c + * + * Authors: + * Dodji Seketeli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef XEPHYR_DRI + +#include + +#define NEED_REPLIES +#define NEED_EVENTS +#include +#include +#define _XF86DRI_SERVER_ +#include +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "swaprep.h" +#include "ephyrdri.h" +#include "ephyrdriext.h" +#include "hostx.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" + +typedef struct { + WindowPtr local ; + int remote ; +} EphyrWindowPair; + +typedef struct { + int foo; +} EphyrDRIWindowPrivRec; +typedef EphyrDRIWindowPrivRec* EphyrDRIWindowPrivPtr; + +typedef struct { + CreateWindowProcPtr CreateWindow ; + DestroyWindowProcPtr DestroyWindow ; + MoveWindowProcPtr MoveWindow ; + PositionWindowProcPtr PositionWindow ; + ClipNotifyProcPtr ClipNotify ; +} EphyrDRIScreenPrivRec; +typedef EphyrDRIScreenPrivRec* EphyrDRIScreenPrivPtr; + +static int DRIErrorBase; + +static DISPATCH_PROC(ProcXF86DRIQueryVersion); +static DISPATCH_PROC(ProcXF86DRIQueryDirectRenderingCapable); +static DISPATCH_PROC(ProcXF86DRIOpenConnection); +static DISPATCH_PROC(ProcXF86DRICloseConnection); +static DISPATCH_PROC(ProcXF86DRIGetClientDriverName); +static DISPATCH_PROC(ProcXF86DRICreateContext); +static DISPATCH_PROC(ProcXF86DRIDestroyContext); +static DISPATCH_PROC(ProcXF86DRICreateDrawable); +static DISPATCH_PROC(ProcXF86DRIDestroyDrawable); +static DISPATCH_PROC(ProcXF86DRIGetDrawableInfo); +static DISPATCH_PROC(ProcXF86DRIGetDeviceInfo); +static DISPATCH_PROC(ProcXF86DRIDispatch); +static DISPATCH_PROC(ProcXF86DRIAuthConnection); + +static DISPATCH_PROC(SProcXF86DRIQueryVersion); +static DISPATCH_PROC(SProcXF86DRIQueryDirectRenderingCapable); +static DISPATCH_PROC(SProcXF86DRIDispatch); + +static void XF86DRIResetProc(ExtensionEntry* extEntry); + +static Bool ephyrDRIScreenInit (ScreenPtr a_screen) ; +static Bool ephyrDRICreateWindow (WindowPtr a_win) ; +static Bool ephyrDRIDestroyWindow (WindowPtr a_win) ; +static void ephyrDRIMoveWindow (WindowPtr a_win, + int a_x, int a_y, + WindowPtr a_siblings, + VTKind a_kind); +static Bool ephyrDRIPositionWindow (WindowPtr a_win, + int x, int y) ; +static void ephyrDRIClipNotify (WindowPtr a_win, + int a_x, int a_y) ; + +static Bool EphyrMirrorHostVisuals (ScreenPtr a_screen) ; +static Bool destroyHostPeerWindow (const WindowPtr a_win) ; +static Bool findWindowPairFromLocal (WindowPtr a_local, + EphyrWindowPair **a_pair); + +static unsigned char DRIReqCode = 0; + +static int ephyrDRIGeneration=-1 ; +static int ephyrDRIWindowIndex=-1 ; +static int ephyrDRIScreenIndex=-1 ; + +#define GET_EPHYR_DRI_WINDOW_PRIV(win) \ + ((EphyrDRIWindowPrivPtr)((win)->devPrivates[ephyrDRIWindowIndex].ptr)) +#define GET_EPHYR_DRI_SCREEN_PRIV(screen) \ + ((EphyrDRIScreenPrivPtr)((screen)->devPrivates[ephyrDRIScreenIndex].ptr)) + + +Bool +ephyrDRIExtensionInit (ScreenPtr a_screen) +{ + Bool is_ok=FALSE ; + ExtensionEntry* extEntry=NULL; + EphyrDRIScreenPrivPtr screen_priv=NULL ; + + EPHYR_LOG ("enter\n") ; + if (!hostx_has_dri ()) { + EPHYR_LOG ("host does not have DRI extension\n") ; + goto out ; + } + EPHYR_LOG ("host X does have DRI extension\n") ; + if (!hostx_has_xshape ()) { + EPHYR_LOG ("host does not have XShape extension\n") ; + goto out ; + } + EPHYR_LOG ("host X does have XShape extension\n") ; + +#ifdef XF86DRI_EVENTS + EventType = CreateNewResourceType (XF86DRIFreeEvents); +#endif + + if ((extEntry = AddExtension(XF86DRINAME, + XF86DRINumberEvents, + XF86DRINumberErrors, + ProcXF86DRIDispatch, + SProcXF86DRIDispatch, + XF86DRIResetProc, + StandardMinorOpcode))) { + DRIReqCode = (unsigned char)extEntry->base; + DRIErrorBase = extEntry->errorBase; + } else { + EPHYR_LOG_ERROR ("failed to register DRI extension\n") ; + goto out ; + } + if (ephyrDRIGeneration != serverGeneration) { + ephyrDRIScreenIndex = AllocateScreenPrivateIndex () ; + if (ephyrDRIScreenIndex < 0) { + EPHYR_LOG_ERROR ("failed to allocate screen priv index\n") ; + goto out ; + } + } + screen_priv = xcalloc (1, sizeof (EphyrDRIScreenPrivRec)) ; + if (!screen_priv) { + EPHYR_LOG_ERROR ("failed to allocate screen_priv\n") ; + goto out ; + } + a_screen->devPrivates[ephyrDRIScreenIndex].ptr = screen_priv; + + if (!ephyrDRIScreenInit (a_screen)) { + EPHYR_LOG_ERROR ("ephyrDRIScreenInit() failed\n") ; + goto out ; + } + EphyrMirrorHostVisuals (a_screen) ; + if (ephyrDRIGeneration != serverGeneration) { + ephyrDRIGeneration = serverGeneration ; + } + is_ok=TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrDRIScreenInit (ScreenPtr a_screen) +{ + Bool is_ok=FALSE ; + EphyrDRIScreenPrivPtr screen_priv=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_screen, FALSE) ; + + screen_priv=GET_EPHYR_DRI_SCREEN_PRIV (a_screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv, FALSE) ; + + if (ephyrDRIGeneration != serverGeneration) { + ephyrDRIWindowIndex = AllocateWindowPrivateIndex () ; + if (ephyrDRIWindowIndex < 0) { + EPHYR_LOG_ERROR ("failed to allocate window priv index\n") ; + goto out ; + } + } + if (!AllocateWindowPrivate (a_screen, ephyrDRIWindowIndex, 0)) { + EPHYR_LOG_ERROR ("failed to allocate window privates\n") ; + goto out ; + } + screen_priv->CreateWindow = a_screen->CreateWindow ; + screen_priv->DestroyWindow = a_screen->DestroyWindow ; + screen_priv->MoveWindow = a_screen->MoveWindow ; + screen_priv->PositionWindow = a_screen->PositionWindow ; + screen_priv->ClipNotify = a_screen->ClipNotify ; + + a_screen->CreateWindow = ephyrDRICreateWindow ; + a_screen->DestroyWindow = ephyrDRIDestroyWindow ; + a_screen->MoveWindow = ephyrDRIMoveWindow ; + a_screen->PositionWindow = ephyrDRIPositionWindow ; + a_screen->ClipNotify = ephyrDRIClipNotify ; + + is_ok = TRUE ; +out: + return is_ok ; +} + +static Bool +ephyrDRICreateWindow (WindowPtr a_win) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->CreateWindow, + FALSE) ; + + EPHYR_LOG ("enter. win:%#x\n", + (unsigned int)a_win) ; + + screen->CreateWindow = screen_priv->CreateWindow ; + is_ok = (*screen->CreateWindow) (a_win) ; + screen->CreateWindow = ephyrDRICreateWindow ; + + if (is_ok) { + a_win->devPrivates[ephyrDRIWindowIndex].ptr = NULL ; + } + return is_ok ; +} + +static Bool +ephyrDRIDestroyWindow (WindowPtr a_win) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->DestroyWindow, + FALSE) ; + + screen->DestroyWindow = screen_priv->DestroyWindow ; + if (screen->DestroyWindow) { + is_ok = (*screen->DestroyWindow) (a_win) ; + } + screen->DestroyWindow = ephyrDRIDestroyWindow ; + + if (is_ok) { + EphyrDRIWindowPrivPtr win_priv=GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (win_priv) { + destroyHostPeerWindow (a_win) ; + xfree (win_priv) ; + a_win->devPrivates[ephyrDRIWindowIndex].ptr = NULL ; + EPHYR_LOG ("destroyed the remote peer window\n") ; + } + } + return is_ok ; +} + +static void +ephyrDRIMoveWindow (WindowPtr a_win, + int a_x, int a_y, + WindowPtr a_siblings, + VTKind a_kind) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrBox geo; + int x=0,y=0;/*coords relative to parent window*/ + + EPHYR_RETURN_IF_FAIL (a_win) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_IF_FAIL (screen) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_IF_FAIL (screen_priv + && screen_priv->MoveWindow) ; + + screen->MoveWindow = screen_priv->MoveWindow ; + if (screen->MoveWindow) { + (*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ; + } + screen->MoveWindow = ephyrDRIMoveWindow ; + + EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ; + if (!a_win->parent) { + EPHYR_LOG ("cannot move root window\n") ; + is_ok = TRUE ; + goto out ; + } + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + /*compute position relative to parent window*/ + x = a_win->drawable.x - a_win->parent->drawable.x ; + y = a_win->drawable.y - a_win->parent->drawable.y ; + /*set the geometry to pass to hostx_set_window_geometry*/ + memset (&geo, 0, sizeof (geo)) ; + geo.x = x ; + geo.y = y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + hostx_set_window_geometry (pair->remote, &geo) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ +} + +static Bool +ephyrDRIPositionWindow (WindowPtr a_win, + int a_x, int a_y) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrBox geo; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->PositionWindow, + FALSE) ; + + screen->PositionWindow = screen_priv->PositionWindow ; + if (screen->PositionWindow) { + (*screen->PositionWindow) (a_win, a_x, a_y) ; + } + screen->PositionWindow = ephyrDRIPositionWindow ; + + EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ; + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + /*set the geometry to pass to hostx_set_window_geometry*/ + memset (&geo, 0, sizeof (geo)) ; + geo.x = a_x ; + geo.y = a_y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + hostx_set_window_geometry (pair->remote, &geo) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ + return is_ok ; +} + +static void +ephyrDRIClipNotify (WindowPtr a_win, + int a_x, int a_y) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrRect *rects=NULL; + int i=0 ; + + EPHYR_RETURN_IF_FAIL (a_win) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_IF_FAIL (screen) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_IF_FAIL (screen_priv && screen_priv->ClipNotify) ; + + screen->ClipNotify = screen_priv->ClipNotify ; + if (screen->ClipNotify) { + (*screen->ClipNotify) (a_win, a_x, a_y) ; + } + screen->ClipNotify = ephyrDRIClipNotify ; + + EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ; + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + rects = xcalloc (REGION_NUM_RECTS (&a_win->clipList), + sizeof (EphyrRect)) ; + for (i=0; i < REGION_NUM_RECTS (&a_win->clipList); i++) { + memmove (&rects[i], + ®ION_RECTS (&a_win->clipList)[i], + sizeof (EphyrRect)) ; + rects[i].x1 -= a_win->drawable.x; + rects[i].x2 -= a_win->drawable.x; + rects[i].y1 -= a_win->drawable.y; + rects[i].y2 -= a_win->drawable.y; + } + /* + * push the clipping region of this window + * to the peer window in the host + */ + is_ok = hostx_set_window_bounding_rectangles + (pair->remote, + rects, + REGION_NUM_RECTS (&a_win->clipList)) ; + is_ok = TRUE ; + +out: + if (rects) { + xfree (rects) ; + rects = NULL ; + } + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ +} + +/** + * Duplicates a visual of a_screen + * In screen a_screen, for depth a_depth, find a visual which + * bitsPerRGBValue and colormap size equal + * a_bits_per_rgb_values and a_colormap_entries. + * The ID of that duplicated visual is set to a_new_id. + * That duplicated visual is then added to the list of visuals + * of the screen. + */ +static Bool +EphyrDuplicateVisual (unsigned int a_screen, + short a_depth, + short a_class, + short a_bits_per_rgb_values, + short a_colormap_entries, + unsigned int a_red_mask, + unsigned int a_green_mask, + unsigned int a_blue_mask, + unsigned int a_new_id) +{ + Bool is_ok = FALSE, found_visual=FALSE, found_depth=FALSE ; + ScreenPtr screen=NULL ; + VisualRec new_visual, *new_visuals=NULL ; + int i=0 ; + + EPHYR_LOG ("enter\n") ; + if (a_screen > screenInfo.numScreens) { + EPHYR_LOG_ERROR ("bad screen number\n") ; + goto out; + } + memset (&new_visual, 0, sizeof (VisualRec)) ; + + /*get the screen pointed to by a_screen*/ + screen = screenInfo.screens[a_screen] ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + + /* + * In that screen, first look for an existing visual that has the + * same characteristics as those passed in parameter + * to this function and copy it. + */ + for (i=0; i < screen->numVisuals; i++) { + if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values && + screen->visuals[i].ColormapEntries == a_colormap_entries ) { + /*copy the visual found*/ + memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ; + new_visual.vid = a_new_id ; + new_visual.class = a_class ; + new_visual.redMask = a_red_mask ; + new_visual.greenMask = a_green_mask ; + new_visual.blueMask = a_blue_mask ; + found_visual = TRUE ; + EPHYR_LOG ("found a visual that matches visual id: %d\n", + a_new_id) ; + break; + } + } + if (!found_visual) { + EPHYR_LOG ("did not find any visual matching %d\n", a_new_id) ; + goto out ; + } + /* + * be prepare to extend screen->visuals to add new_visual to it + */ + new_visuals = xcalloc (screen->numVisuals+1, sizeof (VisualRec)) ; + memmove (new_visuals, + screen->visuals, + screen->numVisuals*sizeof (VisualRec)) ; + memmove (&new_visuals[screen->numVisuals], + &new_visual, + sizeof (VisualRec)) ; + /* + * Now, in that same screen, update the screen->allowedDepths member. + * In that array, each element represents the visuals applicable to + * a given depth. So we need to add an entry matching the new visual + * that we are going to add to screen->visuals + */ + for (i=0; inumDepths; i++) { + VisualID *vids=NULL; + DepthPtr cur_depth=NULL ; + /*find the entry matching a_depth*/ + if (screen->allowedDepths[i].depth != a_depth) + continue ; + cur_depth = &screen->allowedDepths[i]; + /* + * extend the list of visual IDs in that entry, + * so to add a_new_id in there. + */ + vids = xrealloc (cur_depth->vids, + (cur_depth->numVids+1)*sizeof (VisualID)); + if (!vids) { + EPHYR_LOG_ERROR ("failed to realloc numids\n") ; + goto out ; + } + vids[cur_depth->numVids] = a_new_id ; + /* + * Okay now commit our change. + * Do really update screen->allowedDepths[i] + */ + cur_depth->numVids++ ; + cur_depth->vids = vids ; + found_depth=TRUE; + } + if (!found_depth) { + EPHYR_LOG_ERROR ("failed to update screen[%d]->allowedDepth\n", + a_screen) ; + goto out ; + } + /* + * Commit our change to screen->visuals + */ + xfree (screen->visuals) ; + screen->visuals = new_visuals ; + screen->numVisuals++ ; + new_visuals = NULL ; + + is_ok = TRUE ; +out: + if (new_visuals) { + xfree (new_visuals) ; + new_visuals = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +/** + * Duplicates the visuals of the host X server. + * This is necessary to have visuals that have the same + * ID as those of the host X. It is important to have that for + * GLX. + */ +static Bool +EphyrMirrorHostVisuals (ScreenPtr a_screen) +{ + Bool is_ok=FALSE; + EphyrHostVisualInfo *visuals=NULL; + int nb_visuals=0, i=0; + + EPHYR_LOG ("enter\n") ; + if (!hostx_get_visuals_info (&visuals, &nb_visuals)) { + EPHYR_LOG_ERROR ("failed to get host visuals\n") ; + goto out ; + } + for (i=0; imyNum, + visuals[i].depth, + visuals[i].class, + visuals[i].bits_per_rgb, + visuals[i].colormap_size, + visuals[i].red_mask, + visuals[i].green_mask, + visuals[i].blue_mask, + visuals[i].visualid)) { + EPHYR_LOG_ERROR ("failed to duplicate host visual %d\n", + (int)visuals[i].visualid) ; + } + } + + is_ok = TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok; +} + + +/*ARGSUSED*/ +static void +XF86DRIResetProc ( + ExtensionEntry* extEntry +) +{ +} + +static int +ProcXF86DRIQueryVersion (register ClientPtr client) +{ + xXF86DRIQueryVersionReply rep; + register int n; + + EPHYR_LOG ("enter\n") ; + + REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XF86DRI_MAJOR_VERSION; + rep.minorVersion = XF86DRI_MINOR_VERSION; + rep.patchVersion = XF86DRI_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swapl(&rep.patchVersion, n); + } + WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client) +{ + xXF86DRIQueryDirectRenderingCapableReply rep; + Bool isCapable; + register int n; + + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!ephyrDRIQueryDirectRenderingCapable (stuff->screen, &isCapable)) { + return BadValue; + } + rep.isCapable = isCapable; + + if (!LocalClient(client) || client->swapped) + rep.isCapable = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + + WriteToClient(client, sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + + return (client->noClientException); +} + +static int +ProcXF86DRIOpenConnection (register ClientPtr client) +{ + xXF86DRIOpenConnectionReply rep; + drm_handle_t hSAREA; + char* busIdString; + + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRIOpenConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!ephyrDRIOpenConnection(stuff->screen, + &hSAREA, + &busIdString)) { + return BadValue; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.busIdStringLength = 0; + if (busIdString) + rep.busIdStringLength = strlen(busIdString); + rep.length = (SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + + ((rep.busIdStringLength + 3) & ~3)) >> 2; + + rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hSAREAHigh = (CARD32)(hSAREA >> 32); +#else + rep.hSAREAHigh = 0; +#endif + + WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); + if (rep.busIdStringLength) + WriteToClient(client, rep.busIdStringLength, busIdString); + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRIAuthConnection (register ClientPtr client) +{ + xXF86DRIAuthConnectionReply rep; + + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRIAuthConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.authenticated = 1; + + if (!ephyrDRIAuthConnection (stuff->screen, stuff->magic)) { + ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); + rep.authenticated = 0; + } + WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRICloseConnection (register ClientPtr client) +{ + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRICloseConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + /* + DRICloseConnection( screenInfo.screens[stuff->screen]); + */ + + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRIGetClientDriverName (register ClientPtr client) +{ + xXF86DRIGetClientDriverNameReply rep; + char* clientDriverName; + + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRIGetClientDriverNameReq); + REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + ephyrDRIGetClientDriverName (stuff->screen, + (int *)&rep.ddxDriverMajorVersion, + (int *)&rep.ddxDriverMinorVersion, + (int *)&rep.ddxDriverPatchVersion, + &clientDriverName); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.clientDriverNameLength = 0; + if (clientDriverName) + rep.clientDriverNameLength = strlen(clientDriverName); + rep.length = (SIZEOF(xXF86DRIGetClientDriverNameReply) - + SIZEOF(xGenericReply) + + ((rep.clientDriverNameLength + 3) & ~3)) >> 2; + + WriteToClient(client, + sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); + if (rep.clientDriverNameLength) + WriteToClient(client, + rep.clientDriverNameLength, + clientDriverName); + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRICreateContext (register ClientPtr client) +{ + xXF86DRICreateContextReply rep; + ScreenPtr pScreen; + VisualPtr visual; + int i=0; + unsigned long context_id=0; + + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRICreateContextReq); + REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + pScreen = screenInfo.screens[stuff->screen]; + visual = pScreen->visuals; + + /* Find the requested X visual */ + for (i = 0; i < pScreen->numVisuals; i++, visual++) + if (visual->vid == stuff->visual) + break; + if (i == pScreen->numVisuals) { + /* No visual found */ + return BadValue; + } + + context_id = stuff->context ; + if (!ephyrDRICreateContext (stuff->screen, + stuff->visual, + &context_id, + (drm_context_t *)&rep.hHWContext)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRIDestroyContext (register ClientPtr client) +{ + EPHYR_LOG ("enter\n") ; + + REQUEST(xXF86DRIDestroyContextReq); + REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!ephyrDRIDestroyContext (stuff->screen, stuff->context)) { + return BadValue; + } + + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static Bool +getWindowVisual (const WindowPtr a_win, + VisualPtr *a_visual) +{ + int i=0, visual_id=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_win + && a_win->drawable.pScreen + && a_win->drawable.pScreen->visuals, + FALSE) ; + + visual_id = wVisual (a_win) ; + for (i=0; i < a_win->drawable.pScreen->numVisuals; i++) { + if (a_win->drawable.pScreen->visuals[i].vid == visual_id) { + *a_visual = &a_win->drawable.pScreen->visuals[i] ; + return TRUE ; + } + } + return FALSE ; +} + + +#define NUM_WINDOW_PAIRS 256 +static EphyrWindowPair window_pairs[NUM_WINDOW_PAIRS] ; + +static Bool +appendWindowPairToList (WindowPtr a_local, + int a_remote) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_local, FALSE) ; + + EPHYR_LOG ("(local,remote):(%#x, %d)\n", (unsigned int)a_local, a_remote) ; + + for (i=0; i < NUM_WINDOW_PAIRS; i++) { + if (window_pairs[i].local == NULL) { + window_pairs[i].local = a_local ; + window_pairs[i].remote = a_remote ; + return TRUE ; + } + } + return FALSE ; +} + +static Bool +findWindowPairFromLocal (WindowPtr a_local, + EphyrWindowPair **a_pair) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_pair && a_local, FALSE) ; + + for (i=0; i < NUM_WINDOW_PAIRS; i++) { + if (window_pairs[i].local == a_local) { + *a_pair = &window_pairs[i] ; + EPHYR_LOG ("found (%#x, %d)\n", + (unsigned int)(*a_pair)->local, + (*a_pair)->remote) ; + return TRUE ; + } + } + return FALSE ; +} + +static Bool +createHostPeerWindow (const WindowPtr a_win, + int *a_peer_win) +{ + Bool is_ok=FALSE ; + VisualPtr visual=NULL; + EphyrBox geo ; + + EPHYR_RETURN_VAL_IF_FAIL (a_win && a_peer_win, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_win->drawable.pScreen, + FALSE) ; + + EPHYR_LOG ("enter. a_win '%#x'\n", (unsigned int)a_win) ; + if (!getWindowVisual (a_win, &visual)) { + EPHYR_LOG_ERROR ("failed to get window visual\n") ; + goto out ; + } + if (!visual) { + EPHYR_LOG_ERROR ("failed to create visual\n") ; + goto out ; + } + memset (&geo, 0, sizeof (geo)) ; + geo.x = a_win->drawable.x ; + geo.y = a_win->drawable.y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + if (!hostx_create_window (a_win->drawable.pScreen->myNum, + &geo, visual->vid, a_peer_win)) { + EPHYR_LOG_ERROR ("failed to create host peer window\n") ; + goto out ; + } + if (!appendWindowPairToList (a_win, *a_peer_win)) { + EPHYR_LOG_ERROR ("failed to append window to pair list\n") ; + goto out ; + } + is_ok = TRUE ; +out: + EPHYR_LOG ("leave:remote win%d\n", *a_peer_win) ; + return is_ok ; +} + +static Bool +destroyHostPeerWindow (const WindowPtr a_win) +{ + Bool is_ok = FALSE ; + EphyrWindowPair *pair=NULL ; + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to find peer to local window\n") ; + goto out; + } + hostx_destroy_window (pair->remote) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok; +} + +static int +ProcXF86DRICreateDrawable (ClientPtr client) +{ + xXF86DRICreateDrawableReply rep; + DrawablePtr drawable=NULL; + WindowPtr window=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrDRIWindowPrivPtr win_priv=NULL; + int rc=0, remote_win=0; + + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRICreateDrawableReq); + REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable (&drawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ; + return BadImplementation ; + } + EPHYR_LOG ("lookedup drawable %#x\n", (unsigned int)drawable) ; + window = (WindowPtr)drawable; + if (findWindowPairFromLocal (window, &pair) && pair) { + remote_win = pair->remote ; + EPHYR_LOG ("found window '%#x' paire with remote '%d'\n", + (unsigned int)window, remote_win) ; + } else if (!createHostPeerWindow (window, &remote_win)) { + EPHYR_LOG_ERROR ("failed to create host peer window\n") ; + return BadAlloc ; + } + + if (!ephyrDRICreateDrawable (stuff->screen, + remote_win, + (drm_drawable_t *)&rep.hHWDrawable)) { + EPHYR_LOG_ERROR ("failed to create dri drawable\n") ; + return BadValue; + } + + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (window) ; + if (!win_priv) { + win_priv = xcalloc (1, sizeof (EphyrDRIWindowPrivRec)) ; + if (!win_priv) { + EPHYR_LOG_ERROR ("failed to allocate window private\n") ; + return BadAlloc ; + } + window->devPrivates[ephyrDRIWindowIndex].ptr = win_priv ; + EPHYR_LOG ("paired window '%#x' with remote '%d'\n", + (unsigned int)window, remote_win) ; + } + + WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRIDestroyDrawable (register ClientPtr client) +{ + REQUEST(xXF86DRIDestroyDrawableReq); + DrawablePtr drawable=NULL; + WindowPtr window=NULL; + EphyrWindowPair *pair=NULL; + REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); + int rc=0; + + EPHYR_LOG ("enter\n") ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rc = dixLookupDrawable(&drawable, + stuff->drawable, + client, + 0, + DixReadAccess); + if (rc != Success) + return rc; + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ; + return BadImplementation ; + } + window = (WindowPtr)drawable; + if (!findWindowPairFromLocal (window, &pair) && pair) { + EPHYR_LOG_ERROR ("failed to find pair window\n") ; + return BadImplementation; + } + if (!ephyrDRIDestroyDrawable(stuff->screen, + pair->remote/*drawable in host x*/)) { + EPHYR_LOG_ERROR ("failed to destroy dri drawable\n") ; + return BadImplementation; + } + pair->local=NULL ; + pair->remote=0; + + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRIGetDrawableInfo (register ClientPtr client) +{ + xXF86DRIGetDrawableInfoReply rep; + DrawablePtr drawable; + WindowPtr window=NULL; + EphyrWindowPair *pair=NULL; + int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0, i=0; + drm_clip_rect_t *clipRects=NULL; + drm_clip_rect_t *backClipRects=NULL; + + EPHYR_LOG ("enter\n") ; + memset (&rep, 0, sizeof (rep)) ; + REQUEST(xXF86DRIGetDrawableInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success || !drawable) { + EPHYR_LOG_ERROR ("could not get drawable\n") ; + return rc; + } + + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non windows type drawables are not yes supported\n") ; + return BadImplementation ; + } + window = (WindowPtr)drawable ; + memset (&pair, 0, sizeof (pair)) ; + if (!findWindowPairFromLocal (window, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to find remote peer drawable\n") ; + return BadMatch ; + } + EPHYR_LOG ("clip list of xephyr gl drawable:\n") ; + for (i=0; i < REGION_NUM_RECTS (&window->clipList); i++) { + EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", + REGION_RECTS (&window->clipList)[i].x1, + REGION_RECTS (&window->clipList)[i].y1, + REGION_RECTS (&window->clipList)[i].x2, + REGION_RECTS (&window->clipList)[i].y2) ; + } + + if (!ephyrDRIGetDrawableInfo (stuff->screen, + pair->remote/*the drawable in hostx*/, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &clipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &backClipRects)) { + return BadValue; + } + EPHYR_LOG ("num clip rects:%d, num back clip rects:%d\n", + (int)rep.numClipRects, (int)rep.numBackClipRects) ; + + rep.drawableX = X; + rep.drawableY = Y; + rep.drawableWidth = W; + rep.drawableHeight = H; + rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - + SIZEOF(xGenericReply)); + + rep.backX = backX; + rep.backY = backY; + + + if (rep.numClipRects) { + if (clipRects) { + ScreenPtr pScreen = screenInfo.screens[stuff->screen]; + int i=0; + EPHYR_LOG ("clip list of host gl drawable:\n") ; + for (i = 0; i < rep.numClipRects; i++) { + clipRects[i].x1 = max (clipRects[i].x1, 0); + clipRects[i].y1 = max (clipRects[i].y1, 0); + clipRects[i].x2 = min (clipRects[i].x2, + pScreen->width + clipRects[i].x1) ; + clipRects[i].y2 = min (clipRects[i].y2, + pScreen->width + clipRects[i].y1) ; + + EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", + clipRects[i].x1, clipRects[i].y1, + clipRects[i].x2, clipRects[i].y2) ; + } + } else { + rep.numClipRects = 0; + } + } else { + EPHYR_LOG ("got zero host gl drawable clipping rects\n") ; + } + rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + backClipRects = clipRects ; + rep.numBackClipRects = rep.numClipRects ; + if (rep.numBackClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + EPHYR_LOG ("num host clip rects:%d\n", (int)rep.numClipRects) ; + EPHYR_LOG ("num host back clip rects:%d\n", (int)rep.numBackClipRects) ; + + rep.length = ((rep.length + 3) & ~3) >> 2; + + WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); + + if (rep.numClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numClipRects, + (char *)clipRects); + } + + if (rep.numBackClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numBackClipRects, + (char *)backClipRects); + } + if (clipRects) { + xfree(clipRects); + clipRects = NULL ; + } + EPHYR_LOG ("leave\n") ; + + return (client->noClientException); +} + +static int +ProcXF86DRIGetDeviceInfo (register ClientPtr client) +{ + xXF86DRIGetDeviceInfoReply rep; + drm_handle_t hFrameBuffer; + void *pDevPrivate; + + EPHYR_LOG ("enter\n") ; + REQUEST(xXF86DRIGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!ephyrDRIGetDeviceInfo (stuff->screen, + &hFrameBuffer, + (int*)&rep.framebufferOrigin, + (int*)&rep.framebufferSize, + (int*)&rep.framebufferStride, + (int*)&rep.devPrivateSize, + &pDevPrivate)) { + return BadValue; + } + + rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); +#else + rep.hFrameBufferHigh = 0; +#endif + + rep.length = 0; + if (rep.devPrivateSize) { + rep.length = (SIZEOF(xXF86DRIGetDeviceInfoReply) - + SIZEOF(xGenericReply) + + ((rep.devPrivateSize + 3) & ~3)) >> 2; + } + + WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); + if (rep.length) { + WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); + } + EPHYR_LOG ("leave\n") ; + return (client->noClientException); +} + +static int +ProcXF86DRIDispatch (register ClientPtr client) +{ + REQUEST(xReq); + EPHYR_LOG ("enter\n") ; + + switch (stuff->data) + { + case X_XF86DRIQueryVersion: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIQueryVersion(client); + } + case X_XF86DRIQueryDirectRenderingCapable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIQueryDirectRenderingCapable(client); + } + } + + if (!LocalClient(client)) + return DRIErrorBase + XF86DRIClientNotLocal; + + switch (stuff->data) + { + case X_XF86DRIOpenConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIOpenConnection(client); + } + case X_XF86DRICloseConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICloseConnection(client); + } + case X_XF86DRIGetClientDriverName: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetClientDriverName(client); + } + case X_XF86DRICreateContext: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICreateContext(client); + } + case X_XF86DRIDestroyContext: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIDestroyContext(client); + } + case X_XF86DRICreateDrawable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICreateDrawable(client); + } + case X_XF86DRIDestroyDrawable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIDestroyDrawable(client); + } + case X_XF86DRIGetDrawableInfo: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetDrawableInfo(client); + } + case X_XF86DRIGetDeviceInfo: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetDeviceInfo(client); + } + case X_XF86DRIAuthConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIAuthConnection(client); + } + /* {Open,Close}FullScreen are deprecated now */ + default: { + EPHYR_LOG ("leave\n") ; + return BadRequest; + } + } +} + +static int +SProcXF86DRIQueryVersion (register ClientPtr client) +{ + register int n; + REQUEST(xXF86DRIQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86DRIQueryVersion(client); +} + +static int +SProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client) +{ + register int n; + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + swaps(&stuff->length, n); + swapl(&stuff->screen, n); + return ProcXF86DRIQueryDirectRenderingCapable(client); +} + +static int +SProcXF86DRIDispatch (register ClientPtr client) +{ + REQUEST(xReq); + + EPHYR_LOG ("enter\n") ; + /* + * Only local clients are allowed DRI access, but remote clients still need + * these requests to find out cleanly. + */ + switch (stuff->data) + { + case X_XF86DRIQueryVersion: { + EPHYR_LOG ("leave\n") ; + return SProcXF86DRIQueryVersion(client); + } + case X_XF86DRIQueryDirectRenderingCapable: { + EPHYR_LOG ("leave\n") ; + return SProcXF86DRIQueryDirectRenderingCapable(client); + } + default: { + EPHYR_LOG ("leave\n") ; + return DRIErrorBase + XF86DRIClientNotLocal; + } + } +} + +#endif /*XEPHYR_DRI*/ diff --git a/hw/kdrive/ephyr/ephyrdriext.h b/hw/kdrive/ephyr/ephyrdriext.h new file mode 100644 index 000000000..66af833b9 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrdriext.h @@ -0,0 +1,32 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifndef __EPHYRDRIEXT_H__ +#define __EPHYRDRIEXT_H__ +Bool ephyrDRIExtensionInit (ScreenPtr a_screen) ; +#endif /*__EPHYRDRIEXT_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c new file mode 100644 index 000000000..381c9d7ed --- /dev/null +++ b/hw/kdrive/ephyr/ephyrglxext.c @@ -0,0 +1,722 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "extnsionst.h" +#include "ephyrglxext.h" +#include "ephyrhostglx.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include +#include "GL/glx/glxserver.h" +#include "GL/glx/indirect_table.h" +#include "GL/glx/indirect_util.h" +#include "GL/glx/unpack.h" +#include "hostx.h" + + +#ifdef XEPHYR_DRI + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +int ephyrGLXQueryVersion (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXQueryVersionSwap (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXGetVisualConfigs (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXGetVisualConfigsSwap (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXCreateContext (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXCreateContextSwap (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; + +Bool +ephyrHijackGLXExtension (void) +{ + const void *(*dispatch_functions)[2]; + + if (!hostx_has_glx ()) { + EPHYR_LOG ("host X does not have GLX\n") ; + return FALSE ; + } + EPHYR_LOG ("host X does have GLX\n") ; + + if (!Single_dispatch_info.dispatch_functions) { + EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ; + return FALSE ; + } + /* + * hijack some single entry point dispatch functions + */ + dispatch_functions = Single_dispatch_info.dispatch_functions ; + EPHYR_RETURN_VAL_IF_FAIL (dispatch_functions, FALSE) ; + + dispatch_functions[X_GLXQueryVersion][0] = ephyrGLXQueryVersion ; + dispatch_functions[X_GLXQueryVersion][1] = ephyrGLXQueryVersionSwap ; + + dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ; + dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ; + dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ; + dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ; + + dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString ; + dispatch_functions[X_GLXQueryServerString][1] = + ephyrGLXQueryServerStringSwap ; + + dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext ; + dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap ; + + dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext ; + dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap ; + + dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent ; + dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap ; + + dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect ; + dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap ; + + dispatch_functions[73][0] = ephyrGLXGetString ; + dispatch_functions[73][1] = ephyrGLXGetStringSwap ; + + dispatch_functions[61][0] = ephyrGLXGetIntegerv ; + dispatch_functions[61][1] = ephyrGLXGetIntegervSwap ; + + /* + * hijack some vendor priv entry point dispatch functions + */ + dispatch_functions = VendorPriv_dispatch_info.dispatch_functions ; + dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX; + dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap; + EPHYR_LOG ("hijacked glx entry points to forward requests to host X\n") ; + + return TRUE ; +} + +/********************* + * implementation of + * hijacked GLX entry + * points + ********************/ + +int +ephyrGLXQueryVersion(__GLXclientState *a_cl, GLbyte *a_pc) +{ + ClientPtr client = a_cl->client; + xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; + xGLXQueryVersionReply reply; + int major, minor; + int res = BadImplementation ; + + EPHYR_LOG ("enter\n") ; + + major = req->majorVersion ; + minor = req->minorVersion ; + + if (!ephyrHostGLXQueryVersion (&major, &minor)) { + EPHYR_LOG_ERROR ("ephyrHostGLXQueryVersion() failed\n") ; + goto out ; + } + EPHYR_LOG ("major:%d, minor:%d\n", + major, minor); + reply.majorVersion = major ; + reply.minorVersion = minor ; + reply.length = 0 ; + reply.type = X_Reply ; + reply.sequenceNumber = client->sequence ; + + if (client->swapped) { + __glXSwapQueryVersionReply(client, &reply); + } else { + WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply); + } + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res; +} + +int +ephyrGLXQueryVersionSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT (&req->length); + __GLX_SWAP_INT (&req->majorVersion); + __GLX_SWAP_INT (&req->minorVersion); + return ephyrGLXQueryVersion (a_cl, a_pc) ; +} + +static int +ephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc; + ClientPtr client = a_cl->client; + xGLXGetVisualConfigsReply reply; + int32_t *props_buf=NULL, num_visuals=0, + num_props=0, res=BadImplementation, i=0, + props_per_visual_size=0, + props_buf_size=0; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostGLXGetVisualConfigs (req->screen, + &num_visuals, + &num_props, + &props_buf_size, + &props_buf)) { + EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; + goto out ; + } + EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; + + reply.numVisuals = num_visuals; + reply.numProps = num_props; + reply.length = (num_visuals *__GLX_SIZE_CARD32 * num_props) >> 2; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.numVisuals); + __GLX_SWAP_INT(&reply.numProps); + __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; + } + WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); + props_per_visual_size = props_buf_size/num_visuals ; + for (i=0; i < num_visuals; i++) { + WriteToClient (client, + props_per_visual_size, + (char*)props_buf +i*props_per_visual_size); + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + if (props_buf) { + xfree (props_buf) ; + props_buf = NULL ; + } + return res ; +} + +static int +ephyrGLXGetFBConfigsSGIXReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)a_pc; + ClientPtr client = a_cl->client; + xGLXGetVisualConfigsReply reply; + int32_t *props_buf=NULL, num_visuals=0, + num_props=0, res=BadImplementation, i=0, + props_per_visual_size=0, + props_buf_size=0; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX (req->screen, + &num_visuals, + &num_props, + &props_buf_size, + &props_buf)) { + EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; + goto out ; + } + EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; + + reply.numVisuals = num_visuals; + reply.numProps = num_props; + reply.length = props_buf_size >> 2; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.numVisuals); + __GLX_SWAP_INT(&reply.numProps); + __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; + } + WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); + props_per_visual_size = props_buf_size/num_visuals ; + for (i=0; i < num_visuals; i++) { + WriteToClient (client, + props_per_visual_size, + &((char*)props_buf)[i*props_per_visual_size]); + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + if (props_buf) { + xfree (props_buf) ; + props_buf = NULL ; + } + return res ; +} + +int +ephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetVisualConfigsSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, TRUE) ; +} + + +int +ephyrGLXClientInfo(__GLXclientState *a_cl, GLbyte *a_pc) +{ + int res=BadImplementation ; + xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXSendClientInfo (req->major, req->minor, (char*)req+1)) { + EPHYR_LOG_ERROR ("failed to send client info to host\n") ; + goto out ; + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXClientInfoSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + xGLXClientInfoReq *req = (xGLXClientInfoReq *)a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT (&req->length); + __GLX_SWAP_INT (&req->major); + __GLX_SWAP_INT (&req->minor); + __GLX_SWAP_INT (&req->numbytes); + + return ephyrGLXClientInfo (a_cl, a_pc) ; +} + +int +ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) +{ + int res = BadImplementation ; + ClientPtr client = a_cl->client; + xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc; + xGLXQueryServerStringReply reply; + char *server_string=NULL ; + int length=0 ; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetStringFromServer (req->screen, + req->name, + EPHYR_HOST_GLX_QueryServerString, + &server_string)) { + EPHYR_LOG_ERROR ("failed to query string from host\n") ; + goto out ; + } + EPHYR_LOG ("string: %s\n", server_string) ; + length= strlen (server_string) + 1; + reply.type = X_Reply ; + reply.sequenceNumber = client->sequence ; + reply.length = __GLX_PAD (length) >> 2 ; + reply.n = length ; + + WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply); + WriteToClient(client, (int)length, server_string); + + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + if (server_string) { + xfree (server_string) ; + server_string = NULL; + } + return res ; +} + +int +ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) +{ + EPHYR_LOG_ERROR ("not yet implemented\n") ; + return BadImplementation ; +} + + +int +ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap) +{ + int res=BadImplementation; + EphyrHostWindowAttributes host_w_attrs ; + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL (a_req, BadValue) ; + EPHYR_LOG ("enter\n") ; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&a_req->length); + __GLX_SWAP_INT(&a_req->context); + __GLX_SWAP_INT(&a_req->visual); + __GLX_SWAP_INT(&a_req->screen); + __GLX_SWAP_INT(&a_req->shareList); + } + + EPHYR_LOG ("context creation requested. localid:%d, " + "screen:%d, visual:%d, direct:%d\n", + (int)a_req->context, (int)a_req->screen, + (int)a_req->visual, (int)a_req->isDirect) ; + + memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ; + if (!hostx_get_window_attributes (hostx_get_window (a_req->screen), + &host_w_attrs)) { + EPHYR_LOG_ERROR ("failed to get host window attrs\n") ; + goto out ; + } + + EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ; + + if (!ephyrHostGLXCreateContext (a_req->screen, + host_w_attrs.visualid, + a_req->context, + a_req->shareList, + a_req->isDirect)) { + EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ; + goto out ; + } + res = Success; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + + return ephyrGLXCreateContextReal (req, FALSE) ; +} + +int ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + return ephyrGLXCreateContextReal (req, TRUE) ; +} + +static int +ephyrGLXDestroyContextReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + int res=BadImplementation; + ClientPtr client = a_cl->client; + xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc; + + EPHYR_LOG ("enter. id:%d\n", (int)req->context) ; + if (!ephyrHostDestroyContext (req->context)) { + EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ; + client->errorValue = req->context ; + goto out ; + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; + xGLXMakeCurrentReply reply ; + DrawablePtr drawable=NULL; + int rc=0; + + EPHYR_LOG ("enter\n") ; + rc = dixLookupDrawable (&drawable, + req->drawable, + a_cl->client, + 0, + DixReadAccess); + EPHYR_RETURN_VAL_IF_FAIL (drawable, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (drawable->pScreen, BadValue) ; + EPHYR_LOG ("screen nummber requested:%d\n", + drawable->pScreen->myNum) ; + + memset (&reply, 0, sizeof (reply)) ; + if (!ephyrHostGLXMakeCurrent (hostx_get_window (drawable->pScreen->myNum), + req->context, + req->oldContextTag, + (int*)&reply.contextTag)) { + EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ; + goto out; + } + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = a_cl->client->sequence; + if (a_do_swap) { + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.contextTag); + } + WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply); + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + ClientPtr client=NULL ; + int context_tag=0, name=0, res=BadImplementation, length=0 ; + char *string=NULL; + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + client = a_cl->client ; + + if (a_do_swap) { + __GLX_SWAP_INT (a_pc + 4); + __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE); + } + context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ; + a_pc += __GLX_SINGLE_HDR_SIZE; + name = *(GLenum*)(a_pc + 0); + EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ; + if (!ephyrHostGLXGetStringFromServer (context_tag, + name, + EPHYR_HOST_GLX_GetString, + &string)) { + EPHYR_LOG_ERROR ("failed to get string from server\n") ; + goto out ; + } + if (string) { + length = strlen (string) + 1; + EPHYR_LOG ("got string:'%s', size:%d\n", string, length) ; + } else { + EPHYR_LOG ("got string: string (null)\n") ; + } + __GLX_BEGIN_REPLY (length); + __GLX_PUT_SIZE (length); + __GLX_SEND_HEADER (); + if (a_do_swap) { + __GLX_SWAP_REPLY_SIZE (); + __GLX_SWAP_REPLY_HEADER (); + } + WriteToClient (client, length, (char *)string); + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + xGLXSingleReq * const req = (xGLXSingleReq *) a_pc; + GLenum int_name ; + int value=0 ; + GLint answer_buf_room[200]; + GLint *buf=NULL ; + + EPHYR_LOG ("enter\n") ; + + a_pc += __GLX_SINGLE_HDR_SIZE; + + int_name = *(GLenum*) (a_pc+0) ; + if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) { + EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ; + goto out ; + } + buf = __glXGetAnswerBuffer (a_cl, sizeof (value), + answer_buf_room, + sizeof (answer_buf_room), + 4) ; + + if (!buf) { + EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ; + res = BadAlloc ; + goto out ; + } + __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ; + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + ClientPtr client = a_cl->client; + xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc; + xGLXIsDirectReply reply; + int is_direct=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + memset (&reply, 0, sizeof (reply)) ; + if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) { + EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ; + goto out ; + } + reply.isDirect = is_direct ; + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ; +} + +#endif /*XEPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/ephyrglxext.h b/hw/kdrive/ephyr/ephyrglxext.h new file mode 100644 index 000000000..22ea605d7 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrglxext.h @@ -0,0 +1,35 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifndef __EPHYR_GLXEXT_H__ +#define __EPHYR_GLXEXT_H__ + +#include +Bool ephyrHijackGLXExtension (void) ; + +#endif /*__EPHYR_GLXEXT_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c new file mode 100644 index 000000000..5d9a482e8 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -0,0 +1,687 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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. + * + * a lots of the content of this file has been adapted from the mesa source + * code. + * Authors: + * Dodji Seketeli + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "ephyrhostglx.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include "hostx.h" + +#ifdef XEPHYR_DRI +enum VisualConfRequestType { + EPHYR_GET_FB_CONFIG, + EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX, + EPHYR_GET_VISUAL_CONFIGS + +}; + +static Bool ephyrHostGLXGetVisualConfigsInternal + (enum VisualConfRequestType a_type, + int32_t a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf); +Bool +ephyrHostGLXGetMajorOpcode (int *a_opcode) +{ + Bool is_ok=FALSE ; + Display *dpy=hostx_get_display () ; + static int opcode ; + int first_event_return=0, first_error_return=0; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + EPHYR_LOG ("enter\n") ; + if (!opcode) { + if (!XQueryExtension (dpy, GLX_EXTENSION_NAME, &opcode, + &first_event_return, &first_error_return)) { + EPHYR_LOG_ERROR ("XQueryExtension() failed\n") ; + goto out ; + } + } + *a_opcode = opcode ; + is_ok = TRUE ; +out: + EPHYR_LOG ("release\n") ; + return is_ok ; +} + +Bool +ephyrHostGLXQueryVersion (int *a_major, int *a_minor) +{ + Bool is_ok = FALSE ; + Display *dpy = hostx_get_display () ; + int major_opcode=0; + xGLXQueryVersionReq *req=NULL; + xGLXQueryVersionReply reply; + + EPHYR_RETURN_VAL_IF_FAIL (a_major && a_minor, FALSE) ; + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + EPHYR_LOG ("major opcode: %d\n", major_opcode) ; + + /* Send the glXQueryVersion request */ + memset (&reply, 0, sizeof (reply)) ; + LockDisplay (dpy); + GetReq (GLXQueryVersion, req); + req->reqType = major_opcode; + req->glxCode = X_GLXQueryVersion; + req->majorVersion = 2; + req->minorVersion = 1; + _XReply(dpy, (xReply*) &reply, 0, False); + UnlockDisplay (dpy); + SyncHandle (); + + *a_major = reply.majorVersion ; + *a_minor = reply.minorVersion ; + + EPHYR_LOG ("major:%d, minor:%d\n", *a_major, *a_minor) ; + + is_ok = TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +/** + * GLX protocol structure for the ficticious "GXLGenericGetString" request. + * + * This is a non-existant protocol packet. It just so happens that all of + * the real protocol packets used to request a string from the server have + * an identical binary layout. The only difference between them is the + * meaning of the \c for_whom field and the value of the \c glxCode. + * (this has been copied from the mesa source code) + */ +typedef struct GLXGenericGetString { + CARD8 reqType; + CARD8 glxCode; + CARD16 length B16; + CARD32 for_whom B32; + CARD32 name B32; +} xGLXGenericGetStringReq; + +/* These defines are only needed to make the GetReq macro happy. + */ +#define sz_xGLXGenericGetStringReq 12 +#define X_GLXGenericGetString 0 + +Bool +ephyrHostGLXGetStringFromServer (int a_screen_number, + int a_string_name, + enum EphyrHostGLXGetStringOps a_op, + char **a_string) +{ + Bool is_ok=FALSE ; + Display *dpy = hostx_get_display () ; + xGLXGenericGetStringReq *req=NULL; + xGLXSingleReply reply; + int length=0, numbytes=0, major_opcode=0, get_string_op=0; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_string, FALSE) ; + + EPHYR_LOG ("enter\n") ; + switch (a_op) { + case EPHYR_HOST_GLX_QueryServerString: + get_string_op = X_GLXQueryServerString; + break ; + case EPHYR_HOST_GLX_GetString: + get_string_op = X_GLsop_GetString; + EPHYR_LOG ("Going to glXGetString. strname:%#x, ctxttag:%d\n", + a_string_name, a_screen_number) ; + break ; + default: + EPHYR_LOG_ERROR ("unknown EphyrHostGLXGetStringOp:%d\n", a_op) ; + goto out ; + } + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + EPHYR_LOG ("major opcode: %d\n", major_opcode) ; + + LockDisplay (dpy); + + /* All of the GLX protocol requests for getting a string from the server + * look the same. The exact meaning of the a_for_whom field is usually + * either the screen number (for glXQueryServerString) or the context tag + * (for GLXSingle). + */ + GetReq (GLXGenericGetString, req); + req->reqType = major_opcode; + req->glxCode = get_string_op; + req->for_whom = DefaultScreen (dpy); + req->name = a_string_name; + + _XReply (dpy, (xReply *)&reply, 0, False); + + length = reply.length * 4; + numbytes = reply.size; + EPHYR_LOG ("going to get a string of size:%d\n", numbytes) ; + + *a_string = (char *) Xmalloc (numbytes +1); + if (!a_string) { + EPHYR_LOG_ERROR ("allocation failed\n") ; + goto out; + } + + memset (*a_string, 0, numbytes+1) ; + if (_XRead (dpy, *a_string, numbytes)) { + UnlockDisplay (dpy); + SyncHandle (); + EPHYR_LOG_ERROR ("read failed\n") ; + goto out ; + } + length -= numbytes; + _XEatData (dpy, length) ; + UnlockDisplay (dpy); + SyncHandle (); + EPHYR_LOG ("strname:%#x, strvalue:'%s', strlen:%d\n", + a_string_name, *a_string, numbytes) ; + + is_ok = TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrHostGLXGetVisualConfigsInternal (enum VisualConfRequestType a_type, + int32_t a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) +{ + Bool is_ok = FALSE ; + Display *dpy = hostx_get_display () ; + xGLXGetVisualConfigsReq *req; + xGLXGetFBConfigsReq *fb_req; + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXGetFBConfigsSGIXReq *sgi_req; + xGLXGetVisualConfigsReply reply; + char *server_glx_version=NULL, + *server_glx_extensions=NULL ; + int j=0, + screens=0, + major_opcode=0, + num_props=0, + num_visuals=0, + props_buf_size=0, + props_per_visual_size=0; + int32_t *props_buf=NULL; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + screens = ScreenCount (dpy); + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get opcode\n") ; + goto out ; + } + + LockDisplay(dpy); + switch (a_type) { + case EPHYR_GET_FB_CONFIG: + GetReq(GLXGetFBConfigs,fb_req); + fb_req->reqType = major_opcode; + fb_req->glxCode = X_GLXGetFBConfigs; + fb_req->screen = DefaultScreen (dpy); + break; + + case EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX: + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXGetFBConfigsSGIXReq + - + sz_xGLXVendorPrivateWithReplyReq, + vpreq); + sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; + sgi_req->reqType = major_opcode; + sgi_req->glxCode = X_GLXVendorPrivateWithReply; + sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; + sgi_req->screen = DefaultScreen (dpy); + break; + + case EPHYR_GET_VISUAL_CONFIGS: + GetReq(GLXGetVisualConfigs,req); + req->reqType = major_opcode; + req->glxCode = X_GLXGetVisualConfigs; + req->screen = DefaultScreen (dpy); + break; + } + + if (!_XReply(dpy, (xReply*) &reply, 0, False)) { + EPHYR_LOG_ERROR ("unknown error\n") ; + UnlockDisplay(dpy); + goto out ; + } + if (!reply.numVisuals) { + EPHYR_LOG_ERROR ("screen does not support GL rendering\n") ; + UnlockDisplay(dpy); + goto out ; + } + num_visuals = reply.numVisuals ; + + /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for + * FIXME: FBconfigs? + */ + /* Check number of properties */ + num_props = reply.numProps; + if ((num_props < __GLX_MIN_CONFIG_PROPS) || + (num_props > __GLX_MAX_CONFIG_PROPS)) { + /* Huh? Not in protocol defined limits. Punt */ + EPHYR_LOG_ERROR ("got a bad reply to request\n") ; + UnlockDisplay(dpy); + goto out ; + } + + if (a_type != EPHYR_GET_VISUAL_CONFIGS) { + num_props *= 2; + } + props_per_visual_size = num_props * __GLX_SIZE_INT32; + props_buf_size = props_per_visual_size * reply.numVisuals; + props_buf = malloc (props_buf_size) ; + for (j = 0; j < reply.numVisuals; j++) { + if (_XRead (dpy, + &((char*)props_buf)[j*props_per_visual_size], + props_per_visual_size) != Success) { + EPHYR_LOG_ERROR ("read failed\n") ; + } + } + UnlockDisplay(dpy); + + *a_num_visuals = num_visuals ; + *a_num_props = reply.numProps ; + *a_props_buf_size = props_buf_size ; + *a_props_buf = props_buf ; + is_ok = TRUE ; + +out: + if (server_glx_version) { + XFree (server_glx_version) ; + server_glx_version = NULL ; + } + if (server_glx_extensions) { + XFree (server_glx_extensions) ; + server_glx_extensions = NULL ; + } + SyncHandle () ; + return is_ok; +} + +Bool +ephyrHostGLXGetVisualConfigs (int32_t a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) +{ + Bool is_ok = FALSE; + + EPHYR_LOG ("enter\n") ; + is_ok = ephyrHostGLXGetVisualConfigsInternal (EPHYR_GET_VISUAL_CONFIGS, + a_screen, + a_num_visuals, + a_num_props, + a_props_buf_size, + a_props_buf) ; + + EPHYR_LOG ("leave:%d\n", is_ok) ; + return is_ok; +} + +Bool +ephyrHostGLXVendorPrivGetFBConfigsSGIX (int a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) +{ + Bool is_ok=FALSE ; + EPHYR_LOG ("enter\n") ; + is_ok = ephyrHostGLXGetVisualConfigsInternal + (EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX, + a_screen, + a_num_visuals, + a_num_props, + a_props_buf_size, + a_props_buf) ; + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor, + const char* a_extension_list) +{ + Bool is_ok = FALSE ; + Display *dpy = hostx_get_display () ; + xGLXClientInfoReq *req; + int size; + int32_t major_opcode=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_extension_list, FALSE) ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + + LockDisplay (dpy); + + GetReq (GLXClientInfo,req); + req->reqType = major_opcode; + req->glxCode = X_GLXClientInfo; + req->major = a_major; + req->minor = a_minor; + + size = strlen (a_extension_list) + 1; + req->length += (size + 3) >> 2; + req->numbytes = size; + Data (dpy, a_extension_list, size); + + UnlockDisplay(dpy); + SyncHandle(); + + is_ok=TRUE ; + +out: + return is_ok ; +} + +Bool +ephyrHostGLXCreateContext (int a_screen, + int a_visual_id, + int a_context_id, + int a_share_list_ctxt_id, + Bool a_direct) +{ + Bool is_ok = FALSE; + Display *dpy = hostx_get_display (); + int major_opcode=0, remote_context_id=0; + xGLXCreateContextReq *req; + + EPHYR_LOG ("enter. screen:%d, visual:%d, contextid:%d, direct:%d\n", + a_screen, a_visual_id, a_context_id, a_direct) ; + + if (!hostx_allocate_resource_id_peer (a_context_id, &remote_context_id)) { + EPHYR_LOG_ERROR ("failed to peer the context id %d host X", + remote_context_id) ; + goto out ; + } + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + + LockDisplay (dpy) ; + + /* Send the glXCreateContext request */ + GetReq(GLXCreateContext,req); + req->reqType = major_opcode; + req->glxCode = X_GLXCreateContext; + req->context = remote_context_id; + req->visual = a_visual_id; + req->screen = DefaultScreen (dpy); + req->shareList = a_share_list_ctxt_id; + req->isDirect = a_direct; + + UnlockDisplay (dpy); + SyncHandle (); + + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostDestroyContext (int a_ctxt_id) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display (); + int major_opcode=0, remote_ctxt_id=0 ; + xGLXDestroyContextReq *req=NULL; + + EPHYR_LOG ("enter:%d\n", a_ctxt_id) ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + EPHYR_LOG ("host context id:%d\n", remote_ctxt_id) ; + + LockDisplay (dpy); + GetReq (GLXDestroyContext,req); + req->reqType = major_opcode; + req->glxCode = X_GLXDestroyContext; + req->context = remote_ctxt_id; + UnlockDisplay (dpy); + SyncHandle (); + + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostGLXMakeCurrent (int a_drawable, + int a_glx_ctxt_id, + int a_old_ctxt_tag, + int *a_ctxt_tag) +{ + Bool is_ok=FALSE ; + Display *dpy = hostx_get_display () ; + int32_t major_opcode=0 ; + int remote_glx_ctxt_id=0 ; + xGLXMakeCurrentReq *req; + xGLXMakeCurrentReply reply; + + EPHYR_RETURN_VAL_IF_FAIL (a_ctxt_tag, FALSE) ; + + EPHYR_LOG ("enter. drawable:%d, context:%d, oldtag:%d\n", + a_drawable, a_glx_ctxt_id, a_old_ctxt_tag) ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_glx_ctxt_id, &remote_glx_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + + LockDisplay (dpy); + + GetReq (GLXMakeCurrent,req); + req->reqType = major_opcode; + req->glxCode = X_GLXMakeCurrent; + req->drawable = a_drawable; + req->context = remote_glx_ctxt_id; + req->oldContextTag = a_old_ctxt_tag; + + memset (&reply, 0, sizeof (reply)) ; + if (!_XReply (dpy, (xReply*)&reply, 0, False)) { + EPHYR_LOG_ERROR ("failed to get reply from host\n") ; + UnlockDisplay (dpy); + SyncHandle (); + goto out ; + } + UnlockDisplay (dpy); + SyncHandle (); + *a_ctxt_tag = reply.contextTag ; + EPHYR_LOG ("context tag:%d\n", *a_ctxt_tag) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +#define X_GLXSingle 0 + +#define __EPHYR_GLX_SINGLE_PUT_CHAR(offset,a) \ + *((INT8 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_SHORT(offset,a) \ + *((INT16 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_LONG(offset,a) \ + *((INT32 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_FLOAT(offset,a) \ + *((FLOAT32 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_READ_XREPLY() \ + (void) _XReply(dpy, (xReply*) &reply, 0, False) + +#define EPHYR_GLX_SINGLE_GET_RETVAL(a,cast) \ + a = (cast) reply.retval + +#define EPHYR_GLX_SINGLE_GET_SIZE(a) \ + a = (GLint) reply.size + +#define EPHYR_GLX_SINGLE_GET_CHAR(p) \ + *p = *(GLbyte *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_SHORT(p) \ + *p = *(GLshort *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_LONG(p) \ + *p = *(GLint *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_FLOAT(p) \ + *p = *(GLfloat *)&reply.pad3; + +Bool +ephyrHostGetIntegerValue (int a_current_context_tag, int a_int, int *a_val) +{ + Bool is_ok=FALSE; + Display *dpy = hostx_get_display () ; + int major_opcode=0, size=0; + xGLXSingleReq *req=NULL; + xGLXSingleReply reply; + unsigned char* pc=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_val, FALSE) ; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + LockDisplay (dpy) ; + GetReqExtra (GLXSingle, 4, req) ; + req->reqType = major_opcode ; + req->glxCode = X_GLsop_GetIntegerv ; + req->contextTag = a_current_context_tag; + pc = ((unsigned char *)(req) + sz_xGLXSingleReq) ; + EPHYR_GLX_SINGLE_PUT_LONG (0, a_int) ; + EPHYR_GLX_SINGLE_READ_XREPLY () ; + EPHYR_GLX_SINGLE_GET_SIZE (size) ; + if (!size) { + UnlockDisplay (dpy) ; + SyncHandle () ; + EPHYR_LOG_ERROR ("X_GLsop_GetIngerv failed\n") ; + goto out ; + } + EPHYR_GLX_SINGLE_GET_LONG (a_val) ; + UnlockDisplay (dpy) ; + SyncHandle () ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostIsContextDirect (int a_ctxt_id, + int *a_is_direct) +{ + Bool is_ok=FALSE; + Display *dpy = hostx_get_display () ; + xGLXIsDirectReq *req=NULL; + xGLXIsDirectReply reply; + int major_opcode=0, remote_glx_ctxt_id=0; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_glx_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + memset (&reply, 0, sizeof (reply)) ; + + /* Send the glXIsDirect request */ + LockDisplay (dpy); + GetReq (GLXIsDirect,req); + req->reqType = major_opcode; + req->glxCode = X_GLXIsDirect; + req->context = remote_glx_ctxt_id; + if (!_XReply (dpy, (xReply*) &reply, 0, False)) { + EPHYR_LOG_ERROR ("fail in reading reply from host\n") ; + UnlockDisplay (dpy); + SyncHandle (); + goto out ; + } + UnlockDisplay (dpy); + SyncHandle (); + *a_is_direct = reply.isDirect ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +#endif /*XEPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/ephyrhostglx.h b/hw/kdrive/ephyr/ephyrhostglx.h new file mode 100644 index 000000000..6db362f30 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostglx.h @@ -0,0 +1,76 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifndef __EPHYRHOSTGLX_H__ +#define __EPHYRHOSTGLX_H__ + +enum EphyrHostGLXGetStringOps { + EPHYR_HOST_GLX_UNDEF, + EPHYR_HOST_GLX_QueryServerString, + EPHYR_HOST_GLX_GetString, +}; + +Bool ephyrHostGLXQueryVersion (int *a_maj, int *a_min) ; +Bool ephyrHostGLXGetStringFromServer (int a_screen_number, + int a_string_name, + enum EphyrHostGLXGetStringOps a_op, + char **a_string) ; +Bool ephyrHostGLXGetVisualConfigs (int a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf) ; +Bool +ephyrHostGLXVendorPrivGetFBConfigsSGIX (int a_screen, + int32_t *a_num_visuals, + int32_t *a_num_props, + int32_t *a_props_buf_size, + int32_t **a_props_buf); +Bool ephyrHostGLXGetMajorOpcode (int32_t *a_opcode) ; +Bool ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor, + const char* a_extension_list) ; +Bool ephyrHostGLXCreateContext (int a_screen, + int a_visual_id, + int a_context_id, + int a_shared_list_ctx_id, + Bool a_direct) ; + +Bool ephyrHostDestroyContext (int a_ctxt_id) ; + +Bool ephyrHostGLXMakeCurrent (int a_drawable, int a_glx_ctxt_id, + int a_olg_ctxt_tag, int *a_ctxt_tag) ; + +Bool ephyrHostGetIntegerValue (int a_current_context_tag, + int a_int, + int *a_val) ; + +Bool ephyrHostIsContextDirect (int a_ctxt_id, + int *a_is_direct) ; + + +#endif /*__EPHYRHOSTGLX_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrhostproxy.c b/hw/kdrive/ephyr/ephyrhostproxy.c new file mode 100644 index 000000000..ce3f01852 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostproxy.c @@ -0,0 +1,94 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include "ephyrhostproxy.h" +#include "hostx.h" + +/* byte swap a short */ +#define swaps(x, n) { \ + n = ((char *) (x))[0];\ + ((char *) (x))[0] = ((char *) (x))[1];\ + ((char *) (x))[1] = n; } + +#define GetXReq(req) \ + WORD64ALIGN ;\ + if ((dpy->bufptr + SIZEOF(xReq)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xReq *)(dpy->last_req = dpy->bufptr);\ + dpy->bufptr += SIZEOF(xReq);\ + dpy->request++ + + +Bool +ephyrHostProxyDoForward (pointer a_request_buffer, + struct XReply *a_reply, + Bool a_do_swap) +{ + Bool is_ok = FALSE ; + int n=0 ; + Display *dpy=hostx_get_display () ; + xReq *in_req = (xReq*) a_request_buffer ; + xReq *forward_req=NULL ; + struct XReply reply ; + + EPHYR_RETURN_VAL_IF_FAIL (in_req && dpy, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (a_do_swap) { + swaps (&in_req->length, n) ; + } + EPHYR_LOG ("Req {type:%d, data:%d, length:%d}\n", + in_req->reqType, in_req->data, in_req->length) ; + GetXReq (forward_req) ; + memmove (forward_req, in_req, 4) ; + + if (!_XReply (dpy, (xReply*) &reply, 0, FALSE)) { + EPHYR_LOG_ERROR ("failed to get reply\n") ; + goto out; + } + EPHYR_LOG ("XReply{type:%d, foo:%d, seqnum:%d, length:%d}\n", + reply.type, reply.foo, reply.sequence_number, reply.length) ; + + if (a_reply) { + memmove (a_reply, &reply, sizeof (reply)) ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + diff --git a/hw/kdrive/ephyr/ephyrhostproxy.h b/hw/kdrive/ephyr/ephyrhostproxy.h new file mode 100644 index 000000000..720c986ff --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostproxy.h @@ -0,0 +1,51 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ + +#ifndef __EPHYRHOSTPROXY_H__ +#define __EPHYRHOSTPROXY_H__ + +struct XReply { + int8_t type ;/*X_Reply*/ + int8_t foo; + int16_t sequence_number ; + int32_t length ; + /*following is some data up to 32 bytes lenght*/ + int32_t pad0 ; + int32_t pad1 ; + int32_t pad2 ; + int32_t pad3 ; + int32_t pad4 ; + int32_t pad5 ; +}; + +Bool +ephyrHostProxyDoForward (pointer a_request_buffer, + struct XReply *a_reply, + Bool a_do_swap) ; + +#endif /*__EPHYRHOSTPROXY_H__*/ diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c new file mode 100644 index 000000000..562c2a4e8 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -0,0 +1,1004 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#define _HAVE_XALLOC_DECLS + +#include "hostx.h" +#include "ephyrhostvideo.h" +#include "ephyrlog.h" + +#ifndef TRUE +#define TRUE 1 +#endif /*TRUE*/ + +#ifndef FALSE +#define FALSE 0 +#endif /*FALSE*/ + +static XExtensionInfo _xv_info_data; +static XExtensionInfo *xv_info = &_xv_info_data; +static char *xv_extension_name = XvName; +static char *xv_error_string(Display *dpy, int code, XExtCodes *codes, + char * buf, int n); +static int xv_close_display(Display *dpy, XExtCodes *codes); +static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire); + +static XExtensionHooks xv_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + xv_close_display, /* close_display */ + xv_wire_to_event, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + xv_error_string /* error_string */ +}; + + +static char *xv_error_list[] = +{ + "BadPort", /* XvBadPort */ + "BadEncoding", /* XvBadEncoding */ + "BadControl" /* XvBadControl */ +}; + + +#define XvCheckExtension(dpy, i, val) \ + XextCheckExtension(dpy, i, xv_extension_name, val) +#define XvGetReq(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = info->codes->major_opcode;\ + req->xvReqType = xv_##name; \ + req->length = (SIZEOF(xv##name##Req))>>2;\ + dpy->bufptr += SIZEOF(xv##name##Req);\ + dpy->request++ + +static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) + + +static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, + xv_extension_name, + &xv_extension_hooks, + XvNumEvents, NULL) + +static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, + XvNumErrors, xv_error_list) + +struct _EphyrHostXVAdaptorArray { + XvAdaptorInfo *adaptors ; + unsigned int nb_adaptors ; +}; + +/*heavily copied from libx11*/ +#define BUFSIZE 2048 +static void +ephyrHostXVLogXErrorEvent (Display *a_display, + XErrorEvent *a_err_event, + FILE *a_fp) +{ + char buffer[BUFSIZ]; + char mesg[BUFSIZ]; + char number[32]; + const char *mtype = "XlibMessage"; + register _XExtension *ext = (_XExtension *)NULL; + _XExtension *bext = (_XExtension *)NULL; + Display *dpy = a_display ; + + XGetErrorText(dpy, a_err_event->error_code, buffer, BUFSIZ); + XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); + (void) fprintf(a_fp, "%s: %s\n ", mesg, buffer); + XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", + mesg, BUFSIZ); + (void) fprintf(a_fp, mesg, a_err_event->request_code); + if (a_err_event->request_code < 128) { + sprintf(number, "%d", a_err_event->request_code); + XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); + } else { + for (ext = dpy->ext_procs; + ext && (ext->codes.major_opcode != a_err_event->request_code); + ext = ext->next) + ; + if (ext) + strcpy(buffer, ext->name); + else + buffer[0] = '\0'; + } + (void) fprintf(a_fp, " (%s)\n", buffer); + if (a_err_event->request_code >= 128) { + XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->minor_code); + if (ext) { + sprintf(mesg, "%s.%d", ext->name, a_err_event->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); + (void) fprintf(a_fp, " (%s)", buffer); + } + fputs("\n", a_fp); + } + if (a_err_event->error_code >= 128) { + /* kludge, try to find the extension that caused it */ + buffer[0] = '\0'; + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_string) + (*ext->error_string)(dpy, a_err_event->error_code, &ext->codes, + buffer, BUFSIZ); + if (buffer[0]) { + bext = ext; + break; + } + if (ext->codes.first_error && + ext->codes.first_error < (int)a_err_event->error_code && + (!bext || ext->codes.first_error > bext->codes.first_error)) + bext = ext; + } + if (bext) + sprintf(buffer, "%s.%d", bext->name, + a_err_event->error_code - bext->codes.first_error); + else + strcpy(buffer, "Value"); + XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); + if (mesg[0]) { + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->resourceid); + fputs("\n", a_fp); + } + /* let extensions try to print the values */ + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_values) + (*ext->error_values)(dpy, a_err_event, a_fp); + } + } else if ((a_err_event->error_code == BadWindow) || + (a_err_event->error_code == BadPixmap) || + (a_err_event->error_code == BadCursor) || + (a_err_event->error_code == BadFont) || + (a_err_event->error_code == BadDrawable) || + (a_err_event->error_code == BadColor) || + (a_err_event->error_code == BadGC) || + (a_err_event->error_code == BadIDChoice) || + (a_err_event->error_code == BadValue) || + (a_err_event->error_code == BadAtom)) { + if (a_err_event->error_code == BadValue) + XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", + mesg, BUFSIZ); + else if (a_err_event->error_code == BadAtom) + XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", + mesg, BUFSIZ); + else + XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->resourceid); + fputs("\n", a_fp); + } + XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->serial); + XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", + mesg, BUFSIZ); + fputs("\n ", a_fp); + (void) fprintf(a_fp, mesg, dpy->request); + fputs("\n", a_fp); +} + +static int +ephyrHostXVErrorHandler (Display *a_display, + XErrorEvent *a_error_event) +{ + EPHYR_LOG_ERROR ("got an error from the host xserver:\n") ; + ephyrHostXVLogXErrorEvent (a_display, a_error_event, stderr) ; + return Success ; +} + +void +ephyrHostXVInit (void) +{ + static Bool s_initialized ; + + if (s_initialized) + return ; + XSetErrorHandler (ephyrHostXVErrorHandler) ; + s_initialized = TRUE ; +} + +Bool +ephyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) +{ + EphyrHostXVAdaptorArray *result=NULL ; + int ret=0 ; + Bool is_ok=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_adaptors, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + result = Xcalloc (1, sizeof (EphyrHostXVAdaptorArray)) ; + if (!result) + goto out ; + + ret = XvQueryAdaptors (hostx_get_display (), + DefaultRootWindow (hostx_get_display ()), + &result->nb_adaptors, + &result->adaptors) ; + if (ret != Success) { + EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", ret) ; + goto out ; + } + *a_adaptors = result ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +void +ephyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) +{ + if (!a_adaptors) + return ; + if (a_adaptors->adaptors) { + XvFreeAdaptorInfo (a_adaptors->adaptors) ; + a_adaptors->adaptors = NULL ; + a_adaptors->nb_adaptors = 0 ; + } + XFree (a_adaptors) ; +} + +int +ephyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + return a_this->nb_adaptors ; +} + +EphyrHostXVAdaptor* +ephyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, + int a_index) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + if (a_index >= a_this->nb_adaptors) + return NULL ; + return (EphyrHostXVAdaptor*)&a_this->adaptors[a_index] ; +} + +char +ephyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + return ((XvAdaptorInfo*)a_this)->type ; +} + +const char* +ephyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + return ((XvAdaptorInfo*)a_this)->name ; +} + +EphyrHostVideoFormat* +ephyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, + int *a_nb_formats) +{ + EphyrHostVideoFormat *formats=NULL ; + int nb_formats=0, i=0 ; + XVisualInfo *visual_info, visual_info_template ; + int nb_visual_info ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; + formats = Xcalloc (nb_formats, sizeof (EphyrHostVideoFormat)) ; + for (i=0; i < nb_formats; i++) { + memset (&visual_info_template, 0, sizeof (visual_info_template)) ; + visual_info_template.visualid = + ((XvAdaptorInfo*)a_this)->formats[i].visual_id; + visual_info = XGetVisualInfo (hostx_get_display (), + VisualIDMask, + &visual_info_template, + &nb_visual_info) ; + formats[i].depth = ((XvAdaptorInfo*)a_this)->formats[i].depth ; + formats[i].visual_class = visual_info->class ; + XFree (visual_info) ; + } + if (a_nb_formats) + *a_nb_formats = nb_formats ; + return formats ; +} + +int +ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + + return ((XvAdaptorInfo*)a_this)->num_ports ; +} + +int +ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + + return ((XvAdaptorInfo*)a_this)->base_id ; +} + +Bool +ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvInputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasGetVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvOutputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvInputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasGetStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvOutputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvImageMask && XvInputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVQueryEncodings (int a_port_id, + EphyrHostEncoding **a_encodings, + unsigned int *a_num_encodings) +{ + EphyrHostEncoding *encodings=NULL ; + XvEncodingInfo *encoding_info=NULL ; + unsigned int num_encodings=0, i; + int ret=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, FALSE) ; + + ret = XvQueryEncodings (hostx_get_display (), + a_port_id, + &num_encodings, + &encoding_info) ; + if (num_encodings && encoding_info) { + encodings = Xcalloc (num_encodings, sizeof (EphyrHostEncoding)) ; + for (i=0; iu.u.type & 0x7F) - info->codes->first_event) { + case XvVideoNotify: + re->xvvideo.type = event->u.u.type & 0x7f; + re->xvvideo.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); + re->xvvideo.display = dpy; + re->xvvideo.time = event->u.videoNotify.time; + re->xvvideo.reason = event->u.videoNotify.reason; + re->xvvideo.drawable = event->u.videoNotify.drawable; + re->xvvideo.port_id = event->u.videoNotify.port; + break; + case XvPortNotify: + re->xvport.type = event->u.u.type & 0x7f; + re->xvport.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvport.send_event = ((event->u.u.type & 0x80) != 0); + re->xvport.display = dpy; + re->xvport.time = event->u.portNotify.time; + re->xvport.port_id = event->u.portNotify.port; + re->xvport.attribute = event->u.portNotify.attribute; + re->xvport.value = event->u.portNotify.value; + break; + default: + return False; + } + + return True ; +} + +Bool +ephyrHostXVQueryImageAttributes (int a_port_id, + int a_image_id /*image fourcc code*/, + unsigned short *a_width, + unsigned short *a_height, + int *a_image_size, + int *a_pitches, + int *a_offsets) +{ + Display *dpy = hostx_get_display () ; + Bool ret=FALSE ; + XExtDisplayInfo *info = xv_find_display (dpy); + xvQueryImageAttributesReq *req=NULL; + xvQueryImageAttributesReply rep; + + EPHYR_RETURN_VAL_IF_FAIL (a_width, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_height, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_image_size, FALSE) ; + + XvCheckExtension (dpy, info, FALSE); + + LockDisplay (dpy); + + XvGetReq (QueryImageAttributes, req); + req->id = a_image_id; + req->port = a_port_id; + req->width = *a_width; + req->height = *a_height; + /* + * read the reply + */ + if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { + EPHYR_LOG_ERROR ("QeryImageAttribute req failed\n") ; + goto out ; + } + if (a_pitches && a_offsets) { + _XRead (dpy, + (char*)a_pitches, + rep.num_planes << 2); + _XRead (dpy, + (char*)a_offsets, + rep.num_planes << 2); + } else { + _XEatData(dpy, rep.length << 2); + } + *a_width = rep.width ; + *a_height = rep.height ; + *a_image_size = rep.data_size ; + + ret = TRUE ; + +out: + UnlockDisplay (dpy) ; + SyncHandle (); + return ret ; +} + +Bool +ephyrHostGetAtom (const char* a_name, + Bool a_create_if_not_exists, + int *a_atom) +{ + int atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_atom, FALSE) ; + + atom = XInternAtom (hostx_get_display (), a_name, a_create_if_not_exists); + if (atom == None) { + return FALSE ; + } + *a_atom = atom ; + return TRUE ; +} + +char* +ephyrHostGetAtomName (int a_atom) +{ + return XGetAtomName (hostx_get_display (), a_atom) ; +} + +void +ephyrHostFree (void *a_pointer) +{ + if (a_pointer) + XFree (a_pointer) ; +} + +Bool +ephyrHostXVPutImage (int a_screen_num, + int a_port_id, + int a_image_id, + int a_drw_x, + int a_drw_y, + int a_drw_w, + int a_drw_h, + int a_src_x, + int a_src_y, + int a_src_w, + int a_src_h, + int a_image_width, + int a_image_height, + unsigned char *a_buf, + EphyrHostBox *a_clip_rects, + int a_clip_rect_nums ) +{ + Bool is_ok=TRUE ; + XvImage *xv_image=NULL ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy = hostx_get_display () ; + XRectangle *rects=NULL ; + int res = 0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_buf, FALSE) ; + + EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ; + + memset (&gc_values, 0, sizeof (gc_values)) ; + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + xv_image = (XvImage*) XvCreateImage (hostx_get_display (), + a_port_id, a_image_id, + NULL, a_image_width, a_image_height) ; + if (!xv_image) { + EPHYR_LOG_ERROR ("failed to create image\n") ; + goto out ; + } + xv_image->data = (char*)a_buf ; + if (a_clip_rect_nums) { + int i=0 ; + rects = calloc (a_clip_rect_nums, sizeof (XRectangle)) ; + for (i=0; i < a_clip_rect_nums; i++) { + rects[i].x = a_clip_rects[i].x1 ; + rects[i].y = a_clip_rects[i].y1 ; + rects[i].width = a_clip_rects[i].x2 - a_clip_rects[i].x1; + rects[i].height = a_clip_rects[i].y2 - a_clip_rects[i].y1; + EPHYR_LOG ("(x,y,w,h): (%d,%d,%d,%d)\n", + rects[i].x, rects[i].y, + rects[i].width, rects[i].height) ; + } + XSetClipRectangles (dpy, gc, 0, 0, rects, a_clip_rect_nums, YXBanded) ; + /*this always returns 1*/ + } + res = XvPutImage (dpy, a_port_id, + hostx_get_window (a_screen_num), + gc, xv_image, + a_src_x, a_src_y, a_src_w, a_src_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutImage() failed: %d\n", res) ; + goto out ; + } + is_ok = TRUE ; + +out: + if (xv_image) { + XFree (xv_image) ; + xv_image = NULL ; + } + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + if (rects) { + free (rects) ; + rects = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostXVPutVideo (int a_screen_num, int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvPutVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutVideo() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVGetVideo (int a_screen_num, int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvGetVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetVideo() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVPutStill (int a_screen_num, int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvPutStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutStill() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVGetStill (int a_screen_num, int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvGetStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetStill() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVStopVideo (int a_screen_num, int a_port_id) +{ + int ret=0 ; + Bool is_ok=FALSE ; + Display *dpy = hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + ret = XvStopVideo (dpy, a_port_id, hostx_get_window (a_screen_num)) ; + if (ret != Success) { + EPHYR_LOG_ERROR ("XvStopVideo() failed: %d \n", ret) ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h new file mode 100644 index 000000000..05ee38a03 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -0,0 +1,238 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifndef __EPHYRHOSTVIDEO_H__ +#define __EPHYRHOSTVIDEO_H__ + +typedef void* EphyrHostXVAdaptor ; +typedef struct _EphyrHostXVAdaptorArray EphyrHostXVAdaptorArray ; + +typedef struct _EphyrHostVideoFormat { + char depth ; + short visual_class; +} EphyrHostVideoFormat ; + +typedef struct _EphyrHostRational { + int numerator ; + int denominator ; +} EphyrHostRational; + +typedef struct _EphyrHostEncoding { + int id ; + char *name ; + unsigned short width, height ; + EphyrHostRational rate ; +} EphyrHostEncoding ; + +typedef struct _EphyrHostAttribute { + int flags; + int min_value; + int max_value; + char *name; +} EphyrHostAttribute ; + +typedef struct _EphyrHostImageFormat { + int id; /* Unique descriptor for the format */ + int type; /* XvRGB, XvYUV */ + int byte_order; /* LSBFirst, MSBFirst */ + char guid[16]; /* Globally Unique IDentifier */ + int bits_per_pixel; + int format; /* XvPacked, XvPlanar */ + int num_planes; + + /* for RGB formats only */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats only */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; /* eg. UYVY */ + int scanline_order; /* XvTopToBottom, XvBottomToTop */ +} EphyrHostImageFormat ; + +typedef struct { + unsigned short x1, y1, x2, y2 ; +} EphyrHostBox ; + +void ephyrHostXVInit (void) ; + +void ephyrHostFree (void *a_pointer) ; + +/* + * host adaptor array + */ +Bool ephyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) ; +void ephyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) ; +int ephyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) ; +EphyrHostXVAdaptor* ephyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, + int a_index) ; + +/* + * host adaptor + */ + +char ephyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) ; +const char* ephyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) ; +EphyrHostVideoFormat* ephyrHostXVAdaptorGetVideoFormats + (const EphyrHostXVAdaptor *a_this, + int *a_nb_formats) ; +int ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) ; +int ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) ; + +Bool ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; +Bool ephyrHostXVAdaptorHasGetVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; +Bool ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; +Bool ephyrHostXVAdaptorHasGetStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; +Bool ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, + Bool *a_result) ; + +/* + * encoding + */ +Bool ephyrHostXVQueryEncodings (int a_port_id, + EphyrHostEncoding **a_encodings, + unsigned int *a_num_encodings) ; + +void ephyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, + int a_num_encodings) ; + +/* + * attribute + */ +Bool ephyrHostXVQueryPortAttributes (int a_port_id, + EphyrHostAttribute **a_attributes, + int *a_num_attributes) ; + +void ephyrHostAttributesDelete (EphyrHostAttribute *a_attributes) ; +/* + * image format + */ + +Bool ephyrHostXVQueryImageFormats (int a_port_id, + EphyrHostImageFormat **a_formats, + int *a_num_format) ; +/* + * Port Attribute Get/Set + */ +Bool ephyrHostXVSetPortAttribute (int a_port_id, + int a_atom, + int a_attr_value) ; +Bool ephyrHostXVGetPortAttribute (int a_port_id, + int a_atom, + int *a_attr_value) ; +/* + *size query + */ +Bool ephyrHostXVQueryBestSize (int a_port_id, + Bool a_motion, + unsigned int a_frame_w, + unsigned int a_frame_h, + unsigned int a_drw_w, + unsigned int a_drw_h, + unsigned int *a_actual_w, + unsigned int *a_actual_h) ; + +Bool ephyrHostXVQueryImageAttributes (int a_port_id, + int a_image_id /*image fourcc code*/, + unsigned short *a_width, + unsigned short *a_height, + int *a_image_size, + int *a_pitches, + int *a_offsets) ; +/* + * atom + */ +Bool ephyrHostGetAtom (const char* a_name, + Bool a_create_if_not_exists, + int *a_atom) ; +char* ephyrHostGetAtomName (int a_atom) ; + +/* + *PutImage + * (ignore clipping for now) + */ +Bool ephyrHostXVPutImage (int a_screen_num, + int a_port_id, + int a_image_id, + int a_drw_x, + int a_drw_y, + int a_drw_w, + int a_drw_h, + int a_src_x, + int a_src_y, + int a_src_w, + int a_src_h, + int a_image_width, + int a_image_height, + unsigned char *a_buf, + EphyrHostBox *a_clip_rects, + int a_clip_rect_nums) ; + +/* + * Putvideo/PutStill/GetVideo + */ +Bool ephyrHostXVPutVideo (int a_screen_num, + int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; + +Bool ephyrHostXVGetVideo (int a_screen_num, + int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; + +Bool ephyrHostXVPutStill (int a_screen_num, + int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; + +Bool ephyrHostXVGetStill (int a_screen_num, + int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ; + +/* + * StopVideo + */ +Bool ephyrHostXVStopVideo (int a_screen_num, int a_port_id) ; + +#endif /*__EPHYRHOSTVIDEO_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index 687460952..6196996a9 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -27,12 +27,19 @@ #include #endif #include "ephyr.h" +#include "ephyrlog.h" extern Window EphyrPreExistingHostWin; extern Bool EphyrWantGrayScale; extern Bool kdHasPointer; extern Bool kdHasKbd; +#ifdef GLXEXT +extern Bool ephyrNoDRI; +extern Bool noGlxVisualInit; +#endif +extern Bool ephyrNoXV; + void processScreenArg (char *screen_size, char *parent_id) ; void @@ -92,11 +99,16 @@ ddxUseMsg (void) KdUseMsg(); ErrorF("\nXephyr Option Usage:\n"); - ErrorF("-parent XID Use existing window as Xephyr root win\n"); - ErrorF("-host-cursor Re-use exisiting X host server cursor\n"); - ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n"); - ErrorF("-grayscale Simulate 8bit grayscale\n"); - ErrorF("-fakexa Simulate acceleration using software rendering\n"); + ErrorF("-parent Use existing window as Xephyr root win\n"); + ErrorF("-host-cursor Re-use exisiting X host server cursor\n"); + ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n"); + ErrorF("-grayscale Simulate 8bit grayscale\n"); + ErrorF("-fakexa Simulate acceleration using software rendering\n"); + ErrorF("-verbosity Set log verbosity level\n"); +#ifdef GLXEXT + ErrorF("-nodri do not use DRI\n"); +#endif + ErrorF("-noxv do not use XV\n"); ErrorF("\n"); exit(1); @@ -106,7 +118,6 @@ void processScreenArg (char *screen_size, char *parent_id) { KdCardInfo *card; - static int card_exists; InitCard (0); /*Put each screen on a separate card*/ card = KdCardInfoLast (); @@ -182,6 +193,36 @@ ddxProcessArgument (int argc, char **argv, int i) ephyrFuncs.finiAccel = ephyrDrawFini; return 1; } + else if (!strcmp (argv[i], "-verbosity")) + { + if(i+1 < argc && argv[i+1][0] != '-') + { + int verbosity=atoi (argv[i+1]) ; + LogSetParameter (XLOG_VERBOSITY, verbosity) ; + EPHYR_LOG ("set verbosiry to %d\n", verbosity) ; + return 2 ; + } + else + { + UseMsg() ; + exit(1) ; + } + } +#ifdef GLXEXT + else if (!strcmp (argv[i], "-nodri")) + { + noGlxVisualInit = FALSE ; + ephyrNoDRI = TRUE ; + EPHYR_LOG ("no direct rendering enabled\n") ; + return 1 ; + } +#endif + else if (!strcmp (argv[i], "-noxv")) + { + ephyrNoXV = TRUE ; + EPHYR_LOG ("no XVideo enabled\n") ; + return 1 ; + } else if (argv[i][0] == ':') { hostx_set_display_name(argv[i]); diff --git a/hw/kdrive/ephyr/ephyrlog.h b/hw/kdrive/ephyr/ephyrlog.h new file mode 100644 index 000000000..4c6435edd --- /dev/null +++ b/hw/kdrive/ephyr/ephyrlog.h @@ -0,0 +1,67 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifndef __EPHYRLOG_H__ +#define __EPHYRLOG_H__ + +#include +#include "os.h" + +#ifdef NDEBUG +/*we are not in debug mode*/ +#define EPHYR_LOG +#define EPHYR_LOG_ERROR +#endif /*NDEBUG*/ + +#define ERROR_LOG_LEVEL 3 +#define INFO_LOG_LEVEL 4 + +#ifndef EPHYR_LOG +#define EPHYR_LOG(...) \ +LogMessageVerb(X_NOTICE, INFO_LOG_LEVEL, "in %s:%d:%s: ",\ + __FILE__, __LINE__, __func__) ; \ +LogMessageVerb(X_NOTICE, INFO_LOG_LEVEL, __VA_ARGS__) +#endif /*nomadik_log*/ + +#ifndef EPHYR_LOG_ERROR +#define EPHYR_LOG_ERROR(...) \ +LogMessageVerb(X_NOTICE, ERROR_LOG_LEVEL, "Error:in %s:%d:%s: ",\ + __FILE__, __LINE__, __func__) ; \ +LogMessageVerb(X_NOTICE, ERROR_LOG_LEVEL, __VA_ARGS__) +#endif /*EPHYR_LOG_ERROR*/ + +#ifndef EPHYR_RETURN_IF_FAIL +#define EPHYR_RETURN_IF_FAIL(cond) \ +if (!(cond)) {EPHYR_LOG_ERROR("condition %s failed\n", #cond);return;} +#endif /*nomadik_return_if_fail*/ + +#ifndef EPHYR_RETURN_VAL_IF_FAIL +#define EPHYR_RETURN_VAL_IF_FAIL(cond,val) \ +if (!(cond)) {EPHYR_LOG_ERROR("condition %s failed\n", #cond);return val;} +#endif /*nomadik_return_val_if_fail*/ + +#endif /*__EPHYRLOG_H__*/ diff --git a/hw/kdrive/ephyr/ephyrproxyext.c b/hw/kdrive/ephyr/ephyrproxyext.c new file mode 100644 index 000000000..0c070f4c7 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrproxyext.c @@ -0,0 +1,119 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ + +/* + * \file + * This file defines a proxy extension that forwards requests. + * When a request to extension FOO is sent to Xephyr, that request is forwared + * to the host X, without even trying to know what the request means. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "ephyrproxyext.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include "ephyrhostproxy.h" +#include "hostx.h" + +static Bool ephyrProxyGetHostExtensionInfo (const char *a_ext_name, + int *a_major_opcode, + int *a_first_event, + int *a_first_error) ; + +static int ephyrProxyProcDispatch (ClientPtr client) ; + +static Bool +ephyrProxyGetHostExtensionInfo (const char *a_ext_name, + int *a_major_opcode, + int *a_first_event, + int *a_first_error) +{ + return hostx_get_extension_info (a_ext_name, a_major_opcode, + a_first_event, a_first_error) ; +} + +static int +ephyrProxyProcDispatch (ClientPtr a_client) +{ + int res=BadImplementation ; + struct XReply reply ; + + if (!ephyrHostProxyDoForward (a_client->requestBuffer, &reply, FALSE)) { + EPHYR_LOG_ERROR ("forwarding failed\n") ; + goto out ; + } + reply.sequence_number = a_client->sequence; + res = Success ; + + WriteToClient(a_client, 32, (char *)&reply); + +out: + return res ; +} + +static void +ephyrProxyProcReset (ExtensionEntry *a_entry) +{ +} + +Bool +ephyrProxyExtensionInit (const char *a_extension_name) +{ + Bool is_ok = FALSE ; + int major_opcode=0, first_event=0, first_error=0; + ExtensionEntry *ext=NULL ; + + if (!ephyrProxyGetHostExtensionInfo (a_extension_name, + &major_opcode, + &first_event, + &first_error)) { + EPHYR_LOG ("failed to query extension %s from host\n", a_extension_name) ; + goto out; + } + ext = AddExtension ((char*)a_extension_name, 0, 0, + ephyrProxyProcDispatch, + ephyrProxyProcDispatch, + ephyrProxyProcReset, + StandardMinorOpcode) ; + if (!ext) { + EPHYR_LOG_ERROR ("failed to add the extension\n") ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + diff --git a/hw/kdrive/ephyr/ephyrproxyext.h b/hw/kdrive/ephyr/ephyrproxyext.h new file mode 100644 index 000000000..e52f8d887 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrproxyext.h @@ -0,0 +1,34 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ +#ifndef __EPHYRPROXYEXT_H__ +#define __EPHYRPROXYEXT_H__ + +Bool ephyrProxyExtensionInit (const char *a_extension_name) ; + +#endif /*__EPHYRPROXYEXT_H__*/ + diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c new file mode 100644 index 000000000..bfe4d7223 --- /dev/null +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -0,0 +1,1278 @@ +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include "ephyrlog.h" +#include "kdrive.h" +#include "kxv.h" +#include "ephyr.h" +#include "hostx.h" +#include "ephyrhostvideo.h" + +struct _EphyrXVPriv { + EphyrHostXVAdaptorArray *host_adaptors ; + KdVideoAdaptorPtr adaptors ; + int num_adaptors ; +}; +typedef struct _EphyrXVPriv EphyrXVPriv ; + +struct _EphyrPortPriv { + int port_number ; + KdVideoAdaptorPtr current_adaptor ; + EphyrXVPriv *xv_priv; + unsigned char *image_buf ; + int image_buf_size ; + int image_id ; + int drw_x, drw_y, drw_w, drw_h ; + int src_x, src_y, src_w, src_h ; + int image_width, image_height ; +}; +typedef struct _EphyrPortPriv EphyrPortPriv ; + +static Bool DoSimpleClip (BoxPtr a_dst_drw, + BoxPtr a_clipper, + BoxPtr a_result) ; + +static Bool ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; + +/* +static Bool ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; +*/ + +static EphyrXVPriv* ephyrXVPrivNew (void) ; +static void ephyrXVPrivDelete (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, + ScreenPtr a_screen) ; + +static Bool ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, + int a_attrs_len, + const char *a_attr_name, + int a_attr_value, + Bool *a_is_valid) ; + +static Bool ephyrXVPrivGetImageBufSize (int a_port_id, + int a_image_id, + unsigned short a_width, + unsigned short a_height, + int *a_size) ; + +static Bool ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv, + const unsigned char *a_image, + int a_image_len) ; + +static void ephyrStopVideo (KdScreenInfo *a_info, + pointer a_xv_priv, + Bool a_exit); + +static int ephyrSetPortAttribute (KdScreenInfo *a_info, + Atom a_attr_name, + int a_attr_value, + pointer a_port_priv); + +static int ephyrGetPortAttribute (KdScreenInfo *a_screen_info, + Atom a_attr_name, + int *a_attr_value, + pointer a_port_priv); + +static void ephyrQueryBestSize (KdScreenInfo *a_info, + Bool a_motion, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + unsigned int *a_prefered_w, + unsigned int *a_prefered_h, + pointer a_port_priv); + +static int ephyrPutImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_src_x, + short a_src_y, + short a_drw_x, + short a_drw_y, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + int a_id, + unsigned char *a_buf, + short a_width, + short a_height, + Bool a_sync, + RegionPtr a_clipping_region, + pointer a_port_priv); + +static int ephyrReputImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_drw_x, + short a_drw_y, + RegionPtr a_clipping_region, + pointer a_port_priv) ; + +static int ephyrPutVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrGetVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrPutStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrGetStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrQueryImageAttributes (KdScreenInfo *a_info, + int a_id, + unsigned short *a_w, + unsigned short *a_h, + int *a_pitches, + int *a_offsets); +static int s_base_port_id ; + +/************** + * + * ************/ + +static Bool +DoSimpleClip (BoxPtr a_dst_box, + BoxPtr a_clipper, + BoxPtr a_result) +{ + BoxRec dstClippedBox ; + + EPHYR_RETURN_VAL_IF_FAIL (a_dst_box && a_clipper && a_result, FALSE) ; + + /* + * setup the clipbox inside the destination. + */ + dstClippedBox.x1 = a_dst_box->x1 ; + dstClippedBox.x2 = a_dst_box->x2 ; + dstClippedBox.y1 = a_dst_box->y1 ; + dstClippedBox.y2 = a_dst_box->y2 ; + + /* + * if the cliper leftmost edge is inside + * the destination area then the leftmost edge of the resulting + * clipped box is the leftmost edge of the cliper. + */ + if (a_clipper->x1 > dstClippedBox.x1) + dstClippedBox.x1 = a_clipper->x1 ; + + /* + * if the cliper top edge is inside the destination area + * then the bottom horizontal edge of the resulting clipped box + * is the bottom edge of the cliper + */ + if (a_clipper->y1 > dstClippedBox.y1) + dstClippedBox.y1 = a_clipper->y1 ; + + /*ditto for right edge*/ + if (a_clipper->x2 < dstClippedBox.x2) + dstClippedBox.x2 = a_clipper->x2 ; + + /*ditto for bottom edge*/ + if (a_clipper->y2 < dstClippedBox.y2) + dstClippedBox.y2 = a_clipper->y2 ; + + memcpy (a_result, &dstClippedBox, sizeof (dstClippedBox)) ; + return TRUE ; +} + +static Bool +ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) +{ + char *atom_name=NULL; + int host_atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_host_atom, FALSE) ; + + if (!ValidAtom (a_local_atom)) + return FALSE ; + + atom_name = NameForAtom (a_local_atom) ; + + if (!atom_name) + return FALSE ; + + if (!ephyrHostGetAtom (atom_name, FALSE, &host_atom) || host_atom == None) { + EPHYR_LOG_ERROR ("no atom for string %s defined in host X\n", + atom_name) ; + return FALSE ; + } + *a_host_atom = host_atom ; + return TRUE ; +} + +/* + Not used yed. +static Bool +ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) +{ + Bool is_ok=FALSE ; + char *atom_name=NULL ; + int atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_local_atom, FALSE) ; + + atom_name = ephyrHostGetAtomName (a_host_atom) ; + if (!atom_name) + goto out ; + + atom = MakeAtom (atom_name, strlen (atom_name), TRUE) ; + if (atom == None) + goto out ; + + *a_local_atom = atom ; + is_ok = TRUE ; + +out: + if (atom_name) { + ephyrHostFree (atom_name) ; + } + return is_ok ; +} +*/ + +/************** + * + * ************/ + +Bool +ephyrInitVideo (ScreenPtr pScreen) +{ + Bool is_ok = FALSE ; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + static EphyrXVPriv *xv_priv; + + EPHYR_LOG ("enter\n") ; + + if (screen->fb[0].bitsPerPixel == 8) { + EPHYR_LOG_ERROR ("8 bits depth not supported\n") ; + return FALSE ; + } + + if (!xv_priv) { + xv_priv = ephyrXVPrivNew () ; + } + if (!xv_priv) { + EPHYR_LOG_ERROR ("failed to create xv_priv\n") ; + goto out ; + } + + if (!ephyrXVPrivRegisterAdaptors (xv_priv, pScreen)) { + EPHYR_LOG_ERROR ("failed to register adaptors\n") ; + goto out ; + } + is_ok = TRUE ; + +out: + return is_ok ; +} + +static EphyrXVPriv* +ephyrXVPrivNew (void) +{ + EphyrXVPriv *xv_priv=NULL ; + + EPHYR_LOG ("enter\n") ; + + xv_priv = xcalloc (1, sizeof (EphyrXVPriv)) ; + if (!xv_priv) { + EPHYR_LOG_ERROR ("failed to create EphyrXVPriv\n") ; + goto error ; + } + + ephyrHostXVInit () ; + + if (!ephyrXVPrivQueryHostAdaptors (xv_priv)) { + EPHYR_LOG_ERROR ("failed to query the host x for xv properties\n") ; + goto error ; + } + if (!ephyrXVPrivSetAdaptorsHooks (xv_priv)) { + EPHYR_LOG_ERROR ("failed to set xv_priv hooks\n") ; + goto error ; + } + + EPHYR_LOG ("leave\n") ; + return xv_priv ; + +error: + if (xv_priv) { + ephyrXVPrivDelete (xv_priv) ; + xv_priv = NULL ; + } + return NULL ; +} + +static void +ephyrXVPrivDelete (EphyrXVPriv *a_this) +{ + EPHYR_LOG ("enter\n") ; + + if (!a_this) + return ; + if (a_this->host_adaptors) { + ephyrHostXVAdaptorArrayDelete (a_this->host_adaptors) ; + a_this->host_adaptors = NULL ; + } + if (a_this->adaptors) { + xfree (a_this->adaptors) ; + a_this->adaptors = NULL ; + } + xfree (a_this) ; + EPHYR_LOG ("leave\n") ; +} + +static KdVideoEncodingPtr +videoEncodingDup (EphyrHostEncoding *a_encodings, + int a_num_encodings) +{ + KdVideoEncodingPtr result = NULL ; + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ; + + result = xcalloc (a_num_encodings, sizeof (KdVideoEncodingRec)) ; + for (i=0 ; i < a_num_encodings; i++) { + result[i].id = a_encodings[i].id ; + result[i].name = strdup (a_encodings[i].name) ; + result[i].width = a_encodings[i].width ; + result[i].height = a_encodings[i].height ; + result[i].rate.numerator = a_encodings[i].rate.numerator ; + result[i].rate.denominator = a_encodings[i].rate.denominator ; + } + return result ; +} + +static KdAttributePtr +portAttributesDup (EphyrHostAttribute *a_encodings, + int a_num_encodings) +{ + int i=0 ; + KdAttributePtr result=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ; + + result = xcalloc (a_num_encodings, sizeof (KdAttributeRec)) ; + if (!result) { + EPHYR_LOG_ERROR ("failed to allocate attributes\n") ; + return NULL ; + } + for (i=0; i < a_num_encodings; i++) { + result[i].flags = a_encodings[i].flags ; + result[i].min_value = a_encodings[i].min_value ; + result[i].max_value = a_encodings[i].max_value ; + result[i].name = strdup (a_encodings[i].name) ; + } + return result ; +} + +static Bool +ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) +{ + EphyrHostXVAdaptor *cur_host_adaptor=NULL ; + EphyrHostVideoFormat *video_formats=NULL ; + EphyrHostEncoding *encodings=NULL ; + EphyrHostAttribute *attributes=NULL ; + EphyrHostImageFormat *image_formats=NULL ; + int num_video_formats=0, base_port_id=0, + num_attributes=0, num_formats=0, i=0, + port_priv_offset=0; + unsigned num_encodings=0 ; + Bool is_ok = FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostXVQueryAdaptors (&a_this->host_adaptors)) { + EPHYR_LOG_ERROR ("failed to query host adaptors\n") ; + goto out ; + } + if (a_this->host_adaptors) + a_this->num_adaptors = + ephyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; + if (a_this->num_adaptors < 0) { + EPHYR_LOG_ERROR ("failed to get number of host adaptors\n") ; + goto out ; + } + EPHYR_LOG ("host has %d adaptors\n", a_this->num_adaptors) ; + /* + * copy what we can from adaptors into a_this->adaptors + */ + if (a_this->num_adaptors) { + a_this->adaptors = xcalloc (a_this->num_adaptors, + sizeof (KdVideoAdaptorRec)) ; + if (!a_this->adaptors) { + EPHYR_LOG_ERROR ("failed to create internal adaptors\n") ; + goto out ; + } + } + for (i=0; i < a_this->num_adaptors; i++) { + int j=0 ; + cur_host_adaptor = + ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; + if (!cur_host_adaptor) + continue ; + a_this->adaptors[i].nPorts = + ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + if (a_this->adaptors[i].nPorts <=0) { + EPHYR_LOG_ERROR ("Could not find any port of adaptor %d\n", i) ; + continue ; + } + a_this->adaptors[i].type = + ephyrHostXVAdaptorGetType (cur_host_adaptor) ; + a_this->adaptors[i].type |= XvWindowMask ; + a_this->adaptors[i].flags = + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + if (ephyrHostXVAdaptorGetName (cur_host_adaptor)) + a_this->adaptors[i].name = + strdup (ephyrHostXVAdaptorGetName (cur_host_adaptor)) ; + else + a_this->adaptors[i].name = strdup ("Xephyr Video Overlay"); + base_port_id = ephyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ; + if (base_port_id < 0) { + EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; + continue ; + } + if (!s_base_port_id) + s_base_port_id = base_port_id ; + + if (!ephyrHostXVQueryEncodings (base_port_id, + &encodings, + &num_encodings)) { + EPHYR_LOG_ERROR ("failed to get encodings for port port id %d," + " adaptors %d\n", + base_port_id, i) ; + continue ; + } + a_this->adaptors[i].nEncodings = num_encodings ; + a_this->adaptors[i].pEncodings = + videoEncodingDup (encodings, num_encodings) ; + video_formats = (EphyrHostVideoFormat*) + ephyrHostXVAdaptorGetVideoFormats (cur_host_adaptor, + &num_video_formats); + a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats ; + a_this->adaptors[i].nFormats = num_video_formats ; + /* got a_this->adaptors[i].nPorts already + a_this->adaptors[i].nPorts = + ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + */ + a_this->adaptors[i].pPortPrivates = + xcalloc (a_this->adaptors[i].nPorts, + sizeof (DevUnion) + sizeof (EphyrPortPriv)) ; + port_priv_offset = a_this->adaptors[i].nPorts; + for (j=0; j < a_this->adaptors[i].nPorts; j++) { + EphyrPortPriv *port_privs_base = + (EphyrPortPriv*)&a_this->adaptors[i].pPortPrivates[port_priv_offset]; + EphyrPortPriv *port_priv = &port_privs_base[j] ; + port_priv->port_number = base_port_id + j; + port_priv->current_adaptor = &a_this->adaptors[i] ; + port_priv->xv_priv = a_this ; + a_this->adaptors[i].pPortPrivates[j].ptr = port_priv; + } + if (!ephyrHostXVQueryPortAttributes (base_port_id, + &attributes, + &num_attributes)) { + EPHYR_LOG_ERROR ("failed to get port attribute " + "for adaptor %d\n", i) ; + continue ; + } + a_this->adaptors[i].pAttributes = + portAttributesDup (attributes, num_attributes); + a_this->adaptors[i].nAttributes = num_attributes ; + /*make sure atoms of attrs names are created in xephyr*/ + for (j=0; j < a_this->adaptors[i].nAttributes; j++) { + if (a_this->adaptors[i].pAttributes[j].name) + MakeAtom (a_this->adaptors[i].pAttributes[j].name, + strlen (a_this->adaptors[i].pAttributes[j].name), + TRUE) ; + } + if (!ephyrHostXVQueryImageFormats (base_port_id, + &image_formats, + &num_formats)) { + EPHYR_LOG_ERROR ("failed to get image formats " + "for adaptor %d\n", i) ; + continue ; + } + a_this->adaptors[i].pImages = (KdImagePtr) image_formats ; + a_this->adaptors[i].nImages = num_formats ; + } + is_ok = TRUE ; + +out: + if (encodings) { + ephyrHostEncodingsDelete (encodings, num_encodings) ; + encodings = NULL ; + } + if (attributes) { + ephyrHostAttributesDelete (attributes) ; + attributes = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) +{ + int i=0 ; + Bool has_it=FALSE ; + EphyrHostXVAdaptor *cur_host_adaptor=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + for (i=0; i < a_this->num_adaptors; i++) { + a_this->adaptors[i].ReputImage = ephyrReputImage ; + a_this->adaptors[i].StopVideo = ephyrStopVideo ; + a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute ; + a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute ; + a_this->adaptors[i].QueryBestSize = ephyrQueryBestSize ; + a_this->adaptors[i].QueryImageAttributes = ephyrQueryImageAttributes ; + + cur_host_adaptor = + ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; + if (!cur_host_adaptor) { + EPHYR_LOG_ERROR ("failed to get host adaptor at index %d\n", i) ; + continue ; + } + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutImage (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].PutImage = ephyrPutImage; + } + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutVideo (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].PutVideo = ephyrPutVideo; + } + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasGetVideo (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].GetVideo = ephyrGetVideo; + } + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutStill (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].PutStill = ephyrPutStill; + } + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasGetStill (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].GetStill = ephyrGetStill; + } + } + EPHYR_LOG ("leave\n") ; + return TRUE ; +} + +static Bool +ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, + ScreenPtr a_screen) +{ + KdScreenPriv(a_screen); + KdScreenInfo *screen = pScreenPriv->screen; + Bool is_ok = FALSE ; + KdVideoAdaptorPtr *adaptors=NULL, *registered_adaptors=NULL ; + int num_registered_adaptors=0, i=0, num_adaptors=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_screen, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!a_this->num_adaptors) + goto out ; + num_registered_adaptors = + KdXVListGenericAdaptors (screen, ®istered_adaptors); + + num_adaptors = num_registered_adaptors + a_this->num_adaptors ; + adaptors = xcalloc (num_adaptors, sizeof (KdVideoAdaptorPtr)) ; + if (!adaptors) { + EPHYR_LOG_ERROR ("failed to allocate adaptors tab\n") ; + goto out ; + } + memmove (adaptors, registered_adaptors, num_registered_adaptors) ; + for (i=0 ; i < a_this->num_adaptors; i++) { + *(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i] ; + } + if (!KdXVScreenInit (a_screen, adaptors, num_adaptors)) { + EPHYR_LOG_ERROR ("failed to register adaptors\n"); + goto out ; + } + EPHYR_LOG ("there are %d registered adaptors\n", num_adaptors) ; + is_ok = TRUE ; + +out: + if (registered_adaptors) { + xfree (registered_adaptors) ; + registered_adaptors = NULL ; + } + if (adaptors) { + xfree (adaptors) ; + adaptors=NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, + int a_attrs_len, + const char *a_attr_name, + int a_attr_value, + Bool *a_is_valid) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_attrs && a_attr_name && a_is_valid, + FALSE) ; + + for (i=0; i < a_attrs_len; i++) { + if (a_attrs[i].name && strcmp (a_attrs[i].name, a_attr_name)) + continue ; + if (a_attrs[i].min_value > a_attr_value || + a_attrs[i].max_value < a_attr_value) { + *a_is_valid = FALSE ; + EPHYR_LOG_ERROR ("attribute was not valid\n" + "value:%d. min:%d. max:%d\n", + a_attr_value, + a_attrs[i].min_value, + a_attrs[i].max_value) ; + } else { + *a_is_valid = TRUE ; + } + return TRUE ; + } + return FALSE ; +} + +static Bool +ephyrXVPrivGetImageBufSize (int a_port_id, + int a_image_id, + unsigned short a_width, + unsigned short a_height, + int *a_size) +{ + Bool is_ok=FALSE ; + unsigned short width=a_width, height=a_height ; + + EPHYR_RETURN_VAL_IF_FAIL (a_size, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostXVQueryImageAttributes (a_port_id, a_image_id, + &width, &height, a_size, NULL, NULL)) { + EPHYR_LOG_ERROR ("failed to get image attributes\n") ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv, + const unsigned char *a_image_buf, + int a_image_len) +{ + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + + if (a_port_priv->image_buf_size < a_image_len) { + unsigned char *buf=NULL ; + buf = realloc (a_port_priv->image_buf, a_image_len) ; + if (!buf) { + EPHYR_LOG_ERROR ("failed to realloc image buffer\n") ; + goto out ; + } + a_port_priv->image_buf = buf ; + a_port_priv->image_buf_size = a_image_len; + } + memmove (a_port_priv->image_buf, a_image_buf, a_image_len) ; + is_ok = TRUE ; + +out: + return is_ok ; + EPHYR_LOG ("leave\n") ; +} + +static void +ephyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit) +{ + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_IF_FAIL (a_info && a_info->pScreen) ; + EPHYR_RETURN_IF_FAIL (port_priv) ; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostXVStopVideo (a_info->pScreen->myNum, + port_priv->port_number)) { + EPHYR_LOG_ERROR ("XvStopVideo() failed\n") ; + } + EPHYR_LOG ("leave\n") ; +} + +static int +ephyrSetPortAttribute (KdScreenInfo *a_info, + Atom a_attr_name, + int a_attr_value, + pointer a_port_priv) +{ + int res=Success, host_atom=0 ; + EphyrPortPriv *port_priv = a_port_priv ; + Bool is_attr_valid=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->pAttributes, + BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->nAttributes, + BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; + + EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n", + port_priv->port_number, + (int)a_attr_name, + NameForAtom (a_attr_name), + a_attr_value) ; + + if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) { + EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; + res = BadMatch ; + goto out ; + } + + if (!ephyrXVPrivIsAttrValueValid (port_priv->current_adaptor->pAttributes, + port_priv->current_adaptor->nAttributes, + NameForAtom (a_attr_name), + a_attr_value, + &is_attr_valid)) { + EPHYR_LOG_ERROR ("failed to validate attribute %s\n", + NameForAtom (a_attr_name)) ; + /* + res = BadMatch ; + goto out ; + */ + } + if (!is_attr_valid) { + EPHYR_LOG_ERROR ("attribute %s is not valid\n", + NameForAtom (a_attr_name)) ; + /* + res = BadMatch ; + goto out ; + */ + } + + if (!ephyrHostXVSetPortAttribute (port_priv->port_number, + host_atom, + a_attr_value)) { + EPHYR_LOG_ERROR ("failed to set port attribute\n") ; + res = BadMatch ; + goto out ; + } + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +static int +ephyrGetPortAttribute (KdScreenInfo *a_screen_info, + Atom a_attr_name, + int *a_attr_value, + pointer a_port_priv) +{ + int res=Success, host_atom=0 ; + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; + + EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s\n", + port_priv->port_number, + (int)a_attr_name, + NameForAtom (a_attr_name)) ; + + if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) { + EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; + res = BadMatch ; + goto out ; + } + + if (!ephyrHostXVGetPortAttribute (port_priv->port_number, + host_atom, + a_attr_value)) { + EPHYR_LOG_ERROR ("failed to get port attribute\n") ; + res = BadMatch ; + goto out ; + } + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +static void +ephyrQueryBestSize (KdScreenInfo *a_info, + Bool a_motion, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + unsigned int *a_prefered_w, + unsigned int *a_prefered_h, + pointer a_port_priv) +{ + int res=0 ; + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_IF_FAIL (port_priv) ; + + EPHYR_LOG ("enter\n") ; + res = ephyrHostXVQueryBestSize (port_priv->port_number, + a_motion, + a_src_w, a_src_h, + a_drw_w, a_drw_h, + a_prefered_w, a_prefered_h) ; + if (!res) { + EPHYR_LOG_ERROR ("Failed to query best size\n") ; + } + EPHYR_LOG ("leave\n") ; +} + +static int +ephyrPutImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_src_x, + short a_src_y, + short a_drw_x, + short a_drw_y, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + int a_id, + unsigned char *a_buf, + short a_width, + short a_height, + Bool a_sync, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + Bool is_ok=FALSE ; + int result=BadImplementation, image_size=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostXVPutImage (a_info->pScreen->myNum, + port_priv->port_number, + a_id, + a_drw_x, a_drw_y, a_drw_w, a_drw_h, + a_src_x, a_src_y, a_src_w, a_src_h, + a_width, a_height, a_buf, + (EphyrHostBox*)REGION_RECTS (a_clipping_region), + REGION_NUM_RECTS (a_clipping_region))) { + EPHYR_LOG_ERROR ("EphyrHostXVPutImage() failed\n") ; + goto out ; + } + + /* + * Now save the image so that we can resend it to host it + * later, in ReputImage. + */ + if (!ephyrXVPrivGetImageBufSize (port_priv->port_number, + a_id, a_width, a_height, &image_size)) { + EPHYR_LOG_ERROR ("failed to get image size\n") ; + /*this is a minor error so we won't get bail out abruptly*/ + is_ok = FALSE ; + } else { + is_ok = TRUE ; + } + if (is_ok) { + if (!ephyrXVPrivSaveImageToPortPriv (port_priv, a_buf, image_size)) { + is_ok=FALSE ; + } else { + port_priv->image_id = a_id; + port_priv->drw_x = a_drw_x; + port_priv->drw_y = a_drw_y; + port_priv->drw_w = a_drw_w ; + port_priv->drw_h = a_drw_h ; + port_priv->src_x = a_src_x; + port_priv->src_y = a_src_y ; + port_priv->src_w = a_src_w ; + port_priv->src_h = a_src_h ; + port_priv->image_width = a_width ; + port_priv->image_height = a_height ; + } + } + if (!is_ok) { + if (port_priv->image_buf) { + free (port_priv->image_buf) ; + port_priv->image_buf = NULL ; + port_priv->image_buf_size = 0 ; + } + } + + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrReputImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_drw_x, + short a_drw_y, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + int result=BadImplementation ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + if (!port_priv->image_buf_size || !port_priv->image_buf) { + EPHYR_LOG_ERROR ("has null image buf in cache\n") ; + goto out ; + } + if (!ephyrHostXVPutImage (a_info->pScreen->myNum, + port_priv->port_number, + port_priv->image_id, + a_drw_x, a_drw_y, + port_priv->drw_w, port_priv->drw_h, + port_priv->src_x, port_priv->src_y, + port_priv->src_w, port_priv->src_h, + port_priv->image_width, port_priv->image_height, + port_priv->image_buf, + (EphyrHostBox*)REGION_RECTS (a_clipping_region), + REGION_NUM_RECTS (a_clipping_region))) { + EPHYR_LOG_ERROR ("ephyrHostXVPutImage() failed\n") ; + goto out ; + } + + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrPutVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVPutVideo (a_info->pScreen->myNum, + port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVPutVideo() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrGetVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVGetVideo (a_info->pScreen->myNum, + port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVGetVideo() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrPutStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVPutStill (a_info->pScreen->myNum, + port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVPutStill() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrGetStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVGetStill (a_info->pScreen->myNum, + port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVGetStill() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrQueryImageAttributes (KdScreenInfo *a_info, + int a_id, + unsigned short *a_w, + unsigned short *a_h, + int *a_pitches, + int *a_offsets) +{ + int image_size=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_w && a_h, FALSE) ; + + EPHYR_LOG ("enter: dim (%dx%d), pitches: %#x, offsets: %#x\n", + *a_w, *a_h, (unsigned int)a_pitches, (unsigned int)a_offsets) ; + + if (!ephyrHostXVQueryImageAttributes (s_base_port_id, + a_id, + a_w, a_h, + &image_size, + a_pitches, a_offsets)) { + EPHYR_LOG_ERROR ("EphyrHostXVQueryImageAttributes() failed\n") ; + goto out ; + } + EPHYR_LOG ("image size: %d, dim (%dx%d)\n", image_size, *a_w, *a_h) ; + +out: + EPHYR_LOG ("leave\n") ; + return image_size ; +} diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 81678d927..b5ffdd075 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -23,6 +23,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "hostx.h" #include @@ -40,6 +44,17 @@ #include #include #include +#include +#ifdef XEPHYR_DRI +#include +#endif /*XEPHYR_DRI*/ +#include "ephyrlog.h" + +#ifdef XEPHYR_DRI +extern Bool XF86DRIQueryExtension (Display *dpy, + int *event_basep, + int *error_basep); +#endif /* * All xlib calls go here, which gets built as its own .a . @@ -956,3 +971,385 @@ hostx_get_event(EphyrHostXEvent *ev) return 0; } +void* +hostx_get_display(void) +{ + return HostX.dpy ; +} + +int +hostx_get_window (int a_screen_number) +{ + if (a_screen_number < 0 || a_screen_number >= HostX.n_screens) { + EPHYR_LOG_ERROR ("bad screen number:%d\n", a_screen_number) ; + return 0; + } + return HostX.screens[a_screen_number].win ; +} + +int +hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attrs) +{ + XWindowAttributes attrs ; + + memset (&attrs, 0, sizeof (attrs)) ; + + if (!XGetWindowAttributes (hostx_get_display (), + a_window, + &attrs)) { + return FALSE ; + } + a_attrs->x = attrs.x ; + a_attrs->y = attrs.y ; + a_attrs->width = attrs.width ; + a_attrs->height = attrs.height ; + if (attrs.visual) + a_attrs->visualid = attrs.visual->visualid ; + return TRUE ; +} + +int +hostx_get_extension_info (const char *a_ext_name, + int *a_major_opcode, + int *a_first_event, + int *a_first_error) +{ + if (!a_ext_name || !a_major_opcode || !a_first_event || !a_first_error) + return 0 ; + if (!XQueryExtension (HostX.dpy, + a_ext_name, + a_major_opcode, + a_first_event, + a_first_error)) + { + return 0 ; + } + return 1 ; +} + +int +hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals, + int *a_num_entries) +{ + Display *dpy=hostx_get_display () ; + Bool is_ok=False ; + XVisualInfo templ, *visuals=NULL; + EphyrHostVisualInfo *host_visuals=NULL ; + int nb_items=0, i=0; + + EPHYR_RETURN_VAL_IF_FAIL (a_visuals && a_num_entries && dpy, + False) ; + EPHYR_LOG ("enter\n") ; + memset (&templ, 0, sizeof (templ)) ; + visuals = XGetVisualInfo (dpy, VisualNoMask, &templ, &nb_items) ; + if (!visuals) { + EPHYR_LOG_ERROR ("host does not advertise any visual\n") ; + goto out ; + } + EPHYR_LOG ("host advertises %d visuals\n", nb_items) ; + host_visuals = calloc (nb_items, sizeof (EphyrHostVisualInfo)) ; + for (i=0; iscreen), + visual_info->visual, + AllocNone) ; + winmask = CWColormap; + + win = XCreateWindow (dpy, hostx_get_window (a_screen_number), + a_geometry->x, a_geometry->y, + a_geometry->width, a_geometry->height, 0, + visual_info->depth, InputOutput, + visual_info->visual, winmask, &attrs) ; + if (win == None) { + EPHYR_LOG_ERROR ("failed to create peer window\n") ; + goto out ; + } + XFlush (dpy) ; + XMapWindow (dpy, win) ; + *a_host_peer = win ; + is_ok = TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +int +hostx_destroy_window (int a_win) +{ + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + XDestroyWindow (dpy, a_win) ; + XFlush (dpy) ; + return TRUE ; +} + +int +hostx_set_window_geometry (int a_win, EphyrBox *a_geo) +{ + Display *dpy=hostx_get_display (); + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geo, FALSE) ; + + EPHYR_LOG ("enter. x,y,w,h:(%d,%d,%d,%d)\n", + a_geo->x, a_geo->y, + a_geo->width, a_geo->height) ; + + XMoveWindow (dpy, a_win, a_geo->x, a_geo->y) ; + XResizeWindow (dpy, a_win, a_geo->width, a_geo->height) ; + EPHYR_LOG ("leave\n") ; + return TRUE; +} + +int +hostx_set_window_bounding_rectangles (int a_window, + EphyrRect *a_rects, + int a_num_rects) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; + int i=0 ; + XRectangle *rects=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ; + + EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ; + + rects = calloc (a_num_rects, sizeof (XRectangle)) ; + for (i=0; iremote_id = XAllocID (dpy); + peer->local_id = a_local_resource_id ; + peer->is_valid = TRUE ; + } + } + if (peer) { + *a_remote_resource_id = peer->remote_id ; + return TRUE ; + } + return FALSE ; +} + +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + for (i=0; iremote_id ; + return TRUE ; + } + return FALSE ; +} + +int +hostx_has_dri (void) +{ + int event_base=0, error_base=0 ; + Display *dpy=hostx_get_display () ; + + if (!dpy) + return FALSE ; + + if (!XF86DRIQueryExtension (dpy, + &event_base, + &error_base)) { + return FALSE ; + } + return TRUE ; +} + +int +hostx_has_glx (void) +{ + Display *dpy=hostx_get_display () ; + int event_base=0, error_base=0 ; + + if (!glXQueryExtension (dpy, &event_base, &error_base)) { + return FALSE ; + } + return TRUE ; +} + +#endif /*XEPHYR_DRI*/ + diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 93765d096..3caa466a7 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -92,6 +92,32 @@ struct EphyrHostXEvent int key_state; }; +typedef struct { + VisualID visualid; + int screen; + int depth; + int class; + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + int colormap_size; + int bits_per_rgb; +} EphyrHostVisualInfo; + +typedef struct { + int x, y; + int width, height ; + int visualid ; +} EphyrHostWindowAttributes; + +typedef struct { + int x,y,width,height; +} EphyrBox; + +typedef struct { + short x1,y1,x2,y2; +} EphyrRect; + int hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height); @@ -167,9 +193,60 @@ hostx_paint_rect(EphyrScreenInfo screen, void -hostx_load_keymap(void); +hostx_load_keymap (void); int -hostx_get_event(EphyrHostXEvent *ev); +hostx_get_event (EphyrHostXEvent *ev); -#endif +void* +hostx_get_display (void) ; + +int +hostx_get_window (int a_screen_number) ; + +int +hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attr) ; + +int +hostx_get_extension_info (const char *a_ext_name, + int *a_major_opcode, + int *a_first_even, + int *a_first_error) ; +int +hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals, + int *a_num_entries) ; + +int hostx_create_window (int a_screen_number, + EphyrBox *a_geometry, + int a_visual_id, + int *a_host_win /*out parameter*/) ; + +int hostx_destroy_window (int a_win) ; + +int hostx_set_window_geometry (int a_win, EphyrBox *a_geo) ; + + +int hostx_set_window_bounding_rectangles (int a_window, + EphyrRect *a_rects, + int a_num_rects) ; + +int hostx_set_window_clipping_rectangles (int a_window, + EphyrRect *a_rects, + int a_num_rects) ; +int hostx_has_xshape (void) ; + +#ifdef XEPHYR_DRI +int hostx_lookup_peer_window (void *a_local_window, + int *a_host_peer /*out parameter*/) ; +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) ; +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) ; +int hostx_has_dri (void) ; + +int hostx_has_glx (void) ; +#endif /*XEPHYR_DRI*/ + +#endif /*_XLIBS_STUFF_H_*/ diff --git a/hw/kdrive/ephyr/os.c b/hw/kdrive/ephyr/os.c index b58daae68..4bf6e8858 100644 --- a/hw/kdrive/ephyr/os.c +++ b/hw/kdrive/ephyr/os.c @@ -28,6 +28,8 @@ #endif #include "ephyr.h" +extern void processScreenArg (char *screen_size, char *parent_id) ; + static int EphyrInit (void) { diff --git a/hw/kdrive/fbdev/Makefile.am b/hw/kdrive/fbdev/Makefile.am index 1ce4833a7..420855b8d 100644 --- a/hw/kdrive/fbdev/Makefile.am +++ b/hw/kdrive/fbdev/Makefile.am @@ -20,7 +20,7 @@ Xfbdev_LDADD = \ Xfbdev_DEPENDENCIES = \ libfbdev.a \ - @KDRIVE_LOCAL_LIBS@ + $(KDRIVE_PURE_LIBS) relink: rm -f $(bin_PROGRAMS) && make $(bin_PROGRAMS) diff --git a/hw/kdrive/src/Makefile.am b/hw/kdrive/src/Makefile.am index 20fae554a..07ab8c859 100644 --- a/hw/kdrive/src/Makefile.am +++ b/hw/kdrive/src/Makefile.am @@ -37,4 +37,4 @@ libkdrive_a_SOURCES = \ $(top_srcdir)/mi/miinitext.c libkdrivestubs_a_SOURCES = \ - $(top_srcdir)/fb/fbcmap.c + $(top_srcdir)/fb/fbcmap_mi.c diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c index 4bdf1ceb8..8117ace24 100644 --- a/hw/xfree86/common/xf86AutoConfig.c +++ b/hw/xfree86/common/xf86AutoConfig.c @@ -39,6 +39,7 @@ #include "xf86Config.h" #include "xf86Priv.h" #include "xf86_OSlib.h" +#include "dirent.h" /* Sections for the default built-in configuration. */ @@ -174,7 +175,7 @@ videoPtrToDriverName(struct pci_device *dev) case 0x8086: if ((dev->device_id == 0x00d1) || (dev->device_id == 0x7800)) return "i740"; - else return "i810"; + else return "intel"; case 0x102b: return "mga"; case 0x10c8: return "neomagic"; case 0x105d: return "i128"; @@ -214,27 +215,10 @@ xf86AutoConfig(void) { const char **p; char buf[1024]; - struct pci_device_iterator *iter; - struct pci_device * info = NULL; const char *driver = NULL; ConfigStatus ret; - /* Find the primary device, and get some information about it. */ - iter = pci_slot_match_iterator_create(NULL); - while ((info = pci_device_next(iter)) != NULL) { - if (xf86IsPrimaryPci(info)) { - break; - } - } - - pci_iterator_destroy(iter); - - if (!info) { - ErrorF("Primary device is not PCI\n"); - } - - if (info) - driver = videoPtrToDriverName(info); + driver = chooseVideoDriver(); AppendToConfig(BUILTIN_MODULE_SECTION); AppendToConfig(BUILTIN_MONITOR_SECTION); @@ -287,3 +271,217 @@ xf86AutoConfig(void) return (ret == CONFIG_OK); } + +int +xchomp(char *line) +{ + size_t len = 0; + + if (!line) { + return 1; + } + + len = strlen(line); + if (line[len - 1] == '\n' && len > 0) { + line[len - 1] = '\0'; + } + return 0; +} + +GDevPtr +autoConfigDevice(GDevPtr preconf_device) +{ + GDevPtr ptr = NULL; + + if (!xf86configptr) { + return NULL; + } + + /* If there's a configured section with no driver chosen, use it */ + if (preconf_device) { + ptr = preconf_device; + } else { + ptr = (GDevPtr)xalloc(sizeof(GDevRec)); + if (!ptr) { + return NULL; + } + memset((GDevPtr)ptr, 0, sizeof(GDevRec)); + ptr->chipID = -1; + ptr->chipRev = -1; + ptr->irq = -1; + + ptr->active = TRUE; + ptr->claimed = FALSE; + ptr->identifier = "Autoconfigured Video Device"; + ptr->driver = NULL; + } + if (!ptr->driver) { + ptr->driver = chooseVideoDriver(); + } + + /* TODO Handle multiple screen sections */ + if (xf86ConfigLayout.screens && !xf86ConfigLayout.screens->screen->device) { + xf86ConfigLayout.screens->screen->device = ptr; + ptr->myScreenSection = xf86ConfigLayout.screens->screen; + } + xf86Msg(X_DEFAULT, "Assigned the driver to the xf86ConfigLayout\n"); + + return ptr; +} + +#ifdef __linux__ +static void +matchDriverFromFiles (char** matches, uint16_t match_vendor, uint16_t match_chip) +{ + DIR *idsdir; + FILE *fp; + struct dirent *direntry; + char *line = NULL; + size_t len; + ssize_t read; + char path_name[256], vendor_str[5], chip_str[5]; + uint16_t vendor, chip; + int i, j; + idsdir = opendir("/usr/share/xserver-xorg/pci"); + + if (idsdir) { + direntry = readdir(idsdir); + /* Read the directory */ + while (direntry) { + if (direntry->d_name[0] == '.') { + direntry = readdir(idsdir); + continue; + } + len = strlen(direntry->d_name); + /* A tiny bit of sanity checking. We should probably do better */ + if (strncmp(&(direntry->d_name[len-4]), ".ids", 4) == 0) { + /* We need the full path name to open the file */ + strncpy(path_name, "/usr/share/xserver-xorg/pci/", 256); + strncat(path_name, direntry->d_name, (256 - strlen(path_name))); + fp = fopen(path_name, "r"); + if (fp == NULL) { + xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n", path_name); + goto end; + } + /* Read the file */ + while ((read = getline(&line, &len, fp)) != -1) { + xchomp(line); + if (isdigit(line[0])) { + strncpy(vendor_str, line, 4); + vendor_str[4] = '\0'; + vendor = (int)strtol(vendor_str, NULL, 16); + if ((strlen(&line[4])) == 0) { + chip_str[0] = '\0'; + chip = -1; + } else { + /* Handle trailing whitespace */ + if (isspace(line[4])) { + chip_str[0] = '\0'; + chip = -1; + } else { + /* Ok, it's a real ID */ + strncpy(chip_str, &line[4], 4); + chip_str[4] = '\0'; + chip = (int)strtol(chip_str, NULL, 16); + } + } + if (vendor == match_vendor && chip == match_chip ) { + i = 0; + while (matches[i]) { + i++; + } + matches[i] = (char*)xalloc(sizeof(char) * strlen(direntry->d_name) - 3); + if (!matches[i]) { + xf86Msg(X_ERROR, "Could not allocate space for the module name. Exiting.\n"); + goto end; + } + /* hack off the .ids suffix. This should guard + * against other problems, but it will end up + * taking off anything after the first '.' */ + for (j = 0; j < (strlen(direntry->d_name) - 3) ; j++) { + if (direntry->d_name[j] == '.') { + matches[i][j] = '\0'; + break; + } else { + matches[i][j] = direntry->d_name[j]; + } + } + xf86Msg(X_INFO, "Matched %s from file name %s in autoconfig\n", matches[i], direntry->d_name); + + } + } else { + /* TODO Handle driver overrides here */ + } + } + fclose(fp); + } + direntry = readdir(idsdir); + } + } + end: + xfree(line); + closedir(idsdir); +} +#endif /* __linux__ */ + +char* +chooseVideoDriver(void) +{ + struct pci_device * info = NULL; + struct pci_device_iterator *iter; + char *chosen_driver = NULL; + int i; + char *matches[20]; /* If we have more than 20 drivers we're in trouble */ + + for (i=0 ; i<20 ; i++) + matches[i] = NULL; + + /* Find the primary device, and get some information about it. */ + iter = pci_slot_match_iterator_create(NULL); + while ((info = pci_device_next(iter)) != NULL) { + if (xf86IsPrimaryPci(info)) { + break; + } + } + + pci_iterator_destroy(iter); + + if (!info) { + ErrorF("Primary device is not PCI\n"); + } + +#ifdef __linux__ + matchDriverFromFiles(matches, info->vendor_id, info->device_id); +#endif /* __linux__ */ + + /* TODO Handle multiple drivers claiming to support the same PCI ID */ + if (matches[0]) { + chosen_driver = matches[0]; + } else { + if (info != NULL) + chosen_driver = videoPtrToDriverName(info); + if (chosen_driver == NULL) { +#if defined __i386__ || defined __amd64__ || defined __hurd__ + chosen_driver = "vesa"; +#elif defined __alpha__ + chosen_driver = "vga"; +#elif defined __sparc__ + chosen_driver = "sunffb"; +#else + chosen_driver = "fbdev"; +#endif + } + } + + xf86Msg(X_DEFAULT, "Matched %s for the autoconfigured driver\n", chosen_driver); + + i = 0; + while (matches[i]) { + if (matches[i] != chosen_driver) { + xfree(matches[i]); + } + i++; + } + + return chosen_driver; +} diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 71e008069..35b62a244 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -77,7 +77,7 @@ extern DeviceAssocRec mouse_assoc; #include "picture.h" #endif -#if (defined(i386) || defined(__i386__)) && \ +#if (defined(__i386__)) && \ (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ defined(__NetBSD__) || defined(linux) || \ (defined(SVR4) && !defined(sun)) || defined(__GNU__)) @@ -792,6 +792,7 @@ typedef enum { FLAG_USE_DEFAULT_FONT_PATH, FLAG_AUTO_ADD_DEVICES, FLAG_AUTO_ENABLE_DEVICES, + FLAG_GLX_VISUALS, } FlagValues; static OptionInfoRec FlagOptions[] = { @@ -873,11 +874,13 @@ static OptionInfoRec FlagOptions[] = { {0}, TRUE }, { FLAG_AUTO_ENABLE_DEVICES, "AutoEnableDevices", OPTV_BOOLEAN, {0}, TRUE }, + { FLAG_GLX_VISUALS, "GlxVisuals", OPTV_STRING, + {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE }, }; -#if defined(i386) || defined(__i386__) +#ifdef __i386__ static Bool detectPC98(void) { @@ -904,6 +907,7 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) Pix24Flags pix24 = Pix24DontCare; Bool value; MessageType from; + const char *s; /* * Merge the ServerLayout and ServerFlags options. The former have @@ -1021,7 +1025,6 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value)) xf86Info.pmFlag = !value; { - const char *s; if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) { if (!xf86NameCmp(s,"flush")) { xf86Msg(X_CONFIG, "Flushing logfile enabled\n"); @@ -1040,8 +1043,6 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) #ifdef RENDER { - const char *s; - if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))){ int policy = PictureParseCmapPolicy (s); if (policy == PictureCmapPolicyInvalid) @@ -1055,7 +1056,6 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) } #endif { - const char *s; if ((s = xf86GetOptValString(FlagOptions, FLAG_HANDLE_SPECIAL_KEYS))) { if (!xf86NameCmp(s,"always")) { xf86Msg(X_CONFIG, "Always handling special keys in DDX\n"); @@ -1093,6 +1093,27 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) xf86Info.aiglxFrom = X_CONFIG; } +#ifdef GLXEXT + xf86Info.glxVisuals = XF86_GlxVisualsAll; + xf86Info.glxVisualsFrom = X_DEFAULT; + if ((s = xf86GetOptValString(FlagOptions, FLAG_GLX_VISUALS))) { + if (!xf86NameCmp(s, "minimal")) { + xf86Info.glxVisuals = XF86_GlxVisualsMinimal; + } else if (!xf86NameCmp(s, "typical")) { + xf86Info.glxVisuals = XF86_GlxVisualsTypical; + } else if (!xf86NameCmp(s, "all")) { + xf86Info.glxVisuals = XF86_GlxVisualsAll; + } else { + xf86Msg(X_WARNING,"Unknown HandleSpecialKeys option\n"); + } + } + + if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { + xf86Info.aiglx = value; + xf86Info.aiglxFrom = X_CONFIG; + } +#endif + xf86Info.allowEmptyInput = FALSE; if (xf86GetOptValBool(FlagOptions, FLAG_ALLOW_EMPTY_INPUT, &value)) xf86Info.allowEmptyInput = TRUE; @@ -1164,7 +1185,7 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) xf86Info.pixmap24 = Pix24DontCare; xf86Info.pix24From = X_DEFAULT; } -#if defined(i386) || defined(__i386__) +#ifdef __i386__ if (xf86GetOptValBool(FlagOptions, FLAG_PC98, &value)) { xf86Info.pc98 = value; if (value) { @@ -1813,11 +1834,6 @@ configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen) if (!servlayoutp) return FALSE; - if (conf_screen == NULL) { - xf86ConfigError("No Screen sections present\n"); - return FALSE; - } - /* * which screen section is the active one? * @@ -1905,6 +1921,12 @@ configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, XF86ConfAdaptorLinkPtr conf_adaptor; Bool defaultMonitor = FALSE; + if (!conf_screen) { + conf_screen = xnfcalloc(1, sizeof(XF86ConfScreenRec)); + conf_screen->scrn_identifier = "Default Screen Section"; + xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n"); + } + xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier, scrnum); /* @@ -1939,9 +1961,20 @@ configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, if (!configMonitor(screenp->monitor,conf_screen->scrn_monitor)) return FALSE; } + /* Configure the device. If there isn't one configured, attach to the + * first inactive one that we can configure. If there's none that work, + * set it to NULL so that the section can be autoconfigured later */ screenp->device = xnfcalloc(1, sizeof(GDevRec)); - configDevice(screenp->device,conf_screen->scrn_device, TRUE); - screenp->device->myScreenSection = screenp; + if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) { + conf_screen->scrn_device = xf86configptr->conf_device_lst; + xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n" + "\tUsing the first device section listed.\n", screenp->id); + } + if (configDevice(screenp->device,conf_screen->scrn_device, TRUE)) { + screenp->device->myScreenSection = screenp; + } else { + screenp->device = NULL; + } screenp->options = conf_screen->scrn_option_lst; /* @@ -2230,13 +2263,17 @@ configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active) { int i; + if (!conf_device) { + return FALSE; + } + if (active) xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n", conf_device->dev_identifier); else xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n", conf_device->dev_identifier); - + devicep->identifier = conf_device->dev_identifier; devicep->vendor = conf_device->dev_vendor; devicep->board = conf_device->dev_board; diff --git a/hw/xfree86/common/xf86Config.h b/hw/xfree86/common/xf86Config.h index b8b5fd42a..a174e463b 100644 --- a/hw/xfree86/common/xf86Config.h +++ b/hw/xfree86/common/xf86Config.h @@ -34,6 +34,8 @@ #define _xf86_config_h #include "xf86Optrec.h" +#include "xf86Parser.h" +#include "xf86str.h" #ifdef HAVE_PARSER_DECLS /* @@ -65,5 +67,8 @@ Bool xf86BuiltinInputDriver(const char *); ConfigStatus xf86HandleConfigFile(Bool); Bool xf86AutoConfig(void); +GDevPtr autoConfigDevice(GDevPtr preconf_device); +char* chooseVideoDriver(void); +int xchomp(char *line); #endif /* _xf86_config_h */ diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c index 91964c950..785815c6a 100644 --- a/hw/xfree86/common/xf86Events.c +++ b/hw/xfree86/common/xf86Events.c @@ -317,7 +317,7 @@ xf86ProcessActionEvent(ActionEvent action, void *arg) } break; #if !defined(__SOL8__) && !defined(sgi) && \ - (!defined(sun) || defined(i386)) && defined(VT_ACTIVATE) + (!defined(sun) || defined(__i386__)) && defined(VT_ACTIVATE) case ACTION_SWITCHSCREEN: if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) { int vtno = *((int *) arg); @@ -340,7 +340,7 @@ xf86ProcessActionEvent(ActionEvent action, void *arg) #else if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno + 1) < 0) #endif -#if defined (__SCO__) || (defined(sun) && defined (i386) && defined (SVR4)) || defined(__UNIXWARE__) +#if defined (__SCO__) || (defined(sun) && defined (__i386__) && defined (SVR4)) || defined(__UNIXWARE__) if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0) < 0) #else if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) < 0) diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c index 7dc45b75d..b3969b102 100644 --- a/hw/xfree86/common/xf86Globals.c +++ b/hw/xfree86/common/xf86Globals.c @@ -124,7 +124,7 @@ xf86InfoRec xf86Info = { PCIOsConfig, /* pciFlags */ Pix24DontCare, /* pixmap24 */ X_DEFAULT, /* pix24From */ -#if defined(i386) || defined(__i386__) +#ifdef __i386__ FALSE, /* pc98 */ #endif TRUE, /* pmFlag */ diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c index b6fc6b629..1ef79730c 100644 --- a/hw/xfree86/common/xf86Helper.c +++ b/hw/xfree86/common/xf86Helper.c @@ -2341,7 +2341,7 @@ xf86GetAllowMouseOpenFail() _X_EXPORT Bool xf86IsPc98() { -#if defined(i386) || defined(__i386__) +#ifdef __i386__ return xf86Info.pc98; #else return FALSE; diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c index 2f1651cc7..bf577e6ad 100644 --- a/hw/xfree86/common/xf86Init.c +++ b/hw/xfree86/common/xf86Init.c @@ -572,6 +572,16 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) } /* Load all driver modules specified in the config file */ + /* If there aren't any specified in the config file, autoconfig them */ + /* FIXME: Does not handle multiple active screen sections, but I'm not + * sure if we really want to handle that case*/ + GDevPtr configured_device = xf86ConfigLayout.screens->screen->device; + if ((!configured_device) || (!configured_device->driver)) { + if (!autoConfigDevice(configured_device)) { + xf86Msg(X_ERROR, "Automatic driver configuration failed\n"); + return ; + } + } if ((modulelist = xf86DriverlistFromConfig())) { xf86LoadModules(modulelist, NULL); xfree(modulelist); diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h index 09ebb0717..92a6305a0 100644 --- a/hw/xfree86/common/xf86Privstr.h +++ b/hw/xfree86/common/xf86Privstr.h @@ -60,6 +60,12 @@ typedef enum { SKAlways } SpecialKeysInDDX; +typedef enum { + XF86_GlxVisualsMinimal, + XF86_GlxVisualsTypical, + XF86_GlxVisualsAll, +} XF86_GlxVisuals; + /* * xf86InfoRec contains global parameters which the video drivers never * need to access. Global parameters which the video drivers do need @@ -109,7 +115,7 @@ typedef struct { PciProbeType pciFlags; Pix24Flags pixmap24; MessageType pix24From; -#if defined(i386) || defined(__i386__) +#ifdef __i386__ Bool pc98; #endif Bool pmFlag; @@ -120,6 +126,9 @@ typedef struct { MessageType randRFrom; Bool aiglx; MessageType aiglxFrom; + XF86_GlxVisuals glxVisuals; + MessageType glxVisualsFrom; + Bool useDefaultFontPath; MessageType useDefaultFontPathFrom; Bool ignoreABI; diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h index 0365ddd62..af98b4fd5 100644 --- a/hw/xfree86/common/xf86str.h +++ b/hw/xfree86/common/xf86str.h @@ -142,6 +142,7 @@ typedef enum { # define M_T_DEFAULT 0x10 /* (VESA) default modes */ # define M_T_USERDEF 0x20 /* One of the modes from the config file */ # define M_T_DRIVER 0x40 /* Supplied by the driver (EDID, etc) */ +# define M_T_USERPREF 0x80 /* mode preferred by the user config */ /* Video mode */ typedef struct _DisplayModeRec { diff --git a/hw/xfree86/dixmods/glxmodule.c b/hw/xfree86/dixmods/glxmodule.c index 5384f434b..847f0d4a2 100644 --- a/hw/xfree86/dixmods/glxmodule.c +++ b/hw/xfree86/dixmods/glxmodule.c @@ -41,18 +41,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "colormap.h" #include "micmap.h" #include "globals.h" - -typedef struct __GLXscreen __GLXscreen; -typedef struct __GLXprovider __GLXprovider; -struct __GLXprovider { - __GLXscreen *(*screenProbe)(ScreenPtr pScreen); - const char *name; - __GLXprovider *next; -}; - -extern void GlxPushProvider(__GLXprovider *provider); -extern void GlxExtensionInit(void); -extern void GlxWrapInitVisuals(miInitVisualsProcPtr *); +#include "glxserver.h" static MODULESETUPPROTO(glxSetup); @@ -114,7 +103,6 @@ static __GLXprovider __glXMesaProxyProvider = { NULL }; - static pointer glxSetup(pointer module, pointer opts, int *errmaj, int *errmin) { @@ -139,12 +127,22 @@ glxSetup(pointer module, pointer opts, int *errmaj, int *errmin) GlxPushProvider(provider); } - LoadExtension(&GLXExt, FALSE); - /* Wrap the init visuals routine in micmap.c */ - GlxWrapInitVisuals(&miInitVisualsProc); - /* Make sure this gets wrapped each time InitVisualWrap is called */ - miHookInitVisuals(NULL, GlxWrapInitVisuals); + switch (xf86Info.glxVisuals) { + case XF86_GlxVisualsMinimal: + GlxSetVisualConfig(GLX_MINIMAL_VISUALS); + xf86Msg(xf86Info.aiglxFrom, "Exporting only minimal set of GLX visuals\n"); + break; + case XF86_GlxVisualsTypical: + GlxSetVisualConfig(GLX_TYPICAL_VISUALS); + xf86Msg(xf86Info.aiglxFrom, "Exporting typical set of GLX visuals\n"); + break; + case XF86_GlxVisualsAll: + GlxSetVisualConfig(GLX_ALL_VISUALS); + xf86Msg(xf86Info.aiglxFrom, "Exporting all GLX visuals\n"); + break; + } + + LoadExtension(&GLXExt, FALSE); - bail: return module; } diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre index 54d8eaa87..4064ef6d8 100644 --- a/hw/xfree86/doc/man/xorg.conf.man.pre +++ b/hw/xfree86/doc/man/xorg.conf.man.pre @@ -700,6 +700,17 @@ the builtin handler will be used. .BI "Option \*qAIGLX\*q \*q" boolean \*q enable or disable AIGLX. AIGLX is enabled by default. .TP 7 +.BI "Option \*qGlxVisuals\*q \*q" string \*q +This option controls how many GLX visuals the GLX modules sets up. +The default value is +.BR "typical" , +which will setup up a typical subset of +the GLXFBConfigs provided by the driver as GLX visuals. Other options are +.BR "minimal" , +which will set up the minimal set allowed by the GLX specification and +.BR "all" +which will setup GLX visuals for all GLXFBConfigs. +.TP 7 .BI "Option \*qUseDefaultFontPath\*q \*q" boolean \*q Include the default font path even if other paths are specified in xorg.conf. If enabled, other font paths are included as well. Enabled by diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c index d1bbfcd14..2408357e5 100644 --- a/hw/xfree86/dri/dri.c +++ b/hw/xfree86/dri/dri.c @@ -67,7 +67,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dristruct.h" #include "xf86.h" #include "xf86drm.h" -#include "glxserver.h" #include "mi.h" #include "mipointer.h" #include "xf86_OSproc.h" @@ -972,24 +971,8 @@ static Bool DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) { DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - __GLXscreen *pGLXScreen = __glXgetActiveScreen(pScreen->myNum); - __GLcontextModes *modes = pGLXScreen->modes; - void **pVisualConfigPriv = pGLXScreen->pVisualPriv; DRIContextPrivPtr pDRIContextPriv; void *contextStore; - VisualPtr visual; - int visNum; - - visual = pScreen->visuals; - - /* Find the X visual that corresponds the the first GLX visual */ - for (visNum = 0; - visNum < pScreen->numVisuals; - visNum++, visual++) { - if (modes->visualID == visual->vid) - break; - } - if (visNum == pScreen->numVisuals) return FALSE; if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, @@ -999,9 +982,9 @@ DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) contextStore = DRIGetContextStore(pDRIContextPriv); if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { - if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, visual, + if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL, pDRIPriv->pSAREA->dummy_context, - *pVisualConfigPriv, + NULL, (DRIContextType)(long)contextStore)) { DRIDestroyContextPriv(pDRIContextPriv); return FALSE; @@ -1036,9 +1019,6 @@ DRICreateContext(ScreenPtr pScreen, VisualPtr visual, XID context, drm_context_t * pHWContext) { DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - __GLXscreen *pGLXScreen = __glXgetActiveScreen(pScreen->myNum); - __GLcontextModes *modes = pGLXScreen->modes; - void **pVisualConfigPriv = pGLXScreen->pVisualPriv; DRIContextPrivPtr pDRIContextPriv; void *contextStore; @@ -1050,26 +1030,14 @@ DRICreateContext(ScreenPtr pScreen, VisualPtr visual, } } - /* Find the GLX visual associated with the one requested */ - for (modes = pGLXScreen->modes; modes != NULL; modes = modes->next) { - if (modes->visualID == visual->vid) - break; - pVisualConfigPriv++; - } - - if (modes == NULL) { - /* No matching GLX visual found */ - return FALSE; - } - if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { return FALSE; } contextStore = DRIGetContextStore(pDRIContextPriv); if (pDRIPriv->pDriverInfo->CreateContext) { - if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, visual, - *pHWContext, *pVisualConfigPriv, + if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, NULL, + *pHWContext, NULL, (DRIContextType)(long)contextStore))) { DRIDestroyContextPriv(pDRIContextPriv); return FALSE; diff --git a/hw/xfree86/dri/xf86dri.c b/hw/xfree86/dri/xf86dri.c index fdf0e9983..130afdfa4 100644 --- a/hw/xfree86/dri/xf86dri.c +++ b/hw/xfree86/dri/xf86dri.c @@ -337,19 +337,9 @@ ProcXF86DRICreateContext( rep.sequenceNumber = client->sequence; pScreen = screenInfo.screens[stuff->screen]; - visual = pScreen->visuals; - - /* Find the requested X visual */ - for (i = 0; i < pScreen->numVisuals; i++, visual++) - if (visual->vid == stuff->visual) - break; - if (i == pScreen->numVisuals) { - /* No visual found */ - return BadValue; - } if (!DRICreateContext( pScreen, - visual, + NULL, stuff->context, (drm_context_t *)&rep.hHWContext)) { return BadValue; diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 064ff1689..0a48d5bd3 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -711,7 +711,8 @@ xf86DefaultMode (xf86OutputPtr output, int width, int height) for (mode = output->probed_modes; mode; mode = mode->next) { int dpi; - int preferred = (mode->type & M_T_PREFERRED) != 0; + int preferred = (((mode->type & M_T_PREFERRED) != 0) + + ((mode->type & M_T_USERPREF) != 0)); int diff; if (xf86ModeWidth (mode, output->initial_rotation) > width || @@ -1415,7 +1416,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) mode->prev = NULL; output->probed_modes = mode; } - mode->type |= M_T_PREFERRED; + mode->type |= (M_T_PREFERRED|M_T_USERPREF); } else mode->type &= ~M_T_PREFERRED; @@ -1532,6 +1533,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o, c; DisplayModePtr target_mode = NULL; + int target_preferred = 0; Rotation target_rotation = RR_Rotate_0; xf86CrtcPtr *crtcs; DisplayModePtr *modes; @@ -1572,43 +1574,34 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) } /* - * Let outputs with preferred modes drive screen size + * User preferred > preferred > other modes */ for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = config->output[o]; + xf86OutputPtr output = config->output[o]; + DisplayModePtr default_mode; + int default_preferred; - if (enabled[o] && - xf86OutputHasPreferredMode (output, width, height)) + if (!enabled[o]) + continue; + default_mode = xf86DefaultMode (output, width, height); + if (!default_mode) + continue; + default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) + + ((default_mode->type & M_T_USERPREF) != 0)); + if (default_preferred > target_preferred || !target_mode) { - target_mode = xf86DefaultMode (output, width, height); + target_mode = default_mode; + target_preferred = default_preferred; target_rotation = output->initial_rotation; - if (target_mode) - { - modes[o] = target_mode; - config->compat_output = o; - break; - } - } - } - if (!target_mode) - { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - if (enabled[o]) - { - target_mode = xf86DefaultMode (output, width, height); - target_rotation = output->initial_rotation; - if (target_mode) - { - modes[o] = target_mode; - config->compat_output = o; - break; - } - } + config->compat_output = o; } } + if (target_mode) + modes[config->compat_output] = target_mode; + /* + * Fill in other output modes + */ for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; @@ -2134,8 +2127,12 @@ _X_EXPORT xf86MonPtr xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) { ScrnInfoPtr scrn = output->scrn; + xf86MonPtr mon; - return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus); + mon = xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus); + xf86DDCApplyQuirks (scrn->scrnIndex, pDDCBus); + + return mon; } static char *_xf86ConnectorNames[] = { "None", "VGA", "DVI-I", "DVI-D", diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h index 9693e12bb..4c843cd83 100644 --- a/hw/xfree86/modes/xf86Crtc.h +++ b/hw/xfree86/modes/xf86Crtc.h @@ -39,6 +39,9 @@ #ifndef M_T_DRIVER #define M_T_DRIVER 0x40 #endif +#ifndef M_T_USERPREF +#define M_T_USERPREF 0x80 +#endif #ifndef HARDWARE_CURSOR_ARGB #define HARDWARE_CURSOR_ARGB 0x00004000 #endif diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c index 8b5e69d9a..2f26a6450 100644 --- a/hw/xfree86/modes/xf86EdidModes.c +++ b/hw/xfree86/modes/xf86EdidModes.c @@ -54,6 +54,18 @@ typedef enum { DDC_QUIRK_PREFER_LARGE_60 = 1 << 0, /* 135MHz clock is too high, drop a bit */ DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1, + /* Prefer the largest mode at 75 Hz */ + DDC_QUIRK_PREFER_LARGE_75 = 1 << 2, + /* Convert detailed timing's horizontal from units of cm to mm */ + DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3, + /* Convert detailed timing's vertical from units of cm to mm */ + DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4, + /* Detailed timing descriptors have bogus size values, so just take the + * maximum size and use that. + */ + DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5, + /* Monitor forgot to set the first detailed is preferred bit. */ + DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6, } ddc_quirk_t; static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) @@ -81,6 +93,52 @@ static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) return FALSE; } +static Bool quirk_prefer_large_75 (int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #11603: Funai Electronics PM36B */ + if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && + DDC->vendor.prod_id == 13600) + return TRUE; + + return FALSE; +} + +static Bool quirk_detailed_h_in_cm (int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #10304: "LGPhilipsLCD LP154W01-A5" */ + /* Bug #12784: "LGPhilipsLCD LP154W01-TLA2" */ + if (memcmp (DDC->vendor.name, "LPL", 4) == 0 && + DDC->vendor.prod_id == 0) + return TRUE; + + /* Bug #11603: Funai Electronics PM36B */ + if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && + DDC->vendor.prod_id == 13600) + return TRUE; + + return FALSE; +} + +static Bool quirk_detailed_v_in_cm (int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #11603: Funai Electronics PM36B */ + if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && + DDC->vendor.prod_id == 13600) + return TRUE; + + return FALSE; +} + +static Bool quirk_detailed_use_maximum_size (int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #10304: LGPhilipsLCD LP154W01-A5 */ + if (memcmp (DDC->vendor.name, "LPL", 4) == 0 && + DDC->vendor.prod_id == 0) + return TRUE; + + return FALSE; +} + static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC) { /* Envision Peripherals, Inc. EN-7100e. See bug #9550. */ @@ -91,6 +149,16 @@ static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC) return FALSE; } +static Bool quirk_first_detailed_preferred (int scrnIndex, xf86MonPtr DDC) +{ + /* Philips 107p5 CRT. Reported on xorg@ with pastebin. */ + if (memcmp (DDC->vendor.name, "PHL", 4) == 0 && + DDC->vendor.prod_id == 57364) + return TRUE; + + return FALSE; +} + typedef struct { Bool (*detect) (int scrnIndex, xf86MonPtr DDC); ddc_quirk_t quirk; @@ -106,6 +174,26 @@ static const ddc_quirk_map_t ddc_quirks[] = { quirk_135_clock_too_high, DDC_QUIRK_135_CLOCK_TOO_HIGH, "Recommended 135MHz pixel clock is too high" }, + { + quirk_prefer_large_75, DDC_QUIRK_PREFER_LARGE_75, + "Detailed timing is not preferred, use largest mode at 75Hz" + }, + { + quirk_detailed_h_in_cm, DDC_QUIRK_DETAILED_H_IN_CM, + "Detailed timings give horizontal size in cm." + }, + { + quirk_detailed_v_in_cm, DDC_QUIRK_DETAILED_V_IN_CM, + "Detailed timings give vertical size in cm." + }, + { + quirk_detailed_use_maximum_size, DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE, + "Detailed timings give sizes in cm." + }, + { + quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED, + "First detailed timing was not marked as preferred." + }, { NULL, DDC_QUIRK_NONE, "No known quirks" @@ -185,7 +273,7 @@ DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing, */ static DisplayModePtr DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing, - int preferred, ddc_quirk_t quirks) + Bool preferred, ddc_quirk_t quirks) { DisplayModePtr Mode; @@ -303,27 +391,116 @@ DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes) } } +static ddc_quirk_t +xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose) +{ + ddc_quirk_t quirks; + int i; + + quirks = DDC_QUIRK_NONE; + for (i = 0; ddc_quirks[i].detect; i++) { + if (ddc_quirks[i].detect (scrnIndex, DDC)) { + if (verbose) { + xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n", + ddc_quirks[i].description); + } + quirks |= ddc_quirks[i].quirk; + } + } + + return quirks; +} + +/** + * Applies monitor-specific quirks to the decoded EDID information. + * + * Note that some quirks applying to the mode list are still implemented in + * xf86DDCGetModes. + */ +void +xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC) +{ + ddc_quirk_t quirks = xf86DDCDetectQuirks (scrnIndex, DDC, FALSE); + int i; + + for (i = 0; i < DET_TIMINGS; i++) { + struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; + + if (det_mon->type != DT) + continue; + + if (quirks & DDC_QUIRK_DETAILED_H_IN_CM) + det_mon->section.d_timings.h_size *= 10; + + if (quirks & DDC_QUIRK_DETAILED_V_IN_CM) + det_mon->section.d_timings.v_size *= 10; + + if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { + det_mon->section.d_timings.h_size = 10 * DDC->features.hsize; + det_mon->section.d_timings.v_size = 10 * DDC->features.vsize; + } + } +} + +/** + * Walks the modes list, finding the mode with the largest area which is + * closest to the target refresh rate, and marks it as the only preferred mode. +*/ +static void +xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes, + float target_refresh) +{ + DisplayModePtr mode, best = modes; + + for (mode = modes; mode; mode = mode->next) + { + mode->type &= ~M_T_PREFERRED; + + if (mode == best) continue; + + if (mode->HDisplay * mode->VDisplay > + best->HDisplay * best->VDisplay) + { + best = mode; + continue; + } + if (mode->HDisplay * mode->VDisplay == + best->HDisplay * best->VDisplay) + { + double mode_refresh = xf86ModeVRefresh (mode); + double best_refresh = xf86ModeVRefresh (best); + double mode_dist = fabs(mode_refresh - target_refresh); + double best_dist = fabs(best_refresh - target_refresh); + + if (mode_dist < best_dist) + { + best = mode; + continue; + } + } + } + if (best) + best->type |= M_T_PREFERRED; +} + _X_EXPORT DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) { - int preferred, i; + int i; DisplayModePtr Modes = NULL, Mode; ddc_quirk_t quirks; + Bool preferred; xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n", DDC->vendor.name, DDC->vendor.prod_id); - quirks = DDC_QUIRK_NONE; - for (i = 0; ddc_quirks[i].detect; i++) - if (ddc_quirks[i].detect (scrnIndex, DDC)) - { - xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n", - ddc_quirks[i].description); - quirks |= ddc_quirks[i].quirk; - } - + + quirks = xf86DDCDetectQuirks(scrnIndex, DDC, TRUE); + preferred = PREFERRED_TIMING_MODE(DDC->features.msc); - if (quirks & DDC_QUIRK_PREFER_LARGE_60) - preferred = 0; + if (quirks & DDC_QUIRK_FIRST_DETAILED_PREFERRED) + preferred = TRUE; + if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75)) + preferred = FALSE; for (i = 0; i < DET_TIMINGS; i++) { struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; @@ -334,7 +511,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) &det_mon->section.d_timings, preferred, quirks); - preferred = 0; + preferred = FALSE; Modes = xf86ModesAdd(Modes, Mode); break; case DS_STD_TIMINGS: @@ -357,32 +534,11 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) Modes = xf86ModesAdd(Modes, Mode); if (quirks & DDC_QUIRK_PREFER_LARGE_60) - { - DisplayModePtr best = Modes; - for (Mode = Modes; Mode; Mode = Mode->next) - { - if (Mode == best) continue; - if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay) - { - best = Mode; - continue; - } - if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay) - { - double mode_refresh = xf86ModeVRefresh (Mode); - double best_refresh = xf86ModeVRefresh (best); - double mode_dist = fabs(mode_refresh - 60.0); - double best_dist = fabs(best_refresh - 60.0); - if (mode_dist < best_dist) - { - best = Mode; - continue; - } - } - } - if (best) - best->type |= M_T_PREFERRED; - } + xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60); + + if (quirks & DDC_QUIRK_PREFER_LARGE_75) + xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75); + return Modes; } diff --git a/hw/xfree86/modes/xf86Modes.c b/hw/xfree86/modes/xf86Modes.c index f49c2921c..99817898a 100644 --- a/hw/xfree86/modes/xf86Modes.c +++ b/hw/xfree86/modes/xf86Modes.c @@ -389,8 +389,8 @@ xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, bad = TRUE; for (i = 0; i < mon->nHsync; i++) { - if (xf86ModeHSync(mode) >= mon->hsync[i].lo && - xf86ModeHSync(mode) <= mon->hsync[i].hi) + if (xf86ModeHSync(mode) >= mon->hsync[i].lo * (1-SYNC_TOLERANCE) && + xf86ModeHSync(mode) <= mon->hsync[i].hi * (1+SYNC_TOLERANCE)) { bad = FALSE; } @@ -400,8 +400,8 @@ xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, bad = TRUE; for (i = 0; i < mon->nVrefresh; i++) { - if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo && - xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi) + if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo * (1-SYNC_TOLERANCE) && + xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi * (1+SYNC_TOLERANCE)) { bad = FALSE; } @@ -434,7 +434,8 @@ xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, for (mode = modeList; mode != NULL; mode = mode->next) { Bool good = FALSE; for (i = 0; i < n_ranges; i++) { - if (mode->Clock >= min[i] && mode->Clock <= max[i]) { + if (mode->Clock >= min[i] * (1-SYNC_TOLERANCE) && + mode->Clock <= max[i] * (1+SYNC_TOLERANCE)) { good = TRUE; break; } diff --git a/hw/xfree86/modes/xf86Modes.h b/hw/xfree86/modes/xf86Modes.h index 2bd4edeba..3722d25a0 100644 --- a/hw/xfree86/modes/xf86Modes.h +++ b/hw/xfree86/modes/xf86Modes.h @@ -95,4 +95,7 @@ xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor); DisplayModePtr xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed); +void +xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC); + #endif /* _XF86MODES_H_ */ diff --git a/hw/xfree86/os-support/assyntax.h b/hw/xfree86/os-support/assyntax.h index 718312cf0..d3e96e5fd 100644 --- a/hw/xfree86/os-support/assyntax.h +++ b/hw/xfree86/os-support/assyntax.h @@ -91,7 +91,7 @@ #define GNU_ASSEMBLER #endif -#if (defined(__STDC__) && !defined(UNIXCPP)) || (defined (sun) && defined (i386) && defined (SVR4) && defined (__STDC__) && !defined (__GNUC__)) +#if (defined(__STDC__) && !defined(UNIXCPP)) || (defined (sun) && defined (__i386__) && defined (SVR4) && defined (__STDC__) && !defined (__GNUC__)) #define CONCAT(x, y) x ## y #else #define CONCAT(x, y) x/**/y diff --git a/hw/xfree86/os-support/bus/Pci.h b/hw/xfree86/os-support/bus/Pci.h index bb93260d1..6bd0eb7fc 100644 --- a/hw/xfree86/os-support/bus/Pci.h +++ b/hw/xfree86/os-support/bus/Pci.h @@ -210,7 +210,7 @@ # define ARCH_PCI_INIT ia64linuxPciInit # endif # define XF86SCANPCI_WRAPPER ia64ScanPCIWrapper -#elif defined(__i386__) || defined(i386) +#elif defined(__i386__) # if defined(linux) # define ARCH_PCI_INIT linuxPciInit # else diff --git a/hw/xfree86/os-support/linux/lnx_acpi.c b/hw/xfree86/os-support/linux/lnx_acpi.c index 024e6ef09..bb975cc5d 100644 --- a/hw/xfree86/os-support/linux/lnx_acpi.c +++ b/hw/xfree86/os-support/linux/lnx_acpi.c @@ -23,11 +23,11 @@ #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83 #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84 -#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x82 -#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x83 -#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x84 -#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x85 -#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x86 +#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85 +#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 +#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 +#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 +#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 #define ACPI_VIDEO_HEAD_INVALID (~0u - 1) #define ACPI_VIDEO_HEAD_END (~0u) @@ -69,9 +69,11 @@ lnxACPIGetEventFromOs(int fd, pmEvent *events, int num) TimerSet(NULL, 0, ACPI_REOPEN_DELAY, lnxACPIReopen, NULL); return 0; } + /* FIXME: this only processes the first read ACPI event & might break + * with interrupted reads. */ /* Check that we have a video event */ - if (strstr(ev, "video") == ev) { + if (!strncmp(ev, "video", 5)) { char *video = NULL; char *GFX = NULL; char *notify = NULL; @@ -97,26 +99,19 @@ lnxACPIGetEventFromOs(int fd, pmEvent *events, int num) ErrorF("data: 0x%lx\n",data_l); #endif - /* We currently don't differentiate between any event */ + /* Differentiate between events */ switch (notify_l) { case ACPI_VIDEO_NOTIFY_SWITCH: - break; - case ACPI_VIDEO_NOTIFY_PROBE: - break; case ACPI_VIDEO_NOTIFY_CYCLE: - break; case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: - break; case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: - break; + events[0] = XF86_APM_CAPABILITY_CHANGED; + return 1; + case ACPI_VIDEO_NOTIFY_PROBE: + return 0; default: - break; + return 0; } - - /* Deal with all ACPI events as a capability change */ - events[0] = XF86_APM_CAPABILITY_CHANGED; - - return 1; } return 0; diff --git a/hw/xfree86/os-support/solaris/sun_bios.c b/hw/xfree86/os-support/solaris/sun_bios.c index 6a132f5a3..1223dcd68 100644 --- a/hw/xfree86/os-support/solaris/sun_bios.c +++ b/hw/xfree86/os-support/solaris/sun_bios.c @@ -26,7 +26,7 @@ #include #endif -#ifdef i386 +#ifdef __i386__ #define _NEED_SYSI86 #endif #include "xf86.h" @@ -66,7 +66,7 @@ xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf, Offset += Base & (psize - 1); Base &= ~(psize - 1); mlen = (Offset + Len + psize - 1) & ~(psize - 1); -#if defined(i386) && !defined(__SOL8__) +#if defined(__i386__) && !defined(__SOL8__) if (Base >= 0xA0000 && Base + mlen < 0xFFFFF && xf86Info.vtno >= 0) sprintf(solx86_vtname, "/dev/vt%02d", xf86Info.vtno); else diff --git a/hw/xfree86/os-support/solaris/sun_init.c b/hw/xfree86/os-support/solaris/sun_init.c index 08d35c59c..c7fac524f 100644 --- a/hw/xfree86/os-support/solaris/sun_init.c +++ b/hw/xfree86/os-support/solaris/sun_init.c @@ -29,7 +29,7 @@ #include "xf86.h" #include "xf86Priv.h" #include "xf86_OSlib.h" -#if defined(__i386) || defined(__x86) +#if defined(__i386__) || defined(__x86) # include #endif @@ -40,7 +40,7 @@ static int VTnum = -1; static int xf86StartVT = -1; #endif -#if defined(__SOL8__) || !defined(__i386) +#if defined(__SOL8__) || !defined(__i386__) static char fb_dev[PATH_MAX] = "/dev/fb"; #else static char fb_dev[PATH_MAX] = "/dev/console"; @@ -209,11 +209,11 @@ xf86CloseConsole(void) #ifdef HAS_USL_VTS struct vt_mode VT; #endif -#if defined(__SOL8__) || !defined(i386) +#if defined(__SOL8__) || !defined(__i386__) int tmp; #endif -#if !defined(i386) && !defined(__x86) +#if !defined(__i386__) && !defined(__x86) if (!xf86DoProbe && !xf86DoConfigure) { int fd; @@ -332,7 +332,7 @@ xf86ProcessArgument(int argc, char **argv, int i) #endif /* HAS_USL_VTS */ -#if defined(__SOL8__) || !defined(i386) +#if defined(__SOL8__) || !defined(__i386__) if ((i + 1) < argc) { if (!strcmp(argv[i], "-dev")) { @@ -352,7 +352,7 @@ void xf86UseMsg() #ifdef HAS_USL_VTS ErrorF("vtXX Use the specified VT number\n"); #endif -#if defined(__SOL8__) || !defined(i386) +#if defined(__SOL8__) || !defined(__i386__) ErrorF("-dev Framebuffer device\n"); #endif ErrorF("-keeptty Don't detach controlling tty\n"); diff --git a/hw/xfree86/os-support/solaris/sun_vid.c b/hw/xfree86/os-support/solaris/sun_vid.c index 4f2ab871f..494b2cfbf 100644 --- a/hw/xfree86/os-support/solaris/sun_vid.c +++ b/hw/xfree86/os-support/solaris/sun_vid.c @@ -28,7 +28,7 @@ #include /* get __x86 definition if not set by compiler */ -#if defined(i386) || defined(__x86) +#if defined(__i386__) || defined(__x86) #define _NEED_SYSI86 #endif #include "xf86.h" @@ -108,7 +108,7 @@ xf86MapVidMem(int ScreenNum, int Flags, unsigned long Base, unsigned long Size) * TSI - 2001.09 - SPARC changes */ -#if defined(i386) && !defined(__SOL8__) +#if defined(__i386__) && !defined(__SOL8__) if(Base < 0xFFFFF) sprintf(vtname, "/dev/vt%02d", xf86Info.vtno); else @@ -148,14 +148,14 @@ xf86UnMapVidMem(int ScreenNum, pointer Base, unsigned long Size) /* I/O Permissions section */ /***************************************************************************/ -#if defined(i386) || defined(__x86) +#if defined(__i386__) || defined(__x86) static Bool ExtendedEnabled = FALSE; #endif _X_EXPORT Bool xf86EnableIO(void) { -#if defined(i386) || defined(__x86) +#if defined(__i386__) || defined(__x86) if (ExtendedEnabled) return TRUE; @@ -171,7 +171,7 @@ xf86EnableIO(void) _X_EXPORT void xf86DisableIO(void) { -#if defined(i386) || defined(__x86) +#if defined(__i386__) || defined(__x86) if(!ExtendedEnabled) return; @@ -188,7 +188,7 @@ xf86DisableIO(void) _X_EXPORT Bool xf86DisableInterrupts(void) { -#if defined(i386) || defined(__x86) +#if defined(__i386__) || defined(__x86) if (!ExtendedEnabled && (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0)) return FALSE; @@ -207,7 +207,7 @@ _X_EXPORT Bool xf86DisableInterrupts(void) _X_EXPORT void xf86EnableInterrupts(void) { -#if defined(i386) || defined(__x86) +#if defined(__i386__) || defined(__x86) if (!ExtendedEnabled && (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0)) return; diff --git a/hw/xfree86/os-support/sysv/sysv_video.c b/hw/xfree86/os-support/sysv/sysv_video.c index 5811947bd..9972bcaa4 100644 --- a/hw/xfree86/os-support/sysv/sysv_video.c +++ b/hw/xfree86/os-support/sysv/sysv_video.c @@ -234,7 +234,7 @@ unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) return; } -#if defined(SVR4) && defined(i386) && !defined(sun) +#if defined(SVR4) && defined(__i386__) && !defined(sun) /* * For some SVR4 versions, a 32-bit read is done for the first location * in each page when the page is first mapped. If this is done while @@ -270,7 +270,7 @@ xf86OSInitVidMem(VidMemInfoPtr pVidMem) pVidMem->linearSupported = linearVidMem(); pVidMem->mapMem = mapVidMem; pVidMem->unmapMem = unmapVidMem; -#if defined(SVR4) && defined(i386) && !defined(sun) +#if defined(SVR4) && defined(__i386__) && !defined(sun) pVidMem->readSideEffects = readSideEffects; #endif pVidMem->initialised = TRUE; diff --git a/hw/xfree86/os-support/xf86_OSlib.h b/hw/xfree86/os-support/xf86_OSlib.h index fcc79be38..662dbaace 100644 --- a/hw/xfree86/os-support/xf86_OSlib.h +++ b/hw/xfree86/os-support/xf86_OSlib.h @@ -100,7 +100,7 @@ typedef signed long xf86ssize_t; /**************************************************************************/ #if (defined(SYSV) || defined(SVR4)) && \ !defined(DGUX) && !defined(sgi) && \ - (defined(sun) || defined(i386)) + (defined(sun) || defined(__i386__)) # ifdef SCO325 # ifndef _SVID3 # define _SVID3 @@ -140,7 +140,7 @@ typedef signed long xf86ssize_t; # endif /* SVR4 && !sun */ /* V86SC_IOPL was moved to on Solaris 7 and later */ # if defined(sun) && defined (SVR4) /* Solaris? */ -# if defined(i386) || defined(__x86) /* on x86 or x64? */ +# if defined(__i386__) || defined(__x86) /* on x86 or x64? */ # if !defined(V86SC_IOPL) /* Solaris 7 or later? */ # include /* Nope */ # endif @@ -148,7 +148,7 @@ typedef signed long xf86ssize_t; # else # include /* Not solaris */ # endif /* sun && i386 && SVR4 */ -# if defined(sun) && (defined (i386) || defined(__x86)) && defined (SVR4) +# if defined(sun) && (defined (__i386__) || defined(__x86)) && defined (SVR4) # include # endif # endif /* _NEED_SYSI86 */ @@ -224,15 +224,11 @@ typedef signed long xf86ssize_t; # define POSIX_TTY # endif -# if defined(sun) && defined (i386) && defined (SVR4) && !defined(__SOL8__) +# if defined(sun) && defined (__i386__) && defined (SVR4) && !defined(__SOL8__) # define USE_VT_SYSREQ # define VT_SYSREQ_DEFAULT TRUE # endif -# if defined(ATT) && !defined(i386) -# define i386 /* not defined in ANSI C mode */ -# endif /* ATT && !i386 */ - # ifdef SYSV # if !defined(ISC) || defined(ISC202) || defined(ISC22) # define NEED_STRERROR diff --git a/hw/xfree86/parser/Configint.h b/hw/xfree86/parser/Configint.h index c20c1958c..4d5fbcfab 100644 --- a/hw/xfree86/parser/Configint.h +++ b/hw/xfree86/parser/Configint.h @@ -186,8 +186,6 @@ else\ "The Inactive keyword must be followed by a Device name in quotes." #define UNDEFINED_SCREEN_MSG \ "Undefined Screen \"%s\" referenced by ServerLayout \"%s\"." -#define UNDEFINED_MONITOR_MSG \ -"Undefined Monitor \"%s\" referenced by Screen \"%s\"." #define UNDEFINED_MODES_MSG \ "Undefined Modes Section \"%s\" referenced by Monitor \"%s\"." #define UNDEFINED_DEVICE_MSG \ @@ -204,8 +202,6 @@ else\ "This section must have an Identifier line." #define ONLY_ONE_MSG \ "This section must have only one of either %s line." -#define UNDEFINED_DRIVER_MSG \ -"Device section \"%s\" must have a Driver line." #define UNDEFINED_INPUTDRIVER_MSG \ "InputDevice section \"%s\" must have a Driver line." #define INVALID_GAMMA_MSG \ diff --git a/hw/xfree86/parser/Device.c b/hw/xfree86/parser/Device.c index 6ad5601b5..216789fc1 100644 --- a/hw/xfree86/parser/Device.c +++ b/hw/xfree86/parser/Device.c @@ -357,26 +357,6 @@ xf86freeDeviceList (XF86ConfDevicePtr ptr) } } -int -xf86validateDevice (XF86ConfigPtr p) -{ - XF86ConfDevicePtr device = p->conf_device_lst; - - if (!device) { - xf86validationError ("At least one Device section is required."); - return (FALSE); - } - - while (device) { - if (!device->dev_driver) { - xf86validationError (UNDEFINED_DRIVER_MSG, device->dev_identifier); - return (FALSE); - } - device = device->list.next; - } - return (TRUE); -} - XF86ConfDevicePtr xf86findDevice (const char *ident, XF86ConfDevicePtr p) { diff --git a/hw/xfree86/parser/Screen.c b/hw/xfree86/parser/Screen.c index 79e1d24ef..4524f17f6 100644 --- a/hw/xfree86/parser/Screen.c +++ b/hw/xfree86/parser/Screen.c @@ -498,12 +498,6 @@ xf86validateScreen (XF86ConfigPtr p) XF86ConfDevicePtr device; XF86ConfAdaptorLinkPtr adaptor; - if (!screen) - { - xf86validationError ("At least one Screen section is required."); - return (FALSE); - } - while (screen) { if (screen->scrn_obso_driver && !screen->scrn_identifier) @@ -512,13 +506,7 @@ xf86validateScreen (XF86ConfigPtr p) monitor = xf86findMonitor (screen->scrn_monitor_str, p->conf_monitor_lst); if (screen->scrn_monitor_str) { - if (!monitor) - { - xf86validationError (UNDEFINED_MONITOR_MSG, - screen->scrn_monitor_str, screen->scrn_identifier); - return (FALSE); - } - else + if (monitor) { screen->scrn_monitor = monitor; if (!xf86validateMonitor(p, screen)) @@ -526,15 +514,7 @@ xf86validateScreen (XF86ConfigPtr p) } } - device = xf86findDevice (screen->scrn_device_str, p->conf_device_lst); - if (!device) - { - xf86validationError (UNDEFINED_DEVICE_MSG, - screen->scrn_device_str, screen->scrn_identifier); - return (FALSE); - } - else - screen->scrn_device = device; + screen->scrn_device= xf86findDevice (screen->scrn_device_str, p->conf_device_lst); adaptor = screen->scrn_adaptor_lst; while (adaptor) diff --git a/hw/xfree86/parser/read.c b/hw/xfree86/parser/read.c index 9f79696ac..430da0a5a 100644 --- a/hw/xfree86/parser/read.c +++ b/hw/xfree86/parser/read.c @@ -80,8 +80,6 @@ static xf86ConfigSymTabRec TopLevelTab[] = static int xf86validateConfig (XF86ConfigPtr p) { - if (!xf86validateDevice (p)) - return FALSE; if (!xf86validateScreen (p)) return FALSE; if (!xf86validateInput (p)) diff --git a/hw/xfree86/utils/xorgconfig/xorgconfig.c b/hw/xfree86/utils/xorgconfig/xorgconfig.c index 8d9c03f5d..f50b4e225 100644 --- a/hw/xfree86/utils/xorgconfig/xorgconfig.c +++ b/hw/xfree86/utils/xorgconfig/xorgconfig.c @@ -631,7 +631,7 @@ mouse_configuration(void) { config_emulate3buttons = 0; printf("\n"); -#if (defined(sun) && (defined(__i386) || defined(__x86))) +#if (defined(sun) && (defined(__i386__) || defined(__x86))) /* SPARC & USB mice (VUID or AUTO protocols) default to /dev/mouse, but PS/2 mice default to /dev/kdmouse */ if ((config_mousetype != M_AUTO) && (config_mousetype != M_VUID)) { diff --git a/hw/xfree86/xf4bpp/vgaSolid.c b/hw/xfree86/xf4bpp/vgaSolid.c index 501bd3db0..0ef18cfeb 100644 --- a/hw/xfree86/xf4bpp/vgaSolid.c +++ b/hw/xfree86/xf4bpp/vgaSolid.c @@ -54,7 +54,7 @@ static void fastFill { int stop_count = bytewidth ; register int row_jump = bytes_per_line - bytewidth ; -#if !defined(OLDHC) && defined(BSDrt) && !defined(i386) +#if !defined(OLDHC) && defined(BSDrt) && !defined(__i386__) register const unsigned int notZero = ((unsigned char)(~0x0)); #else #define notZero ((unsigned char)(~0)) @@ -112,7 +112,7 @@ static void fastFillRMW { int stop_count = bytewidth ; register int row_jump = bytes_per_line - bytewidth ; -#if !defined(OLDHC) && defined(BSDrt) && !defined(i386) +#if !defined(OLDHC) && defined(BSDrt) && !defined(__i386__) register const unsigned int notZero = ((unsigned char)(~0x0)); #endif register int tmp ; @@ -369,7 +369,7 @@ register unsigned int height ; /* MUST BE > 0 !! */ { int stop_count = wordwidth ; register int row_jump = bytes_per_line - wordwidth*2 ; -#if !defined(OLDHC) && defined(BSDrt) && !defined(i386) && 0 +#if !defined(OLDHC) && defined(BSDrt) && !defined(__i386__) && 0 register const int notZero = ~0x0 ; #else #define notZero ( ~0 ) diff --git a/hw/xnest/Screen.c b/hw/xnest/Screen.c index 86f856e35..02e82d193 100644 --- a/hw/xnest/Screen.c +++ b/hw/xnest/Screen.c @@ -45,10 +45,6 @@ is" without express or implied warranty. Window xnestDefaultWindows[MAXSCREENS]; Window xnestScreenSaverWindows[MAXSCREENS]; -#ifdef GLXEXT -extern void GlxWrapInitVisuals(miInitVisualsProcPtr *); -#endif - static int xnestScreenGeneration = -1; ScreenPtr @@ -230,17 +226,6 @@ xnestOpenScreen(int index, ScreenPtr pScreen, int argc, char *argv[]) defaultVisual = visuals[xnestDefaultVisualIndex].vid; rootDepth = visuals[xnestDefaultVisualIndex].nplanes; -#ifdef GLXEXT - { - miInitVisualsProcPtr proc = NULL; - - GlxWrapInitVisuals(&proc); - /* GlxInitVisuals ignores the last three arguments. */ - proc(&visuals, &depths, &numVisuals, &numDepths, - &rootDepth, &defaultVisual, 0, 0, 0); - } -#endif - if (xnestParentWindow != 0) { XGetWindowAttributes(xnestDisplay, xnestParentWindow, &gattributes); xnestWidth = gattributes.width; diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 563d3439f..5635d64ae 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -184,6 +184,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_RPCSVC_DBM_H +/* Define to 1 if you have the `shmctl64' function. */ +#undef HAVE_SHMCTL64 + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H @@ -425,6 +428,8 @@ /* Support DRI extension */ #undef XF86DRI +#undef XEPHYR_DRI + /* Build DBE support */ #undef DBE diff --git a/include/servermd.h b/include/servermd.h index 74b90b38a..2616bfed6 100644 --- a/include/servermd.h +++ b/include/servermd.h @@ -260,7 +260,7 @@ SOFTWARE. #if defined(ibm032) || defined (ibm) -#ifdef i386 +#ifdef __i386__ # define IMAGE_BYTE_ORDER LSBFirst /* Value for PS/2 only */ #else # define IMAGE_BYTE_ORDER MSBFirst /* Values for the RT only*/ @@ -270,7 +270,7 @@ SOFTWARE. #define GETLEFTBITS_ALIGNMENT 4 /* ibm pcc doesn't understand pragmas. */ -#ifdef i386 +#ifdef __i386__ #define BITMAP_SCANLINE_UNIT 8 #endif @@ -444,10 +444,9 @@ SOFTWARE. #endif /* luna */ -#if (defined(SVR4) && defined(i386)) || \ +#if (defined(SVR4) && defined(__i386__)) || \ defined(__alpha__) || defined(__alpha) || \ - defined(__i386__) || defined(__i386) || \ - defined(__QNX__) || \ + defined(__i386__) || defined(__QNX__) || \ defined(__s390x__) || defined(__s390__) #ifndef IMAGE_BYTE_ORDER diff --git a/mi/micoord.h b/mi/micoord.h index b3d725b73..16a244b96 100644 --- a/mi/micoord.h +++ b/mi/micoord.h @@ -46,8 +46,7 @@ #if defined(mips) || defined(sgi) || \ defined(sparc) || defined(__sparc64__) || \ defined(__alpha) || defined(__alpha__) || \ - defined(__i386__) || defined(i386) || \ - defined(__ia64__) || defined(ia64) || \ + defined(__i386__) || defined(__ia64__) || \ defined(__s390x__) || defined(__s390__) || \ defined(__amd64__) || defined(amd64) || defined(__amd64) #define GetHighWord(x) (((int) (x)) >> 16) diff --git a/mi/miinitext.c b/mi/miinitext.c index 0fc6d1521..556bfc84b 100644 --- a/mi/miinitext.c +++ b/mi/miinitext.c @@ -347,7 +347,6 @@ extern void DarwinGlxWrapInitVisuals(miInitVisualsProcPtr *); extern __GLXprovider __glXMesaProvider; extern void GlxPushProvider(__GLXprovider *impl); extern void GlxExtensionInit(INITARGS); -extern void GlxWrapInitVisuals(miInitVisualsProcPtr *); #endif // INXDARWINAPP #endif // GLXEXT #ifdef XF86DRI @@ -673,9 +672,7 @@ InitVisualWrap() { miResetInitVisuals(); #ifdef GLXEXT -#ifndef __DARWIN__ - GlxWrapInitVisuals(&miInitVisualsProc); -#else +#ifdef __DARWIN__ DarwinGlxWrapInitVisuals(&miInitVisualsProc); #endif #endif diff --git a/os/access.c b/os/access.c index 5b638c70e..b0f63edc2 100644 --- a/os/access.c +++ b/os/access.c @@ -119,10 +119,10 @@ SOFTWARE. # include # endif #else -#if defined(SVR4) || (defined(SYSV) && defined(i386)) || defined(__GNU__) +#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__) # include #endif -#if defined(SYSV) && defined(i386) +#if defined(SYSV) && defined(__i386__) # include # ifdef ISC # include diff --git a/os/io.c b/os/io.c index 9de75eeaa..36abe1332 100644 --- a/os/io.c +++ b/os/io.c @@ -356,7 +356,7 @@ ReadRequestFromClient(ClientPtr client) { if ((result < 0) && ETEST(errno)) { -#if defined(SVR4) && defined(i386) && !defined(sun) +#if defined(SVR4) && defined(__i386__) && !defined(sun) if (0) #endif { diff --git a/os/utils.c b/os/utils.c index 36c8dfeb3..31cb0af92 100644 --- a/os/utils.c +++ b/os/utils.c @@ -160,6 +160,7 @@ _X_EXPORT Bool noFontCacheExtension = FALSE; #endif #ifdef GLXEXT _X_EXPORT Bool noGlxExtension = FALSE; +_X_EXPORT Bool noGlxVisualInit = FALSE; #endif #ifdef SCREENSAVER _X_EXPORT Bool noScreenSaverExtension = FALSE; diff --git a/os/xalloc.c b/os/xalloc.c index 8c019f3bc..e5f39465b 100644 --- a/os/xalloc.c +++ b/os/xalloc.c @@ -211,7 +211,7 @@ extern Bool Must_have_memory; fclose(f); \ } \ } -#if defined(linux) && defined(i386) +#if defined(linux) && defined(__i386__) #define LOG_ALLOC(_fun, _size, _ret) \ { unsigned long *from; \ __asm__("movl %%ebp,%0" : /*OUT*/ "=r" (from) : /*IN*/ ); \ diff --git a/xorg-server.pc.in b/xorg-server.pc.in index d3ffaa2f8..c1cdb7d2a 100644 --- a/xorg-server.pc.in +++ b/xorg-server.pc.in @@ -8,6 +8,6 @@ sdkdir=@sdkdir@ Name: xorg-server Description: Modular X.Org X Server Version: @PACKAGE_VERSION@ -Requires.private: pixman-1 +Requires: pixman-1 Cflags: -I${sdkdir} Libs: -L${libdir}