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