Commit | Line | Data |
---|---|---|
a09e091a JB |
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 *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 * | |
80 | DRIGetGCPriv(GCPtr pGC) | |
81 | { | |
82 | return dixLookupPrivate(&pGC->devPrivates, driGCKey); | |
83 | } | |
84 | ||
85 | static void | |
86 | DRIUnwrapGC(GCPtr pGC) | |
87 | { | |
88 | DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); | |
89 | ||
90 | pGC->ops = pGCPriv->originalOps; | |
91 | } | |
92 | ||
93 | static void | |
94 | DRIWrapGC(GCPtr pGC) | |
95 | { | |
96 | pGC->ops = &driGCOps; | |
97 | } | |
98 | ||
99 | static void | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
448 | DRIImageGlyphBlt(DrawablePtr dst, GCPtr pGC, | |
449 | int x, int y, unsigned int nglyphInit, | |
450 | CharInfoPtr *ppciInit, pointer 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 | |
466 | DRIPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, | |
467 | int x, int y, unsigned int nglyph, | |
468 | CharInfoPtr *ppci, pointer 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 | |
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 | |
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 | |
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 | } |