diff options
99 files changed, 10630 insertions, 1902 deletions
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..f6e032193 100644 --- a/GL/glx/glxcmds.c +++ b/GL/glx/glxcmds.c @@ -73,6 +73,8 @@ GlxSetRenderTables (struct _glapi_table *table) void __glXContextDestroy(__GLXcontext *context) { + if (!context->isDirect) + __glXDeassociateContext(context); __glXFlushContextCache(); } @@ -107,9 +109,10 @@ 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, VisualID visual, + GLuint screen, GLboolean isDirect) { ClientPtr client = cl->client; VisualPtr pVisual; @@ -129,8 +132,8 @@ int DoCreateContext(__GLXclientState *cl, GLXContextID gcId, return BadValue; } pScreen = screenInfo.screens[screen]; - pGlxScreen = __glXActiveScreens[screen]; - + pGlxScreen = glxGetScreen(pScreen); + /* ** Check if the visual ID is valid for this screen. */ @@ -147,7 +150,7 @@ int DoCreateContext(__GLXclientState *cl, GLXContextID gcId, /* ** Get configuration of the visual. This assumes that the - ** glXActiveScreens structure contains visual configurations only for the + ** glxScreen structure contains visual configurations only for the ** subset of Visuals that are supported by this implementation of the ** OpenGL. */ @@ -383,36 +386,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 +396,94 @@ 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; + VisualID vid; 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. */ + vid = wVisual((WindowPtr)pDraw); + modes = _gl_context_modes_find_visual(glxc->pGlxScreen->modes, vid); + + /* We're binding an X Window 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; + *error = BadMatch; + return NULL; } - pGlxDraw = - glxc->pGlxScreen->createDrawable(glxc->pGlxScreen, - pDraw, drawId, modes); + pGlxDraw = glxc->pGlxScreen->createDrawable(glxc->pGlxScreen, + pDraw, GLX_DRAWABLE_WINDOW, + drawId, 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 +541,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 +609,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 +616,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 +634,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,8 +830,8 @@ int __glXDisp_CopyContext(__GLXclientState *cl, GLbyte *pc) } -int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, - GLboolean do_swap) +static int +DoGetVisualConfigs(__GLXclientState *cl, unsigned screen) { ClientPtr client = cl->client; xGLXGetVisualConfigsReply reply; @@ -929,7 +847,7 @@ int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, client->errorValue = screen; return BadValue; } - pGlxScreen = __glXActiveScreens[screen]; + pGlxScreen = glxGetScreen(screenInfo.screens[screen]); reply.numVisuals = pGlxScreen->numUsableVisuals; reply.numProps = __GLX_TOTAL_CONFIG; @@ -938,7 +856,7 @@ int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, 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); @@ -992,7 +910,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, @@ -1004,7 +922,7 @@ int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, int __glXDisp_GetVisualConfigs(__GLXclientState *cl, GLbyte *pc) { xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc; - return DoGetVisualConfigs( cl, req->screen, GL_FALSE ); + return DoGetVisualConfigs(cl, req->screen); } @@ -1100,7 +1018,8 @@ __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; @@ -1117,7 +1036,7 @@ int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) client->errorValue = screen; return BadValue; } - pGlxScreen = __glXActiveScreens[screen]; + pGlxScreen = glxGetScreen(screenInfo.screens[screen]); /* Create the "extra" 32bpp ARGB visual, if not already added. * XXX This is questionable place to do so! Re-examine this someday. @@ -1130,7 +1049,7 @@ int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) 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); @@ -1185,7 +1104,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,41 +1117,32 @@ 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, int screenNum, XID fbconfigId, + DrawablePtr pDraw, XID glxDrawableId, int type) { - DrawablePtr pDraw; ScreenPtr pScreen; VisualPtr pVisual; __GLXscreen *pGlxScreen; - int i, rc; + __GLXdrawable *pGlxDraw; + __GLcontextModes *modes; + int i; 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 (screenNum != pScreen->myNum) return BadMatch; - } /* If this fbconfig has a corresponding VisualRec the number of * planes must match the drawable depth. */ @@ -1243,56 +1153,59 @@ static int ValidateCreateDrawable(ClientPtr client, } /* Get configuration of the visual. */ - pGlxScreen = __glXgetActiveScreen(screenNum); - *modes = _gl_context_modes_find_visual(pGlxScreen->modes, fbconfigId); - if (*modes == NULL) { + pGlxScreen = glxGetScreen(pScreen); + 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; } - *ppDraw = pDraw; + /* FIXME: We need to check that the window visual is compatible + * with the specified fbconfig. */ + pGlxDraw = pGlxScreen->createDrawable(pGlxScreen, pDraw, type, + glxDrawableId, modes); + if (pGlxDraw == NULL) + return BadAlloc; + + if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) { + pGlxDraw->destroy (pGlxDraw); + return BadAlloc; + } 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, int screenNum, XID fbconfigId, + XID drawableId, XID glxDrawableId) { - ClientPtr client = cl->client; DrawablePtr pDraw; - __GLXpixmap *pGlxPixmap; - __GLcontextModes *modes; - GLenum target = 0; - int retval, i; + int err; - 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; + err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixUnknownAccess); + if (err != Success || pDraw->type != DRAWABLE_PIXMAP) { + client->errorValue = drawableId; + return BadPixmap; } - 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; + err = DoCreateGLXDrawable(client, screenNum, fbconfigId, 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 i; + __GLXdrawable *pGlxDraw; + + pGlxDraw = LookupIDByType(glxDrawableID, __glXDrawableRes); for (i = 0; i < numAttribs; i++) { if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) { @@ -1306,63 +1219,74 @@ 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 ); + + return DoCreateGLXPixmap(cl->client, req->screen, req->visual, + 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 ); + int err; + + err = DoCreateGLXPixmap(cl->client, req->screen, req->fbconfig, + 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 ); + + return DoCreateGLXPixmap(cl->client, req->screen, req->fbconfig, + 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 +1295,116 @@ 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) +{ + ScreenPtr pScreen; + VisualPtr pVisual; + PixmapPtr pPixmap; + int i; + + pScreen = screenInfo.screens[screenNum]; + + pVisual = pScreen->visuals; + for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { + if (pVisual->vid == fbconfigId) + break; + } + if (i == pScreen->numVisuals) + return __glXError(GLXBadFBConfig); + + __glXenterServer(GL_FALSE); + pPixmap = (*pScreen->CreatePixmap) (pScreen, + width, height, pVisual->nplanes); + __glXleaveServer(GL_FALSE); + + return DoCreateGLXDrawable(client, screenNum, fbconfigId, + &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 +1412,41 @@ int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc) xGLXChangeDrawableAttributesReq *req = (xGLXChangeDrawableAttributesReq *) pc; - (void) req; - - return BadRequest; + return DoChangeDrawableAttributes(cl->client, req->drawable, + req->numAttribs, (CARD32 *) (req + 1)); } -int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) +int __glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) { - xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; - ClientPtr client = cl->client; - DrawablePtr pDraw; - __GLXdrawable *glxPriv; - __GLXscreen *screen; - __GLcontextModes *modes; - int retval; - - retval = ValidateCreateDrawable (client, req->screen, req->fbconfig, - req->window, req->glxwindow, - DRAWABLE_WINDOW, &modes, &pDraw); - if (retval != Success) - return retval; + xGLXChangeDrawableAttributesSGIXReq *req = + (xGLXChangeDrawableAttributesSGIXReq *)pc; - /* FIXME: We need to check that the window visual is compatible - * with the specified fbconfig. */ + return DoChangeDrawableAttributes(cl->client, req->drawable, + req->numAttribs, (CARD32 *) (req + 1)); +} - screen = __glXgetActiveScreen(req->screen); - glxPriv = screen->createDrawable(screen, pDraw, req->glxwindow, modes); - if (glxPriv == NULL) - return BadAlloc; +int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; + ClientPtr client = cl->client; + DrawablePtr pDraw; + int err; - 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; + return DoCreateGLXDrawable(client, req->screen, req->fbconfig, + 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 +1465,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 +1489,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 +1501,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 +1565,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 +1583,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 +1594,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 +1616,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 +1627,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 +1636,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 +1674,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 +1695,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,22 +1732,18 @@ DoGetDrawableAttributes(__GLXclientState *cl, XID drawId) return Success; } -int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) +int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) { - xGLXVendorPrivateWithReplyReq *req = (xGLXVendorPrivateWithReplyReq *)pc; - CARD32 *data; - XID drawable; - - data = (CARD32 *) (req + 1); - drawable = data[0]; + xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc; - return DoGetDrawableAttributes(cl, drawable); + return DoGetDrawableAttributes(cl, req->drawable); } -int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) +int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) { - xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc; - + xGLXGetDrawableAttributesSGIXReq *req = + (xGLXGetDrawableAttributesSGIXReq *)pc; + return DoGetDrawableAttributes(cl, req->drawable); } @@ -1766,7 +1754,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 +1768,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 +1793,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 +1805,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 +1815,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 +1849,11 @@ int DoRender(__GLXclientState *cl, GLbyte *pc, int do_swap) return Success; } + /* -** Execute all the drawing commands in a request. +** Execute a large rendering request (one that spans multiple X requests). */ -int __glXDisp_Render(__GLXclientState *cl, GLbyte *pc) -{ - return DoRender(cl, pc, False); -} - -int DoRenderLarge(__GLXclientState *cl, GLbyte *pc, int do_swap) +int __glXDisp_RenderLarge(__GLXclientState *cl, GLbyte *pc) { xGLXRenderLargeReq *req; ClientPtr client= cl->client; @@ -1875,10 +1863,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 +1908,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 +1930,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 +2031,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 +2057,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 +2067,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 +2098,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 +2135,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 +2173,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 +2211,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 +2255,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); } @@ -2366,7 +2352,7 @@ int __glXDisp_QueryExtensionsString(__GLXclientState *cl, GLbyte *pc) return BadValue; } - ptr = __glXActiveScreens[screen]->GLXextensions; + ptr = glxGetScreen(screenInfo.screens[screen])->GLXextensions; n = strlen(ptr) + 1; length = __GLX_PAD(n) >> 2; @@ -2402,6 +2388,7 @@ int __glXDisp_QueryServerString(__GLXclientState *cl, GLbyte *pc) size_t n, length; const char *ptr; char *buf; + __GLXscreen *pGlxScreen; name = req->name; screen = req->screen; @@ -2412,15 +2399,17 @@ int __glXDisp_QueryServerString(__GLXclientState *cl, GLbyte *pc) client->errorValue = screen; return BadValue; } + pGlxScreen = glxGetScreen(screenInfo.screens[screen]); + switch(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; + + __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 __glXDisp_CreatePbuffer(cl, pc); +} - (void) req; +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 BadRequest; + return __glXDisp_CreateGLXPbufferSGIX(cl, pc); } int __glXDispSwap_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc) { xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) req; + __GLX_DECLARE_SWAP_VARIABLES; + + __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 BadRequest; + 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; + + __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 BadRequest; + 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); }; @@ -152,12 +152,6 @@ struct __GLXcontext { 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 */ __GLXdrawable *drawPriv; diff --git a/GL/glx/glxdrawable.h b/GL/glx/glxdrawable.h index b7ecad929..858bbb35b 100644 --- a/GL/glx/glxdrawable.h +++ b/GL/glx/glxdrawable.h @@ -46,22 +46,12 @@ #include <GL/internal/dri_interface.h> #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 +68,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 +93,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..2ded6aa81 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; - - __DRIdrawable *driDrawable; + __GLXdrawable base; + __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,21 +641,19 @@ __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; } @@ -727,161 +716,28 @@ filter_modes(__GLcontextModes **server_modes, } -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 +745,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 +801,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 +835,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 +851,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 +861,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) { @@ -1044,8 +951,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; @@ -1170,9 +1075,8 @@ __glXDRIscreenProbe(ScreenPtr pScreen) driver_modes = NULL; screen->driScreen.private = - (*createNewScreen)(NULL, pScreen->myNum, + (*createNewScreen)(pScreen->myNum, &screen->driScreen, - screen->base.modes, &ddx_version, &dri_version, &drm_version, @@ -1191,6 +1095,8 @@ __glXDRIscreenProbe(ScreenPtr pScreen) DRIGetTexOffsetFuncs(pScreen, &screen->texOffsetStart, &screen->texOffsetFinish); + initializeExtensions(screen); + __glXScreenInit(&screen->base, pScreen); buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL); 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); - } /* @@ -130,66 +101,6 @@ static int ContextGone(__GLXcontext* cx, XID id) } /* -** 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..fd4e57d59 100644 --- a/GL/glx/glxglcore.c +++ b/GL/glx/glxglcore.c @@ -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; } diff --git a/GL/glx/glxscreens.c b/GL/glx/glxscreens.c index 43447a4e4..c6f060b3d 100644 --- a/GL/glx/glxscreens.c +++ b/GL/glx/glxscreens.c @@ -45,6 +45,8 @@ #include "glxutil.h" #include "glxext.h" +static int glxScreenPrivateIndex; + const char GLServerVersion[] = "1.4"; static const char GLServerExtensions[] = "GL_ARB_depth_texture " @@ -179,36 +181,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 +250,71 @@ 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]); - __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc = - funcs->bindSwapBarrierFunc; - __glXSwapBarrierFuncs[screen].queryMaxSwapBarriersFunc = - funcs->queryMaxSwapBarriersFunc; + pGlxScreen->swapBarrierFuncs = funcs; } -static __GLXprovider *__glXProviderStack; - -void GlxPushProvider(__GLXprovider *provider) +static Bool +glxCloseScreen (int index, ScreenPtr pScreen) { - provider->next = __glXProviderStack; - __glXProviderStack = provider; -} + __GLXscreen *pGlxScreen = glxGetScreen(pScreen); -void __glXScreenInit(__GLXscreen *screen, ScreenPtr pScreen) -{ - screen->pScreen = pScreen; - screen->GLextensions = xstrdup(GLServerExtensions); - screen->GLXvendor = xstrdup(GLXServerVendorName); - screen->GLXversion = xstrdup(GLXServerVersion); - screen->GLXextensions = xstrdup(GLXServerExtensions); + pScreen->CloseScreen = pGlxScreen->CloseScreen; + pScreen->PositionWindow = pGlxScreen->PositionWindow; - screen->WrappedPositionWindow = pScreen->PositionWindow; - pScreen->PositionWindow = PositionWindow; + pGlxScreen->destroy(pGlxScreen); - __glXScreenInitVisuals(screen); + return pScreen->CloseScreen(index, pScreen); } -void -__glXScreenDestroy(__GLXscreen *screen) +__GLXscreen * +glxGetScreen(ScreenPtr pScreen) { - xfree(screen->GLXvendor); - xfree(screen->GLXversion); - xfree(screen->GLXextensions); - xfree(screen->GLextensions); + return (__GLXscreen *) pScreen->devPrivates[glxScreenPrivateIndex].ptr; } -void __glXInitScreens(void) +void __glXScreenInit(__GLXscreen *glxScreen, ScreenPtr pScreen) { - GLint i; - ScreenPtr pScreen; - __GLXprovider *p; - size_t size; + static int glxGeneration; - /* - ** 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]; + if (glxGeneration != serverGeneration) + { + glxScreenPrivateIndex = AllocateScreenPrivateIndex (); + if (glxScreenPrivateIndex == -1) + return; - 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; - } - } + glxGeneration = serverGeneration; } -} -void __glXResetScreens(void) -{ - int i; + glxScreen->pScreen = pScreen; + glxScreen->GLextensions = xstrdup(GLServerExtensions); + glxScreen->GLXvendor = xstrdup(GLXServerVendorName); + glxScreen->GLXversion = xstrdup(GLXServerVersion); + glxScreen->GLXextensions = xstrdup(GLXServerExtensions); + + glxScreen->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = glxPositionWindow; + + glxScreen->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = glxCloseScreen; - for (i = 0; i < screenInfo.numScreens; i++) - if (__glXActiveScreens[i]) - __glXActiveScreens[i]->destroy(__glXActiveScreens[i]); + __glXScreenInitVisuals(glxScreen); - xfree(__glXActiveScreens); - xfree(__glXHyperpipeFuncs); - xfree(__glXSwapBarrierFuncs); - __glXNumHyperpipeFuncs = 0; - __glXNumSwapBarrierFuncs = 0; - __glXHyperpipeFuncs = NULL; - __glXSwapBarrierFuncs = NULL; - __glXActiveScreens = NULL; + pScreen->devPrivates[glxScreenPrivateIndex].ptr = (pointer) glxScreen; +} + +void __glXScreenDestroy(__GLXscreen *screen) +{ + xfree(screen->GLXvendor); + xfree(screen->GLXversion); + xfree(screen->GLXextensions); + xfree(screen->GLextensions); } diff --git a/GL/glx/glxscreens.h b/GL/glx/glxscreens.h index bba45572f..7b1bbcd58 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,11 +72,15 @@ 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; /** @@ -79,18 +98,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..45de8e794 100644 --- a/GL/glx/glxserver.h +++ b/GL/glx/glxserver.h @@ -90,9 +90,8 @@ 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); /************************************************************************/ 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 index 0e9bdedec..46b380b3d 100644 --- a/GL/glx/glxvisuals.c +++ b/GL/glx/glxvisuals.c @@ -55,6 +55,7 @@ void GlxWrapInitVisuals(miInitVisualsProcPtr *); +extern Bool noGlxVisualInit; #include "glcontextmodes.h" struct ScreenVisualsRec { @@ -452,14 +453,15 @@ Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, /* * Setup the visuals supported by this particular screen. */ - init_visuals(nvisualp, visualp, defaultVisp, - *ndepthp, *depthp, *rootDepthp); + if (!noGlxVisualInit) { + init_visuals(nvisualp, visualp, defaultVisp, + *ndepthp, *depthp, *rootDepthp); + } return True; } - /************************************************************************/ 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 56a944be1..db3c2ec90 100644 --- a/Xext/shm.c +++ b/Xext/shm.c @@ -64,6 +64,33 @@ in this Software without prior written authorization from The Open Group. #include <X11/extensions/shmstr.h> #include <X11/Xfuncproto.h> +/* Needed for Solaris cross-zone shared memory extension */ +#ifdef HAVE_SHMCTL64 +#include <sys/ipc_impl.h> +#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" @@ -362,32 +389,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) { - - /* User id 0 always gets access */ - if (uid == 0) { - return 0; + if (lcc->fieldsSet & LCC_UID_SET) { + uid = lcc->euid; + uidset = 1; + } + if (lcc->fieldsSet & LCC_GID_SET) { + gid = lcc->egid; + gidset = 1; } - /* Check the owner */ - if (perm->uid == uid || perm->cuid == uid) { - mask = S_IRUSR; - if (!readonly) { - mask |= S_IWUSR; + +#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); + + if (uidset) { + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* 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; } - 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; + + 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 */ @@ -395,14 +447,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); @@ -431,7 +483,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; @@ -441,7 +493,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; @@ -450,7 +502,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 8901faec3..d224185be 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]) + 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 ;; @@ -725,6 +726,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 @@ -780,7 +782,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' @@ -1446,6 +1448,7 @@ dnl has it in libc), or if libdl is needed to get it. case $host_os in darwin*) ;; *bsd*) ;; + linux*) ;; *) xorg_bus_ix86pci=yes ;; esac ;; @@ -1464,7 +1467,7 @@ dnl has it in libc), or if libdl is needed to get it. ;; x86_64*|amd64*) case $host_os in - darwin*|*bsd*) + darwin*|*bsd*|linux*) ;; *) xorg_bus_ix86pci="yes" @@ -1859,6 +1862,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], [], @@ -1878,9 +1888,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*) @@ -1892,7 +1902,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 $XSERVERLIBS_LIBS" + KDRIVE_LIBS="$KDRIVE_LOCAL_LIBS $XSERVERLIBS_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/events.c b/dix/events.c index 0d82d19f3..bb5b9507b 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2365,6 +2365,61 @@ DefineInitialRootWindow(WindowPtr win) #endif } +/** + * Update the mouse sprite info when the server switches from a pScreen to another. + * Otherwise, the pScreen of the mouse sprite is never updated when we switch + * from a pScreen to another. Never updating the pScreen of the mouse sprite + * implies that windows that are in pScreen whose pScreen->myNum >0 will never + * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen + * always points to the first pScreen it has been set by + * DefineInitialRootWindow(). + * + * Calling this function is useful for use cases where the server + * has more than one pScreen. + * This function is similar to DefineInitialRootWindow() but it does not + * reset the mouse pointer position. + * @param win must be the new pScreen we are switching to. + */ +void +UpdateSpriteForScreen(ScreenPtr pScreen) +{ + WindowPtr win = NULL; + if (!pScreen) + return ; + win = WindowTable[pScreen->myNum]; + + sprite.hotPhys.pScreen = pScreen; + sprite.hot = sprite.hotPhys; + sprite.hotLimits.x2 = pScreen->width; + sprite.hotLimits.y2 = pScreen->height; +#ifdef XEVIE + xeviewin = +#endif + sprite.win = win; + sprite.current = wCursor (win); + sprite.current->refcnt++; + spriteTraceGood = 1; + ROOT = win; + (*pScreen->CursorLimits) (pScreen, + sprite.current, + &sprite.hotLimits, + &sprite.physLimits); + sprite.confined = FALSE; + (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); + (*pScreen->DisplayCursor) (pScreen, sprite.current); + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; + sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; + sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + sprite.physLimits = sprite.hotLimits; + sprite.screen = pScreen; + } +#endif +} + /* * This does not take any shortcuts, and even ignores its argument, since * it does not happen very often, and one has to walk up the tree since diff --git a/dix/extension.c b/dix/extension.c index c81c1a123..b765008e8 100644 --- a/dix/extension.c +++ b/dix/extension.c @@ -151,6 +151,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) @@ -73,6 +73,14 @@ exaGetPixmapOffset(PixmapPtr pPix) (unsigned long)pExaScr->info->memoryBase); } +void * +exaGetPixmapDriverPrivate(PixmapPtr pPix) +{ + ExaPixmapPriv(pPix); + + return pExaPixmap->driverPriv; +} + /** * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. * @@ -174,9 +182,18 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) static Bool exaDestroyPixmap (PixmapPtr pPixmap) { + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ExaScreenPriv(pScreen); + if (pPixmap->refcnt == 1) { ExaPixmapPriv (pPixmap); + + if (pExaPixmap->driverPriv) { + pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); + pExaPixmap->driverPriv = NULL; + } + if (pExaPixmap->area) { DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", @@ -220,46 +237,87 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth) { PixmapPtr pPixmap; ExaPixmapPrivPtr pExaPixmap; + int driver_alloc = 0; int bpp; ExaScreenPriv(pScreen); if (w > 32767 || h > 32767) return NullPixmap; - pPixmap = fbCreatePixmap (pScreen, w, h, depth); + if (!pExaScr->info->CreatePixmap) { + pPixmap = fbCreatePixmap (pScreen, w, h, depth); + } else { + driver_alloc = 1; + pPixmap = fbCreatePixmap(pScreen, 0, 0, depth); + } + if (!pPixmap) - return NULL; + return NULL; + pExaPixmap = ExaGetPixmapPriv(pPixmap); bpp = pPixmap->drawable.bitsPerPixel; - /* Glyphs have w/h equal to zero, and may not be migrated. See exaGlyphs. */ - if (!w || !h) - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; - else - pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; - - pExaPixmap->area = NULL; - - pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; - pExaPixmap->sys_pitch = pPixmap->devKind; - - pPixmap->devPrivate.ptr = NULL; - pExaPixmap->offscreen = FALSE; - - pExaPixmap->fb_ptr = NULL; - if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) - pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8; - else - pExaPixmap->fb_pitch = w * bpp / 8; - pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, - pExaScr->info->pixmapPitchAlign); - pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; + if (driver_alloc) { + size_t paddedWidth, datasize; + void *driver_priv; + + paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); + if (paddedWidth / 4 > 32767 || h > 32767) + return NullPixmap; + + if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) + pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8; + else + pExaPixmap->fb_pitch = w * bpp / 8; + pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, + pExaScr->info->pixmapPitchAlign); + if (paddedWidth < pExaPixmap->fb_pitch) + paddedWidth = pExaPixmap->fb_pitch; + + datasize = h * paddedWidth; + + driver_priv = pExaScr->info->CreatePixmap(pScreen, datasize, 0); + if (!driver_priv) { + fbDestroyPixmap(pPixmap); + return NULL; + } - if (pExaPixmap->fb_pitch > 131071) { - fbDestroyPixmap(pPixmap); - return NULL; + (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, + paddedWidth, NULL); + 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. */ + if (!w || !h) + pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; + else + pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; + + pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; + pExaPixmap->sys_pitch = pPixmap->devKind; + + pPixmap->devPrivate.ptr = NULL; + pExaPixmap->offscreen = FALSE; + + pExaPixmap->fb_ptr = NULL; + if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) + pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8; + else + pExaPixmap->fb_pitch = w * bpp / 8; + pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, + pExaScr->info->pixmapPitchAlign); + pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; + + if (pExaPixmap->fb_pitch > 131071) { + fbDestroyPixmap(pPixmap); + return NULL; + } } + + pExaPixmap->area = NULL; /* Set up damage tracking */ pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE, @@ -306,6 +364,7 @@ exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, { ExaScreenPrivPtr pExaScr; ExaPixmapPrivPtr pExaPixmap; + Bool ret; if (!pPixmap) return FALSE; @@ -317,6 +376,12 @@ exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, pExaScr = ExaGetScreenPriv(pPixmap->drawable.pScreen); + if (pExaScr->info->ModifyPixmapHeader) { + ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, + bitsPerPixel, devKind, pPixData); + if (ret == TRUE) + return ret; + } return pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData); } @@ -344,7 +409,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) @@ -394,7 +459,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); } @@ -455,8 +520,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; } @@ -690,22 +754,24 @@ exaDriverInit (ScreenPtr pScreen, return FALSE; } - if (!pScreenInfo->memoryBase) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase must be " - "non-zero\n", pScreen->myNum); - return FALSE; - } + if (!pScreenInfo->CreatePixmap) { + if (!pScreenInfo->memoryBase) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase " + "must be non-zero\n", pScreen->myNum); + return FALSE; + } - if (!pScreenInfo->memorySize) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " - "non-zero\n", pScreen->myNum); - return FALSE; - } + if (!pScreenInfo->memorySize) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " + "non-zero\n", pScreen->myNum); + return FALSE; + } - if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must be <= " - "ExaDriverRec::memorySize\n", pScreen->myNum); - return FALSE; + if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must " + "be <= ExaDriverRec::memorySize\n", pScreen->myNum); + return FALSE; + } } if (!pScreenInfo->PrepareSolid) { @@ -729,36 +795,17 @@ exaDriverInit (ScreenPtr pScreen, /* If the driver doesn't set any max pitch values, we'll just assume * that there's a limitation by pixels, and that it's the same as * maxX. + * + * We want maxPitchPixels or maxPitchBytes to be set so we can check + * pixmaps against the max pitch in exaCreatePixmap() -- it matters + * whether a pixmap is rejected because of its pitch or + * because of its width. */ if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) { pScreenInfo->maxPitchPixels = pScreenInfo->maxX; } - /* If set, maxPitchPixels must not be smaller than maxX. */ - if (pScreenInfo->maxPitchPixels && - pScreenInfo->maxPitchPixels < pScreenInfo->maxX) - { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::maxPitchPixels " - "is smaller than ExaDriverRec::maxX\n", - pScreen->myNum); - return FALSE; - } - - /* If set, maxPitchBytes must not be smaller than maxX * 4. - * This is to ensure that a 32bpp pixmap with the maximum width - * can be handled wrt the pitch. - */ - if (pScreenInfo->maxPitchBytes && - pScreenInfo->maxPitchBytes < (pScreenInfo->maxX * 4)) - { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::maxPitchBytes " - "doesn't allow a 32bpp pixmap with width equal to " - "ExaDriverRec::maxX\n", - pScreen->myNum); - return FALSE; - } - #ifdef RENDER ps = GetPictureScreenIfSet(pScreen); #endif @@ -829,8 +876,7 @@ exaDriverInit (ScreenPtr pScreen, /* * Hookup offscreen pixmaps */ - if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && - pExaScr->info->offScreenBase < pExaScr->info->memorySize) + if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) { if (!dixRequestPrivate(exaPixmapPrivateKey, sizeof(ExaPixmapPrivRec))) { LogMessage(X_WARNING, @@ -846,21 +892,29 @@ exaDriverInit (ScreenPtr pScreen, pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader; pScreen->ModifyPixmapHeader = exaModifyPixmapHeader; - LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %d bytes\n", - pScreen->myNum, - pExaScr->info->memorySize - pExaScr->info->offScreenBase); + if (!pExaScr->info->CreatePixmap) { + LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", + pScreen->myNum, + pExaScr->info->memorySize - pExaScr->info->offScreenBase); + } else { + LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n", + pScreen->myNum); + + } } else LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); - DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, - pExaScr->info->memorySize)); - if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { - if (!exaOffscreenInit (pScreen)) { - LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n", - pScreen->myNum); - return FALSE; - } + if (!pExaScr->info->CreatePixmap) { + DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, + pExaScr->info->memorySize)); + if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { + if (!exaOffscreenInit (pScreen)) { + LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n", + pScreen->myNum); + return FALSE; + } + } } LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" @@ -39,7 +39,7 @@ #include "fb.h" #define EXA_VERSION_MAJOR 2 -#define EXA_VERSION_MINOR 3 +#define EXA_VERSION_MINOR 4 #define EXA_VERSION_RELEASE 0 typedef struct _ExaOffscreenArea ExaOffscreenArea; @@ -702,6 +702,13 @@ typedef struct _ExaDriver { */ int maxPitchBytes; + /* Hooks to allow driver to its own pixmap memory management */ + void *(*CreatePixmap)(ScreenPtr pScreen, int size, int align); + void (*DestroyPixmap)(ScreenPtr pScreen, void *driverPriv); + Bool (*ModifyPixmapHeader)(PixmapPtr pPixmap, int width, int height, + int depth, int bitsPerPixel, int devKind, + pointer pPixData); + /** @} */ } ExaDriverRec, *ExaDriverPtr; @@ -726,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 @@ -773,6 +787,9 @@ exaMoveInPixmap (PixmapPtr pPixmap); void exaMoveOutPixmap (PixmapPtr pPixmap); +void * +exaGetPixmapDriverPrivate(PixmapPtr p); + /** * Returns TRUE if the given planemask covers all the significant bits in the * pixel values for pDrawable. diff --git a/exa/exa_accel.c b/exa/exa_accel.c index 028d93644..8bbf036e4 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -508,14 +508,6 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, region = RECTS_TO_REGION(pScreen, nbox, rects, CT_YXBANDED); DEALLOCATE_LOCAL(rects); - - if (region) { - src_off_x -= dst_off_x; - src_off_y -= dst_off_y; - dst_off_x = dst_off_y = 0; - pbox = REGION_RECTS(region); - nbox = REGION_NUM_RECTS(region); - } } } @@ -1106,6 +1098,7 @@ exaFillRegionSolid (DrawablePtr pDrawable, ExaPixmapPriv (pPixmap); int xoff, yoff; ExaMigrationRec pixmaps[1]; + Bool ret = FALSE; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; @@ -1118,12 +1111,12 @@ exaFillRegionSolid (DrawablePtr pDrawable, if (pExaPixmap->accel_blocked) { - goto fallback; + goto out; } else { exaDoMigration (pixmaps, 1, TRUE); } - if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && + if (exaPixmapIsOffscreen (pPixmap) && (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) { int nbox; @@ -1141,7 +1134,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); @@ -1160,24 +1154,13 @@ exaFillRegionSolid (DrawablePtr pDrawable, pRegion); } - REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); - return TRUE; + ret = TRUE; } -fallback: - if (alu != GXcopy || !EXA_PM_IS_SOLID(pDrawable, planemask)) { - REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); - return FALSE; - } - EXA_FALLBACK(("to %p (%c)\n", pDrawable, - exaDrawableLocation(pDrawable))); - exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg); +out: REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); - fbFillRegionSolid (pDrawable, pRegion, 0, - fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - return TRUE; + return ret; } /* Try to do an accelerated tile of the pTile into pRegion of pDrawable. @@ -1195,11 +1178,12 @@ exaFillRegionTiled (DrawablePtr pDrawable, PixmapPtr pPixmap; ExaPixmapPrivPtr pExaPixmap; ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile); - int xoff, yoff, tileXoff, tileYoff; + int xoff, yoff; int tileWidth, tileHeight; ExaMigrationRec pixmaps[2]; int nbox = REGION_NUM_RECTS (pRegion); BoxPtr pBox = REGION_RECTS (pRegion); + Bool ret = FALSE; tileWidth = pTile->drawable.width; tileHeight = pTile->drawable.height; @@ -1229,22 +1213,17 @@ exaFillRegionTiled (DrawablePtr pDrawable, if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked) { - goto fallback; + goto out; } else { exaDoMigration (pixmaps, 2, TRUE); } pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); - if (!pPixmap) - goto fallback; - - if (!exaPixmapIsOffscreen(pTile)) - goto fallback; + if (!pPixmap || !exaPixmapIsOffscreen(pTile)) + goto out; - if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile, - &tileXoff, &tileYoff), - pPixmap, 0, 0, alu, planemask)) + if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask)) { while (nbox--) { @@ -1252,7 +1231,8 @@ exaFillRegionTiled (DrawablePtr pDrawable, int dstY = pBox->y1; int tileY; - tileY = (dstY - yoff - pDrawable->y - pPatOrg->y) % tileHeight; + modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY); + while (height > 0) { int width = pBox->x2 - pBox->x1; int dstX = pBox->x1; @@ -1263,16 +1243,17 @@ exaFillRegionTiled (DrawablePtr pDrawable, h = height; height -= h; - tileX = (dstX - xoff - pDrawable->x - pPatOrg->x) % tileWidth; + modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth, + tileX); + while (width > 0) { int w = tileWidth - tileX; if (w > width) w = width; width -= w; - (*pExaScr->info->Copy) (pPixmap, - tileX + tileXoff, tileY + tileYoff, - dstX, dstY, w, h); + (*pExaScr->info->Copy) (pPixmap, tileX, tileY, dstX, dstY, + w, h); dstX += w; tileX = 0; } @@ -1283,26 +1264,14 @@ exaFillRegionTiled (DrawablePtr pDrawable, } (*pExaScr->info->DoneCopy) (pPixmap); exaMarkSync(pDrawable->pScreen); - REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); - return TRUE; - } -fallback: - if (alu != GXcopy || !EXA_PM_IS_SOLID(pDrawable, planemask)) { - REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); - return FALSE; + ret = TRUE; } - EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable, - exaDrawableLocation(&pTile->drawable), - exaDrawableLocation(pDrawable))); - exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg); + +out: REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); - exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); - fbFillRegionTiled (pDrawable, pRegion, pTile); - exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - return TRUE; + return ret; } diff --git a/exa/exa_migration.c b/exa/exa_migration.c index c0e022ca7..7968521c5 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -553,6 +553,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_priv.h b/exa/exa_priv.h index b1023a67e..582ddcaa6 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -192,6 +192,10 @@ typedef struct { * damage, which may be overreported) of a pixmap's system and FB copies. */ RegionRec validSys, validFB; + /** + * Driver private storage per EXA pixmap + */ + void *driverPriv; } ExaPixmapPrivRec, *ExaPixmapPrivPtr; typedef struct _ExaMigrationRec { diff --git a/fb/fbarc.c b/fb/fbarc.c index 3f46bd4b2..f89b81c52 100644 --- a/fb/fbarc.c +++ b/fb/fbarc.c @@ -71,9 +71,13 @@ fbPolyArc (DrawablePtr pDrawable, BoxRec box; int x2, y2; RegionPtr cclip; + int wrapped = 0; cclip = fbGetCompositeClip (pGC); fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); +#ifdef FB_ACCESS_WRAPPER + wrapped = 1; +#endif while (narcs--) { if (miCanZeroArc (parcs)) @@ -96,18 +100,43 @@ fbPolyArc (DrawablePtr pDrawable, y2 = box.y1 + (int)parcs->height + 1; box.y2 = y2; if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) && - (RECT_IN_REGION(pDrawable->pScreen, cclip, &box) == rgnIN) ) + (RECT_IN_REGION(pDrawable->pScreen, cclip, &box) == rgnIN) ) { +#ifdef FB_ACCESS_WRAPPER + if (!wrapped) { + fbPrepareAccess (pDrawable); + wrapped = 1; + } +#endif (*arc) (dst, dstStride, dstBpp, parcs, pDrawable->x + dstXoff, pDrawable->y + dstYoff, pPriv->and, pPriv->xor); - else + } else { +#ifdef FB_ACCESS_WRAPPER + if (wrapped) { + fbFinishAccess (pDrawable); + wrapped = 0; + } +#endif miZeroPolyArc(pDrawable, pGC, 1, parcs); + } } - else + else { +#ifdef FB_ACCESS_WRAPPER + if (wrapped) { + fbFinishAccess (pDrawable); + wrapped = 0; + } +#endif miPolyArc(pDrawable, pGC, 1, parcs); + } parcs++; } - fbFinishAccess (pDrawable); +#ifdef FB_ACCESS_WRAPPER + if (wrapped) { + fbFinishAccess (pDrawable); + wrapped = 0; + } +#endif } else #endif 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 <kevin@precisioninsight.com> + * \author Ian Romanick <idr@us.ibm.com> + */ + +#ifndef DRI_INTERFACE_H +#define DRI_INTERFACE_H + +#include <GL/internal/glcore.h> +#include <drm.h> + +/** + * \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 - -libxephyr_hostx_a_SOURCES = \ - hostx.c \ - hostx.h + hostx.h \ + ephyr.h \ + ephyrlog.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 <martin@valinux.com> + * Jens Owen <jens@tungstengraphics.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +/* + * This file has been copied from the mesa source tree and a little bit + * modified by: + * + * Dodji Seketeli <dodji@openedhand.com> + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#ifdef XEPHYR_DRI + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_REPLIES +#include <X11/Xlibint.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include <GL/glx.h> +#include <X11/dri/xf86dri.h> +#include <X11/dri/xf86dristr.h> + +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 <stdio.h> +#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 2e0c00491..d5a3545f5 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -23,22 +23,32 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* TODO: - * - * o Support multiple screens, shouldn't be hard just alot of rejigging. - */ - #ifdef HAVE_CONFIG_H #include <kdrive-config.h> #endif #include "ephyr.h" #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; @@ -48,6 +58,7 @@ typedef struct _EphyrInputPrivate { Bool EphyrWantGrayScale = 0; + Bool ephyrInitialize (KdCardInfo *card, EphyrPriv *priv) { @@ -83,7 +94,7 @@ ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv) int width = 640, height = 480; unsigned long redMask, greenMask, blueMask; - if (hostx_want_screen_size(&width, &height) + if (hostx_want_screen_size(screen, &width, &height) || !screen->width || !screen->height) { screen->width = width; @@ -99,13 +110,13 @@ ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv) && (screen->fb[0].depth == 24 || screen->fb[0].depth == 16 || screen->fb[0].depth == 8)) { - hostx_set_server_depth(screen->fb[0].depth); + hostx_set_server_depth(screen, screen->fb[0].depth); } - else + else ErrorF("\nXephyr: requested screen depth not supported, setting to match hosts.\n"); } - screen->fb[0].depth = hostx_get_server_depth(); + screen->fb[0].depth = hostx_get_server_depth(screen); screen->rate = 72; if (screen->fb[0].depth <= 8) @@ -146,7 +157,7 @@ ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv) screen->fb[0].bitsPerPixel = 32; } - hostx_get_visual_masks (&redMask, &greenMask, &blueMask); + hostx_get_visual_masks (screen, &redMask, &greenMask, &blueMask); screen->fb[0].redMask = (Pixel) redMask; screen->fb[0].greenMask = (Pixel) greenMask; @@ -194,9 +205,7 @@ ephyrWindowLinear (ScreenPtr pScreen, EphyrPriv *priv = pScreenPriv->card->driver; if (!pScreenPriv->enabled) - { - return 0; - } + return 0; *size = priv->bytes_per_line; return priv->base + row * priv->bytes_per_line + offset; @@ -210,8 +219,8 @@ ephyrMapFramebuffer (KdScreenInfo *screen) KdPointerMatrix m; int buffer_height; - EPHYR_DBG(" screen->width: %d, screen->height: %d", - screen->width, screen->height); + EPHYR_LOG("screen->width: %d, screen->height: %d index=%d", + screen->width, screen->height, screen->mynum); KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); KdSetPointerMatrix (&m); @@ -226,8 +235,8 @@ ephyrMapFramebuffer (KdScreenInfo *screen) buffer_height = screen->height; else buffer_height = 3 * screen->height; - - priv->base = hostx_screen_init (screen->width, screen->height, buffer_height); + + priv->base = hostx_screen_init (screen, screen->width, screen->height, buffer_height); screen->memory_base = (CARD8 *) (priv->base); screen->memory_size = priv->bytes_per_line * buffer_height; @@ -246,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)); @@ -297,14 +306,14 @@ 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 * pBuf->pDamage regions */ shadowUpdateRotatePacked(pScreen, pBuf); - hostx_paint_rect(0,0,0,0, screen->width, screen->height); + hostx_paint_rect(screen, 0,0,0,0, screen->width, screen->height); } static void @@ -314,29 +323,29 @@ ephyrInternalDamageRedisplay (ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; EphyrScrPriv *scrpriv = screen->driver; RegionPtr pRegion; - + if (!scrpriv || !scrpriv->pDamage) return; - + pRegion = DamageRegion (scrpriv->pDamage); - + if (REGION_NOTEMPTY (pScreen, pRegion)) { int nbox; BoxPtr pbox; - + nbox = REGION_NUM_RECTS (pRegion); pbox = REGION_RECTS (pRegion); - + while (nbox--) - { - hostx_paint_rect(pbox->x1, pbox->y1, - pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - pbox++; - } - + { + hostx_paint_rect(screen, + pbox->x1, pbox->y1, + pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + pbox++; + } DamageEmpty (scrpriv->pDamage); } } @@ -411,7 +420,7 @@ ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) Rotation randr; int n = 0; - EPHYR_DBG("mark"); + EPHYR_LOG("mark"); struct { int width, height; } sizes[] = { @@ -432,11 +441,11 @@ ephyrRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { 160, 160 }, { 0, 0 } }; - + *rotations = RR_Rotate_All|RR_Reflect_All; - - if (!hostx_want_preexisting_window() - && !hostx_want_fullscreen()) /* only if no -parent switch */ + + if (!hostx_want_preexisting_window (screen) + && !hostx_want_fullscreen ()) /* only if no -parent switch */ { while (sizes[n].width != 0 && sizes[n].height != 0) { @@ -564,7 +573,7 @@ ephyrRandRSetConfig (ScreenPtr pScreen, return TRUE; bail4: - EPHYR_DBG("bailed"); + EPHYR_LOG("bailed"); ephyrUnmapFramebuffer (screen); *scrpriv = oldscr; @@ -586,9 +595,7 @@ ephyrRandRInit (ScreenPtr pScreen) rrScrPrivPtr pScrPriv; if (!RRScreenInit (pScreen)) - { - return FALSE; - } + return FALSE; pScrPriv = rrGetScrPriv(pScreen); pScrPriv->rrGetInfo = ephyrRandRGetInfo; @@ -606,7 +613,43 @@ ephyrCreateColormap (ColormapPtr pmap) Bool ephyrInitScreen (ScreenPtr pScreen) { + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + + 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; } @@ -618,12 +661,12 @@ ephyrFinishInitScreen (ScreenPtr pScreen) */ if (!shadowSetup (pScreen)) return FALSE; - + #ifdef RANDR if (!ephyrRandRInit (pScreen)) return FALSE; #endif - + return TRUE; } @@ -634,7 +677,8 @@ ephyrCreateResources (ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; EphyrScrPriv *scrpriv = screen->driver; - EPHYR_DBG("mark"); + EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d", + pScreen, pScreen->myNum, scrpriv->shadow); if (scrpriv->shadow) return KdShadowSet (pScreen, @@ -743,6 +787,56 @@ ephyrUpdateModifierState(unsigned int state) } } +static void +ephyrBlockSigio (void) +{ + sigset_t set; + + sigemptyset (&set); + sigaddset (&set, SIGIO); + sigprocmask (SIG_BLOCK, &set, 0); +} + +static void +ephyrUnblockSigio (void) +{ + sigset_t set; + + sigemptyset (&set); + sigaddset (&set, SIGIO); + sigprocmask (SIG_UNBLOCK, &set, 0); +} + +static Bool +ephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) +{ + return FALSE; +} + +static void +ephyrCrossScreen (ScreenPtr pScreen, Bool entering) +{ +} + +int ephyrCurScreen; /*current event screen*/ + +static void +ephyrWarpCursor (ScreenPtr pScreen, int x, int y) +{ + ephyrBlockSigio (); + ephyrCurScreen = pScreen->myNum; + miPointerWarpCursor (pScreen, x, y); + ephyrUnblockSigio (); +} + +miPointerScreenFuncRec ephyrPointerScreenFuncs = +{ + ephyrCursorOffScreen, + ephyrCrossScreen, + ephyrWarpCursor +}; + + void ephyrPoll(void) { @@ -751,21 +845,39 @@ ephyrPoll(void) while (hostx_get_event(&ev)) { switch (ev.type) - { - case EPHYR_EV_MOUSE_MOTION: + { + case EPHYR_EV_MOUSE_MOTION: if (!ephyrMouse || - !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) + !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) { + EPHYR_LOG ("skipping mouse motion:%d\n", ephyrCurScreen) ; continue; - KdEnqueuePointerEvent(ephyrMouse, mouseState, - ev.data.mouse_motion.x, - ev.data.mouse_motion.y, - 0); - break; - - case EPHYR_EV_MOUSE_PRESS: + } + { + if (ephyrCurScreen != ev.data.mouse_motion.screen) + { + 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_LOG ("enqueuing mouse motion:%d\n", ephyrCurScreen) ; + KdEnqueuePointerEvent(ephyrMouse, mouseState, + ev.data.mouse_motion.x, + ev.data.mouse_motion.y, + 0); + } + } + break; + + case EPHYR_EV_MOUSE_PRESS: if (!ephyrMouse || - !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) + !((EphyrPointerPrivate *)ephyrMouse->driverPrivate)->enabled) { + EPHYR_LOG ("skipping mouse press:%d\n", ephyrCurScreen) ; continue; + } + 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); @@ -777,6 +889,7 @@ ephyrPoll(void) continue; ephyrUpdateModifierState(ev.key_state); mouseState &= ~ev.data.mouse_up.button_num; + EPHYR_LOG ("enqueuing mouse release:%d\n", ephyrCurScreen) ; KdEnqueuePointerEvent(ephyrMouse, mouseState|KD_MOUSE_DELTA, 0, 0, 0); break; @@ -792,7 +905,6 @@ ephyrPoll(void) if (!ephyrKbd || !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) continue; - ephyrUpdateModifierState(ev.key_state); KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE); break; @@ -814,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--) { @@ -953,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 f49d920d1..8ed7e23dd 100644 --- a/hw/kdrive/ephyr/ephyr.h +++ b/hw/kdrive/ephyr/ephyr.h @@ -71,6 +71,8 @@ extern KdCardFuncs ephyrFuncs; extern KdKeyboardInfo *ephyrKbd; extern KdPointerInfo *ephyrMouse; +extern miPointerScreenFuncRec ephyrPointerScreenFuncs; + Bool ephyrInitialize (KdCardInfo *card, EphyrPriv *priv); @@ -192,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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#ifdef XEPHYR_DRI + +#include <X11/Xutil.h> +#include <X11/Xlibint.h> +/*#define _XF86DRI_SERVER_*/ +#include <GL/glx.h> +#include <X11/dri/xf86dri.h> +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ + +#ifndef __EPHYRDRI_H__ +#define __EPHYRDRI_H__ + +#include <xf86drm.h> + +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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#ifdef XEPHYR_DRI + +#include <string.h> + +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#define _XF86DRI_SERVER_ +#include <X11/dri/xf86dri.h> +#include <X11/dri/xf86dristr.h> +#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; i<screen->numDepths; 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; i<nb_visuals; i++) { + if (!EphyrDuplicateVisual (a_screen->myNum, + 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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include "extnsionst.h" +#include "ephyrglxext.h" +#include "ephyrhostglx.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include <GL/glxproto.h> +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#ifndef __EPHYR_GLXEXT_H__ +#define __EPHYR_GLXEXT_H__ + +#include <X11/Xdefs.h> +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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include <X11/Xlibint.h> +#include <GL/glx.h> +#include <GL/internal/glcore.h> +#include <GL/glxproto.h> +#include <GL/glxint.h> +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include <X11/Xlibint.h> +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ + +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include <X11/Xutil.h> +#include <X11/Xlibint.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/Xvproto.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#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; i<num_encodings; i++) { + encodings[i].id = encoding_info[i].encoding_id ; + encodings[i].name = strdup (encoding_info[i].name) ; + encodings[i].width = encoding_info[i].width ; + encodings[i].height = encoding_info[i].height ; + encodings[i].rate.numerator = encoding_info[i].rate.numerator ; + encodings[i].rate.denominator = encoding_info[i].rate.denominator ; + } + } + if (encoding_info) { + XvFreeEncodingInfo (encoding_info) ; + encoding_info = NULL ; + } + *a_encodings = encodings ; + *a_num_encodings = num_encodings ; + + if (ret != Success) + return FALSE ; + return TRUE ; +} + +void +ephyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, + int a_num_encodings) +{ + int i=0 ; + + if (!a_encodings) + return ; + for (i=0; i < a_num_encodings; i++) { + if (a_encodings[i].name) { + xfree (a_encodings[i].name) ; + a_encodings[i].name = NULL ; + } + } + xfree (a_encodings) ; +} + +void +ephyrHostAttributesDelete (EphyrHostAttribute *a_attributes) +{ + if (!a_attributes) + return ; + XFree (a_attributes) ; +} + +Bool +ephyrHostXVQueryPortAttributes (int a_port_id, + EphyrHostAttribute **a_attributes, + int *a_num_attributes) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_attributes && a_num_attributes, FALSE) ; + + *a_attributes = + (EphyrHostAttribute*)XvQueryPortAttributes (hostx_get_display (), + a_port_id, + a_num_attributes); + + return TRUE ; +} + +Bool +ephyrHostXVQueryImageFormats (int a_port_id, + EphyrHostImageFormat **a_formats, + int *a_num_format) +{ + XvImageFormatValues *result=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_formats && a_num_format, FALSE) ; + + result = XvListImageFormats (hostx_get_display (), + a_port_id, + a_num_format) ; + *a_formats = (EphyrHostImageFormat*) result ; + return TRUE ; + +} + +Bool +ephyrHostXVSetPortAttribute (int a_port_id, + int a_atom, + int a_attr_value) +{ + int res=Success ; + + EPHYR_LOG ("atom,name,value: (%d,%s,%d)\n", + a_atom, + XGetAtomName (hostx_get_display (), a_atom), + a_attr_value) ; + + res = XvSetPortAttribute (hostx_get_display (), + a_port_id, + a_atom, + a_attr_value) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvSetPortAttribute() failed: %d\n", res) ; + return FALSE ; + } + XFlush (hostx_get_display ()) ; + EPHYR_LOG ("leave\n") ; + + return TRUE ; +} + +Bool +ephyrHostXVGetPortAttribute (int a_port_id, + int a_atom, + int *a_attr_value) +{ + int res=Success ; + Bool ret=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_attr_value, FALSE) ; + + EPHYR_LOG ("enter, a_port_id: %d, a_atomid: %d, attr_name: %s\n", + a_port_id, a_atom, XGetAtomName (hostx_get_display (), a_atom)) ; + + res = XvGetPortAttribute (hostx_get_display (), + a_port_id, + a_atom, + a_attr_value) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetPortAttribute() failed: %d \n", res) ; + goto out ; + } + EPHYR_LOG ("atom,value: (%d, %d)\n", a_atom, *a_attr_value) ; + + ret = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return ret ; +} + +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) +{ + int res=0 ; + Bool is_ok=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_actual_w && a_actual_h, FALSE) ; + + EPHYR_LOG ("enter: frame (%dx%d), drw (%dx%d)\n", + a_frame_w, a_frame_h, + a_drw_w, a_drw_h) ; + + res = XvQueryBestSize (hostx_get_display (), + a_port_id, + a_motion, + a_frame_w, a_frame_h, + a_drw_w, a_drw_h, + a_actual_w, a_actual_h) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvQueryBestSize() failed: %d\n", res) ; + goto out ; + } + XSync (hostx_get_display (), FALSE) ; + + EPHYR_LOG ("actual (%dx%d)\n", *a_actual_w, *a_actual_h) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) +{ + XExtDisplayInfo *info = xv_find_display (dpy); + XvEvent *re = (XvEvent *)host; + xvEvent *event = (xvEvent *)wire; + + XvCheckExtension(dpy, info, False); + + switch ((event->u.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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#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 a76da03b4..6196996a9 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -27,12 +27,21 @@ #include <kdrive-config.h> #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 InitCard (char *name) { @@ -90,29 +99,74 @@ 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 <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("-verbosity <level> 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); } +void +processScreenArg (char *screen_size, char *parent_id) +{ + KdCardInfo *card; + + InitCard (0); /*Put each screen on a separate card*/ + card = KdCardInfoLast (); + + if (card) + { + KdScreenInfo *screen; + unsigned long p_id = 0; + + screen = KdScreenInfoAdd (card); + KdParseScreen (screen, screen_size); + + if (parent_id) + { + p_id = strtol (parent_id, NULL, 0); + } + EPHYR_DBG ("screen number:%d\n", screen->mynum) ; + hostx_add_screen (screen, p_id, screen->mynum); + } + else + { + ErrorF("No matching card found!\n"); + } +} + int ddxProcessArgument (int argc, char **argv, int i) { - EPHYR_DBG("mark"); + EPHYR_DBG("mark argv[%d]='%s'", i, argv[i] ); if (!strcmp (argv[i], "-parent")) { - if(i+1 < argc) + if(i+1 < argc) { - hostx_use_preexisting_window(strtol(argv[i+1], NULL, 0)); + processScreenArg ("100x100", argv[i+1]); return 2; - } - + } + + UseMsg(); + exit(1); + } + else if (!strcmp (argv[i], "-screen")) + { + if ((i+1) < argc) + { + processScreenArg (argv[i+1], NULL); + return 2; + } + UseMsg(); exit(1); } @@ -139,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]); @@ -198,8 +282,10 @@ miPointerSpriteFuncRec EphyrPointerSpriteFuncs = { Bool ephyrCursorInit(ScreenPtr pScreen) { - miPointerInitialize(pScreen, &EphyrPointerSpriteFuncs, - &kdPointerScreenFuncs, FALSE); + miPointerInitialize(pScreen, + &EphyrPointerSpriteFuncs, + &ephyrPointerScreenFuncs, + FALSE); return TRUE; } 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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#ifndef __EPHYRLOG_H__ +#define __EPHYRLOG_H__ + +#include <assert.h> +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ + +/* + * \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 <kdrive-config.h> +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ +#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 <mallum@openedhand.com> + * + * 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 <dodji@openedhand.com> + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include <string.h> +#include <X11/extensions/Xv.h> +#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 ; + +/************** + * <helpers> + * ************/ + +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 ; +} +*/ + +/************** + *</helpers> + * ************/ + +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 36d3cbd46..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 <kdrive-config.h> +#endif + #include "hostx.h" #include <stdlib.h> @@ -40,6 +44,17 @@ #include <X11/Xatom.h> #include <X11/keysym.h> #include <X11/extensions/XShm.h> +#include <X11/extensions/shape.h> +#ifdef XEPHYR_DRI +#include <GL/glx.h> +#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 . @@ -47,33 +62,44 @@ * to get clobbered. */ +struct EphyrHostScreen +{ + Window win; + Window win_pre_existing; /* Set via -parent option like xnest */ + XImage *ximg; + int win_width, win_height; + int server_depth; + unsigned char *fb_data; /* only used when host bpp != server bpp */ + XShmSegmentInfo shminfo; + + void *info; /* Pointer to the screen this is associated with */ + int mynum; /* Screen number */ +}; + struct EphyrHostXVars { char *server_dpy_name; Display *dpy; int screen; Visual *visual; - Window win, winroot; - Window win_pre_existing; /* Set via -parent option like xnest */ + Window winroot; GC gc; int depth; - int server_depth; - XImage *ximg; - int win_width, win_height; Bool use_host_cursor; Bool use_fullscreen; Bool have_shm; + int n_screens; + struct EphyrHostScreen *screens; + long damage_debug_msec; - unsigned char *fb_data; /* only used when host bpp != server bpp */ unsigned long cmap[256]; - - XShmSegmentInfo shminfo; }; /* memset ( missing> ) instead of below */ -static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +/*static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};*/ +static EphyrHostXVars HostX; static int HostXWantDamageDebug = 0; @@ -89,8 +115,22 @@ hostx_set_fullscreen_hint(void); static int trapped_error_code = 0; static int (*old_error_handler) (Display *d, XErrorEvent *e); -#define host_depth_matches_server() (HostX.depth == HostX.server_depth) +#define host_depth_matches_server(_vars) (HostX.depth == (_vars)->server_depth) +static struct EphyrHostScreen * +host_screen_from_screen_info (EphyrScreenInfo *screen) +{ + int i; + + for (i = 0 ; i < HostX.n_screens ; i++) + { + if ( HostX.screens[i].info == screen) + { + return &HostX.screens[i]; + } + } + return NULL; +} static int error_handler(Display *display, @@ -115,13 +155,16 @@ hostx_errors_untrap(void) } int -hostx_want_screen_size(int *width, int *height) +hostx_want_screen_size (EphyrScreenInfo screen, int *width, int *height ) { - if (HostX.win_pre_existing != None - || HostX.use_fullscreen == True) + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen && + (host_screen->win_pre_existing != None || + HostX.use_fullscreen == True)) { - *width = HostX.win_width; - *height = HostX.win_height; + *width = host_screen->win_width; + *height = host_screen->win_height; return 1; } @@ -129,100 +172,140 @@ hostx_want_screen_size(int *width, int *height) } void -hostx_set_display_name(char *name) +hostx_add_screen (EphyrScreenInfo screen, + unsigned long win_id, + int screen_num) +{ + int index = HostX.n_screens; + + HostX.n_screens += 1; + HostX.screens = realloc (HostX.screens, + HostX.n_screens * sizeof(struct EphyrHostScreen)); + memset (&HostX.screens[index], 0, sizeof (struct EphyrHostScreen)); + + HostX.screens[index].info = screen; + HostX.screens[index].win_pre_existing = win_id; +} + + +void +hostx_set_display_name (char *name) { - HostX.server_dpy_name = strdup(name); + HostX.server_dpy_name = strdup (name); } void -hostx_set_win_title(char *extra_text) +hostx_set_screen_number(EphyrScreenInfo screen, int number) { - char buf[256]; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + if (host_screen) { + host_screen->mynum = number; + hostx_set_win_title (host_screen->info, "") ; + }} - snprintf(buf, 256, "Xephyr on %s %s", - HostX.server_dpy_name, - (extra_text != NULL) ? extra_text : ""); +void +hostx_set_win_title (EphyrScreenInfo screen, char *extra_text) +{ + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); +#define BUF_LEN 256 + char buf[BUF_LEN+1]; + + if (!host_screen) + return; + + memset (buf, 0, BUF_LEN+1) ; + snprintf (buf, BUF_LEN, "Xephyr on %s.%d %s", + HostX.server_dpy_name, + host_screen->mynum, + (extra_text != NULL) ? extra_text : ""); - XStoreName(HostX.dpy, HostX.win, buf); + XStoreName (HostX.dpy, host_screen->win, buf); } int -hostx_want_host_cursor(void) +hostx_want_host_cursor (void) { return HostX.use_host_cursor; } void -hostx_use_host_cursor(void) +hostx_use_host_cursor (void) { HostX.use_host_cursor = True; } int -hostx_want_preexisting_window(void) +hostx_want_preexisting_window (EphyrScreenInfo screen) { - if (HostX.win_pre_existing) - return 1; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen && host_screen->win_pre_existing) + { + return 1; + } else + { return 0; + } } void -hostx_use_fullscreen(void) +hostx_use_fullscreen (void) { HostX.use_fullscreen = True; } int -hostx_want_fullscreen(void) +hostx_want_fullscreen (void) { return HostX.use_fullscreen; } static void -hostx_set_fullscreen_hint(void) +hostx_set_fullscreen_hint (void) { Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN; + int index; atom_WINDOW_STATE = XInternAtom(HostX.dpy, "_NET_WM_STATE", False); atom_WINDOW_STATE_FULLSCREEN = XInternAtom(HostX.dpy, "_NET_WM_STATE_FULLSCREEN",False); - XChangeProperty(HostX.dpy, HostX.win, - atom_WINDOW_STATE, XA_ATOM, 32, - PropModeReplace, - (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1); + for (index = 0 ; index < HostX.n_screens ; index++) + { + XChangeProperty (HostX.dpy, HostX.screens[index].win, + atom_WINDOW_STATE, XA_ATOM, 32, + PropModeReplace, + (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1); + } } -void -hostx_use_preexisting_window(unsigned long win_id) -{ - HostX.win_pre_existing = win_id; -} static void -hostx_toggle_damage_debug(void) +hostx_toggle_damage_debug (void) { HostXWantDamageDebug ^= 1; } -void -hostx_handle_signal(int signum) +void +hostx_handle_signal (int signum) { hostx_toggle_damage_debug(); - EPHYR_DBG("Signal caught. Damage Debug:%i\n", HostXWantDamageDebug); + EPHYR_DBG ("Signal caught. Damage Debug:%i\n", + HostXWantDamageDebug); } int -hostx_init(void) +hostx_init (void) { XSetWindowAttributes attr; Cursor empty_cursor; Pixmap cursor_pxm; XColor col; + int index; - attr.event_mask = + attr.event_mask = ButtonPressMask |ButtonReleaseMask |PointerMotionMask @@ -233,126 +316,142 @@ hostx_init(void) EPHYR_DBG("mark"); if ((HostX.dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) - { - fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n"); - exit(1); - } + { + fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n"); + exit(1); + } HostX.screen = DefaultScreen(HostX.dpy); HostX.winroot = RootWindow(HostX.dpy, HostX.screen); HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL); HostX.depth = DefaultDepth(HostX.dpy, HostX.screen); - HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); - - HostX.server_depth = HostX.depth; - - if (HostX.win_pre_existing != None) - { - Status result; - XWindowAttributes prewin_attr; + HostX.visual = DefaultVisual(HostX.dpy, HostX.screen); - /* Get screen size from existing window */ - - hostx_errors_trap(); - - result = XGetWindowAttributes(HostX.dpy, - HostX.win_pre_existing, - &prewin_attr); - - - if (hostx_errors_untrap() || !result) - { - fprintf(stderr, "\nXephyr -parent window' does not exist!\n"); - exit(1); - } - - HostX.win_width = prewin_attr.width; - HostX.win_height = prewin_attr.height; - - HostX.win = XCreateWindow(HostX.dpy, - HostX.win_pre_existing, - 0,0,HostX.win_width,HostX.win_height, - 0, - CopyFromParent, - CopyFromParent, - CopyFromParent, - CWEventMask, - &attr); - } - else + for (index = 0 ; index < HostX.n_screens ; index++) { - HostX.win = XCreateWindow(HostX.dpy, - HostX.winroot, - 0,0,100,100, /* will resize */ - 0, - CopyFromParent, - CopyFromParent, - CopyFromParent, - CWEventMask, - &attr); - - hostx_set_win_title("( ctrl+shift grabs mouse and keyboard )"); - - if (HostX.use_fullscreen) - { - HostX.win_width = DisplayWidth(HostX.dpy, HostX.screen); - HostX.win_height = DisplayHeight(HostX.dpy, HostX.screen); - - hostx_set_fullscreen_hint(); - } + struct EphyrHostScreen *host_screen = &HostX.screens[index]; + + host_screen->server_depth = HostX.depth; + if (host_screen->win_pre_existing != None) + { + Status result; + XWindowAttributes prewin_attr; + + /* Get screen size from existing window */ + + hostx_errors_trap(); + + result = XGetWindowAttributes (HostX.dpy, + host_screen->win_pre_existing, + &prewin_attr); + + + if (hostx_errors_untrap() || !result) + { + fprintf (stderr, "\nXephyr -parent window' does not exist!\n"); + exit (1); + } + + host_screen->win_width = prewin_attr.width; + host_screen->win_height = prewin_attr.height; + + host_screen->win = XCreateWindow (HostX.dpy, + host_screen->win_pre_existing, + 0,0, + host_screen->win_width, + host_screen->win_height, + 0, + CopyFromParent, + CopyFromParent, + CopyFromParent, + CWEventMask, + &attr); + } + else + { + host_screen->win = XCreateWindow (HostX.dpy, + HostX.winroot, + 0,0,100,100, /* will resize */ + 0, + CopyFromParent, + CopyFromParent, + CopyFromParent, + CWEventMask, + &attr); + + hostx_set_win_title (host_screen->info, + "(ctrl+shift grabs mouse and keyboard)"); + + if (HostX.use_fullscreen) + { + host_screen->win_width = DisplayWidth(HostX.dpy, HostX.screen); + host_screen->win_height = DisplayHeight(HostX.dpy, HostX.screen); + + hostx_set_fullscreen_hint(); + } + } } - XParseColor(HostX.dpy, DefaultColormap(HostX.dpy,HostX.screen), "red", &col); - XAllocColor(HostX.dpy, DefaultColormap(HostX.dpy, HostX.screen), &col); - XSetForeground(HostX.dpy, HostX.gc, col.pixel); + XParseColor (HostX.dpy, DefaultColormap (HostX.dpy,HostX.screen), + "red", &col); + XAllocColor (HostX.dpy, DefaultColormap (HostX.dpy, HostX.screen), + &col); + XSetForeground (HostX.dpy, HostX.gc, col.pixel); - if (!hostx_want_host_cursor()) + if (!hostx_want_host_cursor ()) { /* Ditch the cursor, we provide our 'own' */ cursor_pxm = XCreatePixmap (HostX.dpy, HostX.winroot, 1, 1, 1); memset (&col, 0, sizeof (col)); - empty_cursor = XCreatePixmapCursor (HostX.dpy, - cursor_pxm, cursor_pxm, - &col, &col, 1, 1); - XDefineCursor (HostX.dpy, HostX.win, empty_cursor); + empty_cursor = XCreatePixmapCursor (HostX.dpy, + cursor_pxm, cursor_pxm, + &col, &col, 1, 1); + for ( index = 0 ; index < HostX.n_screens ; index++ ) + { + XDefineCursor (HostX.dpy, + HostX.screens[index].win, + empty_cursor); + } XFreePixmap (HostX.dpy, cursor_pxm); } - HostX.ximg = NULL; - + for (index = 0 ; index < HostX.n_screens ; index++) + { + HostX.screens[index].ximg = NULL; + } /* Try to get share memory ximages for a little bit more speed */ - if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM")) + if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM")) { fprintf(stderr, "\nXephyr unable to use SHM XImages\n"); HostX.have_shm = False; - } - else - { + } + else + { /* Really really check we have shm - better way ?*/ - XShmSegmentInfo shminfo; + XShmSegmentInfo shminfo; - HostX.have_shm = True; + HostX.have_shm = True; - shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777); - shminfo.shmaddr=shmat(shminfo.shmid,0,0); - shminfo.readOnly=True; + shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777); + shminfo.shmaddr=shmat(shminfo.shmid,0,0); + shminfo.readOnly=True; - hostx_errors_trap(); - - XShmAttach(HostX.dpy, &shminfo); - XSync(HostX.dpy, False); + hostx_errors_trap(); - if (hostx_errors_untrap()) - { - fprintf(stderr, "\nXephyr unable to use SHM XImages\n"); - HostX.have_shm = False; - } + XShmAttach(HostX.dpy, &shminfo); + XSync(HostX.dpy, False); - shmdt(shminfo.shmaddr); - shmctl(shminfo.shmid, IPC_RMID, 0); - } + if (hostx_errors_untrap()) + { + fprintf(stderr, "\nXephyr unable to use SHM XImages\n"); + HostX.have_shm = False; + } + + shmdt(shminfo.shmaddr); + shmctl(shminfo.shmid, IPC_RMID, 0); +} XFlush(HostX.dpy); @@ -360,10 +459,10 @@ hostx_init(void) HostX.damage_debug_msec = 20000; /* 1/50 th of a second */ - if (getenv("XEPHYR_PAUSE")) + if (getenv ("XEPHYR_PAUSE")) { - HostX.damage_debug_msec = strtol(getenv("XEPHYR_PAUSE"), NULL, 0); - EPHYR_DBG("pause is %li\n", HostX.damage_debug_msec); + HostX.damage_debug_msec = strtol (getenv ("XEPHYR_PAUSE"), NULL, 0); + EPHYR_DBG ("pause is %li\n", HostX.damage_debug_msec); } return 1; @@ -376,38 +475,54 @@ hostx_get_depth (void) } int -hostx_get_server_depth (void) +hostx_get_server_depth (EphyrScreenInfo screen) { - return HostX.server_depth; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + return (host_screen ? host_screen->server_depth : 0); } void -hostx_set_server_depth(int depth) +hostx_set_server_depth (EphyrScreenInfo screen, int depth) { - HostX.server_depth = depth; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (host_screen) + host_screen->server_depth = depth; } int -hostx_get_bpp(void) +hostx_get_bpp (EphyrScreenInfo screen) { - if (host_depth_matches_server()) - return HostX.visual->bits_per_rgb; + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (!host_screen) + return 0; + + if (host_depth_matches_server (host_screen)) + return HostX.visual->bits_per_rgb; else - return HostX.server_depth; /* XXX correct ? */ + return host_screen->server_depth; /*XXX correct ?*/ } void -hostx_get_visual_masks (CARD32 *rmsk, - CARD32 *gmsk, +hostx_get_visual_masks (EphyrScreenInfo screen, + CARD32 *rmsk, + CARD32 *gmsk, CARD32 *bmsk) { - if (host_depth_matches_server()) + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + if (!host_screen) + return; + + if (host_depth_matches_server(host_screen)) { *rmsk = HostX.visual->red_mask; *gmsk = HostX.visual->green_mask; *bmsk = HostX.visual->blue_mask; } - else if (HostX.server_depth == 16) + else if (host_screen->server_depth == 16) { /* Assume 16bpp 565 */ *rmsk = 0xf800; @@ -423,9 +538,9 @@ hostx_get_visual_masks (CARD32 *rmsk, } void -hostx_set_cmap_entry(unsigned char idx, - unsigned char r, - unsigned char g, +hostx_set_cmap_entry(unsigned char idx, + unsigned char r, + unsigned char g, unsigned char b) { /* XXX Will likely break for 8 on 16, not sure if this is correct */ @@ -445,15 +560,25 @@ hostx_set_cmap_entry(unsigned char idx, * by fakexa for storing offscreen pixmap data. */ void* -hostx_screen_init (int width, int height, int buffer_height) +hostx_screen_init (EphyrScreenInfo screen, + int width, int height, + int buffer_height) { int bitmap_pad; Bool shm_success = False; XSizeHints *size_hints; - EPHYR_DBG("mark"); + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + if (!host_screen) + { + fprintf (stderr, "%s: Error in accessing hostx data\n", __func__ ); + exit(1); + } - if (HostX.ximg != NULL) + EPHYR_DBG ("host_screen=%p wxh=%dx%d, buffer_height=%d", + host_screen, width, height, buffer_height); + + if (host_screen->ximg != NULL) { /* Free up the image data if previously used * i.ie called by server reset @@ -461,47 +586,48 @@ hostx_screen_init (int width, int height, int buffer_height) if (HostX.have_shm) { - XShmDetach(HostX.dpy, &HostX.shminfo); - XDestroyImage (HostX.ximg); - shmdt(HostX.shminfo.shmaddr); - shmctl(HostX.shminfo.shmid, IPC_RMID, 0); + XShmDetach(HostX.dpy, &host_screen->shminfo); + XDestroyImage (host_screen->ximg); + shmdt(host_screen->shminfo.shmaddr); + shmctl(host_screen->shminfo.shmid, IPC_RMID, 0); } else { - if (HostX.ximg->data) + if (host_screen->ximg->data) { - free(HostX.ximg->data); - HostX.ximg->data = NULL; + free(host_screen->ximg->data); + host_screen->ximg->data = NULL; } - XDestroyImage(HostX.ximg); + XDestroyImage(host_screen->ximg); } } if (HostX.have_shm) { - HostX.ximg = XShmCreateImage(HostX.dpy, HostX.visual, HostX.depth, - ZPixmap, NULL, &HostX.shminfo, - width, buffer_height ); - - HostX.shminfo.shmid = shmget(IPC_PRIVATE, - HostX.ximg->bytes_per_line * buffer_height, - IPC_CREAT|0777); - HostX.shminfo.shmaddr = HostX.ximg->data = shmat(HostX.shminfo.shmid, - 0, 0); - - if (HostX.ximg->data == (char *)-1) + host_screen->ximg = XShmCreateImage (HostX.dpy, HostX.visual, HostX.depth, + ZPixmap, NULL, &host_screen->shminfo, + width, buffer_height ); + + host_screen->shminfo.shmid = + shmget(IPC_PRIVATE, + host_screen->ximg->bytes_per_line * buffer_height, + IPC_CREAT|0777); + host_screen->ximg->data = shmat(host_screen->shminfo.shmid, 0, 0); + host_screen->shminfo.shmaddr = host_screen->ximg->data; + + if (host_screen->ximg->data == (char *)-1) { EPHYR_DBG("Can't attach SHM Segment, falling back to plain XImages"); HostX.have_shm = False; - XDestroyImage(HostX.ximg); - shmctl(HostX.shminfo.shmid, IPC_RMID, 0); + XDestroyImage(host_screen->ximg); + shmctl(host_screen->shminfo.shmid, IPC_RMID, 0); } else { - EPHYR_DBG("SHM segment attached"); - HostX.shminfo.readOnly = False; - XShmAttach(HostX.dpy, &HostX.shminfo); + EPHYR_DBG("SHM segment attached %p", host_screen->shminfo.shmaddr); + host_screen->shminfo.readOnly = False; + XShmAttach(HostX.dpy, &host_screen->shminfo); shm_success = True; } } @@ -509,63 +635,74 @@ hostx_screen_init (int width, int height, int buffer_height) if (!shm_success) { bitmap_pad = ( HostX.depth > 16 )? 32 : (( HostX.depth > 8 )? 16 : 8 ); - - HostX.ximg = XCreateImage( HostX.dpy, - HostX.visual, - HostX.depth, - ZPixmap, 0, 0, - width, - buffer_height, - bitmap_pad, - 0); - HostX.ximg->data = malloc( HostX.ximg->bytes_per_line * buffer_height ); + EPHYR_DBG("Creating image %dx%d for screen host_screen=%p\n", + width, buffer_height, host_screen ); + host_screen->ximg = XCreateImage (HostX.dpy, + HostX.visual, + HostX.depth, + ZPixmap, 0, 0, + width, + buffer_height, + bitmap_pad, + 0); + + host_screen->ximg->data = + malloc (host_screen->ximg->bytes_per_line * buffer_height); } - - XResizeWindow(HostX.dpy, HostX.win, width, height); + XResizeWindow (HostX.dpy, host_screen->win, width, height); /* Ask the WM to keep our size static */ size_hints = XAllocSizeHints(); size_hints->max_width = size_hints->min_width = width; size_hints->max_height = size_hints->min_height = height; size_hints->flags = PMinSize|PMaxSize; - XSetWMNormalHints(HostX.dpy, HostX.win, size_hints); + XSetWMNormalHints(HostX.dpy, host_screen->win, size_hints); XFree(size_hints); - XMapWindow(HostX.dpy, HostX.win); + XMapWindow(HostX.dpy, host_screen->win); XSync(HostX.dpy, False); - HostX.win_width = width; - HostX.win_height = height; + host_screen->win_width = width; + host_screen->win_height = height; - if (host_depth_matches_server()) + if (host_depth_matches_server(host_screen)) { EPHYR_DBG("Host matches server"); - return HostX.ximg->data; + return host_screen->ximg->data; } else { - EPHYR_DBG("server bpp %i", HostX.server_depth>>3); - HostX.fb_data = malloc(width*buffer_height*(HostX.server_depth>>3)); - return HostX.fb_data; + EPHYR_DBG("server bpp %i", host_screen->server_depth>>3); + host_screen->fb_data = malloc(width*buffer_height*(host_screen->server_depth>>3)); + return host_screen->fb_data; } } +static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen, + int x, int y, + int width, int height); + void -hostx_paint_rect(int sx, int sy, - int dx, int dy, - int width, int height) +hostx_paint_rect (EphyrScreenInfo screen, + int sx, int sy, + int dx, int dy, + int width, int height) { - /* + struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen); + + EPHYR_DBG ("painting in screen %d\n", host_screen->mynum) ; + + /* * Copy the image data updated by the shadow layer * on to the window */ if (HostXWantDamageDebug) { - hostx_paint_debug_rect(dx, dy, width, height); + hostx_paint_debug_rect(host_screen, dx, dy, width, height); } /* @@ -580,22 +717,23 @@ hostx_paint_rect(int sx, int sy, * ... and it will be slower than the matching depth case. */ - if (!host_depth_matches_server()) + if (!host_depth_matches_server(host_screen)) { - int x,y,idx, bytes_per_pixel = (HostX.server_depth>>3); + int x,y,idx, bytes_per_pixel = (host_screen->server_depth>>3); unsigned char r,g,b; unsigned long host_pixel; + EPHYR_DBG("Unmatched host depth host_screen=%p\n", host_screen); for (y=sy; y<sy+height; y++) for (x=sx; x<sx+width; x++) { - idx = (HostX.win_width*y*bytes_per_pixel)+(x*bytes_per_pixel); - - switch (HostX.server_depth) + idx = (host_screen->win_width*y*bytes_per_pixel)+(x*bytes_per_pixel); + + switch (host_screen->server_depth) { case 16: { - unsigned short pixel = *(unsigned short*)(HostX.fb_data+idx); + unsigned short pixel = *(unsigned short*)(host_screen->fb_data+idx); r = ((pixel & 0xf800) >> 8); g = ((pixel & 0x07e0) >> 3); @@ -603,13 +741,13 @@ hostx_paint_rect(int sx, int sy, host_pixel = (r << 16) | (g << 8) | (b); - XPutPixel(HostX.ximg, x, y, host_pixel); + XPutPixel(host_screen->ximg, x, y, host_pixel); break; } case 8: { - unsigned char pixel = *(unsigned char*)(HostX.fb_data+idx); - XPutPixel(HostX.ximg, x, y, HostX.cmap[pixel]); + unsigned char pixel = *(unsigned char*)(host_screen->fb_data+idx); + XPutPixel(host_screen->ximg, x, y, HostX.cmap[pixel]); break; } default: @@ -620,21 +758,23 @@ hostx_paint_rect(int sx, int sy, if (HostX.have_shm) { - XShmPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, - sx, sy, dx, dy, width, height, False); + XShmPutImage (HostX.dpy, host_screen->win, + HostX.gc, host_screen->ximg, + sx, sy, dx, dy, width, height, False); } else { - XPutImage(HostX.dpy, HostX.win, HostX.gc, HostX.ximg, - sx, sy, dx, dy, width, height); + XPutImage (HostX.dpy, host_screen->win, HostX.gc, host_screen->ximg, + sx, sy, dx, dy, width, height); } - XSync(HostX.dpy, False); + XSync (HostX.dpy, False); } -void -hostx_paint_debug_rect(int x, int y, - int width, int height) +static void +hostx_paint_debug_rect (struct EphyrHostScreen *host_screen, + int x, int y, + int width, int height) { struct timespec tspec; @@ -646,8 +786,8 @@ hostx_paint_debug_rect(int x, int y, /* fprintf(stderr, "Xephyr updating: %i+%i %ix%i\n", x, y, width, height); */ - XFillRectangle(HostX.dpy, HostX.win, HostX.gc, x, y, width,height); - XSync(HostX.dpy, False); + XFillRectangle (HostX.dpy, host_screen->win, HostX.gc, x, y, width,height); + XSync (HostX.dpy, False); /* nanosleep seems to work better than usleep for me... */ nanosleep(&tspec, NULL); @@ -660,14 +800,14 @@ hostx_load_keymap(void) int host_width, min_keycode, max_keycode, width; int i,j; - XDisplayKeycodes(HostX.dpy, &min_keycode, &max_keycode); + XDisplayKeycodes (HostX.dpy, &min_keycode, &max_keycode); - EPHYR_DBG("min: %d, max: %d", min_keycode, max_keycode); + EPHYR_DBG ("min: %d, max: %d", min_keycode, max_keycode); - keymap = XGetKeyboardMapping(HostX.dpy, - min_keycode, - max_keycode - min_keycode + 1, - &host_width); + keymap = XGetKeyboardMapping (HostX.dpy, + min_keycode, + max_keycode - min_keycode + 1, + &host_width); /* Try and copy the hosts keymap into our keymap to avoid loads * of messing around. @@ -688,7 +828,7 @@ hostx_load_keymap(void) ephyrKeySyms.map[(i*width)+j] = (CARD32) keymap[(i*host_width) + j]; EPHYR_DBG("keymap width, host:%d kdrive:%d", host_width, width); - + ephyrKeySyms.minKeyCode = min_keycode; ephyrKeySyms.maxKeyCode = max_keycode; ephyrKeySyms.mapWidth = width; @@ -696,11 +836,26 @@ hostx_load_keymap(void) XFree(keymap); } +static struct EphyrHostScreen * +host_screen_from_window (Window w) +{ + int index; + + for (index = 0 ; index < HostX.n_screens ; index++) + { + if (HostX.screens[index].win == w) + { + return &HostX.screens[index]; + } + } + return NULL; +} + int hostx_get_event(EphyrHostXEvent *ev) { XEvent xev; - static Bool grabbed; + static int grabbed_screen = -1; if (XPending(HostX.dpy)) { @@ -710,15 +865,27 @@ hostx_get_event(EphyrHostXEvent *ev) { case Expose: /* Not so great event compression, but works ok */ - while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window, + while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window, Expose, &xev)); - hostx_paint_rect(0, 0, 0, 0, HostX.win_width, HostX.win_height); + { + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xexpose.window); + hostx_paint_rect (host_screen->info, 0, 0, 0, 0, + host_screen->win_width, + host_screen->win_height); + } return 0; case MotionNotify: - ev->type = EPHYR_EV_MOUSE_MOTION; - ev->data.mouse_motion.x = xev.xmotion.x; - ev->data.mouse_motion.y = xev.xmotion.y; + { + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xmotion.window); + + ev->type = EPHYR_EV_MOUSE_MOTION; + ev->data.mouse_motion.x = xev.xmotion.x; + ev->data.mouse_motion.y = xev.xmotion.y; + ev->data.mouse_motion.screen = (host_screen ? host_screen->mynum : -1); + } return 1; case ButtonPress: @@ -750,29 +917,35 @@ hostx_get_event(EphyrHostXEvent *ev) || XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_R) && (xev.xkey.state & ControlMask)) { - if (grabbed) + struct EphyrHostScreen *host_screen = + host_screen_from_window (xev.xexpose.window); + + if (grabbed_screen != -1) { XUngrabKeyboard (HostX.dpy, CurrentTime); XUngrabPointer (HostX.dpy, CurrentTime); - grabbed = False; - hostx_set_win_title("( ctrl+shift grabs mouse and keyboard )"); - } - else + grabbed_screen = -1; + hostx_set_win_title (host_screen->info, + "(ctrl+shift grabs mouse and keyboard)"); + } + else { /* Attempt grab */ - if (XGrabKeyboard (HostX.dpy, HostX.win, True, + if (XGrabKeyboard (HostX.dpy, host_screen->win, True, GrabModeAsync, GrabModeAsync, CurrentTime) == 0) { - if (XGrabPointer (HostX.dpy, HostX.win, True, + if (XGrabPointer (HostX.dpy, host_screen->win, True, NoEventMask, GrabModeAsync, GrabModeAsync, - HostX.win, None, CurrentTime) == 0) + host_screen->win, None, CurrentTime) == 0) { - grabbed = True; - hostx_set_win_title("( ctrl+shift releases mouse and keyboard )"); + grabbed_screen = host_screen->mynum; + hostx_set_win_title + (host_screen->info, + "(ctrl+shift releases mouse and keyboard)"); } else /* Failed pointer grabm ungrab keyboard */ XUngrabKeyboard (HostX.dpy, CurrentTime); @@ -798,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; i<nb_items; i++) { + host_visuals[i].visualid = visuals[i].visualid ; + host_visuals[i].screen = visuals[i].screen ; + host_visuals[i].depth = visuals[i].depth ; + host_visuals[i].class = visuals[i].class ; + host_visuals[i].red_mask = visuals[i].red_mask ; + host_visuals[i].green_mask = visuals[i].green_mask ; + host_visuals[i].blue_mask = visuals[i].blue_mask ; + host_visuals[i].colormap_size = visuals[i].colormap_size ; + host_visuals[i].bits_per_rgb = visuals[i].bits_per_rgb ; + } + *a_visuals = host_visuals ; + *a_num_entries = nb_items; + host_visuals=NULL; + + is_ok = TRUE; +out: + if (visuals) { + XFree (visuals) ; + visuals = NULL; + } + if (host_visuals) { + free (host_visuals) ; + host_visuals = NULL; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; + +} + +typedef struct { + int is_valid ; + int local_id ; + int remote_id ; +} ResourcePair ; + +#define RESOURCE_PEERS_SIZE 1024*10 +static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ; + + +int +hostx_create_window (int a_screen_number, + EphyrBox *a_geometry, + int a_visual_id, + int *a_host_peer /*out parameter*/) +{ + Bool is_ok=FALSE ; + Display *dpy=hostx_get_display () ; + XVisualInfo *visual_info=NULL, visual_info_templ; + int visual_mask=VisualIDMask ; + Window win=None ; + int nb_visuals=0, winmask=0; + XSetWindowAttributes attrs; + + EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geometry, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + /*get visual*/ + memset (&visual_info, 0, sizeof (visual_info)) ; + visual_info_templ.visualid = a_visual_id ; + visual_info = XGetVisualInfo (dpy, visual_mask, + &visual_info_templ, + &nb_visuals) ; + if (!visual_info) { + EPHYR_LOG_ERROR ("argh, could not find a remote visual with id:%d\n", + a_visual_id) ; + goto out ; + } + memset (&attrs, 0, sizeof (attrs)) ; + attrs.colormap = XCreateColormap (dpy, + RootWindow (dpy, + visual_info->screen), + 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; i<a_num_rects; i++) { + rects[i].x = a_rects[i].x1 ; + rects[i].y = a_rects[i].y1 ; + rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1); + rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ; + EPHYR_LOG ("borders clipped to rect[x:%d,y:%d,w:%d,h:%d]\n", + rects[i].x, rects[i].y, + rects[i].width, rects[i].height) ; + } + /*this aways returns 1*/ + XShapeCombineRectangles (dpy, a_window, ShapeBounding, 0, 0, + rects, a_num_rects, ShapeSet, YXBanded) ; + is_ok = TRUE ; + + if (rects) { + free (rects) ; + rects = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok; +} + +int +hostx_set_window_clipping_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; i<a_num_rects; i++) { + rects[i].x = a_rects[i].x1 ; + rects[i].y = a_rects[i].y1 ; + rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1); + rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ; + EPHYR_LOG ("clipped to rect[x:%d,y:%d,w:%d,h:%d]\n", + rects[i].x, rects[i].y, + rects[i].width, rects[i].height) ; + } + /*this aways returns 1*/ + XShapeCombineRectangles (dpy, a_window, ShapeClip, 0, 0, + rects, a_num_rects, ShapeSet, YXBanded) ; + is_ok = TRUE ; + + if (rects) { + free (rects) ; + rects = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok; +} + +int +hostx_has_xshape (void) +{ + int event_base=0, error_base=0 ; + Display *dpy=hostx_get_display () ; + if (!XShapeQueryExtension (dpy, + &event_base, + &error_base)) { + return FALSE ; + } + return TRUE; +} + +#ifdef XEPHYR_DRI +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + Display *dpy=hostx_get_display (); + + /* + * first make sure a resource peer + * does not exist already for + * a_local_resource_id + */ + for (i=0; i<RESOURCE_PEERS_SIZE; i++) { + if (resource_peers[i].is_valid + && resource_peers[i].local_id == a_local_resource_id) { + peer = &resource_peers[i] ; + break ; + } + } + /* + * find one free peer entry, an feed it with + */ + if (!peer) { + for (i=0; i<RESOURCE_PEERS_SIZE; i++) { + if (!resource_peers[i].is_valid) { + peer = &resource_peers[i] ; + break ; + } + } + if (peer) { + peer->remote_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; i<RESOURCE_PEERS_SIZE; i++) { + if (resource_peers[i].is_valid + && resource_peers[i].local_id == a_local_resource_id) { + peer = &resource_peers[i] ; + break ; + } + } + if (peer) { + *a_remote_resource_id = peer->remote_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 4d5f37f0a..3caa466a7 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -40,8 +40,8 @@ typedef struct EphyrHostXVars EphyrHostXVars; typedef struct EphyrHostXEvent EphyrHostXEvent; - -typedef enum EphyrHostXEventType +typedef void* EphyrScreenInfo ; +typedef enum EphyrHostXEventType { EPHYR_EV_MOUSE_MOTION, EPHYR_EV_MOUSE_PRESS, @@ -68,6 +68,7 @@ struct EphyrHostXEvent struct mouse_motion { int x; int y; + int screen; } mouse_motion; struct mouse_down { @@ -91,8 +92,34 @@ 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(int *width, int *height); +hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height); int hostx_want_host_cursor(void); @@ -107,7 +134,7 @@ int hostx_want_fullscreen(void); int -hostx_want_preexisting_window(void); +hostx_want_preexisting_window(EphyrScreenInfo screen); void hostx_use_preexisting_window(unsigned long win_id); @@ -119,25 +146,32 @@ int hostx_init(void); void +hostx_add_screen(EphyrScreenInfo screen, unsigned long win_id, int screen_num); + +void hostx_set_display_name(char *name); void -hostx_set_win_title(char *extra_text); +hostx_set_screen_number(EphyrScreenInfo screen, int number); + +void +hostx_set_win_title(EphyrScreenInfo screen, char *extra_text); int hostx_get_depth (void); int -hostx_get_server_depth (void); +hostx_get_server_depth (EphyrScreenInfo screen); void -hostx_set_server_depth(int depth); +hostx_set_server_depth(EphyrScreenInfo screen, int depth); int -hostx_get_bpp(void); +hostx_get_bpp(void *info); void -hostx_get_visual_masks (CARD32 *rmsk, +hostx_get_visual_masks (void *info, + CARD32 *rmsk, CARD32 *gmsk, CARD32 *bmsk); void @@ -147,20 +181,72 @@ hostx_set_cmap_entry(unsigned char idx, unsigned char b); void* -hostx_screen_init (int width, int height, int buffer_height); +hostx_screen_init (EphyrScreenInfo screen, + int width, int height, + int buffer_height); void -hostx_paint_rect(int sx, int sy, - int dx, int dy, +hostx_paint_rect(EphyrScreenInfo screen, + int sx, int sy, + int dx, int dy, int width, int height); -void -hostx_paint_debug_rect(int x, int y, - int width, int height); + 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 1a42495f3..4bf6e8858 100644 --- a/hw/kdrive/ephyr/os.c +++ b/hw/kdrive/ephyr/os.c @@ -28,9 +28,19 @@ #endif #include "ephyr.h" +extern void processScreenArg (char *screen_size, char *parent_id) ; + static int EphyrInit (void) { + /* + * make sure at least one screen + * has been added to the system. + */ + if (!KdCardInfoLast ()) + { + processScreenArg ("640x480", NULL) ; + } return hostx_init(); } 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..a6bfc0190 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,212 @@ 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; +} + +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); +} + +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"); + } + + matchDriverFromFiles(matches, info->vendor_id, info->device_id); + + /* TODO Handle multiple drivers claiming to support the same PCI ID */ + if (matches[0]) { + chosen_driver = matches[0]; + } else { + chosen_driver = videoPtrToDriverName(info); + #if 0 /* Save for later */ + #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 + #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..96fadc9dd 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__)) @@ -877,7 +877,7 @@ static OptionInfoRec FlagOptions[] = { {0}, FALSE }, }; -#if defined(i386) || defined(__i386__) +#ifdef __i386__ static Bool detectPC98(void) { @@ -1164,7 +1164,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 +1813,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 +1900,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 +1940,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 +2242,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 c31879ca3..574602f43 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 4b5105632..d796d627c 100644 --- a/hw/xfree86/common/xf86Globals.c +++ b/hw/xfree86/common/xf86Globals.c @@ -126,7 +126,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 9ff2da73a..b3cae2707 100644 --- a/hw/xfree86/common/xf86Init.c +++ b/hw/xfree86/common/xf86Init.c @@ -563,6 +563,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..75d497471 100644 --- a/hw/xfree86/common/xf86Privstr.h +++ b/hw/xfree86/common/xf86Privstr.h @@ -109,7 +109,7 @@ typedef struct { PciProbeType pciFlags; Pix24Flags pixmap24; MessageType pix24From; -#if defined(i386) || defined(__i386__) +#ifdef __i386__ Bool pc98; #endif Bool pmFlag; 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/dri/dri.c b/hw/xfree86/dri/dri.c index 84c0508bc..c35386354 100644 --- a/hw/xfree86/dri/dri.c +++ b/hw/xfree86/dri/dri.c @@ -953,7 +953,7 @@ static Bool DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) { DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - __GLXscreen *pGLXScreen = __glXgetActiveScreen(pScreen->myNum); + __GLXscreen *pGLXScreen = glxGetScreen(pScreen); __GLcontextModes *modes = pGLXScreen->modes; void **pVisualConfigPriv = pGLXScreen->pVisualPriv; DRIContextPrivPtr pDRIContextPriv; @@ -1017,7 +1017,7 @@ DRICreateContext(ScreenPtr pScreen, VisualPtr visual, XID context, drm_context_t * pHWContext) { DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - __GLXscreen *pGLXScreen = __glXgetActiveScreen(pScreen->myNum); + __GLXscreen *pGLXScreen = glxGetScreen(pScreen); __GLcontextModes *modes = pGLXScreen->modes; void **pVisualConfigPriv = pGLXScreen->pVisualPriv; DRIContextPrivPtr pDRIContextPriv; 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; + + mon = xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus); + xf86DDCApplyQuirks (scrn->scrnIndex, pDDCBus); - return xf86DoEDID_DDC2 (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..9fa5fef9e 100644 --- a/hw/xfree86/modes/xf86EdidModes.c +++ b/hw/xfree86/modes/xf86EdidModes.c @@ -54,6 +54,16 @@ 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, } ddc_quirk_t; static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) @@ -81,6 +91,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. */ @@ -106,6 +162,22 @@ 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." + }, { NULL, DDC_QUIRK_NONE, "No known quirks" @@ -303,6 +375,98 @@ 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) { @@ -312,15 +476,9 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) 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; @@ -357,32 +515,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/bus/ix86Pci.c b/hw/xfree86/os-support/bus/ix86Pci.c index 3ed4f1422..e54246355 100644 --- a/hw/xfree86/os-support/bus/ix86Pci.c +++ b/hw/xfree86/os-support/bus/ix86Pci.c @@ -188,8 +188,8 @@ static pciBusFuncs_t ix86Funcs0 = { /* pciReadLong */ ix86PciReadLongSetup, /* pciWriteLong */ ix86PciWriteLongSetup, /* pciSetBitsLong */ ix86PciSetBitsLongSetup, -#endif /* pciAddrHostToBus */ pciAddrNOOP, +#endif /* pciAddrBusToHost */ pciAddrNOOP }; @@ -198,8 +198,8 @@ static pciBusFuncs_t ix86Funcs1 = { /* pciReadLong */ ix86PciReadLongCFG1, /* pciWriteLong */ ix86PciWriteLongCFG1, /* pciSetBitsLong */ ix86PciSetBitsLongCFG1, -#endif /* pciAddrHostToBus */ pciAddrNOOP, +#endif /* pciAddrBusToHost */ pciAddrNOOP }; @@ -208,8 +208,8 @@ static pciBusFuncs_t ix86Funcs2 = { /* pciReadLong */ ix86PciReadLongCFG2, /* pciWriteLong */ ix86PciWriteLongCFG2, /* pciSetBitsLong */ ix86PciSetBitsLongCFG2, -#endif /* pciAddrHostToBus */ pciAddrNOOP, +#endif /* pciAddrBusToHost */ pciAddrNOOP }; @@ -223,6 +223,20 @@ static pciBusInfo_t ix86Pci0 = { /* bridge */ NULL }; +_X_EXPORT pointer +xf86MapDomainMemory(int ScreenNum, int Flags, struct pci_device *dev, + ADDRESS Base, unsigned long Size) +{ + return xf86MapVidMem(ScreenNum, Flags, Base, Size); +} + +IOADDRESS +xf86MapLegacyIO(struct pci_device *dev) +{ + (void)dev; + return 0; +} + static Bool ix86PciBusCheck(void) { diff --git a/hw/xfree86/os-support/shared/stdResource.c b/hw/xfree86/os-support/shared/stdResource.c index 7229d55b5..c144211f0 100644 --- a/hw/xfree86/os-support/shared/stdResource.c +++ b/hw/xfree86/os-support/shared/stdResource.c @@ -44,7 +44,7 @@ #include "bus/Pci.h" #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ - defined(__DragonFly__) + defined(__DragonFly__) || defined(__sun) #define xf86StdAccResFromOS xf86AccResFromOS #endif 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 <xorg-config.h> #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 <sys/kd.h> #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 <fb> 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 <sys/types.h> /* 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 <sys/sysi86.h> 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 <sys/v86.h> /* Nope */ # endif @@ -148,7 +148,7 @@ typedef signed long xf86ssize_t; # else # include <sys/v86.h> /* 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 <sys/psw.h> # 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/xorgcfg/Makefile.am b/hw/xfree86/utils/xorgcfg/Makefile.am index 309ed5c0a..e7113035f 100644 --- a/hw/xfree86/utils/xorgcfg/Makefile.am +++ b/hw/xfree86/utils/xorgcfg/Makefile.am @@ -33,7 +33,7 @@ INCLUDES = $(XORG_INCS) -I$(top_srcdir)/hw/xfree86/parser OPTIONSPATH=$(libdir)/X11 -xorgcfg_CFLAGS = $(XORG_CFLAGS) $(CURSESDEFINES) \ +xorgcfg_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(CURSESDEFINES) \ $(XORGCFG_DEP_CFLAGS) -DXKB_RULES_DIR=\"$(XKB_BASE_DIRECTORY)/rules\" \ -DPROJECT_ROOT=\"$(PROJECTROOT)\" -DOPTIONSPATH=\"$(OPTIONSPATH)\" xorgcfg_LDADD = $(XORGCFG_DEP_LIBS) ../../parser/libxf86config.a $(LOADERLIB) \ 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/include/dix-config.h.in b/include/dix-config.h.in index a091527f1..342d7417e 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -136,6 +136,9 @@ /* Define to 1 if you have the `getuid' function. */ #undef HAVE_GETUID +/* Define to 1 if you have the `getzoneid' function. */ +#undef HAVE_GETZONEID + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H @@ -181,6 +184,9 @@ /* Define to 1 if you have the <rpcsvc/dbm.h> 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 <stdint.h> header file. */ #undef HAVE_STDINT_H @@ -425,6 +431,8 @@ /* Support DRI extension */ #undef XF86DRI +#undef XEPHYR_DRI + /* Build DBE support */ #undef DBE diff --git a/include/dix.h b/include/dix.h index 59533bae7..09ed6d944 100644 --- a/include/dix.h +++ b/include/dix.h @@ -389,6 +389,9 @@ extern int DeliverDeviceEvents( extern void DefineInitialRootWindow( WindowPtr /* win */); +extern void UpdateSpriteForScreen( + ScreenPtr /* pScreen */); + extern void WindowHasNewCursor( WindowPtr /* pWin */); diff --git a/include/os.h b/include/os.h index 891f331c9..ac61992fe 100644 --- a/include/os.h +++ b/include/os.h @@ -323,6 +323,24 @@ extern int LocalClient(ClientPtr /* client */); extern int LocalClientCred(ClientPtr, int *, int *); +#define LCC_UID_SET (1 << 0) +#define LCC_GID_SET (1 << 1) +#define LCC_PID_SET (1 << 2) +#define LCC_ZID_SET (1 << 3) + +typedef struct { + int fieldsSet; /* Bit mask of fields set */ + int euid; /* Effective uid */ + int egid; /* Primary effective group id */ + int nSuppGids; /* Number of supplementary group ids */ + int *pSuppGids; /* Array of supplementary group ids */ + int pid; /* Process id */ + int zoneid; /* Only set on Solaris 10 & later */ +} LocalClientCredRec; + +extern int GetLocalClientCreds(ClientPtr, LocalClientCredRec **); +extern void FreeLocalClientCreds(LocalClientCredRec *); + extern int ChangeAccessControl(ClientPtr /*client*/, int /*fEnabled*/); extern int GetAccessControl(void); 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/mipointer.c b/mi/mipointer.c index 4d1db4fca..2c3c68913 100644 --- a/mi/mipointer.c +++ b/mi/mipointer.c @@ -255,6 +255,7 @@ miPointerWarpCursor (pScreen, x, y) miPointer.y = y; miPointer.pScreen = pScreen; } + UpdateSpriteForScreen (pScreen) ; } /* diff --git a/os/access.c b/os/access.c index 33b2eb6a7..e91dd37e4 100644 --- a/os/access.c +++ b/os/access.c @@ -119,10 +119,10 @@ SOFTWARE. # include <net/if.h> # endif #else -#if defined(SVR4) || (defined(SYSV) && defined(i386)) || defined(__GNU__) +#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__) # include <sys/utsname.h> #endif -#if defined(SYSV) && defined(i386) +#if defined(SYSV) && defined(__i386__) # include <sys/stream.h> # ifdef ISC # include <sys/stropts.h> @@ -234,10 +234,6 @@ static Bool NewHost(int /*family*/, int /*len*/, int /* addingLocalHosts */); -static int LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, - int **pSuppGids, int *nSuppGids); - - /* XFree86 bug #156: To keep track of which hosts were explicitly requested in /etc/X<display>.hosts, we've added a requested field to the HOST struct, and a LocalHostRequested variable. These default to FALSE, but are set @@ -1383,38 +1379,51 @@ _X_EXPORT Bool LocalClient(ClientPtr client) /* * Return the uid and gid of a connected local client - * or the uid/gid for nobody those ids cannot be determined * * Used by XShm to test access rights to shared memory segments */ int LocalClientCred(ClientPtr client, int *pUid, int *pGid) { - return LocalClientCredAndGroups(client, pUid, pGid, NULL, NULL); + LocalClientCredRec *lcc; + int ret = GetLocalClientCreds(client, &lcc); + + if (ret == 0) { +#ifdef HAVE_GETZONEID /* only local if in the same zone */ + if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { + FreeLocalClientCreds(lcc); + return -1; + } +#endif + if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL)) + *pUid = lcc->euid; + if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL)) + *pGid = lcc->egid; + FreeLocalClientCreds(lcc); + } + return ret; } /* * Return the uid and all gids of a connected local client - * or the uid/gid for nobody those ids cannot be determined + * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds * - * If the caller passes non-NULL values for pSuppGids & nSuppGids, - * they are responsible for calling XFree(*pSuppGids) to release the - * memory allocated for the supplemental group ids list. - * * Used by localuser & localgroup ServerInterpreted access control forms below + * Used by AuthAudit to log who local connections came from */ -static int -LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, - int **pSuppGids, int *nSuppGids) +int +GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp) { #if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED) int fd; XtransConnInfo ci; + LocalClientCredRec *lcc; #ifdef HAS_GETPEEREID uid_t uid; gid_t gid; #elif defined(HAS_GETPEERUCRED) ucred_t *peercred = NULL; + const gid_t *gids; #elif defined(SO_PEERCRED) struct ucred peercred; socklen_t so_len = sizeof(peercred); @@ -1433,57 +1442,65 @@ LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, } #endif - if (pSuppGids != NULL) - *pSuppGids = NULL; - if (nSuppGids != NULL) - *nSuppGids = 0; - + *lccp = Xcalloc(sizeof(LocalClientCredRec)); + if (*lccp == NULL) + return -1; + lcc = *lccp; + fd = _XSERVTransGetConnectionNumber(ci); #ifdef HAS_GETPEEREID - if (getpeereid(fd, &uid, &gid) == -1) - return -1; - if (pUid != NULL) - *pUid = uid; - if (pGid != NULL) - *pGid = gid; + if (getpeereid(fd, &uid, &gid) == -1) { + FreeLocalClientCreds(lcc); + return -1; + } + lcc->euid = uid; + lcc->egid = gid; + lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET; return 0; #elif defined(HAS_GETPEERUCRED) - if (getpeerucred(fd, &peercred) < 0) + if (getpeerucred(fd, &peercred) < 0) { + FreeLocalClientCreds(lcc); return -1; -#ifdef sun /* Ensure process is in the same zone */ - if (getzoneid() != ucred_getzoneid(peercred)) { - ucred_free(peercred); - return -1; } -#endif - if (pUid != NULL) - *pUid = ucred_geteuid(peercred); - if (pGid != NULL) - *pGid = ucred_getegid(peercred); - if (pSuppGids != NULL && nSuppGids != NULL) { - const gid_t *gids; - *nSuppGids = ucred_getgroups(peercred, &gids); - if (*nSuppGids > 0) { - *pSuppGids = xalloc(sizeof(int) * (*nSuppGids)); - if (*pSuppGids == NULL) { - *nSuppGids = 0; - } else { - int i; - for (i = 0 ; i < *nSuppGids; i++) { - (*pSuppGids)[i] = (int) gids[i]; - } + lcc->euid = ucred_geteuid(peercred); + if (lcc->euid != -1) + lcc->fieldsSet |= LCC_UID_SET; + lcc->egid = ucred_getegid(peercred); + if (lcc->egid != -1) + lcc->fieldsSet |= LCC_GID_SET; + lcc->pid = ucred_getpid(peercred); + if (lcc->pid != -1) + lcc->fieldsSet |= LCC_PID_SET; +#ifdef HAVE_GETZONEID + lcc->zoneid = ucred_getzoneid(peercred); + if (lcc->zoneid != -1) + lcc->fieldsSet |= LCC_ZID_SET; +#endif + lcc->nSuppGids = ucred_getgroups(peercred, &gids); + if (lcc->nSuppGids > 0) { + lcc->pSuppGids = Xcalloc((lcc->nSuppGids) * sizeof(int)); + if (lcc->pSuppGids == NULL) { + lcc->nSuppGids = 0; + } else { + int i; + for (i = 0 ; i < lcc->nSuppGids; i++) { + (lcc->pSuppGids)[i] = (int) gids[i]; } } + } else { + lcc->nSuppGids = 0; } ucred_free(peercred); return 0; #elif defined(SO_PEERCRED) - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) - return -1; - if (pUid != NULL) - *pUid = peercred.uid; - if (pGid != NULL) - *pGid = peercred.gid; + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) { + FreeLocalClientCreds(lcc); + return -1; + } + lcc->euid = peercred.uid; + lcc->egid = peercred.gid; + lcc->pid = peercred.pid; + lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET; return 0; #endif #else @@ -1493,6 +1510,17 @@ LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, #endif } +void +FreeLocalClientCreds(LocalClientCredRec *lcc) +{ + if (lcc != NULL) { + if (lcc->nSuppGids > 0) { + Xfree(lcc->pSuppGids); + } + Xfree(lcc); + } +} + static int AuthorizedClient(ClientPtr client) { @@ -2327,38 +2355,48 @@ static Bool siLocalCredAddrMatch(int family, pointer addr, int len, const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv) { - int connUid, connGid, *connSuppGids, connNumSuppGids, siAddrId; + int siAddrId; + LocalClientCredRec *lcc; siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv; - if (LocalClientCredAndGroups(client, &connUid, &connGid, - &connSuppGids, &connNumSuppGids) == -1) { + if (GetLocalClientCreds(client, &lcc) == -1) { return FALSE; } +#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */ + if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { + FreeLocalClientCreds(lcc); + return FALSE; + } +#endif + if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) { + FreeLocalClientCreds(lcc); return FALSE; } if (lcPriv->credType == LOCAL_USER) { - if (connUid == siAddrId) { + if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) { + FreeLocalClientCreds(lcc); return TRUE; } } else { - if (connGid == siAddrId) { + if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) { + FreeLocalClientCreds(lcc); return TRUE; } - if (connSuppGids != NULL) { + if (lcc->pSuppGids != NULL) { int i; - for (i = 0 ; i < connNumSuppGids; i++) { - if (connSuppGids[i] == siAddrId) { - xfree(connSuppGids); + for (i = 0 ; i < lcc->nSuppGids; i++) { + if (lcc->pSuppGids[i] == siAddrId) { + FreeLocalClientCreds(lcc); return TRUE; } } - xfree(connSuppGids); } } + FreeLocalClientCreds(lcc); return FALSE; } diff --git a/os/connection.c b/os/connection.c index 3d9d2e919..357878100 100644 --- a/os/connection.c +++ b/os/connection.c @@ -536,10 +536,8 @@ AuthAudit (ClientPtr client, Bool letin, char *out = addr; int client_uid; char client_uid_string[64]; -#ifdef HAS_GETPEERUCRED - ucred_t *peercred = NULL; -#endif -#if defined(HAS_GETPEERUCRED) || defined(XSERVER_DTRACE) + LocalClientCredRec *lcc; +#ifdef XSERVER_DTRACE pid_t client_pid = -1; zoneid_t client_zid = -1; #endif @@ -580,23 +578,50 @@ AuthAudit (ClientPtr client, Bool letin, strcpy(out, "unknown address"); } -#ifdef HAS_GETPEERUCRED - if (getpeerucred(((OsCommPtr)client->osPrivate)->fd, &peercred) >= 0) { - client_uid = ucred_geteuid(peercred); - client_pid = ucred_getpid(peercred); - client_zid = ucred_getzoneid(peercred); - - ucred_free(peercred); - snprintf(client_uid_string, sizeof(client_uid_string), - " (uid %ld, pid %ld, zone %ld)", - (long) client_uid, (long) client_pid, (long) client_zid); - } -#else - if (LocalClientCred(client, &client_uid, NULL) != -1) { - snprintf(client_uid_string, sizeof(client_uid_string), - " (uid %d)", client_uid); - } + if (GetLocalClientCreds(client, &lcc) != -1) { + int slen; /* length written to client_uid_string */ + + strcpy(client_uid_string, " ( "); + slen = 3; + + if (lcc->fieldsSet & LCC_UID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "uid=%ld ", (long) lcc->euid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_GID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "gid=%ld ", (long) lcc->egid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_PID_SET) { +#ifdef XSERVER_DTRACE + client_pid = lcc->pid; #endif + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "pid=%ld ", (long) lcc->pid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_ZID_SET) { +#ifdef XSERVER_DTRACE + client_zid = lcc->zoneid; +#endif + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "zoneid=%ld ", (long) lcc->zoneid); + slen = strlen(client_uid_string); + } + + snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, + ")"); + FreeLocalClientCreds(lcc); + } else { client_uid_string[0] = '\0'; } @@ -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} |