1 /*
2 *
3 * Copyright © 2000 SuSE, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of SuSE not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. SuSE makes no representations about the
12 * suitability of this software for any purpose. It is provided "as is"
13 * without express or implied warranty.
14 *
15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Author: Keith Packard, SuSE, Inc.
23 */
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
27 #endif
29 #include "misc.h"
30 #include "scrnintstr.h"
31 #include "os.h"
32 #include "regionstr.h"
33 #include "validate.h"
34 #include "windowstr.h"
35 #include "input.h"
36 #include "resource.h"
37 #include "colormapst.h"
38 #include "cursorstr.h"
39 #include "dixstruct.h"
40 #include "gcstruct.h"
41 #include "servermd.h"
42 #include "picturestr.h"
43 #include "xace.h"
45 DevPrivateKeyRec PictureScreenPrivateKeyRec;
46 DevPrivateKeyRec PictureWindowPrivateKeyRec;
47 static int PictureGeneration;
48 RESTYPE PictureType;
49 RESTYPE PictFormatType;
50 RESTYPE GlyphSetType;
51 int PictureCmapPolicy = PictureCmapPolicyDefault;
53 Bool
54 PictureDestroyWindow (WindowPtr pWindow)
55 {
56 ScreenPtr pScreen = pWindow->drawable.pScreen;
57 PicturePtr pPicture;
58 PictureScreenPtr ps = GetPictureScreen(pScreen);
59 Bool ret;
61 while ((pPicture = GetPictureWindow(pWindow)))
62 {
63 SetPictureWindow(pWindow, pPicture->pNext);
64 if (pPicture->id)
65 FreeResource (pPicture->id, PictureType);
66 FreePicture ((pointer) pPicture, pPicture->id);
67 }
68 pScreen->DestroyWindow = ps->DestroyWindow;
69 ret = (*pScreen->DestroyWindow) (pWindow);
70 ps->DestroyWindow = pScreen->DestroyWindow;
71 pScreen->DestroyWindow = PictureDestroyWindow;
72 return ret;
73 }
75 Bool
76 PictureCloseScreen (int index, ScreenPtr pScreen)
77 {
78 PictureScreenPtr ps = GetPictureScreen(pScreen);
79 Bool ret;
80 int n;
82 pScreen->CloseScreen = ps->CloseScreen;
83 ret = (*pScreen->CloseScreen) (index, pScreen);
84 PictureResetFilters (pScreen);
85 for (n = 0; n < ps->nformats; n++)
86 if (ps->formats[n].type == PictTypeIndexed)
87 (*ps->CloseIndexed) (pScreen, &ps->formats[n]);
88 GlyphUninit (pScreen);
89 SetPictureScreen(pScreen, 0);
90 free(ps->formats);
91 free(ps);
92 return ret;
93 }
95 void
96 PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef)
97 {
98 ScreenPtr pScreen = pColormap->pScreen;
99 PictureScreenPtr ps = GetPictureScreen(pScreen);
101 pScreen->StoreColors = ps->StoreColors;
102 (*pScreen->StoreColors) (pColormap, ndef, pdef);
103 ps->StoreColors = pScreen->StoreColors;
104 pScreen->StoreColors = PictureStoreColors;
106 if (pColormap->class == PseudoColor || pColormap->class == GrayScale)
107 {
108 PictFormatPtr format = ps->formats;
109 int nformats = ps->nformats;
111 while (nformats--)
112 {
113 if (format->type == PictTypeIndexed &&
114 format->index.pColormap == pColormap)
115 {
116 (*ps->UpdateIndexed) (pScreen, format, ndef, pdef);
117 break;
118 }
119 format++;
120 }
121 }
122 }
124 static int
125 visualDepth (ScreenPtr pScreen, VisualPtr pVisual)
126 {
127 int d, v;
128 DepthPtr pDepth;
130 for (d = 0; d < pScreen->numDepths; d++)
131 {
132 pDepth = &pScreen->allowedDepths[d];
133 for (v = 0; v < pDepth->numVids; v++)
134 if (pDepth->vids[v] == pVisual->vid)
135 return pDepth->depth;
136 }
137 return 0;
138 }
140 typedef struct _formatInit {
141 CARD32 format;
142 CARD8 depth;
143 } FormatInitRec, *FormatInitPtr;
145 static int
146 addFormat (FormatInitRec formats[256],
147 int nformat,
148 CARD32 format,
149 CARD8 depth)
150 {
151 int n;
153 for (n = 0; n < nformat; n++)
154 if (formats[n].format == format && formats[n].depth == depth)
155 return nformat;
156 formats[nformat].format = format;
157 formats[nformat].depth = depth;
158 return ++nformat;
159 }
161 #define Mask(n) ((1 << (n)) - 1)
163 PictFormatPtr
164 PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp)
165 {
166 int nformats, f;
167 PictFormatPtr pFormats;
168 FormatInitRec formats[1024];
169 CARD32 format;
170 CARD8 depth;
171 VisualPtr pVisual;
172 int v;
173 int bpp;
174 int type;
175 int r, g, b;
176 int d;
177 DepthPtr pDepth;
179 nformats = 0;
180 /* formats required by protocol */
181 formats[nformats].format = PICT_a1;
182 formats[nformats].depth = 1;
183 nformats++;
184 formats[nformats].format = PICT_FORMAT(BitsPerPixel(8),
185 PICT_TYPE_A,
186 8, 0, 0, 0);
187 formats[nformats].depth = 8;
188 nformats++;
189 formats[nformats].format = PICT_FORMAT(BitsPerPixel(4),
190 PICT_TYPE_A,
191 4, 0, 0, 0);
192 formats[nformats].depth = 4;
193 nformats++;
194 formats[nformats].format = PICT_a8r8g8b8;
195 formats[nformats].depth = 32;
196 nformats++;
197 formats[nformats].format = PICT_x8r8g8b8;
198 formats[nformats].depth = 32;
199 nformats++;
200 formats[nformats].format = PICT_b8g8r8a8;
201 formats[nformats].depth = 32;
202 nformats++;
203 formats[nformats].format = PICT_b8g8r8x8;
204 formats[nformats].depth = 32;
205 nformats++;
207 /* now look through the depths and visuals adding other formats */
208 for (v = 0; v < pScreen->numVisuals; v++)
209 {
210 pVisual = &pScreen->visuals[v];
211 depth = visualDepth (pScreen, pVisual);
212 if (!depth)
213 continue;
214 bpp = BitsPerPixel (depth);
215 switch (pVisual->class) {
216 case DirectColor:
217 case TrueColor:
218 r = Ones (pVisual->redMask);
219 g = Ones (pVisual->greenMask);
220 b = Ones (pVisual->blueMask);
221 type = PICT_TYPE_OTHER;
222 /*
223 * Current rendering code supports only three direct formats,
224 * fields must be packed together at the bottom of the pixel
225 */
226 if (pVisual->offsetBlue == 0 &&
227 pVisual->offsetGreen == b &&
228 pVisual->offsetRed == b + g)
229 {
230 type = PICT_TYPE_ARGB;
231 }
232 else if (pVisual->offsetRed == 0 &&
233 pVisual->offsetGreen == r &&
234 pVisual->offsetBlue == r + g)
235 {
236 type = PICT_TYPE_ABGR;
237 }
238 else if (pVisual->offsetRed == pVisual->offsetGreen - r &&
239 pVisual->offsetGreen == pVisual->offsetBlue - g &&
240 pVisual->offsetBlue == bpp - b)
241 {
242 type = PICT_TYPE_BGRA;
243 }
244 if (type != PICT_TYPE_OTHER)
245 {
246 format = PICT_FORMAT(bpp, type, 0, r, g, b);
247 nformats = addFormat (formats, nformats, format, depth);
248 }
249 break;
250 case StaticColor:
251 case PseudoColor:
252 format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v);
253 nformats = addFormat (formats, nformats, format, depth);
254 break;
255 case StaticGray:
256 case GrayScale:
257 format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v);
258 nformats = addFormat (formats, nformats, format, depth);
259 break;
260 }
261 }
262 /*
263 * Walk supported depths and add useful Direct formats
264 */
265 for (d = 0; d < pScreen->numDepths; d++)
266 {
267 pDepth = &pScreen->allowedDepths[d];
268 bpp = BitsPerPixel (pDepth->depth);
269 format = 0;
270 switch (bpp) {
271 case 16:
272 /* depth 12 formats */
273 if (pDepth->depth >= 12)
274 {
275 nformats = addFormat (formats, nformats,
276 PICT_x4r4g4b4, pDepth->depth);
277 nformats = addFormat (formats, nformats,
278 PICT_x4b4g4r4, pDepth->depth);
279 }
280 /* depth 15 formats */
281 if (pDepth->depth >= 15)
282 {
283 nformats = addFormat (formats, nformats,
284 PICT_x1r5g5b5, pDepth->depth);
285 nformats = addFormat (formats, nformats,
286 PICT_x1b5g5r5, pDepth->depth);
287 }
288 /* depth 16 formats */
289 if (pDepth->depth >= 16)
290 {
291 nformats = addFormat (formats, nformats,
292 PICT_a1r5g5b5, pDepth->depth);
293 nformats = addFormat (formats, nformats,
294 PICT_a1b5g5r5, pDepth->depth);
295 nformats = addFormat (formats, nformats,
296 PICT_r5g6b5, pDepth->depth);
297 nformats = addFormat (formats, nformats,
298 PICT_b5g6r5, pDepth->depth);
299 nformats = addFormat (formats, nformats,
300 PICT_a4r4g4b4, pDepth->depth);
301 nformats = addFormat (formats, nformats,
302 PICT_a4b4g4r4, pDepth->depth);
303 }
304 break;
305 case 24:
306 if (pDepth->depth >= 24)
307 {
308 nformats = addFormat (formats, nformats,
309 PICT_r8g8b8, pDepth->depth);
310 nformats = addFormat (formats, nformats,
311 PICT_b8g8r8, pDepth->depth);
312 }
313 break;
314 case 32:
315 if (pDepth->depth >= 24)
316 {
317 nformats = addFormat (formats, nformats,
318 PICT_x8r8g8b8, pDepth->depth);
319 nformats = addFormat (formats, nformats,
320 PICT_x8b8g8r8, pDepth->depth);
321 }
322 if (pDepth->depth >= 30)
323 {
324 nformats = addFormat (formats, nformats,
325 PICT_a2r10g10b10, pDepth->depth);
326 nformats = addFormat (formats, nformats,
327 PICT_x2r10g10b10, pDepth->depth);
328 nformats = addFormat (formats, nformats,
329 PICT_a2b10g10r10, pDepth->depth);
330 nformats = addFormat (formats, nformats,
331 PICT_x2b10g10r10, pDepth->depth);
332 }
333 break;
334 }
335 }
338 pFormats = calloc(nformats, sizeof (PictFormatRec));
339 if (!pFormats)
340 return 0;
341 for (f = 0; f < nformats; f++)
342 {
343 pFormats[f].id = FakeClientID (0);
344 pFormats[f].depth = formats[f].depth;
345 format = formats[f].format;
346 pFormats[f].format = format;
347 switch (PICT_FORMAT_TYPE(format)) {
348 case PICT_TYPE_ARGB:
349 pFormats[f].type = PictTypeDirect;
351 pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
352 if (pFormats[f].direct.alphaMask)
353 pFormats[f].direct.alpha = (PICT_FORMAT_R(format) +
354 PICT_FORMAT_G(format) +
355 PICT_FORMAT_B(format));
357 pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
358 pFormats[f].direct.red = (PICT_FORMAT_G(format) +
359 PICT_FORMAT_B(format));
361 pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
362 pFormats[f].direct.green = PICT_FORMAT_B(format);
364 pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
365 pFormats[f].direct.blue = 0;
366 break;
368 case PICT_TYPE_ABGR:
369 pFormats[f].type = PictTypeDirect;
371 pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
372 if (pFormats[f].direct.alphaMask)
373 pFormats[f].direct.alpha = (PICT_FORMAT_B(format) +
374 PICT_FORMAT_G(format) +
375 PICT_FORMAT_R(format));
377 pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
378 pFormats[f].direct.blue = (PICT_FORMAT_G(format) +
379 PICT_FORMAT_R(format));
381 pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
382 pFormats[f].direct.green = PICT_FORMAT_R(format);
384 pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
385 pFormats[f].direct.red = 0;
386 break;
388 case PICT_TYPE_BGRA:
389 pFormats[f].type = PictTypeDirect;
391 pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
392 pFormats[f].direct.blue = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format));
394 pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
395 pFormats[f].direct.green = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) -
396 PICT_FORMAT_G(format));
398 pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
399 pFormats[f].direct.red = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) -
400 PICT_FORMAT_G(format) - PICT_FORMAT_R(format));
402 pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
403 pFormats[f].direct.alpha = 0;
404 break;
406 case PICT_TYPE_A:
407 pFormats[f].type = PictTypeDirect;
409 pFormats[f].direct.alpha = 0;
410 pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
412 /* remaining fields already set to zero */
413 break;
415 case PICT_TYPE_COLOR:
416 case PICT_TYPE_GRAY:
417 pFormats[f].type = PictTypeIndexed;
418 pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
419 break;
420 }
421 }
422 *nformatp = nformats;
423 return pFormats;
424 }
426 static VisualPtr
427 PictureFindVisual (ScreenPtr pScreen, VisualID visual)
428 {
429 int i;
430 VisualPtr pVisual;
431 for (i = 0, pVisual = pScreen->visuals;
432 i < pScreen->numVisuals;
433 i++, pVisual++)
434 {
435 if (pVisual->vid == visual)
436 return pVisual;
437 }
438 return 0;
439 }
441 Bool
442 PictureInitIndexedFormat(ScreenPtr pScreen, PictFormatPtr format)
443 {
444 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
446 if (format->type != PictTypeIndexed || format->index.pColormap)
447 return TRUE;
449 if (format->index.vid == pScreen->rootVisual) {
450 dixLookupResourceByType((pointer *)&format->index.pColormap,
451 pScreen->defColormap, RT_COLORMAP,
452 serverClient, DixGetAttrAccess);
453 } else {
454 VisualPtr pVisual = PictureFindVisual(pScreen, format->index.vid);
455 if (CreateColormap(FakeClientID (0), pScreen, pVisual,
456 &format->index.pColormap, AllocNone, 0)
457 != Success)
458 return FALSE;
459 }
460 if (!ps->InitIndexed(pScreen, format))
461 return FALSE;
462 return TRUE;
463 }
465 static Bool
466 PictureInitIndexedFormats (ScreenPtr pScreen)
467 {
468 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
469 PictFormatPtr format;
470 int nformat;
472 if (!ps)
473 return FALSE;
474 format = ps->formats;
475 nformat = ps->nformats;
476 while (nformat--)
477 if (!PictureInitIndexedFormat(pScreen, format++))
478 return FALSE;
479 return TRUE;
480 }
482 Bool
483 PictureFinishInit (void)
484 {
485 int s;
487 for (s = 0; s < screenInfo.numScreens; s++)
488 {
489 if (!PictureInitIndexedFormats (screenInfo.screens[s]))
490 return FALSE;
491 (void) AnimCurInit (screenInfo.screens[s]);
492 }
494 return TRUE;
495 }
497 Bool
498 PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel)
499 {
500 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
502 if (!ps)
503 return FALSE;
504 ps->subpixel = subpixel;
505 return TRUE;
507 }
509 int
510 PictureGetSubpixelOrder (ScreenPtr pScreen)
511 {
512 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
514 if (!ps)
515 return SubPixelUnknown;
516 return ps->subpixel;
517 }
519 PictFormatPtr
520 PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual)
521 {
522 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
523 PictFormatPtr format;
524 int nformat;
525 int type;
527 if (!ps)
528 return 0;
529 format = ps->formats;
530 nformat = ps->nformats;
531 switch (pVisual->class) {
532 case StaticGray:
533 case GrayScale:
534 case StaticColor:
535 case PseudoColor:
536 type = PictTypeIndexed;
537 break;
538 case TrueColor:
539 case DirectColor:
540 type = PictTypeDirect;
541 break;
542 default:
543 return 0;
544 }
545 while (nformat--)
546 {
547 if (format->depth == depth && format->type == type)
548 {
549 if (type == PictTypeIndexed)
550 {
551 if (format->index.vid == pVisual->vid)
552 return format;
553 }
554 else
555 {
556 if (format->direct.redMask << format->direct.red ==
557 pVisual->redMask &&
558 format->direct.greenMask << format->direct.green ==
559 pVisual->greenMask &&
560 format->direct.blueMask << format->direct.blue ==
561 pVisual->blueMask)
562 {
563 return format;
564 }
565 }
566 }
567 format++;
568 }
569 return 0;
570 }
572 PictFormatPtr
573 PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f)
574 {
575 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
576 PictFormatPtr format;
577 int nformat;
579 if (!ps)
580 return 0;
581 format = ps->formats;
582 nformat = ps->nformats;
583 while (nformat--)
584 {
585 if (format->depth == depth && format->format == (f & 0xffffff))
586 return format;
587 format++;
588 }
589 return 0;
590 }
592 int
593 PictureParseCmapPolicy (const char *name)
594 {
595 if ( strcmp (name, "default" ) == 0)
596 return PictureCmapPolicyDefault;
597 else if ( strcmp (name, "mono" ) == 0)
598 return PictureCmapPolicyMono;
599 else if ( strcmp (name, "gray" ) == 0)
600 return PictureCmapPolicyGray;
601 else if ( strcmp (name, "color" ) == 0)
602 return PictureCmapPolicyColor;
603 else if ( strcmp (name, "all" ) == 0)
604 return PictureCmapPolicyAll;
605 else
606 return PictureCmapPolicyInvalid;
607 }
609 Bool
610 PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
611 {
612 PictureScreenPtr ps;
613 int n;
614 CARD32 type, a, r, g, b;
616 if (PictureGeneration != serverGeneration)
617 {
618 PictureType = CreateNewResourceType (FreePicture, "PICTURE");
619 if (!PictureType)
620 return FALSE;
621 PictFormatType = CreateNewResourceType (FreePictFormat, "PICTFORMAT");
622 if (!PictFormatType)
623 return FALSE;
624 GlyphSetType = CreateNewResourceType (FreeGlyphSet, "GLYPHSET");
625 if (!GlyphSetType)
626 return FALSE;
627 PictureGeneration = serverGeneration;
628 }
629 if (!dixRegisterPrivateKey(&PictureScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
630 return FALSE;
632 if (!dixRegisterPrivateKey(&PictureWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
633 return FALSE;
635 if (!formats)
636 {
637 formats = PictureCreateDefaultFormats (pScreen, &nformats);
638 if (!formats)
639 return FALSE;
640 }
641 for (n = 0; n < nformats; n++)
642 {
643 if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n)))
644 {
645 free(formats);
646 return FALSE;
647 }
648 if (formats[n].type == PictTypeIndexed)
649 {
650 VisualPtr pVisual = PictureFindVisual (pScreen, formats[n].index.vid);
651 if ((pVisual->class | DynamicClass) == PseudoColor)
652 type = PICT_TYPE_COLOR;
653 else
654 type = PICT_TYPE_GRAY;
655 a = r = g = b = 0;
656 }
657 else
658 {
659 if ((formats[n].direct.redMask|
660 formats[n].direct.blueMask|
661 formats[n].direct.greenMask) == 0)
662 type = PICT_TYPE_A;
663 else if (formats[n].direct.red > formats[n].direct.blue)
664 type = PICT_TYPE_ARGB;
665 else if (formats[n].direct.red == 0)
666 type = PICT_TYPE_ABGR;
667 else
668 type = PICT_TYPE_BGRA;
669 a = Ones (formats[n].direct.alphaMask);
670 r = Ones (formats[n].direct.redMask);
671 g = Ones (formats[n].direct.greenMask);
672 b = Ones (formats[n].direct.blueMask);
673 }
674 formats[n].format = PICT_FORMAT(0,type,a,r,g,b);
675 }
676 ps = (PictureScreenPtr) malloc(sizeof (PictureScreenRec));
677 if (!ps)
678 {
679 free(formats);
680 return FALSE;
681 }
682 SetPictureScreen(pScreen, ps);
684 ps->formats = formats;
685 ps->fallback = formats;
686 ps->nformats = nformats;
688 ps->filters = 0;
689 ps->nfilters = 0;
690 ps->filterAliases = 0;
691 ps->nfilterAliases = 0;
693 ps->subpixel = SubPixelUnknown;
695 ps->CloseScreen = pScreen->CloseScreen;
696 ps->DestroyWindow = pScreen->DestroyWindow;
697 ps->StoreColors = pScreen->StoreColors;
698 pScreen->DestroyWindow = PictureDestroyWindow;
699 pScreen->CloseScreen = PictureCloseScreen;
700 pScreen->StoreColors = PictureStoreColors;
702 if (!PictureSetDefaultFilters (pScreen))
703 {
704 PictureResetFilters (pScreen);
705 SetPictureScreen(pScreen, 0);
706 free(formats);
707 free(ps);
708 return FALSE;
709 }
711 return TRUE;
712 }
714 void
715 SetPictureToDefaults (PicturePtr pPicture)
716 {
717 pPicture->refcnt = 1;
718 pPicture->repeat = 0;
719 pPicture->graphicsExposures = FALSE;
720 pPicture->subWindowMode = ClipByChildren;
721 pPicture->polyEdge = PolyEdgeSharp;
722 pPicture->polyMode = PolyModePrecise;
723 pPicture->freeCompClip = FALSE;
724 pPicture->clientClipType = CT_NONE;
725 pPicture->componentAlpha = FALSE;
726 pPicture->repeatType = RepeatNone;
728 pPicture->alphaMap = 0;
729 pPicture->alphaOrigin.x = 0;
730 pPicture->alphaOrigin.y = 0;
732 pPicture->clipOrigin.x = 0;
733 pPicture->clipOrigin.y = 0;
734 pPicture->clientClip = 0;
736 pPicture->transform = 0;
738 pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE);
739 pPicture->filter_params = 0;
740 pPicture->filter_nparams = 0;
742 pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
743 pPicture->stateChanges = -1;
744 pPicture->pSourcePict = 0;
745 }
747 PicturePtr
748 CreatePicture (Picture pid,
749 DrawablePtr pDrawable,
750 PictFormatPtr pFormat,
751 Mask vmask,
752 XID *vlist,
753 ClientPtr client,
754 int *error)
755 {
756 PicturePtr pPicture;
757 PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen);
759 pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE);
760 if (!pPicture)
761 {
762 *error = BadAlloc;
763 return 0;
764 }
766 pPicture->id = pid;
767 pPicture->pDrawable = pDrawable;
768 pPicture->pFormat = pFormat;
769 pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
771 /* security creation/labeling check */
772 *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture,
773 RT_PIXMAP, pDrawable, DixCreateAccess|DixSetAttrAccess);
774 if (*error != Success)
775 goto out;
777 if (pDrawable->type == DRAWABLE_PIXMAP)
778 {
779 ++((PixmapPtr)pDrawable)->refcnt;
780 pPicture->pNext = 0;
781 }
782 else
783 {
784 pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable));
785 SetPictureWindow(((WindowPtr) pDrawable), pPicture);
786 }
788 SetPictureToDefaults (pPicture);
790 if (vmask)
791 *error = ChangePicture (pPicture, vmask, vlist, 0, client);
792 else
793 *error = Success;
794 if (*error == Success)
795 *error = (*ps->CreatePicture) (pPicture);
796 out:
797 if (*error != Success)
798 {
799 FreePicture (pPicture, (XID) 0);
800 pPicture = 0;
801 }
802 return pPicture;
803 }
805 static CARD32 xRenderColorToCard32(xRenderColor c)
806 {
807 return
808 (c.alpha >> 8 << 24) |
809 (c.red >> 8 << 16) |
810 (c.green & 0xff00) |
811 (c.blue >> 8);
812 }
814 static void initGradient(SourcePictPtr pGradient, int stopCount,
815 xFixed *stopPoints, xRenderColor *stopColors, int *error)
816 {
817 int i;
818 xFixed dpos;
820 if (stopCount <= 0) {
821 *error = BadValue;
822 return;
823 }
825 dpos = -1;
826 for (i = 0; i < stopCount; ++i) {
827 if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) {
828 *error = BadValue;
829 return;
830 }
831 dpos = stopPoints[i];
832 }
834 pGradient->gradient.stops = malloc(stopCount*sizeof(PictGradientStop));
835 if (!pGradient->gradient.stops) {
836 *error = BadAlloc;
837 return;
838 }
840 pGradient->gradient.nstops = stopCount;
842 for (i = 0; i < stopCount; ++i) {
843 pGradient->gradient.stops[i].x = stopPoints[i];
844 pGradient->gradient.stops[i].color = stopColors[i];
845 }
846 }
848 static PicturePtr createSourcePicture(void)
849 {
850 PicturePtr pPicture;
851 pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE);
852 pPicture->pDrawable = 0;
853 pPicture->pFormat = 0;
854 pPicture->pNext = 0;
855 pPicture->format = PICT_a8r8g8b8;
857 SetPictureToDefaults(pPicture);
858 return pPicture;
859 }
861 PicturePtr
862 CreateSolidPicture (Picture pid, xRenderColor *color, int *error)
863 {
864 PicturePtr pPicture;
865 pPicture = createSourcePicture();
866 if (!pPicture) {
867 *error = BadAlloc;
868 return 0;
869 }
871 pPicture->id = pid;
872 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictSolidFill));
873 if (!pPicture->pSourcePict) {
874 *error = BadAlloc;
875 free(pPicture);
876 return 0;
877 }
878 pPicture->pSourcePict->type = SourcePictTypeSolidFill;
879 pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color);
880 return pPicture;
881 }
883 PicturePtr
884 CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2,
885 int nStops, xFixed *stops, xRenderColor *colors, int *error)
886 {
887 PicturePtr pPicture;
889 if (nStops < 2) {
890 *error = BadValue;
891 return 0;
892 }
894 pPicture = createSourcePicture();
895 if (!pPicture) {
896 *error = BadAlloc;
897 return 0;
898 }
900 pPicture->id = pid;
901 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictLinearGradient));
902 if (!pPicture->pSourcePict) {
903 *error = BadAlloc;
904 free(pPicture);
905 return 0;
906 }
908 pPicture->pSourcePict->linear.type = SourcePictTypeLinear;
909 pPicture->pSourcePict->linear.p1 = *p1;
910 pPicture->pSourcePict->linear.p2 = *p2;
912 initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
913 if (*error) {
914 free(pPicture);
915 return 0;
916 }
917 return pPicture;
918 }
920 PicturePtr
921 CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer,
922 xFixed innerRadius, xFixed outerRadius,
923 int nStops, xFixed *stops, xRenderColor *colors, int *error)
924 {
925 PicturePtr pPicture;
926 PictRadialGradient *radial;
928 if (nStops < 2) {
929 *error = BadValue;
930 return 0;
931 }
933 pPicture = createSourcePicture();
934 if (!pPicture) {
935 *error = BadAlloc;
936 return 0;
937 }
939 pPicture->id = pid;
940 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictRadialGradient));
941 if (!pPicture->pSourcePict) {
942 *error = BadAlloc;
943 free(pPicture);
944 return 0;
945 }
946 radial = &pPicture->pSourcePict->radial;
948 radial->type = SourcePictTypeRadial;
949 radial->c1.x = inner->x;
950 radial->c1.y = inner->y;
951 radial->c1.radius = innerRadius;
952 radial->c2.x = outer->x;
953 radial->c2.y = outer->y;
954 radial->c2.radius = outerRadius;
956 initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
957 if (*error) {
958 free(pPicture);
959 return 0;
960 }
961 return pPicture;
962 }
964 PicturePtr
965 CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle,
966 int nStops, xFixed *stops, xRenderColor *colors, int *error)
967 {
968 PicturePtr pPicture;
970 if (nStops < 2) {
971 *error = BadValue;
972 return 0;
973 }
975 pPicture = createSourcePicture();
976 if (!pPicture) {
977 *error = BadAlloc;
978 return 0;
979 }
981 pPicture->id = pid;
982 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictConicalGradient));
983 if (!pPicture->pSourcePict) {
984 *error = BadAlloc;
985 free(pPicture);
986 return 0;
987 }
989 pPicture->pSourcePict->conical.type = SourcePictTypeConical;
990 pPicture->pSourcePict->conical.center = *center;
991 pPicture->pSourcePict->conical.angle = angle;
993 initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
994 if (*error) {
995 free(pPicture);
996 return 0;
997 }
998 return pPicture;
999 }
1001 #define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
1003 #define NEXT_PTR(_type) ((_type) ulist++->ptr)
1005 int
1006 ChangePicture (PicturePtr pPicture,
1007 Mask vmask,
1008 XID *vlist,
1009 DevUnion *ulist,
1010 ClientPtr client)
1011 {
1012 ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
1013 PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
1014 BITS32 index2;
1015 int error = 0;
1016 BITS32 maskQ;
1018 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1019 maskQ = vmask;
1020 while (vmask && !error)
1021 {
1022 index2 = (BITS32) lowbit (vmask);
1023 vmask &= ~index2;
1024 pPicture->stateChanges |= index2;
1025 switch (index2)
1026 {
1027 case CPRepeat:
1028 {
1029 unsigned int newr;
1030 newr = NEXT_VAL(unsigned int);
1031 if (newr <= RepeatReflect)
1032 {
1033 pPicture->repeat = (newr != RepeatNone);
1034 pPicture->repeatType = newr;
1035 }
1036 else
1037 {
1038 client->errorValue = newr;
1039 error = BadValue;
1040 }
1041 }
1042 break;
1043 case CPAlphaMap:
1044 {
1045 PicturePtr pAlpha;
1047 if (vlist)
1048 {
1049 Picture pid = NEXT_VAL(Picture);
1051 if (pid == None)
1052 pAlpha = 0;
1053 else
1054 {
1055 error = dixLookupResourceByType((pointer *)&pAlpha, pid,
1056 PictureType, client,
1057 DixReadAccess);
1058 if (error != Success)
1059 {
1060 client->errorValue = pid;
1061 break;
1062 }
1063 if (pAlpha->pDrawable == NULL ||
1064 pAlpha->pDrawable->type != DRAWABLE_PIXMAP)
1065 {
1066 client->errorValue = pid;
1067 error = BadMatch;
1068 break;
1069 }
1070 }
1071 }
1072 else
1073 pAlpha = NEXT_PTR(PicturePtr);
1074 if (!error)
1075 {
1076 if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP)
1077 pAlpha->refcnt++;
1078 if (pPicture->alphaMap)
1079 FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
1080 pPicture->alphaMap = pAlpha;
1081 }
1082 }
1083 break;
1084 case CPAlphaXOrigin:
1085 pPicture->alphaOrigin.x = NEXT_VAL(INT16);
1086 break;
1087 case CPAlphaYOrigin:
1088 pPicture->alphaOrigin.y = NEXT_VAL(INT16);
1089 break;
1090 case CPClipXOrigin:
1091 pPicture->clipOrigin.x = NEXT_VAL(INT16);
1092 break;
1093 case CPClipYOrigin:
1094 pPicture->clipOrigin.y = NEXT_VAL(INT16);
1095 break;
1096 case CPClipMask:
1097 {
1098 Pixmap pid;
1099 PixmapPtr pPixmap;
1100 int clipType;
1101 if (!pScreen)
1102 return BadDrawable;
1104 if (vlist)
1105 {
1106 pid = NEXT_VAL(Pixmap);
1107 if (pid == None)
1108 {
1109 clipType = CT_NONE;
1110 pPixmap = NullPixmap;
1111 }
1112 else
1113 {
1114 clipType = CT_PIXMAP;
1115 error = dixLookupResourceByType((pointer *)&pPixmap, pid,
1116 RT_PIXMAP, client,
1117 DixReadAccess);
1118 if (error != Success)
1119 {
1120 client->errorValue = pid;
1121 break;
1122 }
1123 }
1124 }
1125 else
1126 {
1127 pPixmap = NEXT_PTR(PixmapPtr);
1128 if (pPixmap)
1129 clipType = CT_PIXMAP;
1130 else
1131 clipType = CT_NONE;
1132 }
1134 if (pPixmap)
1135 {
1136 if ((pPixmap->drawable.depth != 1) ||
1137 (pPixmap->drawable.pScreen != pScreen))
1138 {
1139 error = BadMatch;
1140 break;
1141 }
1142 else
1143 {
1144 clipType = CT_PIXMAP;
1145 pPixmap->refcnt++;
1146 }
1147 }
1148 error = (*ps->ChangePictureClip)(pPicture, clipType,
1149 (pointer)pPixmap, 0);
1150 break;
1151 }
1152 case CPGraphicsExposure:
1153 {
1154 unsigned int newe;
1155 newe = NEXT_VAL(unsigned int);
1156 if (newe <= xTrue)
1157 pPicture->graphicsExposures = newe;
1158 else
1159 {
1160 client->errorValue = newe;
1161 error = BadValue;
1162 }
1163 }
1164 break;
1165 case CPSubwindowMode:
1166 {
1167 unsigned int news;
1168 news = NEXT_VAL(unsigned int);
1169 if (news == ClipByChildren || news == IncludeInferiors)
1170 pPicture->subWindowMode = news;
1171 else
1172 {
1173 client->errorValue = news;
1174 error = BadValue;
1175 }
1176 }
1177 break;
1178 case CPPolyEdge:
1179 {
1180 unsigned int newe;
1181 newe = NEXT_VAL(unsigned int);
1182 if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
1183 pPicture->polyEdge = newe;
1184 else
1185 {
1186 client->errorValue = newe;
1187 error = BadValue;
1188 }
1189 }
1190 break;
1191 case CPPolyMode:
1192 {
1193 unsigned int newm;
1194 newm = NEXT_VAL(unsigned int);
1195 if (newm == PolyModePrecise || newm == PolyModeImprecise)
1196 pPicture->polyMode = newm;
1197 else
1198 {
1199 client->errorValue = newm;
1200 error = BadValue;
1201 }
1202 }
1203 break;
1204 case CPDither:
1205 (void) NEXT_VAL(Atom); /* unimplemented */
1206 break;
1207 case CPComponentAlpha:
1208 {
1209 unsigned int newca;
1211 newca = NEXT_VAL (unsigned int);
1212 if (newca <= xTrue)
1213 pPicture->componentAlpha = newca;
1214 else
1215 {
1216 client->errorValue = newca;
1217 error = BadValue;
1218 }
1219 }
1220 break;
1221 default:
1222 client->errorValue = maskQ;
1223 error = BadValue;
1224 break;
1225 }
1226 }
1227 if (ps)
1228 (*ps->ChangePicture) (pPicture, maskQ);
1229 return error;
1230 }
1232 int
1233 SetPictureClipRects (PicturePtr pPicture,
1234 int xOrigin,
1235 int yOrigin,
1236 int nRect,
1237 xRectangle *rects)
1238 {
1239 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1240 PictureScreenPtr ps = GetPictureScreen(pScreen);
1241 RegionPtr clientClip;
1242 int result;
1244 clientClip = RegionFromRects(nRect, rects, CT_UNSORTED);
1245 if (!clientClip)
1246 return BadAlloc;
1247 result =(*ps->ChangePictureClip) (pPicture, CT_REGION,
1248 (pointer) clientClip, 0);
1249 if (result == Success)
1250 {
1251 pPicture->clipOrigin.x = xOrigin;
1252 pPicture->clipOrigin.y = yOrigin;
1253 pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
1254 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1255 }
1256 return result;
1257 }
1259 int
1260 SetPictureClipRegion (PicturePtr pPicture,
1261 int xOrigin,
1262 int yOrigin,
1263 RegionPtr pRegion)
1264 {
1265 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1266 PictureScreenPtr ps = GetPictureScreen(pScreen);
1267 RegionPtr clientClip;
1268 int result;
1269 int type;
1271 if (pRegion)
1272 {
1273 type = CT_REGION;
1274 clientClip = RegionCreate(RegionExtents(pRegion),
1275 RegionNumRects(pRegion));
1276 if (!clientClip)
1277 return BadAlloc;
1278 if (!RegionCopy(clientClip, pRegion))
1279 {
1280 RegionDestroy(clientClip);
1281 return BadAlloc;
1282 }
1283 }
1284 else
1285 {
1286 type = CT_NONE;
1287 clientClip = 0;
1288 }
1290 result =(*ps->ChangePictureClip) (pPicture, type,
1291 (pointer) clientClip, 0);
1292 if (result == Success)
1293 {
1294 pPicture->clipOrigin.x = xOrigin;
1295 pPicture->clipOrigin.y = yOrigin;
1296 pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
1297 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1298 }
1299 return result;
1300 }
1302 static Bool
1303 transformIsIdentity(PictTransform *t)
1304 {
1305 return ((t->matrix[0][0] == t->matrix[1][1]) &&
1306 (t->matrix[0][0] == t->matrix[2][2]) &&
1307 (t->matrix[0][0] != 0) &&
1308 (t->matrix[0][1] == 0) &&
1309 (t->matrix[0][2] == 0) &&
1310 (t->matrix[1][0] == 0) &&
1311 (t->matrix[1][2] == 0) &&
1312 (t->matrix[2][0] == 0) &&
1313 (t->matrix[2][1] == 0));
1314 }
1316 int
1317 SetPictureTransform (PicturePtr pPicture,
1318 PictTransform *transform)
1319 {
1320 if (transform && transformIsIdentity (transform))
1321 transform = 0;
1323 if (transform)
1324 {
1325 if (!pPicture->transform)
1326 {
1327 pPicture->transform = (PictTransform *) malloc(sizeof (PictTransform));
1328 if (!pPicture->transform)
1329 return BadAlloc;
1330 }
1331 *pPicture->transform = *transform;
1332 }
1333 else
1334 {
1335 free(pPicture->transform);
1336 pPicture->transform = NULL;
1337 }
1338 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1340 if (pPicture->pDrawable != NULL) {
1341 int result;
1342 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1344 result = (*ps->ChangePictureTransform) (pPicture, transform);
1346 return result;
1347 }
1349 return Success;
1350 }
1352 void
1353 CopyPicture (PicturePtr pSrc,
1354 Mask mask,
1355 PicturePtr pDst)
1356 {
1357 PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen);
1358 Mask origMask = mask;
1360 pDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
1361 pDst->stateChanges |= mask;
1363 while (mask) {
1364 Mask bit = lowbit(mask);
1366 switch (bit)
1367 {
1368 case CPRepeat:
1369 pDst->repeat = pSrc->repeat;
1370 pDst->repeatType = pSrc->repeatType;
1371 break;
1372 case CPAlphaMap:
1373 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP)
1374 pSrc->alphaMap->refcnt++;
1375 if (pDst->alphaMap)
1376 FreePicture ((pointer) pDst->alphaMap, (XID) 0);
1377 pDst->alphaMap = pSrc->alphaMap;
1378 break;
1379 case CPAlphaXOrigin:
1380 pDst->alphaOrigin.x = pSrc->alphaOrigin.x;
1381 break;
1382 case CPAlphaYOrigin:
1383 pDst->alphaOrigin.y = pSrc->alphaOrigin.y;
1384 break;
1385 case CPClipXOrigin:
1386 pDst->clipOrigin.x = pSrc->clipOrigin.x;
1387 break;
1388 case CPClipYOrigin:
1389 pDst->clipOrigin.y = pSrc->clipOrigin.y;
1390 break;
1391 case CPClipMask:
1392 switch (pSrc->clientClipType) {
1393 case CT_NONE:
1394 (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
1395 break;
1396 case CT_REGION:
1397 if (!pSrc->clientClip) {
1398 (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
1399 } else {
1400 RegionPtr clientClip;
1401 RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip;
1403 clientClip = RegionCreate(
1404 RegionExtents(srcClientClip),
1405 RegionNumRects(srcClientClip));
1406 (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0);
1407 }
1408 break;
1409 default:
1410 /* XXX: CT_PIXMAP unimplemented */
1411 break;
1412 }
1413 break;
1414 case CPGraphicsExposure:
1415 pDst->graphicsExposures = pSrc->graphicsExposures;
1416 break;
1417 case CPPolyEdge:
1418 pDst->polyEdge = pSrc->polyEdge;
1419 break;
1420 case CPPolyMode:
1421 pDst->polyMode = pSrc->polyMode;
1422 break;
1423 case CPDither:
1424 break;
1425 case CPComponentAlpha:
1426 pDst->componentAlpha = pSrc->componentAlpha;
1427 break;
1428 }
1429 mask &= ~bit;
1430 }
1432 (*ps->ChangePicture)(pDst, origMask);
1433 }
1435 static void
1436 ValidateOnePicture (PicturePtr pPicture)
1437 {
1438 if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber)
1439 {
1440 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1442 (*ps->ValidatePicture) (pPicture, pPicture->stateChanges);
1443 pPicture->stateChanges = 0;
1444 pPicture->serialNumber = pPicture->pDrawable->serialNumber;
1445 }
1446 }
1448 void
1449 ValidatePicture(PicturePtr pPicture)
1450 {
1451 ValidateOnePicture (pPicture);
1452 if (pPicture->alphaMap)
1453 ValidateOnePicture (pPicture->alphaMap);
1454 }
1456 int
1457 FreePicture (pointer value,
1458 XID pid)
1459 {
1460 PicturePtr pPicture = (PicturePtr) value;
1462 if (--pPicture->refcnt == 0)
1463 {
1464 free(pPicture->transform);
1466 if (pPicture->pSourcePict)
1467 {
1468 if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
1469 free(pPicture->pSourcePict->linear.stops);
1471 free(pPicture->pSourcePict);
1472 }
1474 if (pPicture->pDrawable)
1475 {
1476 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1477 PictureScreenPtr ps = GetPictureScreen(pScreen);
1479 if (pPicture->alphaMap)
1480 FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
1481 (*ps->DestroyPicture) (pPicture);
1482 (*ps->DestroyPictureClip) (pPicture);
1483 if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
1484 {
1485 WindowPtr pWindow = (WindowPtr) pPicture->pDrawable;
1486 PicturePtr *pPrev;
1488 for (pPrev = (PicturePtr *)dixLookupPrivateAddr
1489 (&pWindow->devPrivates, PictureWindowPrivateKey);
1490 *pPrev;
1491 pPrev = &(*pPrev)->pNext)
1492 {
1493 if (*pPrev == pPicture)
1494 {
1495 *pPrev = pPicture->pNext;
1496 break;
1497 }
1498 }
1499 }
1500 else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
1501 {
1502 (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
1503 }
1504 }
1505 dixFreeObjectWithPrivates(pPicture, PRIVATE_PICTURE);
1506 }
1507 return Success;
1508 }
1510 int
1511 FreePictFormat (pointer pPictFormat,
1512 XID pid)
1513 {
1514 return Success;
1515 }
1517 /**
1518 * ReduceCompositeOp is used to choose simpler ops for cases where alpha
1519 * channels are always one and so math on the alpha channel per pixel becomes
1520 * unnecessary. It may also avoid destination reads sometimes if apps aren't
1521 * being careful to avoid these cases.
1522 */
1523 static CARD8
1524 ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1525 INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height)
1526 {
1527 Bool no_src_alpha, no_dst_alpha;
1529 /* Sampling off the edge of a RepeatNone picture introduces alpha
1530 * even if the picture itself doesn't have alpha. We don't try to
1531 * detect every case where we don't sample off the edge, just the
1532 * simplest case where there is no transform on the source
1533 * picture.
1534 */
1535 no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) &&
1536 PICT_FORMAT_A(pSrc->format) == 0 &&
1537 (pSrc->repeatType != RepeatNone ||
1538 (!pSrc->transform &&
1539 xSrc >= 0 && ySrc >= 0 &&
1540 xSrc + width <= pSrc->pDrawable->width &&
1541 ySrc + height <= pSrc->pDrawable->height)) &&
1542 pSrc->alphaMap == NULL &&
1543 pMask == NULL;
1544 no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) &&
1545 PICT_FORMAT_A(pDst->format) == 0 &&
1546 pDst->alphaMap == NULL;
1548 /* TODO, maybe: Conjoint and Disjoint op reductions? */
1550 /* Deal with simplifications where the source alpha is always 1. */
1551 if (no_src_alpha)
1552 {
1553 switch (op) {
1554 case PictOpOver:
1555 op = PictOpSrc;
1556 break;
1557 case PictOpInReverse:
1558 op = PictOpDst;
1559 break;
1560 case PictOpOutReverse:
1561 op = PictOpClear;
1562 break;
1563 case PictOpAtop:
1564 op = PictOpIn;
1565 break;
1566 case PictOpAtopReverse:
1567 op = PictOpOverReverse;
1568 break;
1569 case PictOpXor:
1570 op = PictOpOut;
1571 break;
1572 default:
1573 break;
1574 }
1575 }
1577 /* Deal with simplifications when the destination alpha is always 1 */
1578 if (no_dst_alpha)
1579 {
1580 switch (op) {
1581 case PictOpOverReverse:
1582 op = PictOpDst;
1583 break;
1584 case PictOpIn:
1585 op = PictOpSrc;
1586 break;
1587 case PictOpOut:
1588 op = PictOpClear;
1589 break;
1590 case PictOpAtop:
1591 op = PictOpOver;
1592 break;
1593 case PictOpXor:
1594 op = PictOpOutReverse;
1595 break;
1596 default:
1597 break;
1598 }
1599 }
1601 /* Reduce some con/disjoint ops to the basic names. */
1602 switch (op) {
1603 case PictOpDisjointClear:
1604 case PictOpConjointClear:
1605 op = PictOpClear;
1606 break;
1607 case PictOpDisjointSrc:
1608 case PictOpConjointSrc:
1609 op = PictOpSrc;
1610 break;
1611 case PictOpDisjointDst:
1612 case PictOpConjointDst:
1613 op = PictOpDst;
1614 break;
1615 default:
1616 break;
1617 }
1619 return op;
1620 }
1622 void
1623 CompositePicture (CARD8 op,
1624 PicturePtr pSrc,
1625 PicturePtr pMask,
1626 PicturePtr pDst,
1627 INT16 xSrc,
1628 INT16 ySrc,
1629 INT16 xMask,
1630 INT16 yMask,
1631 INT16 xDst,
1632 INT16 yDst,
1633 CARD16 width,
1634 CARD16 height)
1635 {
1636 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1638 ValidatePicture (pSrc);
1639 if (pMask)
1640 ValidatePicture (pMask);
1641 ValidatePicture (pDst);
1643 op = ReduceCompositeOp (op, pSrc, pMask, pDst, xSrc, ySrc, width, height);
1644 if (op == PictOpDst)
1645 return;
1647 (*ps->Composite) (op,
1648 pSrc,
1649 pMask,
1650 pDst,
1651 xSrc,
1652 ySrc,
1653 xMask,
1654 yMask,
1655 xDst,
1656 yDst,
1657 width,
1658 height);
1659 }
1661 void
1662 CompositeRects (CARD8 op,
1663 PicturePtr pDst,
1664 xRenderColor *color,
1665 int nRect,
1666 xRectangle *rects)
1667 {
1668 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1670 ValidatePicture (pDst);
1671 (*ps->CompositeRects) (op, pDst, color, nRect, rects);
1672 }
1674 void
1675 CompositeTrapezoids (CARD8 op,
1676 PicturePtr pSrc,
1677 PicturePtr pDst,
1678 PictFormatPtr maskFormat,
1679 INT16 xSrc,
1680 INT16 ySrc,
1681 int ntrap,
1682 xTrapezoid *traps)
1683 {
1684 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1686 ValidatePicture (pSrc);
1687 ValidatePicture (pDst);
1688 (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
1689 }
1691 void
1692 CompositeTriangles (CARD8 op,
1693 PicturePtr pSrc,
1694 PicturePtr pDst,
1695 PictFormatPtr maskFormat,
1696 INT16 xSrc,
1697 INT16 ySrc,
1698 int ntriangles,
1699 xTriangle *triangles)
1700 {
1701 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1703 ValidatePicture (pSrc);
1704 ValidatePicture (pDst);
1705 (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles);
1706 }
1708 void
1709 CompositeTriStrip (CARD8 op,
1710 PicturePtr pSrc,
1711 PicturePtr pDst,
1712 PictFormatPtr maskFormat,
1713 INT16 xSrc,
1714 INT16 ySrc,
1715 int npoints,
1716 xPointFixed *points)
1717 {
1718 xTriangle *tris, *tri;
1719 int ntri;
1721 if (npoints < 3)
1722 return;
1723 ntri = npoints - 2;
1724 tris = malloc(ntri * sizeof (xTriangle));
1725 if (!tris)
1726 return;
1727 for (tri = tris; npoints >= 3; npoints--, points++, tri++)
1728 {
1729 tri->p1 = points[0];
1730 tri->p2 = points[1];
1731 tri->p3 = points[2];
1732 }
1733 CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
1734 free(tris);
1735 }
1737 void
1738 CompositeTriFan (CARD8 op,
1739 PicturePtr pSrc,
1740 PicturePtr pDst,
1741 PictFormatPtr maskFormat,
1742 INT16 xSrc,
1743 INT16 ySrc,
1744 int npoints,
1745 xPointFixed *points)
1746 {
1747 xTriangle *tris, *tri;
1748 xPointFixed *first;
1749 int ntri;
1751 if (npoints < 3)
1752 return;
1753 ntri = npoints - 2;
1754 tris = malloc(ntri * sizeof (xTriangle));
1755 if (!tris)
1756 return;
1757 first = points++;
1758 for (tri = tris; npoints >= 3; npoints--, points++, tri++)
1759 {
1760 tri->p1 = *first;
1761 tri->p2 = points[0];
1762 tri->p3 = points[1];
1763 }
1764 CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
1765 free(tris);
1766 }
1768 void
1769 AddTraps (PicturePtr pPicture,
1770 INT16 xOff,
1771 INT16 yOff,
1772 int ntrap,
1773 xTrap *traps)
1774 {
1775 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1777 ValidatePicture (pPicture);
1778 (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps);
1779 }