dri2_glx.c revision c796bb0cc3fde409545bff320540ddf5c029e513
15e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com/* 25e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * Copyright © 2008 Red Hat, Inc. 35e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * 45e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * Permission is hereby granted, free of charge, to any person obtaining a 55e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * copy of this software and associated documentation files (the "Soft- 65e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * ware"), to deal in the Software without restriction, including without 75e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * limitation the rights to use, copy, modify, merge, publish, distribute, 85e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * and/or sell copies of the Software, and to permit persons to whom the 95e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * Software is furnished to do so, provided that the above copyright 105e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * notice(s) and this permission notice appear in all copies of the Soft- 115e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * ware and that both the above copyright notice(s) and this permission 125e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * notice appear in supporting documentation. 135e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * 145e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 155e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 165e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 175e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 185e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 195e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 205e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 215e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 225e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * MANCE OF THIS SOFTWARE. 235e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * 245e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * Except as contained in this notice, the name of a copyright holder shall 255e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * not be used in advertising or otherwise to promote the sale, use or 265e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * other dealings in this Software without prior written authorization of 275e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * the copyright holder. 285e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * 295e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * Authors: 305e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * Kristian Høgsberg (krh@redhat.com) 315e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com */ 32bdf981cb383b7ec472ee86d2fedb53937285f894rtoy@google.com 33bdf981cb383b7ec472ee86d2fedb53937285f894rtoy@google.com#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 345e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 355e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <X11/Xlib.h> 365e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <X11/extensions/Xfixes.h> 375e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <X11/extensions/Xdamage.h> 385e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include "glapi.h" 395e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include "glxclient.h" 405e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <X11/extensions/dri2proto.h> 415e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include "xf86dri.h" 425e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <dlfcn.h> 435e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <fcntl.h> 445e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <unistd.h> 455e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <sys/types.h> 465e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include <sys/mman.h> 475e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include "xf86drm.h" 485e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include "dri2.h" 495e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#include "dri_common.h" 505e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 515e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com/* From xmlpool/options.h, user exposed so should be stable */ 525e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#define DRI_CONF_VBLANK_NEVER 0 535e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 545e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 555e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 565e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 575e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#undef DRI2_MINOR 585e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#define DRI2_MINOR 1 595e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 605e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstruct dri2_display 615e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 625e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXDRIdisplay base; 635e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 645e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com /* 655e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com ** XFree86-DRI version information 665e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com */ 675e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int driMajor; 685e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int driMinor; 695e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int driPatch; 705e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int swapAvailable; 715e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int invalidateAvailable; 725e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 735e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __glxHashTable *dri2Hash; 745e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 755e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com const __DRIextension *loader_extensions[4]; 765e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com}; 775e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 785e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstruct dri2_screen { 795e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXscreenConfigs base; 805e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 815e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __DRIscreen *driScreen; 825e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXDRIscreen vtable; 835e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com const __DRIdri2Extension *dri2; 845e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com const __DRIcoreExtension *core; 855e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 865e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com const __DRI2flushExtension *f; 875e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com const __DRI2configQueryExtension *config; 885e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com const __DRItexBufferExtension *texBuffer; 895e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com const __DRIconfig **driver_configs; 905e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 915e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com void *driver; 925e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int fd; 935e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com}; 945e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 955e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstruct dri2_context 965e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 975e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXcontext base; 985e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXDRIcontext dri_vtable; 995e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __DRIcontext *driContext; 1005e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com}; 1015e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1025e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstruct dri2_drawable 1035e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 1045e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXDRIdrawable base; 1055e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __DRIdrawable *driDrawable; 1065e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __DRIbuffer buffers[5]; 1075e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int bufferCount; 1085e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int width, height; 1095e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int have_back; 1105e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int have_fake_front; 1115e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int swap_interval; 1125e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com}; 1135e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1145e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstatic const struct glx_context_vtable dri2_context_vtable; 1155e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1165d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.comstatic void 1175e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comdri2_destroy_context(__GLXcontext *context) 1185e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 1195e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_context *pcp = (struct dri2_context *) context; 120a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com struct dri2_screen *psc = (struct dri2_screen *) context->psc; 1215e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1225e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com glx_send_destroy_context(psc->base.dpy, context->xid); 1235e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1245e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (context->extensions) 1255e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com XFree((char *) context->extensions); 1265e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 127a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com GarbageCollectDRIDrawables(context->psc); 1285e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1295e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com (*psc->core->destroyContext) (pcp->driContext); 1305e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1315e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com Xfree(pcp); 1325e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com} 1335e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1345e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstatic Bool 1355e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comdri2BindContext(__GLXcontext *context, 1365e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXDRIdrawable *draw, __GLXDRIdrawable *read) 1375e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 138a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com struct dri2_context *pcp = (struct dri2_context *) context; 1395e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; 140a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com struct dri2_drawable *pdr = (struct dri2_drawable *) draw; 1415e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_drawable *prd = (struct dri2_drawable *) read; 1425e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1435e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return (*psc->core->bindContext) (pcp->driContext, 1445e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdr->driDrawable, prd->driDrawable); 1455e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com} 1465e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1475e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstatic void 1485e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comdri2UnbindContext(__GLXcontext *context) 1495e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 1505d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.com struct dri2_context *pcp = (struct dri2_context *) context; 1515e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; 1525d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.com 153a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com (*psc->core->unbindContext) (pcp->driContext); 1545e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com} 1555e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1565e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstatic __GLXcontext * 1575e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comdri2CreateContext(__GLXscreenConfigs *base, 1585e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com const __GLcontextModes * mode, 1595e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com GLXContext shareList, int renderType) 16065de2e82c765748bda2d1c6275be479daf6c8e31kma@webrtc.org{ 1615e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_context *pcp, *pcp_shared; 1625e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_screen *psc = (struct dri2_screen *) base; 1635e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode; 1645e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __DRIcontext *shared = NULL; 1655e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1665e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (shareList) { 1675e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pcp_shared = (struct dri2_context *) shareList->driContext; 1685e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com shared = pcp_shared->driContext; 1695e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com } 1705e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1715e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pcp = Xmalloc(sizeof *pcp); 1725e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (pcp == NULL) 1735e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return NULL; 1745e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1755e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com memset(pcp, 0, sizeof *pcp); 1765e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (!glx_context_init(&pcp->base, &psc->base, mode)) { 1775e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com Xfree(pcp); 1785e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return NULL; 1795e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com } 1805e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1815e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pcp->driContext = 1825e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com (*psc->dri2->createNewContext) (psc->driScreen, 1835e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com config->driConfig, shared, pcp); 184a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com 1855e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (pcp->driContext == NULL) { 1865e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com Xfree(pcp); 1875e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return NULL; 1885e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com } 1895e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1905e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pcp->base.vtable = &dri2_context_vtable; 1915e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pcp->base.driContext = &pcp->dri_vtable; 192a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com pcp->dri_vtable.bindContext = dri2BindContext; 1935e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pcp->dri_vtable.unbindContext = dri2UnbindContext; 1945e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1955e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return &pcp->base; 1965e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com} 1975e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 1985d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.comstatic void 1995e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comdri2DestroyDrawable(__GLXDRIdrawable *base) 2005e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 201a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com struct dri2_screen *psc = (struct dri2_screen *) base->psc; 2025e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 2035e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXdisplayPrivate *dpyPriv = psc->base.display; 2045e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_display *pdp = (struct dri2_display *)dpyPriv->dri2Display; 2055e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2065e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __glxHashDelete(pdp->dri2Hash, pdraw->base.xDrawable); 2075e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com (*psc->core->destroyDrawable) (pdraw->driDrawable); 208a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com DRI2DestroyDrawable(psc->base.dpy, pdraw->base.xDrawable); 2095e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com Xfree(pdraw); 2105e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com} 2115e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2125e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstatic __GLXDRIdrawable * 2135d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.comdri2CreateDrawable(__GLXscreenConfigs *base, XID xDrawable, 2145e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com GLXDrawable drawable, const __GLcontextModes * modes) 2155e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 2165d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.com struct dri2_drawable *pdraw; 2175e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_screen *psc = (struct dri2_screen *) base; 2185e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes; 2195e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com __GLXdisplayPrivate *dpyPriv; 2205e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com struct dri2_display *pdp; 2215e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 2225e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2235e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw = Xmalloc(sizeof(*pdraw)); 2245e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (!pdraw) 2255e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return NULL; 2265e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2275e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->base.destroyDrawable = dri2DestroyDrawable; 2285e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->base.xDrawable = xDrawable; 2295e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->base.drawable = drawable; 2305e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->base.psc = &psc->base; 2315e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->bufferCount = 0; 2325e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->swap_interval = 1; /* default may be overridden below */ 2335e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->have_back = 0; 2345e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2355e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (psc->config) 2365e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com psc->config->configQueryi(psc->driScreen, 2375e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com "vblank_mode", &vblank_mode); 238a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com 2395e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com switch (vblank_mode) { 2405e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com case DRI_CONF_VBLANK_NEVER: 2415e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com case DRI_CONF_VBLANK_DEF_INTERVAL_0: 2425e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->swap_interval = 0; 2435e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com break; 2445e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com case DRI_CONF_VBLANK_DEF_INTERVAL_1: 2455e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com case DRI_CONF_VBLANK_ALWAYS_SYNC: 246a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com default: 2475e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->swap_interval = 1; 2485e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com break; 2495e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com } 2505e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2515e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com DRI2CreateDrawable(psc->base.dpy, xDrawable); 2525d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.com 2535e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com dpyPriv = __glXInitialize(psc->base.dpy); 2545e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdp = (struct dri2_display *)dpyPriv->dri2Display;; 255a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com /* Create a new drawable */ 2565e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com pdraw->driDrawable = 2575e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com (*psc->dri2->createNewDrawable) (psc->driScreen, 2585e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com config->driConfig, pdraw); 2595e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2605e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (!pdraw->driDrawable) { 2615e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com DRI2DestroyDrawable(psc->base.dpy, xDrawable); 262a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com Xfree(pdraw); 2635e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return NULL; 2645e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com } 2655e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2665e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (__glxHashInsert(pdp->dri2Hash, xDrawable, pdraw)) { 2675d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.com (*psc->core->destroyDrawable) (pdraw->driDrawable); 2685e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com DRI2DestroyDrawable(psc->base.dpy, xDrawable); 2695e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com Xfree(pdraw); 2705d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.com return None; 2715e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com } 2725e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2735e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2745e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#ifdef X_DRI2SwapInterval 2755e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com /* 2765e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com * Make sure server has the same swap interval we do for the new 277a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com * drawable. 278a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com */ 2795e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com if (pdp->swapAvailable) 2805e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com DRI2SwapInterval(psc->base.dpy, xDrawable, pdraw->swap_interval); 2815e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#endif 2825e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 2835e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return &pdraw->base; 284a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com} 2855e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 286a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com#ifdef X_DRI2GetMSC 287a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com 2885e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comstatic int 2895e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.comdri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw, 290a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com int64_t *ust, int64_t *msc, int64_t *sbc) 2915e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com{ 292a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com CARD64 dri2_ust, dri2_msc, dri2_sbc; 2935e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com int ret; 2945e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 295a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com ret = DRI2GetMSC(psc->dpy, pdraw->xDrawable, 2965e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com &dri2_ust, &dri2_msc, &dri2_sbc); 297a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com *ust = dri2_ust; 298a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com *msc = dri2_msc; 2995e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com *sbc = dri2_sbc; 300a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com 3015e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com return ret; 302a2c02e342750946639b77d1a42f9a9da85a84b82rtoy@google.com} 3035e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 3045e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#endif 3055e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 3065e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com 3075e49351d609862d862bd3d3b8dbd133205079b84rtoy@google.com#ifdef X_DRI2WaitMSC 3085d8507771824df2b96d9c6f2fd55a47fcfd9dec9rtoy@google.com 309static int 310dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 311 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) 312{ 313 CARD64 dri2_ust, dri2_msc, dri2_sbc; 314 int ret; 315 316 ret = DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor, 317 remainder, &dri2_ust, &dri2_msc, &dri2_sbc); 318 *ust = dri2_ust; 319 *msc = dri2_msc; 320 *sbc = dri2_sbc; 321 322 return ret; 323} 324 325static int 326dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, 327 int64_t *msc, int64_t *sbc) 328{ 329 CARD64 dri2_ust, dri2_msc, dri2_sbc; 330 int ret; 331 332 ret = DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, 333 target_sbc, &dri2_ust, &dri2_msc, &dri2_sbc); 334 *ust = dri2_ust; 335 *msc = dri2_msc; 336 *sbc = dri2_sbc; 337 338 return ret; 339} 340 341#endif /* X_DRI2WaitMSC */ 342 343static void 344dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) 345{ 346 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 347 struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc; 348 XRectangle xrect; 349 XserverRegion region; 350 351 /* Check we have the right attachments */ 352 if (!priv->have_back) 353 return; 354 355 xrect.x = x; 356 xrect.y = priv->height - y - height; 357 xrect.width = width; 358 xrect.height = height; 359 360#ifdef __DRI2_FLUSH 361 if (psc->f) 362 (*psc->f->flush) (priv->driDrawable); 363#endif 364 365 region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); 366 DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, 367 DRI2BufferFrontLeft, DRI2BufferBackLeft); 368 369 /* Refresh the fake front (if present) after we just damaged the real 370 * front. 371 */ 372 if (priv->have_fake_front) 373 DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, 374 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 375 376 XFixesDestroyRegion(psc->base.dpy, region); 377} 378 379static void 380dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src) 381{ 382 XRectangle xrect; 383 XserverRegion region; 384 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 385 386 xrect.x = 0; 387 xrect.y = 0; 388 xrect.width = priv->width; 389 xrect.height = priv->height; 390 391#ifdef __DRI2_FLUSH 392 if (psc->f) 393 (*psc->f->flush) (priv->driDrawable); 394#endif 395 396 region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); 397 DRI2CopyRegion(psc->base.dpy, priv->base.xDrawable, region, dest, src); 398 XFixesDestroyRegion(psc->base.dpy, region); 399 400} 401 402static void 403dri2_wait_x(__GLXcontext *gc) 404{ 405 struct dri2_drawable *priv = (struct dri2_drawable *) 406 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 407 408 if (priv == NULL || !priv->have_fake_front) 409 return; 410 411 dri2_copy_drawable(priv, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 412} 413 414static void 415dri2_wait_gl(__GLXcontext *gc) 416{ 417 struct dri2_drawable *priv = (struct dri2_drawable *) 418 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 419 420 if (priv == NULL || !priv->have_fake_front) 421 return; 422 423 dri2_copy_drawable(priv, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 424} 425 426static void 427dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) 428{ 429 struct dri2_drawable *pdraw = loaderPrivate; 430 __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy); 431 struct dri2_display *pdp = (struct dri2_display *)priv->dri2Display; 432 GLXContext gc = __glXGetCurrentContext(); 433 434 /* Old servers don't send invalidate events */ 435 if (!pdp->invalidateAvailable) 436 dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable); 437 438 dri2_wait_gl(gc); 439} 440 441 442static void 443dri2DestroyScreen(__GLXscreenConfigs *base) 444{ 445 struct dri2_screen *psc = (struct dri2_screen *) base; 446 447 /* Free the direct rendering per screen data */ 448 (*psc->core->destroyScreen) (psc->driScreen); 449 driDestroyConfigs(psc->driver_configs); 450 close(psc->fd); 451 Xfree(psc); 452} 453 454/** 455 * Process list of buffer received from the server 456 * 457 * Processes the list of buffers received in a reply from the server to either 458 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 459 */ 460static void 461process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers, 462 unsigned count) 463{ 464 int i; 465 466 pdraw->bufferCount = count; 467 pdraw->have_fake_front = 0; 468 pdraw->have_back = 0; 469 470 /* This assumes the DRI2 buffer attachment tokens matches the 471 * __DRIbuffer tokens. */ 472 for (i = 0; i < count; i++) { 473 pdraw->buffers[i].attachment = buffers[i].attachment; 474 pdraw->buffers[i].name = buffers[i].name; 475 pdraw->buffers[i].pitch = buffers[i].pitch; 476 pdraw->buffers[i].cpp = buffers[i].cpp; 477 pdraw->buffers[i].flags = buffers[i].flags; 478 if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 479 pdraw->have_fake_front = 1; 480 if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) 481 pdraw->have_back = 1; 482 } 483 484} 485 486static int64_t 487dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, 488 int64_t remainder) 489{ 490 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 491 __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy); 492 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 493 struct dri2_display *pdp = 494 (struct dri2_display *)dpyPriv->dri2Display; 495 CARD64 ret; 496 497#ifdef __DRI2_FLUSH 498 if (psc->f) 499 (*psc->f->flush)(priv->driDrawable); 500#endif 501 502 /* Old servers don't send invalidate events */ 503 if (!pdp->invalidateAvailable) 504 dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable); 505 506 /* Old servers can't handle swapbuffers */ 507 if (!pdp->swapAvailable) { 508 dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); 509 return 0; 510 } 511 512#ifdef X_DRI2SwapBuffers 513 DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable, target_msc, divisor, 514 remainder, &ret); 515#endif 516 517 return ret; 518} 519 520static __DRIbuffer * 521dri2GetBuffers(__DRIdrawable * driDrawable, 522 int *width, int *height, 523 unsigned int *attachments, int count, 524 int *out_count, void *loaderPrivate) 525{ 526 struct dri2_drawable *pdraw = loaderPrivate; 527 DRI2Buffer *buffers; 528 529 buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, 530 width, height, attachments, count, out_count); 531 if (buffers == NULL) 532 return NULL; 533 534 pdraw->width = *width; 535 pdraw->height = *height; 536 process_buffers(pdraw, buffers, *out_count); 537 538 Xfree(buffers); 539 540 return pdraw->buffers; 541} 542 543static __DRIbuffer * 544dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, 545 int *width, int *height, 546 unsigned int *attachments, int count, 547 int *out_count, void *loaderPrivate) 548{ 549 struct dri2_drawable *pdraw = loaderPrivate; 550 DRI2Buffer *buffers; 551 552 buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy, 553 pdraw->base.xDrawable, 554 width, height, attachments, 555 count, out_count); 556 if (buffers == NULL) 557 return NULL; 558 559 pdraw->width = *width; 560 pdraw->height = *height; 561 process_buffers(pdraw, buffers, *out_count); 562 563 Xfree(buffers); 564 565 return pdraw->buffers; 566} 567 568#ifdef X_DRI2SwapInterval 569 570static int 571dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) 572{ 573 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 574 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 575 struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc; 576 577 if (psc->config) 578 psc->config->configQueryi(psc->driScreen, 579 "vblank_mode", &vblank_mode); 580 581 switch (vblank_mode) { 582 case DRI_CONF_VBLANK_NEVER: 583 return GLX_BAD_VALUE; 584 case DRI_CONF_VBLANK_ALWAYS_SYNC: 585 if (interval <= 0) 586 return GLX_BAD_VALUE; 587 break; 588 default: 589 break; 590 } 591 592 DRI2SwapInterval(priv->base.psc->dpy, priv->base.xDrawable, interval); 593 priv->swap_interval = interval; 594 595 return 0; 596} 597 598static int 599dri2GetSwapInterval(__GLXDRIdrawable *pdraw) 600{ 601 struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; 602 603 return priv->swap_interval; 604} 605 606#endif /* X_DRI2SwapInterval */ 607 608static const __DRIdri2LoaderExtension dri2LoaderExtension = { 609 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 610 dri2GetBuffers, 611 dri2FlushFrontBuffer, 612 dri2GetBuffersWithFormat, 613}; 614 615static const __DRIdri2LoaderExtension dri2LoaderExtension_old = { 616 {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION}, 617 dri2GetBuffers, 618 dri2FlushFrontBuffer, 619 NULL, 620}; 621 622#ifdef __DRI_USE_INVALIDATE 623static const __DRIuseInvalidateExtension dri2UseInvalidate = { 624 { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION } 625}; 626#endif 627 628_X_HIDDEN void 629dri2InvalidateBuffers(Display *dpy, XID drawable) 630{ 631 __GLXDRIdrawable *pdraw = 632 dri2GetGlxDrawableFromXDrawableId(dpy, drawable); 633 struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc; 634 struct dri2_drawable *pdp = (struct dri2_drawable *) pdraw; 635 636#if __DRI2_FLUSH_VERSION >= 3 637 if (pdraw && psc->f) 638 psc->f->invalidate(pdp->driDrawable); 639#endif 640} 641 642static void 643dri2_bind_tex_image(Display * dpy, 644 GLXDrawable drawable, 645 int buffer, const int *attrib_list) 646{ 647 GLXContext gc = __glXGetCurrentContext(); 648 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable); 649 __GLXdisplayPrivate *dpyPriv = __glXInitialize(dpy); 650 struct dri2_drawable *pdraw = (struct dri2_drawable *) base; 651 struct dri2_display *pdp = 652 (struct dri2_display *) dpyPriv->dri2Display; 653 struct dri2_screen *psc = (struct dri2_screen *) base->psc; 654 struct dri2_context *pcp = (struct dri2_context *) gc->driContext; 655 656 if (pdraw != NULL) { 657 658#if __DRI2_FLUSH_VERSION >= 3 659 if (!pdp->invalidateAvailable && psc->f) 660 psc->f->invalidate(pdraw->driDrawable); 661#endif 662 663 if (psc->texBuffer->base.version >= 2 && 664 psc->texBuffer->setTexBuffer2 != NULL) { 665 (*psc->texBuffer->setTexBuffer2) (pcp->driContext, 666 pdraw->base.textureTarget, 667 pdraw->base.textureFormat, 668 pdraw->driDrawable); 669 } 670 else { 671 (*psc->texBuffer->setTexBuffer) (pcp->driContext, 672 pdraw->base.textureTarget, 673 pdraw->driDrawable); 674 } 675 } 676} 677 678static void 679dri2_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer) 680{ 681} 682 683static const struct glx_context_vtable dri2_context_vtable = { 684 dri2_destroy_context, 685 dri2_wait_gl, 686 dri2_wait_x, 687 DRI_glXUseXFont, 688 dri2_bind_tex_image, 689 dri2_release_tex_image, 690}; 691 692static void 693dri2BindExtensions(struct dri2_screen *psc, const __DRIextension **extensions) 694{ 695 int i; 696 697 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync"); 698 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); 699 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); 700 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); 701 702 /* FIXME: if DRI2 version supports it... */ 703 __glXEnableDirectExtension(&psc->base, "INTEL_swap_event"); 704 705 for (i = 0; extensions[i]; i++) { 706 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { 707 psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; 708 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap"); 709 } 710 711 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) { 712 psc->f = (__DRI2flushExtension *) extensions[i]; 713 /* internal driver extension, no GL extension exposed */ 714 } 715 716 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0)) 717 psc->config = (__DRI2configQueryExtension *) extensions[i]; 718 } 719} 720 721 722static __GLXscreenConfigs * 723dri2CreateScreen(int screen, __GLXdisplayPrivate * priv) 724{ 725 const __DRIconfig **driver_configs; 726 const __DRIextension **extensions; 727 const struct dri2_display *const pdp = (struct dri2_display *) 728 priv->dri2Display; 729 struct dri2_screen *psc; 730 __GLXDRIscreen *psp; 731 char *driverName, *deviceName; 732 drm_magic_t magic; 733 int i; 734 735 psc = Xmalloc(sizeof *psc); 736 if (psc == NULL) 737 return NULL; 738 739 memset(psc, 0, sizeof *psc); 740 if (!glx_screen_init(&psc->base, screen, priv)) 741 return NULL; 742 743 if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen), 744 &driverName, &deviceName)) { 745 XFree(psc); 746 return NULL; 747 } 748 749 psc->driver = driOpenDriver(driverName); 750 if (psc->driver == NULL) { 751 ErrorMessageF("driver pointer missing\n"); 752 goto handle_error; 753 } 754 755 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); 756 if (extensions == NULL) { 757 ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 758 goto handle_error; 759 } 760 761 for (i = 0; extensions[i]; i++) { 762 if (strcmp(extensions[i]->name, __DRI_CORE) == 0) 763 psc->core = (__DRIcoreExtension *) extensions[i]; 764 if (strcmp(extensions[i]->name, __DRI_DRI2) == 0) 765 psc->dri2 = (__DRIdri2Extension *) extensions[i]; 766 } 767 768 if (psc->core == NULL || psc->dri2 == NULL) { 769 ErrorMessageF("core dri or dri2 extension not found\n"); 770 goto handle_error; 771 } 772 773 psc->fd = open(deviceName, O_RDWR); 774 if (psc->fd < 0) { 775 ErrorMessageF("failed to open drm device: %s\n", strerror(errno)); 776 goto handle_error; 777 } 778 779 if (drmGetMagic(psc->fd, &magic)) { 780 ErrorMessageF("failed to get magic\n"); 781 goto handle_error; 782 } 783 784 if (!DRI2Authenticate(priv->dpy, RootWindow(priv->dpy, screen), magic)) { 785 ErrorMessageF("failed to authenticate magic %d\n", magic); 786 goto handle_error; 787 } 788 789 790 /* If the server does not support the protocol for 791 * DRI2GetBuffersWithFormat, don't supply that interface to the driver. 792 */ 793 psc->driScreen = 794 psc->dri2->createNewScreen(screen, psc->fd, 795 (const __DRIextension **) 796 &pdp->loader_extensions[0], 797 &driver_configs, psc); 798 799 if (psc->driScreen == NULL) { 800 ErrorMessageF("failed to create dri screen\n"); 801 goto handle_error; 802 } 803 804 extensions = psc->core->getExtensions(psc->driScreen); 805 dri2BindExtensions(psc, extensions); 806 807 psc->base.configs = 808 driConvertConfigs(psc->core, psc->base.configs, driver_configs); 809 psc->base.visuals = 810 driConvertConfigs(psc->core, psc->base.visuals, driver_configs); 811 812 psc->driver_configs = driver_configs; 813 814 psp = &psc->vtable; 815 psc->base.driScreen = psp; 816 psp->destroyScreen = dri2DestroyScreen; 817 psp->createContext = dri2CreateContext; 818 psp->createDrawable = dri2CreateDrawable; 819 psp->swapBuffers = dri2SwapBuffers; 820 psp->getDrawableMSC = NULL; 821 psp->waitForMSC = NULL; 822 psp->waitForSBC = NULL; 823 psp->setSwapInterval = NULL; 824 psp->getSwapInterval = NULL; 825 826 if (pdp->driMinor >= 2) { 827#ifdef X_DRI2GetMSC 828 psp->getDrawableMSC = dri2DrawableGetMSC; 829#endif 830#ifdef X_DRI2WaitMSC 831 psp->waitForMSC = dri2WaitForMSC; 832 psp->waitForSBC = dri2WaitForSBC; 833#endif 834#ifdef X_DRI2SwapInterval 835 psp->setSwapInterval = dri2SetSwapInterval; 836 psp->getSwapInterval = dri2GetSwapInterval; 837#endif 838#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval) 839 __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control"); 840#endif 841 } 842 843 /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always 844 * available.*/ 845 psp->copySubBuffer = dri2CopySubBuffer; 846 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer"); 847 848 Xfree(driverName); 849 Xfree(deviceName); 850 851 return &psc->base; 852 853handle_error: 854 Xfree(driverName); 855 Xfree(deviceName); 856 XFree(psc); 857 858 /* FIXME: clean up here */ 859 860 return NULL; 861} 862 863/* Called from __glXFreeDisplayPrivate. 864 */ 865static void 866dri2DestroyDisplay(__GLXDRIdisplay * dpy) 867{ 868 Xfree(dpy); 869} 870 871_X_HIDDEN __GLXDRIdrawable * 872dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id) 873{ 874 __GLXdisplayPrivate *d = __glXInitialize(dpy); 875 struct dri2_display *pdp = (struct dri2_display *) d->dri2Display; 876 __GLXDRIdrawable *pdraw; 877 878 if (__glxHashLookup(pdp->dri2Hash, id, (void *) &pdraw) == 0) 879 return pdraw; 880 881 return NULL; 882} 883 884/* 885 * Allocate, initialize and return a __DRIdisplayPrivate object. 886 * This is called from __glXInitialize() when we are given a new 887 * display pointer. 888 */ 889_X_HIDDEN __GLXDRIdisplay * 890dri2CreateDisplay(Display * dpy) 891{ 892 struct dri2_display *pdp; 893 int eventBase, errorBase, i; 894 895 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) 896 return NULL; 897 898 pdp = Xmalloc(sizeof *pdp); 899 if (pdp == NULL) 900 return NULL; 901 902 if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) { 903 Xfree(pdp); 904 return NULL; 905 } 906 907 pdp->driPatch = 0; 908 pdp->swapAvailable = (pdp->driMinor >= 2); 909 pdp->invalidateAvailable = (pdp->driMinor >= 3); 910 911 pdp->base.destroyDisplay = dri2DestroyDisplay; 912 pdp->base.createScreen = dri2CreateScreen; 913 914 i = 0; 915 if (pdp->driMinor < 1) 916 pdp->loader_extensions[i++] = &dri2LoaderExtension_old.base; 917 else 918 pdp->loader_extensions[i++] = &dri2LoaderExtension.base; 919 920 pdp->loader_extensions[i++] = &systemTimeExtension.base; 921 922#ifdef __DRI_USE_INVALIDATE 923 pdp->loader_extensions[i++] = &dri2UseInvalidate.base; 924#endif 925 pdp->loader_extensions[i++] = NULL; 926 927 pdp->dri2Hash = __glxHashCreate(); 928 if (pdp->dri2Hash == NULL) { 929 Xfree(pdp); 930 return NULL; 931 } 932 933 return &pdp->base; 934} 935 936#endif /* GLX_DIRECT_RENDERING */ 937