• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2012 Intel Corporation
3  * Copyright © 2013 Vasily Khoruzhick <anarsoul@gmail.com>
4  * Copyright © 2015 Collabora, Ltd.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial
16  * portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #include "config.h"
29 
30 #include <errno.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <assert.h>
34 
35 #include "pixman-renderer.h"
36 #include "pixman-renderer-protected.h"
37 #include "shared/helpers.h"
38 
39 #include <linux/input.h>
40 
41 #include "tde-render-part.h"
42 
43 static int
44 pixman_renderer_create_surface(struct weston_surface *surface);
45 
46 struct pixman_output_state *
get_output_state(struct weston_output * output)47 get_output_state(struct weston_output *output)
48 {
49 	return (struct pixman_output_state *)output->renderer_state;
50 }
51 
52 static int
53 pixman_renderer_create_surface(struct weston_surface *surface);
54 
55 struct pixman_surface_state *
get_surface_state(struct weston_surface * surface)56 get_surface_state(struct weston_surface *surface)
57 {
58 	if (!surface->renderer_state)
59 		pixman_renderer_create_surface(surface);
60 
61 	return (struct pixman_surface_state *)surface->renderer_state;
62 }
63 
64 struct pixman_renderer *
get_renderer(struct weston_compositor * ec)65 get_renderer(struct weston_compositor *ec)
66 {
67 	return (struct pixman_renderer *)ec->renderer;
68 }
69 
70 static int
pixman_renderer_read_pixels(struct weston_output * output,pixman_format_code_t format,void * pixels,uint32_t x,uint32_t y,uint32_t width,uint32_t height)71 pixman_renderer_read_pixels(struct weston_output *output,
72 			       pixman_format_code_t format, void *pixels,
73 			       uint32_t x, uint32_t y,
74 			       uint32_t width, uint32_t height)
75 {
76 	struct pixman_output_state *po = get_output_state(output);
77 	pixman_image_t *out_buf;
78 
79 	if (!po->hw_buffer) {
80 		errno = ENODEV;
81 		return -1;
82 	}
83 
84 	out_buf = pixman_image_create_bits(format,
85 		width,
86 		height,
87 		pixels,
88 		(PIXMAN_FORMAT_BPP(format) / 8) * width);
89 
90 	pixman_image_composite32(PIXMAN_OP_SRC,
91 				 po->hw_buffer, /* src */
92 				 NULL /* mask */,
93 				 out_buf, /* dest */
94 				 x, y, /* src_x, src_y */
95 				 0, 0, /* mask_x, mask_y */
96 				 0, 0, /* dest_x, dest_y */
97 				 pixman_image_get_width (po->hw_buffer), /* width */
98 				 pixman_image_get_height (po->hw_buffer) /* height */);
99 
100 	pixman_image_unref(out_buf);
101 
102 	return 0;
103 }
104 
105 static void
region_global_to_output(struct weston_output * output,pixman_region32_t * region)106 region_global_to_output(struct weston_output *output, pixman_region32_t *region)
107 {
108 	if (output->zoom.active) {
109 		weston_matrix_transform_region(region, &output->matrix, region);
110 	} else {
111 		pixman_region32_translate(region, -output->x, -output->y);
112 		weston_transformed_region(output->width, output->height,
113 					  output->transform,
114 					  output->current_scale,
115 					  region, region);
116 	}
117 }
118 
119 #define D2F(v) pixman_double_to_fixed((double)v)
120 
121 static void
weston_matrix_to_pixman_transform(pixman_transform_t * pt,const struct weston_matrix * wm)122 weston_matrix_to_pixman_transform(pixman_transform_t *pt,
123 				  const struct weston_matrix *wm)
124 {
125 	/* Pixman supports only 2D transform matrix, but Weston uses 3D, *
126 	 * so we're omitting Z coordinate here. */
127 	pt->matrix[0][0] = pixman_double_to_fixed(wm->d[0]);
128 	pt->matrix[0][1] = pixman_double_to_fixed(wm->d[4]);
129 	pt->matrix[0][2] = pixman_double_to_fixed(wm->d[12]);
130 	pt->matrix[1][0] = pixman_double_to_fixed(wm->d[1]);
131 	pt->matrix[1][1] = pixman_double_to_fixed(wm->d[5]);
132 	pt->matrix[1][2] = pixman_double_to_fixed(wm->d[13]);
133 	pt->matrix[2][0] = pixman_double_to_fixed(wm->d[3]);
134 	pt->matrix[2][1] = pixman_double_to_fixed(wm->d[7]);
135 	pt->matrix[2][2] = pixman_double_to_fixed(wm->d[15]);
136 }
137 
138 static void
pixman_renderer_compute_transform(pixman_transform_t * transform_out,struct weston_view * ev,struct weston_output * output)139 pixman_renderer_compute_transform(pixman_transform_t *transform_out,
140 				  struct weston_view *ev,
141 				  struct weston_output *output)
142 {
143 	struct weston_matrix matrix;
144 
145 	/* Set up the source transformation based on the surface
146 	   position, the output position/transform/scale and the client
147 	   specified buffer transform/scale */
148 	matrix = output->inverse_matrix;
149 
150 	if (ev->transform.enabled) {
151 		weston_matrix_multiply(&matrix, &ev->transform.inverse);
152 	} else {
153 		weston_matrix_translate(&matrix,
154 					-ev->geometry.x, -ev->geometry.y, 0);
155 	}
156 
157 	weston_matrix_multiply(&matrix, &ev->surface->surface_to_buffer_matrix);
158 
159 	weston_matrix_to_pixman_transform(transform_out, &matrix);
160 }
161 
162 static bool
view_transformation_is_translation(struct weston_view * view)163 view_transformation_is_translation(struct weston_view *view)
164 {
165 	if (!view->transform.enabled)
166 		return true;
167 
168 	if (view->transform.matrix.type <= WESTON_MATRIX_TRANSFORM_TRANSLATE)
169 		return true;
170 
171 	return false;
172 }
173 
174 static void
region_intersect_only_translation(pixman_region32_t * result_global,pixman_region32_t * global,pixman_region32_t * surf,struct weston_view * view)175 region_intersect_only_translation(pixman_region32_t *result_global,
176 				  pixman_region32_t *global,
177 				  pixman_region32_t *surf,
178 				  struct weston_view *view)
179 {
180 	float view_x, view_y;
181 
182 	assert(view_transformation_is_translation(view));
183 
184 	/* Convert from surface to global coordinates */
185 	pixman_region32_copy(result_global, surf);
186 	weston_view_to_global_float(view, 0, 0, &view_x, &view_y);
187 	pixman_region32_translate(result_global, (int)view_x, (int)view_y);
188 
189 	pixman_region32_intersect(result_global, result_global, global);
190 }
191 
192 static void
composite_whole(pixman_op_t op,pixman_image_t * src,pixman_image_t * mask,pixman_image_t * dest,const pixman_transform_t * transform,pixman_filter_t filter)193 composite_whole(pixman_op_t op,
194 		pixman_image_t *src,
195 		pixman_image_t *mask,
196 		pixman_image_t *dest,
197 		const pixman_transform_t *transform,
198 		pixman_filter_t filter)
199 {
200 	int32_t dest_width;
201 	int32_t dest_height;
202 
203 	dest_width = pixman_image_get_width(dest);
204 	dest_height = pixman_image_get_height(dest);
205 
206 	pixman_image_set_transform(src, transform);
207 	pixman_image_set_filter(src, filter, NULL, 0);
208 
209 	/* bilinear filtering needs the equivalent of OpenGL CLAMP_TO_EDGE */
210 	if (filter == PIXMAN_FILTER_NEAREST)
211 		pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
212 	else
213 		pixman_image_set_repeat(src, PIXMAN_REPEAT_PAD);
214 
215 	pixman_image_composite32(op, src, mask, dest,
216 				 0, 0, /* src_x, src_y */
217 				 0, 0, /* mask_x, mask_y */
218 				 0, 0, /* dest_x, dest_y */
219 				 dest_width, dest_height);
220 }
221 
222 static void
composite_clipped(pixman_image_t * src,pixman_image_t * mask,pixman_image_t * dest,const pixman_transform_t * transform,pixman_filter_t filter,pixman_region32_t * src_clip)223 composite_clipped(pixman_image_t *src,
224 		  pixman_image_t *mask,
225 		  pixman_image_t *dest,
226 		  const pixman_transform_t *transform,
227 		  pixman_filter_t filter,
228 		  pixman_region32_t *src_clip)
229 {
230 	int n_box;
231 	pixman_box32_t *boxes;
232 	int32_t dest_width;
233 	int32_t dest_height;
234 	int src_stride;
235 	int bitspp;
236 	pixman_format_code_t src_format;
237 	void *src_data;
238 	int i;
239 
240 	/*
241 	 * Hardcoded to use PIXMAN_OP_OVER, because sampling outside of
242 	 * a Pixman image produces (0,0,0,0) instead of discarding the
243 	 * fragment.
244 	 *
245 	 * Also repeat mode must be PIXMAN_REPEAT_NONE (the default) to
246 	 * actually sample (0,0,0,0). This may cause issues for clients that
247 	 * expect OpenGL CLAMP_TO_EDGE sampling behavior on their buffer.
248 	 * Using temporary 'boximg' it is not possible to apply CLAMP_TO_EDGE
249 	 * correctly with bilinear filter. Maybe trapezoid rendering could be
250 	 * the answer instead of source clip?
251 	 */
252 
253 	dest_width = pixman_image_get_width(dest);
254 	dest_height = pixman_image_get_height(dest);
255 	src_format = pixman_image_get_format(src);
256 	src_stride = pixman_image_get_stride(src);
257 	bitspp = PIXMAN_FORMAT_BPP(src_format);
258 	src_data = pixman_image_get_data(src);
259 
260 	assert(src_format);
261 
262 	/* This would be massive overdraw, except when n_box is 1. */
263 	boxes = pixman_region32_rectangles(src_clip, &n_box);
264 	for (i = 0; i < n_box; i++) {
265 		uint8_t *ptr = src_data;
266 		pixman_image_t *boximg;
267 		pixman_transform_t adj = *transform;
268 
269 		ptr += boxes[i].y1 * src_stride;
270 		ptr += boxes[i].x1 * bitspp / 8;
271 		boximg = pixman_image_create_bits_no_clear(src_format,
272 					boxes[i].x2 - boxes[i].x1,
273 					boxes[i].y2 - boxes[i].y1,
274 					(uint32_t *)ptr, src_stride);
275 
276 		pixman_transform_translate(&adj, NULL,
277 					   pixman_int_to_fixed(-boxes[i].x1),
278 					   pixman_int_to_fixed(-boxes[i].y1));
279 		pixman_image_set_transform(boximg, &adj);
280 
281 		pixman_image_set_filter(boximg, filter, NULL, 0);
282 		pixman_image_composite32(PIXMAN_OP_OVER, boximg, mask, dest,
283 					 0, 0, /* src_x, src_y */
284 					 0, 0, /* mask_x, mask_y */
285 					 0, 0, /* dest_x, dest_y */
286 					 dest_width, dest_height);
287 
288 		pixman_image_unref(boximg);
289 	}
290 
291 	if (n_box > 1) {
292 		static bool warned = false;
293 
294 		if (!warned)
295 			weston_log("Pixman-renderer warning: %dx overdraw\n",
296 				   n_box);
297 		warned = true;
298 	}
299 }
300 
301 /** Paint an intersected region
302  *
303  * \param ev The view to be painted.
304  * \param output The output being painted.
305  * \param repaint_output The region to be painted in output coordinates.
306  * \param source_clip The region of the source image to use, in source image
307  *                    coordinates. If NULL, use the whole source image.
308  * \param pixman_op Compositing operator, either SRC or OVER.
309  */
310 static void
repaint_region(struct weston_view * ev,struct weston_output * output,pixman_region32_t * repaint_output,pixman_region32_t * source_clip,pixman_op_t pixman_op)311 repaint_region(struct weston_view *ev, struct weston_output *output,
312 	       pixman_region32_t *repaint_output,
313 	       pixman_region32_t *source_clip,
314 	       pixman_op_t pixman_op)
315 {
316 	struct pixman_renderer *pr =
317 		(struct pixman_renderer *) output->compositor->renderer;
318 	struct pixman_surface_state *ps = get_surface_state(ev->surface);
319 	struct pixman_output_state *po = get_output_state(output);
320 	struct weston_buffer_viewport *vp = &ev->surface->buffer_viewport;
321 	pixman_image_t *target_image;
322 	pixman_transform_t transform;
323 	pixman_filter_t filter;
324 	pixman_image_t *mask_image;
325 	pixman_color_t mask = { 0, };
326 
327 	if (po->shadow_image)
328 		target_image = po->shadow_image;
329 	else
330 		target_image = po->hw_buffer;
331 
332 	/* Clip rendering to the damaged output region */
333 	pixman_image_set_clip_region32(target_image, repaint_output);
334 
335 	pixman_renderer_compute_transform(&transform, ev, output);
336 
337 	if (ev->transform.enabled || output->current_scale != vp->buffer.scale)
338 		filter = PIXMAN_FILTER_BILINEAR;
339 	else
340 		filter = PIXMAN_FILTER_NEAREST;
341 
342 	if (ps->buffer_ref.buffer && ps->buffer_ref.buffer->shm_buffer)
343 		wl_shm_buffer_begin_access(ps->buffer_ref.buffer->shm_buffer);
344 
345 	if (ev->alpha < 1.0) {
346 		mask.alpha = 0xffff * ev->alpha;
347 		mask_image = pixman_image_create_solid_fill(&mask);
348 	} else {
349 		mask_image = NULL;
350 	}
351 
352 	if (source_clip)
353 		composite_clipped(ps->image, mask_image, target_image,
354 				  &transform, filter, source_clip);
355 	else
356 		composite_whole(pixman_op, ps->image, mask_image,
357 				target_image, &transform, filter);
358 
359 	if (mask_image)
360 		pixman_image_unref(mask_image);
361 
362 	if (ps->buffer_ref.buffer && ps->buffer_ref.buffer->shm_buffer)
363 		wl_shm_buffer_end_access(ps->buffer_ref.buffer->shm_buffer);
364 
365 	if (pr->repaint_debug)
366 		pixman_image_composite32(PIXMAN_OP_OVER,
367 					 pr->debug_color, /* src */
368 					 NULL /* mask */,
369 					 target_image, /* dest */
370 					 0, 0, /* src_x, src_y */
371 					 0, 0, /* mask_x, mask_y */
372 					 0, 0, /* dest_x, dest_y */
373 					 pixman_image_get_width (target_image), /* width */
374 					 pixman_image_get_height (target_image) /* height */);
375 
376 	pixman_image_set_clip_region32(target_image, NULL);
377 }
378 
379 static void
draw_view_translated(struct weston_view * view,struct weston_output * output,pixman_region32_t * repaint_global)380 draw_view_translated(struct weston_view *view, struct weston_output *output,
381 		     pixman_region32_t *repaint_global)
382 {
383 	struct weston_surface *surface = view->surface;
384 	/* non-opaque region in surface coordinates: */
385 	pixman_region32_t surface_blend;
386 	/* region to be painted in output coordinates: */
387 	pixman_region32_t repaint_output;
388 
389 	pixman_region32_init(&repaint_output);
390 
391 	/* Blended region is whole surface minus opaque region,
392 	 * unless surface alpha forces us to blend all.
393 	 */
394 	pixman_region32_init_rect(&surface_blend, 0, 0,
395 				  surface->width, surface->height);
396 
397 	if (!(view->alpha < 1.0)) {
398 		pixman_region32_subtract(&surface_blend, &surface_blend,
399 					 &surface->opaque);
400 
401 		if (pixman_region32_not_empty(&surface->opaque)) {
402 			region_intersect_only_translation(&repaint_output,
403 							  repaint_global,
404 							  &surface->opaque,
405 							  view);
406 			region_global_to_output(output, &repaint_output);
407 
408 			repaint_region(view, output, &repaint_output, NULL,
409 				       PIXMAN_OP_SRC);
410 		}
411 	}
412 
413 	if (pixman_region32_not_empty(&surface_blend)) {
414 		region_intersect_only_translation(&repaint_output,
415 						  repaint_global,
416 						  &surface_blend, view);
417 		region_global_to_output(output, &repaint_output);
418 
419 		// OHOS TDE
420 		if (tde_repaint_region_hook(view, output, &surface_blend, &repaint_output) != 0) {
421 			repaint_region(view, output, &repaint_output, NULL,
422 				       PIXMAN_OP_OVER);
423 		}
424 	}
425 
426 	pixman_region32_fini(&surface_blend);
427 	pixman_region32_fini(&repaint_output);
428 }
429 
430 static void
draw_view_source_clipped(struct weston_view * view,struct weston_output * output,pixman_region32_t * repaint_global)431 draw_view_source_clipped(struct weston_view *view,
432 			 struct weston_output *output,
433 			 pixman_region32_t *repaint_global)
434 {
435 	struct weston_surface *surface = view->surface;
436 	pixman_region32_t surf_region;
437 	pixman_region32_t buffer_region;
438 	pixman_region32_t repaint_output;
439 
440 	/* Do not bother separating the opaque region from non-opaque.
441 	 * Source clipping requires PIXMAN_OP_OVER in all cases, so painting
442 	 * opaque separately has no benefit.
443 	 */
444 
445 	pixman_region32_init_rect(&surf_region, 0, 0,
446 				  surface->width, surface->height);
447 	if (view->geometry.scissor_enabled)
448 		pixman_region32_intersect(&surf_region, &surf_region,
449 					  &view->geometry.scissor);
450 
451 	pixman_region32_init(&buffer_region);
452 	weston_surface_to_buffer_region(surface, &surf_region, &buffer_region);
453 
454 	pixman_region32_init(&repaint_output);
455 	pixman_region32_copy(&repaint_output, repaint_global);
456 	region_global_to_output(output, &repaint_output);
457 
458 	// OHOS TDE
459 	if (tde_repaint_region_hook(view, output, &buffer_region, &repaint_output) != 0) {
460 		repaint_region(view, output, &repaint_output, &buffer_region,
461 				PIXMAN_OP_OVER);
462 	}
463 
464 	pixman_region32_fini(&repaint_output);
465 	pixman_region32_fini(&buffer_region);
466 	pixman_region32_fini(&surf_region);
467 }
468 
469 static void
draw_view(struct weston_view * ev,struct weston_output * output,pixman_region32_t * damage)470 draw_view(struct weston_view *ev, struct weston_output *output,
471 	  pixman_region32_t *damage) /* in global coordinates */
472 {
473 	struct pixman_surface_state *ps = get_surface_state(ev->surface);
474 	/* repaint bounding region in global coordinates: */
475 	pixman_region32_t repaint;
476 
477 	/* No buffer attached */
478 	if (!ps->image)
479 		return;
480 
481 	pixman_region32_init(&repaint);
482 	pixman_region32_intersect(&repaint,
483 				  &ev->transform.boundingbox, damage);
484 	pixman_region32_subtract(&repaint, &repaint, &ev->clip);
485 
486 	if (!pixman_region32_not_empty(&repaint))
487 		goto out;
488 
489 	if (view_transformation_is_translation(ev)) {
490 		/* The simple case: The surface regions opaque, non-opaque,
491 		 * etc. are convertible to global coordinate space.
492 		 * There is no need to use a source clip region.
493 		 * It is possible to paint opaque region as PIXMAN_OP_SRC.
494 		 * Also the boundingbox is accurate rather than an
495 		 * approximation.
496 		 */
497 		draw_view_translated(ev, output, &repaint);
498 	} else {
499 		/* The complex case: the view transformation does not allow
500 		 * converting opaque etc. regions into global coordinate space.
501 		 * Therefore we need source clipping to avoid sampling from
502 		 * unwanted source image areas, unless the source image is
503 		 * to be used whole. Source clipping does not work with
504 		 * PIXMAN_OP_SRC.
505 		 */
506 		draw_view_source_clipped(ev, output, &repaint);
507 	}
508 
509 out:
510 	pixman_region32_fini(&repaint);
511 }
512 static void
repaint_surfaces(struct weston_output * output,pixman_region32_t * damage)513 repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
514 {
515 	struct weston_compositor *compositor = output->compositor;
516 	struct weston_view *view;
517 
518 	wl_list_for_each_reverse(view, &compositor->view_list, link)
519 		if (view->plane == &compositor->primary_plane)
520 			draw_view(view, output, damage);
521 	tde_repaint_finish_hook(output);
522 }
523 
524 static void
copy_to_hw_buffer(struct weston_output * output,pixman_region32_t * region)525 copy_to_hw_buffer(struct weston_output *output, pixman_region32_t *region)
526 {
527 	struct pixman_output_state *po = get_output_state(output);
528 	pixman_region32_t output_region;
529 
530 	pixman_region32_init(&output_region);
531 	pixman_region32_copy(&output_region, region);
532 
533 	region_global_to_output(output, &output_region);
534 
535 	pixman_image_set_clip_region32 (po->hw_buffer, &output_region);
536 	pixman_region32_fini(&output_region);
537 
538 	pixman_image_composite32(PIXMAN_OP_SRC,
539 				 po->shadow_image, /* src */
540 				 NULL /* mask */,
541 				 po->hw_buffer, /* dest */
542 				 0, 0, /* src_x, src_y */
543 				 0, 0, /* mask_x, mask_y */
544 				 0, 0, /* dest_x, dest_y */
545 				 pixman_image_get_width (po->hw_buffer), /* width */
546 				 pixman_image_get_height (po->hw_buffer) /* height */);
547 
548 	pixman_image_set_clip_region32 (po->hw_buffer, NULL);
549 }
550 
551 static void
pixman_renderer_repaint_output(struct weston_output * output,pixman_region32_t * output_damage)552 pixman_renderer_repaint_output(struct weston_output *output,
553 			       pixman_region32_t *output_damage)
554 {
555 	struct pixman_output_state *po = get_output_state(output);
556     // OHOS TDE
557     tde_output_state_init_hook(po);
558 	pixman_region32_t hw_damage;
559 
560 	if (!po->hw_buffer) {
561 		po->hw_extra_damage = NULL;
562 		return;
563 	}
564 
565 	pixman_region32_init(&hw_damage);
566 	if (po->hw_extra_damage) {
567 		pixman_region32_union(&hw_damage,
568 				      po->hw_extra_damage, output_damage);
569 		po->hw_extra_damage = NULL;
570 	} else {
571 		pixman_region32_copy(&hw_damage, output_damage);
572 	}
573 
574 	if (po->shadow_image) {
575 		repaint_surfaces(output, output_damage);
576 		copy_to_hw_buffer(output, &hw_damage);
577 	} else {
578 		repaint_surfaces(output, &hw_damage);
579 	}
580 	pixman_region32_fini(&hw_damage);
581 
582 	// wl_signal_emit(&output->frame_signal, output_damage); // OHOS ScreenShot: move to output->repaint
583 
584 	/* Actual flip should be done by caller */
585 }
586 
587 static void
pixman_renderer_flush_damage(struct weston_surface * surface)588 pixman_renderer_flush_damage(struct weston_surface *surface)
589 {
590 	/* No-op for pixman renderer */
591 }
592 
593 static void
buffer_state_handle_buffer_destroy(struct wl_listener * listener,void * data)594 buffer_state_handle_buffer_destroy(struct wl_listener *listener, void *data)
595 {
596 	struct pixman_surface_state *ps;
597 
598 	ps = container_of(listener, struct pixman_surface_state,
599 			  buffer_destroy_listener);
600 
601 	if (ps->image) {
602         tde_unref_image_hook(ps);
603 		pixman_image_unref(ps->image);
604 		ps->image = NULL;
605 	}
606 
607 	ps->buffer_destroy_listener.notify = NULL;
608 }
609 
610 static void
pixman_renderer_attach(struct weston_surface * es,struct weston_buffer * buffer)611 pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
612 {
613 	// OHOS TDE
614 	if (tde_render_attach_hook(es, buffer) == 0) {
615 		return;
616 	}
617 
618 	struct pixman_surface_state *ps = get_surface_state(es);
619 	struct wl_shm_buffer *shm_buffer;
620 	pixman_format_code_t pixman_format;
621 
622 	weston_buffer_reference(&ps->buffer_ref, buffer);
623 	weston_buffer_release_reference(&ps->buffer_release_ref,
624 					es->buffer_release_ref.buffer_release);
625 
626 	if (ps->buffer_destroy_listener.notify) {
627 		wl_list_remove(&ps->buffer_destroy_listener.link);
628 		ps->buffer_destroy_listener.notify = NULL;
629 	}
630 
631 	if (ps->image) {
632 		pixman_image_unref(ps->image);
633 		ps->image = NULL;
634 	}
635 
636 	if (!buffer)
637 		return;
638 
639 	shm_buffer = wl_shm_buffer_get(buffer->resource);
640 
641 	if (! shm_buffer) {
642 		weston_log("Pixman renderer supports only SHM buffers\n");
643 		weston_buffer_reference(&ps->buffer_ref, NULL);
644 		weston_buffer_release_reference(&ps->buffer_release_ref, NULL);
645 		return;
646 	}
647 
648 	switch (wl_shm_buffer_get_format(shm_buffer)) {
649 	case WL_SHM_FORMAT_XRGB8888:
650 		pixman_format = PIXMAN_x8r8g8b8;
651 		es->is_opaque = true;
652 		break;
653 	case WL_SHM_FORMAT_ARGB8888:
654 		pixman_format = PIXMAN_a8r8g8b8;
655 		es->is_opaque = false;
656 		break;
657 	case WL_SHM_FORMAT_RGB565:
658 		pixman_format = PIXMAN_r5g6b5;
659 		es->is_opaque = true;
660 		break;
661 	default:
662 		weston_log("Unsupported SHM buffer format 0x%x\n",
663 			wl_shm_buffer_get_format(shm_buffer));
664 		weston_buffer_reference(&ps->buffer_ref, NULL);
665 		weston_buffer_release_reference(&ps->buffer_release_ref, NULL);
666                 weston_buffer_send_server_error(buffer,
667 			"disconnecting due to unhandled buffer type");
668 		return;
669 	break;
670 	}
671 
672 	buffer->shm_buffer = shm_buffer;
673 	buffer->width = wl_shm_buffer_get_width(shm_buffer);
674 	buffer->height = wl_shm_buffer_get_height(shm_buffer);
675 
676 	ps->image = pixman_image_create_bits(pixman_format,
677 		buffer->width, buffer->height,
678 		wl_shm_buffer_get_data(shm_buffer),
679 		wl_shm_buffer_get_stride(shm_buffer));
680 
681 	ps->buffer_destroy_listener.notify =
682 		buffer_state_handle_buffer_destroy;
683 	wl_signal_add(&buffer->destroy_signal,
684 		      &ps->buffer_destroy_listener);
685 }
686 
687 static void
pixman_renderer_surface_state_destroy(struct pixman_surface_state * ps)688 pixman_renderer_surface_state_destroy(struct pixman_surface_state *ps)
689 {
690 	wl_list_remove(&ps->surface_destroy_listener.link);
691 	wl_list_remove(&ps->renderer_destroy_listener.link);
692 	if (ps->buffer_destroy_listener.notify) {
693 		wl_list_remove(&ps->buffer_destroy_listener.link);
694 		ps->buffer_destroy_listener.notify = NULL;
695 	}
696 
697 	ps->surface->renderer_state = NULL;
698 
699 	if (ps->image) {
700         tde_unref_image_hook(ps);
701 		pixman_image_unref(ps->image);
702 		ps->image = NULL;
703 	}
704 	weston_buffer_reference(&ps->buffer_ref, NULL);
705 	weston_buffer_release_reference(&ps->buffer_release_ref, NULL);
706     tde_surface_state_free_hook(ps);
707 	free(ps);
708 }
709 
710 static void
surface_state_handle_surface_destroy(struct wl_listener * listener,void * data)711 surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
712 {
713 	struct pixman_surface_state *ps;
714 
715 	ps = container_of(listener, struct pixman_surface_state,
716 			  surface_destroy_listener);
717 
718 	pixman_renderer_surface_state_destroy(ps);
719 }
720 
721 static void
surface_state_handle_renderer_destroy(struct wl_listener * listener,void * data)722 surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
723 {
724 	struct pixman_surface_state *ps;
725 
726 	ps = container_of(listener, struct pixman_surface_state,
727 			  renderer_destroy_listener);
728 
729 	pixman_renderer_surface_state_destroy(ps);
730 }
731 
732 int
pixman_renderer_create_surface(struct weston_surface * surface)733 pixman_renderer_create_surface(struct weston_surface *surface)
734 {
735 	struct pixman_surface_state *ps;
736 	struct pixman_renderer *pr = get_renderer(surface->compositor);
737 
738 	ps = zalloc(sizeof *ps);
739 	if (ps == NULL)
740 		return -1;
741 
742     tde_surface_state_alloc_hook(ps);
743 
744 	surface->renderer_state = ps;
745 
746 	ps->surface = surface;
747 
748 	ps->surface_destroy_listener.notify =
749 		surface_state_handle_surface_destroy;
750 	wl_signal_add(&surface->destroy_signal,
751 		      &ps->surface_destroy_listener);
752 
753 	ps->renderer_destroy_listener.notify =
754 		surface_state_handle_renderer_destroy;
755 	wl_signal_add(&pr->destroy_signal,
756 		      &ps->renderer_destroy_listener);
757 
758 	return 0;
759 }
760 
761 static void
pixman_renderer_surface_set_color(struct weston_surface * es,float red,float green,float blue,float alpha)762 pixman_renderer_surface_set_color(struct weston_surface *es,
763 		 float red, float green, float blue, float alpha)
764 {
765 	struct pixman_surface_state *ps = get_surface_state(es);
766 	pixman_color_t color;
767 
768 	color.red = red * 0xffff;
769 	color.green = green * 0xffff;
770 	color.blue = blue * 0xffff;
771 	color.alpha = alpha * 0xffff;
772 
773 	if (ps->image) {
774         tde_unref_image_hook(ps);
775 		pixman_image_unref(ps->image);
776 		ps->image = NULL;
777 	}
778 
779 	ps->image = pixman_image_create_solid_fill(&color);
780 }
781 
782 static void
pixman_renderer_destroy(struct weston_compositor * ec)783 pixman_renderer_destroy(struct weston_compositor *ec)
784 {
785 	struct pixman_renderer *pr = get_renderer(ec);
786 
787 	wl_signal_emit(&pr->destroy_signal, pr);
788 
789 	// OHOS remove debugger
790 	if (pr->debug_binding != NULL)
791 		weston_binding_destroy(pr->debug_binding);
792 
793 	// OHOS TDE
794 	tde_renderer_free_hook(pr);
795 	free(pr);
796 
797 	ec->renderer = NULL;
798 }
799 
800 static void
pixman_renderer_surface_get_content_size(struct weston_surface * surface,int * width,int * height)801 pixman_renderer_surface_get_content_size(struct weston_surface *surface,
802 					 int *width, int *height)
803 {
804 	struct pixman_surface_state *ps = get_surface_state(surface);
805 
806 	if (ps->image) {
807 		*width = pixman_image_get_width(ps->image);
808 		*height = pixman_image_get_height(ps->image);
809 	} else {
810 		*width = 0;
811 		*height = 0;
812 	}
813 }
814 
815 static int
pixman_renderer_surface_copy_content(struct weston_surface * surface,void * target,size_t size,int src_x,int src_y,int width,int height)816 pixman_renderer_surface_copy_content(struct weston_surface *surface,
817 				     void *target, size_t size,
818 				     int src_x, int src_y,
819 				     int width, int height)
820 {
821 	const pixman_format_code_t format = PIXMAN_a8b8g8r8;
822 	const size_t bytespp = 4; /* PIXMAN_a8b8g8r8 */
823 	struct pixman_surface_state *ps = get_surface_state(surface);
824 	pixman_image_t *out_buf;
825 
826 	if (!ps->image)
827 		return -1;
828 
829 	out_buf = pixman_image_create_bits(format, width, height,
830 					   target, width * bytespp);
831 
832 	pixman_image_set_transform(ps->image, NULL);
833 	pixman_image_composite32(PIXMAN_OP_SRC,
834 				 ps->image,    /* src */
835 				 NULL,         /* mask */
836 				 out_buf,      /* dest */
837 				 src_x, src_y, /* src_x, src_y */
838 				 0, 0,         /* mask_x, mask_y */
839 				 0, 0,         /* dest_x, dest_y */
840 				 width, height);
841 
842 	pixman_image_unref(out_buf);
843 
844 	return 0;
845 }
846 
847 // OHOS debugger
848 //static void
849 //debug_binding(struct weston_keyboard *keyboard, const struct timespec *time,
850 //	      uint32_t key, void *data)
851 //{
852 //	struct weston_compositor *ec = data;
853 //	struct pixman_renderer *pr = (struct pixman_renderer *) ec->renderer;
854 //
855 //	pr->repaint_debug ^= 1;
856 //
857 //	if (pr->repaint_debug) {
858 //		pixman_color_t red = {
859 //			0x3fff, 0x0000, 0x0000, 0x3fff
860 //		};
861 //
862 //		pr->debug_color = pixman_image_create_solid_fill(&red);
863 //	} else {
864 //		pixman_image_unref(pr->debug_color);
865 //		weston_compositor_damage_all(ec);
866 //	}
867 //}
868 
869 static bool pixman_renderer_import_dmabuf(struct weston_compositor *ec, struct linux_dmabuf_buffer *dmabuf);
870 static void pixman_renderer_query_dmabuf_formats(struct weston_compositor *wc, int **formats, int *num_formats);
871 static void pixman_renderer_query_dmabuf_modifiers(struct weston_compositor *wc, int format, uint64_t **modifiers, int *num_modifiers);
872 
873 WL_EXPORT int
pixman_renderer_init(struct weston_compositor * ec)874 pixman_renderer_init(struct weston_compositor *ec)
875 {
876 	struct pixman_renderer *renderer;
877 
878 	renderer = zalloc(sizeof *renderer);
879 	if (renderer == NULL)
880 		return -1;
881 
882 	// OHOS TDE
883     tde_renderer_alloc_hook(renderer, ec);
884 
885 	renderer->repaint_debug = 0;
886 	renderer->debug_color = NULL;
887 	renderer->base.read_pixels = pixman_renderer_read_pixels;
888 	renderer->base.repaint_output = pixman_renderer_repaint_output;
889 	renderer->base.flush_damage = pixman_renderer_flush_damage;
890 	renderer->base.attach = pixman_renderer_attach;
891 	renderer->base.surface_set_color = pixman_renderer_surface_set_color;
892 	renderer->base.destroy = pixman_renderer_destroy;
893 	renderer->base.surface_get_content_size =
894 		pixman_renderer_surface_get_content_size;
895 	renderer->base.surface_copy_content =
896 		pixman_renderer_surface_copy_content;
897 	ec->renderer = &renderer->base;
898 	ec->capabilities |= WESTON_CAP_ROTATION_ANY;
899 	ec->capabilities |= WESTON_CAP_VIEW_CLIP_MASK;
900 
901 	// OHOS remove debugger
902 	//renderer->debug_binding =
903 	//	weston_compositor_add_debug_binding(ec, KEY_R,
904 	//					    debug_binding, ec);
905 
906 	wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
907 
908 	wl_signal_init(&renderer->destroy_signal);
909 
910 	return 0;
911 }
912 
913 WL_EXPORT void
pixman_renderer_output_set_buffer(struct weston_output * output,pixman_image_t * buffer)914 pixman_renderer_output_set_buffer(struct weston_output *output,
915 				  pixman_image_t *buffer)
916 {
917 	struct pixman_output_state *po = get_output_state(output);
918 
919 	if (po->hw_buffer)
920 		pixman_image_unref(po->hw_buffer);
921 	po->hw_buffer = buffer;
922 
923 	if (po->hw_buffer) {
924 		output->compositor->read_format = pixman_image_get_format(po->hw_buffer);
925 		pixman_image_ref(po->hw_buffer);
926 	}
927 }
928 
929 WL_EXPORT void
pixman_renderer_output_set_hw_extra_damage(struct weston_output * output,pixman_region32_t * extra_damage)930 pixman_renderer_output_set_hw_extra_damage(struct weston_output *output,
931 					   pixman_region32_t *extra_damage)
932 {
933 	struct pixman_output_state *po = get_output_state(output);
934 
935 	po->hw_extra_damage = extra_damage;
936 }
937 
938 WL_EXPORT int
pixman_renderer_output_create(struct weston_output * output,const struct pixman_renderer_output_options * options)939 pixman_renderer_output_create(struct weston_output *output,
940 			      const struct pixman_renderer_output_options *options)
941 {
942 	struct pixman_output_state *po;
943 	int w, h;
944 
945 	po = zalloc(sizeof *po);
946 	if (po == NULL)
947 		return -1;
948 
949     // OHOS TDE
950     tde_output_state_alloc_hook(po);
951 
952 	if (options->use_shadow) {
953 		/* set shadow image transformation */
954 		w = output->current_mode->width;
955 		h = output->current_mode->height;
956 
957 		po->shadow_buffer = malloc(w * h * 4);
958 
959 		if (!po->shadow_buffer) {
960             tde_output_state_free_hook(po);
961 			free(po);
962 			return -1;
963 		}
964 
965 		po->shadow_image =
966 			pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
967 						 po->shadow_buffer, w * 4);
968 
969 		if (!po->shadow_image) {
970 			free(po->shadow_buffer);
971             tde_output_state_free_hook(po);
972 			free(po);
973 			return -1;
974 		}
975 	}
976 
977 	output->renderer_state = po;
978 
979 	return 0;
980 }
981 
982 WL_EXPORT void
pixman_renderer_output_destroy(struct weston_output * output)983 pixman_renderer_output_destroy(struct weston_output *output)
984 {
985 	struct pixman_output_state *po = get_output_state(output);
986 
987 	if (po->shadow_image)
988 		pixman_image_unref(po->shadow_image);
989 
990 	if (po->hw_buffer)
991 		pixman_image_unref(po->hw_buffer);
992 
993 	free(po->shadow_buffer);
994 
995 	po->shadow_buffer = NULL;
996 	po->shadow_image = NULL;
997 	po->hw_buffer = NULL;
998 
999     tde_output_state_free_hook(po);
1000 	free(po);
1001 }
1002