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} DRIGCRec; 45 46typedef struct { 47 GCOps *originalOps; 48 CreateGCProcPtr CreateGC; 49} DRIWrapScreenRec; 50 51typedef struct { 52 Bool didSave; 53 int devKind; 54 DevUnion devPrivate; 55} DRISavedDrawableState; 56 57static DevPrivateKeyRec driGCKeyRec; 58#define driGCKey (&driGCKeyRec) 59 60static DevPrivateKeyRec driWrapScreenKeyRec; 61#define driWrapScreenKey (&driWrapScreenKeyRec) 62 63static GCOps driGCOps; 64 65#define wrap(priv, real, member, func) { \ 66 priv->member = real->member; \ 67 real->member = func; \ 68 } 69 70#define unwrap(priv, real, member) { \ 71 real->member = priv->member; \ 72 } 73 74static DRIGCRec * 75DRIGetGCPriv(GCPtr pGC) { 76 return dixLookupPrivate(&pGC->devPrivates, driGCKey); 77} 78 79static void 80DRIUnwrapGC(GCPtr pGC) { 81 DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); 82 83 pGC->ops = pGCPriv->originalOps; 84} 85 86static void 87DRIWrapGC(GCPtr pGC) { 88 pGC->ops = &driGCOps; 89} 90 91static void 92DRISurfaceSetDrawable(DrawablePtr pDraw, 93 DRISavedDrawableState *saved) { 94 saved->didSave = FALSE; 95 96 if(pDraw->type == DRAWABLE_PIXMAP) { 97 int pitch, width, height, bpp; 98 void *buffer; 99 100 if(DRIGetPixmapData(pDraw, &width, &height, &pitch, &bpp, &buffer)) { 101 PixmapPtr pPix = (PixmapPtr)pDraw; 102 103 saved->devKind = pPix->devKind; 104 saved->devPrivate.ptr = pPix->devPrivate.ptr; 105 saved->didSave = TRUE; 106 107 pPix->devKind = pitch; 108 pPix->devPrivate.ptr = buffer; 109 } 110 } 111} 112 113static void 114DRISurfaceRestoreDrawable(DrawablePtr pDraw, 115 DRISavedDrawableState *saved) { 116 PixmapPtr pPix = (PixmapPtr)pDraw; 117 118 if(!saved->didSave) 119 return; 120 121 pPix->devKind = saved->devKind; 122 pPix->devPrivate.ptr = saved->devPrivate.ptr; 123} 124 125static void 126DRIFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, 127 DDXPointPtr pptInit, int *pwidthInit, 128 int sorted) { 129 DRISavedDrawableState saved; 130 131 DRISurfaceSetDrawable(dst, &saved); 132 133 DRIUnwrapGC(pGC); 134 135 pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); 136 137 DRIWrapGC(pGC); 138 139 DRISurfaceRestoreDrawable(dst, &saved); 140} 141 142static void 143DRISetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, 144 DDXPointPtr pptInit, int *pwidthInit, 145 int nspans, int sorted) { 146 DRISavedDrawableState saved; 147 148 DRISurfaceSetDrawable(dst, &saved); 149 150 DRIUnwrapGC(pGC); 151 152 pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); 153 154 DRIWrapGC(pGC); 155 156 DRISurfaceRestoreDrawable(dst, &saved); 157} 158 159static void 160DRIPutImage(DrawablePtr dst, GCPtr pGC, 161 int depth, int x, int y, int w, int h, 162 int leftPad, int format, char *pBits) { 163 DRISavedDrawableState saved; 164 165 DRISurfaceSetDrawable(dst, &saved); 166 167 DRIUnwrapGC(pGC); 168 169 pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits); 170 171 DRIWrapGC(pGC); 172 173 DRISurfaceRestoreDrawable(dst, &saved); 174} 175 176static RegionPtr 177DRICopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, 178 int srcx, int srcy, int w, int h, 179 int dstx, int dsty) { 180 RegionPtr pReg; 181 DRISavedDrawableState pSrcSaved, dstSaved; 182 183 DRISurfaceSetDrawable(pSrc, &pSrcSaved); 184 DRISurfaceSetDrawable(dst, &dstSaved); 185 186 DRIUnwrapGC(pGC); 187 188 pReg = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); 189 190 DRIWrapGC(pGC); 191 192 DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); 193 DRISurfaceRestoreDrawable(dst, &dstSaved); 194 195 return pReg; 196} 197 198static RegionPtr 199DRICopyPlane(DrawablePtr pSrc, DrawablePtr dst, 200 GCPtr pGC, int srcx, int srcy, 201 int w, int h, int dstx, int dsty, 202 unsigned long plane) { 203 RegionPtr pReg; 204 DRISavedDrawableState pSrcSaved, dstSaved; 205 206 DRISurfaceSetDrawable(pSrc, &pSrcSaved); 207 DRISurfaceSetDrawable(dst, &dstSaved); 208 209 210 DRIUnwrapGC(pGC); 211 212 pReg = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty, 213 plane); 214 215 DRIWrapGC(pGC); 216 217 DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); 218 DRISurfaceRestoreDrawable(dst, &dstSaved); 219 220 return pReg; 221} 222 223static void 224DRIPolyPoint(DrawablePtr dst, GCPtr pGC, 225 int mode, int npt, DDXPointPtr pptInit) { 226 DRISavedDrawableState saved; 227 228 DRISurfaceSetDrawable(dst, &saved); 229 230 DRIUnwrapGC(pGC); 231 232 pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); 233 234 DRIWrapGC(pGC); 235 236 DRISurfaceRestoreDrawable(dst, &saved); 237} 238 239static void 240DRIPolylines(DrawablePtr dst, GCPtr pGC, 241 int mode, int npt, DDXPointPtr pptInit) { 242 DRISavedDrawableState saved; 243 244 DRISurfaceSetDrawable(dst, &saved); 245 246 DRIUnwrapGC(pGC); 247 248 pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); 249 250 DRIWrapGC(pGC); 251 252 DRISurfaceRestoreDrawable(dst, &saved); 253} 254 255static void 256DRIPolySegment(DrawablePtr dst, GCPtr pGC, 257 int nseg, xSegment *pSeg) { 258 DRISavedDrawableState saved; 259 260 DRISurfaceSetDrawable(dst, &saved); 261 262 DRIUnwrapGC(pGC); 263 264 pGC->ops->PolySegment(dst, pGC, nseg, pSeg); 265 266 DRIWrapGC(pGC); 267 268 DRISurfaceRestoreDrawable(dst, &saved); 269} 270 271static void 272DRIPolyRectangle(DrawablePtr dst, GCPtr pGC, 273 int nRects, xRectangle *pRects) { 274 DRISavedDrawableState saved; 275 276 DRISurfaceSetDrawable(dst, &saved); 277 278 DRIUnwrapGC(pGC); 279 280 pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); 281 282 DRIWrapGC(pGC); 283 284 DRISurfaceRestoreDrawable(dst, &saved); 285} 286static void 287DRIPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs) { 288 DRISavedDrawableState saved; 289 290 DRISurfaceSetDrawable(dst, &saved); 291 292 DRIUnwrapGC(pGC); 293 294 pGC->ops->PolyArc(dst, pGC, narcs, parcs); 295 296 DRIWrapGC(pGC); 297 298 DRISurfaceRestoreDrawable(dst, &saved); 299} 300 301static void 302DRIFillPolygon(DrawablePtr dst, GCPtr pGC, 303 int shape, int mode, int count, 304 DDXPointPtr pptInit) { 305 DRISavedDrawableState saved; 306 307 DRISurfaceSetDrawable(dst, &saved); 308 309 DRIUnwrapGC(pGC); 310 311 pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); 312 313 DRIWrapGC(pGC); 314 315 DRISurfaceRestoreDrawable(dst, &saved); 316} 317 318static void 319DRIPolyFillRect(DrawablePtr dst, GCPtr pGC, 320 int nRectsInit, xRectangle *pRectsInit) { 321 DRISavedDrawableState saved; 322 323 DRISurfaceSetDrawable(dst, &saved); 324 325 DRIUnwrapGC(pGC); 326 327 pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); 328 329 DRIWrapGC(pGC); 330 331 DRISurfaceRestoreDrawable(dst, &saved); 332} 333 334static void 335DRIPolyFillArc(DrawablePtr dst, GCPtr pGC, 336 int narcsInit, xArc *parcsInit) { 337 DRISavedDrawableState saved; 338 339 DRISurfaceSetDrawable(dst, &saved); 340 341 DRIUnwrapGC(pGC); 342 343 pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); 344 345 DRIWrapGC(pGC); 346 347 DRISurfaceRestoreDrawable(dst, &saved); 348} 349 350static int 351DRIPolyText8(DrawablePtr dst, GCPtr pGC, 352 int x, int y, int count, char *chars) { 353 int ret; 354 DRISavedDrawableState saved; 355 356 DRISurfaceSetDrawable(dst, &saved); 357 358 DRIUnwrapGC(pGC); 359 360 ret = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); 361 362 DRIWrapGC(pGC); 363 364 DRISurfaceRestoreDrawable(dst, &saved); 365 366 return ret; 367} 368 369static int 370DRIPolyText16(DrawablePtr dst, GCPtr pGC, 371 int x, int y, int count, unsigned short *chars) { 372 int ret; 373 DRISavedDrawableState saved; 374 375 DRISurfaceSetDrawable(dst, &saved); 376 377 DRIUnwrapGC(pGC); 378 379 ret = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); 380 381 DRIWrapGC(pGC); 382 383 DRISurfaceRestoreDrawable(dst, &saved); 384 385 return ret; 386} 387 388static void 389DRIImageText8(DrawablePtr dst, GCPtr pGC, 390 int x, int y, int count, char *chars) { 391 DRISavedDrawableState saved; 392 393 DRISurfaceSetDrawable(dst, &saved); 394 395 DRIUnwrapGC(pGC); 396 397 pGC->ops->ImageText8(dst, pGC, x, y, count, chars); 398 399 DRIWrapGC(pGC); 400 401 DRISurfaceRestoreDrawable(dst, &saved); 402} 403 404static void 405DRIImageText16(DrawablePtr dst, GCPtr pGC, 406 int x, int y, int count, unsigned short *chars) { 407 DRISavedDrawableState saved; 408 409 DRISurfaceSetDrawable(dst, &saved); 410 411 DRIUnwrapGC(pGC); 412 413 pGC->ops->ImageText16(dst, pGC, x, y, count, chars); 414 415 DRIWrapGC(pGC); 416 417 DRISurfaceRestoreDrawable(dst, &saved); 418} 419 420static void 421DRIImageGlyphBlt(DrawablePtr dst, GCPtr pGC, 422 int x, int y, unsigned int nglyphInit, 423 CharInfoPtr *ppciInit, pointer unused) { 424 DRISavedDrawableState saved; 425 426 DRISurfaceSetDrawable(dst, &saved); 427 428 DRIUnwrapGC(pGC); 429 430 pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); 431 432 DRIWrapGC(pGC); 433 434 DRISurfaceRestoreDrawable(dst, &saved); 435} 436 437static void DRIPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, 438 int x, int y, unsigned int nglyph, 439 CharInfoPtr *ppci, pointer pglyphBase) { 440 DRISavedDrawableState saved; 441 442 DRISurfaceSetDrawable(dst, &saved); 443 444 DRIUnwrapGC(pGC); 445 446 pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); 447 448 DRIWrapGC(pGC); 449 450 DRISurfaceRestoreDrawable(dst, &saved); 451} 452 453static void 454DRIPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, 455 int dx, int dy, int xOrg, int yOrg) { 456 DRISavedDrawableState bitMapSaved, dstSaved; 457 458 DRISurfaceSetDrawable(&pBitMap->drawable, &bitMapSaved); 459 DRISurfaceSetDrawable(dst, &dstSaved); 460 461 DRIUnwrapGC(pGC); 462 463 pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); 464 465 DRIWrapGC(pGC); 466 467 DRISurfaceRestoreDrawable(&pBitMap->drawable, &bitMapSaved); 468 DRISurfaceRestoreDrawable(dst, &dstSaved); 469} 470 471 472static GCOps driGCOps = { 473 DRIFillSpans, 474 DRISetSpans, 475 DRIPutImage, 476 DRICopyArea, 477 DRICopyPlane, 478 DRIPolyPoint, 479 DRIPolylines, 480 DRIPolySegment, 481 DRIPolyRectangle, 482 DRIPolyArc, 483 DRIFillPolygon, 484 DRIPolyFillRect, 485 DRIPolyFillArc, 486 DRIPolyText8, 487 DRIPolyText16, 488 DRIImageText8, 489 DRIImageText16, 490 DRIImageGlyphBlt, 491 DRIPolyGlyphBlt, 492 DRIPushPixels 493}; 494 495 496static Bool 497DRICreateGC(GCPtr pGC) { 498 ScreenPtr pScreen = pGC->pScreen; 499 DRIWrapScreenRec *pScreenPriv; 500 DRIGCRec *pGCPriv; 501 Bool ret; 502 503 pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, driWrapScreenKey); 504 505 pGCPriv = DRIGetGCPriv(pGC); 506 507 unwrap(pScreenPriv, pScreen, CreateGC); 508 ret = pScreen->CreateGC(pGC); 509 510 if(ret) { 511 pGCPriv->originalOps = pGC->ops; 512 pGC->ops = &driGCOps; 513 } 514 515 wrap(pScreenPriv, pScreen, CreateGC, DRICreateGC); 516 517 return ret; 518} 519 520 521/* Return false if an error occurred. */ 522Bool 523DRIWrapInit(ScreenPtr pScreen) { 524 DRIWrapScreenRec *pScreenPriv; 525 526 if(!dixRegisterPrivateKey(&driGCKeyRec, PRIVATE_GC, sizeof(DRIGCRec))) 527 return FALSE; 528 529 if(!dixRegisterPrivateKey(&driWrapScreenKeyRec, PRIVATE_SCREEN, sizeof(DRIWrapScreenRec))) 530 return FALSE; 531 532 pScreenPriv = dixGetPrivateAddr(&pScreen->devPrivates, &driWrapScreenKeyRec); 533 pScreenPriv->CreateGC = pScreen->CreateGC; 534 pScreen->CreateGC = DRICreateGC; 535 536 return TRUE; 537} 538