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
47 typedef struct {
48 GCOps const *originalOps;
49 } DRIGCRec;
50
51 typedef struct {
52 GCOps *originalOps;
53 CreateGCProcPtr CreateGC;
54 } DRIWrapScreenRec;
55
56 typedef struct {
57 Bool didSave;
58 int devKind;
59 DevUnion devPrivate;
60 } DRISavedDrawableState;
61
62 static DevPrivateKeyRec driGCKeyRec;
63 #define driGCKey (&driGCKeyRec)
64
65 static DevPrivateKeyRec driWrapScreenKeyRec;
66 #define driWrapScreenKey (&driWrapScreenKeyRec)
67
68 static 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
79 static DRIGCRec *
DRIGetGCPriv(GCPtr pGC)80 DRIGetGCPriv(GCPtr pGC)
81 {
82 return dixLookupPrivate(&pGC->devPrivates, driGCKey);
83 }
84
85 static void
DRIUnwrapGC(GCPtr pGC)86 DRIUnwrapGC(GCPtr pGC)
87 {
88 DRIGCRec *pGCPriv = DRIGetGCPriv(pGC);
89
90 pGC->ops = pGCPriv->originalOps;
91 }
92
93 static void
DRIWrapGC(GCPtr pGC)94 DRIWrapGC(GCPtr pGC)
95 {
96 pGC->ops = &driGCOps;
97 }
98
99 static void
DRISurfaceSetDrawable(DrawablePtr pDraw,DRISavedDrawableState * saved)100 DRISurfaceSetDrawable(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
123 static void
DRISurfaceRestoreDrawable(DrawablePtr pDraw,DRISavedDrawableState * saved)124 DRISurfaceRestoreDrawable(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
136 static void
DRIFillSpans(DrawablePtr dst,GCPtr pGC,int nInit,DDXPointPtr pptInit,int * pwidthInit,int sorted)137 DRIFillSpans(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
154 static void
DRISetSpans(DrawablePtr dst,GCPtr pGC,char * pSrc,DDXPointPtr pptInit,int * pwidthInit,int nspans,int sorted)155 DRISetSpans(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
172 static void
DRIPutImage(DrawablePtr dst,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * pBits)173 DRIPutImage(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
190 static RegionPtr
DRICopyArea(DrawablePtr pSrc,DrawablePtr dst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty)191 DRICopyArea(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
213 static RegionPtr
DRICopyPlane(DrawablePtr pSrc,DrawablePtr dst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty,unsigned long plane)214 DRICopyPlane(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
238 static void
DRIPolyPoint(DrawablePtr dst,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)239 DRIPolyPoint(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
255 static void
DRIPolylines(DrawablePtr dst,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)256 DRIPolylines(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
272 static void
DRIPolySegment(DrawablePtr dst,GCPtr pGC,int nseg,xSegment * pSeg)273 DRIPolySegment(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
289 static void
DRIPolyRectangle(DrawablePtr dst,GCPtr pGC,int nRects,xRectangle * pRects)290 DRIPolyRectangle(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 }
305 static void
DRIPolyArc(DrawablePtr dst,GCPtr pGC,int narcs,xArc * parcs)306 DRIPolyArc(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
321 static void
DRIFillPolygon(DrawablePtr dst,GCPtr pGC,int shape,int mode,int count,DDXPointPtr pptInit)322 DRIFillPolygon(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
339 static void
DRIPolyFillRect(DrawablePtr dst,GCPtr pGC,int nRectsInit,xRectangle * pRectsInit)340 DRIPolyFillRect(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
356 static void
DRIPolyFillArc(DrawablePtr dst,GCPtr pGC,int narcsInit,xArc * parcsInit)357 DRIPolyFillArc(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
373 static int
DRIPolyText8(DrawablePtr dst,GCPtr pGC,int x,int y,int count,char * chars)374 DRIPolyText8(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
393 static int
DRIPolyText16(DrawablePtr dst,GCPtr pGC,int x,int y,int count,unsigned short * chars)394 DRIPolyText16(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
413 static void
DRIImageText8(DrawablePtr dst,GCPtr pGC,int x,int y,int count,char * chars)414 DRIImageText8(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
430 static void
DRIImageText16(DrawablePtr dst,GCPtr pGC,int x,int y,int count,unsigned short * chars)431 DRIImageText16(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
447 static void
DRIImageGlyphBlt(DrawablePtr dst,GCPtr pGC,int x,int y,unsigned int nglyphInit,CharInfoPtr * ppciInit,void * unused)448 DRIImageGlyphBlt(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
465 static void
DRIPolyGlyphBlt(DrawablePtr dst,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,void * pglyphBase)466 DRIPolyGlyphBlt(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
483 static void
DRIPushPixels(GCPtr pGC,PixmapPtr pBitMap,DrawablePtr dst,int dx,int dy,int xOrg,int yOrg)484 DRIPushPixels(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
502 static 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
525 static Bool
DRICreateGC(GCPtr pGC)526 DRICreateGC(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. */
551 Bool
DRIWrapInit(ScreenPtr pScreen)552 DRIWrapInit(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