dri2_glx.c revision cdc920a0
1cdc920a0Smrg/* 2cdc920a0Smrg * Copyright © 2008 Red Hat, Inc. 3cdc920a0Smrg * 4cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5cdc920a0Smrg * copy of this software and associated documentation files (the "Soft- 6cdc920a0Smrg * ware"), to deal in the Software without restriction, including without 7cdc920a0Smrg * limitation the rights to use, copy, modify, merge, publish, distribute, 8cdc920a0Smrg * and/or sell copies of the Software, and to permit persons to whom the 9cdc920a0Smrg * Software is furnished to do so, provided that the above copyright 10cdc920a0Smrg * notice(s) and this permission notice appear in all copies of the Soft- 11cdc920a0Smrg * ware and that both the above copyright notice(s) and this permission 12cdc920a0Smrg * notice appear in supporting documentation. 13cdc920a0Smrg * 14cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16cdc920a0Smrg * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17cdc920a0Smrg * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18cdc920a0Smrg * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19cdc920a0Smrg * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20cdc920a0Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21cdc920a0Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22cdc920a0Smrg * MANCE OF THIS SOFTWARE. 23cdc920a0Smrg * 24cdc920a0Smrg * Except as contained in this notice, the name of a copyright holder shall 25cdc920a0Smrg * not be used in advertising or otherwise to promote the sale, use or 26cdc920a0Smrg * other dealings in this Software without prior written authorization of 27cdc920a0Smrg * the copyright holder. 28cdc920a0Smrg * 29cdc920a0Smrg * Authors: 30cdc920a0Smrg * Kristian Høgsberg (krh@redhat.com) 31cdc920a0Smrg */ 32cdc920a0Smrg 33cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 34cdc920a0Smrg 35cdc920a0Smrg#include <X11/Xlib.h> 36cdc920a0Smrg#include <X11/extensions/Xfixes.h> 37cdc920a0Smrg#include <X11/extensions/Xdamage.h> 38cdc920a0Smrg#include "glapi.h" 39cdc920a0Smrg#include "glxclient.h" 40cdc920a0Smrg#include <X11/extensions/dri2proto.h> 41cdc920a0Smrg#include "xf86dri.h" 42cdc920a0Smrg#include <dlfcn.h> 43cdc920a0Smrg#include <fcntl.h> 44cdc920a0Smrg#include <unistd.h> 45cdc920a0Smrg#include <sys/types.h> 46cdc920a0Smrg#include <sys/mman.h> 47cdc920a0Smrg#include "xf86drm.h" 48cdc920a0Smrg#include "dri2.h" 49cdc920a0Smrg#include "dri_common.h" 50cdc920a0Smrg#include "../../mesa/drivers/dri/common/dri_util.h" 51cdc920a0Smrg 52cdc920a0Smrg#undef DRI2_MINOR 53cdc920a0Smrg#define DRI2_MINOR 1 54cdc920a0Smrg 55cdc920a0Smrgtypedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate; 56cdc920a0Smrgtypedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate; 57cdc920a0Smrgtypedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate; 58cdc920a0Smrg 59cdc920a0Smrgstruct __GLXDRIdisplayPrivateRec 60cdc920a0Smrg{ 61cdc920a0Smrg __GLXDRIdisplay base; 62cdc920a0Smrg 63cdc920a0Smrg /* 64cdc920a0Smrg ** XFree86-DRI version information 65cdc920a0Smrg */ 66cdc920a0Smrg int driMajor; 67cdc920a0Smrg int driMinor; 68cdc920a0Smrg int driPatch; 69cdc920a0Smrg int swapAvailable; 70cdc920a0Smrg int invalidateAvailable; 71cdc920a0Smrg}; 72cdc920a0Smrg 73cdc920a0Smrgstruct __GLXDRIcontextPrivateRec 74cdc920a0Smrg{ 75cdc920a0Smrg __GLXDRIcontext base; 76cdc920a0Smrg __DRIcontext *driContext; 77cdc920a0Smrg __GLXscreenConfigs *psc; 78cdc920a0Smrg}; 79cdc920a0Smrg 80cdc920a0Smrgstruct __GLXDRIdrawablePrivateRec 81cdc920a0Smrg{ 82cdc920a0Smrg __GLXDRIdrawable base; 83cdc920a0Smrg __DRIbuffer buffers[5]; 84cdc920a0Smrg int bufferCount; 85cdc920a0Smrg int width, height; 86cdc920a0Smrg int have_back; 87cdc920a0Smrg int have_fake_front; 88cdc920a0Smrg int swap_interval; 89cdc920a0Smrg}; 90cdc920a0Smrg 91cdc920a0Smrgstatic void dri2WaitX(__GLXDRIdrawable * pdraw); 92cdc920a0Smrg 93cdc920a0Smrgstatic void 94cdc920a0Smrgdri2DestroyContext(__GLXDRIcontext * context, 95cdc920a0Smrg __GLXscreenConfigs * psc, Display * dpy) 96cdc920a0Smrg{ 97cdc920a0Smrg __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 98cdc920a0Smrg const __DRIcoreExtension *core = pcp->psc->core; 99cdc920a0Smrg 100cdc920a0Smrg (*core->destroyContext) (pcp->driContext); 101cdc920a0Smrg 102cdc920a0Smrg Xfree(pcp); 103cdc920a0Smrg} 104cdc920a0Smrg 105cdc920a0Smrgstatic Bool 106cdc920a0Smrgdri2BindContext(__GLXDRIcontext * context, 107cdc920a0Smrg __GLXDRIdrawable * draw, __GLXDRIdrawable * read) 108cdc920a0Smrg{ 109cdc920a0Smrg __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 110cdc920a0Smrg const __DRIcoreExtension *core = pcp->psc->core; 111cdc920a0Smrg 112cdc920a0Smrg return (*core->bindContext) (pcp->driContext, 113cdc920a0Smrg draw->driDrawable, read->driDrawable); 114cdc920a0Smrg} 115cdc920a0Smrg 116cdc920a0Smrgstatic void 117cdc920a0Smrgdri2UnbindContext(__GLXDRIcontext * context) 118cdc920a0Smrg{ 119cdc920a0Smrg __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context; 120cdc920a0Smrg const __DRIcoreExtension *core = pcp->psc->core; 121cdc920a0Smrg 122cdc920a0Smrg (*core->unbindContext) (pcp->driContext); 123cdc920a0Smrg} 124cdc920a0Smrg 125cdc920a0Smrgstatic __GLXDRIcontext * 126cdc920a0Smrgdri2CreateContext(__GLXscreenConfigs * psc, 127cdc920a0Smrg const __GLcontextModes * mode, 128cdc920a0Smrg GLXContext gc, GLXContext shareList, int renderType) 129cdc920a0Smrg{ 130cdc920a0Smrg __GLXDRIcontextPrivate *pcp, *pcp_shared; 131cdc920a0Smrg __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; 132cdc920a0Smrg __DRIcontext *shared = NULL; 133cdc920a0Smrg 134cdc920a0Smrg if (shareList) { 135cdc920a0Smrg pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext; 136cdc920a0Smrg shared = pcp_shared->driContext; 137cdc920a0Smrg } 138cdc920a0Smrg 139cdc920a0Smrg pcp = Xmalloc(sizeof *pcp); 140cdc920a0Smrg if (pcp == NULL) 141cdc920a0Smrg return NULL; 142cdc920a0Smrg 143cdc920a0Smrg pcp->psc = psc; 144cdc920a0Smrg pcp->driContext = 145cdc920a0Smrg (*psc->dri2->createNewContext) (psc->__driScreen, 146cdc920a0Smrg config->driConfig, shared, pcp); 147cdc920a0Smrg gc->__driContext = pcp->driContext; 148cdc920a0Smrg 149cdc920a0Smrg if (pcp->driContext == NULL) { 150cdc920a0Smrg Xfree(pcp); 151cdc920a0Smrg return NULL; 152cdc920a0Smrg } 153cdc920a0Smrg 154cdc920a0Smrg pcp->base.destroyContext = dri2DestroyContext; 155cdc920a0Smrg pcp->base.bindContext = dri2BindContext; 156cdc920a0Smrg pcp->base.unbindContext = dri2UnbindContext; 157cdc920a0Smrg 158cdc920a0Smrg return &pcp->base; 159cdc920a0Smrg} 160cdc920a0Smrg 161cdc920a0Smrgstatic void 162cdc920a0Smrgdri2DestroyDrawable(__GLXDRIdrawable * pdraw) 163cdc920a0Smrg{ 164cdc920a0Smrg const __DRIcoreExtension *core = pdraw->psc->core; 165cdc920a0Smrg 166cdc920a0Smrg (*core->destroyDrawable) (pdraw->driDrawable); 167cdc920a0Smrg DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->xDrawable); 168cdc920a0Smrg Xfree(pdraw); 169cdc920a0Smrg} 170cdc920a0Smrg 171cdc920a0Smrgstatic __GLXDRIdrawable * 172cdc920a0Smrgdri2CreateDrawable(__GLXscreenConfigs * psc, 173cdc920a0Smrg XID xDrawable, 174cdc920a0Smrg GLXDrawable drawable, const __GLcontextModes * modes) 175cdc920a0Smrg{ 176cdc920a0Smrg __GLXDRIdrawablePrivate *pdraw; 177cdc920a0Smrg __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; 178cdc920a0Smrg __GLXdisplayPrivate *dpyPriv; 179cdc920a0Smrg __GLXDRIdisplayPrivate *pdp; 180cdc920a0Smrg 181cdc920a0Smrg pdraw = Xmalloc(sizeof(*pdraw)); 182cdc920a0Smrg if (!pdraw) 183cdc920a0Smrg return NULL; 184cdc920a0Smrg 185cdc920a0Smrg pdraw->base.destroyDrawable = dri2DestroyDrawable; 186cdc920a0Smrg pdraw->base.xDrawable = xDrawable; 187cdc920a0Smrg pdraw->base.drawable = drawable; 188cdc920a0Smrg pdraw->base.psc = psc; 189cdc920a0Smrg pdraw->bufferCount = 0; 190cdc920a0Smrg pdraw->swap_interval = 1; 191cdc920a0Smrg pdraw->have_back = 0; 192cdc920a0Smrg 193cdc920a0Smrg DRI2CreateDrawable(psc->dpy, xDrawable); 194cdc920a0Smrg 195cdc920a0Smrg dpyPriv = __glXInitialize(psc->dpy); 196cdc920a0Smrg pdp = (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;; 197cdc920a0Smrg /* Create a new drawable */ 198cdc920a0Smrg pdraw->base.driDrawable = 199cdc920a0Smrg (*psc->dri2->createNewDrawable) (psc->__driScreen, 200cdc920a0Smrg config->driConfig, pdraw); 201cdc920a0Smrg 202cdc920a0Smrg if (!pdraw->base.driDrawable) { 203cdc920a0Smrg DRI2DestroyDrawable(psc->dpy, xDrawable); 204cdc920a0Smrg Xfree(pdraw); 205cdc920a0Smrg return NULL; 206cdc920a0Smrg } 207cdc920a0Smrg 208cdc920a0Smrg#ifdef X_DRI2SwapInterval 209cdc920a0Smrg /* 210cdc920a0Smrg * Make sure server has the same swap interval we do for the new 211cdc920a0Smrg * drawable. 212cdc920a0Smrg */ 213cdc920a0Smrg if (pdp->swapAvailable) 214cdc920a0Smrg DRI2SwapInterval(psc->dpy, xDrawable, pdraw->swap_interval); 215cdc920a0Smrg#endif 216cdc920a0Smrg 217cdc920a0Smrg return &pdraw->base; 218cdc920a0Smrg} 219cdc920a0Smrg 220cdc920a0Smrg#ifdef X_DRI2GetMSC 221cdc920a0Smrg 222cdc920a0Smrgstatic int 223cdc920a0Smrgdri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw, 224cdc920a0Smrg int64_t *ust, int64_t *msc, int64_t *sbc) 225cdc920a0Smrg{ 226cdc920a0Smrg return DRI2GetMSC(psc->dpy, pdraw->xDrawable, ust, msc, sbc); 227cdc920a0Smrg} 228cdc920a0Smrg 229cdc920a0Smrg#endif 230cdc920a0Smrg 231cdc920a0Smrg 232cdc920a0Smrg#ifdef X_DRI2WaitMSC 233cdc920a0Smrg 234cdc920a0Smrgstatic int 235cdc920a0Smrgdri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 236cdc920a0Smrg int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 237cdc920a0Smrg{ 238cdc920a0Smrg return DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 239cdc920a0Smrg remainder, ust, msc, sbc); 240cdc920a0Smrg} 241cdc920a0Smrg 242cdc920a0Smrgstatic int 243cdc920a0Smrgdri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 244cdc920a0Smrg int64_t *msc, int64_t *sbc) 245cdc920a0Smrg{ 246cdc920a0Smrg return DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, target_sbc, ust, msc, 247cdc920a0Smrg sbc); 248cdc920a0Smrg} 249cdc920a0Smrg 250cdc920a0Smrg#endif /* X_DRI2WaitMSC */ 251cdc920a0Smrg 252cdc920a0Smrgstatic void 253cdc920a0Smrgdri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) 254cdc920a0Smrg{ 255cdc920a0Smrg __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 256cdc920a0Smrg XRectangle xrect; 257cdc920a0Smrg XserverRegion region; 258cdc920a0Smrg 259cdc920a0Smrg /* Check we have the right attachments */ 260cdc920a0Smrg if (!priv->have_back) 261cdc920a0Smrg return; 262cdc920a0Smrg 263cdc920a0Smrg xrect.x = x; 264cdc920a0Smrg xrect.y = priv->height - y - height; 265cdc920a0Smrg xrect.width = width; 266cdc920a0Smrg xrect.height = height; 267cdc920a0Smrg 268cdc920a0Smrg#ifdef __DRI2_FLUSH 269cdc920a0Smrg if (pdraw->psc->f) 270cdc920a0Smrg (*pdraw->psc->f->flush) (pdraw->driDrawable); 271cdc920a0Smrg#endif 272cdc920a0Smrg 273cdc920a0Smrg region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 274cdc920a0Smrg /* should get a fence ID back from here at some point */ 275cdc920a0Smrg DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 276cdc920a0Smrg DRI2BufferFrontLeft, DRI2BufferBackLeft); 277cdc920a0Smrg XFixesDestroyRegion(pdraw->psc->dpy, region); 278cdc920a0Smrg 279cdc920a0Smrg /* Refresh the fake front (if present) after we just damaged the real 280cdc920a0Smrg * front. 281cdc920a0Smrg */ 282cdc920a0Smrg dri2WaitX(pdraw); 283cdc920a0Smrg} 284cdc920a0Smrg 285cdc920a0Smrgstatic void 286cdc920a0Smrgdri2WaitX(__GLXDRIdrawable *pdraw) 287cdc920a0Smrg{ 288cdc920a0Smrg __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 289cdc920a0Smrg XRectangle xrect; 290cdc920a0Smrg XserverRegion region; 291cdc920a0Smrg 292cdc920a0Smrg /* Check we have the right attachments */ 293cdc920a0Smrg if (!priv->have_fake_front) 294cdc920a0Smrg return; 295cdc920a0Smrg 296cdc920a0Smrg xrect.x = 0; 297cdc920a0Smrg xrect.y = 0; 298cdc920a0Smrg xrect.width = priv->width; 299cdc920a0Smrg xrect.height = priv->height; 300cdc920a0Smrg 301cdc920a0Smrg#ifdef __DRI2_FLUSH 302cdc920a0Smrg if (pdraw->psc->f) 303cdc920a0Smrg (*pdraw->psc->f->flush) (pdraw->driDrawable); 304cdc920a0Smrg#endif 305cdc920a0Smrg 306cdc920a0Smrg region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 307cdc920a0Smrg DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 308cdc920a0Smrg DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 309cdc920a0Smrg XFixesDestroyRegion(pdraw->psc->dpy, region); 310cdc920a0Smrg} 311cdc920a0Smrg 312cdc920a0Smrgstatic void 313cdc920a0Smrgdri2WaitGL(__GLXDRIdrawable * pdraw) 314cdc920a0Smrg{ 315cdc920a0Smrg __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 316cdc920a0Smrg XRectangle xrect; 317cdc920a0Smrg XserverRegion region; 318cdc920a0Smrg 319cdc920a0Smrg if (!priv->have_fake_front) 320cdc920a0Smrg return; 321cdc920a0Smrg 322cdc920a0Smrg xrect.x = 0; 323cdc920a0Smrg xrect.y = 0; 324cdc920a0Smrg xrect.width = priv->width; 325cdc920a0Smrg xrect.height = priv->height; 326cdc920a0Smrg 327cdc920a0Smrg#ifdef __DRI2_FLUSH 328cdc920a0Smrg if (pdraw->psc->f) 329cdc920a0Smrg (*pdraw->psc->f->flush) (pdraw->driDrawable); 330cdc920a0Smrg#endif 331cdc920a0Smrg 332cdc920a0Smrg region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1); 333cdc920a0Smrg DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region, 334cdc920a0Smrg DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 335cdc920a0Smrg XFixesDestroyRegion(pdraw->psc->dpy, region); 336cdc920a0Smrg} 337cdc920a0Smrg 338cdc920a0Smrgstatic void 339cdc920a0Smrgdri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) 340cdc920a0Smrg{ 341cdc920a0Smrg __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 342cdc920a0Smrg __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy); 343cdc920a0Smrg __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display; 344cdc920a0Smrg 345cdc920a0Smrg /* Old servers don't send invalidate events */ 346cdc920a0Smrg if (!pdp->invalidateAvailable) 347cdc920a0Smrg dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable); 348cdc920a0Smrg 349cdc920a0Smrg dri2WaitGL(loaderPrivate); 350cdc920a0Smrg} 351cdc920a0Smrg 352cdc920a0Smrg 353cdc920a0Smrgstatic void 354cdc920a0Smrgdri2DestroyScreen(__GLXscreenConfigs * psc) 355cdc920a0Smrg{ 356cdc920a0Smrg /* Free the direct rendering per screen data */ 357cdc920a0Smrg (*psc->core->destroyScreen) (psc->__driScreen); 358cdc920a0Smrg close(psc->fd); 359cdc920a0Smrg psc->__driScreen = NULL; 360cdc920a0Smrg} 361cdc920a0Smrg 362cdc920a0Smrg/** 363cdc920a0Smrg * Process list of buffer received from the server 364cdc920a0Smrg * 365cdc920a0Smrg * Processes the list of buffers received in a reply from the server to either 366cdc920a0Smrg * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 367cdc920a0Smrg */ 368cdc920a0Smrgstatic void 369cdc920a0Smrgprocess_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, 370cdc920a0Smrg unsigned count) 371cdc920a0Smrg{ 372cdc920a0Smrg int i; 373cdc920a0Smrg 374cdc920a0Smrg pdraw->bufferCount = count; 375cdc920a0Smrg pdraw->have_fake_front = 0; 376cdc920a0Smrg pdraw->have_back = 0; 377cdc920a0Smrg 378cdc920a0Smrg /* This assumes the DRI2 buffer attachment tokens matches the 379cdc920a0Smrg * __DRIbuffer tokens. */ 380cdc920a0Smrg for (i = 0; i < count; i++) { 381cdc920a0Smrg pdraw->buffers[i].attachment = buffers[i].attachment; 382cdc920a0Smrg pdraw->buffers[i].name = buffers[i].name; 383cdc920a0Smrg pdraw->buffers[i].pitch = buffers[i].pitch; 384cdc920a0Smrg pdraw->buffers[i].cpp = buffers[i].cpp; 385cdc920a0Smrg pdraw->buffers[i].flags = buffers[i].flags; 386cdc920a0Smrg if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 387cdc920a0Smrg pdraw->have_fake_front = 1; 388cdc920a0Smrg if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 389cdc920a0Smrg pdraw->have_back = 1; 390cdc920a0Smrg } 391cdc920a0Smrg 392cdc920a0Smrg} 393cdc920a0Smrg 394cdc920a0Smrgstatic int64_t 395cdc920a0Smrgdri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 396cdc920a0Smrg int64_t remainder) 397cdc920a0Smrg{ 398cdc920a0Smrg __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 399cdc920a0Smrg __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy); 400cdc920a0Smrg __GLXDRIdisplayPrivate *pdp = 401cdc920a0Smrg (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; 402cdc920a0Smrg int64_t ret; 403cdc920a0Smrg 404cdc920a0Smrg#ifdef __DRI2_FLUSH 405cdc920a0Smrg if (pdraw->psc->f) 406cdc920a0Smrg (*pdraw->psc->f->flush)(pdraw->driDrawable); 407cdc920a0Smrg#endif 408cdc920a0Smrg 409cdc920a0Smrg /* Old servers don't send invalidate events */ 410cdc920a0Smrg if (!pdp->invalidateAvailable) 411cdc920a0Smrg dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable); 412cdc920a0Smrg 413cdc920a0Smrg /* Old servers can't handle swapbuffers */ 414cdc920a0Smrg if (!pdp->swapAvailable) { 415cdc920a0Smrg dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); 416cdc920a0Smrg return 0; 417cdc920a0Smrg } 418cdc920a0Smrg 419cdc920a0Smrg#ifdef X_DRI2SwapBuffers 420cdc920a0Smrg DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 421cdc920a0Smrg remainder, &ret); 422cdc920a0Smrg#endif 423cdc920a0Smrg 424cdc920a0Smrg return ret; 425cdc920a0Smrg} 426cdc920a0Smrg 427cdc920a0Smrgstatic __DRIbuffer * 428cdc920a0Smrgdri2GetBuffers(__DRIdrawable * driDrawable, 429cdc920a0Smrg int *width, int *height, 430cdc920a0Smrg unsigned int *attachments, int count, 431cdc920a0Smrg int *out_count, void *loaderPrivate) 432cdc920a0Smrg{ 433cdc920a0Smrg __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 434cdc920a0Smrg DRI2Buffer *buffers; 435cdc920a0Smrg 436cdc920a0Smrg buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 437cdc920a0Smrg width, height, attachments, count, out_count); 438cdc920a0Smrg if (buffers == NULL) 439cdc920a0Smrg return NULL; 440cdc920a0Smrg 441cdc920a0Smrg pdraw->width = *width; 442cdc920a0Smrg pdraw->height = *height; 443cdc920a0Smrg process_buffers(pdraw, buffers, *out_count); 444cdc920a0Smrg 445cdc920a0Smrg Xfree(buffers); 446cdc920a0Smrg 447cdc920a0Smrg return pdraw->buffers; 448cdc920a0Smrg} 449cdc920a0Smrg 450cdc920a0Smrgstatic __DRIbuffer * 451cdc920a0Smrgdri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 452cdc920a0Smrg int *width, int *height, 453cdc920a0Smrg unsigned int *attachments, int count, 454cdc920a0Smrg int *out_count, void *loaderPrivate) 455cdc920a0Smrg{ 456cdc920a0Smrg __GLXDRIdrawablePrivate *pdraw = loaderPrivate; 457cdc920a0Smrg DRI2Buffer *buffers; 458cdc920a0Smrg 459cdc920a0Smrg buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 460cdc920a0Smrg pdraw->base.xDrawable, 461cdc920a0Smrg width, height, attachments, 462cdc920a0Smrg count, out_count); 463cdc920a0Smrg if (buffers == NULL) 464cdc920a0Smrg return NULL; 465cdc920a0Smrg 466cdc920a0Smrg pdraw->width = *width; 467cdc920a0Smrg pdraw->height = *height; 468cdc920a0Smrg process_buffers(pdraw, buffers, *out_count); 469cdc920a0Smrg 470cdc920a0Smrg Xfree(buffers); 471cdc920a0Smrg 472cdc920a0Smrg return pdraw->buffers; 473cdc920a0Smrg} 474cdc920a0Smrg 475cdc920a0Smrg#ifdef X_DRI2SwapInterval 476cdc920a0Smrg 477cdc920a0Smrgstatic void 478cdc920a0Smrgdri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 479cdc920a0Smrg{ 480cdc920a0Smrg __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 481cdc920a0Smrg 482cdc920a0Smrg DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval); 483cdc920a0Smrg priv->swap_interval = interval; 484cdc920a0Smrg} 485cdc920a0Smrg 486cdc920a0Smrgstatic unsigned int 487cdc920a0Smrgdri2GetSwapInterval(__GLXDRIdrawable *pdraw) 488cdc920a0Smrg{ 489cdc920a0Smrg __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; 490cdc920a0Smrg 491cdc920a0Smrg return priv->swap_interval; 492cdc920a0Smrg} 493cdc920a0Smrg 494cdc920a0Smrg#endif /* X_DRI2SwapInterval */ 495cdc920a0Smrg 496cdc920a0Smrgstatic const __DRIdri2LoaderExtension dri2LoaderExtension = { 497cdc920a0Smrg {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 498cdc920a0Smrg dri2GetBuffers, 499cdc920a0Smrg dri2FlushFrontBuffer, 500cdc920a0Smrg dri2GetBuffersWithFormat, 501cdc920a0Smrg}; 502cdc920a0Smrg 503cdc920a0Smrgstatic const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 504cdc920a0Smrg {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 505cdc920a0Smrg dri2GetBuffers, 506cdc920a0Smrg dri2FlushFrontBuffer, 507cdc920a0Smrg NULL, 508cdc920a0Smrg}; 509cdc920a0Smrg 510cdc920a0Smrgstatic const __DRIextension *loader_extensions[] = { 511cdc920a0Smrg &dri2LoaderExtension.base, 512cdc920a0Smrg &systemTimeExtension.base, 513cdc920a0Smrg NULL 514cdc920a0Smrg}; 515cdc920a0Smrg 516cdc920a0Smrgstatic const __DRIextension *loader_extensions_old[] = { 517cdc920a0Smrg &dri2LoaderExtension_old.base, 518cdc920a0Smrg &systemTimeExtension.base, 519cdc920a0Smrg NULL 520cdc920a0Smrg}; 521cdc920a0Smrg 522cdc920a0Smrg_X_HIDDEN void 523cdc920a0Smrgdri2InvalidateBuffers(Display *dpy, XID drawable) 524cdc920a0Smrg{ 525cdc920a0Smrg __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); 526cdc920a0Smrg 527cdc920a0Smrg#if __DRI2_FLUSH_VERSION >= 3 528cdc920a0Smrg if (pdraw && pdraw->psc->f) 529cdc920a0Smrg pdraw->psc->f->invalidate(pdraw->driDrawable); 530cdc920a0Smrg#endif 531cdc920a0Smrg} 532cdc920a0Smrg 533cdc920a0Smrgstatic __GLXDRIscreen * 534cdc920a0Smrgdri2CreateScreen(__GLXscreenConfigs * psc, int screen, 535cdc920a0Smrg __GLXdisplayPrivate * priv) 536cdc920a0Smrg{ 537cdc920a0Smrg const __DRIconfig **driver_configs; 538cdc920a0Smrg const __DRIextension **extensions; 539cdc920a0Smrg const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *) 540cdc920a0Smrg priv->dri2Display; 541cdc920a0Smrg __GLXDRIscreen *psp; 542cdc920a0Smrg char *driverName, *deviceName; 543cdc920a0Smrg drm_magic_t magic; 544cdc920a0Smrg int i; 545cdc920a0Smrg 546cdc920a0Smrg psp = Xmalloc(sizeof *psp); 547cdc920a0Smrg if (psp == NULL) 548cdc920a0Smrg return NULL; 549cdc920a0Smrg 550cdc920a0Smrg if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen), 551cdc920a0Smrg &driverName, &deviceName)) { 552cdc920a0Smrg XFree(psp); 553cdc920a0Smrg return NULL; 554cdc920a0Smrg } 555cdc920a0Smrg 556cdc920a0Smrg psc->driver = driOpenDriver(driverName); 557cdc920a0Smrg if (psc->driver == NULL) { 558cdc920a0Smrg ErrorMessageF("driver pointer missing\n"); 559cdc920a0Smrg goto handle_error; 560cdc920a0Smrg } 561cdc920a0Smrg 562cdc920a0Smrg extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 563cdc920a0Smrg if (extensions == NULL) { 564cdc920a0Smrg ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 565cdc920a0Smrg goto handle_error; 566cdc920a0Smrg } 567cdc920a0Smrg 568cdc920a0Smrg for (i = 0; extensions[i]; i++) { 569cdc920a0Smrg if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 570cdc920a0Smrg psc->core = (__DRIcoreExtension *) extensions[i]; 571cdc920a0Smrg if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 572cdc920a0Smrg psc->dri2 = (__DRIdri2Extension *) extensions[i]; 573cdc920a0Smrg } 574cdc920a0Smrg 575cdc920a0Smrg if (psc->core == NULL || psc->dri2 == NULL) { 576cdc920a0Smrg ErrorMessageF("core dri or dri2 extension not found\n"); 577cdc920a0Smrg goto handle_error; 578cdc920a0Smrg } 579cdc920a0Smrg 580cdc920a0Smrg psc->fd = open(deviceName, O_RDWR); 581cdc920a0Smrg if (psc->fd < 0) { 582cdc920a0Smrg ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 583cdc920a0Smrg goto handle_error; 584cdc920a0Smrg } 585cdc920a0Smrg 586cdc920a0Smrg if (drmGetMagic(psc->fd, &magic)) { 587cdc920a0Smrg ErrorMessageF("failed to get magic\n"); 588cdc920a0Smrg goto handle_error; 589cdc920a0Smrg } 590cdc920a0Smrg 591cdc920a0Smrg if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { 592cdc920a0Smrg ErrorMessageF("failed to authenticate magic %d\n", magic); 593cdc920a0Smrg goto handle_error; 594cdc920a0Smrg } 595cdc920a0Smrg 596cdc920a0Smrg /* If the server does not support the protocol for 597cdc920a0Smrg * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 598cdc920a0Smrg */ 599cdc920a0Smrg psc->__driScreen = 600cdc920a0Smrg psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1) 601cdc920a0Smrg ? loader_extensions_old 602cdc920a0Smrg : loader_extensions), 603cdc920a0Smrg &driver_configs, psc); 604cdc920a0Smrg 605cdc920a0Smrg if (psc->__driScreen == NULL) { 606cdc920a0Smrg ErrorMessageF("failed to create dri screen\n"); 607cdc920a0Smrg goto handle_error; 608cdc920a0Smrg } 609cdc920a0Smrg 610cdc920a0Smrg driBindCommonExtensions(psc); 611cdc920a0Smrg dri2BindExtensions(psc); 612cdc920a0Smrg 613cdc920a0Smrg psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs); 614cdc920a0Smrg psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs); 615cdc920a0Smrg 616cdc920a0Smrg psc->driver_configs = driver_configs; 617cdc920a0Smrg 618cdc920a0Smrg psp->destroyScreen = dri2DestroyScreen; 619cdc920a0Smrg psp->createContext = dri2CreateContext; 620cdc920a0Smrg psp->createDrawable = dri2CreateDrawable; 621cdc920a0Smrg psp->swapBuffers = dri2SwapBuffers; 622cdc920a0Smrg psp->waitGL = dri2WaitGL; 623cdc920a0Smrg psp->waitX = dri2WaitX; 624cdc920a0Smrg psp->getDrawableMSC = NULL; 625cdc920a0Smrg psp->waitForMSC = NULL; 626cdc920a0Smrg psp->waitForSBC = NULL; 627cdc920a0Smrg psp->setSwapInterval = NULL; 628cdc920a0Smrg psp->getSwapInterval = NULL; 629cdc920a0Smrg 630cdc920a0Smrg if (pdp->driMinor >= 2) { 631cdc920a0Smrg#ifdef X_DRI2GetMSC 632cdc920a0Smrg psp->getDrawableMSC = dri2DrawableGetMSC; 633cdc920a0Smrg#endif 634cdc920a0Smrg#ifdef X_DRI2WaitMSC 635cdc920a0Smrg psp->waitForMSC = dri2WaitForMSC; 636cdc920a0Smrg psp->waitForSBC = dri2WaitForSBC; 637cdc920a0Smrg#endif 638cdc920a0Smrg#ifdef X_DRI2SwapInterval 639cdc920a0Smrg psp->setSwapInterval = dri2SetSwapInterval; 640cdc920a0Smrg psp->getSwapInterval = dri2GetSwapInterval; 641cdc920a0Smrg#endif 642cdc920a0Smrg#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 643cdc920a0Smrg __glXEnableDirectExtension(psc, "GLX_OML_sync_control"); 644cdc920a0Smrg#endif 645cdc920a0Smrg } 646cdc920a0Smrg 647cdc920a0Smrg /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 648cdc920a0Smrg * available.*/ 649cdc920a0Smrg psp->copySubBuffer = dri2CopySubBuffer; 650cdc920a0Smrg __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); 651cdc920a0Smrg 652cdc920a0Smrg Xfree(driverName); 653cdc920a0Smrg Xfree(deviceName); 654cdc920a0Smrg 655cdc920a0Smrg return psp; 656cdc920a0Smrg 657cdc920a0Smrghandle_error: 658cdc920a0Smrg Xfree(driverName); 659cdc920a0Smrg Xfree(deviceName); 660cdc920a0Smrg XFree(psp); 661cdc920a0Smrg 662cdc920a0Smrg /* FIXME: clean up here */ 663cdc920a0Smrg 664cdc920a0Smrg return NULL; 665cdc920a0Smrg} 666cdc920a0Smrg 667cdc920a0Smrg/* Called from __glXFreeDisplayPrivate. 668cdc920a0Smrg */ 669cdc920a0Smrgstatic void 670cdc920a0Smrgdri2DestroyDisplay(__GLXDRIdisplay * dpy) 671cdc920a0Smrg{ 672cdc920a0Smrg Xfree(dpy); 673cdc920a0Smrg} 674cdc920a0Smrg 675cdc920a0Smrg/* 676cdc920a0Smrg * Allocate, initialize and return a __DRIdisplayPrivate object. 677cdc920a0Smrg * This is called from __glXInitialize() when we are given a new 678cdc920a0Smrg * display pointer. 679cdc920a0Smrg */ 680cdc920a0Smrg_X_HIDDEN __GLXDRIdisplay * 681cdc920a0Smrgdri2CreateDisplay(Display * dpy) 682cdc920a0Smrg{ 683cdc920a0Smrg __GLXDRIdisplayPrivate *pdp; 684cdc920a0Smrg int eventBase, errorBase; 685cdc920a0Smrg 686cdc920a0Smrg if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 687cdc920a0Smrg return NULL; 688cdc920a0Smrg 689cdc920a0Smrg pdp = Xmalloc(sizeof *pdp); 690cdc920a0Smrg if (pdp == NULL) 691cdc920a0Smrg return NULL; 692cdc920a0Smrg 693cdc920a0Smrg if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 694cdc920a0Smrg Xfree(pdp); 695cdc920a0Smrg return NULL; 696cdc920a0Smrg } 697cdc920a0Smrg 698cdc920a0Smrg pdp->driPatch = 0; 699cdc920a0Smrg pdp->swapAvailable = (pdp->driMinor >= 2); 700cdc920a0Smrg pdp->invalidateAvailable = (pdp->driMinor >= 3); 701cdc920a0Smrg 702cdc920a0Smrg pdp->base.destroyDisplay = dri2DestroyDisplay; 703cdc920a0Smrg pdp->base.createScreen = dri2CreateScreen; 704cdc920a0Smrg 705cdc920a0Smrg return &pdp->base; 706cdc920a0Smrg} 707cdc920a0Smrg 708cdc920a0Smrg#endif /* GLX_DIRECT_RENDERING */ 709