1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #include "tde-render-part.h"
27
28 #include <sstream>
29 #include <unistd.h>
30 #include <vector>
31
32 #include <display_gfx.h>
33 #include <idisplay_gralloc.h>
34
35 extern "C" {
36 #include <securec.h>
37 #include <stdbool.h>
38 #include <stddef.h>
39 #include <stdio.h>
40 #include <string.h>
41
42 #include <dlfcn.h>
43 #include <drm.h>
44 #include <drm/drm_fourcc.h>
45 #include <linux-dmabuf.h>
46 #include <linux-dmabuf-unstable-v1-server-protocol.h>
47 #include <linux-explicit-synchronization.h>
48 #include <sys/mman.h>
49
50 #include "libweston/weston-log.h"
51 #include "shared/helpers.h"
52 #include "pixman-renderer-protected.h"
53 #define virtual __keyword__virtual
54 #include <drm-internal.h>
55 #undef virtual
56 }
57
58 #include "libweston/trace.h"
59 DEFINE_LOG_LABEL("TDERenderer");
60
61 struct tde_image_t {
62 int32_t width;
63 int32_t height;
64 uint32_t format;
65 int n_planes; // 默认为1,引入plane是为了保证方案的通用性
66 __u64 phyaddr; // 物理地址
67 int fd[MAX_DMABUF_PLANES];
68 uint32_t offset[MAX_DMABUF_PLANES];
69 uint32_t stride[MAX_DMABUF_PLANES];
70 };
71
72 struct fill_rect_call {
73 ISurface surface;
74 IRect rect;
75 uint32_t color;
76 GfxOpt opt;
77 };
78
79 struct tde_output_state_t {
80 int32_t draw_count;
81 std::vector<struct fill_rect_call> calls;
82 };
83
84 struct tde_surface_state_t {
85 struct tde_image_t image;
86 struct linux_dmabuf_buffer *buffer;
87 struct tde_renderer_t *renderer;
88 };
89
90 struct tde_renderer_t {
91 GfxFuncs *gfx_funcs;
92 ::OHOS::HDI::Display::V1_0::IDisplayGralloc *display_gralloc;
93 void *module;
94 int use_tde;
95 int use_dmabuf;
96 };
97
98 struct drm_hisilicon_phy_addr {
99 uint64_t phyaddr; // return the phy addr
100 int fd; // dmabuf file descriptor
101 };
102
103 #define LIB_GFX_NAME "libdisplay_gfx.z.so"
104 #define LIB_GFX_FUNC_NAME_INIT "GfxInitialize"
105 #define LIB_GFX_FUNC_NAME_DEINIT "GfxUninitialize"
106 #define DRM_HISILICON_GEM_FD_TO_PHYADDR (0x1)
107 #define DRM_IOCTL_HISILICON_GEM_FD_TO_PHYADDR \
108 (DRM_IOWR(DRM_COMMAND_BASE + DRM_HISILICON_GEM_FD_TO_PHYADDR, \
109 struct drm_hisilicon_phy_addr))
110
dst_image_phyaddr(struct weston_output * wo)111 static uint64_t dst_image_phyaddr(struct weston_output *wo)
112 {
113 struct drm_output *output = to_drm_output(wo);
114 struct drm_backend *backend = to_drm_backend(wo->compositor);
115
116 int prime_fd;
117 drmPrimeHandleToFD(backend->drm.fd,
118 output->dumb[output->current_image]->handles[0],
119 DRM_CLOEXEC, &prime_fd);
120
121 struct drm_hisilicon_phy_addr args = { .fd = prime_fd };
122
123 ioctl(backend->drm.fd, DRM_IOCTL_HISILICON_GEM_FD_TO_PHYADDR, &args);
124 close(prime_fd);
125 return args.phyaddr;
126 }
127
src_surface_init(ISurface * surface,struct tde_image_t buffer)128 static void src_surface_init(ISurface *surface, struct tde_image_t buffer)
129 {
130 surface->width = buffer.width;
131 surface->height = buffer.height;
132 surface->phyAddr = buffer.phyaddr;
133 surface->stride = buffer.stride[0];
134 surface->enColorFmt = PIXEL_FMT_RGBA_8888;
135 surface->bAlphaExt1555 = true;
136 surface->bAlphaMax255 = true;
137 surface->alpha0 = 0XFF;
138 surface->alpha1 = 0XFF;
139 }
140
dst_surface_init(ISurface * surface,pixman_image_t * target_image,struct weston_output * output)141 static void dst_surface_init(ISurface *surface, pixman_image_t *target_image,
142 struct weston_output *output)
143 {
144 surface->width = pixman_image_get_width(target_image);
145 surface->height = pixman_image_get_height(target_image);
146 surface->phyAddr = dst_image_phyaddr(output);
147 surface->enColorFmt = PIXEL_FMT_BGRA_8888;
148 surface->stride = pixman_image_get_stride(target_image);
149 surface->bAlphaExt1555 = true;
150 surface->bAlphaMax255 = true;
151 surface->alpha0 = 0XFF;
152 surface->alpha1 = 0XFF;
153 }
154
155 #define min(a, b) ((a) < (b) ? (a) : (b))
156 #define max(a, b) ((a) > (b) ? (a) : (b))
157
158 typedef void(*weston_view_compute_global_region_func)(struct weston_view *view,
159 float x, float y, float *vx, float *vy);
160
161 static void
weston_view_compute_global_region(struct weston_view * view,pixman_region32_t * outr,pixman_region32_t * inr,weston_view_compute_global_region_func fn)162 weston_view_compute_global_region(struct weston_view *view,
163 pixman_region32_t *outr,
164 pixman_region32_t *inr,
165 weston_view_compute_global_region_func fn)
166 {
167 float min_x = HUGE_VALF, min_y = HUGE_VALF;
168 float max_x = -HUGE_VALF, max_y = -HUGE_VALF;
169 pixman_box32_t *inbox = pixman_region32_extents(inr);
170 int32_t vs[4][2] = {
171 { inbox->x1, inbox->y1 },
172 { inbox->x1, inbox->y2 },
173 { inbox->x2, inbox->y1 },
174 { inbox->x2, inbox->y2 },
175 };
176
177 if (inbox->x1 == inbox->x2 || inbox->y1 == inbox->y2) {
178 pixman_region32_init(outr);
179 return;
180 }
181
182 for (int i = 0; i < 4; i++) {
183 float x, y;
184 fn(view, vs[i][0], vs[i][1], &x, &y);
185 min_x = min(min_x, x);
186 max_x = max(max_x, x);
187 min_y = min(min_y, y);
188 max_y = max(max_y, y);
189 }
190
191 float int_x = floorf(min_x);
192 float int_y = floorf(min_y);
193 pixman_region32_init_rect(outr, int_x, int_y,
194 ceilf(max_x) - int_x, ceilf(max_y) - int_y);
195 }
196
197 #undef min
198 #undef max
199
200 static void
weston_view_to_global_region(struct weston_view * view,pixman_region32_t * outr,pixman_region32_t * inr)201 weston_view_to_global_region(struct weston_view *view,
202 pixman_region32_t *outr,
203 pixman_region32_t *inr)
204 {
205 weston_view_compute_global_region(view, outr, inr, weston_view_to_global_float);
206 }
207
208 static void
weston_view_from_global_region(struct weston_view * view,pixman_region32_t * outr,pixman_region32_t * inr)209 weston_view_from_global_region(struct weston_view *view,
210 pixman_region32_t *outr,
211 pixman_region32_t *inr)
212 {
213 weston_view_compute_global_region(view, outr, inr, weston_view_from_global_float);
214 }
215
dump_to_file(struct pixman_surface_state * ps)216 static void dump_to_file(struct pixman_surface_state *ps)
217 {
218 if (access("/data/tde_dump", F_OK) == -1) {
219 return;
220 }
221
222 struct timeval now;
223 gettimeofday(&now, nullptr);
224 constexpr int secToUsec = 1000 * 1000;
225 int64_t nowVal = (int64_t)now.tv_sec * secToUsec + (int64_t)now.tv_usec;
226
227 std::stringstream ss;
228 ss << "/data/tde-dumpimage-" << nowVal << ".raw";
229
230 auto fp = fopen(ss.str().c_str(), "a+");
231 if (fp == nullptr) {
232 return;
233 }
234
235 void *viraddr = pixman_image_get_data(ps->image);
236 int32_t size = pixman_image_get_stride(ps->image) * pixman_image_get_height(ps->image);
237 fwrite(viraddr, size, 1, fp);
238 fclose(fp);
239 }
240
tde_repaint_region(struct weston_view * ev,struct weston_output * output,pixman_region32_t * buffer_region,pixman_region32_t * output_damage)241 static int tde_repaint_region(struct weston_view *ev,
242 struct weston_output *output,
243 pixman_region32_t *buffer_region,
244 pixman_region32_t *output_damage)
245 {
246 struct pixman_renderer *renderer = (struct pixman_renderer *)output->compositor->renderer;
247 struct pixman_surface_state *surface = get_surface_state(ev->surface);
248 dump_to_file(surface);
249 struct pixman_output_state *output_state = get_output_state(output);
250 pixman_image_t *target_image = output_state->hw_buffer;
251 if (output_state->shadow_image) {
252 target_image = output_state->shadow_image;
253 }
254
255 GfxOpt opt = {
256 .enPixelAlpha = true,
257 .blendType = output_state->tde->draw_count ? BLEND_SRCOVER : BLEND_SRC,
258 .enableScale = true,
259 };
260
261 // region calc
262 pixman_region32_t global_repaint_region;
263 pixman_region32_t buffer_repaint_region;
264 {
265 pixman_region32_t surface_region;
266 pixman_region32_init_rect(&surface_region, 0, 0, ev->surface->width, ev->surface->height);
267
268 pixman_region32_t repaint_output;
269 pixman_region32_init(&repaint_output);
270 pixman_region32_copy(&repaint_output, output_damage);
271 if (output->zoom.active) {
272 weston_matrix_transform_region(&repaint_output, &output->matrix, &repaint_output);
273 } else {
274 pixman_region32_translate(&repaint_output, -output->x, -output->y);
275 weston_transformed_region(output->width, output->height,
276 static_cast<enum wl_output_transform>(output->transform),
277 output->current_scale,
278 &repaint_output, &repaint_output);
279 }
280
281 LOG_REGION(1, &surface_region);
282 LOG_REGION(2, &repaint_output);
283
284 struct weston_matrix matrix = output->inverse_matrix;
285 if (ev->transform.enabled) {
286 weston_matrix_multiply(&matrix, &ev->transform.inverse);
287 LOG_INFO("transform enabled");
288 } else {
289 weston_matrix_translate(&matrix,
290 -ev->geometry.x, -ev->geometry.y, 0);
291 LOG_INFO("transform disabled");
292 }
293 weston_matrix_multiply(&matrix, &ev->surface->surface_to_buffer_matrix);
294
295 if (matrix.d[0] == matrix.d[5] && matrix.d[0] == 0) {
296 if (matrix.d[4] > 0 && matrix.d[1] > 0) {
297 LOG_INFO("90 mirror");
298 opt.rotateType = ROTATE_90;
299 opt.mirrorType = MIRROR_LR;
300 } else if (matrix.d[4] < 0 && matrix.d[1] > 0) {
301 LOG_INFO("90");
302 opt.rotateType = ROTATE_90;
303 } else if (matrix.d[4] < 0 && matrix.d[1] < 0) {
304 LOG_INFO("270 mirror");
305 opt.rotateType = ROTATE_270;
306 opt.mirrorType = MIRROR_LR;
307 } else if (matrix.d[4] > 0 && matrix.d[1] < 0) {
308 LOG_INFO("270");
309 opt.rotateType = ROTATE_270;
310 }
311 } else {
312 if (matrix.d[0] > 0 && matrix.d[5] > 0) {
313 LOG_INFO("0");
314 opt.rotateType = ROTATE_NONE;
315 } else if (matrix.d[0] < 0 && matrix.d[5] < 0) {
316 LOG_INFO("180");
317 opt.rotateType = ROTATE_180;
318 } else if (matrix.d[0] < 0 && matrix.d[5] > 0) {
319 LOG_INFO("0 mirror");
320 opt.rotateType = ROTATE_NONE;
321 opt.mirrorType = MIRROR_LR;
322 } else if (matrix.d[0] > 0 && matrix.d[5] < 0) {
323 LOG_INFO("180 mirror");
324 opt.rotateType = ROTATE_180;
325 opt.mirrorType = MIRROR_LR;
326 }
327 }
328 LOG_INFO("%f %f %f %f", matrix.d[0], matrix.d[1], matrix.d[2], matrix.d[3]);
329 LOG_INFO("%f %f %f %f", matrix.d[4], matrix.d[5], matrix.d[6], matrix.d[7]);
330 LOG_INFO("%f %f %f %f", matrix.d[8], matrix.d[9], matrix.d[10], matrix.d[11]);
331 LOG_INFO("%f %f %f %f", matrix.d[12], matrix.d[13], matrix.d[14], matrix.d[15]);
332 LOG_INFO("%d %d", ev->surface->width, ev->surface->height);
333
334 weston_view_to_global_region(ev, &global_repaint_region, &surface_region);
335 pixman_region32_intersect(&global_repaint_region, &global_repaint_region, &repaint_output);
336 LOG_REGION(3, &global_repaint_region);
337
338 pixman_region32_t surface_repaint_region;
339 pixman_region32_init(&surface_repaint_region);
340 weston_view_from_global_region(ev, &surface_repaint_region, &global_repaint_region);
341 LOG_REGION(4, &surface_repaint_region);
342
343 pixman_region32_init(&buffer_repaint_region);
344 weston_surface_to_buffer_region(ev->surface, &surface_repaint_region, &buffer_repaint_region);
345 LOG_REGION(5, &buffer_repaint_region);
346 pixman_region32_fini(&surface_repaint_region);
347 pixman_region32_fini(&surface_region);
348 pixman_region32_fini(&repaint_output);
349 }
350 pixman_box32_t *global_box = pixman_region32_extents(&global_repaint_region);
351 IRect dstRect = {
352 .x = global_box->x1, .y = global_box->y1,
353 .w = global_box->x2 - global_box->x1,
354 .h = global_box->y2 - global_box->y1
355 };
356
357 pixman_box32_t *buffer_box = pixman_region32_extents(&buffer_repaint_region);
358 IRect srcRect = {
359 .x = buffer_box->x1, .y = buffer_box->y1,
360 .w = buffer_box->x2 - buffer_box->x1,
361 .h = buffer_box->y2 - buffer_box->y1
362 };
363 pixman_region32_fini(&global_repaint_region);
364 pixman_region32_fini(&buffer_repaint_region);
365
366 // tde
367 ISurface dstSurface = {};
368 dst_surface_init(&dstSurface, target_image, output);
369 ISurface srcSurface = {};
370 src_surface_init(&srcSurface, surface->tde->image);
371
372 if (ev->surface->type == WL_SURFACE_TYPE_VIDEO) {
373 opt.blendType = BLEND_SRC;
374 struct fill_rect_call call = {
375 .surface = dstSurface,
376 .rect = dstRect,
377 .color = 0x00000000,
378 .opt = opt,
379 };
380 output_state->tde->calls.push_back(call);
381 return 0;
382 } else {
383 if (renderer->tde->gfx_funcs->InitGfx() != 0) {
384 weston_log("tde_repaint_region InitGfx failed");
385 return -1;
386 }
387 output_state->tde->draw_count++;
388 renderer->tde->gfx_funcs->Blit(&srcSurface, &srcRect, &dstSurface, &dstRect, &opt);
389 weston_log("Blit dst(%{public}d, %{public}d) %{public}dx%{public}d",
390 dstRect.x, dstRect.y, dstRect.w, dstRect.h);
391 weston_log("Blit src(%{public}d, %{public}d) %{public}dx%{public}d",
392 srcRect.x, srcRect.y, srcRect.w, srcRect.h);
393 renderer->tde->gfx_funcs->DeinitGfx();
394 }
395 return 0;
396 }
397
tde_repaint_finish_hook(struct weston_output * output)398 void tde_repaint_finish_hook(struct weston_output *output)
399 {
400 struct pixman_renderer *renderer = (struct pixman_renderer *)output->compositor->renderer;
401 struct pixman_output_state *output_state = get_output_state(output);
402 for (auto &call : output_state->tde->calls) {
403 if (renderer->tde->gfx_funcs->InitGfx() != 0) {
404 weston_log("tde_repaint_finish_hook InitGfx failed");
405 continue;
406 }
407 renderer->tde->gfx_funcs->FillRect(&call.surface, &call.rect, call.color, &call.opt);
408 weston_log("FillRect (%{public}d, %{public}d) %{public}dx%{public}d",
409 call.rect.x, call.rect.y, call.rect.w, call.rect.h);
410 renderer->tde->gfx_funcs->DeinitGfx();
411 }
412 }
413
import_dmabuf(struct weston_compositor * ec,struct linux_dmabuf_buffer * dmabuf)414 static bool import_dmabuf(struct weston_compositor *ec,
415 struct linux_dmabuf_buffer *dmabuf)
416 {
417 return true;
418 }
419
query_dmabuf_formats(struct weston_compositor * wc,int ** formats,int * num_formats)420 static void query_dmabuf_formats(struct weston_compositor *wc,
421 int **formats, int *num_formats)
422 {
423 static const int fallback_formats[] = {
424 DRM_FORMAT_ARGB8888,
425 DRM_FORMAT_XRGB8888,
426 DRM_FORMAT_YUYV,
427 DRM_FORMAT_NV12,
428 DRM_FORMAT_YUV420,
429 DRM_FORMAT_YUV444,
430 };
431 int num = ARRAY_LENGTH(fallback_formats);
432 if (num > 0) {
433 *formats = (int *)calloc(num, sizeof(int));
434 }
435
436 memcpy_s(*formats, num * sizeof(int), fallback_formats, sizeof(fallback_formats));
437 *num_formats = num;
438 }
439
query_dmabuf_modifiers(struct weston_compositor * wc,int format,uint64_t ** modifiers,int * num_modifiers)440 static void query_dmabuf_modifiers(struct weston_compositor *wc, int format,
441 uint64_t **modifiers, int *num_modifiers)
442 {
443 *modifiers = NULL;
444 *num_modifiers = 0;
445 }
446
tde_render_gfx_init(struct tde_renderer_t * tde)447 static int32_t tde_render_gfx_init(struct tde_renderer_t *tde)
448 {
449 tde->module = dlopen(LIB_GFX_NAME, RTLD_NOW | RTLD_NOLOAD);
450 if (tde->module) {
451 weston_log("Module '%{public}s' already loaded\n", LIB_GFX_NAME);
452 } else {
453 weston_log("Loading module '%{public}s'\n", LIB_GFX_NAME);
454 tde->module = dlopen(LIB_GFX_NAME, RTLD_NOW);
455 if (!tde->module) {
456 weston_log("Failed to load module: %{public}s\n", dlerror());
457 return DISPLAY_FAILURE;
458 }
459 }
460
461 auto func = (int32_t(*)(GfxFuncs **funcs))dlsym(tde->module, LIB_GFX_FUNC_NAME_INIT);
462 if (!func) {
463 weston_log("Failed to lookup %{public}s function: %s\n", LIB_GFX_FUNC_NAME_INIT, dlerror());
464 dlclose(tde->module);
465 return DISPLAY_FAILURE;
466 }
467
468 return func(&tde->gfx_funcs);
469 }
470
tde_render_gfx_deinit(struct tde_renderer_t * tde)471 static int32_t tde_render_gfx_deinit(struct tde_renderer_t *tde)
472 {
473 int32_t ret = DISPLAY_FAILURE;
474 if (tde->module) {
475 auto func = (int32_t(*)(GfxFuncs *funcs))dlsym(tde->module, LIB_GFX_FUNC_NAME_DEINIT);
476 if (!func) {
477 weston_log("Failed to lookup %{public}s function: %s\n", LIB_GFX_FUNC_NAME_DEINIT, dlerror());
478 } else {
479 ret = func(tde->gfx_funcs);
480 }
481 dlclose(tde->module);
482 }
483 return ret;
484 }
485
tde_renderer_alloc_hook(struct pixman_renderer * renderer,struct weston_compositor * ec)486 int tde_renderer_alloc_hook(struct pixman_renderer *renderer, struct weston_compositor *ec)
487 {
488 renderer->tde = (struct tde_renderer_t *)zalloc(sizeof(*renderer->tde));
489 if (renderer->tde == NULL) {
490 return -1;
491 }
492
493 // Gfx Init
494 int ret = tde_render_gfx_init(renderer->tde);
495 if (ret == DISPLAY_SUCCESS && renderer->tde->gfx_funcs != NULL) {
496 renderer->tde->use_tde = 1;
497 weston_log("use tde");
498 } else {
499 renderer->tde->use_tde = 0;
500 weston_log("use no tde");
501 }
502
503 // Gralloc Init
504 renderer->tde->display_gralloc = ::OHOS::HDI::Display::V1_0::IDisplayGralloc::Get();
505 if (renderer->tde->display_gralloc != NULL) {
506 renderer->tde->use_dmabuf = 1;
507 weston_log("use dmabuf");
508 } else {
509 renderer->tde->use_tde = 0;
510 weston_log("use no tde");
511 renderer->tde->use_dmabuf = 0;
512 weston_log("use no dmabuf");
513 }
514
515 renderer->base.import_dmabuf = import_dmabuf;
516 renderer->base.query_dmabuf_formats = query_dmabuf_formats;
517 renderer->base.query_dmabuf_modifiers = query_dmabuf_modifiers;
518 return 0;
519 }
520
tde_renderer_free_hook(struct pixman_renderer * renderer)521 int tde_renderer_free_hook(struct pixman_renderer *renderer)
522 {
523 tde_render_gfx_deinit(renderer->tde);
524 delete renderer->tde->display_gralloc;
525 free(renderer->tde);
526 return 0;
527 }
528
tde_output_state_alloc_hook(struct pixman_output_state * state)529 int tde_output_state_alloc_hook(struct pixman_output_state *state)
530 {
531 state->tde = (struct tde_output_state_t *)zalloc(sizeof(*state->tde));
532 return 0;
533 }
534
tde_output_state_init_hook(struct pixman_output_state * state)535 int tde_output_state_init_hook(struct pixman_output_state *state)
536 {
537 state->tde->draw_count = 0;
538 state->tde->calls.clear();
539 return 0;
540 }
541
tde_output_state_free_hook(struct pixman_output_state * state)542 int tde_output_state_free_hook(struct pixman_output_state *state)
543 {
544 free(state->tde);
545 return 0;
546 }
547
tde_surface_state_alloc_hook(struct pixman_surface_state * state)548 int tde_surface_state_alloc_hook(struct pixman_surface_state *state)
549 {
550 state->tde = (struct tde_surface_state_t *)zalloc(sizeof(*state->tde));
551 return 0;
552 }
553
tde_surface_state_free_hook(struct pixman_surface_state * state)554 int tde_surface_state_free_hook(struct pixman_surface_state *state)
555 {
556 free(state->tde);
557 return 0;
558 }
559
buffer_state_handle_buffer_destroy(struct wl_listener * listener,void * data)560 static void buffer_state_handle_buffer_destroy(struct wl_listener *listener,
561 void *data)
562 {
563 struct pixman_surface_state *ps = container_of(listener,
564 struct pixman_surface_state, buffer_destroy_listener);
565 if (ps->image) {
566 tde_unref_image_hook(ps);
567
568 pixman_image_unref(ps->image);
569 ps->image = NULL;
570 }
571
572 ps->buffer_destroy_listener.notify = NULL;
573 }
574
tde_render_attach_hook(struct weston_surface * es,struct weston_buffer * buffer)575 int tde_render_attach_hook(struct weston_surface *es, struct weston_buffer *buffer)
576 {
577 if (buffer == NULL) {
578 return -1;
579 }
580
581 struct linux_dmabuf_buffer *dmabuf = linux_dmabuf_buffer_get(buffer->resource);
582 if (dmabuf == NULL) {
583 return -1;
584 }
585
586 struct pixman_surface_state *ps = get_surface_state(es);
587 ps->tde->renderer = get_renderer(es->compositor)->tde;
588 if (ps->tde->renderer->use_dmabuf != 1) {
589 return -1;
590 }
591
592 void *ptr = ps->tde->renderer->display_gralloc->Mmap(*dmabuf->attributes.buffer_handle);
593 if (ptr == NULL) {
594 return -1;
595 }
596
597 weston_buffer_reference(&ps->buffer_ref, buffer);
598 weston_buffer_release_reference(&ps->buffer_release_ref,
599 es->buffer_release_ref.buffer_release);
600
601 if (ps->buffer_destroy_listener.notify) {
602 wl_list_remove(&ps->buffer_destroy_listener.link);
603 ps->buffer_destroy_listener.notify = NULL;
604 }
605
606 if (ps->image) {
607 tde_unref_image_hook(ps);
608
609 pixman_image_unref(ps->image);
610 ps->image = NULL;
611 }
612
613 pixman_format_code_t pixman_format = PIXMAN_a8b8g8r8;
614 buffer->legacy_buffer = NULL;
615 buffer->width = dmabuf->attributes.width;
616 buffer->height = dmabuf->attributes.height;
617
618 ps->tde->image.width = dmabuf->attributes.width;
619 ps->tde->image.height = dmabuf->attributes.height;
620 ps->tde->image.stride[0] = dmabuf->attributes.stride[0];
621 ps->tde->image.format = dmabuf->attributes.format;
622 ps->tde->image.fd[0] = dmabuf->attributes.fd[0];
623 ps->tde->buffer = dmabuf;
624
625 ps->tde->image.phyaddr = dmabuf->attributes.buffer_handle->phyAddr;
626 if (ps->tde->image.phyaddr == 0) {
627 weston_log("tde-renderer: phyAddr is invalid.\n");
628 }
629
630 ps->image = pixman_image_create_bits(pixman_format,
631 buffer->width, buffer->height,
632 (uint32_t *)dmabuf->attributes.buffer_handle->virAddr,
633 dmabuf->attributes.stride[0]);
634
635 ps->buffer_destroy_listener.notify = buffer_state_handle_buffer_destroy;
636 wl_signal_add(&buffer->destroy_signal, &ps->buffer_destroy_listener);
637 return 0;
638 }
639
tde_repaint_region_hook(struct weston_view * ev,struct weston_output * output,pixman_region32_t * buffer_region,pixman_region32_t * repaint_output)640 int tde_repaint_region_hook(struct weston_view *ev, struct weston_output *output,
641 pixman_region32_t *buffer_region, pixman_region32_t *repaint_output)
642 {
643 struct pixman_renderer *renderer = (struct pixman_renderer *)output->compositor->renderer;
644 if (!renderer->tde->use_tde) {
645 return -1;
646 }
647
648 return tde_repaint_region(ev, output, buffer_region, repaint_output);
649 }
650
tde_unref_image_hook(struct pixman_surface_state * ps)651 int tde_unref_image_hook(struct pixman_surface_state *ps)
652 {
653 if (ps == NULL) {
654 return 0;
655 }
656
657 if (ps->tde == NULL) {
658 return 0;
659 }
660
661 struct tde_surface_state_t *tss = ps->tde;
662 if (tss->renderer == NULL || tss->buffer == NULL) {
663 return 0;
664 }
665
666 BufferHandle *bh = tss->buffer->attributes.buffer_handle;
667 if (bh == NULL || bh->virAddr == NULL) {
668 return 0;
669 }
670
671 if (tss->renderer->use_dmabuf == 1) {
672 tss->renderer->display_gralloc->Unmap(*bh);
673 }
674 return 0;
675 }
676