3 * Copyright © 2000 SuSE, Inc.
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.
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.
22 * Author: Keith Packard, SuSE, Inc.
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
30 #include "scrnintstr.h"
32 #include "regionstr.h"
34 #include "windowstr.h"
37 #include "colormapst.h"
38 #include "cursorstr.h"
39 #include "dixstruct.h"
42 #include "picturestr.h"
45 DevPrivateKeyRec PictureScreenPrivateKeyRec
;
46 DevPrivateKeyRec PictureWindowPrivateKeyRec
;
47 static int PictureGeneration
;
49 RESTYPE PictFormatType
;
51 int PictureCmapPolicy
= PictureCmapPolicyDefault
;
54 PictureWindowFormat(WindowPtr pWindow
)
56 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
57 return PictureMatchVisual(pScreen
, pWindow
->drawable
.depth
,
58 WindowGetVisual(pWindow
));
62 PictureDestroyWindow(WindowPtr pWindow
)
64 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
66 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
69 while ((pPicture
= GetPictureWindow(pWindow
))) {
70 SetPictureWindow(pWindow
, pPicture
->pNext
);
72 FreeResource(pPicture
->id
, PictureType
);
73 FreePicture((pointer
) pPicture
, pPicture
->id
);
75 pScreen
->DestroyWindow
= ps
->DestroyWindow
;
76 ret
= (*pScreen
->DestroyWindow
) (pWindow
);
77 ps
->DestroyWindow
= pScreen
->DestroyWindow
;
78 pScreen
->DestroyWindow
= PictureDestroyWindow
;
83 PictureCloseScreen(ScreenPtr pScreen
)
85 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
89 pScreen
->CloseScreen
= ps
->CloseScreen
;
90 ret
= (*pScreen
->CloseScreen
) (pScreen
);
91 PictureResetFilters(pScreen
);
92 for (n
= 0; n
< ps
->nformats
; n
++)
93 if (ps
->formats
[n
].type
== PictTypeIndexed
)
94 (*ps
->CloseIndexed
) (pScreen
, &ps
->formats
[n
]);
96 SetPictureScreen(pScreen
, 0);
103 PictureStoreColors(ColormapPtr pColormap
, int ndef
, xColorItem
* pdef
)
105 ScreenPtr pScreen
= pColormap
->pScreen
;
106 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
108 pScreen
->StoreColors
= ps
->StoreColors
;
109 (*pScreen
->StoreColors
) (pColormap
, ndef
, pdef
);
110 ps
->StoreColors
= pScreen
->StoreColors
;
111 pScreen
->StoreColors
= PictureStoreColors
;
113 if (pColormap
->class == PseudoColor
|| pColormap
->class == GrayScale
) {
114 PictFormatPtr format
= ps
->formats
;
115 int nformats
= ps
->nformats
;
118 if (format
->type
== PictTypeIndexed
&&
119 format
->index
.pColormap
== pColormap
) {
120 (*ps
->UpdateIndexed
) (pScreen
, format
, ndef
, pdef
);
129 visualDepth(ScreenPtr pScreen
, VisualPtr pVisual
)
134 for (d
= 0; d
< pScreen
->numDepths
; d
++) {
135 pDepth
= &pScreen
->allowedDepths
[d
];
136 for (v
= 0; v
< pDepth
->numVids
; v
++)
137 if (pDepth
->vids
[v
] == pVisual
->vid
)
138 return pDepth
->depth
;
143 typedef struct _formatInit
{
146 } FormatInitRec
, *FormatInitPtr
;
149 addFormat(FormatInitRec formats
[256], int nformat
, CARD32 format
, CARD8 depth
)
153 for (n
= 0; n
< nformat
; n
++)
154 if (formats
[n
].format
== format
&& formats
[n
].depth
== depth
)
156 formats
[nformat
].format
= format
;
157 formats
[nformat
].depth
= depth
;
161 #define Mask(n) ((1 << (n)) - 1)
164 PictureCreateDefaultFormats(ScreenPtr pScreen
, int *nformatp
)
167 PictFormatPtr pFormats
;
168 FormatInitRec formats
[1024];
180 /* formats required by protocol */
181 formats
[nformats
].format
= PICT_a1
;
182 formats
[nformats
].depth
= 1;
184 formats
[nformats
].format
= PICT_FORMAT(BitsPerPixel(8),
185 PICT_TYPE_A
, 8, 0, 0, 0);
186 formats
[nformats
].depth
= 8;
188 formats
[nformats
].format
= PICT_FORMAT(BitsPerPixel(4),
189 PICT_TYPE_A
, 4, 0, 0, 0);
190 formats
[nformats
].depth
= 4;
192 formats
[nformats
].format
= PICT_a8r8g8b8
;
193 formats
[nformats
].depth
= 32;
195 formats
[nformats
].format
= PICT_x8r8g8b8
;
196 formats
[nformats
].depth
= 32;
198 formats
[nformats
].format
= PICT_b8g8r8a8
;
199 formats
[nformats
].depth
= 32;
201 formats
[nformats
].format
= PICT_b8g8r8x8
;
202 formats
[nformats
].depth
= 32;
205 /* now look through the depths and visuals adding other formats */
206 for (v
= 0; v
< pScreen
->numVisuals
; v
++) {
207 pVisual
= &pScreen
->visuals
[v
];
208 depth
= visualDepth(pScreen
, pVisual
);
211 bpp
= BitsPerPixel(depth
);
212 switch (pVisual
->class) {
215 r
= Ones(pVisual
->redMask
);
216 g
= Ones(pVisual
->greenMask
);
217 b
= Ones(pVisual
->blueMask
);
218 type
= PICT_TYPE_OTHER
;
220 * Current rendering code supports only three direct formats,
221 * fields must be packed together at the bottom of the pixel
223 if (pVisual
->offsetBlue
== 0 &&
224 pVisual
->offsetGreen
== b
&& pVisual
->offsetRed
== b
+ g
) {
225 type
= PICT_TYPE_ARGB
;
227 else if (pVisual
->offsetRed
== 0 &&
228 pVisual
->offsetGreen
== r
&&
229 pVisual
->offsetBlue
== r
+ g
) {
230 type
= PICT_TYPE_ABGR
;
232 else if (pVisual
->offsetRed
== pVisual
->offsetGreen
- r
&&
233 pVisual
->offsetGreen
== pVisual
->offsetBlue
- g
&&
234 pVisual
->offsetBlue
== bpp
- b
) {
235 type
= PICT_TYPE_BGRA
;
237 if (type
!= PICT_TYPE_OTHER
) {
238 format
= PICT_FORMAT(bpp
, type
, 0, r
, g
, b
);
239 nformats
= addFormat(formats
, nformats
, format
, depth
);
244 format
= PICT_VISFORMAT(bpp
, PICT_TYPE_COLOR
, v
);
245 nformats
= addFormat(formats
, nformats
, format
, depth
);
249 format
= PICT_VISFORMAT(bpp
, PICT_TYPE_GRAY
, v
);
250 nformats
= addFormat(formats
, nformats
, format
, depth
);
255 * Walk supported depths and add useful Direct formats
257 for (d
= 0; d
< pScreen
->numDepths
; d
++) {
258 pDepth
= &pScreen
->allowedDepths
[d
];
259 bpp
= BitsPerPixel(pDepth
->depth
);
263 /* depth 12 formats */
264 if (pDepth
->depth
>= 12) {
265 nformats
= addFormat(formats
, nformats
,
266 PICT_x4r4g4b4
, pDepth
->depth
);
267 nformats
= addFormat(formats
, nformats
,
268 PICT_x4b4g4r4
, pDepth
->depth
);
270 /* depth 15 formats */
271 if (pDepth
->depth
>= 15) {
272 nformats
= addFormat(formats
, nformats
,
273 PICT_x1r5g5b5
, pDepth
->depth
);
274 nformats
= addFormat(formats
, nformats
,
275 PICT_x1b5g5r5
, pDepth
->depth
);
277 /* depth 16 formats */
278 if (pDepth
->depth
>= 16) {
279 nformats
= addFormat(formats
, nformats
,
280 PICT_a1r5g5b5
, pDepth
->depth
);
281 nformats
= addFormat(formats
, nformats
,
282 PICT_a1b5g5r5
, pDepth
->depth
);
283 nformats
= addFormat(formats
, nformats
,
284 PICT_r5g6b5
, pDepth
->depth
);
285 nformats
= addFormat(formats
, nformats
,
286 PICT_b5g6r5
, pDepth
->depth
);
287 nformats
= addFormat(formats
, nformats
,
288 PICT_a4r4g4b4
, pDepth
->depth
);
289 nformats
= addFormat(formats
, nformats
,
290 PICT_a4b4g4r4
, pDepth
->depth
);
294 if (pDepth
->depth
>= 24) {
295 nformats
= addFormat(formats
, nformats
,
296 PICT_r8g8b8
, pDepth
->depth
);
297 nformats
= addFormat(formats
, nformats
,
298 PICT_b8g8r8
, pDepth
->depth
);
302 if (pDepth
->depth
>= 24) {
303 nformats
= addFormat(formats
, nformats
,
304 PICT_x8r8g8b8
, pDepth
->depth
);
305 nformats
= addFormat(formats
, nformats
,
306 PICT_x8b8g8r8
, pDepth
->depth
);
308 if (pDepth
->depth
>= 30) {
309 nformats
= addFormat(formats
, nformats
,
310 PICT_a2r10g10b10
, pDepth
->depth
);
311 nformats
= addFormat(formats
, nformats
,
312 PICT_x2r10g10b10
, pDepth
->depth
);
313 nformats
= addFormat(formats
, nformats
,
314 PICT_a2b10g10r10
, pDepth
->depth
);
315 nformats
= addFormat(formats
, nformats
,
316 PICT_x2b10g10r10
, pDepth
->depth
);
322 pFormats
= calloc(nformats
, sizeof(PictFormatRec
));
325 for (f
= 0; f
< nformats
; f
++) {
326 pFormats
[f
].id
= FakeClientID(0);
327 pFormats
[f
].depth
= formats
[f
].depth
;
328 format
= formats
[f
].format
;
329 pFormats
[f
].format
= format
;
330 switch (PICT_FORMAT_TYPE(format
)) {
332 pFormats
[f
].type
= PictTypeDirect
;
334 pFormats
[f
].direct
.alphaMask
= Mask (PICT_FORMAT_A(format
));
336 if (pFormats
[f
].direct
.alphaMask
)
337 pFormats
[f
].direct
.alpha
= (PICT_FORMAT_R(format
) +
338 PICT_FORMAT_G(format
) +
339 PICT_FORMAT_B(format
));
341 pFormats
[f
].direct
.redMask
= Mask (PICT_FORMAT_R(format
));
343 pFormats
[f
].direct
.red
= (PICT_FORMAT_G(format
) +
344 PICT_FORMAT_B(format
));
346 pFormats
[f
].direct
.greenMask
= Mask (PICT_FORMAT_G(format
));
348 pFormats
[f
].direct
.green
= PICT_FORMAT_B(format
);
350 pFormats
[f
].direct
.blueMask
= Mask (PICT_FORMAT_B(format
));
352 pFormats
[f
].direct
.blue
= 0;
356 pFormats
[f
].type
= PictTypeDirect
;
358 pFormats
[f
].direct
.alphaMask
= Mask (PICT_FORMAT_A(format
));
360 if (pFormats
[f
].direct
.alphaMask
)
361 pFormats
[f
].direct
.alpha
= (PICT_FORMAT_B(format
) +
362 PICT_FORMAT_G(format
) +
363 PICT_FORMAT_R(format
));
365 pFormats
[f
].direct
.blueMask
= Mask (PICT_FORMAT_B(format
));
367 pFormats
[f
].direct
.blue
= (PICT_FORMAT_G(format
) +
368 PICT_FORMAT_R(format
));
370 pFormats
[f
].direct
.greenMask
= Mask (PICT_FORMAT_G(format
));
372 pFormats
[f
].direct
.green
= PICT_FORMAT_R(format
);
374 pFormats
[f
].direct
.redMask
= Mask (PICT_FORMAT_R(format
));
376 pFormats
[f
].direct
.red
= 0;
380 pFormats
[f
].type
= PictTypeDirect
;
382 pFormats
[f
].direct
.blueMask
= Mask (PICT_FORMAT_B(format
));
384 pFormats
[f
].direct
.blue
=
385 (PICT_FORMAT_BPP(format
) - PICT_FORMAT_B(format
));
387 pFormats
[f
].direct
.greenMask
= Mask (PICT_FORMAT_G(format
));
389 pFormats
[f
].direct
.green
=
390 (PICT_FORMAT_BPP(format
) - PICT_FORMAT_B(format
) -
391 PICT_FORMAT_G(format
));
393 pFormats
[f
].direct
.redMask
= Mask (PICT_FORMAT_R(format
));
395 pFormats
[f
].direct
.red
=
396 (PICT_FORMAT_BPP(format
) - PICT_FORMAT_B(format
) -
397 PICT_FORMAT_G(format
) - PICT_FORMAT_R(format
));
399 pFormats
[f
].direct
.alphaMask
= Mask (PICT_FORMAT_A(format
));
401 pFormats
[f
].direct
.alpha
= 0;
405 pFormats
[f
].type
= PictTypeDirect
;
407 pFormats
[f
].direct
.alpha
= 0;
408 pFormats
[f
].direct
.alphaMask
= Mask (PICT_FORMAT_A(format
));
410 /* remaining fields already set to zero */
413 case PICT_TYPE_COLOR
:
415 pFormats
[f
].type
= PictTypeIndexed
;
416 pFormats
[f
].index
.vid
=
417 pScreen
->visuals
[PICT_FORMAT_VIS(format
)].vid
;
421 *nformatp
= nformats
;
426 PictureFindVisual(ScreenPtr pScreen
, VisualID visual
)
431 for (i
= 0, pVisual
= pScreen
->visuals
;
432 i
< pScreen
->numVisuals
; i
++, pVisual
++) {
433 if (pVisual
->vid
== visual
)
440 PictureInitIndexedFormat(ScreenPtr pScreen
, PictFormatPtr format
)
442 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
444 if (format
->type
!= PictTypeIndexed
|| format
->index
.pColormap
)
447 if (format
->index
.vid
== pScreen
->rootVisual
) {
448 dixLookupResourceByType((pointer
*) &format
->index
.pColormap
,
449 pScreen
->defColormap
, RT_COLORMAP
,
450 serverClient
, DixGetAttrAccess
);
453 VisualPtr pVisual
= PictureFindVisual(pScreen
, format
->index
.vid
);
455 if (CreateColormap(FakeClientID(0), pScreen
, pVisual
,
456 &format
->index
.pColormap
, AllocNone
, 0)
460 if (!ps
->InitIndexed(pScreen
, format
))
466 PictureInitIndexedFormats(ScreenPtr pScreen
)
468 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
469 PictFormatPtr format
;
474 format
= ps
->formats
;
475 nformat
= ps
->nformats
;
477 if (!PictureInitIndexedFormat(pScreen
, format
++))
483 PictureFinishInit(void)
487 for (s
= 0; s
< screenInfo
.numScreens
; s
++) {
488 if (!PictureInitIndexedFormats(screenInfo
.screens
[s
]))
490 (void) AnimCurInit(screenInfo
.screens
[s
]);
497 PictureSetSubpixelOrder(ScreenPtr pScreen
, int subpixel
)
499 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
503 ps
->subpixel
= subpixel
;
509 PictureGetSubpixelOrder(ScreenPtr pScreen
)
511 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
514 return SubPixelUnknown
;
519 PictureMatchVisual(ScreenPtr pScreen
, int depth
, VisualPtr pVisual
)
521 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
522 PictFormatPtr format
;
528 format
= ps
->formats
;
529 nformat
= ps
->nformats
;
530 switch (pVisual
->class) {
535 type
= PictTypeIndexed
;
539 type
= PictTypeDirect
;
545 if (format
->depth
== depth
&& format
->type
== type
) {
546 if (type
== PictTypeIndexed
) {
547 if (format
->index
.vid
== pVisual
->vid
)
551 if (format
->direct
.redMask
<< format
->direct
.red
==
553 format
->direct
.greenMask
<< format
->direct
.green
==
554 pVisual
->greenMask
&&
555 format
->direct
.blueMask
<< format
->direct
.blue
==
567 PictureMatchFormat(ScreenPtr pScreen
, int depth
, CARD32 f
)
569 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
570 PictFormatPtr format
;
575 format
= ps
->formats
;
576 nformat
= ps
->nformats
;
578 if (format
->depth
== depth
&& format
->format
== (f
& 0xffffff))
586 PictureParseCmapPolicy(const char *name
)
588 if (strcmp(name
, "default") == 0)
589 return PictureCmapPolicyDefault
;
590 else if (strcmp(name
, "mono") == 0)
591 return PictureCmapPolicyMono
;
592 else if (strcmp(name
, "gray") == 0)
593 return PictureCmapPolicyGray
;
594 else if (strcmp(name
, "color") == 0)
595 return PictureCmapPolicyColor
;
596 else if (strcmp(name
, "all") == 0)
597 return PictureCmapPolicyAll
;
599 return PictureCmapPolicyInvalid
;
602 /** @see GetDefaultBytes */
604 GetPictureBytes(pointer value
, XID id
, ResourceSizePtr size
)
606 PicturePtr picture
= value
;
608 /* Currently only pixmap bytes are reported to clients. */
609 size
->resourceSize
= 0;
611 size
->refCnt
= picture
->refcnt
;
613 /* Calculate pixmap reference sizes. */
614 size
->pixmapRefSize
= 0;
615 if (picture
->pDrawable
&& (picture
->pDrawable
->type
== DRAWABLE_PIXMAP
))
617 SizeType pixmapSizeFunc
= GetResourceTypeSizeFunc(RT_PIXMAP
);
618 ResourceSizeRec pixmapSize
= { 0, 0, 0 };
619 PixmapPtr pixmap
= (PixmapPtr
)picture
->pDrawable
;
620 pixmapSizeFunc(pixmap
, pixmap
->drawable
.id
, &pixmapSize
);
621 size
->pixmapRefSize
+= pixmapSize
.pixmapRefSize
;
626 PictureInit(ScreenPtr pScreen
, PictFormatPtr formats
, int nformats
)
630 CARD32 type
, a
, r
, g
, b
;
632 if (PictureGeneration
!= serverGeneration
) {
633 PictureType
= CreateNewResourceType(FreePicture
, "PICTURE");
636 SetResourceTypeSizeFunc(PictureType
, GetPictureBytes
);
637 PictFormatType
= CreateNewResourceType(FreePictFormat
, "PICTFORMAT");
640 GlyphSetType
= CreateNewResourceType(FreeGlyphSet
, "GLYPHSET");
643 PictureGeneration
= serverGeneration
;
645 if (!dixRegisterPrivateKey(&PictureScreenPrivateKeyRec
, PRIVATE_SCREEN
, 0))
648 if (!dixRegisterPrivateKey(&PictureWindowPrivateKeyRec
, PRIVATE_WINDOW
, 0))
652 formats
= PictureCreateDefaultFormats(pScreen
, &nformats
);
656 for (n
= 0; n
< nformats
; n
++) {
658 (formats
[n
].id
, PictFormatType
, (pointer
) (formats
+ n
))) {
662 if (formats
[n
].type
== PictTypeIndexed
) {
664 PictureFindVisual(pScreen
, formats
[n
].index
.vid
);
665 if ((pVisual
->class | DynamicClass
) == PseudoColor
)
666 type
= PICT_TYPE_COLOR
;
668 type
= PICT_TYPE_GRAY
;
672 if ((formats
[n
].direct
.redMask
|
673 formats
[n
].direct
.blueMask
| formats
[n
].direct
.greenMask
) == 0)
675 else if (formats
[n
].direct
.red
> formats
[n
].direct
.blue
)
676 type
= PICT_TYPE_ARGB
;
677 else if (formats
[n
].direct
.red
== 0)
678 type
= PICT_TYPE_ABGR
;
680 type
= PICT_TYPE_BGRA
;
681 a
= Ones(formats
[n
].direct
.alphaMask
);
682 r
= Ones(formats
[n
].direct
.redMask
);
683 g
= Ones(formats
[n
].direct
.greenMask
);
684 b
= Ones(formats
[n
].direct
.blueMask
);
686 formats
[n
].format
= PICT_FORMAT(0, type
, a
, r
, g
, b
);
688 ps
= (PictureScreenPtr
) malloc(sizeof(PictureScreenRec
));
693 SetPictureScreen(pScreen
, ps
);
695 ps
->formats
= formats
;
696 ps
->fallback
= formats
;
697 ps
->nformats
= nformats
;
701 ps
->filterAliases
= 0;
702 ps
->nfilterAliases
= 0;
704 ps
->subpixel
= SubPixelUnknown
;
706 ps
->CloseScreen
= pScreen
->CloseScreen
;
707 ps
->DestroyWindow
= pScreen
->DestroyWindow
;
708 ps
->StoreColors
= pScreen
->StoreColors
;
709 pScreen
->DestroyWindow
= PictureDestroyWindow
;
710 pScreen
->CloseScreen
= PictureCloseScreen
;
711 pScreen
->StoreColors
= PictureStoreColors
;
713 if (!PictureSetDefaultFilters(pScreen
)) {
714 PictureResetFilters(pScreen
);
715 SetPictureScreen(pScreen
, 0);
725 SetPictureToDefaults(PicturePtr pPicture
)
727 pPicture
->refcnt
= 1;
728 pPicture
->repeat
= 0;
729 pPicture
->graphicsExposures
= FALSE
;
730 pPicture
->subWindowMode
= ClipByChildren
;
731 pPicture
->polyEdge
= PolyEdgeSharp
;
732 pPicture
->polyMode
= PolyModePrecise
;
733 pPicture
->freeCompClip
= FALSE
;
734 pPicture
->clientClipType
= CT_NONE
;
735 pPicture
->componentAlpha
= FALSE
;
736 pPicture
->repeatType
= RepeatNone
;
738 pPicture
->alphaMap
= 0;
739 pPicture
->alphaOrigin
.x
= 0;
740 pPicture
->alphaOrigin
.y
= 0;
742 pPicture
->clipOrigin
.x
= 0;
743 pPicture
->clipOrigin
.y
= 0;
744 pPicture
->clientClip
= 0;
746 pPicture
->transform
= 0;
748 pPicture
->filter
= PictureGetFilterId(FilterNearest
, -1, TRUE
);
749 pPicture
->filter_params
= 0;
750 pPicture
->filter_nparams
= 0;
752 pPicture
->serialNumber
= GC_CHANGE_SERIAL_BIT
;
753 pPicture
->stateChanges
= -1;
754 pPicture
->pSourcePict
= 0;
758 CreatePicture(Picture pid
,
759 DrawablePtr pDrawable
,
760 PictFormatPtr pFormat
,
761 Mask vmask
, XID
*vlist
, ClientPtr client
, int *error
)
764 PictureScreenPtr ps
= GetPictureScreen(pDrawable
->pScreen
);
766 pPicture
= dixAllocateScreenObjectWithPrivates(pDrawable
->pScreen
,
767 PictureRec
, PRIVATE_PICTURE
);
774 pPicture
->pDrawable
= pDrawable
;
775 pPicture
->pFormat
= pFormat
;
776 pPicture
->format
= pFormat
->format
| (pDrawable
->bitsPerPixel
<< 24);
778 /* security creation/labeling check */
779 *error
= XaceHook(XACE_RESOURCE_ACCESS
, client
, pid
, PictureType
, pPicture
,
780 RT_PIXMAP
, pDrawable
, DixCreateAccess
| DixSetAttrAccess
);
781 if (*error
!= Success
)
784 if (pDrawable
->type
== DRAWABLE_PIXMAP
) {
785 ++((PixmapPtr
) pDrawable
)->refcnt
;
789 pPicture
->pNext
= GetPictureWindow(((WindowPtr
) pDrawable
));
790 SetPictureWindow(((WindowPtr
) pDrawable
), pPicture
);
793 SetPictureToDefaults(pPicture
);
796 *error
= ChangePicture(pPicture
, vmask
, vlist
, 0, client
);
799 if (*error
== Success
)
800 *error
= (*ps
->CreatePicture
) (pPicture
);
802 if (*error
!= Success
) {
803 FreePicture(pPicture
, (XID
) 0);
810 xRenderColorToCard32(xRenderColor c
)
813 (c
.alpha
>> 8 << 24) |
814 (c
.red
>> 8 << 16) | (c
.green
& 0xff00) | (c
.blue
>> 8);
818 initGradient(SourcePictPtr pGradient
, int stopCount
,
819 xFixed
* stopPoints
, xRenderColor
* stopColors
, int *error
)
824 if (stopCount
<= 0) {
830 for (i
= 0; i
< stopCount
; ++i
) {
831 if (stopPoints
[i
] < dpos
|| stopPoints
[i
] > (1 << 16)) {
835 dpos
= stopPoints
[i
];
838 pGradient
->gradient
.stops
= malloc(stopCount
* sizeof(PictGradientStop
));
839 if (!pGradient
->gradient
.stops
) {
844 pGradient
->gradient
.nstops
= stopCount
;
846 for (i
= 0; i
< stopCount
; ++i
) {
847 pGradient
->gradient
.stops
[i
].x
= stopPoints
[i
];
848 pGradient
->gradient
.stops
[i
].color
= stopColors
[i
];
853 createSourcePicture(void)
857 pPicture
= dixAllocateScreenObjectWithPrivates(NULL
, PictureRec
, PRIVATE_PICTURE
);
858 pPicture
->pDrawable
= 0;
859 pPicture
->pFormat
= 0;
861 pPicture
->format
= PICT_a8r8g8b8
;
863 SetPictureToDefaults(pPicture
);
868 CreateSolidPicture(Picture pid
, xRenderColor
* color
, int *error
)
872 pPicture
= createSourcePicture();
879 pPicture
->pSourcePict
= (SourcePictPtr
) malloc(sizeof(PictSolidFill
));
880 if (!pPicture
->pSourcePict
) {
885 pPicture
->pSourcePict
->type
= SourcePictTypeSolidFill
;
886 pPicture
->pSourcePict
->solidFill
.color
= xRenderColorToCard32(*color
);
891 CreateLinearGradientPicture(Picture pid
, xPointFixed
* p1
, xPointFixed
* p2
,
892 int nStops
, xFixed
* stops
, xRenderColor
* colors
,
902 pPicture
= createSourcePicture();
909 pPicture
->pSourcePict
= (SourcePictPtr
) malloc(sizeof(PictLinearGradient
));
910 if (!pPicture
->pSourcePict
) {
916 pPicture
->pSourcePict
->linear
.type
= SourcePictTypeLinear
;
917 pPicture
->pSourcePict
->linear
.p1
= *p1
;
918 pPicture
->pSourcePict
->linear
.p2
= *p2
;
920 initGradient(pPicture
->pSourcePict
, nStops
, stops
, colors
, error
);
929 CreateRadialGradientPicture(Picture pid
, xPointFixed
* inner
,
930 xPointFixed
* outer
, xFixed innerRadius
,
931 xFixed outerRadius
, int nStops
, xFixed
* stops
,
932 xRenderColor
* colors
, int *error
)
935 PictRadialGradient
*radial
;
942 pPicture
= createSourcePicture();
949 pPicture
->pSourcePict
= (SourcePictPtr
) malloc(sizeof(PictRadialGradient
));
950 if (!pPicture
->pSourcePict
) {
955 radial
= &pPicture
->pSourcePict
->radial
;
957 radial
->type
= SourcePictTypeRadial
;
958 radial
->c1
.x
= inner
->x
;
959 radial
->c1
.y
= inner
->y
;
960 radial
->c1
.radius
= innerRadius
;
961 radial
->c2
.x
= outer
->x
;
962 radial
->c2
.y
= outer
->y
;
963 radial
->c2
.radius
= outerRadius
;
965 initGradient(pPicture
->pSourcePict
, nStops
, stops
, colors
, error
);
974 CreateConicalGradientPicture(Picture pid
, xPointFixed
* center
, xFixed angle
,
975 int nStops
, xFixed
* stops
, xRenderColor
* colors
,
985 pPicture
= createSourcePicture();
992 pPicture
->pSourcePict
= (SourcePictPtr
) malloc(sizeof(PictConicalGradient
));
993 if (!pPicture
->pSourcePict
) {
999 pPicture
->pSourcePict
->conical
.type
= SourcePictTypeConical
;
1000 pPicture
->pSourcePict
->conical
.center
= *center
;
1001 pPicture
->pSourcePict
->conical
.angle
= angle
;
1003 initGradient(pPicture
->pSourcePict
, nStops
, stops
, colors
, error
);
1011 #define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
1013 #define NEXT_PTR(_type) ((_type) ulist++->ptr)
1016 ChangePicture(PicturePtr pPicture
,
1017 Mask vmask
, XID
*vlist
, DevUnion
*ulist
, ClientPtr client
)
1019 ScreenPtr pScreen
= pPicture
->pDrawable
? pPicture
->pDrawable
->pScreen
: 0;
1020 PictureScreenPtr ps
= pScreen
? GetPictureScreen(pScreen
) : 0;
1025 pPicture
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
1027 while (vmask
&& !error
) {
1028 index2
= (BITS32
) lowbit(vmask
);
1030 pPicture
->stateChanges
|= index2
;
1035 newr
= NEXT_VAL(unsigned int);
1037 if (newr
<= RepeatReflect
) {
1038 pPicture
->repeat
= (newr
!= RepeatNone
);
1039 pPicture
->repeatType
= newr
;
1042 client
->errorValue
= newr
;
1052 Picture pid
= NEXT_VAL(Picture
);
1057 error
= dixLookupResourceByType((pointer
*) &pAlpha
, pid
,
1058 PictureType
, client
,
1060 if (error
!= Success
) {
1061 client
->errorValue
= pid
;
1064 if (pAlpha
->pDrawable
== NULL
||
1065 pAlpha
->pDrawable
->type
!= DRAWABLE_PIXMAP
) {
1066 client
->errorValue
= pid
;
1073 pAlpha
= NEXT_PTR(PicturePtr
);
1075 if (pAlpha
&& pAlpha
->pDrawable
->type
== DRAWABLE_PIXMAP
)
1077 if (pPicture
->alphaMap
)
1078 FreePicture((pointer
) pPicture
->alphaMap
, (XID
) 0);
1079 pPicture
->alphaMap
= pAlpha
;
1083 case CPAlphaXOrigin
:
1084 pPicture
->alphaOrigin
.x
= NEXT_VAL(INT16
);
1087 case CPAlphaYOrigin
:
1088 pPicture
->alphaOrigin
.y
= NEXT_VAL(INT16
);
1092 pPicture
->clipOrigin
.x
= NEXT_VAL(INT16
);
1096 pPicture
->clipOrigin
.y
= NEXT_VAL(INT16
);
1109 pid
= NEXT_VAL(Pixmap
);
1112 pPixmap
= NullPixmap
;
1115 clipType
= CT_PIXMAP
;
1116 error
= dixLookupResourceByType((pointer
*) &pPixmap
, pid
,
1119 if (error
!= Success
) {
1120 client
->errorValue
= pid
;
1126 pPixmap
= NEXT_PTR(PixmapPtr
);
1129 clipType
= CT_PIXMAP
;
1135 if ((pPixmap
->drawable
.depth
!= 1) ||
1136 (pPixmap
->drawable
.pScreen
!= pScreen
)) {
1141 clipType
= CT_PIXMAP
;
1145 error
= (*ps
->ChangePictureClip
) (pPicture
, clipType
,
1146 (pointer
) pPixmap
, 0);
1149 case CPGraphicsExposure
:
1152 newe
= NEXT_VAL(unsigned int);
1155 pPicture
->graphicsExposures
= newe
;
1157 client
->errorValue
= newe
;
1162 case CPSubwindowMode
:
1165 news
= NEXT_VAL(unsigned int);
1167 if (news
== ClipByChildren
|| news
== IncludeInferiors
)
1168 pPicture
->subWindowMode
= news
;
1170 client
->errorValue
= news
;
1178 newe
= NEXT_VAL(unsigned int);
1180 if (newe
== PolyEdgeSharp
|| newe
== PolyEdgeSmooth
)
1181 pPicture
->polyEdge
= newe
;
1183 client
->errorValue
= newe
;
1191 newm
= NEXT_VAL(unsigned int);
1193 if (newm
== PolyModePrecise
|| newm
== PolyModeImprecise
)
1194 pPicture
->polyMode
= newm
;
1196 client
->errorValue
= newm
;
1202 (void) NEXT_VAL(Atom
); /* unimplemented */
1205 case CPComponentAlpha
:
1209 newca
= NEXT_VAL(unsigned int);
1212 pPicture
->componentAlpha
= newca
;
1214 client
->errorValue
= newca
;
1220 client
->errorValue
= maskQ
;
1226 (*ps
->ChangePicture
) (pPicture
, maskQ
);
1231 SetPictureClipRects(PicturePtr pPicture
,
1232 int xOrigin
, int yOrigin
, int nRect
, xRectangle
*rects
)
1234 ScreenPtr pScreen
= pPicture
->pDrawable
->pScreen
;
1235 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
1236 RegionPtr clientClip
;
1239 clientClip
= RegionFromRects(nRect
, rects
, CT_UNSORTED
);
1242 result
= (*ps
->ChangePictureClip
) (pPicture
, CT_REGION
,
1243 (pointer
) clientClip
, 0);
1244 if (result
== Success
) {
1245 pPicture
->clipOrigin
.x
= xOrigin
;
1246 pPicture
->clipOrigin
.y
= yOrigin
;
1247 pPicture
->stateChanges
|= CPClipXOrigin
| CPClipYOrigin
| CPClipMask
;
1248 pPicture
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
1254 SetPictureClipRegion(PicturePtr pPicture
,
1255 int xOrigin
, int yOrigin
, RegionPtr pRegion
)
1257 ScreenPtr pScreen
= pPicture
->pDrawable
->pScreen
;
1258 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
1259 RegionPtr clientClip
;
1265 clientClip
= RegionCreate(RegionExtents(pRegion
),
1266 RegionNumRects(pRegion
));
1269 if (!RegionCopy(clientClip
, pRegion
)) {
1270 RegionDestroy(clientClip
);
1279 result
= (*ps
->ChangePictureClip
) (pPicture
, type
, (pointer
) clientClip
, 0);
1280 if (result
== Success
) {
1281 pPicture
->clipOrigin
.x
= xOrigin
;
1282 pPicture
->clipOrigin
.y
= yOrigin
;
1283 pPicture
->stateChanges
|= CPClipXOrigin
| CPClipYOrigin
| CPClipMask
;
1284 pPicture
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
1290 transformIsIdentity(PictTransform
* t
)
1292 return ((t
->matrix
[0][0] == t
->matrix
[1][1]) &&
1293 (t
->matrix
[0][0] == t
->matrix
[2][2]) &&
1294 (t
->matrix
[0][0] != 0) &&
1295 (t
->matrix
[0][1] == 0) &&
1296 (t
->matrix
[0][2] == 0) &&
1297 (t
->matrix
[1][0] == 0) &&
1298 (t
->matrix
[1][2] == 0) &&
1299 (t
->matrix
[2][0] == 0) && (t
->matrix
[2][1] == 0));
1303 SetPictureTransform(PicturePtr pPicture
, PictTransform
* transform
)
1305 if (transform
&& transformIsIdentity(transform
))
1309 if (!pPicture
->transform
) {
1310 pPicture
->transform
=
1311 (PictTransform
*) malloc(sizeof(PictTransform
));
1312 if (!pPicture
->transform
)
1315 *pPicture
->transform
= *transform
;
1318 free(pPicture
->transform
);
1319 pPicture
->transform
= NULL
;
1321 pPicture
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
1323 if (pPicture
->pDrawable
!= NULL
) {
1325 PictureScreenPtr ps
= GetPictureScreen(pPicture
->pDrawable
->pScreen
);
1327 result
= (*ps
->ChangePictureTransform
) (pPicture
, transform
);
1336 CopyPicture(PicturePtr pSrc
, Mask mask
, PicturePtr pDst
)
1338 PictureScreenPtr ps
= GetPictureScreen(pSrc
->pDrawable
->pScreen
);
1339 Mask origMask
= mask
;
1341 pDst
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
1342 pDst
->stateChanges
|= mask
;
1345 Mask bit
= lowbit(mask
);
1349 pDst
->repeat
= pSrc
->repeat
;
1350 pDst
->repeatType
= pSrc
->repeatType
;
1353 if (pSrc
->alphaMap
&&
1354 pSrc
->alphaMap
->pDrawable
->type
== DRAWABLE_PIXMAP
)
1355 pSrc
->alphaMap
->refcnt
++;
1357 FreePicture((pointer
) pDst
->alphaMap
, (XID
) 0);
1358 pDst
->alphaMap
= pSrc
->alphaMap
;
1360 case CPAlphaXOrigin
:
1361 pDst
->alphaOrigin
.x
= pSrc
->alphaOrigin
.x
;
1363 case CPAlphaYOrigin
:
1364 pDst
->alphaOrigin
.y
= pSrc
->alphaOrigin
.y
;
1367 pDst
->clipOrigin
.x
= pSrc
->clipOrigin
.x
;
1370 pDst
->clipOrigin
.y
= pSrc
->clipOrigin
.y
;
1373 switch (pSrc
->clientClipType
) {
1375 (*ps
->ChangePictureClip
) (pDst
, CT_NONE
, NULL
, 0);
1378 if (!pSrc
->clientClip
) {
1379 (*ps
->ChangePictureClip
) (pDst
, CT_NONE
, NULL
, 0);
1382 RegionPtr clientClip
;
1383 RegionPtr srcClientClip
= (RegionPtr
) pSrc
->clientClip
;
1385 clientClip
= RegionCreate(RegionExtents(srcClientClip
),
1386 RegionNumRects(srcClientClip
));
1387 (*ps
->ChangePictureClip
) (pDst
, CT_REGION
, clientClip
, 0);
1391 /* XXX: CT_PIXMAP unimplemented */
1395 case CPGraphicsExposure
:
1396 pDst
->graphicsExposures
= pSrc
->graphicsExposures
;
1399 pDst
->polyEdge
= pSrc
->polyEdge
;
1402 pDst
->polyMode
= pSrc
->polyMode
;
1406 case CPComponentAlpha
:
1407 pDst
->componentAlpha
= pSrc
->componentAlpha
;
1413 (*ps
->ChangePicture
) (pDst
, origMask
);
1417 ValidateOnePicture(PicturePtr pPicture
)
1419 if (pPicture
->pDrawable
&&
1420 pPicture
->serialNumber
!= pPicture
->pDrawable
->serialNumber
) {
1421 PictureScreenPtr ps
= GetPictureScreen(pPicture
->pDrawable
->pScreen
);
1423 (*ps
->ValidatePicture
) (pPicture
, pPicture
->stateChanges
);
1424 pPicture
->stateChanges
= 0;
1425 pPicture
->serialNumber
= pPicture
->pDrawable
->serialNumber
;
1430 ValidatePicture(PicturePtr pPicture
)
1432 ValidateOnePicture(pPicture
);
1433 if (pPicture
->alphaMap
)
1434 ValidateOnePicture(pPicture
->alphaMap
);
1438 FreePicture(pointer value
, XID pid
)
1440 PicturePtr pPicture
= (PicturePtr
) value
;
1442 if (--pPicture
->refcnt
== 0) {
1443 free(pPicture
->transform
);
1445 if (pPicture
->pSourcePict
) {
1446 if (pPicture
->pSourcePict
->type
!= SourcePictTypeSolidFill
)
1447 free(pPicture
->pSourcePict
->linear
.stops
);
1449 free(pPicture
->pSourcePict
);
1452 if (pPicture
->pDrawable
) {
1453 ScreenPtr pScreen
= pPicture
->pDrawable
->pScreen
;
1454 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
1456 if (pPicture
->alphaMap
)
1457 FreePicture((pointer
) pPicture
->alphaMap
, (XID
) 0);
1458 (*ps
->DestroyPicture
) (pPicture
);
1459 (*ps
->DestroyPictureClip
) (pPicture
);
1460 if (pPicture
->pDrawable
->type
== DRAWABLE_WINDOW
) {
1461 WindowPtr pWindow
= (WindowPtr
) pPicture
->pDrawable
;
1464 for (pPrev
= (PicturePtr
*) dixLookupPrivateAddr
1465 (&pWindow
->devPrivates
, PictureWindowPrivateKey
);
1466 *pPrev
; pPrev
= &(*pPrev
)->pNext
) {
1467 if (*pPrev
== pPicture
) {
1468 *pPrev
= pPicture
->pNext
;
1473 else if (pPicture
->pDrawable
->type
== DRAWABLE_PIXMAP
) {
1474 (*pScreen
->DestroyPixmap
) ((PixmapPtr
) pPicture
->pDrawable
);
1477 dixFreeObjectWithPrivates(pPicture
, PRIVATE_PICTURE
);
1483 FreePictFormat(pointer pPictFormat
, XID pid
)
1489 * ReduceCompositeOp is used to choose simpler ops for cases where alpha
1490 * channels are always one and so math on the alpha channel per pixel becomes
1491 * unnecessary. It may also avoid destination reads sometimes if apps aren't
1492 * being careful to avoid these cases.
1495 ReduceCompositeOp(CARD8 op
, PicturePtr pSrc
, PicturePtr pMask
, PicturePtr pDst
,
1496 INT16 xSrc
, INT16 ySrc
, CARD16 width
, CARD16 height
)
1498 Bool no_src_alpha
, no_dst_alpha
;
1500 /* Sampling off the edge of a RepeatNone picture introduces alpha
1501 * even if the picture itself doesn't have alpha. We don't try to
1502 * detect every case where we don't sample off the edge, just the
1503 * simplest case where there is no transform on the source
1506 no_src_alpha
= PICT_FORMAT_COLOR(pSrc
->format
) &&
1507 PICT_FORMAT_A(pSrc
->format
) == 0 &&
1508 (pSrc
->repeatType
!= RepeatNone
||
1509 (!pSrc
->transform
&&
1510 xSrc
>= 0 && ySrc
>= 0 &&
1511 xSrc
+ width
<= pSrc
->pDrawable
->width
&&
1512 ySrc
+ height
<= pSrc
->pDrawable
->height
)) &&
1513 pSrc
->alphaMap
== NULL
&& pMask
== NULL
;
1514 no_dst_alpha
= PICT_FORMAT_COLOR(pDst
->format
) &&
1515 PICT_FORMAT_A(pDst
->format
) == 0 && pDst
->alphaMap
== NULL
;
1517 /* TODO, maybe: Conjoint and Disjoint op reductions? */
1519 /* Deal with simplifications where the source alpha is always 1. */
1525 case PictOpInReverse
:
1528 case PictOpOutReverse
:
1534 case PictOpAtopReverse
:
1535 op
= PictOpOverReverse
;
1545 /* Deal with simplifications when the destination alpha is always 1 */
1548 case PictOpOverReverse
:
1561 op
= PictOpOutReverse
;
1568 /* Reduce some con/disjoint ops to the basic names. */
1570 case PictOpDisjointClear
:
1571 case PictOpConjointClear
:
1574 case PictOpDisjointSrc
:
1575 case PictOpConjointSrc
:
1578 case PictOpDisjointDst
:
1579 case PictOpConjointDst
:
1590 CompositePicture(CARD8 op
,
1598 INT16 xDst
, INT16 yDst
, CARD16 width
, CARD16 height
)
1600 PictureScreenPtr ps
= GetPictureScreen(pDst
->pDrawable
->pScreen
);
1602 ValidatePicture(pSrc
);
1604 ValidatePicture(pMask
);
1605 ValidatePicture(pDst
);
1607 op
= ReduceCompositeOp(op
, pSrc
, pMask
, pDst
, xSrc
, ySrc
, width
, height
);
1608 if (op
== PictOpDst
)
1611 (*ps
->Composite
) (op
,
1615 xSrc
, ySrc
, xMask
, yMask
, xDst
, yDst
, width
, height
);
1619 CompositeRects(CARD8 op
,
1621 xRenderColor
* color
, int nRect
, xRectangle
*rects
)
1623 PictureScreenPtr ps
= GetPictureScreen(pDst
->pDrawable
->pScreen
);
1625 ValidatePicture(pDst
);
1626 (*ps
->CompositeRects
) (op
, pDst
, color
, nRect
, rects
);
1630 CompositeTrapezoids(CARD8 op
,
1633 PictFormatPtr maskFormat
,
1634 INT16 xSrc
, INT16 ySrc
, int ntrap
, xTrapezoid
* traps
)
1636 PictureScreenPtr ps
= GetPictureScreen(pDst
->pDrawable
->pScreen
);
1638 ValidatePicture(pSrc
);
1639 ValidatePicture(pDst
);
1640 (*ps
->Trapezoids
) (op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, ntrap
, traps
);
1644 CompositeTriangles(CARD8 op
,
1647 PictFormatPtr maskFormat
,
1649 INT16 ySrc
, int ntriangles
, xTriangle
* triangles
)
1651 PictureScreenPtr ps
= GetPictureScreen(pDst
->pDrawable
->pScreen
);
1653 ValidatePicture(pSrc
);
1654 ValidatePicture(pDst
);
1655 (*ps
->Triangles
) (op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, ntriangles
,
1660 CompositeTriStrip(CARD8 op
,
1663 PictFormatPtr maskFormat
,
1664 INT16 xSrc
, INT16 ySrc
, int npoints
, xPointFixed
* points
)
1666 PictureScreenPtr ps
= GetPictureScreen(pDst
->pDrawable
->pScreen
);
1671 ValidatePicture(pSrc
);
1672 ValidatePicture(pDst
);
1673 (*ps
->TriStrip
) (op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, npoints
, points
);
1677 CompositeTriFan(CARD8 op
,
1680 PictFormatPtr maskFormat
,
1681 INT16 xSrc
, INT16 ySrc
, int npoints
, xPointFixed
* points
)
1683 PictureScreenPtr ps
= GetPictureScreen(pDst
->pDrawable
->pScreen
);
1688 ValidatePicture(pSrc
);
1689 ValidatePicture(pDst
);
1690 (*ps
->TriFan
) (op
, pSrc
, pDst
, maskFormat
, xSrc
, ySrc
, npoints
, points
);
1694 AddTraps(PicturePtr pPicture
, INT16 xOff
, INT16 yOff
, int ntrap
, xTrap
* traps
)
1696 PictureScreenPtr ps
= GetPictureScreen(pPicture
->pDrawable
->pScreen
);
1698 ValidatePicture(pPicture
);
1699 (*ps
->AddTraps
) (pPicture
, xOff
, yOff
, ntrap
, traps
);