2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
4 #include "evas_common.h"
5 //#include "evas_macros.h"
6 #include "evas_private.h"
7 #include "evas_engine.h"
8 #include "Evas_Engine_XRender_X11.h"
11 /* this is a work around broken xrender - when/if this ever gets fixed in xorg
12 * we can comment this out and one day remove it - for now keep it until such
13 * a fix is spotted in the wild
15 #define BROKEN_XORG_XRENDER 1
17 /* should be const char*, but the prototype for XRenderSetPictureFilter
21 get_filter(int smooth)
23 return smooth ? FilterBest : FilterNearest;
27 _xr_render_surface_new(Ximage_Info *xinf, int w, int h, XRenderPictFormat *fmt, int alpha)
30 XRenderPictureAttributes att;
32 if ((!xinf) || (!fmt) || (w < 1) || (h < 1)) return NULL;
33 rs = calloc(1, sizeof(Xrender_Surface));
40 rs->depth = fmt->depth;
42 rs->draw = XCreatePixmap(xinf->disp, xinf->root, w, h, fmt->depth);
48 rs->xinf->references++;
50 att.component_alpha = 0;
52 rs->pic = XRenderCreatePicture(xinf->disp, rs->draw, fmt,
53 CPRepeat | CPDither | CPComponentAlpha, &att);
56 XFreePixmap(rs->xinf->disp, rs->draw);
57 rs->xinf->references--;
65 _xr_render_surface_adopt(Ximage_Info *xinf, Drawable draw, int w, int h, int alpha)
68 XRenderPictFormat *fmt;
69 XRenderPictureAttributes att;
71 if ((!xinf) || (draw == None) || (w < 1) || (h < 1)) return NULL;
72 fmt = XRenderFindVisualFormat(xinf->disp, xinf->vis);
73 if (!fmt) return NULL;
74 rs = calloc(1, sizeof(Xrender_Surface));
81 rs->depth = fmt->depth;
82 if (fmt->depth == 32) rs->alpha = 1;
85 rs->xinf->references++;
87 att.component_alpha = 0;
89 rs->pic = XRenderCreatePicture(xinf->disp, rs->draw, fmt,
90 CPRepeat | CPDither | CPComponentAlpha, &att);
93 rs->xinf->references--;
101 _xr_render_surface_format_adopt(Ximage_Info *xinf, Drawable draw, int w, int h, XRenderPictFormat *fmt, int alpha)
104 XRenderPictureAttributes att;
106 if ((!xinf) || (!fmt) || (draw == None) || (w < 1) || (h < 1)) return NULL;
107 rs = calloc(1, sizeof(Xrender_Surface));
108 if (!rs) return NULL;
114 rs->depth = fmt->depth;
115 if (fmt->depth == 32) rs->alpha = 1;
116 rs->xinf->references++;
120 att.component_alpha = 0;
122 rs->pic = XRenderCreatePicture(xinf->disp, rs->draw, fmt, CPRepeat | CPDither | CPComponentAlpha, &att);
125 rs->xinf->references--;
133 _xr_render_surface_free(Xrender_Surface *rs)
138 if ((rs->allocated) && (rs->draw != None))
139 XFreePixmap(rs->xinf->disp, rs->draw);
141 XRenderFreePicture(rs->xinf->disp, rs->pic);
142 _xr_image_info_free(rs->xinf);
149 _xr_render_surface_repeat_set(Xrender_Surface *rs, int repeat)
151 XRenderPictureAttributes att;
154 XRenderChangePicture(rs->xinf->disp, rs->pic, CPRepeat, &att);
158 _xr_render_surface_solid_rectangle_set(Xrender_Surface *rs, int r, int g, int b, int a, int x, int y, int w, int h)
162 col.red = (r << 8) | r;
163 col.green = (g << 8) | g;
164 col.blue = (b << 8) | b;
165 col.alpha = (a << 8) | a;
166 XRenderFillRectangle(rs->xinf->disp, PictOpSrc, rs->pic, &col, x, y, w, h);
170 _xr_render_surface_argb_pixels_fill(Xrender_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h, int ox, int oy)
173 unsigned int *p, *sp, *sple, *spe;
174 unsigned int jump, sjump;
176 xim = _xr_image_new(rs->xinf, w, h, rs->depth);
178 p = (unsigned int *)xim->data;
179 sp = ((unsigned int *)pixels) + (y * sw) + x;
180 jump = ((xim->line_bytes / 4) - w);
182 spe = sp + ((h - 1) * sw) + w;
184 #ifdef WORDS_BIGENDIAN
185 (xim->xim->byte_order == LSBFirst)
187 (xim->xim->byte_order == MSBFirst)
195 *p++ = (*sp << 24) + ((*sp << 8) & 0xff0000) + ((*sp >> 8) & 0xff00) + (*sp >> 24);
196 // *p++ = (B_VAL(sp) << 24) | (G_VAL(sp) << 16) | (R_VAL(sp) << 8) | A_VAL(sp);
214 _xr_image_put(xim, rs->draw, x + ox, y + oy, w, h);
218 _xr_render_surface_rgb_pixels_fill(Xrender_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h, int ox, int oy)
221 unsigned int *p, *sp, *sple, *spe;
222 unsigned int jump, sjump;
224 xim = _xr_image_new(rs->xinf, w, h, rs->depth);
226 p = (unsigned int *)xim->data;
227 sp = ((unsigned int *)pixels) + (y * sw) + x;
229 spe = sp + ((h - 1) * sw) + w;
232 jump = ((xim->line_bytes / 2) - w);
233 /* FIXME: if rs->depth == 16 - convert */
234 Gfx_Func_Convert conv_func;
237 #ifdef WORDS_BIGENDIAN
238 swap = (int)(xim->xim->byte_order == LSBFirst);
240 swap = (int)(xim->xim->byte_order == MSBFirst);
242 /* FIXME: swap not handled */
243 conv_func = evas_common_convert_func_get(sp, w, h, rs->depth,
244 rs->xinf->vis->red_mask,
245 rs->xinf->vis->green_mask,
246 rs->xinf->vis->blue_mask,
249 conv_func(sp, p, sjump, jump, w, h, x, y, NULL);
253 jump = ((xim->line_bytes / 4) - w);
255 #ifdef WORDS_BIGENDIAN
256 (xim->xim->byte_order == LSBFirst)
258 (xim->xim->byte_order == MSBFirst)
266 *p++ = (*sp << 24) + ((*sp << 8) & 0xff0000) + ((*sp >> 8) & 0xff00) + 0xff;
267 // *p++ = ((B_VAL(sp)) << 24) | ((G_VAL(sp)) << 16) | ((R_VAL(sp)) << 8) | 0x000000ff;
280 *p++ = 0xff000000 | *sp++;
286 _xr_image_put(xim, rs->draw, x + ox, y + oy, w, h);
290 _xr_render_surface_clips_set(Xrender_Surface *rs, RGBA_Draw_Context *dc, int rx, int ry, int rw, int rh)
293 XRectangle *rect = NULL;
295 if ((dc) && (dc->clip.use))
297 RECTS_CLIP_TO_RECT(rx, ry, rw, rh,
298 dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
300 if ((!dc) || (!dc->cutout.rects))
302 rect = malloc(sizeof(XRectangle));
316 rects = evas_common_draw_context_apply_cutouts(dc);
318 rect = malloc(num * sizeof(XRectangle));
320 for (i = 0; i < num; i++)
322 r = rects->rects + i;
325 rect[i].width = r->w;
326 rect[i].height = r->h;
328 evas_common_draw_context_apply_clear_cutouts(rects);
331 XRenderSetPictureClipRectangles(rs->xinf->disp, rs->pic, 0, 0, rect, num);
335 /* initialized the transform to the identity */
337 init_xtransform(XTransform *t)
341 for (i = 0; i < 3; i++)
342 for (j = 0; j < 3; j++)
343 t->matrix[i][j] = XDoubleToFixed((i == j) ? 1 : 0);
347 set_xtransform_scale(XTransform *t, int sw, int sh, int w, int h, int tx, int ty)
349 // if ((sw > 1) && (w > 1))
351 // if ((sh > 1) && (h > 1))
353 t->matrix[0][0] = XDoubleToFixed((double)(sw) / (double)(w));
354 t->matrix[1][1] = XDoubleToFixed((double)(sh) / (double)(h));
355 t->matrix[2][0] = (tx * sw) / w;
356 t->matrix[2][1] = (ty * sh) / h;
359 // when color multiplier is used want: instead
360 // CA src IN mask SRC temp; non-CA temp OVER dst. - i think. need to check.
362 _xr_render_surface_composite(Xrender_Surface *srs, Xrender_Surface *drs, RGBA_Draw_Context *dc, int sx, int sy, int sw, int sh, int x, int y, int w, int h, int smooth)
364 Xrender_Surface *trs = NULL;
366 XRenderPictureAttributes att;
368 int e, is_scaling, op;
370 if ((sw <= 0) || (sh <= 0) || (w <= 0) || (h <= 0)) return;
372 is_scaling = e = ((sw != w) || (sh != h));
374 att.clip_mask = None;
375 XRenderChangePicture(srs->xinf->disp, srs->pic, CPClipMask, &att);
376 XRenderChangePicture(drs->xinf->disp, drs->pic, CPClipMask, &att);
378 init_xtransform(&xf);
381 if (dc->render_op == _EVAS_RENDER_BLEND)
383 if (!srs->alpha) op = PictOpSrc;
385 else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
387 else if (dc->render_op == _EVAS_RENDER_MUL)
389 else if (dc->render_op == _EVAS_RENDER_COPY)
391 else if (dc->render_op == _EVAS_RENDER_COPY_REL)
393 else if (dc->render_op == _EVAS_RENDER_MASK)
394 op = PictOpInReverse;
396 if ((dc) && (dc->mul.use))
400 if ((op == PictOpOver) && (!dc->mul.col)) return;
401 a = dc->mul.col >> 24;
402 r = (dc->mul.col >> 16) & 0xff;
403 g = (dc->mul.col >> 8) & 0xff;
404 b = dc->mul.col & 0xff;
405 if (a < 255) op = PictOpOver;
406 if (dc->mul.col != 0xffffffff)
408 if ((srs->xinf->mul_r != r) || (srs->xinf->mul_g != g) ||
409 (srs->xinf->mul_b != b) || (srs->xinf->mul_a != a))
411 srs->xinf->mul_r = r;
412 srs->xinf->mul_g = g;
413 srs->xinf->mul_b = b;
414 srs->xinf->mul_a = a;
415 _xr_render_surface_solid_rectangle_set(srs->xinf->mul,
419 mask = srs->xinf->mul->pic;
420 if (dc->mul.col == (a * 0x01010101))
422 att.component_alpha = 0;
423 XRenderChangePicture(srs->xinf->disp, mask, CPComponentAlpha, &att);
427 if ((srs->alpha) || (a != 0xff))
428 trs = _xr_render_surface_new(srs->xinf, sw + 2, sh + 2,
429 srs->xinf->fmt32, 1);
431 trs = _xr_render_surface_new(srs->xinf, sw + 2, sh + 2,
432 srs->fmt, srs->alpha);
435 att.component_alpha = 1;
436 XRenderChangePicture(srs->xinf->disp, mask, CPComponentAlpha, &att);
437 XRenderSetPictureTransform(srs->xinf->disp, srs->pic, &xf);
438 XRenderComposite(srs->xinf->disp, PictOpSrc, srs->pic, mask,
442 0, 0, sw + 2, sh + 2);
448 //#define HFW + (sw / 2)
449 //#define HFH + (sh / 2)
453 _xr_render_surface_clips_set(drs, dc, x, y, w, h);
456 XRenderSetPictureFilter(trs->xinf->disp, trs->pic, get_filter(smooth), NULL, 0);
458 set_xtransform_scale(&xf, sw, sh, w, h, -1, -1);
459 XRenderSetPictureTransform(trs->xinf->disp, trs->pic, &xf);
461 att.component_alpha = 0;
462 if (dc->render_op == _EVAS_RENDER_MUL) att.component_alpha = 1;
463 XRenderChangePicture(trs->xinf->disp, trs->pic, CPComponentAlpha, &att);
465 XRenderComposite(trs->xinf->disp, op, trs->pic, mask, drs->pic,
466 (w HFW) / sw, (h HFH) / sh,
467 (w HFW) / sw, (h HFH) / sh,
469 _xr_render_surface_free(trs);
473 if (srs->bordered && is_scaling)
475 trs = _xr_render_surface_new(srs->xinf, sw + 2, sh + 2,
476 srs->fmt, srs->alpha);
479 att.component_alpha = 0;
480 XRenderChangePicture(srs->xinf->disp, srs->pic, CPComponentAlpha, &att);
481 XRenderSetPictureTransform(srs->xinf->disp, srs->pic, &xf);
483 XRenderComposite(srs->xinf->disp, PictOpSrc, srs->pic, None,
484 trs->pic, sx, sy, sx, sy, 0, 0, sw + 2, sh + 2);
486 XRenderSetPictureFilter(trs->xinf->disp, trs->pic, get_filter(smooth), NULL, 0);
488 set_xtransform_scale(&xf, sw, sh, w, h, -1, -1);
489 XRenderSetPictureTransform(trs->xinf->disp, trs->pic, &xf);
491 if (dc->render_op == _EVAS_RENDER_MUL)
493 att.component_alpha = 1;
494 XRenderChangePicture(trs->xinf->disp, trs->pic, CPComponentAlpha, &att);
497 XRenderComposite(trs->xinf->disp, op, trs->pic, mask, drs->pic,
498 (w HFW) / sw, (h HFH) / sh,
499 (w HFW) / sw, (h HFH) / sh,
502 _xr_render_surface_free(trs);
506 XRenderSetPictureFilter(srs->xinf->disp, srs->pic, get_filter(smooth), NULL, 0);
508 set_xtransform_scale(&xf, sw, sh, w, h, 0, 0);
509 XRenderSetPictureTransform(srs->xinf->disp, srs->pic, &xf);
511 att.component_alpha = 0;
512 if (dc->render_op == _EVAS_RENDER_MUL)
513 att.component_alpha = 1;
514 XRenderChangePicture(srs->xinf->disp, srs->pic, CPComponentAlpha, &att);
516 XRenderComposite(srs->xinf->disp, op, srs->pic, mask, drs->pic,
517 ((((sx + 1) * w) HFW) / sw),
518 ((((sy + 1) * h) HFH) / sh),
519 ((((sx + 1) * w) HFW) / sw),
520 ((((sy + 1) * h) HFH) / sh),
527 _xr_render_surface_copy(Xrender_Surface *srs, Xrender_Surface *drs, int sx, int sy, int x, int y, int w, int h)
530 XRenderPictureAttributes att;
532 if ((w <= 0) || (h <= 0) || (!srs) || (!drs)) return;
534 init_xtransform(&xf);
535 #ifdef BROKEN_XORG_XRENDER
536 /* FIXME: why do we need to change the identity matrix ifthe src surface
541 xf.matrix[0][0] = xf.matrix[1][1] = xf.matrix[2][2] = 1;
544 XRenderSetPictureTransform(srs->xinf->disp, srs->pic, &xf);
545 // XRenderSetPictureFilter(srs->xinf->disp, srs->pic, FilterNearest, NULL, 0);
547 att.clip_mask = None;
548 XRenderChangePicture(srs->xinf->disp, srs->pic, CPClipMask, &att);
549 XRenderChangePicture(drs->xinf->disp, drs->pic, CPClipMask, &att);
551 XRenderComposite(srs->xinf->disp, PictOpSrc, srs->pic, None, drs->pic,
552 sx, sy, 0, 0, x, y, w, h);
556 _xr_render_surface_rectangle_draw(Xrender_Surface *rs, RGBA_Draw_Context *dc, int x, int y, int w, int h)
559 XRenderPictureAttributes att;
562 if ((!rs) || (!dc)) return;
563 if ((w <= 0) || (h <= 0)) return;
564 a = dc->col.col >> 24;
565 r = (dc->col.col >> 16) & 0xff;
566 g = (dc->col.col >> 8 ) & 0xff;
567 b = (dc->col.col ) & 0xff;
568 col.red = (r << 8) | r;
569 col.green = (g << 8) | g;
570 col.blue = (b << 8) | b;
571 col.alpha = (a << 8) | a;
573 if (dc->render_op == _EVAS_RENDER_BLEND)
575 if (!dc->col.col) return;
576 if (a == 0xff) op = PictOpSrc;
578 else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
580 if (!dc->col.col) return;
583 else if (dc->render_op == _EVAS_RENDER_MUL)
585 if (dc->col.col == 0xffffffff) return;
588 else if (dc->render_op == _EVAS_RENDER_COPY)
590 else if (dc->render_op == _EVAS_RENDER_COPY_REL)
592 else if (dc->render_op == _EVAS_RENDER_MASK)
593 op = PictOpInReverse;
595 att.clip_mask = None;
596 XRenderChangePicture(rs->xinf->disp, rs->pic, CPClipMask, &att);
598 _xr_render_surface_clips_set(rs, dc, x, y, w, h);
599 XRenderFillRectangle(rs->xinf->disp, op, rs->pic, &col, x, y, w, h);
603 _xr_render_surface_line_draw(Xrender_Surface *rs, RGBA_Draw_Context *dc, int x1, int y1, int x2, int y2)
605 XRenderPictureAttributes att;
608 if ((!rs) || (!dc) || (!dc->col.col)) return;
610 if (dc->render_op == _EVAS_RENDER_BLEND)
612 if (!dc->col.col) return;
614 else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
616 if (!dc->col.col) return;
619 else if (dc->render_op == _EVAS_RENDER_MUL)
621 if (dc->col.col == 0xffffffff) return;
624 else if (dc->render_op == _EVAS_RENDER_COPY)
626 else if (dc->render_op == _EVAS_RENDER_COPY_REL)
628 else if (dc->render_op == _EVAS_RENDER_MASK)
629 op = PictOpInReverse;
630 att.clip_mask = None;
631 XRenderChangePicture(rs->xinf->disp, rs->pic, CPClipMask, &att);
632 _xr_render_surface_clips_set(rs, dc, 0, 0, rs->w, rs->h);
636 XPointDouble poly[4];
638 double len, ddx, ddy;
642 len = sqrt((double)(dx * dx) + (double)(dy * dy));
643 ddx = (0.5 * dx) / len;
644 ddy = (0.5 * dy) / len;
645 if (ddx < 0) ddx = -0.5 - ddx;
646 else ddx = 0.5 - ddx;
647 if (ddy < 0) ddy = -0.5 - ddy;
648 else ddy = 0.5 - ddy;
649 poly[0].x = (x1 + ddx);
650 poly[0].y = (y1 - ddy);
651 poly[1].x = (x2 + ddx);
652 poly[1].y = (y2 - ddy);
653 poly[2].x = (x2 - ddx);
654 poly[2].y = (y2 + ddy);
655 poly[3].x = (x1 - ddx);
656 poly[3].y = (y1 + ddy);
658 a = (dc->col.col >> 24) & 0xff;
659 r = (dc->col.col >> 16) & 0xff;
660 g = (dc->col.col >> 8 ) & 0xff;
661 b = (dc->col.col ) & 0xff;
662 if ((rs->xinf->mul_r != r) || (rs->xinf->mul_g != g) ||
663 (rs->xinf->mul_b != b) || (rs->xinf->mul_a != a))
669 _xr_render_surface_solid_rectangle_set(rs->xinf->mul, r, g, b, a, 0, 0, 1, 1);
671 XRenderCompositeDoublePoly(rs->xinf->disp, op,
672 rs->xinf->mul->pic, rs->pic,
673 rs->xinf->fmt8, 0, 0, 0, 0,
674 poly, 4, EvenOddRule);
679 _xre_poly_draw(Xrender_Surface *rs, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points)
681 RGBA_Polygon_Point *pt;
685 XRenderPictureAttributes att;
688 if ((!rs) || (!dc)) return;
690 for (pt = points; pt; pt = (RGBA_Polygon_Point *)(((Evas_Object_List *)pt)->next)) num++;
693 if (dc->render_op == _EVAS_RENDER_BLEND)
695 if (!dc->col.col) return;
697 else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
699 if (!dc->col.col) return;
702 else if (dc->render_op == _EVAS_RENDER_MUL)
704 if (dc->col.col == 0xffffffff) return;
707 else if (dc->render_op == _EVAS_RENDER_COPY)
709 else if (dc->render_op == _EVAS_RENDER_COPY_REL)
711 else if (dc->render_op == _EVAS_RENDER_MASK)
712 op = PictOpInReverse;
713 a = (dc->col.col >> 24) & 0xff;
714 r = (dc->col.col >> 16) & 0xff;
715 g = (dc->col.col >> 8 ) & 0xff;
716 b = (dc->col.col ) & 0xff;
717 if ((rs->xinf->mul_r != r) || (rs->xinf->mul_g != g) ||
718 (rs->xinf->mul_b != b) || (rs->xinf->mul_a != a))
724 _xr_render_surface_solid_rectangle_set(rs->xinf->mul, r, g, b, a, 0, 0, 1, 1);
726 pts = malloc(num * sizeof(XPointDouble));
729 for (pt = points; pt; pt = (RGBA_Polygon_Point *)(((Evas_Object_List *)pt)->next))
738 att.clip_mask = None;
739 XRenderChangePicture(rs->xinf->disp, rs->pic, CPClipMask, &att);
741 _xr_render_surface_clips_set(rs, dc, 0, 0, rs->w, rs->h);
742 XRenderCompositeDoublePoly(rs->xinf->disp, op,
743 rs->xinf->mul->pic, rs->pic,
744 rs->xinf->fmt8, 0, 0, 0, 0,