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