1 /*
2 * Support for RENDER extension with rootless
3 */
4 /*
5 * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
6 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Except as contained in this notice, the name(s) of the above copyright
27 * holders shall not be used in advertising or otherwise to promote the sale,
28 * use or other dealings in this Software without prior written authorization.
29 */
30 /* This file is largely based on fbcompose.c and fbpict.c, which contain
31 * the following copyright:
32 *
33 * Copyright � 2000 Keith Packard, member of The XFree86 Project, Inc.
34 */
35 /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/aquaPicture.c,v 1.3 2002/09/28 00:00:03 torrey Exp $ */
36
37 #define DEFAULT_LOG_FORMATS 0
38
39 #ifdef RENDER
40
41 #include "fb.h"
42 #include "picturestr.h"
43 #include "mipict.h"
44 #include "fbpict.h"
45 #include "rootless.h"
46
47 # define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
48
49
50 // Replacement for fbStore_x8r8g8b8 that sets the alpha channel
51 void
RootlessStore_x8r8g8b8(FbCompositeOperand * op,CARD32 value)52 RootlessStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value)
53 {
54 FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset;
55 ((CARD32 *)line)[offset >> 5] = (value & 0xffffff) | 0xff000000;
56 }
57
58
59 // Defined in fbcompose.c
60 extern FbCombineFunc fbCombineFuncU[];
61 extern FbCombineFunc fbCombineFuncC[];
62
63 void
RootlessCompositeGeneral(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)64 RootlessCompositeGeneral(
65 CARD8 op,
66 PicturePtr pSrc,
67 PicturePtr pMask,
68 PicturePtr pDst,
69 INT16 xSrc,
70 INT16 ySrc,
71 INT16 xMask,
72 INT16 yMask,
73 INT16 xDst,
74 INT16 yDst,
75 CARD16 width,
76 CARD16 height)
77 {
78 FbCompositeOperand src[4],msk[4],dst[4],*pmsk;
79 FbCompositeOperand *srcPict, *srcAlpha;
80 FbCompositeOperand *dstPict, *dstAlpha;
81 FbCompositeOperand *mskPict = 0, *mskAlpha = 0;
82 FbCombineFunc f;
83 int w;
84
85 if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE))
86 return;
87 if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE))
88 return;
89
90 // Use Rootless operands for on screen picture formats
91 if (pDst->format == PICT_x8r8g8b8) {
92 dst[0].store = RootlessStore_x8r8g8b8;
93 }
94
95 if (pSrc->alphaMap)
96 {
97 srcPict = &src[1];
98 srcAlpha = &src[2];
99 }
100 else
101 {
102 srcPict = &src[0];
103 srcAlpha = 0;
104 }
105 if (pDst->alphaMap)
106 {
107 dstPict = &dst[1];
108 dstAlpha = &dst[2];
109 }
110 else
111 {
112 dstPict = &dst[0];
113 dstAlpha = 0;
114 }
115 f = fbCombineFuncU[op];
116 if (pMask)
117 {
118 if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE))
119 return;
120 pmsk = msk;
121 if (pMask->componentAlpha)
122 f = fbCombineFuncC[op];
123 if (pMask->alphaMap)
124 {
125 mskPict = &msk[1];
126 mskAlpha = &msk[2];
127 }
128 else
129 {
130 mskPict = &msk[0];
131 mskAlpha = 0;
132 }
133 }
134 else
135 pmsk = 0;
136 while (height--)
137 {
138 w = width;
139
140 while (w--)
141 {
142 (*f) (src, pmsk, dst);
143 (*src->over) (src);
144 (*dst->over) (dst);
145 if (pmsk)
146 (*pmsk->over) (pmsk);
147 }
148 (*src->down) (src);
149 (*dst->down) (dst);
150 if (pmsk)
151 (*pmsk->down) (pmsk);
152 }
153 }
154
155 static int rootless_log_pict_formats = DEFAULT_LOG_FORMATS;
156
op_name(int op)157 static const char *op_name (int op)
158 {
159 static const char *ops[] = {
160 "Clear", "Src", "Dst", "Over", "OverReverse", "In", "InReverse",
161 "Out", "OutReverse", "Atop", "AtopReverse", "Xor", "Add",
162 "Saturate", "Maximum",
163
164 "DisjointClear", "DisjointSrc", "DisjointDst", "DisjointOver",
165 "DisjointOverReverse", "DisjointIn", "DisjointInReverse",
166 "DisjointOut", "DisjointOutReverse", "DisjointAtop",
167 "DisjointAtopReverse", "DisjointXor", "DisjointMaximum",
168
169 "ConjointClear", "ConjointSrc", "ConjointDst", "ConjointOver",
170 "ConjointOverReverse", "ConjointIn", "ConjointInReverse",
171 "ConjointOut", "ConjointOutReverse", "ConjointAtop",
172 "ConjointAtopReverse", "ConjointXor", "ConjointMaximum",
173 };
174
175 if (op >= 0 && op < (int) (sizeof (ops) / sizeof (ops[0])))
176 return ops[op];
177 else
178 return "Unknown";
179 }
180
type_name(int type)181 static const char *type_name (int type)
182 {
183 switch (type)
184 {
185 case PICT_TYPE_OTHER:
186 return "Other";
187 case PICT_TYPE_A:
188 return "A";
189 case PICT_TYPE_ARGB:
190 return "ARGB";
191 case PICT_TYPE_ABGR:
192 return "ABGR";
193 case PICT_TYPE_COLOR:
194 return "Color";
195 case PICT_TYPE_GRAY:
196 return "Gray";
197 default:
198 return "Unknown";
199 }
200 }
201
log_format(int op,unsigned int src,unsigned int dst,unsigned int mask)202 static void log_format (int op, unsigned int src,
203 unsigned int dst, unsigned int mask)
204 {
205 struct op {
206 int op;
207 unsigned int src, dst, mask;
208 };
209
210 static struct op *ops;
211 static int n_ops, allocated_ops;
212
213 int i;
214
215 for (i = 0; i < n_ops; i++)
216 {
217 if (ops[i].op == op && ops[i].src == src
218 && ops[i].dst == dst && ops[i].mask == mask)
219 {
220 return;
221 }
222 }
223
224 if (n_ops == allocated_ops)
225 {
226 allocated_ops *= 2;
227 ops = realloc (ops, allocated_ops * sizeof (struct op));
228 }
229
230 ops[n_ops].op = op;
231 ops[n_ops].src = src;
232 ops[n_ops].dst = dst;
233 ops[n_ops].mask = mask;
234 n_ops++;
235
236 fprintf (stderr,
237 "op: %s src (%dbpp %s %04x) dst (%dbpp %s %04x) mask (%dbpp %s %04x)\n",
238 op_name (op), PICT_FORMAT_BPP (src),
239 type_name (PICT_FORMAT_TYPE (src)),
240 src & 0xffff, PICT_FORMAT_BPP (dst),
241 type_name (PICT_FORMAT_TYPE (dst)),
242 dst & 0xffff, PICT_FORMAT_BPP (mask),
243 type_name (PICT_FORMAT_TYPE (mask)),
244 mask & 0xffff);
245 }
246
247 void
RootlessComposite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)248 RootlessComposite(
249 CARD8 op,
250 PicturePtr pSrc,
251 PicturePtr pMask,
252 PicturePtr pDst,
253 INT16 xSrc,
254 INT16 ySrc,
255 INT16 xMask,
256 INT16 yMask,
257 INT16 xDst,
258 INT16 yDst,
259 CARD16 width,
260 CARD16 height)
261 {
262 RegionRec region;
263 int n;
264 BoxPtr pbox;
265 CompositeFunc func;
266 Bool srcRepeat = pSrc->repeat;
267 Bool maskRepeat = FALSE;
268 Bool srcAlphaMap = pSrc->alphaMap != 0;
269 Bool maskAlphaMap = FALSE;
270 Bool dstAlphaMap = pDst->alphaMap != 0;
271 int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
272 int w, h, w_this, h_this;
273 int dstDepth = pDst->pDrawable->depth;
274
275 xDst += pDst->pDrawable->x;
276 yDst += pDst->pDrawable->y;
277 xSrc += pSrc->pDrawable->x;
278 ySrc += pSrc->pDrawable->y;
279 if (pMask)
280 {
281 xMask += pMask->pDrawable->x;
282 yMask += pMask->pDrawable->y;
283 maskRepeat = pMask->repeat;
284 maskAlphaMap = pMask->alphaMap != 0;
285 }
286
287 if (rootless_log_pict_formats)
288 {
289 log_format (op, pSrc->format, pDst->format,
290 pMask != 0 ? pMask->format : 0);
291 }
292
293 if (!miComputeCompositeRegion (®ion,
294 pSrc,
295 pMask,
296 pDst,
297 xSrc,
298 ySrc,
299 xMask,
300 yMask,
301 xDst,
302 yDst,
303 width,
304 height))
305 return;
306
307 if (pDst->pDrawable->type == DRAWABLE_WINDOW
308 && pDst->pDrawable->depth == 24
309 && pDst->pDrawable->bitsPerPixel == 32)
310 {
311 /* fbpict code sets bits above depth to zero. We don't want that! */
312
313 pDst->pDrawable->depth = 32;
314 }
315
316 func = RootlessCompositeGeneral;
317
318 if (!maskAlphaMap && !srcAlphaMap && !dstAlphaMap)
319 switch (op) {
320 case PictOpOver:
321 if (pMask)
322 {
323 if (srcRepeat &&
324 pSrc->pDrawable->width == 1 &&
325 pSrc->pDrawable->height == 1)
326 {
327 srcRepeat = FALSE;
328 if (PICT_FORMAT_COLOR(pSrc->format)) {
329 switch (pMask->format) {
330 case PICT_a8:
331 switch (pDst->format) {
332 case PICT_r5g6b5:
333 case PICT_b5g6r5:
334 func = fbCompositeSolidMask_nx8x0565;
335 break;
336 case PICT_r8g8b8:
337 case PICT_b8g8r8:
338 func = fbCompositeSolidMask_nx8x0888;
339 break;
340 case PICT_a8r8g8b8:
341 case PICT_x8r8g8b8:
342 case PICT_a8b8g8r8:
343 case PICT_x8b8g8r8:
344 func = fbCompositeSolidMask_nx8x8888;
345 break;
346 }
347 break;
348 case PICT_a8r8g8b8:
349 if (pMask->componentAlpha) {
350 switch (pDst->format) {
351 case PICT_a8r8g8b8:
352 case PICT_x8r8g8b8:
353 func = fbCompositeSolidMask_nx8888x8888C;
354 break;
355 case PICT_r5g6b5:
356 func = fbCompositeSolidMask_nx8888x0565C;
357 break;
358 }
359 }
360 break;
361 case PICT_a8b8g8r8:
362 if (pMask->componentAlpha) {
363 switch (pDst->format) {
364 case PICT_a8b8g8r8:
365 case PICT_x8b8g8r8:
366 func = fbCompositeSolidMask_nx8888x8888C;
367 break;
368 case PICT_b5g6r5:
369 func = fbCompositeSolidMask_nx8888x0565C;
370 break;
371 }
372 }
373 break;
374 case PICT_a1:
375 switch (pDst->format) {
376 case PICT_r5g6b5:
377 case PICT_b5g6r5:
378 case PICT_r8g8b8:
379 case PICT_b8g8r8:
380 case PICT_a8r8g8b8:
381 case PICT_x8r8g8b8:
382 case PICT_a8b8g8r8:
383 case PICT_x8b8g8r8:
384 func = fbCompositeSolidMask_nx1xn;
385 break;
386 }
387 }
388 }
389 }
390 }
391 else
392 {
393 switch (pSrc->format) {
394 case PICT_a8r8g8b8:
395 case PICT_x8r8g8b8:
396 switch (pDst->format) {
397 case PICT_a8r8g8b8:
398 case PICT_x8r8g8b8:
399 func = fbCompositeSrc_8888x8888;
400 break;
401 case PICT_r8g8b8:
402 func = fbCompositeSrc_8888x0888;
403 break;
404 case PICT_r5g6b5:
405 func = fbCompositeSrc_8888x0565;
406 break;
407 }
408 break;
409 case PICT_a8b8g8r8:
410 case PICT_x8b8g8r8:
411 switch (pDst->format) {
412 case PICT_a8b8g8r8:
413 case PICT_x8b8g8r8:
414 func = fbCompositeSrc_8888x8888;
415 break;
416 case PICT_b8g8r8:
417 func = fbCompositeSrc_8888x0888;
418 break;
419 case PICT_b5g6r5:
420 func = fbCompositeSrc_8888x0565;
421 break;
422 }
423 break;
424 case PICT_r5g6b5:
425 switch (pDst->format) {
426 case PICT_r5g6b5:
427 func = fbCompositeSrc_0565x0565;
428 break;
429 }
430 break;
431 case PICT_b5g6r5:
432 switch (pDst->format) {
433 case PICT_b5g6r5:
434 func = fbCompositeSrc_0565x0565;
435 break;
436 }
437 break;
438 }
439 }
440 break;
441 case PictOpAdd:
442 if (pMask == 0)
443 {
444 switch (pSrc->format) {
445 case PICT_a8r8g8b8:
446 switch (pDst->format) {
447 case PICT_a8r8g8b8:
448 func = fbCompositeSrcAdd_8888x8888;
449 break;
450 }
451 break;
452 case PICT_a8b8g8r8:
453 switch (pDst->format) {
454 case PICT_a8b8g8r8:
455 func = fbCompositeSrcAdd_8888x8888;
456 break;
457 }
458 break;
459 case PICT_a8:
460 switch (pDst->format) {
461 case PICT_a8:
462 func = fbCompositeSrcAdd_8000x8000;
463 break;
464 }
465 break;
466 case PICT_a1:
467 switch (pDst->format) {
468 case PICT_a1:
469 func = fbCompositeSrcAdd_1000x1000;
470 break;
471 }
472 break;
473 }
474 }
475 break;
476 }
477
478 n = REGION_NUM_RECTS (®ion);
479 pbox = REGION_RECTS (®ion);
480 while (n--)
481 {
482 h = pbox->y2 - pbox->y1;
483 y_src = pbox->y1 - yDst + ySrc;
484 y_msk = pbox->y1 - yDst + yMask;
485 y_dst = pbox->y1;
486 while (h)
487 {
488 h_this = h;
489 w = pbox->x2 - pbox->x1;
490 x_src = pbox->x1 - xDst + xSrc;
491 x_msk = pbox->x1 - xDst + xMask;
492 x_dst = pbox->x1;
493 if (maskRepeat)
494 {
495 y_msk = mod (y_msk, pMask->pDrawable->height);
496 if (h_this > pMask->pDrawable->height - y_msk)
497 h_this = pMask->pDrawable->height - y_msk;
498 }
499 if (srcRepeat)
500 {
501 y_src = mod (y_src, pSrc->pDrawable->height);
502 if (h_this > pSrc->pDrawable->height - y_src)
503 h_this = pSrc->pDrawable->height - y_src;
504 }
505 while (w)
506 {
507 w_this = w;
508 if (maskRepeat)
509 {
510 x_msk = mod (x_msk, pMask->pDrawable->width);
511 if (w_this > pMask->pDrawable->width - x_msk)
512 w_this = pMask->pDrawable->width - x_msk;
513 }
514 if (srcRepeat)
515 {
516 x_src = mod (x_src, pSrc->pDrawable->width);
517 if (w_this > pSrc->pDrawable->width - x_src)
518 w_this = pSrc->pDrawable->width - x_src;
519 }
520 (*func) (op, pSrc, pMask, pDst,
521 x_src, y_src, x_msk, y_msk, x_dst, y_dst,
522 w_this, h_this);
523 w -= w_this;
524 x_src += w_this;
525 x_msk += w_this;
526 x_dst += w_this;
527 }
528 h -= h_this;
529 y_src += h_this;
530 y_msk += h_this;
531 y_dst += h_this;
532 }
533 pbox++;
534 }
535 REGION_UNINIT (pDst->pDrawable->pScreen, ®ion);
536
537 pDst->pDrawable->depth = dstDepth;
538 }
539
540 #endif /* RENDER */
541