• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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