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