From d7fc524f534a9b0a3cd8c8056ad54025291c598a Mon Sep 17 00:00:00 2001 From: Taekyun Kim Date: Wed, 11 Nov 2015 19:53:27 +0900 Subject: [PATCH] drm: Check format and buffer scale when assigning HW planes Change-Id: Ie514243f4db2c7db77f66f040fbdc53dd551cc0f --- src/lib/drm/drm-buffer.c | 51 ++++--------- src/lib/drm/drm-internal.h | 3 +- src/lib/drm/drm-output.c | 151 ++++++++++++++++++++++++++++++------- src/lib/pepper/output.c | 2 +- src/lib/pepper/pepper.h | 2 +- 5 files changed, 145 insertions(+), 64 deletions(-) diff --git a/src/lib/drm/drm-buffer.c b/src/lib/drm/drm-buffer.c index bf97c0b..ba6a0a6 100644 --- a/src/lib/drm/drm-buffer.c +++ b/src/lib/drm/drm-buffer.c @@ -30,15 +30,6 @@ #include #include -static void -destroy_buffer_gbm(struct gbm_bo *bo, void *data) -{ - drm_buffer_t *buffer = data; - - drmModeRmFB(buffer->drm->fd, buffer->id); - free(buffer); -} - drm_buffer_t * drm_buffer_create_dumb(pepper_drm_t *drm, uint32_t w, uint32_t h) { @@ -135,6 +126,9 @@ init_buffer_gbm(drm_buffer_t *buffer, pepper_drm_t *drm, struct gbm_bo *bo, uint PEPPER_CHECK(ret, return PEPPER_FALSE, "drmModeAddFB() failed.\n"); } + buffer->bo = bo; + gbm_bo_set_user_data(bo, buffer, NULL); + return PEPPER_TRUE; } @@ -155,7 +149,6 @@ drm_buffer_create_gbm(pepper_drm_t *drm, struct gbm_surface *surface, struct gbm buffer->type = DRM_BUFFER_TYPE_GBM; buffer->surface = surface; buffer->bo = bo; - gbm_bo_set_user_data(bo, buffer, destroy_buffer_gbm); return buffer; } @@ -169,41 +162,29 @@ handle_client_buffer_destroy(pepper_event_listener_t *listener, pepper_object_t } drm_buffer_t * -drm_buffer_create_pepper(pepper_drm_t *drm, pepper_buffer_t *pb) +drm_buffer_create_client(pepper_drm_t *drm, + struct gbm_bo *bo, pepper_buffer_t *client_buffer, uint32_t format) { - struct gbm_bo *bo = NULL; - drm_buffer_t *buffer = NULL; - struct wl_resource *resource = pepper_buffer_get_resource(pb); - - bo = gbm_bo_import(drm->gbm_device, GBM_BO_IMPORT_WL_BUFFER, resource, GBM_BO_USE_SCANOUT); - if (!bo) - goto error; + drm_buffer_t *buffer; buffer = calloc(1, sizeof(drm_buffer_t)); - if (!buffer) - goto error; + PEPPER_CHECK(buffer, return NULL, "calloc() failed.\n"); - if (!init_buffer_gbm(buffer, drm, bo, GBM_FORMAT_XRGB8888 /* FIXME */)) - goto error; + if (!init_buffer_gbm(buffer, drm, bo, format)) + { + free(buffer); + return NULL; + } buffer->type = DRM_BUFFER_TYPE_CLIENT; - buffer->client_buffer = pb; - buffer->bo = bo; - pepper_buffer_reference(pb); + buffer->client_buffer = client_buffer; + pepper_buffer_reference(client_buffer); buffer->client_buffer_destroy_listener = - pepper_object_add_event_listener((pepper_object_t *)pb, PEPPER_EVENT_OBJECT_DESTROY, 0, + pepper_object_add_event_listener((pepper_object_t *)client_buffer, + PEPPER_EVENT_OBJECT_DESTROY, 0, handle_client_buffer_destroy, buffer); return buffer; - -error: - if (bo) - gbm_bo_destroy(bo); - - if (buffer) - free(buffer); - - return NULL; } void diff --git a/src/lib/drm/drm-internal.h b/src/lib/drm/drm-internal.h index 011a265..12d247f 100644 --- a/src/lib/drm/drm-internal.h +++ b/src/lib/drm/drm-internal.h @@ -130,7 +130,8 @@ drm_buffer_t * drm_buffer_create_gbm(pepper_drm_t *drm, struct gbm_surface *surface, struct gbm_bo *bo); drm_buffer_t * -drm_buffer_create_pepper(pepper_drm_t *drm, pepper_buffer_t *buffer); +drm_buffer_create_client(pepper_drm_t *drm, + struct gbm_bo *bo, pepper_buffer_t *buffer, uint32_t format); void drm_buffer_release(drm_buffer_t *buffer); diff --git a/src/lib/drm/drm-output.c b/src/lib/drm/drm-output.c index 5e633b6..b918490 100644 --- a/src/lib/drm/drm-output.c +++ b/src/lib/drm/drm-output.c @@ -145,9 +145,11 @@ static pepper_plane_t * assign_fb_plane(drm_output_t *output, pepper_view_t *view) { double x, y; - int32_t w, h, transform; + int32_t w, h; pepper_surface_t *surface; pepper_buffer_t *buffer; + struct wl_resource *resource; + struct gbm_bo *bo; const pepper_output_geometry_t *geometry; @@ -170,17 +172,55 @@ assign_fb_plane(drm_output_t *output, pepper_view_t *view) return NULL; surface = pepper_view_get_surface(view); - transform = pepper_surface_get_buffer_transform(surface); - if (geometry->transform != transform) + if (!surface) + return NULL; + + if (geometry->transform != pepper_surface_get_buffer_transform(surface)) + return NULL; + + if (pepper_output_get_scale(output->base) != pepper_surface_get_buffer_scale(surface)) return NULL; buffer = pepper_surface_get_buffer(surface); if (!buffer) return NULL; - output->back = drm_buffer_create_pepper(output->drm, buffer); + resource = pepper_buffer_get_resource(buffer); + if (!resource) + return NULL; + + bo = gbm_bo_import(output->drm->gbm_device, + GBM_BO_IMPORT_WL_BUFFER, resource, GBM_BO_USE_SCANOUT); + if (!bo) + return NULL; + + /* TODO: Other alpha formats like ARGB4444, ABGR8888 ?? */ + if (gbm_bo_get_format(bo) == GBM_FORMAT_ARGB8888) + { + pixman_box32_t box; + pixman_region32_t *opaque; + + box.x1 = 0; + box.y1 = 0; + box.x2 = w; + box.y2 = h; + + opaque = pepper_surface_get_opaque_region(surface); + + if (pixman_region32_contains_rectangle(opaque, &box) != PIXMAN_REGION_IN) + { + gbm_bo_destroy(bo); + return NULL; + } + } + + /* TODO: Hard-coded XRGB8888 */ + output->back = drm_buffer_create_client(output->drm, bo, buffer, GBM_FORMAT_XRGB8888); if (!output->back) + { + gbm_bo_destroy(bo); return NULL; + } return output->fb_plane; } @@ -192,10 +232,16 @@ assign_overlay_plane(drm_output_t *output, pepper_view_t *view) pepper_surface_t *surface; pepper_buffer_t *buffer; struct wl_resource *resource; + struct gbm_bo *bo; + uint32_t format; + pepper_bool_t found; + uint32_t i; double x, y; int w, h; + return NULL; + if (!output->drm->gbm_device) return NULL; @@ -214,34 +260,87 @@ assign_overlay_plane(drm_output_t *output, pepper_view_t *view) if (wl_shm_buffer_get(resource)) return NULL; + found = PEPPER_FALSE; + pepper_list_for_each(plane, &output->drm->plane_list, link) { - if (!plane->back && (plane->plane->possible_crtcs & (1 << output->crtc_index))) + if (plane->back) + continue; + + if (!(plane->plane->possible_crtcs & (1 << output->crtc_index))) + continue; + + found = PEPPER_TRUE; + break; + } + + if (!found) + return NULL; + + bo = gbm_bo_import(output->drm->gbm_device, + GBM_BO_IMPORT_WL_BUFFER, resource, GBM_BO_USE_SCANOUT); + if (!bo) + return NULL; + + /* TODO: Other alpha formats like ARGB4444, ABGR8888 ?? */ + format = gbm_bo_get_format(bo); + + if (format == GBM_FORMAT_ARGB8888) + { + pixman_box32_t box; + pixman_region32_t *opaque; + + box.x1 = 0; + box.y1 = 0; + box.x2 = w; + box.y2 = h; + + opaque = pepper_surface_get_opaque_region(surface); + + if (pixman_region32_contains_rectangle(opaque, &box) == PIXMAN_REGION_IN) + format = GBM_FORMAT_XRGB8888; + } + + found = PEPPER_FALSE; + + for (i = 0; i < plane->plane->count_formats; i++) + { + if (plane->plane->formats[i] == format) { - plane->back = drm_buffer_create_pepper(output->drm, buffer); - if (!plane->back) - return NULL; - - /* set position */ - pepper_view_get_position(view, &x, &y); - pepper_view_get_size(view, &w, &h); - plane->dx = (int)x; - plane->dy = (int)y; - plane->dw = w; - plane->dh = h; - - plane->sx = 0 << 16; - plane->sy = 0 << 16; - plane->sw = w << 16; - plane->sh = h << 16; - - plane->output = output; - - return plane->base; + found = PEPPER_TRUE; + break; } } - return NULL; + if (!found) + { + gbm_bo_destroy(bo); + return NULL; + } + + plane->back = drm_buffer_create_client(output->drm, bo, buffer, format); + if (!plane->back) + { + gbm_bo_destroy(bo); + return NULL; + } + + /* set position */ + pepper_view_get_position(view, &x, &y); + pepper_view_get_size(view, &w, &h); + plane->dx = (int)x; + plane->dy = (int)y; + plane->dw = w; + plane->dh = h; + + plane->sx = 0 << 16; + plane->sy = 0 << 16; + plane->sw = w << 16; + plane->sh = h << 16; + + plane->output = output; + + return plane->base; } static void diff --git a/src/lib/pepper/output.c b/src/lib/pepper/output.c index b300b39..0047c71 100644 --- a/src/lib/pepper/output.c +++ b/src/lib/pepper/output.c @@ -399,7 +399,7 @@ pepper_output_get_geometry(pepper_output_t *output) return &output->geometry; } -PEPPER_API uint32_t +PEPPER_API int32_t pepper_output_get_scale(pepper_output_t *output) { return output->scale; diff --git a/src/lib/pepper/pepper.h b/src/lib/pepper/pepper.h index 9772e0c..239bc22 100644 --- a/src/lib/pepper/pepper.h +++ b/src/lib/pepper/pepper.h @@ -884,7 +884,7 @@ pepper_output_move(pepper_output_t *output, int32_t x, int32_t y); PEPPER_API const pepper_output_geometry_t * pepper_output_get_geometry(pepper_output_t *output); -PEPPER_API unsigned int +PEPPER_API int32_t pepper_output_get_scale(pepper_output_t *output); PEPPER_API int -- 2.34.1