dri2.c revision 4642e01f
1/* 2 * Copyright © 2007, 2008 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Soft- 6 * ware"), to deal in the Software without restriction, including without 7 * limitation the rights to use, copy, modify, merge, publish, distribute, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, provided that the above copyright 10 * notice(s) and this permission notice appear in all copies of the Soft- 11 * ware and that both the above copyright notice(s) and this permission 12 * notice appear in supporting documentation. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22 * MANCE OF THIS SOFTWARE. 23 * 24 * Except as contained in this notice, the name of a copyright holder shall 25 * not be used in advertising or otherwise to promote the sale, use or 26 * other dealings in this Software without prior written authorization of 27 * the copyright holder. 28 * 29 * Authors: 30 * Kristian Høgsberg (krh@redhat.com) 31 */ 32 33#ifdef HAVE_XORG_CONFIG_H 34#include <xorg-config.h> 35#endif 36 37#include <xf86drm.h> 38#include "xf86Module.h" 39#include "scrnintstr.h" 40#include "windowstr.h" 41#include "dri2.h" 42 43#include "xf86.h" 44 45static int dri2ScreenPrivateKeyIndex; 46static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex; 47static int dri2WindowPrivateKeyIndex; 48static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex; 49static int dri2PixmapPrivateKeyIndex; 50static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex; 51 52typedef struct _DRI2Drawable { 53 unsigned int refCount; 54 int width; 55 int height; 56 DRI2BufferPtr buffers; 57 int bufferCount; 58 unsigned int pendingSequence; 59} DRI2DrawableRec, *DRI2DrawablePtr; 60 61typedef struct _DRI2Screen { 62 const char *driverName; 63 const char *deviceName; 64 int fd; 65 unsigned int lastSequence; 66 DRI2CreateBuffersProcPtr CreateBuffers; 67 DRI2DestroyBuffersProcPtr DestroyBuffers; 68 DRI2CopyRegionProcPtr CopyRegion; 69 70 HandleExposuresProcPtr HandleExposures; 71} DRI2ScreenRec, *DRI2ScreenPtr; 72 73static DRI2ScreenPtr 74DRI2GetScreen(ScreenPtr pScreen) 75{ 76 return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey); 77} 78 79static DRI2DrawablePtr 80DRI2GetDrawable(DrawablePtr pDraw) 81{ 82 WindowPtr pWin; 83 PixmapPtr pPixmap; 84 85 if (pDraw->type == DRAWABLE_WINDOW) 86 { 87 pWin = (WindowPtr) pDraw; 88 return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey); 89 } 90 else 91 { 92 pPixmap = (PixmapPtr) pDraw; 93 return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey); 94 } 95} 96 97int 98DRI2CreateDrawable(DrawablePtr pDraw) 99{ 100 WindowPtr pWin; 101 PixmapPtr pPixmap; 102 DRI2DrawablePtr pPriv; 103 104 pPriv = DRI2GetDrawable(pDraw); 105 if (pPriv != NULL) 106 { 107 pPriv->refCount++; 108 return Success; 109 } 110 111 pPriv = xalloc(sizeof *pPriv); 112 if (pPriv == NULL) 113 return BadAlloc; 114 115 pPriv->refCount = 1; 116 pPriv->width = pDraw->width; 117 pPriv->height = pDraw->height; 118 pPriv->buffers = NULL; 119 pPriv->bufferCount = 0; 120 121 if (pDraw->type == DRAWABLE_WINDOW) 122 { 123 pWin = (WindowPtr) pDraw; 124 dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv); 125 } 126 else 127 { 128 pPixmap = (PixmapPtr) pDraw; 129 dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv); 130 } 131 132 return Success; 133} 134 135DRI2BufferPtr 136DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height, 137 unsigned int *attachments, int count, int *out_count) 138{ 139 DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); 140 DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); 141 DRI2BufferPtr buffers; 142 143 if (pPriv->buffers == NULL || 144 pDraw->width != pPriv->width || pDraw->height != pPriv->height) 145 { 146 buffers = (*ds->CreateBuffers)(pDraw, attachments, count); 147 (*ds->DestroyBuffers)(pDraw, pPriv->buffers, pPriv->bufferCount); 148 pPriv->buffers = buffers; 149 pPriv->bufferCount = count; 150 pPriv->width = pDraw->width; 151 pPriv->height = pDraw->height; 152 } 153 154 *width = pPriv->width; 155 *height = pPriv->height; 156 *out_count = pPriv->bufferCount; 157 158 return pPriv->buffers; 159} 160 161int 162DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, 163 unsigned int dest, unsigned int src) 164{ 165 DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); 166 DRI2DrawablePtr pPriv; 167 DRI2BufferPtr pDestBuffer, pSrcBuffer; 168 int i; 169 170 pPriv = DRI2GetDrawable(pDraw); 171 if (pPriv == NULL) 172 return BadDrawable; 173 174 pDestBuffer = NULL; 175 pSrcBuffer = NULL; 176 for (i = 0; i < pPriv->bufferCount; i++) 177 { 178 if (pPriv->buffers[i].attachment == dest) 179 pDestBuffer = &pPriv->buffers[i]; 180 if (pPriv->buffers[i].attachment == src) 181 pSrcBuffer = &pPriv->buffers[i]; 182 } 183 if (pSrcBuffer == NULL || pDestBuffer == NULL) 184 return BadValue; 185 186 (*ds->CopyRegion)(pDraw, pRegion, pDestBuffer, pSrcBuffer); 187 188 return Success; 189} 190 191void 192DRI2DestroyDrawable(DrawablePtr pDraw) 193{ 194 DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); 195 DRI2DrawablePtr pPriv; 196 WindowPtr pWin; 197 PixmapPtr pPixmap; 198 199 pPriv = DRI2GetDrawable(pDraw); 200 if (pPriv == NULL) 201 return; 202 203 pPriv->refCount--; 204 if (pPriv->refCount > 0) 205 return; 206 207 (*ds->DestroyBuffers)(pDraw, pPriv->buffers, pPriv->bufferCount); 208 xfree(pPriv); 209 210 if (pDraw->type == DRAWABLE_WINDOW) 211 { 212 pWin = (WindowPtr) pDraw; 213 dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL); 214 } 215 else 216 { 217 pPixmap = (PixmapPtr) pDraw; 218 dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL); 219 } 220} 221 222Bool 223DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd, 224 const char **driverName, const char **deviceName) 225{ 226 DRI2ScreenPtr ds = DRI2GetScreen(pScreen); 227 228 if (ds == NULL) 229 return FALSE; 230 231 if (driverType != DRI2DriverDRI) 232 return BadValue; 233 234 *fd = ds->fd; 235 *driverName = ds->driverName; 236 *deviceName = ds->deviceName; 237 238 return TRUE; 239} 240 241Bool 242DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic) 243{ 244 DRI2ScreenPtr ds = DRI2GetScreen(pScreen); 245 246 if (ds == NULL || drmAuthMagic(ds->fd, magic)) 247 return FALSE; 248 249 return TRUE; 250} 251 252Bool 253DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) 254{ 255 DRI2ScreenPtr ds; 256 257 ds = xalloc(sizeof *ds); 258 if (!ds) 259 return FALSE; 260 261 ds->fd = info->fd; 262 ds->driverName = info->driverName; 263 ds->deviceName = info->deviceName; 264 ds->CreateBuffers = info->CreateBuffers; 265 ds->DestroyBuffers = info->DestroyBuffers; 266 ds->CopyRegion = info->CopyRegion; 267 268 dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds); 269 270 xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n"); 271 272 return TRUE; 273} 274 275void 276DRI2CloseScreen(ScreenPtr pScreen) 277{ 278 DRI2ScreenPtr ds = DRI2GetScreen(pScreen); 279 280 xfree(ds); 281 dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL); 282} 283 284extern ExtensionModule dri2ExtensionModule; 285 286static pointer 287DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin) 288{ 289 static Bool setupDone = FALSE; 290 291 if (!setupDone) 292 { 293 setupDone = TRUE; 294 LoadExtension(&dri2ExtensionModule, FALSE); 295 } 296 else 297 { 298 if (errmaj) 299 *errmaj = LDR_ONCEONLY; 300 } 301 302 return (pointer) 1; 303} 304 305static XF86ModuleVersionInfo DRI2VersRec = 306{ 307 "dri2", 308 MODULEVENDORSTRING, 309 MODINFOSTRING1, 310 MODINFOSTRING2, 311 XORG_VERSION_CURRENT, 312 1, 0, 0, 313 ABI_CLASS_EXTENSION, 314 ABI_EXTENSION_VERSION, 315 MOD_CLASS_NONE, 316 { 0, 0, 0, 0 } 317}; 318 319_X_EXPORT XF86ModuleData dri2ModuleData = { &DRI2VersRec, DRI2Setup, NULL }; 320 321