1From b53115faf91a004249451513f8da6c5b0434d5da Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Fri, 3 Jul 2020 14:43:49 +0800 4Subject: [PATCH 18/79] pixman-renderer: Support linux dmabuf 5 6NOTE: Only support contig dmabuf. 7 8Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 9--- 10 libweston/pixman-renderer.c | 258 +++++++++++++++++++++++++++++++++++- 11 1 file changed, 253 insertions(+), 5 deletions(-) 12 13diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c 14index d7182e7..d5c5422 100644 15--- a/libweston/pixman-renderer.c 16+++ b/libweston/pixman-renderer.c 17@@ -37,8 +37,15 @@ 18 #include "pixel-formats.h" 19 #include "shared/helpers.h" 20 21+#include <drm_fourcc.h> 22+#include <string.h> 23+#include <unistd.h> 24+#include <sys/mman.h> 25 #include <linux/input.h> 26 27+#include "linux-dmabuf.h" 28+#include "linux-dmabuf-unstable-v1-server-protocol.h" 29+ 30 struct pixman_output_state { 31 void *shadow_buffer; 32 pixman_image_t *shadow_image; 33@@ -66,6 +73,13 @@ struct pixman_renderer { 34 struct weston_binding *debug_binding; 35 36 struct wl_signal destroy_signal; 37+ 38+ struct weston_drm_format_array supported_formats; 39+}; 40+ 41+struct dmabuf_data { 42+ void *ptr; 43+ size_t size; 44 }; 45 46 static inline struct pixman_output_state * 47@@ -353,7 +367,7 @@ repaint_region(struct weston_view *ev, struct weston_output *output, 48 else 49 filter = PIXMAN_FILTER_NEAREST; 50 51- if (ps->buffer_ref.buffer) 52+ if (ps->buffer_ref.buffer && ps->buffer_ref.buffer->shm_buffer) 53 wl_shm_buffer_begin_access(ps->buffer_ref.buffer->shm_buffer); 54 55 if (ev->alpha < 1.0) { 56@@ -373,7 +387,7 @@ repaint_region(struct weston_view *ev, struct weston_output *output, 57 if (mask_image) 58 pixman_image_unref(mask_image); 59 60- if (ps->buffer_ref.buffer) 61+ if (ps->buffer_ref.buffer && ps->buffer_ref.buffer->shm_buffer) 62 wl_shm_buffer_end_access(ps->buffer_ref.buffer->shm_buffer); 63 64 if (pr->repaint_debug) 65@@ -622,11 +636,88 @@ buffer_state_handle_buffer_destroy(struct wl_listener *listener, void *data) 66 ps->buffer_destroy_listener.notify = NULL; 67 } 68 69+static void 70+pixman_renderer_attach_dmabuf(struct weston_surface *es, 71+ struct weston_buffer *buffer, 72+ struct linux_dmabuf_buffer *dmabuf) 73+{ 74+ struct pixman_surface_state *ps = get_surface_state(es); 75+ struct dmabuf_attributes *attributes = &dmabuf->attributes; 76+ struct dmabuf_data *data; 77+ pixman_format_code_t pixman_format; 78+ size_t vstride; 79+ 80+ data = linux_dmabuf_buffer_get_user_data(dmabuf); 81+ if (!data || !data->ptr) { 82+ weston_buffer_reference(&ps->buffer_ref, NULL); 83+ weston_buffer_release_reference(&ps->buffer_release_ref, 84+ NULL); 85+ return; 86+ } 87+ 88+ buffer->width = attributes->width; 89+ buffer->height = attributes->height; 90+ 91+ if (attributes->n_planes == 1) 92+ vstride = attributes->height; 93+ else 94+ vstride = (attributes->offset[1] - attributes->offset[0]) / 95+ attributes->stride[0]; 96+ 97+ switch (attributes->format) { 98+ case DRM_FORMAT_ARGB8888: 99+ pixman_format = PIXMAN_a8r8g8b8; 100+ break; 101+ case DRM_FORMAT_XRGB8888: 102+ pixman_format = PIXMAN_x8r8g8b8; 103+ break; 104+ case DRM_FORMAT_YUYV: 105+ pixman_format = PIXMAN_yuy2; 106+ break; 107+ case DRM_FORMAT_YVU420: 108+ pixman_format = PIXMAN_yv12; 109+ break; 110+#ifdef HAVE_PIXMAN_I420 111+ case DRM_FORMAT_YUV420: 112+ pixman_format = PIXMAN_i420; 113+ break; 114+#endif 115+#ifdef HAVE_PIXMAN_NV12 116+ case DRM_FORMAT_NV12: 117+ pixman_format = PIXMAN_nv12; 118+ break; 119+#endif 120+#ifdef HAVE_PIXMAN_NV16 121+ case DRM_FORMAT_NV16: 122+ pixman_format = PIXMAN_nv16; 123+ break; 124+#endif 125+ default: 126+ weston_log("Unsupported dmabuf format\n"); 127+ weston_buffer_reference(&ps->buffer_ref, NULL); 128+ weston_buffer_release_reference(&ps->buffer_release_ref, 129+ NULL); 130+ return; 131+ break; 132+ } 133+ 134+ ps->image = pixman_image_create_bits(pixman_format, 135+ buffer->width, vstride, 136+ data->ptr + attributes->offset[0], 137+ attributes->stride[0]); 138+ 139+ ps->buffer_destroy_listener.notify = 140+ buffer_state_handle_buffer_destroy; 141+ wl_signal_add(&buffer->destroy_signal, 142+ &ps->buffer_destroy_listener); 143+} 144+ 145 static void 146 pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) 147 { 148 struct pixman_surface_state *ps = get_surface_state(es); 149 struct wl_shm_buffer *shm_buffer; 150+ struct linux_dmabuf_buffer *dmabuf; 151 const struct pixel_format_info *pixel_info; 152 153 weston_buffer_reference(&ps->buffer_ref, buffer); 154@@ -649,9 +740,17 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) 155 shm_buffer = wl_shm_buffer_get(buffer->resource); 156 157 if (! shm_buffer) { 158- weston_log("Pixman renderer supports only SHM buffers\n"); 159- weston_buffer_reference(&ps->buffer_ref, NULL); 160- weston_buffer_release_reference(&ps->buffer_release_ref, NULL); 161+ if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource))) { 162+ pixman_renderer_attach_dmabuf(es, buffer, dmabuf); 163+ } else { 164+ weston_log("unhandled buffer type!\n"); 165+ weston_buffer_reference(&ps->buffer_ref, NULL); 166+ weston_buffer_release_reference(&ps->buffer_release_ref, 167+ NULL); 168+ weston_buffer_send_server_error(buffer, 169+ "disconnecting due to unhandled buffer type"); 170+ } 171+ 172 return; 173 } 174 175@@ -750,6 +849,9 @@ pixman_renderer_create_surface(struct weston_surface *surface) 176 wl_signal_add(&pr->destroy_signal, 177 &ps->renderer_destroy_listener); 178 179+ if (surface->buffer_ref.buffer) 180+ pixman_renderer_attach(surface, surface->buffer_ref.buffer); 181+ 182 return 0; 183 } 184 185@@ -780,6 +882,9 @@ pixman_renderer_destroy(struct weston_compositor *ec) 186 187 wl_signal_emit(&pr->destroy_signal, pr); 188 weston_binding_destroy(pr->debug_binding); 189+ 190+ weston_drm_format_array_fini(&pr->supported_formats); 191+ 192 free(pr); 193 194 ec->renderer = NULL; 195@@ -853,12 +958,141 @@ debug_binding(struct weston_keyboard *keyboard, const struct timespec *time, 196 } 197 } 198 199+static void 200+pixman_renderer_destroy_dmabuf(struct linux_dmabuf_buffer *dmabuf) 201+{ 202+ struct dmabuf_data *data = dmabuf->user_data; 203+ linux_dmabuf_buffer_set_user_data(dmabuf, NULL, NULL); 204+ 205+ if (data) { 206+ if (data->ptr) 207+ munmap(data->ptr, data->size); 208+ 209+ free(data); 210+ } 211+} 212+ 213+static bool 214+pixman_renderer_import_dmabuf(struct weston_compositor *ec, 215+ struct linux_dmabuf_buffer *dmabuf) 216+{ 217+ struct dmabuf_attributes *attributes = &dmabuf->attributes; 218+ struct dmabuf_data *data; 219+ size_t total_size, vstride0; 220+ int i; 221+ 222+ for (i = 0; i < attributes->n_planes; i++) { 223+ if (attributes->modifier[i] != DRM_FORMAT_MOD_INVALID) 224+ return false; 225+ } 226+ 227+ /* reject all flags we do not recognize or handle */ 228+ if (attributes->flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT) 229+ return false; 230+ 231+ if (attributes->n_planes < 0) 232+ return false; 233+ 234+ if (attributes->n_planes == 1) 235+ goto out; 236+ 237+ total_size = lseek(attributes->fd[0], 0, SEEK_END); 238+ vstride0 = (attributes->offset[1] - attributes->offset[0]) / 239+ attributes->stride[0]; 240+ 241+ for (i = 1; i < attributes->n_planes; i++) { 242+ size_t size = attributes->offset[i] - attributes->offset[i - 1]; 243+ size_t vstride = size / attributes->stride[i - 1]; 244+ 245+ /* not contig */ 246+ if (size <= 0 || vstride <= 0 || 247+ attributes->offset[i - 1] + size > total_size) 248+ return false; 249+ 250+ /* stride unmatched */ 251+ if ((vstride != vstride0 && vstride != vstride0 / 2) || 252+ (attributes->stride[i] != attributes->stride[0] && 253+ attributes->stride[i] != attributes->stride[0] / 2)) 254+ return false; 255+ } 256+ 257+out: 258+ /* Handle contig dma buffer */ 259+ 260+ data = zalloc(sizeof *data); 261+ if (!data) 262+ return false; 263+ 264+ linux_dmabuf_buffer_set_user_data(dmabuf, data, 265+ pixman_renderer_destroy_dmabuf); 266+ 267+ data->size = lseek(attributes->fd[0], 0, SEEK_END); 268+ 269+ data->ptr = mmap(NULL, data->size, PROT_READ, 270+ MAP_SHARED, attributes->fd[0], 0); 271+ return data->ptr != MAP_FAILED; 272+} 273+ 274+static const struct weston_drm_format_array * 275+pixman_renderer_get_supported_formats(struct weston_compositor *ec) 276+{ 277+ struct pixman_renderer *pr = get_renderer(ec); 278+ 279+ return &pr->supported_formats; 280+} 281+ 282+static int 283+populate_supported_formats(struct weston_compositor *ec, 284+ struct weston_drm_format_array *supported_formats) 285+{ 286+ struct weston_drm_format *fmt; 287+ int i, ret = 0; 288+ 289+ /* TODO: support more formats */ 290+ static const int formats[] = { 291+ DRM_FORMAT_ARGB8888, 292+ DRM_FORMAT_XRGB8888, 293+ DRM_FORMAT_RGBA8888, 294+ DRM_FORMAT_RGBX8888, 295+ DRM_FORMAT_ABGR8888, 296+ DRM_FORMAT_XBGR8888, 297+ DRM_FORMAT_BGRA8888, 298+ DRM_FORMAT_BGRX8888, 299+ DRM_FORMAT_YUYV, 300+ DRM_FORMAT_YVU420, 301+ DRM_FORMAT_YUV420, 302+ DRM_FORMAT_NV12, 303+ DRM_FORMAT_NV16, 304+ }; 305+ 306+ int num_formats = ARRAY_LENGTH(formats); 307+ 308+ for (i = 0; i < num_formats; i++) { 309+ fmt = weston_drm_format_array_add_format(supported_formats, 310+ formats[i]); 311+ if (!fmt) { 312+ ret = -1; 313+ goto out; 314+ } 315+ 316+ /* Always add DRM_FORMAT_MOD_INVALID, as EGL implementations 317+ * support implicit modifiers. */ 318+ ret = weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_INVALID); 319+ if (ret < 0) 320+ goto out; 321+ } 322+ 323+out: 324+ return ret; 325+} 326+ 327 WL_EXPORT int 328 pixman_renderer_init(struct weston_compositor *ec) 329 { 330 struct pixman_renderer *renderer; 331 const struct pixel_format_info *pixel_info, *info_argb8888, *info_xrgb8888; 332 unsigned int i, num_formats; 333+ int ret; 334 335 renderer = zalloc(sizeof *renderer); 336 if (renderer == NULL) 337@@ -880,6 +1114,15 @@ pixman_renderer_init(struct weston_compositor *ec) 338 ec->capabilities |= WESTON_CAP_ROTATION_ANY; 339 ec->capabilities |= WESTON_CAP_VIEW_CLIP_MASK; 340 341+ weston_drm_format_array_init(&renderer->supported_formats); 342+ 343+ ret = populate_supported_formats(ec, &renderer->supported_formats); 344+ if (ret < 0) { 345+ weston_drm_format_array_fini(&renderer->supported_formats); 346+ free(renderer); 347+ return -1; 348+ } 349+ 350 renderer->debug_binding = 351 weston_compositor_add_debug_binding(ec, KEY_R, 352 debug_binding, ec); 353@@ -902,6 +1145,11 @@ pixman_renderer_init(struct weston_compositor *ec) 354 355 wl_signal_init(&renderer->destroy_signal); 356 357+ renderer->base.import_dmabuf = pixman_renderer_import_dmabuf; 358+ 359+ renderer->base.get_supported_formats = 360+ pixman_renderer_get_supported_formats; 361+ 362 return 0; 363 } 364 365-- 3662.20.1 367 368