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