move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / xrender_xcb / evas_engine_xrender.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
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_Xcb.h"
9 #include <math.h>
10
11 /* As opposed to libXRender, we don't have
12  * XDoubleToFixed in XCB :/
13  */
14 #define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536))
15
16 /* this is a work around broken xrender - when/if this ever gets fixed in xorg
17  * we can comment this out and one day remove it - for now keep it until such
18  * a fix is spotted in the wild
19  */
20 #define BROKEN_XORG_XRENDER 1
21
22 static inline void
23 set_filter(Xcb_Render_Surface *s, int smooth)
24 {
25    const char *f = smooth ? "best": "nearest";
26
27    xcb_render_set_picture_filter (s->xcbinf->conn, s->pic, strlen (f), f, 0, NULL);
28 }
29
30 xcb_render_pictforminfo_t *
31 xcb_render_find_visual_format (xcb_connection_t *c, xcb_visualid_t visual)
32 {
33   xcb_render_query_pict_formats_cookie_t cookie;
34   xcb_render_query_pict_formats_reply_t *rep;
35   xcb_render_pictscreen_iterator_t       screen_iter;
36   xcb_render_pictformat_t                format = { 0 };
37
38   cookie = xcb_render_query_pict_formats (c);
39   rep = xcb_render_query_pict_formats_reply (c, cookie, NULL);
40   if (!rep)
41     return NULL;
42
43   screen_iter = xcb_render_query_pict_formats_screens_iterator (rep);
44   for (; screen_iter.rem; xcb_render_pictscreen_next (&screen_iter)) {
45     xcb_render_pictdepth_iterator_t depth_iter;
46
47     depth_iter = xcb_render_pictscreen_depths_iterator (screen_iter.data);
48     for (; depth_iter.rem; xcb_render_pictdepth_next (&depth_iter)) {
49       xcb_render_pictvisual_iterator_t visual_iter;
50
51       visual_iter = xcb_render_pictdepth_visuals_iterator (depth_iter.data);
52       for (; visual_iter.rem; xcb_render_pictvisual_next (&visual_iter)) {
53         if (visual == visual_iter.data->visual) {
54           format = visual_iter.data->format;
55         }
56       }
57     }
58   }
59   if (format != 0) {
60     xcb_render_pictforminfo_iterator_t forminfo_iter;
61
62     forminfo_iter = xcb_render_query_pict_formats_formats_iterator (rep);
63     for (; forminfo_iter.rem; xcb_render_pictforminfo_next (&forminfo_iter)) {
64       if (forminfo_iter.data->id == format) {
65         xcb_render_pictforminfo_t *forminfo;
66
67         forminfo = (xcb_render_pictforminfo_t *)malloc (sizeof (xcb_render_pictforminfo_t));
68         memcpy (forminfo, forminfo_iter.data, sizeof (xcb_render_pictforminfo_t));
69         free (rep);
70
71         return forminfo;
72       }
73     }
74   }
75   free (rep);
76
77   return NULL;
78 }
79
80 Xcb_Render_Surface *
81 _xr_render_surface_new(Xcb_Image_Info *xcbinf, int w, int h, xcb_render_pictforminfo_t *fmt, int alpha)
82 {
83    Xcb_Render_Surface *rs;
84    uint32_t            mask;
85    uint32_t            values[3];
86
87    if ((!xcbinf) || (!fmt) || (w < 1) || (h < 1)) return NULL;
88
89    rs = calloc(1, sizeof(Xcb_Render_Surface));
90    if (!rs) return NULL;
91    rs->xcbinf = xcbinf;
92    rs->w = w;
93    rs->h = h;
94    rs->fmt = (xcb_render_pictforminfo_t *)malloc (sizeof (xcb_render_pictforminfo_t));
95    if (!rs->fmt)
96      {
97         free(rs);
98         return NULL;
99      }
100    memcpy (rs->fmt, fmt, sizeof (xcb_render_pictforminfo_t));
101    rs->alpha = alpha;
102    rs->depth = fmt->depth;
103    rs->allocated = 1;
104    rs->draw = xcb_generate_id(xcbinf->conn);
105    xcb_create_pixmap(xcbinf->conn, fmt->depth, rs->draw, xcbinf->root, w, h);
106    if (rs->draw == 0)
107      {
108        free(rs->fmt);
109        free(rs);
110        return NULL;
111      }
112    rs->xcbinf->references++;
113    mask = XCB_RENDER_CP_REPEAT | XCB_RENDER_CP_DITHER | XCB_RENDER_CP_COMPONENT_ALPHA;
114    values[0] = 0;
115    values[1] = 0;
116    values[2] = 0;
117    rs->pic = xcb_generate_id(xcbinf->conn);
118    xcb_render_create_picture(xcbinf->conn, rs->pic, rs->draw, fmt->id, mask, values);
119    if (rs->pic == 0)
120      {
121        xcb_free_pixmap(rs->xcbinf->conn, rs->draw);
122        rs->xcbinf->references--;
123        free(rs->fmt);
124        free(rs);
125        return NULL;
126      }
127
128    return rs;
129 }
130
131 Xcb_Render_Surface *
132 _xr_render_surface_adopt(Xcb_Image_Info *xcbinf, xcb_drawable_t draw, int w, int h, int alpha)
133 {
134    Xcb_Render_Surface        *rs;
135    uint32_t                   mask;
136    uint32_t                   values[3];
137
138    if ((!xcbinf) || (draw == 0) || (w < 1) || (h < 1)) return NULL;
139    rs = calloc(1, sizeof(Xcb_Render_Surface));
140    if (!rs) return NULL;
141    rs->xcbinf = xcbinf;
142    rs->w = w;
143    rs->h = h;
144 /*    if (fmt->depth == xcbinf->fmt32->depth) */
145 /*      rs->fmt = xcbinf->fmt32; */
146 /*    else if (fmt->depth == xcbinf->fmt24->depth) */
147 /*      rs->fmt = xcbinf->fmt24; */
148 /*    else if (fmt->depth == xcbinf->fmt8->depth) */
149 /*      rs->fmt = xcbinf->fmt8; */
150 /*    else if (fmt->depth == xcbinf->fmt4->depth) */
151 /*      rs->fmt = xcbinf->fmt4; */
152 /*    else */
153 /*      rs->fmt = xcbinf->fmt1; */
154 /*    free(fmt); */
155
156    rs->fmt = xcb_render_find_visual_format(xcbinf->conn, xcbinf->vis);
157    if (!rs->fmt)
158      {
159         free(rs);
160         return NULL;
161      }
162    rs->alpha = alpha;
163    rs->depth = rs->fmt->depth;
164    if (rs->fmt->depth == 32) rs->alpha = 1;
165    rs->allocated = 0;
166    rs->draw = draw;
167    rs->xcbinf->references++;
168    mask = XCB_RENDER_CP_REPEAT | XCB_RENDER_CP_DITHER | XCB_RENDER_CP_COMPONENT_ALPHA;
169    values[0] = 0;
170    values[1] = 0;
171    values[2] = 0;
172    rs->pic = xcb_generate_id(xcbinf->conn);
173    xcb_render_create_picture(xcbinf->conn, rs->pic, rs->draw, rs->fmt->id, mask, values);
174    if (rs->pic == 0)
175      {
176        rs->xcbinf->references--;
177        free(rs->fmt);
178        free(rs);
179        return NULL;
180      }
181
182    return rs;
183 }
184
185 Xcb_Render_Surface *
186 _xr_render_surface_format_adopt(Xcb_Image_Info *xcbinf, xcb_drawable_t draw, int w, int h, xcb_render_pictforminfo_t *fmt, int alpha)
187 {
188    Xcb_Render_Surface *rs;
189    uint32_t            mask;
190    uint32_t            values[3];
191
192    if ((!xcbinf) || (!fmt) || (draw == 0) || (w < 1) || (h < 1)) return NULL;
193    rs = calloc(1, sizeof(Xcb_Render_Surface));
194    if (!rs) return NULL;
195    rs->xcbinf = xcbinf;
196    rs->w = w;
197    rs->h = h;
198    rs->fmt = (xcb_render_pictforminfo_t *)malloc (sizeof (xcb_render_pictforminfo_t));
199    memcpy (rs->fmt, fmt, sizeof (xcb_render_pictforminfo_t));
200    rs->alpha = alpha;
201    rs->depth = fmt->depth;
202    if (fmt->depth == 32) rs->alpha = 1;
203    rs->xcbinf->references++;
204    rs->allocated = 0;
205    rs->draw = draw;
206    mask = XCB_RENDER_CP_REPEAT | XCB_RENDER_CP_DITHER | XCB_RENDER_CP_COMPONENT_ALPHA;
207    values[0] = 0;
208    values[1] = 0;
209    values[2] = 0;
210    rs->pic = xcb_generate_id(xcbinf->conn);
211    xcb_render_create_picture(xcbinf->conn, rs->pic, rs->draw, fmt->id, mask, values);
212    if (rs->pic == 0)
213      {
214        rs->xcbinf->references--;
215        free(rs->fmt);
216        free(rs);
217        return NULL;
218      }
219
220    return rs;
221 }
222
223 void
224 _xr_render_surface_free(Xcb_Render_Surface *rs)
225 {
226    if (!rs) return;
227    if (rs->xcbinf)
228      {
229        if ((rs->allocated) && (rs->draw != 0))
230           xcb_free_pixmap(rs->xcbinf->conn, rs->draw);
231        if (rs->pic != 0)
232           xcb_render_free_picture(rs->xcbinf->conn, rs->pic);
233        _xr_image_info_free(rs->xcbinf);
234        rs->xcbinf = NULL;
235      }
236    free(rs->fmt);
237    free(rs);
238 }
239
240 void
241 _xr_render_surface_repeat_set(Xcb_Render_Surface *rs, int repeat)
242 {
243    uint32_t mask;
244    uint32_t value[1];
245
246    mask = XCB_RENDER_CP_REPEAT;
247    value[0] = repeat;
248    xcb_render_change_picture(rs->xcbinf->conn, rs->pic, mask, value);
249 }
250
251 void
252 _xr_render_surface_solid_rectangle_set(Xcb_Render_Surface *rs, int r, int g, int b, int a, int x, int y, int w, int h)
253 {
254    xcb_render_color_t col;
255    xcb_rectangle_t    rect;
256    int                aa;
257
258    aa = a + 1;
259    r = (r * aa) >> 8;
260    g = (g * aa) >> 8;
261    b = (b * aa) >> 8;
262    col.red   = (r << 8) | r;
263    col.green = (g << 8) | g;
264    col.blue  = (b << 8) | b;
265    col.alpha = (a << 8) | a;
266    rect.x = x;
267    rect.y = y;
268    rect.width = w;
269    rect.height = h;
270    xcb_render_fill_rectangles(rs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, rs->pic, col, 1, &rect);
271 }
272
273 void
274 _xr_render_surface_argb_pixels_fill(Xcb_Render_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h)
275 {
276    Xcb_Image_Image  *xcbim;
277    unsigned int     *p, *sp, *sple, *spe;
278    unsigned int      jump, sjump;
279    unsigned int      a, r, g, b, aa;
280
281    xcbim = _xr_image_new(rs->xcbinf, w, h, rs->depth);
282    if (!xcbim) return;
283    p = (unsigned int *)xcbim->data;
284    sp = ((unsigned int *)pixels) + (y * sw) + x;
285    jump = ((xcbim->line_bytes / 4) - w);
286    sjump = sw - w;
287    spe = sp + ((h - 1) * sw) + w;
288    if
289 #ifdef WORDS_BIGENDIAN
290      (xcbim->xcbim->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST)
291 #else
292      (xcbim->xcbim->image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
293 #endif
294      {
295         while (sp < spe)
296           {
297              sple = sp + w;
298              while (sp < sple)
299                {
300                   switch (a = A_VAL(sp))
301                   {
302                     case 0:
303                         *p = 0;
304                     break;
305                     case 255:
306                         *p = (B_VAL(sp) << 24) | (G_VAL(sp) << 16) | (R_VAL(sp) << 8) | 0xff;
307                     break;
308                     default:
309                         aa = a + 1;
310                         r = ((R_VAL(sp)) * aa) >> 8;
311                         g = ((G_VAL(sp)) * aa) >> 8;
312                         b = ((B_VAL(sp)) * aa) >> 8;
313                         *p = (b << 24) | (g << 16) | (r << 8) | a;
314                     break;
315                   }
316                   p++;
317                   sp++;
318                }
319              p += jump;
320              sp += sjump;
321           }
322      }
323    else
324      {
325         while (sp < spe)
326           {
327              sple = sp + w;
328              while (sp < sple)
329                {
330                   switch (a = (*sp & 0xff000000))
331                   {
332                     case 0:
333                         *p = 0;
334                     break;
335                     case 0xff000000:
336                         *p = *sp;
337                     break;
338                   default:
339                     aa = (a >> 24) + 1;
340                     *p = a + (((((*sp) >> 8) & 0xff) * aa) & 0xff00) +
341                       (((((*sp) & 0x00ff00ff) * aa) >> 8) & 0x00ff00ff);
342                     break;
343                   }
344                   p++;
345                   sp++;
346                }
347              p += jump;
348              sp += sjump;
349           }
350      }
351    _xr_image_put(xcbim, rs->draw, x, y, w, h);
352 }
353
354 void
355 _xr_render_surface_rgb_pixels_fill(Xcb_Render_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h)
356 {
357    Xcb_Image_Image *xcbim;
358    unsigned int    *p, *sp, *sple, *spe;
359    unsigned int     jump, sjump;
360
361    xcbim = _xr_image_new(rs->xcbinf, w, h, rs->depth);
362    if (!xcbim) return;
363    p = (unsigned int *)xcbim->data;
364    sp = ((unsigned int *)pixels) + (y * sw) + x;
365    jump = ((xcbim->line_bytes / 4) - w);
366    sjump = sw - w;
367    spe = sp + ((h - 1) * sw) + w;
368    if
369 #ifdef WORDS_BIGENDIAN
370      (xcbim->xcbim->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST)
371 #else
372      (xcbim->xcbim->image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
373 #endif
374      {
375         while (sp < spe)
376           {
377              sple = sp + w;
378              while (sp < sple)
379                {
380                   *p = ((B_VAL(sp)) << 24) | ((G_VAL(sp)) << 16) | ((R_VAL(sp)) << 8) | 0x000000ff;
381                   p++;
382                   sp++;
383                }
384              p += jump;
385              sp += sjump;
386           }
387      }
388    else
389      {
390         while (sp < spe)
391           {
392              sple = sp + w;
393              while (sp < sple)
394                {
395                   *p = 0xff000000 | *sp;
396                   p++;
397                   sp++;
398                }
399              p += jump;
400              sp += sjump;
401           }
402      }
403    _xr_image_put(xcbim, rs->draw, x, y, w, h);
404 }
405
406 void
407 _xr_render_surface_clips_set(Xcb_Render_Surface *rs, RGBA_Draw_Context *dc, int rx, int ry, int rw, int rh)
408 {
409    int              num = 0;
410    xcb_rectangle_t *rect = NULL;
411
412    if ((dc) && (dc->clip.use))
413      {
414         RECTS_CLIP_TO_RECT(rx, ry, rw, rh,
415                            dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
416      }
417    if ((!dc) || (!dc->cutout.rects))
418      {
419         rect = malloc(sizeof(xcb_rectangle_t));
420         if (!rect) return;
421         rect->x = rx;
422         rect->y = ry;
423         rect->width = rw;
424         rect->height = rh;
425         num = 1;
426      }
427    else
428      {
429         Cutout_Rects    *rects;
430         Cutout_Rect     *r;
431         int             i;
432
433         rects = evas_common_draw_context_apply_cutouts(dc);
434         num = rects->active;
435         rect = malloc(num * sizeof(xcb_rectangle_t));
436         if (!rect) return;
437         for (i = 0; i < num; i++)
438           {
439              r = rects->rects + i;
440              rect[i].x = r->x;
441              rect[i].y = r->y;
442              rect[i].width = r->w;
443              rect[i].height = r->h;
444           }
445         evas_common_draw_context_apply_clear_cutouts(rects);
446      }
447    if (!rect) return;
448    xcb_render_set_picture_clip_rectangles(rs->xcbinf->conn, rs->pic, 0, 0, num, rect);
449    free(rect);
450 }
451
452 /* initialized the transform to the identity */
453 static void
454 init_transform (xcb_render_transform_t *t)
455 {
456    t->matrix11 = t->matrix22 = t->matrix33 = DOUBLE_TO_FIXED(1);
457
458    t->matrix12 = t->matrix13 = t->matrix21 = t->matrix23 =
459    t->matrix31 = t->matrix32 = 0;
460 }
461
462 static void
463 set_transform_scale(xcb_render_transform_t *t,
464                     int                     sw,
465                     int                     sh,
466                     int                     w,
467                     int                     h)
468 {
469    if ((sw > 1) && (w > 1))
470      { sw--;  w--; }
471    if ((sh > 1) && (h > 1))
472      { sh--;  h--; }
473    t->matrix11 = DOUBLE_TO_FIXED((double)sw / (double)w);
474    t->matrix22 = DOUBLE_TO_FIXED((double)sh / (double)h);
475 }
476
477 // when color multiplier is used want: instead
478 // CA src IN mask SRC temp; non-CA temp OVER dst. - i think. need to check.
479 void
480 _xr_render_surface_composite(Xcb_Render_Surface *srs,
481                              Xcb_Render_Surface *drs,
482                              RGBA_Draw_Context  *dc,
483                              int                 sx,
484                              int                 sy,
485                              int                 sw,
486                              int                 sh,
487                              int                 x,
488                              int                 y,
489                              int                 w,
490                              int                 h,
491                              int                 smooth)
492 {
493    Xcb_Render_Surface    *trs = NULL;
494    xcb_render_transform_t xf;
495    xcb_render_picture_t   mask = XCB_NONE;
496    uint32_t               value_mask;
497    uint32_t               value_list[1];
498    int                    e, is_scaling;
499    xcb_render_pict_op_t   op;
500
501    if ((sw < 1) || (sh < 1) || (w < 1) || (h < 1)) return;
502
503    is_scaling = e = (sw != w) || (sh != h);
504
505    value_mask = XCB_RENDER_CP_CLIP_MASK;
506    value_list[0] = 0;
507    xcb_render_change_picture(srs->xcbinf->conn, srs->pic, value_mask, value_list);
508    xcb_render_change_picture(drs->xcbinf->conn, drs->pic, value_mask, value_list);
509
510    init_transform(&xf);
511
512    op = XCB_RENDER_PICT_OP_OVER;
513    if (dc->render_op == _EVAS_RENDER_BLEND)
514      {
515        if (!srs->alpha) op = XCB_RENDER_PICT_OP_SRC;
516      }
517    else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
518        op = XCB_RENDER_PICT_OP_ATOP;
519    else if (dc->render_op == _EVAS_RENDER_MUL)
520        op = XCB_RENDER_PICT_OP_IN;
521    else if (dc->render_op == _EVAS_RENDER_COPY)
522        op = XCB_RENDER_PICT_OP_SRC;
523    else if (dc->render_op == _EVAS_RENDER_COPY_REL)
524        op = XCB_RENDER_PICT_OP_IN;
525    else if (dc->render_op == _EVAS_RENDER_MASK)
526        op = XCB_RENDER_PICT_OP_IN_REVERSE;
527
528    if ((dc) && (dc->mul.use))
529      {
530        int r, g, b, a;
531
532        if ((op == XCB_RENDER_PICT_OP_OVER) && (!dc->mul.col)) return;
533        a = dc->mul.col >> 24;
534        r = (dc->mul.col >> 16) & 0xff;
535        g = (dc->mul.col >> 8) & 0xff;
536        b = dc->mul.col & 0xff;
537        if (dc->mul.col != 0xffffffff)
538          {
539             if ((srs->xcbinf->mul_r != r) || (srs->xcbinf->mul_g != g) ||
540                 (srs->xcbinf->mul_b != b) || (srs->xcbinf->mul_a != a))
541               {
542                  srs->xcbinf->mul_r = r;
543                  srs->xcbinf->mul_g = g;
544                  srs->xcbinf->mul_b = b;
545                  srs->xcbinf->mul_a = a;
546                  _xr_render_surface_solid_rectangle_set(srs->xcbinf->mul,
547                                                         r,
548                                                         g,
549                                                         b,
550                                                         a,
551                                                         0, 0, 1, 1);
552               }
553             mask = srs->xcbinf->mul->pic;
554             if (dc->mul.col == (a * 0x01010101))
555               {
556                  value_mask = XCB_RENDER_CP_COMPONENT_ALPHA;
557                  value_list[0] = 0;
558                  xcb_render_change_picture(srs->xcbinf->conn, mask, value_mask, value_list);
559               }
560             else
561               {
562                  if ((srs->alpha) || (a != 0xff))
563                    trs = _xr_render_surface_new(srs->xcbinf, sw + e, sh + e,
564                                                 srs->xcbinf->fmt32, 1);
565                  else
566                    trs = _xr_render_surface_new(srs->xcbinf, sw + e, sh + e,
567                                                 srs->fmt, srs->alpha);
568                  if (!trs) return;
569
570                  value_mask = XCB_RENDER_CP_COMPONENT_ALPHA;
571                  value_list[0] = 0;
572                  xcb_render_change_picture(srs->xcbinf->conn, mask, value_mask, value_list);
573                  xcb_render_set_picture_transform(trs->xcbinf->conn, srs->pic, xf);
574                  xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, mask, trs->pic,
575                                       sx, sy, 0, 0, 0, 0, sw, sh);
576                  /* fill right and bottom pixel so interpolation works right */
577                   if (e)
578                     {
579                        xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, mask, trs->pic,
580                                             sx + sw - 1, sy, 0, 0, sw, 0, 1, sh);
581                        xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, mask, trs->pic,
582                                             sx, sy + sh - 1, 0, 0, 0, sh, sw, 1);
583                        xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, mask, trs->pic,
584                                             sx + sw - 1, sy + sh - 1, 0, 0, sw, sh, 1, 1);
585                     }
586                   mask = XCB_NONE;
587               }
588          }
589      }
590
591    _xr_render_surface_clips_set(drs, dc, x, y, w, h);
592    if (trs)
593      {
594         set_filter(trs, smooth);
595
596         set_transform_scale(&xf, sw, sh, w, h);
597         xcb_render_set_picture_transform(trs->xcbinf->conn, trs->pic, xf);
598
599         value_mask = XCB_RENDER_CP_COMPONENT_ALPHA;
600         value_list[0] = 0;
601         if (dc->render_op == _EVAS_RENDER_MUL)
602            value_list[0] = 1;
603         xcb_render_change_picture(trs->xcbinf->conn, trs->pic, value_mask, value_list);
604
605         xcb_render_composite(trs->xcbinf->conn, op, trs->pic, mask, drs->pic,
606                              0, 0, 0, 0, x, y, w, h);
607         _xr_render_surface_free(trs);
608      }
609    else
610      {
611         if (srs->bordered && is_scaling)
612           {
613             trs = _xr_render_surface_new(srs->xcbinf, sw + 1, sh + 1,
614                                          srs->fmt, srs->alpha);
615             if (!trs) return;
616
617             value_mask = XCB_RENDER_CP_COMPONENT_ALPHA;
618             value_list[0] = 0;
619             xcb_render_change_picture(srs->xcbinf->conn, srs->pic, value_mask, value_list);
620             xcb_render_set_picture_transform(srs->xcbinf->conn, srs->pic, xf);
621             xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, XCB_NONE, trs->pic,
622                                  sx, sy, 0, 0, 0, 0, sw, sh);
623
624             xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, XCB_NONE, trs->pic,
625                                  sx + sw - 1, sy, 0, 0, sw, 0, 1, sh);
626             xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, XCB_NONE, trs->pic,
627                                  sx, sy + sh - 1, 0, 0, 0, sh, sw, 1);
628             xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, XCB_NONE, trs->pic,
629                                  sx + sw - 1, sy + sh - 1, 0, 0, sw, sh, 1, 1);
630
631             set_filter(trs, smooth);
632
633             set_transform_scale(&xf, sw, sh, w, h);
634             xcb_render_set_picture_transform(trs->xcbinf->conn, trs->pic, xf);
635
636             if (dc->render_op == _EVAS_RENDER_MUL)
637               {
638                  value_mask = XCB_RENDER_CP_COMPONENT_ALPHA;
639                  value_list[0] = 1;
640                  xcb_render_change_picture(trs->xcbinf->conn, trs->pic, value_mask, value_list);
641               }
642
643             xcb_render_composite(trs->xcbinf->conn, op, trs->pic, mask, drs->pic,
644                                  0, 0, 0, 0, x, y, w, h);
645             _xr_render_surface_free(trs);
646           }
647         else
648           {
649             set_filter(srs, smooth);
650
651             set_transform_scale(&xf, sw, sh, w, h);
652             xcb_render_set_picture_transform(srs->xcbinf->conn, srs->pic, xf);
653
654             value_mask = XCB_RENDER_CP_COMPONENT_ALPHA;
655             value_list[0] = 0;
656             if (dc->render_op == _EVAS_RENDER_MUL)
657                value_list[0] = 1;
658             xcb_render_change_picture(srs->xcbinf->conn, srs->pic, value_mask, value_list);
659
660             xcb_render_composite(srs->xcbinf->conn, op, srs->pic, mask, drs->pic,
661                              ((sx * w) + (sw / 2)) / sw, 
662                              ((sy * h) + (sh / 2)) / sh,
663                              0, 0, x, y, w, h);
664           }
665       }
666 }
667
668 void
669 _xr_render_surface_copy(Xcb_Render_Surface *srs, Xcb_Render_Surface *drs, int sx, int sy, int x, int y, int w, int h)
670 {
671    xcb_render_transform_t xf;
672    uint32_t               value_mask;
673    uint32_t               value_list[1];
674
675    if ((w < 1) || (h < 1) || (!srs) || (!drs)) return;
676
677    init_transform(&xf);
678 #ifdef BROKEN_XORG_XRENDER
679    /* FIXME: why do we need to change the identity matrix if the src surface
680     *        is 1 bit deep?
681     */
682    if (srs->depth == 1)
683      {
684         xf.matrix11 = xf.matrix22 = xf.matrix33 = 1;
685      }
686 #endif
687    xcb_render_set_picture_transform(srs->xcbinf->conn, srs->pic, xf);
688 /*    set_filter(srs, 0); */
689
690    value_mask = XCB_RENDER_CP_CLIP_MASK;
691    value_list[0] = 0;
692    xcb_render_change_picture(srs->xcbinf->conn, srs->pic, value_mask, value_list);
693    xcb_render_change_picture(drs->xcbinf->conn, drs->pic, value_mask, value_list);
694
695    xcb_render_composite(srs->xcbinf->conn, XCB_RENDER_PICT_OP_SRC, srs->pic, XCB_NONE, drs->pic,
696                         sx, sy, 0, 0, x, y, w, h);
697 }
698
699 void
700 _xr_render_surface_rectangle_draw(Xcb_Render_Surface *rs, RGBA_Draw_Context *dc, int x, int y, int w, int h)
701 {
702    xcb_render_color_t   col;
703    xcb_rectangle_t      rect;
704    uint32_t             value_mask;
705    uint32_t             value_list;
706    int                  r, g, b, a;
707    xcb_render_pict_op_t op;
708
709    if ((!rs) || (!dc)) return;
710    if ((w < 1) || (h < 1)) return;
711    a = dc->col.col >> 24;
712    r = (dc->col.col >> 16) & 0xff;
713    g = (dc->col.col >> 8 ) & 0xff;
714    b = (dc->col.col      ) & 0xff;
715    col.red   = (r << 8) | r;
716    col.green = (g << 8) | g;
717    col.blue  = (b << 8) | b;
718    col.alpha = (a << 8) | a;
719
720    op = XCB_RENDER_PICT_OP_SRC;
721    if (dc->render_op == _EVAS_RENDER_BLEND)
722      {
723         if (!dc->col.col) return;
724         if (a == 0xff) op = XCB_RENDER_PICT_OP_SRC;
725      }
726    else if (dc->render_op == _EVAS_RENDER_BLEND_REL)
727      {
728         if (!dc->col.col) return;
729         op = XCB_RENDER_PICT_OP_ATOP;
730      }
731    else if (dc->render_op == _EVAS_RENDER_MUL)
732      {
733         if (dc->col.col == 0xffffffff) return;
734         op = XCB_RENDER_PICT_OP_IN;
735      }
736    else if (dc->render_op == _EVAS_RENDER_COPY)
737         op = XCB_RENDER_PICT_OP_SRC;
738    else if (dc->render_op == _EVAS_RENDER_COPY_REL)
739         op = XCB_RENDER_PICT_OP_IN;
740    else if (dc->render_op == _EVAS_RENDER_MASK)
741         op = XCB_RENDER_PICT_OP_IN_REVERSE;
742
743    value_mask = XCB_RENDER_CP_CLIP_MASK;
744    value_list = 0;
745    xcb_render_change_picture(rs->xcbinf->conn, rs->pic, value_mask, &value_list);
746
747    _xr_render_surface_clips_set(rs, dc, x, y, w, h);
748    rect.x = x;
749    rect.y = y;
750    rect.width = w;
751    rect.height = h;
752    xcb_render_fill_rectangles(rs->xcbinf->conn, op, rs->pic, col, 1, &rect);
753 }
754
755 void
756 _xr_render_surface_line_draw(Xcb_Render_Surface *rs, RGBA_Draw_Context *dc, int x1, int y1, int x2, int y2)
757 {
758 /*    uint32_t         value_mask; */
759 /*    uint32_t         value_list[1]; */
760 /*    int            op; */
761
762 /*    if ((!rs) || (!dc)) return; */
763 /*    op = XCB_RENDER_PICT_OP_SRC; */
764 /*    value_mask = XCB_RENDER_CP_CLIP_MASK; */
765 /*    value_list[0] = 0; */
766 /*    xcb_render_change_picture(rs->xcbinf->conn, rs->pic, value_mask, value_list); */
767 /*    _xr_render_surface_clips_set(rs, dc, 0, 0, rs->w, rs->h); */
768
769 /*      { */
770 /*      int r, g, b, a; */
771 /*      XPointDouble poly[4]; */
772 /*      int dx, dy; */
773 /*      double len, ddx, ddy; */
774
775 /*      dx = x2 - x1; */
776 /*      dy = y2 - y1; */
777 /*      len = sqrt((double)(dx * dx) + (double)(dy * dy)); */
778 /*      ddx = (0.5 * dx) / len; */
779 /*      ddy = (0.5 * dy) / len; */
780 /*      poly[0].x =  (x1 + ddx); */
781 /*      poly[0].y =  (y1 - ddy); */
782 /*      poly[1].x =  (x2 + ddx); */
783 /*      poly[1].y =  (y2 - ddy); */
784 /*      poly[2].x =  (x2 - ddx); */
785 /*      poly[2].y =  (y2 + ddy); */
786 /*      poly[3].x =  (x1 - ddx); */
787 /*      poly[3].y =  (y1 + ddy); */
788
789 /*      a = (dc->col.col >> 24) & 0xff; */
790 /*      if (a == 0) return; */
791 /*      if (a < 0xff) op = XCB_RENDER_PICT_OP_OVER; */
792 /*      r = (dc->col.col >> 16) & 0xff; */
793 /*      g = (dc->col.col >> 8 ) & 0xff; */
794 /*      b = (dc->col.col      ) & 0xff; */
795 /*      if ((rs->xcbinf->mul_r != r) || (rs->xcbinf->mul_g != g) || */
796 /*          (rs->xcbinf->mul_b != b) || (rs->xcbinf->mul_a != a)) */
797 /*        { */
798 /*           rs->xcbinf->mul_r = r; */
799 /*           rs->xcbinf->mul_g = g; */
800 /*           rs->xcbinf->mul_b = b; */
801 /*           rs->xcbinf->mul_a = a; */
802 /*           _xr_render_surface_solid_rectangle_set(rs->xcbinf->mul, r, g, b, a, 0, 0, 1, 1); */
803 /*        } */
804 /*      XRenderCompositeDoublePoly(rs->xcbinf->conn, op, */
805 /*                                 rs->xcbinf->mul->pic, rs->pic,  */
806 /*                                 rs->xcbinf->fmt8, 0, 0, 0, 0, */
807 /*                                 poly, 4, EvenOddRule); */
808 /*      } */
809 }
810
811 void
812 _xre_poly_draw(Xcb_Render_Surface *rs, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points)
813 {
814 /*    RGBA_Polygon_Point *pt; */
815 /*    int i, num; */
816 /*    XPointDouble *pts; */
817 /*    int r, g, b, a; */
818 /*    uint32_t         value_mask; */
819 /*    uint32_t         value_list[1]; */
820 /*    int op; */
821
822 /*    if ((!rs) || (!dc)) return; */
823 /*    num = 0; */
824 /*    for (pt = points; pt; pt = (RGBA_Polygon_Point *)(((Evas_Object_List *)pt)->next)) num++; */
825 /*    if (num < 3) return; */
826 /*    a = (dc->col.col >> 24) & 0xff; */
827 /*    if (a == 0) return; */
828 /*    op = XCB_RENDER_PICT_OP_OVER; */
829 /*    r = (dc->col.col >> 16) & 0xff; */
830 /*    g = (dc->col.col >> 8 ) & 0xff; */
831 /*    b = (dc->col.col      ) & 0xff; */
832 /*    if ((rs->xcbinf->mul_r != r) || (rs->xcbinf->mul_g != g) || */
833 /*        (rs->xcbinf->mul_b != b) || (rs->xcbinf->mul_a != a)) */
834 /*      { */
835 /*      rs->xcbinf->mul_r = r; */
836 /*      rs->xcbinf->mul_g = g; */
837 /*      rs->xcbinf->mul_b = b; */
838 /*      rs->xcbinf->mul_a = a; */
839 /*      _xr_render_surface_solid_rectangle_set(rs->xcbinf->mul, r, g, b, a, 0, 0, 1, 1); */
840 /*      } */
841 /*    pts = malloc(num * sizeof(XPointDouble)); */
842 /*    if (!pts) return; */
843 /*    i = 0; */
844 /*    for (pt = points; pt; pt = (RGBA_Polygon_Point *)(((Evas_Object_List *)pt)->next)) */
845 /*      { */
846 /*      if (i < num) */
847 /*        { */
848 /*           pts[i].x = pt->x; */
849 /*           pts[i].y = pt->y; */
850 /*           i++; */
851 /*        } */
852 /*      } */
853 /*    value_mask = XCB_RENDER_CP_CLIP_MASK; */
854 /*    value_list[0] = 0; */
855 /*    xcb_render_change_picture(rs->xcbinf->conn, rs->pic, value_mask, value_list); */
856
857 /*    _xr_render_surface_clips_set(rs, dc, 0, 0, rs->w, rs->h); */
858 /*    XRenderCompositeDoublePoly(rs->xcbinf->conn, op, */
859 /*                            rs->xcbinf->mul->pic, rs->pic,  */
860 /*                            rs->xcbinf->fmt8, 0, 0, 0, 0, */
861 /*                            pts, num, Complex); */
862 /*    free(pts); */
863 }