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