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 */
24
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
27 #endif
28
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"
44 #ifdef PANORAMIX
45 #include "panoramiXsrv.h"
46 #endif
47
48 DevPrivateKeyRec PictureScreenPrivateKeyRec;
49 DevPrivateKeyRec PictureWindowPrivateKeyRec;
50 static int PictureGeneration;
51 RESTYPE PictureType;
52 RESTYPE PictFormatType;
53 RESTYPE GlyphSetType;
54 int PictureCmapPolicy = PictureCmapPolicyDefault;
55
56 PictFormatPtr
PictureWindowFormat(WindowPtr pWindow)57 PictureWindowFormat(WindowPtr pWindow)
58 {
59 ScreenPtr pScreen = pWindow->drawable.pScreen;
60 return PictureMatchVisual(pScreen, pWindow->drawable.depth,
61 WindowGetVisual(pWindow));
62 }
63
64 static Bool
PictureDestroyWindow(WindowPtr pWindow)65 PictureDestroyWindow(WindowPtr pWindow)
66 {
67 ScreenPtr pScreen = pWindow->drawable.pScreen;
68 PicturePtr pPicture;
69 PictureScreenPtr ps = GetPictureScreen(pScreen);
70 Bool ret;
71
72 while ((pPicture = GetPictureWindow(pWindow))) {
73 SetPictureWindow(pWindow, pPicture->pNext);
74 if (pPicture->id)
75 FreeResource(pPicture->id, PictureType);
76 FreePicture((void *) pPicture, pPicture->id);
77 }
78 pScreen->DestroyWindow = ps->DestroyWindow;
79 ret = (*pScreen->DestroyWindow) (pWindow);
80 ps->DestroyWindow = pScreen->DestroyWindow;
81 pScreen->DestroyWindow = PictureDestroyWindow;
82 return ret;
83 }
84
85 static Bool
PictureCloseScreen(ScreenPtr pScreen)86 PictureCloseScreen(ScreenPtr pScreen)
87 {
88 PictureScreenPtr ps = GetPictureScreen(pScreen);
89 Bool ret;
90 int n;
91
92 pScreen->CloseScreen = ps->CloseScreen;
93 ret = (*pScreen->CloseScreen) (pScreen);
94 PictureResetFilters(pScreen);
95 for (n = 0; n < ps->nformats; n++)
96 if (ps->formats[n].type == PictTypeIndexed)
97 (*ps->CloseIndexed) (pScreen, &ps->formats[n]);
98 GlyphUninit(pScreen);
99 SetPictureScreen(pScreen, 0);
100 free(ps->formats);
101 free(ps);
102 return ret;
103 }
104
105 static void
PictureStoreColors(ColormapPtr pColormap,int ndef,xColorItem * pdef)106 PictureStoreColors(ColormapPtr pColormap, int ndef, xColorItem * pdef)
107 {
108 ScreenPtr pScreen = pColormap->pScreen;
109 PictureScreenPtr ps = GetPictureScreen(pScreen);
110
111 pScreen->StoreColors = ps->StoreColors;
112 (*pScreen->StoreColors) (pColormap, ndef, pdef);
113 ps->StoreColors = pScreen->StoreColors;
114 pScreen->StoreColors = PictureStoreColors;
115
116 if (pColormap->class == PseudoColor || pColormap->class == GrayScale) {
117 PictFormatPtr format = ps->formats;
118 int nformats = ps->nformats;
119
120 while (nformats--) {
121 if (format->type == PictTypeIndexed &&
122 format->index.pColormap == pColormap) {
123 (*ps->UpdateIndexed) (pScreen, format, ndef, pdef);
124 break;
125 }
126 format++;
127 }
128 }
129 }
130
131 static int
visualDepth(ScreenPtr pScreen,VisualPtr pVisual)132 visualDepth(ScreenPtr pScreen, VisualPtr pVisual)
133 {
134 int d, v;
135 DepthPtr pDepth;
136
137 for (d = 0; d < pScreen->numDepths; d++) {
138 pDepth = &pScreen->allowedDepths[d];
139 for (v = 0; v < pDepth->numVids; v++)
140 if (pDepth->vids[v] == pVisual->vid)
141 return pDepth->depth;
142 }
143 return 0;
144 }
145
146 typedef struct _formatInit {
147 CARD32 format;
148 CARD8 depth;
149 } FormatInitRec, *FormatInitPtr;
150
151 static void
addFormat(FormatInitRec formats[256],int * nformat,CARD32 format,CARD8 depth)152 addFormat(FormatInitRec formats[256], int *nformat, CARD32 format, CARD8 depth)
153 {
154 int n;
155
156 for (n = 0; n < *nformat; n++)
157 if (formats[n].format == format && formats[n].depth == depth)
158 return;
159 formats[*nformat].format = format;
160 formats[*nformat].depth = depth;
161 ++*nformat;
162 }
163
164 #define Mask(n) ((1 << (n)) - 1)
165
166 static PictFormatPtr
PictureCreateDefaultFormats(ScreenPtr pScreen,int * nformatp)167 PictureCreateDefaultFormats(ScreenPtr pScreen, int *nformatp)
168 {
169 int nformats = 0, f;
170 PictFormatPtr pFormats;
171 FormatInitRec formats[1024];
172 CARD32 format;
173 CARD8 depth;
174 VisualPtr pVisual;
175 int v;
176 int bpp;
177 int type;
178 int r, g, b;
179 int d;
180 DepthPtr pDepth;
181
182 nformats = 0;
183 /* formats required by protocol */
184 formats[nformats].format = PICT_a1;
185 formats[nformats].depth = 1;
186 nformats++;
187 formats[nformats].format = PICT_FORMAT(BitsPerPixel(8),
188 PICT_TYPE_A, 8, 0, 0, 0);
189 formats[nformats].depth = 8;
190 nformats++;
191 formats[nformats].format = PICT_FORMAT(BitsPerPixel(4),
192 PICT_TYPE_A, 4, 0, 0, 0);
193 formats[nformats].depth = 4;
194 nformats++;
195 formats[nformats].format = PICT_a8r8g8b8;
196 formats[nformats].depth = 32;
197 nformats++;
198 formats[nformats].format = PICT_x8r8g8b8;
199 formats[nformats].depth = 32;
200 nformats++;
201 formats[nformats].format = PICT_b8g8r8a8;
202 formats[nformats].depth = 32;
203 nformats++;
204 formats[nformats].format = PICT_b8g8r8x8;
205 formats[nformats].depth = 32;
206 nformats++;
207
208 /* now look through the depths and visuals adding other formats */
209 for (v = 0; v < pScreen->numVisuals; v++) {
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 && pVisual->offsetRed == b + g) {
228 type = PICT_TYPE_ARGB;
229 }
230 else if (pVisual->offsetRed == 0 &&
231 pVisual->offsetGreen == r &&
232 pVisual->offsetBlue == r + g) {
233 type = PICT_TYPE_ABGR;
234 }
235 else if (pVisual->offsetRed == pVisual->offsetGreen - r &&
236 pVisual->offsetGreen == pVisual->offsetBlue - g &&
237 pVisual->offsetBlue == bpp - b) {
238 type = PICT_TYPE_BGRA;
239 }
240 if (type != PICT_TYPE_OTHER) {
241 format = PICT_FORMAT(bpp, type, 0, r, g, b);
242 addFormat(formats, &nformats, format, depth);
243 }
244 break;
245 case StaticColor:
246 case PseudoColor:
247 format = PICT_VISFORMAT(bpp, PICT_TYPE_COLOR, v);
248 addFormat(formats, &nformats, format, depth);
249 break;
250 case StaticGray:
251 case GrayScale:
252 format = PICT_VISFORMAT(bpp, PICT_TYPE_GRAY, v);
253 addFormat(formats, &nformats, format, depth);
254 break;
255 }
256 }
257 /*
258 * Walk supported depths and add useful Direct formats
259 */
260 for (d = 0; d < pScreen->numDepths; d++) {
261 pDepth = &pScreen->allowedDepths[d];
262 bpp = BitsPerPixel(pDepth->depth);
263 format = 0;
264 switch (bpp) {
265 case 16:
266 /* depth 12 formats */
267 if (pDepth->depth >= 12) {
268 addFormat(formats, &nformats, PICT_x4r4g4b4, pDepth->depth);
269 addFormat(formats, &nformats, PICT_x4b4g4r4, pDepth->depth);
270 }
271 /* depth 15 formats */
272 if (pDepth->depth >= 15) {
273 addFormat(formats, &nformats, PICT_x1r5g5b5, pDepth->depth);
274 addFormat(formats, &nformats, PICT_x1b5g5r5, pDepth->depth);
275 }
276 /* depth 16 formats */
277 if (pDepth->depth >= 16) {
278 addFormat(formats, &nformats, PICT_a1r5g5b5, pDepth->depth);
279 addFormat(formats, &nformats, PICT_a1b5g5r5, pDepth->depth);
280 addFormat(formats, &nformats, PICT_r5g6b5, pDepth->depth);
281 addFormat(formats, &nformats, PICT_b5g6r5, pDepth->depth);
282 addFormat(formats, &nformats, PICT_a4r4g4b4, pDepth->depth);
283 addFormat(formats, &nformats, PICT_a4b4g4r4, pDepth->depth);
284 }
285 break;
286 case 32:
287 if (pDepth->depth >= 24) {
288 addFormat(formats, &nformats, PICT_x8r8g8b8, pDepth->depth);
289 addFormat(formats, &nformats, PICT_x8b8g8r8, pDepth->depth);
290 }
291 if (pDepth->depth >= 30) {
292 addFormat(formats, &nformats, PICT_a2r10g10b10, pDepth->depth);
293 addFormat(formats, &nformats, PICT_x2r10g10b10, pDepth->depth);
294 addFormat(formats, &nformats, PICT_a2b10g10r10, pDepth->depth);
295 addFormat(formats, &nformats, PICT_x2b10g10r10, pDepth->depth);
296 }
297 break;
298 }
299 }
300
301 pFormats = calloc(nformats, sizeof(PictFormatRec));
302 if (!pFormats)
303 return 0;
304 for (f = 0; f < nformats; f++) {
305 pFormats[f].id = FakeClientID(0);
306 pFormats[f].depth = formats[f].depth;
307 format = formats[f].format;
308 pFormats[f].format = format;
309 switch (PICT_FORMAT_TYPE(format)) {
310 case PICT_TYPE_ARGB:
311 pFormats[f].type = PictTypeDirect;
312
313 pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A(format));
314
315 if (pFormats[f].direct.alphaMask)
316 pFormats[f].direct.alpha = (PICT_FORMAT_R(format) +
317 PICT_FORMAT_G(format) +
318 PICT_FORMAT_B(format));
319
320 pFormats[f].direct.redMask = Mask (PICT_FORMAT_R(format));
321
322 pFormats[f].direct.red = (PICT_FORMAT_G(format) +
323 PICT_FORMAT_B(format));
324
325 pFormats[f].direct.greenMask = Mask (PICT_FORMAT_G(format));
326
327 pFormats[f].direct.green = PICT_FORMAT_B(format);
328
329 pFormats[f].direct.blueMask = Mask (PICT_FORMAT_B(format));
330
331 pFormats[f].direct.blue = 0;
332 break;
333
334 case PICT_TYPE_ABGR:
335 pFormats[f].type = PictTypeDirect;
336
337 pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A(format));
338
339 if (pFormats[f].direct.alphaMask)
340 pFormats[f].direct.alpha = (PICT_FORMAT_B(format) +
341 PICT_FORMAT_G(format) +
342 PICT_FORMAT_R(format));
343
344 pFormats[f].direct.blueMask = Mask (PICT_FORMAT_B(format));
345
346 pFormats[f].direct.blue = (PICT_FORMAT_G(format) +
347 PICT_FORMAT_R(format));
348
349 pFormats[f].direct.greenMask = Mask (PICT_FORMAT_G(format));
350
351 pFormats[f].direct.green = PICT_FORMAT_R(format);
352
353 pFormats[f].direct.redMask = Mask (PICT_FORMAT_R(format));
354
355 pFormats[f].direct.red = 0;
356 break;
357
358 case PICT_TYPE_BGRA:
359 pFormats[f].type = PictTypeDirect;
360
361 pFormats[f].direct.blueMask = Mask (PICT_FORMAT_B(format));
362
363 pFormats[f].direct.blue =
364 (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format));
365
366 pFormats[f].direct.greenMask = Mask (PICT_FORMAT_G(format));
367
368 pFormats[f].direct.green =
369 (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) -
370 PICT_FORMAT_G(format));
371
372 pFormats[f].direct.redMask = Mask (PICT_FORMAT_R(format));
373
374 pFormats[f].direct.red =
375 (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) -
376 PICT_FORMAT_G(format) - PICT_FORMAT_R(format));
377
378 pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A(format));
379
380 pFormats[f].direct.alpha = 0;
381 break;
382
383 case PICT_TYPE_A:
384 pFormats[f].type = PictTypeDirect;
385
386 pFormats[f].direct.alpha = 0;
387 pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A(format));
388
389 /* remaining fields already set to zero */
390 break;
391
392 case PICT_TYPE_COLOR:
393 case PICT_TYPE_GRAY:
394 pFormats[f].type = PictTypeIndexed;
395 pFormats[f].index.vid =
396 pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
397 break;
398 }
399 }
400 *nformatp = nformats;
401 return pFormats;
402 }
403
404 static VisualPtr
PictureFindVisual(ScreenPtr pScreen,VisualID visual)405 PictureFindVisual(ScreenPtr pScreen, VisualID visual)
406 {
407 int i;
408 VisualPtr pVisual;
409
410 for (i = 0, pVisual = pScreen->visuals;
411 i < pScreen->numVisuals; i++, pVisual++) {
412 if (pVisual->vid == visual)
413 return pVisual;
414 }
415 return 0;
416 }
417
418 static Bool
PictureInitIndexedFormat(ScreenPtr pScreen,PictFormatPtr format)419 PictureInitIndexedFormat(ScreenPtr pScreen, PictFormatPtr format)
420 {
421 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
422
423 if (format->type != PictTypeIndexed || format->index.pColormap)
424 return TRUE;
425
426 if (format->index.vid == pScreen->rootVisual) {
427 dixLookupResourceByType((void **) &format->index.pColormap,
428 pScreen->defColormap, RT_COLORMAP,
429 serverClient, DixGetAttrAccess);
430 }
431 else {
432 VisualPtr pVisual = PictureFindVisual(pScreen, format->index.vid);
433
434 if (CreateColormap(FakeClientID(0), pScreen, pVisual,
435 &format->index.pColormap, AllocNone, 0)
436 != Success)
437 return FALSE;
438 }
439 if (!ps->InitIndexed(pScreen, format))
440 return FALSE;
441 return TRUE;
442 }
443
444 static Bool
PictureInitIndexedFormats(ScreenPtr pScreen)445 PictureInitIndexedFormats(ScreenPtr pScreen)
446 {
447 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
448 PictFormatPtr format;
449 int nformat;
450
451 if (!ps)
452 return FALSE;
453 format = ps->formats;
454 nformat = ps->nformats;
455 while (nformat--)
456 if (!PictureInitIndexedFormat(pScreen, format++))
457 return FALSE;
458 return TRUE;
459 }
460
461 Bool
PictureFinishInit(void)462 PictureFinishInit(void)
463 {
464 int s;
465
466 for (s = 0; s < screenInfo.numScreens; s++) {
467 if (!PictureInitIndexedFormats(screenInfo.screens[s]))
468 return FALSE;
469 (void) AnimCurInit(screenInfo.screens[s]);
470 }
471
472 return TRUE;
473 }
474
475 Bool
PictureSetSubpixelOrder(ScreenPtr pScreen,int subpixel)476 PictureSetSubpixelOrder(ScreenPtr pScreen, int subpixel)
477 {
478 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
479
480 if (!ps)
481 return FALSE;
482 ps->subpixel = subpixel;
483 return TRUE;
484
485 }
486
487 int
PictureGetSubpixelOrder(ScreenPtr pScreen)488 PictureGetSubpixelOrder(ScreenPtr pScreen)
489 {
490 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
491
492 if (!ps)
493 return SubPixelUnknown;
494 return ps->subpixel;
495 }
496
497 PictFormatPtr
PictureMatchVisual(ScreenPtr pScreen,int depth,VisualPtr pVisual)498 PictureMatchVisual(ScreenPtr pScreen, int depth, VisualPtr pVisual)
499 {
500 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
501 PictFormatPtr format;
502 int nformat;
503 int type;
504
505 if (!ps)
506 return 0;
507 format = ps->formats;
508 nformat = ps->nformats;
509 switch (pVisual->class) {
510 case StaticGray:
511 case GrayScale:
512 case StaticColor:
513 case PseudoColor:
514 type = PictTypeIndexed;
515 break;
516 case TrueColor:
517 case DirectColor:
518 type = PictTypeDirect;
519 break;
520 default:
521 return 0;
522 }
523 while (nformat--) {
524 if (format->depth == depth && format->type == type) {
525 if (type == PictTypeIndexed) {
526 if (format->index.vid == pVisual->vid)
527 return format;
528 }
529 else {
530 if (format->direct.redMask << format->direct.red ==
531 pVisual->redMask &&
532 format->direct.greenMask << format->direct.green ==
533 pVisual->greenMask &&
534 format->direct.blueMask << format->direct.blue ==
535 pVisual->blueMask) {
536 return format;
537 }
538 }
539 }
540 format++;
541 }
542 return 0;
543 }
544
545 PictFormatPtr
PictureMatchFormat(ScreenPtr pScreen,int depth,CARD32 f)546 PictureMatchFormat(ScreenPtr pScreen, int depth, CARD32 f)
547 {
548 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
549 PictFormatPtr format;
550 int nformat;
551
552 if (!ps)
553 return 0;
554 format = ps->formats;
555 nformat = ps->nformats;
556 while (nformat--) {
557 if (format->depth == depth && format->format == (f & 0xffffff))
558 return format;
559 format++;
560 }
561 return 0;
562 }
563
564 int
PictureParseCmapPolicy(const char * name)565 PictureParseCmapPolicy(const char *name)
566 {
567 if (strcmp(name, "default") == 0)
568 return PictureCmapPolicyDefault;
569 else if (strcmp(name, "mono") == 0)
570 return PictureCmapPolicyMono;
571 else if (strcmp(name, "gray") == 0)
572 return PictureCmapPolicyGray;
573 else if (strcmp(name, "color") == 0)
574 return PictureCmapPolicyColor;
575 else if (strcmp(name, "all") == 0)
576 return PictureCmapPolicyAll;
577 else
578 return PictureCmapPolicyInvalid;
579 }
580
581 /** @see GetDefaultBytes */
582 static void
GetPictureBytes(void * value,XID id,ResourceSizePtr size)583 GetPictureBytes(void *value, XID id, ResourceSizePtr size)
584 {
585 PicturePtr picture = value;
586
587 /* Currently only pixmap bytes are reported to clients. */
588 size->resourceSize = 0;
589
590 size->refCnt = picture->refcnt;
591
592 /* Calculate pixmap reference sizes. */
593 size->pixmapRefSize = 0;
594 if (picture->pDrawable && (picture->pDrawable->type == DRAWABLE_PIXMAP))
595 {
596 SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
597 ResourceSizeRec pixmapSize = { 0, 0, 0 };
598 PixmapPtr pixmap = (PixmapPtr)picture->pDrawable;
599 pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
600 size->pixmapRefSize += pixmapSize.pixmapRefSize;
601 }
602 }
603
604 static int
FreePictFormat(void * pPictFormat,XID pid)605 FreePictFormat(void *pPictFormat, XID pid)
606 {
607 return Success;
608 }
609
610 Bool
PictureInit(ScreenPtr pScreen,PictFormatPtr formats,int nformats)611 PictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
612 {
613 PictureScreenPtr ps;
614 int n;
615 CARD32 type, a, r, g, b;
616
617 if (PictureGeneration != serverGeneration) {
618 PictureType = CreateNewResourceType(FreePicture, "PICTURE");
619 if (!PictureType)
620 return FALSE;
621 SetResourceTypeSizeFunc(PictureType, GetPictureBytes);
622 PictFormatType = CreateNewResourceType(FreePictFormat, "PICTFORMAT");
623 if (!PictFormatType)
624 return FALSE;
625 GlyphSetType = CreateNewResourceType(FreeGlyphSet, "GLYPHSET");
626 if (!GlyphSetType)
627 return FALSE;
628 PictureGeneration = serverGeneration;
629 }
630 if (!dixRegisterPrivateKey(&PictureScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
631 return FALSE;
632
633 if (!dixRegisterPrivateKey(&PictureWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
634 return FALSE;
635
636 if (!formats) {
637 formats = PictureCreateDefaultFormats(pScreen, &nformats);
638 if (!formats)
639 return FALSE;
640 }
641 for (n = 0; n < nformats; n++) {
642 if (!AddResource
643 (formats[n].id, PictFormatType, (void *) (formats + n))) {
644 int i;
645 for (i = 0; i < n; i++)
646 FreeResource(formats[i].id, RT_NONE);
647 free(formats);
648 return FALSE;
649 }
650 if (formats[n].type == PictTypeIndexed) {
651 VisualPtr pVisual =
652 PictureFindVisual(pScreen, formats[n].index.vid);
653 if ((pVisual->class | DynamicClass) == PseudoColor)
654 type = PICT_TYPE_COLOR;
655 else
656 type = PICT_TYPE_GRAY;
657 a = r = g = b = 0;
658 }
659 else {
660 if ((formats[n].direct.redMask |
661 formats[n].direct.blueMask | 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 free(formats);
679 return FALSE;
680 }
681 SetPictureScreen(pScreen, ps);
682
683 ps->formats = formats;
684 ps->fallback = formats;
685 ps->nformats = nformats;
686
687 ps->filters = 0;
688 ps->nfilters = 0;
689 ps->filterAliases = 0;
690 ps->nfilterAliases = 0;
691
692 ps->subpixel = SubPixelUnknown;
693
694 ps->CloseScreen = pScreen->CloseScreen;
695 ps->DestroyWindow = pScreen->DestroyWindow;
696 ps->StoreColors = pScreen->StoreColors;
697 pScreen->DestroyWindow = PictureDestroyWindow;
698 pScreen->CloseScreen = PictureCloseScreen;
699 pScreen->StoreColors = PictureStoreColors;
700
701 if (!PictureSetDefaultFilters(pScreen)) {
702 PictureResetFilters(pScreen);
703 SetPictureScreen(pScreen, 0);
704 free(formats);
705 free(ps);
706 return FALSE;
707 }
708
709 return TRUE;
710 }
711
712 static void
SetPictureToDefaults(PicturePtr pPicture)713 SetPictureToDefaults(PicturePtr pPicture)
714 {
715 pPicture->refcnt = 1;
716 pPicture->repeat = 0;
717 pPicture->graphicsExposures = FALSE;
718 pPicture->subWindowMode = ClipByChildren;
719 pPicture->polyEdge = PolyEdgeSharp;
720 pPicture->polyMode = PolyModePrecise;
721 pPicture->freeCompClip = FALSE;
722 pPicture->componentAlpha = FALSE;
723 pPicture->repeatType = RepeatNone;
724
725 pPicture->alphaMap = 0;
726 pPicture->alphaOrigin.x = 0;
727 pPicture->alphaOrigin.y = 0;
728
729 pPicture->clipOrigin.x = 0;
730 pPicture->clipOrigin.y = 0;
731 pPicture->clientClip = 0;
732
733 pPicture->transform = 0;
734
735 pPicture->filter = PictureGetFilterId(FilterNearest, -1, TRUE);
736 pPicture->filter_params = 0;
737 pPicture->filter_nparams = 0;
738
739 pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
740 pPicture->stateChanges = -1;
741 pPicture->pSourcePict = 0;
742 }
743
744 PicturePtr
CreatePicture(Picture pid,DrawablePtr pDrawable,PictFormatPtr pFormat,Mask vmask,XID * vlist,ClientPtr client,int * error)745 CreatePicture(Picture pid,
746 DrawablePtr pDrawable,
747 PictFormatPtr pFormat,
748 Mask vmask, XID *vlist, ClientPtr client, int *error)
749 {
750 PicturePtr pPicture;
751 PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen);
752
753 pPicture = dixAllocateScreenObjectWithPrivates(pDrawable->pScreen,
754 PictureRec, PRIVATE_PICTURE);
755 if (!pPicture) {
756 *error = BadAlloc;
757 return 0;
758 }
759
760 pPicture->id = pid;
761 pPicture->pDrawable = pDrawable;
762 pPicture->pFormat = pFormat;
763 pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
764
765 /* security creation/labeling check */
766 *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture,
767 RT_PIXMAP, pDrawable, DixCreateAccess | DixSetAttrAccess);
768 if (*error != Success)
769 goto out;
770
771 if (pDrawable->type == DRAWABLE_PIXMAP) {
772 ++((PixmapPtr) pDrawable)->refcnt;
773 pPicture->pNext = 0;
774 }
775 else {
776 pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable));
777 SetPictureWindow(((WindowPtr) pDrawable), pPicture);
778 }
779
780 SetPictureToDefaults(pPicture);
781
782 if (vmask)
783 *error = ChangePicture(pPicture, vmask, vlist, 0, client);
784 else
785 *error = Success;
786 if (*error == Success)
787 *error = (*ps->CreatePicture) (pPicture);
788 out:
789 if (*error != Success) {
790 FreePicture(pPicture, (XID) 0);
791 pPicture = 0;
792 }
793 return pPicture;
794 }
795
796 static CARD32
xRenderColorToCard32(xRenderColor c)797 xRenderColorToCard32(xRenderColor c)
798 {
799 return
800 (c.alpha >> 8 << 24) |
801 (c.red >> 8 << 16) | (c.green & 0xff00) | (c.blue >> 8);
802 }
803
804 static void
initGradient(SourcePictPtr pGradient,int stopCount,xFixed * stopPoints,xRenderColor * stopColors,int * error)805 initGradient(SourcePictPtr pGradient, int stopCount,
806 xFixed * stopPoints, xRenderColor * stopColors, int *error)
807 {
808 int i;
809 xFixed dpos;
810
811 if (stopCount <= 0) {
812 *error = BadValue;
813 return;
814 }
815
816 dpos = -1;
817 for (i = 0; i < stopCount; ++i) {
818 if (stopPoints[i] < dpos || stopPoints[i] > (1 << 16)) {
819 *error = BadValue;
820 return;
821 }
822 dpos = stopPoints[i];
823 }
824
825 pGradient->gradient.stops = xallocarray(stopCount, sizeof(PictGradientStop));
826 if (!pGradient->gradient.stops) {
827 *error = BadAlloc;
828 return;
829 }
830
831 pGradient->gradient.nstops = stopCount;
832
833 for (i = 0; i < stopCount; ++i) {
834 pGradient->gradient.stops[i].x = stopPoints[i];
835 pGradient->gradient.stops[i].color = stopColors[i];
836 }
837 }
838
839 static PicturePtr
createSourcePicture(void)840 createSourcePicture(void)
841 {
842 PicturePtr pPicture;
843
844 pPicture = dixAllocateScreenObjectWithPrivates(NULL, PictureRec,
845 PRIVATE_PICTURE);
846 if (!pPicture)
847 return 0;
848
849 pPicture->pDrawable = 0;
850 pPicture->pFormat = 0;
851 pPicture->pNext = 0;
852 pPicture->format = PICT_a8r8g8b8;
853
854 SetPictureToDefaults(pPicture);
855 return pPicture;
856 }
857
858 PicturePtr
CreateSolidPicture(Picture pid,xRenderColor * color,int * error)859 CreateSolidPicture(Picture pid, xRenderColor * color, int *error)
860 {
861 PicturePtr pPicture;
862
863 pPicture = createSourcePicture();
864 if (!pPicture) {
865 *error = BadAlloc;
866 return 0;
867 }
868
869 pPicture->id = pid;
870 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictSolidFill));
871 if (!pPicture->pSourcePict) {
872 *error = BadAlloc;
873 free(pPicture);
874 return 0;
875 }
876 pPicture->pSourcePict->type = SourcePictTypeSolidFill;
877 pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color);
878 memcpy(&pPicture->pSourcePict->solidFill.fullcolor, color, sizeof(*color));
879 return pPicture;
880 }
881
882 PicturePtr
CreateLinearGradientPicture(Picture pid,xPointFixed * p1,xPointFixed * p2,int nStops,xFixed * stops,xRenderColor * colors,int * error)883 CreateLinearGradientPicture(Picture pid, xPointFixed * p1, xPointFixed * p2,
884 int nStops, xFixed * stops, xRenderColor * colors,
885 int *error)
886 {
887 PicturePtr pPicture;
888
889 if (nStops < 1) {
890 *error = BadValue;
891 return 0;
892 }
893
894 pPicture = createSourcePicture();
895 if (!pPicture) {
896 *error = BadAlloc;
897 return 0;
898 }
899
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 }
907
908 pPicture->pSourcePict->linear.type = SourcePictTypeLinear;
909 pPicture->pSourcePict->linear.p1 = *p1;
910 pPicture->pSourcePict->linear.p2 = *p2;
911
912 initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
913 if (*error) {
914 free(pPicture);
915 return 0;
916 }
917 return pPicture;
918 }
919
920 PicturePtr
CreateRadialGradientPicture(Picture pid,xPointFixed * inner,xPointFixed * outer,xFixed innerRadius,xFixed outerRadius,int nStops,xFixed * stops,xRenderColor * colors,int * error)921 CreateRadialGradientPicture(Picture pid, xPointFixed * inner,
922 xPointFixed * outer, xFixed innerRadius,
923 xFixed outerRadius, int nStops, xFixed * stops,
924 xRenderColor * colors, int *error)
925 {
926 PicturePtr pPicture;
927 PictRadialGradient *radial;
928
929 if (nStops < 1) {
930 *error = BadValue;
931 return 0;
932 }
933
934 pPicture = createSourcePicture();
935 if (!pPicture) {
936 *error = BadAlloc;
937 return 0;
938 }
939
940 pPicture->id = pid;
941 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictRadialGradient));
942 if (!pPicture->pSourcePict) {
943 *error = BadAlloc;
944 free(pPicture);
945 return 0;
946 }
947 radial = &pPicture->pSourcePict->radial;
948
949 radial->type = SourcePictTypeRadial;
950 radial->c1.x = inner->x;
951 radial->c1.y = inner->y;
952 radial->c1.radius = innerRadius;
953 radial->c2.x = outer->x;
954 radial->c2.y = outer->y;
955 radial->c2.radius = outerRadius;
956
957 initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
958 if (*error) {
959 free(pPicture);
960 return 0;
961 }
962 return pPicture;
963 }
964
965 PicturePtr
CreateConicalGradientPicture(Picture pid,xPointFixed * center,xFixed angle,int nStops,xFixed * stops,xRenderColor * colors,int * error)966 CreateConicalGradientPicture(Picture pid, xPointFixed * center, xFixed angle,
967 int nStops, xFixed * stops, xRenderColor * colors,
968 int *error)
969 {
970 PicturePtr pPicture;
971
972 if (nStops < 1) {
973 *error = BadValue;
974 return 0;
975 }
976
977 pPicture = createSourcePicture();
978 if (!pPicture) {
979 *error = BadAlloc;
980 return 0;
981 }
982
983 pPicture->id = pid;
984 pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictConicalGradient));
985 if (!pPicture->pSourcePict) {
986 *error = BadAlloc;
987 free(pPicture);
988 return 0;
989 }
990
991 pPicture->pSourcePict->conical.type = SourcePictTypeConical;
992 pPicture->pSourcePict->conical.center = *center;
993 pPicture->pSourcePict->conical.angle = angle;
994
995 initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
996 if (*error) {
997 free(pPicture);
998 return 0;
999 }
1000 return pPicture;
1001 }
1002
1003 static int
cpAlphaMap(void ** result,XID id,ScreenPtr screen,ClientPtr client,Mask mode)1004 cpAlphaMap(void **result, XID id, ScreenPtr screen, ClientPtr client, Mask mode)
1005 {
1006 #ifdef PANORAMIX
1007 if (!noPanoramiXExtension) {
1008 PanoramiXRes *res;
1009 int err = dixLookupResourceByType((void **)&res, id, XRT_PICTURE,
1010 client, mode);
1011 if (err != Success)
1012 return err;
1013 id = res->info[screen->myNum].id;
1014 }
1015 #endif
1016 return dixLookupResourceByType(result, id, PictureType, client, mode);
1017 }
1018
1019 static int
cpClipMask(void ** result,XID id,ScreenPtr screen,ClientPtr client,Mask mode)1020 cpClipMask(void **result, XID id, ScreenPtr screen, ClientPtr client, Mask mode)
1021 {
1022 #ifdef PANORAMIX
1023 if (!noPanoramiXExtension) {
1024 PanoramiXRes *res;
1025 int err = dixLookupResourceByType((void **)&res, id, XRT_PIXMAP,
1026 client, mode);
1027 if (err != Success)
1028 return err;
1029 id = res->info[screen->myNum].id;
1030 }
1031 #endif
1032 return dixLookupResourceByType(result, id, RT_PIXMAP, client, mode);
1033 }
1034
1035 #define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
1036
1037 #define NEXT_PTR(_type) ((_type) ulist++->ptr)
1038
1039 int
ChangePicture(PicturePtr pPicture,Mask vmask,XID * vlist,DevUnion * ulist,ClientPtr client)1040 ChangePicture(PicturePtr pPicture,
1041 Mask vmask, XID *vlist, DevUnion *ulist, ClientPtr client)
1042 {
1043 ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
1044 PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
1045 BITS32 index2;
1046 int error = 0;
1047 BITS32 maskQ;
1048
1049 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1050 maskQ = vmask;
1051 while (vmask && !error) {
1052 index2 = (BITS32) lowbit(vmask);
1053 vmask &= ~index2;
1054 pPicture->stateChanges |= index2;
1055 switch (index2) {
1056 case CPRepeat:
1057 {
1058 unsigned int newr;
1059 newr = NEXT_VAL(unsigned int);
1060
1061 if (newr <= RepeatReflect) {
1062 pPicture->repeat = (newr != RepeatNone);
1063 pPicture->repeatType = newr;
1064 }
1065 else {
1066 client->errorValue = newr;
1067 error = BadValue;
1068 }
1069 }
1070 break;
1071 case CPAlphaMap:
1072 {
1073 PicturePtr pAlpha;
1074
1075 if (vlist) {
1076 Picture pid = NEXT_VAL(Picture);
1077
1078 if (pid == None)
1079 pAlpha = 0;
1080 else {
1081 error = cpAlphaMap((void **) &pAlpha, pid, pScreen,
1082 client, DixReadAccess);
1083 if (error != Success) {
1084 client->errorValue = pid;
1085 break;
1086 }
1087 if (pAlpha->pDrawable == NULL ||
1088 pAlpha->pDrawable->type != DRAWABLE_PIXMAP) {
1089 client->errorValue = pid;
1090 error = BadMatch;
1091 break;
1092 }
1093 }
1094 }
1095 else
1096 pAlpha = NEXT_PTR(PicturePtr);
1097 if (!error) {
1098 if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP)
1099 pAlpha->refcnt++;
1100 if (pPicture->alphaMap)
1101 FreePicture((void *) pPicture->alphaMap, (XID) 0);
1102 pPicture->alphaMap = pAlpha;
1103 }
1104 }
1105 break;
1106 case CPAlphaXOrigin:
1107 pPicture->alphaOrigin.x = NEXT_VAL(INT16);
1108
1109 break;
1110 case CPAlphaYOrigin:
1111 pPicture->alphaOrigin.y = NEXT_VAL(INT16);
1112
1113 break;
1114 case CPClipXOrigin:
1115 pPicture->clipOrigin.x = NEXT_VAL(INT16);
1116
1117 break;
1118 case CPClipYOrigin:
1119 pPicture->clipOrigin.y = NEXT_VAL(INT16);
1120
1121 break;
1122 case CPClipMask:
1123 {
1124 Pixmap pid;
1125 PixmapPtr pPixmap;
1126 int clipType;
1127
1128 if (!pScreen)
1129 return BadDrawable;
1130
1131 if (vlist) {
1132 pid = NEXT_VAL(Pixmap);
1133 if (pid == None) {
1134 clipType = CT_NONE;
1135 pPixmap = NullPixmap;
1136 }
1137 else {
1138 clipType = CT_PIXMAP;
1139 error = cpClipMask((void **) &pPixmap, pid, pScreen,
1140 client, DixReadAccess);
1141 if (error != Success) {
1142 client->errorValue = pid;
1143 break;
1144 }
1145 }
1146 }
1147 else {
1148 pPixmap = NEXT_PTR(PixmapPtr);
1149
1150 if (pPixmap)
1151 clipType = CT_PIXMAP;
1152 else
1153 clipType = CT_NONE;
1154 }
1155
1156 if (pPixmap) {
1157 if ((pPixmap->drawable.depth != 1) ||
1158 (pPixmap->drawable.pScreen != pScreen)) {
1159 error = BadMatch;
1160 break;
1161 }
1162 else {
1163 clipType = CT_PIXMAP;
1164 pPixmap->refcnt++;
1165 }
1166 }
1167 error = (*ps->ChangePictureClip) (pPicture, clipType,
1168 (void *) pPixmap, 0);
1169 break;
1170 }
1171 case CPGraphicsExposure:
1172 {
1173 unsigned int newe;
1174 newe = NEXT_VAL(unsigned int);
1175
1176 if (newe <= xTrue)
1177 pPicture->graphicsExposures = newe;
1178 else {
1179 client->errorValue = newe;
1180 error = BadValue;
1181 }
1182 }
1183 break;
1184 case CPSubwindowMode:
1185 {
1186 unsigned int news;
1187 news = NEXT_VAL(unsigned int);
1188
1189 if (news == ClipByChildren || news == IncludeInferiors)
1190 pPicture->subWindowMode = news;
1191 else {
1192 client->errorValue = news;
1193 error = BadValue;
1194 }
1195 }
1196 break;
1197 case CPPolyEdge:
1198 {
1199 unsigned int newe;
1200 newe = NEXT_VAL(unsigned int);
1201
1202 if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
1203 pPicture->polyEdge = newe;
1204 else {
1205 client->errorValue = newe;
1206 error = BadValue;
1207 }
1208 }
1209 break;
1210 case CPPolyMode:
1211 {
1212 unsigned int newm;
1213 newm = NEXT_VAL(unsigned int);
1214
1215 if (newm == PolyModePrecise || newm == PolyModeImprecise)
1216 pPicture->polyMode = newm;
1217 else {
1218 client->errorValue = newm;
1219 error = BadValue;
1220 }
1221 }
1222 break;
1223 case CPDither:
1224 (void) NEXT_VAL(Atom); /* unimplemented */
1225
1226 break;
1227 case CPComponentAlpha:
1228 {
1229 unsigned int newca;
1230
1231 newca = NEXT_VAL(unsigned int);
1232
1233 if (newca <= xTrue)
1234 pPicture->componentAlpha = newca;
1235 else {
1236 client->errorValue = newca;
1237 error = BadValue;
1238 }
1239 }
1240 break;
1241 default:
1242 client->errorValue = maskQ;
1243 error = BadValue;
1244 break;
1245 }
1246 }
1247 if (ps)
1248 (*ps->ChangePicture) (pPicture, maskQ);
1249 return error;
1250 }
1251
1252 int
SetPictureClipRects(PicturePtr pPicture,int xOrigin,int yOrigin,int nRect,xRectangle * rects)1253 SetPictureClipRects(PicturePtr pPicture,
1254 int xOrigin, int yOrigin, int nRect, xRectangle *rects)
1255 {
1256 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1257 PictureScreenPtr ps = GetPictureScreen(pScreen);
1258 RegionPtr clientClip;
1259 int result;
1260
1261 clientClip = RegionFromRects(nRect, rects, CT_UNSORTED);
1262 if (!clientClip)
1263 return BadAlloc;
1264 result = (*ps->ChangePictureClip) (pPicture, CT_REGION,
1265 (void *) clientClip, 0);
1266 if (result == Success) {
1267 pPicture->clipOrigin.x = xOrigin;
1268 pPicture->clipOrigin.y = yOrigin;
1269 pPicture->stateChanges |= CPClipXOrigin | CPClipYOrigin | CPClipMask;
1270 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1271 }
1272 return result;
1273 }
1274
1275 int
SetPictureClipRegion(PicturePtr pPicture,int xOrigin,int yOrigin,RegionPtr pRegion)1276 SetPictureClipRegion(PicturePtr pPicture,
1277 int xOrigin, int yOrigin, RegionPtr pRegion)
1278 {
1279 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1280 PictureScreenPtr ps = GetPictureScreen(pScreen);
1281 RegionPtr clientClip;
1282 int result;
1283 int type;
1284
1285 if (pRegion) {
1286 type = CT_REGION;
1287 clientClip = RegionCreate(RegionExtents(pRegion),
1288 RegionNumRects(pRegion));
1289 if (!clientClip)
1290 return BadAlloc;
1291 if (!RegionCopy(clientClip, pRegion)) {
1292 RegionDestroy(clientClip);
1293 return BadAlloc;
1294 }
1295 }
1296 else {
1297 type = CT_NONE;
1298 clientClip = 0;
1299 }
1300
1301 result = (*ps->ChangePictureClip) (pPicture, type, (void *) clientClip, 0);
1302 if (result == Success) {
1303 pPicture->clipOrigin.x = xOrigin;
1304 pPicture->clipOrigin.y = yOrigin;
1305 pPicture->stateChanges |= CPClipXOrigin | CPClipYOrigin | CPClipMask;
1306 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1307 }
1308 return result;
1309 }
1310
1311 static Bool
transformIsIdentity(PictTransform * t)1312 transformIsIdentity(PictTransform * t)
1313 {
1314 return ((t->matrix[0][0] == t->matrix[1][1]) &&
1315 (t->matrix[0][0] == t->matrix[2][2]) &&
1316 (t->matrix[0][0] != 0) &&
1317 (t->matrix[0][1] == 0) &&
1318 (t->matrix[0][2] == 0) &&
1319 (t->matrix[1][0] == 0) &&
1320 (t->matrix[1][2] == 0) &&
1321 (t->matrix[2][0] == 0) && (t->matrix[2][1] == 0));
1322 }
1323
1324 int
SetPictureTransform(PicturePtr pPicture,PictTransform * transform)1325 SetPictureTransform(PicturePtr pPicture, PictTransform * transform)
1326 {
1327 if (transform && transformIsIdentity(transform))
1328 transform = 0;
1329
1330 if (transform) {
1331 if (!pPicture->transform) {
1332 pPicture->transform =
1333 (PictTransform *) malloc(sizeof(PictTransform));
1334 if (!pPicture->transform)
1335 return BadAlloc;
1336 }
1337 *pPicture->transform = *transform;
1338 }
1339 else {
1340 free(pPicture->transform);
1341 pPicture->transform = NULL;
1342 }
1343 pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1344
1345 if (pPicture->pDrawable != NULL) {
1346 int result;
1347 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1348
1349 result = (*ps->ChangePictureTransform) (pPicture, transform);
1350
1351 return result;
1352 }
1353
1354 return Success;
1355 }
1356
1357 static void
ValidateOnePicture(PicturePtr pPicture)1358 ValidateOnePicture(PicturePtr pPicture)
1359 {
1360 if (pPicture->pDrawable &&
1361 pPicture->serialNumber != pPicture->pDrawable->serialNumber) {
1362 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1363
1364 (*ps->ValidatePicture) (pPicture, pPicture->stateChanges);
1365 pPicture->stateChanges = 0;
1366 pPicture->serialNumber = pPicture->pDrawable->serialNumber;
1367 }
1368 }
1369
1370 void
ValidatePicture(PicturePtr pPicture)1371 ValidatePicture(PicturePtr pPicture)
1372 {
1373 ValidateOnePicture(pPicture);
1374 if (pPicture->alphaMap)
1375 ValidateOnePicture(pPicture->alphaMap);
1376 }
1377
1378 int
FreePicture(void * value,XID pid)1379 FreePicture(void *value, XID pid)
1380 {
1381 PicturePtr pPicture = (PicturePtr) value;
1382
1383 if (--pPicture->refcnt == 0) {
1384 free(pPicture->transform);
1385 free(pPicture->filter_params);
1386
1387 if (pPicture->pSourcePict) {
1388 if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
1389 free(pPicture->pSourcePict->linear.stops);
1390
1391 free(pPicture->pSourcePict);
1392 }
1393
1394 if (pPicture->pDrawable) {
1395 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1396 PictureScreenPtr ps = GetPictureScreen(pScreen);
1397
1398 if (pPicture->alphaMap)
1399 FreePicture((void *) pPicture->alphaMap, (XID) 0);
1400 (*ps->DestroyPicture) (pPicture);
1401 (*ps->DestroyPictureClip) (pPicture);
1402 if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
1403 WindowPtr pWindow = (WindowPtr) pPicture->pDrawable;
1404 PicturePtr *pPrev;
1405
1406 for (pPrev = (PicturePtr *) dixLookupPrivateAddr
1407 (&pWindow->devPrivates, PictureWindowPrivateKey);
1408 *pPrev; pPrev = &(*pPrev)->pNext) {
1409 if (*pPrev == pPicture) {
1410 *pPrev = pPicture->pNext;
1411 break;
1412 }
1413 }
1414 }
1415 else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP) {
1416 (*pScreen->DestroyPixmap) ((PixmapPtr) pPicture->pDrawable);
1417 }
1418 }
1419 dixFreeObjectWithPrivates(pPicture, PRIVATE_PICTURE);
1420 }
1421 return Success;
1422 }
1423
1424 /**
1425 * ReduceCompositeOp is used to choose simpler ops for cases where alpha
1426 * channels are always one and so math on the alpha channel per pixel becomes
1427 * unnecessary. It may also avoid destination reads sometimes if apps aren't
1428 * being careful to avoid these cases.
1429 */
1430 static CARD8
ReduceCompositeOp(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,CARD16 width,CARD16 height)1431 ReduceCompositeOp(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1432 INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height)
1433 {
1434 Bool no_src_alpha, no_dst_alpha;
1435
1436 /* Sampling off the edge of a RepeatNone picture introduces alpha
1437 * even if the picture itself doesn't have alpha. We don't try to
1438 * detect every case where we don't sample off the edge, just the
1439 * simplest case where there is no transform on the source
1440 * picture.
1441 */
1442 no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) &&
1443 PICT_FORMAT_A(pSrc->format) == 0 &&
1444 (pSrc->repeatType != RepeatNone ||
1445 (!pSrc->transform &&
1446 xSrc >= 0 && ySrc >= 0 &&
1447 xSrc + width <= pSrc->pDrawable->width &&
1448 ySrc + height <= pSrc->pDrawable->height)) &&
1449 pSrc->alphaMap == NULL && pMask == NULL;
1450 no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) &&
1451 PICT_FORMAT_A(pDst->format) == 0 && pDst->alphaMap == NULL;
1452
1453 /* TODO, maybe: Conjoint and Disjoint op reductions? */
1454
1455 /* Deal with simplifications where the source alpha is always 1. */
1456 if (no_src_alpha) {
1457 switch (op) {
1458 case PictOpOver:
1459 op = PictOpSrc;
1460 break;
1461 case PictOpInReverse:
1462 op = PictOpDst;
1463 break;
1464 case PictOpOutReverse:
1465 op = PictOpClear;
1466 break;
1467 case PictOpAtop:
1468 op = PictOpIn;
1469 break;
1470 case PictOpAtopReverse:
1471 op = PictOpOverReverse;
1472 break;
1473 case PictOpXor:
1474 op = PictOpOut;
1475 break;
1476 default:
1477 break;
1478 }
1479 }
1480
1481 /* Deal with simplifications when the destination alpha is always 1 */
1482 if (no_dst_alpha) {
1483 switch (op) {
1484 case PictOpOverReverse:
1485 op = PictOpDst;
1486 break;
1487 case PictOpIn:
1488 op = PictOpSrc;
1489 break;
1490 case PictOpOut:
1491 op = PictOpClear;
1492 break;
1493 case PictOpAtop:
1494 op = PictOpOver;
1495 break;
1496 case PictOpXor:
1497 op = PictOpOutReverse;
1498 break;
1499 default:
1500 break;
1501 }
1502 }
1503
1504 /* Reduce some con/disjoint ops to the basic names. */
1505 switch (op) {
1506 case PictOpDisjointClear:
1507 case PictOpConjointClear:
1508 op = PictOpClear;
1509 break;
1510 case PictOpDisjointSrc:
1511 case PictOpConjointSrc:
1512 op = PictOpSrc;
1513 break;
1514 case PictOpDisjointDst:
1515 case PictOpConjointDst:
1516 op = PictOpDst;
1517 break;
1518 default:
1519 break;
1520 }
1521
1522 return op;
1523 }
1524
1525 void
CompositePicture(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)1526 CompositePicture(CARD8 op,
1527 PicturePtr pSrc,
1528 PicturePtr pMask,
1529 PicturePtr pDst,
1530 INT16 xSrc,
1531 INT16 ySrc,
1532 INT16 xMask,
1533 INT16 yMask,
1534 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
1535 {
1536 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1537
1538 ValidatePicture(pSrc);
1539 if (pMask)
1540 ValidatePicture(pMask);
1541 ValidatePicture(pDst);
1542
1543 op = ReduceCompositeOp(op, pSrc, pMask, pDst, xSrc, ySrc, width, height);
1544 if (op == PictOpDst)
1545 return;
1546
1547 (*ps->Composite) (op,
1548 pSrc,
1549 pMask,
1550 pDst,
1551 xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
1552 }
1553
1554 void
CompositeRects(CARD8 op,PicturePtr pDst,xRenderColor * color,int nRect,xRectangle * rects)1555 CompositeRects(CARD8 op,
1556 PicturePtr pDst,
1557 xRenderColor * color, int nRect, xRectangle *rects)
1558 {
1559 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1560
1561 ValidatePicture(pDst);
1562 (*ps->CompositeRects) (op, pDst, color, nRect, rects);
1563 }
1564
1565 void
CompositeTrapezoids(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntrap,xTrapezoid * traps)1566 CompositeTrapezoids(CARD8 op,
1567 PicturePtr pSrc,
1568 PicturePtr pDst,
1569 PictFormatPtr maskFormat,
1570 INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps)
1571 {
1572 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1573
1574 ValidatePicture(pSrc);
1575 ValidatePicture(pDst);
1576 (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
1577 }
1578
1579 void
CompositeTriangles(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntriangles,xTriangle * triangles)1580 CompositeTriangles(CARD8 op,
1581 PicturePtr pSrc,
1582 PicturePtr pDst,
1583 PictFormatPtr maskFormat,
1584 INT16 xSrc,
1585 INT16 ySrc, int ntriangles, xTriangle * triangles)
1586 {
1587 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1588
1589 ValidatePicture(pSrc);
1590 ValidatePicture(pDst);
1591 (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles,
1592 triangles);
1593 }
1594
1595 void
CompositeTriStrip(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int npoints,xPointFixed * points)1596 CompositeTriStrip(CARD8 op,
1597 PicturePtr pSrc,
1598 PicturePtr pDst,
1599 PictFormatPtr maskFormat,
1600 INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
1601 {
1602 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1603
1604 if (npoints < 3)
1605 return;
1606
1607 ValidatePicture(pSrc);
1608 ValidatePicture(pDst);
1609 (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
1610 }
1611
1612 void
CompositeTriFan(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int npoints,xPointFixed * points)1613 CompositeTriFan(CARD8 op,
1614 PicturePtr pSrc,
1615 PicturePtr pDst,
1616 PictFormatPtr maskFormat,
1617 INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
1618 {
1619 PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
1620
1621 if (npoints < 3)
1622 return;
1623
1624 ValidatePicture(pSrc);
1625 ValidatePicture(pDst);
1626 (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
1627 }
1628
1629 void
AddTraps(PicturePtr pPicture,INT16 xOff,INT16 yOff,int ntrap,xTrap * traps)1630 AddTraps(PicturePtr pPicture, INT16 xOff, INT16 yOff, int ntrap, xTrap * traps)
1631 {
1632 PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1633
1634 ValidatePicture(pPicture);
1635 (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps);
1636 }
1637