driWrap.c revision 6747b715
1/* 2Copyright (c) 2009 Apple Computer, Inc. 3All Rights Reserved. 4 5Permission is hereby granted, free of charge, to any person obtaining a 6copy of this software and associated documentation files (the 7"Software"), to deal in the Software without restriction, including 8without limitation the rights to use, copy, modify, merge, publish, 9distribute, sub license, and/or sell copies of the Software, and to 10permit persons to whom the Software is furnished to do so, subject to 11the following conditions: 12 13The above copyright notice and this permission notice (including the 14next paragraph) shall be included in all copies or substantial portions 15of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 21ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24*/ 25#ifdef HAVE_DIX_CONFIG_H 26#include <dix-config.h> 27#endif 28 29#include <stddef.h> 30#include "mi.h" 31#include "scrnintstr.h" 32#include "gcstruct.h" 33#include "pixmapstr.h" 34#include "windowstr.h" 35#include "dixfontstr.h" 36#include "mivalidate.h" 37#include "driWrap.h" 38#include "dri.h" 39 40#include <OpenGL/OpenGL.h> 41 42typedef struct { 43 GCOps *originalOps; 44 GCOps *driOps; 45} DRIGCRec; 46 47typedef struct { 48 GCOps *originalOps; 49 CreateGCProcPtr CreateGC; 50} DRIWrapScreenRec; 51 52typedef struct { 53 Bool didSave; 54 int devKind; 55 DevUnion devPrivate; 56} DRISavedDrawableState; 57 58static DevPrivateKeyRec driGCKeyRec; 59#define driGCKey (&driGCKeyRec) 60 61static DevPrivateKeyRec driWrapScreenKeyRec; 62#define driWrapScreenKey (&driWrapScreenKeyRec) 63 64static GCOps driGCOps; 65 66#define wrap(priv, real, member, func) { \ 67 priv->member = real->member; \ 68 real->member = func; \ 69 } 70 71#define unwrap(priv, real, member) { \ 72 real->member = priv->member; \ 73 } 74 75static DRIGCRec * 76DRIGetGCPriv(GCPtr pGC) { 77 return dixLookupPrivate(&pGC->devPrivates, driGCKey); 78} 79 80static void 81DRIUnwrapGC(GCPtr pGC) { 82 DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); 83 84 pGC->ops = pGCPriv->originalOps; 85} 86 87static void 88DRIWrapGC(GCPtr pGC) { 89 DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); 90 91 pGC->ops = pGCPriv->driOps; 92} 93 94static void 95DRISurfaceSetDrawable(DrawablePtr pDraw, 96 DRISavedDrawableState *saved) { 97 saved->didSave = FALSE; 98 99 if(pDraw->type == DRAWABLE_PIXMAP) { 100 int pitch, width, height, bpp; 101 void *buffer; 102 103 if(DRIGetPixmapData(pDraw, &width, &height, &pitch, &bpp, &buffer)) { 104 PixmapPtr pPix = (PixmapPtr)pDraw; 105 106 saved->devKind = pPix->devKind; 107 saved->devPrivate.ptr = pPix->devPrivate.ptr; 108 saved->didSave = TRUE; 109 110 pPix->devKind = pitch; 111 pPix->devPrivate.ptr = buffer; 112 } 113 } 114} 115 116static void 117DRISurfaceRestoreDrawable(DrawablePtr pDraw, 118 DRISavedDrawableState *saved) { 119 PixmapPtr pPix = (PixmapPtr)pDraw; 120 121 if(!saved->didSave) 122 return; 123 124 pPix->devKind = saved->devKind; 125 pPix->devPrivate.ptr = saved->devPrivate.ptr; 126} 127 128static void 129DRIFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, 130 DDXPointPtr pptInit, int *pwidthInit, 131 int sorted) { 132 DRISavedDrawableState saved; 133 134 DRISurfaceSetDrawable(dst, &saved); 135 136 DRIUnwrapGC(pGC); 137 138 pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); 139 140 DRIWrapGC(pGC); 141 142 DRISurfaceRestoreDrawable(dst, &saved); 143} 144 145static void 146DRISetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, 147 DDXPointPtr pptInit, int *pwidthInit, 148 int nspans, int sorted) { 149 DRISavedDrawableState saved; 150 151 DRISurfaceSetDrawable(dst, &saved); 152 153 DRIUnwrapGC(pGC); 154 155 pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); 156 157 DRIWrapGC(pGC); 158 159 DRISurfaceRestoreDrawable(dst, &saved); 160} 161 162static void 163DRIPutImage(DrawablePtr dst, GCPtr pGC, 164 int depth, int x, int y, int w, int h, 165 int leftPad, int format, char *pBits) { 166 DRISavedDrawableState saved; 167 168 DRISurfaceSetDrawable(dst, &saved); 169 170 DRIUnwrapGC(pGC); 171 172 pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits); 173 174 DRIWrapGC(pGC); 175 176 DRISurfaceRestoreDrawable(dst, &saved); 177} 178 179static RegionPtr 180DRICopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, 181 int srcx, int srcy, int w, int h, 182 int dstx, int dsty) { 183 RegionPtr pReg; 184 DRISavedDrawableState pSrcSaved, dstSaved; 185 186 DRISurfaceSetDrawable(pSrc, &pSrcSaved); 187 DRISurfaceSetDrawable(dst, &dstSaved); 188 189 DRIUnwrapGC(pGC); 190 191 pReg = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); 192 193 DRIWrapGC(pGC); 194 195 DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); 196 DRISurfaceRestoreDrawable(dst, &dstSaved); 197 198 return pReg; 199} 200 201static RegionPtr 202DRICopyPlane(DrawablePtr pSrc, DrawablePtr dst, 203 GCPtr pGC, int srcx, int srcy, 204 int w, int h, int dstx, int dsty, 205 unsigned long plane) { 206 RegionPtr pReg; 207 DRISavedDrawableState pSrcSaved, dstSaved; 208 209 DRISurfaceSetDrawable(pSrc, &pSrcSaved); 210 DRISurfaceSetDrawable(dst, &dstSaved); 211 212 213 DRIUnwrapGC(pGC); 214 215 pReg = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty, 216 plane); 217 218 DRIWrapGC(pGC); 219 220 DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); 221 DRISurfaceRestoreDrawable(dst, &dstSaved); 222 223 return pReg; 224} 225 226static void 227DRIPolyPoint(DrawablePtr dst, GCPtr pGC, 228 int mode, int npt, DDXPointPtr pptInit) { 229 DRISavedDrawableState saved; 230 231 DRISurfaceSetDrawable(dst, &saved); 232 233 DRIUnwrapGC(pGC); 234 235 pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); 236 237 DRIWrapGC(pGC); 238 239 DRISurfaceRestoreDrawable(dst, &saved); 240} 241 242static void 243DRIPolylines(DrawablePtr dst, GCPtr pGC, 244 int mode, int npt, DDXPointPtr pptInit) { 245 DRISavedDrawableState saved; 246 247 DRISurfaceSetDrawable(dst, &saved); 248 249 DRIUnwrapGC(pGC); 250 251 pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); 252 253 DRIWrapGC(pGC); 254 255 DRISurfaceRestoreDrawable(dst, &saved); 256} 257 258static void 259DRIPolySegment(DrawablePtr dst, GCPtr pGC, 260 int nseg, xSegment *pSeg) { 261 DRISavedDrawableState saved; 262 263 DRISurfaceSetDrawable(dst, &saved); 264 265 DRIUnwrapGC(pGC); 266 267 pGC->ops->PolySegment(dst, pGC, nseg, pSeg); 268 269 DRIWrapGC(pGC); 270 271 DRISurfaceRestoreDrawable(dst, &saved); 272} 273 274static void 275DRIPolyRectangle(DrawablePtr dst, GCPtr pGC, 276 int nRects, xRectangle *pRects) { 277 DRISavedDrawableState saved; 278 279 DRISurfaceSetDrawable(dst, &saved); 280 281 DRIUnwrapGC(pGC); 282 283 pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); 284 285 DRIWrapGC(pGC); 286 287 DRISurfaceRestoreDrawable(dst, &saved); 288} 289static void 290DRIPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs) { 291 DRISavedDrawableState saved; 292 293 DRISurfaceSetDrawable(dst, &saved); 294 295 DRIUnwrapGC(pGC); 296 297 pGC->ops->PolyArc(dst, pGC, narcs, parcs); 298 299 DRIWrapGC(pGC); 300 301 DRISurfaceRestoreDrawable(dst, &saved); 302} 303 304static void 305DRIFillPolygon(DrawablePtr dst, GCPtr pGC, 306 int shape, int mode, int count, 307 DDXPointPtr pptInit) { 308 DRISavedDrawableState saved; 309 310 DRISurfaceSetDrawable(dst, &saved); 311 312 DRIUnwrapGC(pGC); 313 314 pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); 315 316 DRIWrapGC(pGC); 317 318 DRISurfaceRestoreDrawable(dst, &saved); 319} 320 321static void 322DRIPolyFillRect(DrawablePtr dst, GCPtr pGC, 323 int nRectsInit, xRectangle *pRectsInit) { 324 DRISavedDrawableState saved; 325 326 DRISurfaceSetDrawable(dst, &saved); 327 328 DRIUnwrapGC(pGC); 329 330 pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); 331 332 DRIWrapGC(pGC); 333 334 DRISurfaceRestoreDrawable(dst, &saved); 335} 336 337static void 338DRIPolyFillArc(DrawablePtr dst, GCPtr pGC, 339 int narcsInit, xArc *parcsInit) { 340 DRISavedDrawableState saved; 341 342 DRISurfaceSetDrawable(dst, &saved); 343 344 DRIUnwrapGC(pGC); 345 346 pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); 347 348 DRIWrapGC(pGC); 349 350 DRISurfaceRestoreDrawable(dst, &saved); 351} 352 353static int 354DRIPolyText8(DrawablePtr dst, GCPtr pGC, 355 int x, int y, int count, char *chars) { 356 int ret; 357 DRISavedDrawableState saved; 358 359 DRISurfaceSetDrawable(dst, &saved); 360 361 DRIUnwrapGC(pGC); 362 363 ret = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); 364 365 DRIWrapGC(pGC); 366 367 DRISurfaceRestoreDrawable(dst, &saved); 368 369 return ret; 370} 371 372static int 373DRIPolyText16(DrawablePtr dst, GCPtr pGC, 374 int x, int y, int count, unsigned short *chars) { 375 int ret; 376 DRISavedDrawableState saved; 377 378 DRISurfaceSetDrawable(dst, &saved); 379 380 DRIUnwrapGC(pGC); 381 382 ret = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); 383 384 DRIWrapGC(pGC); 385 386 DRISurfaceRestoreDrawable(dst, &saved); 387 388 return ret; 389} 390 391static void 392DRIImageText8(DrawablePtr dst, GCPtr pGC, 393 int x, int y, int count, char *chars) { 394 DRISavedDrawableState saved; 395 396 DRISurfaceSetDrawable(dst, &saved); 397 398 DRIUnwrapGC(pGC); 399 400 pGC->ops->ImageText8(dst, pGC, x, y, count, chars); 401 402 DRIWrapGC(pGC); 403 404 DRISurfaceRestoreDrawable(dst, &saved); 405} 406 407static void 408DRIImageText16(DrawablePtr dst, GCPtr pGC, 409 int x, int y, int count, unsigned short *chars) { 410 DRISavedDrawableState saved; 411 412 DRISurfaceSetDrawable(dst, &saved); 413 414 DRIUnwrapGC(pGC); 415 416 pGC->ops->ImageText16(dst, pGC, x, y, count, chars); 417 418 DRIWrapGC(pGC); 419 420 DRISurfaceRestoreDrawable(dst, &saved); 421} 422 423static void 424DRIImageGlyphBlt(DrawablePtr dst, GCPtr pGC, 425 int x, int y, unsigned int nglyphInit, 426 CharInfoPtr *ppciInit, pointer unused) { 427 DRISavedDrawableState saved; 428 429 DRISurfaceSetDrawable(dst, &saved); 430 431 DRIUnwrapGC(pGC); 432 433 pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); 434 435 DRIWrapGC(pGC); 436 437 DRISurfaceRestoreDrawable(dst, &saved); 438} 439 440static void DRIPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, 441 int x, int y, unsigned int nglyph, 442 CharInfoPtr *ppci, pointer pglyphBase) { 443 DRISavedDrawableState saved; 444 445 DRISurfaceSetDrawable(dst, &saved); 446 447 DRIUnwrapGC(pGC); 448 449 pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); 450 451 DRIWrapGC(pGC); 452 453 DRISurfaceRestoreDrawable(dst, &saved); 454} 455 456static void 457DRIPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, 458 int dx, int dy, int xOrg, int yOrg) { 459 DRISavedDrawableState bitMapSaved, dstSaved; 460 461 DRISurfaceSetDrawable(&pBitMap->drawable, &bitMapSaved); 462 DRISurfaceSetDrawable(dst, &dstSaved); 463 464 DRIUnwrapGC(pGC); 465 466 pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); 467 468 DRIWrapGC(pGC); 469 470 DRISurfaceRestoreDrawable(&pBitMap->drawable, &bitMapSaved); 471 DRISurfaceRestoreDrawable(dst, &dstSaved); 472} 473 474 475static GCOps driGCOps = { 476 DRIFillSpans, 477 DRISetSpans, 478 DRIPutImage, 479 DRICopyArea, 480 DRICopyPlane, 481 DRIPolyPoint, 482 DRIPolylines, 483 DRIPolySegment, 484 DRIPolyRectangle, 485 DRIPolyArc, 486 DRIFillPolygon, 487 DRIPolyFillRect, 488 DRIPolyFillArc, 489 DRIPolyText8, 490 DRIPolyText16, 491 DRIImageText8, 492 DRIImageText16, 493 DRIImageGlyphBlt, 494 DRIPolyGlyphBlt, 495 DRIPushPixels 496}; 497 498 499static Bool 500DRICreateGC(GCPtr pGC) { 501 ScreenPtr pScreen = pGC->pScreen; 502 DRIWrapScreenRec *pScreenPriv; 503 DRIGCRec *pGCPriv; 504 Bool ret; 505 506 pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, driWrapScreenKey); 507 508 pGCPriv = DRIGetGCPriv(pGC); 509 510 unwrap(pScreenPriv, pScreen, CreateGC); 511 ret = pScreen->CreateGC(pGC); 512 513 if(ret) { 514 pGCPriv->originalOps = pGC->ops; 515 pGC->ops = &driGCOps; 516 pGCPriv->driOps = &driGCOps; 517 } 518 519 wrap(pScreenPriv, pScreen, CreateGC, DRICreateGC); 520 521 return ret; 522} 523 524 525/* Return false if an error occurred. */ 526Bool 527DRIWrapInit(ScreenPtr pScreen) { 528 DRIWrapScreenRec *pScreenPriv; 529 530 if(!dixRegisterPrivateKey(&driGCKeyRec, PRIVATE_GC, sizeof(DRIGCRec))) 531 return FALSE; 532 533 if(!dixRegisterPrivateKey(&driWrapScreenKeyRec, PRIVATE_SCREEN, sizeof(DRIWrapScreenRec))) 534 return FALSE; 535 536 pScreenPriv = dixGetPrivateAddr(&pScreen->devPrivates, &driWrapScreenKeyRec); 537 pScreenPriv->CreateGC = pScreen->CreateGC; 538 pScreen->CreateGC = DRICreateGC; 539 540 return TRUE; 541} 542