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