dri2_glx.c revision 441344ba7ed2a1d162ee33ac4bac4bf645188ceb
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/* 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Copyright © 2008 Red Hat, Inc. 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Permission is hereby granted, free of charge, to any person obtaining a 55f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * copy of this software and associated documentation files (the "Soft- 65f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * ware"), to deal in the Software without restriction, including without 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * limitation the rights to use, copy, modify, merge, publish, distribute, 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * and/or sell copies of the Software, and to permit persons to whom the 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Software is furnished to do so, provided that the above copyright 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * notice(s) and this permission notice appear in all copies of the Soft- 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * ware and that both the above copyright notice(s) and this permission 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * notice appear in supporting documentation. 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * MANCE OF THIS SOFTWARE. 235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * 245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Except as contained in this notice, the name of a copyright holder shall 255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * not be used in advertising or otherwise to promote the sale, use or 265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * other dealings in this Software without prior written authorization of 275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * the copyright holder. 285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * 295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Authors: 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Kristian Høgsberg (krh@redhat.com) 315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer */ 325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <X11/Xlib.h> 365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <X11/extensions/Xfixes.h> 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <X11/extensions/Xdamage.h> 385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "glapi.h" 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "glxclient.h" 405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <X11/extensions/dri2proto.h> 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "xf86dri.h" 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <dlfcn.h> 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <fcntl.h> 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <unistd.h> 455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/types.h> 465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <sys/mman.h> 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "xf86drm.h" 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "dri2.h" 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "dri_common.h" 505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/* From xmlpool/options.h, user exposed so should be stable */ 525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#define DRI_CONF_VBLANK_NEVER 0 535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#undef DRI2_MINOR 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#define DRI2_MINOR 1 595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstruct dri2_display 615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __GLXDRIdisplay base; 635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer /* 655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ** XFree86-DRI version information 665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer */ 675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int driMajor; 685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int driMinor; 695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int driPatch; 705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int swapAvailable; 715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int invalidateAvailable; 725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __glxHashTable *dri2Hash; 745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const __DRIextension *loader_extensions[4]; 765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}; 7768d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff 7868d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroffstruct dri2_screen { 7968d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff struct glx_screen base; 8068d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff 8168d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff __DRIscreen *driScreen; 8268d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff __GLXDRIscreen vtable; 8368d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff const __DRIdri2Extension *dri2; 8429238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff const __DRIcoreExtension *core; 8568d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff 865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const __DRI2flushExtension *f; 875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const __DRI2configQueryExtension *config; 885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const __DRItexBufferExtension *texBuffer; 895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const __DRIconfig **driver_configs; 905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer void *driver; 925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int fd; 935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}; 945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstruct dri2_context 965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct glx_context base; 985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __DRIcontext *driContext; 995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}; 1005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstruct dri2_drawable 1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __GLXDRIdrawable base; 1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __DRIdrawable *driDrawable; 1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __DRIbuffer buffers[5]; 1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int bufferCount; 1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int width, height; 1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int have_back; 1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int have_fake_front; 1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int swap_interval; 1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}; 1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic const struct glx_context_vtable dri2_context_vtable; 1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2_destroy_context(struct glx_context *context) 1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_context *pcp = (struct dri2_context *) context; 1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_screen *psc = (struct dri2_screen *) context->psc; 120cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner 121cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner driReleaseDrawables(&pcp->base); 122cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner 123cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner if (context->xid) 1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer glx_send_destroy_context(psc->base.dpy, context->xid); 1255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (context->extensions) 1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer XFree((char *) context->extensions); 1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (*psc->core->destroyContext) (pcp->driContext); 1305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1319594acf32de2939b15eafa8fe818607bfc56bf66Chris Lattner Xfree(pcp); 1329594acf32de2939b15eafa8fe818607bfc56bf66Chris Lattner} 1339594acf32de2939b15eafa8fe818607bfc56bf66Chris Lattner 1349594acf32de2939b15eafa8fe818607bfc56bf66Chris Lattnerstatic Bool 1359594acf32de2939b15eafa8fe818607bfc56bf66Chris Lattnerdri2_bind_context(struct glx_context *context, struct glx_context *old, 1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer GLXDrawable draw, GLXDrawable read) 1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_context *pcp = (struct dri2_context *) context; 1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; 1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_drawable *pdraw, *pread; 1415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw = (struct dri2_drawable *) driFetchDrawable(context, draw); 1435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pread = (struct dri2_drawable *) driFetchDrawable(context, read); 1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (pdraw == NULL || pread == NULL) 1465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return GLXBadDrawable; 1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if ((*psc->core->bindContext) (pcp->driContext, 14929238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff pdraw->driDrawable, pread->driDrawable)) 15068d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff return Success; 1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return GLXBadContext; 1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2_unbind_context(struct glx_context *context, struct glx_context *new) 1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_context *pcp = (struct dri2_context *) context; 1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; 1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (*psc->core->unbindContext) (pcp->driContext); 1625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (context == new) 1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer driReleaseDrawables(&pcp->base); 1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic struct glx_context * 1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2_create_context(struct glx_screen *base, 1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct glx_config *config_base, 1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct glx_context *shareList, int renderType) 1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_context *pcp, *pcp_shared; 1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_screen *psc = (struct dri2_screen *) base; 1745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 1755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __DRIcontext *shared = NULL; 1765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (shareList) { 1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pcp_shared = (struct dri2_context *) shareList; 1795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer shared = pcp_shared->driContext; 1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 182cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner pcp = Xmalloc(sizeof *pcp); 183cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner if (pcp == NULL) 184cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner return NULL; 185cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner 186cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner memset(pcp, 0, sizeof *pcp); 187cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner if (!glx_context_init(&pcp->base, &psc->base, &config->base)) { 188cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner Xfree(pcp); 189cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner return NULL; 190cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner } 191cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner 1925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pcp->driContext = 1935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (*psc->dri2->createNewContext) (psc->driScreen, 1945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer config->driConfig, shared, pcp); 1955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (pcp->driContext == NULL) { 1975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Xfree(pcp); 1985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return NULL; 1995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pcp->base.vtable = &dri2_context_vtable; 2025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &pcp->base; 2045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2DestroyDrawable(__GLXDRIdrawable *base) 2085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 2095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_screen *psc = (struct dri2_screen *) base->psc; 2105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 2115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct glx_display *dpyPriv = psc->base.display; 2125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_display *pdp = (struct dri2_display *)dpyPriv->dri2Display; 2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __glxHashDelete(pdp->dri2Hash, pdraw->base.xDrawable); 2155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (*psc->core->destroyDrawable) (pdraw->driDrawable); 2165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer /* If it's a GLX 1.3 drawables, we can destroy the DRI2 drawable 2185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * now, as the application explicitly asked to destroy the GLX 219d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner * drawable. Otherwise, for legacy drawables, we let the DRI2 2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * drawable linger on the server, since there's no good way of 2215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * knowing when the application is done with it. The server will 2225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * destroy the DRI2 drawable when it destroys the X drawable or the 2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * client exits anyway. */ 2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (pdraw->base.xDrawable != pdraw->base.drawable) 2255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2DestroyDrawable(psc->base.dpy, pdraw->base.xDrawable); 226d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 2275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Xfree(pdraw); 2285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic __GLXDRIdrawable * 2315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2CreateDrawable(struct glx_screen *base, XID xDrawable, 2325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer GLXDrawable drawable, struct glx_config *config_base) 2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_drawable *pdraw; 235d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner struct dri2_screen *psc = (struct dri2_screen *) base; 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base; 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct glx_display *dpyPriv; 2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_display *pdp; 2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw = Xmalloc(sizeof(*pdraw)); 2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (!pdraw) 2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return NULL; 2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 245d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner memset(pdraw, 0, sizeof *pdraw); 2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->base.destroyDrawable = dri2DestroyDrawable; 2475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->base.xDrawable = xDrawable; 2485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->base.drawable = drawable; 2495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->base.psc = &psc->base; 2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->bufferCount = 0; 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->swap_interval = 1; /* default may be overridden below */ 2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->have_back = 0; 253d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (psc->config) 2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer psc->config->configQueryi(psc->driScreen, 2565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer "vblank_mode", &vblank_mode); 2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer switch (vblank_mode) { 2595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case DRI_CONF_VBLANK_NEVER: 2605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case DRI_CONF_VBLANK_DEF_INTERVAL_0: 2615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->swap_interval = 0; 2625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case DRI_CONF_VBLANK_DEF_INTERVAL_1: 2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer case DRI_CONF_VBLANK_ALWAYS_SYNC: 265d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner default: 2665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->swap_interval = 1; 2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer break; 2685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 269d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2CreateDrawable(psc->base.dpy, xDrawable); 2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 272d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner dpyPriv = __glXInitialize(psc->base.dpy); 2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdp = (struct dri2_display *)dpyPriv->dri2Display;; 2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer /* Create a new drawable */ 2755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->driDrawable = 2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (*psc->dri2->createNewDrawable) (psc->driScreen, 2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer config->driConfig, pdraw); 2785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (!pdraw->driDrawable) { 2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2DestroyDrawable(psc->base.dpy, xDrawable); 281d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner Xfree(pdraw); 2825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return NULL; 2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (__glxHashInsert(pdp->dri2Hash, xDrawable, pdraw)) { 2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (*psc->core->destroyDrawable) (pdraw->driDrawable); 2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2DestroyDrawable(psc->base.dpy, xDrawable); 2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer Xfree(pdraw); 2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return None; 2905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 293d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner#ifdef X_DRI2SwapInterval 2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer /* 2955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Make sure server has the same swap interval we do for the new 2965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * drawable. 2975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer */ 2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (pdp->swapAvailable) 2995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2SwapInterval(psc->base.dpy, xDrawable, pdraw->swap_interval); 3005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif 3015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &pdraw->base; 3035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 304d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 3055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#ifdef X_DRI2GetMSC 3065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 30797ba77cf09bf7b83b679165ce67ad7d49ffd568cChris Lattnerstatic int 30897ba77cf09bf7b83b679165ce67ad7d49ffd568cChris Lattnerdri2DrawableGetMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw, 30997ba77cf09bf7b83b679165ce67ad7d49ffd568cChris Lattner int64_t *ust, int64_t *msc, int64_t *sbc) 31097ba77cf09bf7b83b679165ce67ad7d49ffd568cChris Lattner{ 3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CARD64 dri2_ust, dri2_msc, dri2_sbc; 3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int ret; 3135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ret = DRI2GetMSC(psc->dpy, pdraw->xDrawable, 3155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer &dri2_ust, &dri2_msc, &dri2_sbc); 3165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *ust = dri2_ust; 3175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *msc = dri2_msc; 3185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *sbc = dri2_sbc; 3195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ret; 3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif 3245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#ifdef X_DRI2WaitMSC 3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 330d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 3325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CARD64 dri2_ust, dri2_msc, dri2_sbc; 3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int ret; 3345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ret = DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer remainder, &dri2_ust, &dri2_msc, &dri2_sbc); 337d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner *ust = dri2_ust; 3385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *msc = dri2_msc; 3395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *sbc = dri2_sbc; 3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ret; 3425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 344d217773f106856a11879ec79dc468efefaf2ee75Chris Lattnerstatic int 3455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 3465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t *msc, int64_t *sbc) 3475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 3485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer CARD64 dri2_ust, dri2_msc, dri2_sbc; 349d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner int ret; 3505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ret = DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, 3525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer target_sbc, &dri2_ust, &dri2_msc, &dri2_sbc); 3535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *ust = dri2_ust; 3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer *msc = dri2_msc; 355d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner *sbc = dri2_sbc; 3565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return ret; 3585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif /* X_DRI2WaitMSC */ 3615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 3635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) 3645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 3655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 3665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc; 3675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer XRectangle xrect; 3685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer XserverRegion region; 369d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 3705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer /* Check we have the right attachments */ 3715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (!priv->have_back) 3725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return; 3735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer xrect.x = x; 3755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer xrect.y = priv->height - y - height; 3765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer xrect.width = width; 3775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer xrect.height = height; 3785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#ifdef __DRI2_FLUSH 3805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (psc->f) 3815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (*psc->f->flush) (priv->driDrawable); 3825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif 3835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); 3855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, 3865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2BufferFrontLeft, DRI2BufferBackLeft); 3875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer /* Refresh the fake front (if present) after we just damaged the real 3895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * front. 3905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer */ 3915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (priv->have_fake_front) 3925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, 3935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 3945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer XFixesDestroyRegion(psc->base.dpy, region); 3965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 3995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2_copy_drawable(struct dri2_drawable *priv, int dest, int src) 4005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 4015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer XRectangle xrect; 4025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer XserverRegion region; 4035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 4045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 405d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner xrect.x = 0; 4065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer xrect.y = 0; 4075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer xrect.width = priv->width; 4085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer xrect.height = priv->height; 4095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#ifdef __DRI2_FLUSH 4115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (psc->f) 4125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (*psc->f->flush) (priv->driDrawable); 4135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif 4145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 415d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); 4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer DRI2CopyRegion(psc->base.dpy, priv->base.xDrawable, region, dest, src); 4175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer XFixesDestroyRegion(psc->base.dpy, region); 4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 419d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner} 4205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 4225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2_wait_x(struct glx_context *gc) 4235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 424d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner struct dri2_drawable *priv = (struct dri2_drawable *) 4255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 4265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (priv == NULL || !priv->have_fake_front) 4285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return; 4295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer dri2_copy_drawable(priv, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 4315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 4345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2_wait_gl(struct glx_context *gc) 4355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_drawable *priv = (struct dri2_drawable *) 437f1c99acc544a4e70f308db4e7200ca04cd5a06d2Chris Lattner GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 4385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (priv == NULL || !priv->have_fake_front) 4405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return; 4415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer dri2_copy_drawable(priv, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 4435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 4445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 4465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) 4475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 4485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_drawable *pdraw = loaderPrivate; 4495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct glx_display *priv = __glXInitialize(pdraw->base.psc->dpy); 4505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct dri2_display *pdp = (struct dri2_display *)priv->dri2Display; 4515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer struct glx_context *gc = __glXGetCurrentContext(); 452d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 453d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner /* Old servers don't send invalidate events */ 4545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (!pdp->invalidateAvailable) 4555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer dri2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable); 456d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 4575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer dri2_wait_gl(gc); 4585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 459d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 460d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 4615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 4625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerdri2DestroyScreen(struct glx_screen *base) 463d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner{ 464d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner struct dri2_screen *psc = (struct dri2_screen *) base; 465d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 466d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner /* Free the direct rendering per screen data */ 467d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner (*psc->core->destroyScreen) (psc->driScreen); 4685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer driDestroyConfigs(psc->driver_configs); 4695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer close(psc->fd); 470d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner Xfree(psc); 4715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 472d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner 473d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner/** 474d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner * Process list of buffer received from the server 475d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner * 4765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Processes the list of buffers received in a reply from the server to either 4775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 4785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer */ 4795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void 480d217773f106856a11879ec79dc468efefaf2ee75Chris Lattnerprocess_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers, 481d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner unsigned count) 482d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner{ 483d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner int i; 4845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 4855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->bufferCount = count; 4865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->have_fake_front = 0; 4875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer pdraw->have_back = 0; 4885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 489 /* This assumes the DRI2 buffer attachment tokens matches the 490 * __DRIbuffer tokens. */ 491 for (i = 0; i < count; i++) { 492 pdraw->buffers[i].attachment = buffers[i].attachment; 493 pdraw->buffers[i].name = buffers[i].name; 494 pdraw->buffers[i].pitch = buffers[i].pitch; 495 pdraw->buffers[i].cpp = buffers[i].cpp; 496 pdraw->buffers[i].flags = buffers[i].flags; 497 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 498 pdraw->have_fake_front = 1; 499 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 500 pdraw->have_back = 1; 501 } 502 503} 504 505static int64_t 506dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 507 int64_t remainder) 508{ 509 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 510 struct glx_display *dpyPriv = __glXInitialize(priv->base.psc->dpy); 511 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 512 struct dri2_display *pdp = 513 (struct dri2_display *)dpyPriv->dri2Display; 514 CARD64 ret = 0; 515 516#ifdef __DRI2_FLUSH 517 if (psc->f) 518 (*psc->f->flush)(priv->driDrawable); 519#endif 520 521 /* Old servers don't send invalidate events */ 522 if (!pdp->invalidateAvailable) 523 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable); 524 525 /* Old servers can't handle swapbuffers */ 526 if (!pdp->swapAvailable) { 527 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); 528 return 0; 529 } 530 531#ifdef X_DRI2SwapBuffers 532 DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable, target_msc, divisor, 533 remainder, &ret); 534#endif 535 536 return ret; 537} 538 539static __DRIbuffer * 540dri2GetBuffers(__DRIdrawable * driDrawable, 541 int *width, int *height, 542 unsigned int *attachments, int count, 543 int *out_count, void *loaderPrivate) 544{ 545 struct dri2_drawable *pdraw = loaderPrivate; 546 DRI2Buffer *buffers; 547 548 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 549 width, height, attachments, count, out_count); 550 if (buffers == NULL) 551 return NULL; 552 553 pdraw->width = *width; 554 pdraw->height = *height; 555 process_buffers(pdraw, buffers, *out_count); 556 557 Xfree(buffers); 558 559 return pdraw->buffers; 560} 561 562static __DRIbuffer * 563dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 564 int *width, int *height, 565 unsigned int *attachments, int count, 566 int *out_count, void *loaderPrivate) 567{ 568 struct dri2_drawable *pdraw = loaderPrivate; 569 DRI2Buffer *buffers; 570 571 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 572 pdraw->base.xDrawable, 573 width, height, attachments, 574 count, out_count); 575 if (buffers == NULL) 576 return NULL; 577 578 pdraw->width = *width; 579 pdraw->height = *height; 580 process_buffers(pdraw, buffers, *out_count); 581 582 Xfree(buffers); 583 584 return pdraw->buffers; 585} 586 587#ifdef X_DRI2SwapInterval 588 589static int 590dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 591{ 592 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 593 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 594 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 595 596 if (psc->config) 597 psc->config->configQueryi(psc->driScreen, 598 "vblank_mode", &vblank_mode); 599 600 switch (vblank_mode) { 601 case DRI_CONF_VBLANK_NEVER: 602 return GLX_BAD_VALUE; 603 case DRI_CONF_VBLANK_ALWAYS_SYNC: 604 if (interval <= 0) 605 return GLX_BAD_VALUE; 606 break; 607 default: 608 break; 609 } 610 611 DRI2SwapInterval(priv->base.psc->dpy, priv->base.xDrawable, interval); 612 priv->swap_interval = interval; 613 614 return 0; 615} 616 617static int 618dri2GetSwapInterval(__GLXDRIdrawable *pdraw) 619{ 620 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 621 622 return priv->swap_interval; 623} 624 625#endif /* X_DRI2SwapInterval */ 626 627static const __DRIdri2LoaderExtension dri2LoaderExtension = { 628 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 629 dri2GetBuffers, 630 dri2FlushFrontBuffer, 631 dri2GetBuffersWithFormat, 632}; 633 634static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 635 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 636 dri2GetBuffers, 637 dri2FlushFrontBuffer, 638 NULL, 639}; 640 641#ifdef __DRI_USE_INVALIDATE 642static const __DRIuseInvalidateExtension dri2UseInvalidate = { 643 { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION } 644}; 645#endif 646 647_X_HIDDEN void 648dri2InvalidateBuffers(Display *dpy, XID drawable) 649{ 650 __GLXDRIdrawable *pdraw = 651 dri2GetGlxDrawableFromXDrawableId(dpy, drawable); 652 struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc; 653 struct dri2_drawable *pdp = (struct dri2_drawable *) pdraw; 654 655#if __DRI2_FLUSH_VERSION >= 3 656 if (pdraw && psc->f) 657 psc->f->invalidate(pdp->driDrawable); 658#endif 659} 660 661static void 662dri2_bind_tex_image(Display * dpy, 663 GLXDrawable drawable, 664 int buffer, const int *attrib_list) 665{ 666 struct glx_context *gc = __glXGetCurrentContext(); 667 struct dri2_context *pcp = (struct dri2_context *) gc; 668 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 669 struct glx_display *dpyPriv = __glXInitialize(dpy); 670 struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 671 struct dri2_display *pdp = 672 (struct dri2_display *) dpyPriv->dri2Display; 673 struct dri2_screen *psc; 674 675 if (pdraw != NULL) { 676 psc = (struct dri2_screen *) base->psc; 677 678#if __DRI2_FLUSH_VERSION >= 3 679 if (!pdp->invalidateAvailable && psc->f) 680 psc->f->invalidate(pdraw->driDrawable); 681#endif 682 683 if (psc->texBuffer->base.version >= 2 && 684 psc->texBuffer->setTexBuffer2 != NULL) { 685 (*psc->texBuffer->setTexBuffer2) (pcp->driContext, 686 pdraw->base.textureTarget, 687 pdraw->base.textureFormat, 688 pdraw->driDrawable); 689 } 690 else { 691 (*psc->texBuffer->setTexBuffer) (pcp->driContext, 692 pdraw->base.textureTarget, 693 pdraw->driDrawable); 694 } 695 } 696} 697 698static void 699dri2_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 700{ 701} 702 703static const struct glx_context_vtable dri2_context_vtable = { 704 dri2_destroy_context, 705 dri2_bind_context, 706 dri2_unbind_context, 707 dri2_wait_gl, 708 dri2_wait_x, 709 DRI_glXUseXFont, 710 dri2_bind_tex_image, 711 dri2_release_tex_image, 712}; 713 714static void 715dri2BindExtensions(struct dri2_screen *psc, const __DRIextension **extensions) 716{ 717 int i; 718 719 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync"); 720 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); 721 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); 722 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); 723 724 /* FIXME: if DRI2 version supports it... */ 725 __glXEnableDirectExtension(&psc->base, "INTEL_swap_event"); 726 727 for (i = 0; extensions[i]; i++) { 728 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { 729 psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; 730 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); 731 } 732 733 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) { 734 psc->f = (__DRI2flushExtension *) extensions[i]; 735 /* internal driver extension, no GL extension exposed */ 736 } 737 738 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0)) 739 psc->config = (__DRI2configQueryExtension *) extensions[i]; 740 } 741} 742 743static const struct glx_screen_vtable dri2_screen_vtable = { 744 dri2_create_context 745}; 746 747static struct glx_screen * 748dri2CreateScreen(int screen, struct glx_display * priv) 749{ 750 const __DRIconfig **driver_configs; 751 const __DRIextension **extensions; 752 const struct dri2_display *const pdp = (struct dri2_display *) 753 priv->dri2Display; 754 struct dri2_screen *psc; 755 __GLXDRIscreen *psp; 756 char *driverName, *deviceName; 757 drm_magic_t magic; 758 int i; 759 760 psc = Xmalloc(sizeof *psc); 761 if (psc == NULL) 762 return NULL; 763 764 memset(psc, 0, sizeof *psc); 765 if (!glx_screen_init(&psc->base, screen, priv)) 766 return NULL; 767 768 if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen), 769 &driverName, &deviceName)) { 770 XFree(psc); 771 return NULL; 772 } 773 774 psc->driver = driOpenDriver(driverName); 775 if (psc->driver == NULL) { 776 ErrorMessageF("driver pointer missing\n"); 777 goto handle_error; 778 } 779 780 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 781 if (extensions == NULL) { 782 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 783 goto handle_error; 784 } 785 786 for (i = 0; extensions[i]; i++) { 787 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 788 psc->core = (__DRIcoreExtension *) extensions[i]; 789 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 790 psc->dri2 = (__DRIdri2Extension *) extensions[i]; 791 } 792 793 if (psc->core == NULL || psc->dri2 == NULL) { 794 ErrorMessageF("core dri or dri2 extension not found\n"); 795 goto handle_error; 796 } 797 798 psc->fd = open(deviceName, O_RDWR); 799 if (psc->fd < 0) { 800 ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 801 goto handle_error; 802 } 803 804 if (drmGetMagic(psc->fd, &magic)) { 805 ErrorMessageF("failed to get magic\n"); 806 goto handle_error; 807 } 808 809 if (!DRI2Authenticate(priv->dpy, RootWindow(priv->dpy, screen), magic)) { 810 ErrorMessageF("failed to authenticate magic %d\n", magic); 811 goto handle_error; 812 } 813 814 815 /* If the server does not support the protocol for 816 * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 817 */ 818 psc->driScreen = 819 psc->dri2->createNewScreen(screen, psc->fd, 820 (const __DRIextension **) 821 &pdp->loader_extensions[0], 822 &driver_configs, psc); 823 824 if (psc->driScreen == NULL) { 825 ErrorMessageF("failed to create dri screen\n"); 826 goto handle_error; 827 } 828 829 extensions = psc->core->getExtensions(psc->driScreen); 830 dri2BindExtensions(psc, extensions); 831 832 psc->base.configs = 833 driConvertConfigs(psc->core, psc->base.configs, driver_configs); 834 psc->base.visuals = 835 driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 836 837 psc->driver_configs = driver_configs; 838 839 psc->base.vtable = &dri2_screen_vtable; 840 psp = &psc->vtable; 841 psc->base.driScreen = psp; 842 psp->destroyScreen = dri2DestroyScreen; 843 psp->createDrawable = dri2CreateDrawable; 844 psp->swapBuffers = dri2SwapBuffers; 845 psp->getDrawableMSC = NULL; 846 psp->waitForMSC = NULL; 847 psp->waitForSBC = NULL; 848 psp->setSwapInterval = NULL; 849 psp->getSwapInterval = NULL; 850 851 if (pdp->driMinor >= 2) { 852#ifdef X_DRI2GetMSC 853 psp->getDrawableMSC = dri2DrawableGetMSC; 854#endif 855#ifdef X_DRI2WaitMSC 856 psp->waitForMSC = dri2WaitForMSC; 857 psp->waitForSBC = dri2WaitForSBC; 858#endif 859#ifdef X_DRI2SwapInterval 860 psp->setSwapInterval = dri2SetSwapInterval; 861 psp->getSwapInterval = dri2GetSwapInterval; 862#endif 863#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 864 __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control"); 865#endif 866 } 867 868 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 869 * available.*/ 870 psp->copySubBuffer = dri2CopySubBuffer; 871 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); 872 873 Xfree(driverName); 874 Xfree(deviceName); 875 876 return &psc->base; 877 878handle_error: 879 Xfree(driverName); 880 Xfree(deviceName); 881 XFree(psc); 882 883 /* FIXME: clean up here */ 884 885 return NULL; 886} 887 888/* Called from __glXFreeDisplayPrivate. 889 */ 890static void 891dri2DestroyDisplay(__GLXDRIdisplay * dpy) 892{ 893 Xfree(dpy); 894} 895 896_X_HIDDEN __GLXDRIdrawable * 897dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id) 898{ 899 struct glx_display *d = __glXInitialize(dpy); 900 struct dri2_display *pdp = (struct dri2_display *) d->dri2Display; 901 __GLXDRIdrawable *pdraw; 902 903 if (__glxHashLookup(pdp->dri2Hash, id, (void *) &pdraw) == 0) 904 return pdraw; 905 906 return NULL; 907} 908 909/* 910 * Allocate, initialize and return a __DRIdisplayPrivate object. 911 * This is called from __glXInitialize() when we are given a new 912 * display pointer. 913 */ 914_X_HIDDEN __GLXDRIdisplay * 915dri2CreateDisplay(Display * dpy) 916{ 917 struct dri2_display *pdp; 918 int eventBase, errorBase, i; 919 920 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 921 return NULL; 922 923 pdp = Xmalloc(sizeof *pdp); 924 if (pdp == NULL) 925 return NULL; 926 927 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 928 Xfree(pdp); 929 return NULL; 930 } 931 932 pdp->driPatch = 0; 933 pdp->swapAvailable = (pdp->driMinor >= 2); 934 pdp->invalidateAvailable = (pdp->driMinor >= 3); 935 936 pdp->base.destroyDisplay = dri2DestroyDisplay; 937 pdp->base.createScreen = dri2CreateScreen; 938 939 i = 0; 940 if (pdp->driMinor < 1) 941 pdp->loader_extensions[i++] = &dri2LoaderExtension_old.base; 942 else 943 pdp->loader_extensions[i++] = &dri2LoaderExtension.base; 944 945 pdp->loader_extensions[i++] = &systemTimeExtension.base; 946 947#ifdef __DRI_USE_INVALIDATE 948 pdp->loader_extensions[i++] = &dri2UseInvalidate.base; 949#endif 950 pdp->loader_extensions[i++] = NULL; 951 952 pdp->dri2Hash = __glxHashCreate(); 953 if (pdp->dri2Hash == NULL) { 954 Xfree(pdp); 955 return NULL; 956 } 957 958 return &pdp->base; 959} 960 961#endif /* GLX_DIRECT_RENDERING */ 962