text: Add language and text-direction to protocol
[profile/ivi/weston-ivi-shell.git] / src / pixman-renderer.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  * Copyright © 2013 Vasily Khoruzhick <anarsoul@gmail.com>
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that 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 the copyright holders not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission.  The copyright holders make
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #define _GNU_SOURCE
25
26 #include <errno.h>
27 #include <stdlib.h>
28
29 #include "pixman-renderer.h"
30
31 #include <linux/input.h>
32
33 struct pixman_output_state {
34         void *shadow_buffer;
35         pixman_image_t *shadow_image;
36         pixman_image_t *hw_buffer;
37 };
38
39 struct pixman_surface_state {
40         pixman_image_t *image;
41         struct weston_buffer_reference buffer_ref;
42 };
43
44 struct pixman_renderer {
45         struct weston_renderer base;
46         int repaint_debug;
47         pixman_image_t *debug_color;
48 };
49
50 static inline struct pixman_output_state *
51 get_output_state(struct weston_output *output)
52 {
53         return (struct pixman_output_state *)output->renderer_state;
54 }
55
56 static inline struct pixman_surface_state *
57 get_surface_state(struct weston_surface *surface)
58 {
59         return (struct pixman_surface_state *)surface->renderer_state;
60 }
61
62 static inline struct pixman_renderer *
63 get_renderer(struct weston_compositor *ec)
64 {
65         return (struct pixman_renderer *)ec->renderer;
66 }
67
68 static int
69 pixman_renderer_read_pixels(struct weston_output *output,
70                                pixman_format_code_t format, void *pixels,
71                                uint32_t x, uint32_t y,
72                                uint32_t width, uint32_t height)
73 {
74         struct pixman_output_state *po = get_output_state(output);
75         pixman_image_t *out_buf;
76         uint32_t cur_y;
77
78         if (!po->hw_buffer) {
79                 errno = ENODEV;
80                 return -1;
81         }
82
83         out_buf = pixman_image_create_bits(format,
84                 width,
85                 height,
86                 pixels,
87                 (PIXMAN_FORMAT_BPP(format) / 8) * width);
88
89         /* Caller expects vflipped image */
90         for (cur_y = y; cur_y < y + height; cur_y++) {
91                 pixman_image_composite32(PIXMAN_OP_SRC,
92                         po->hw_buffer, /* src */
93                         NULL /* mask */,
94                         out_buf, /* dest */
95                         x, cur_y, /* src_x, src_y */
96                         0, 0, /* mask_x, mask_y */
97                         0, height - (cur_y - y), /* dest_x, dest_y */
98                         width, /* width */
99                         1 /* height */);
100         }
101
102         pixman_image_unref(out_buf);
103
104         return 0;
105 }
106
107 static void
108 box_translate(pixman_box32_t *dst, const pixman_box32_t *src, int x, int y)
109 {
110         dst->x1 = src->x1 + x;
111         dst->x2 = src->x2 + x;
112         dst->y1 = src->y1 + y;
113         dst->y2 = src->y2 + y;
114 }
115
116 #define D2F(v) pixman_double_to_fixed((double)v)
117
118 static void
119 repaint_region_complex(struct weston_surface *es, struct weston_output *output,
120                 pixman_region32_t *region)
121 {
122         struct pixman_renderer *pr =
123                 (struct pixman_renderer *) output->compositor->renderer;
124         struct pixman_surface_state *ps = get_surface_state(es);
125         struct pixman_output_state *po = get_output_state(output);
126         int nrects, i;
127         pixman_box32_t *rects, rect;
128
129         /* Pixman supports only 2D transform matrix, but Weston uses 3D,
130          * so we're omitting Z coordinate here
131          */
132         pixman_transform_t transform = {{
133                 { D2F(es->transform.matrix.d[0]),
134                   D2F(es->transform.matrix.d[4]),
135                   D2F(es->transform.matrix.d[12]),
136                 },
137                 { D2F(es->transform.matrix.d[1]),
138                   D2F(es->transform.matrix.d[5]),
139                   D2F(es->transform.matrix.d[13]),
140                 },
141                 { D2F(es->transform.matrix.d[3]),
142                   D2F(es->transform.matrix.d[7]),
143                   D2F(es->transform.matrix.d[15]),
144                 }
145         }};
146
147         pixman_transform_invert(&transform, &transform);
148
149         pixman_image_set_transform(ps->image, &transform);
150         pixman_image_set_filter(ps->image, PIXMAN_FILTER_BILINEAR, NULL, 0);
151
152         rects = pixman_region32_rectangles(region, &nrects);
153         for (i = 0; i < nrects; i++) {
154                 box_translate(&rect, &rects[i], -output->x, -output->y);
155                 pixman_image_composite32(PIXMAN_OP_OVER,
156                         ps->image, /* src */
157                         NULL /* mask */,
158                         po->shadow_image, /* dest */
159                         rects[i].x1, rects[i].y1, /* src_x, src_y */
160                         0, 0, /* mask_x, mask_y */
161                         rect.x1, rect.y1, /* dst_x, dst_y */
162                         rect.x2 - rect.x1, /* width */
163                         rect.y2 - rect.y1 /* height */
164                         );
165
166                 if (!pr->repaint_debug)
167                         continue;
168
169                 pixman_image_composite32(PIXMAN_OP_OVER,
170                         pr->debug_color, /* src */
171                         NULL /* mask */,
172                         po->shadow_image, /* dest */
173                         0, 0, /* src_x, src_y */
174                         0, 0, /* mask_x, mask_y */
175                         rect.x1, rect.y1, /* dest_x, dest_y */
176                         rect.x2 - rect.x1, /* width */
177                         rect.y2 - rect.y1 /* height */);
178         }
179 }
180
181 static void
182 repaint_region_simple(struct weston_surface *es, struct weston_output *output,
183                 pixman_region32_t *region, pixman_region32_t *surf_region,
184                 pixman_op_t pixman_op)
185 {
186         struct pixman_renderer *pr =
187                 (struct pixman_renderer *) output->compositor->renderer;
188         struct pixman_surface_state *ps = get_surface_state(es);
189         struct pixman_output_state *po = get_output_state(output);
190         pixman_region32_t final_region;
191         pixman_box32_t *rects, rect;
192         int nrects, i, src_x, src_y;
193         float surface_x, surface_y;
194
195         /* The final region to be painted is the intersection of
196          * 'region' and 'surf_region'. However, 'region' is in the global
197          * coordinates, and 'surf_region' is in the surface-local
198          * coordinates
199          */
200         pixman_region32_init(&final_region);
201         pixman_region32_copy(&final_region, surf_region);
202
203         pixman_image_set_filter(ps->image, PIXMAN_FILTER_NEAREST, NULL, 0);
204         pixman_image_set_transform(ps->image, NULL);
205
206         if (!es->transform.enabled) {
207                 pixman_region32_translate(&final_region, es->geometry.x, es->geometry.y);
208         } else {
209                 weston_surface_to_global_float(es, 0, 0, &surface_x, &surface_y);
210                 pixman_region32_translate(&final_region, (int)surface_x, (int)surface_y);
211         }
212
213         /* That's what we need to paint */
214         pixman_region32_intersect(&final_region, &final_region, region);
215         rects = pixman_region32_rectangles(&final_region, &nrects);
216
217         for (i = 0; i < nrects; i++) {
218                 weston_surface_from_global(es, rects[i].x1, rects[i].y1, &src_x, &src_y);
219                 box_translate(&rect, &rects[i], -output->x, -output->y);
220                 pixman_image_composite32(pixman_op,
221                         ps->image, /* src */
222                         NULL /* mask */,
223                         po->shadow_image, /* dest */
224                         src_x, src_y, /* src_x, src_y */
225                         0, 0, /* mask_x, mask_y */
226                         rect.x1, rect.y1, /* dest_x, dest_y */
227                         rect.x2 - rect.x1, /* width */
228                         rect.y2 - rect.y1 /* height */);
229
230                 if (!pr->repaint_debug)
231                         continue;
232
233                 pixman_image_composite32(PIXMAN_OP_OVER,
234                         pr->debug_color, /* src */
235                         NULL /* mask */,
236                         po->shadow_image, /* dest */
237                         src_x, src_y, /* src_x, src_y */
238                         0, 0, /* mask_x, mask_y */
239                         rect.x1, rect.y1, /* dest_x, dest_y */
240                         rect.x2 - rect.x1, /* width */
241                         rect.y2 - rect.y1 /* height */);
242         }
243         pixman_region32_fini(&final_region);
244 }
245
246 static void
247 draw_surface(struct weston_surface *es, struct weston_output *output,
248              pixman_region32_t *damage) /* in global coordinates */
249 {
250         struct pixman_surface_state *ps = get_surface_state(es);
251         /* repaint bounding region in global coordinates: */
252         pixman_region32_t repaint;
253         /* non-opaque region in surface coordinates: */
254         pixman_region32_t surface_blend;
255
256         /* No buffer attached */
257         if (!ps->image)
258                 return;
259
260         pixman_region32_init(&repaint);
261         pixman_region32_intersect(&repaint,
262                                   &es->transform.boundingbox, damage);
263         pixman_region32_subtract(&repaint, &repaint, &es->clip);
264
265         if (!pixman_region32_not_empty(&repaint))
266                 goto out;
267
268         if (output->zoom.active) {
269                 weston_log("pixman renderer does not support zoom\n");
270                 goto out;
271         }
272
273         /* TODO: Implement repaint_region_complex() using pixman_composite_trapezoids() */
274         if (es->transform.enabled &&
275             es->transform.matrix.type != WESTON_MATRIX_TRANSFORM_TRANSLATE) {
276                 repaint_region_complex(es, output, &repaint);
277         } else {
278                 /* blended region is whole surface minus opaque region: */
279                 pixman_region32_init_rect(&surface_blend, 0, 0,
280                                           es->geometry.width, es->geometry.height);
281                 pixman_region32_subtract(&surface_blend, &surface_blend, &es->opaque);
282
283                 if (pixman_region32_not_empty(&es->opaque)) {
284                         repaint_region_simple(es, output, &repaint, &es->opaque, PIXMAN_OP_SRC);
285                 }
286
287                 if (pixman_region32_not_empty(&surface_blend)) {
288                         repaint_region_simple(es, output, &repaint, &surface_blend, PIXMAN_OP_OVER);
289                 }
290                 pixman_region32_fini(&surface_blend);
291         }
292
293
294 out:
295         pixman_region32_fini(&repaint);
296 }
297 static void
298 repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
299 {
300         struct weston_compositor *compositor = output->compositor;
301         struct weston_surface *surface;
302
303         wl_list_for_each_reverse(surface, &compositor->surface_list, link)
304                 if (surface->plane == &compositor->primary_plane)
305                         draw_surface(surface, output, damage);
306 }
307
308 static void
309 copy_to_hw_buffer(struct weston_output *output, pixman_region32_t *region)
310 {
311         struct pixman_output_state *po = get_output_state(output);
312         int nrects, i, width, height;
313         pixman_box32_t *rects;
314         pixman_box32_t b, rect;
315
316         width = pixman_image_get_width(po->shadow_image);
317         height = pixman_image_get_height(po->shadow_image);
318
319         rects = pixman_region32_rectangles(region, &nrects);
320         for (i = 0; i < nrects; i++) {
321                 box_translate(&rect, &rects[i], -output->x, -output->y);
322                 b = weston_transformed_rect(width, height,
323                                             output->transform, rect);
324
325                 pixman_image_composite32(PIXMAN_OP_SRC,
326                         po->shadow_image, /* src */
327                         NULL /* mask */,
328                         po->hw_buffer, /* dest */
329                         b.x1, b.y1, /* src_x, src_y */
330                         0, 0, /* mask_x, mask_y */
331                         b.x1, b.y1, /* dest_x, dest_y */
332                         b.x2 - b.x1, /* width */
333                         b.y2 - b.y1 /* height */);
334         }
335
336 }
337
338 static void
339 pixman_renderer_repaint_output(struct weston_output *output,
340                              pixman_region32_t *output_damage)
341 {
342         struct pixman_output_state *po = get_output_state(output);
343
344         if (!po->hw_buffer)
345                 return;
346
347         repaint_surfaces(output, output_damage);
348         copy_to_hw_buffer(output, output_damage);
349
350         pixman_region32_copy(&output->previous_damage, output_damage);
351         wl_signal_emit(&output->frame_signal, output);
352
353         /* Actual flip should be done by caller */
354 }
355
356 static void
357 pixman_renderer_flush_damage(struct weston_surface *surface)
358 {
359         /* No-op for pixman renderer */
360 }
361
362 static void
363 pixman_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
364 {
365         struct pixman_surface_state *ps = get_surface_state(es);
366         pixman_format_code_t pixman_format;
367
368         weston_buffer_reference(&ps->buffer_ref, buffer);
369
370         if (ps->image) {
371                 pixman_image_unref(ps->image);
372                 ps->image = NULL;
373         }
374
375         if (!buffer)
376                 return;
377
378         if (!wl_buffer_is_shm(buffer)) {
379                 weston_log("Pixman renderer supports only SHM buffers\n");
380                 weston_buffer_reference(&ps->buffer_ref, NULL);
381                 return;
382         }
383
384         switch (wl_shm_buffer_get_format(buffer)) {
385         case WL_SHM_FORMAT_XRGB8888:
386                 pixman_format = PIXMAN_x8r8g8b8;
387                 break;
388         case WL_SHM_FORMAT_ARGB8888:
389                 pixman_format = PIXMAN_a8r8g8b8;
390                 break;
391         default:
392                 weston_log("Unsupported SHM buffer format\n");
393                 weston_buffer_reference(&ps->buffer_ref, NULL);
394                 return;
395         break;
396         }
397         ps->image = pixman_image_create_bits(pixman_format,
398                 wl_shm_buffer_get_width(buffer),
399                 wl_shm_buffer_get_height(buffer),
400                 wl_shm_buffer_get_data(buffer),
401                 wl_shm_buffer_get_stride(buffer));
402 }
403
404 static int
405 pixman_renderer_create_surface(struct weston_surface *surface)
406 {
407         struct pixman_surface_state *ps;
408
409         ps = calloc(1, sizeof *ps);
410         if (!ps)
411                 return -1;
412
413         surface->renderer_state = ps;
414
415         return 0;
416 }
417
418 static void
419 pixman_renderer_surface_set_color(struct weston_surface *es,
420                  float red, float green, float blue, float alpha)
421 {
422         struct pixman_surface_state *ps = get_surface_state(es);
423         pixman_color_t color;
424
425         color.red = red * 0xffff;
426         color.green = green * 0xffff;
427         color.blue = blue * 0xffff;
428         color.alpha = alpha * 0xffff;
429         
430         if (ps->image) {
431                 pixman_image_unref(ps->image);
432                 ps->image = NULL;
433         }
434
435         ps->image = pixman_image_create_solid_fill(&color);
436 }
437
438 static void
439 pixman_renderer_destroy_surface(struct weston_surface *surface)
440 {
441         struct pixman_surface_state *ps = get_surface_state(surface);
442
443         if (ps->image) {
444                 pixman_image_unref(ps->image);
445                 ps->image = NULL;
446         }
447         weston_buffer_reference(&ps->buffer_ref, NULL);
448         free(ps);
449 }
450
451 static void
452 pixman_renderer_destroy(struct weston_compositor *ec)
453 {
454         free(ec->renderer);
455         ec->renderer = NULL;
456 }
457
458 static void
459 debug_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
460               void *data)
461 {
462         struct weston_compositor *ec = data;
463         struct pixman_renderer *pr = (struct pixman_renderer *) ec->renderer;
464
465         pr->repaint_debug ^= 1;
466
467         if (pr->repaint_debug) {
468                 pixman_color_t red = {
469                         0x3fff, 0x0000, 0x0000, 0x3fff
470                 };
471
472                 pr->debug_color = pixman_image_create_solid_fill(&red);
473         } else {
474                 pixman_image_unref(pr->debug_color);
475                 weston_compositor_damage_all(ec);
476         }
477 }
478
479 WL_EXPORT int
480 pixman_renderer_init(struct weston_compositor *ec)
481 {
482         struct pixman_renderer *renderer;
483
484         renderer = malloc(sizeof *renderer);
485         if (renderer == NULL)
486                 return -1;
487
488         renderer->repaint_debug = 0;
489         renderer->debug_color = NULL;
490         renderer->base.read_pixels = pixman_renderer_read_pixels;
491         renderer->base.repaint_output = pixman_renderer_repaint_output;
492         renderer->base.flush_damage = pixman_renderer_flush_damage;
493         renderer->base.attach = pixman_renderer_attach;
494         renderer->base.create_surface = pixman_renderer_create_surface;
495         renderer->base.surface_set_color = pixman_renderer_surface_set_color;
496         renderer->base.destroy_surface = pixman_renderer_destroy_surface;
497         renderer->base.destroy = pixman_renderer_destroy;
498         ec->renderer = &renderer->base;
499
500         weston_compositor_add_debug_binding(ec, KEY_R,
501                                             debug_binding, ec);
502         return 0;
503 }
504
505 WL_EXPORT void
506 pixman_renderer_output_set_buffer(struct weston_output *output, pixman_image_t *buffer)
507 {
508         struct pixman_output_state *po = get_output_state(output);
509
510         if (po->hw_buffer)
511                 pixman_image_unref(po->hw_buffer);
512         po->hw_buffer = buffer;
513
514         if (po->hw_buffer) {
515                 output->compositor->read_format = pixman_image_get_format(po->hw_buffer);
516                 pixman_image_ref(po->hw_buffer);
517         }
518 }
519
520 WL_EXPORT int
521 pixman_renderer_output_create(struct weston_output *output)
522 {
523         struct pixman_output_state *po = calloc(1, sizeof *po);
524         pixman_transform_t transform;
525         pixman_fixed_t fw, fh;
526         int w, h;
527         int rotated = 0;
528
529         if (!po)
530                 return -1;
531
532         /* set shadow image transformation */
533         w = output->current->width;
534         h = output->current->height;
535
536         fw = pixman_int_to_fixed(w);
537         fh = pixman_int_to_fixed(h);
538
539         pixman_transform_init_identity(&transform);
540
541         switch (output->transform) {
542         default:
543         case WL_OUTPUT_TRANSFORM_NORMAL:
544                 break;
545         case WL_OUTPUT_TRANSFORM_180:
546                 pixman_transform_rotate(&transform, NULL, -pixman_fixed_1, 0);
547                 pixman_transform_translate(NULL, &transform, fw, fh);
548                 break;
549         case WL_OUTPUT_TRANSFORM_270:
550                 rotated = 1;
551                 pixman_transform_rotate(&transform, NULL, 0, pixman_fixed_1);
552                 pixman_transform_translate(&transform, NULL, fh, 0);
553                 break;
554         case WL_OUTPUT_TRANSFORM_90:
555                 rotated = 1;
556                 pixman_transform_rotate(&transform, NULL, 0, -pixman_fixed_1);
557                 pixman_transform_translate(&transform, NULL, 0, fw);
558                 break;
559         }
560
561         if (rotated) {
562                 int tmp = w;
563                 w = h;
564                 h = tmp;
565         }
566
567         po->shadow_buffer = malloc(w * h * 4);
568
569         if (!po->shadow_buffer) {
570                 free(po);
571                 return -1;
572         }
573
574         po->shadow_image =
575                 pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
576                                          po->shadow_buffer, w * 4);
577
578         if (!po->shadow_image) {
579                 free(po->shadow_buffer);
580                 free(po);
581                 return -1;
582         }
583
584         pixman_image_set_transform(po->shadow_image, &transform);
585
586         output->renderer_state = po;
587
588         return 0;
589 }
590
591 WL_EXPORT void
592 pixman_renderer_output_destroy(struct weston_output *output)
593 {
594         struct pixman_output_state *po = get_output_state(output);
595
596         pixman_image_unref(po->shadow_image);
597
598         if (po->hw_buffer)
599                 pixman_image_unref(po->hw_buffer);
600
601         po->shadow_image = NULL;
602         po->hw_buffer = NULL;
603
604         free(po);
605 }