change plane list
authorJunkyeong Kim <jk0430.kim@samsung.com>
Thu, 30 Nov 2017 06:44:01 +0000 (15:44 +0900)
committerBoram Park <boram1288.park@samsung.com>
Fri, 1 Dec 2017 05:39:11 +0000 (14:39 +0900)
do not use oringin primay layer because of yuv format data showing problem.
set 2nd overlay plane to primary.
do not use pageflip. use only setplane.

Change-Id: I0cb2021a32627b6ebe95d3eecc88aafac3107226
Signed-off-by: Junkyeong Kim <jk0430.kim@samsung.com>
src/tdm_vc4_display.c

index 2acb707..c59b60a 100644 (file)
@@ -62,6 +62,10 @@ struct _tdm_vc4_output_data {
 
        int mode_changed;
        const tdm_output_mode *current_mode;
+
+       tbm_surface_h crtc_buffer;
+       int crtc_enabled;
+       unsigned int crtc_fb_id;
 };
 
 struct _tdm_vc4_layer_data {
@@ -106,6 +110,129 @@ _tdm_vc4_display_get_mode(tdm_vc4_output_data *output_data)
        return NULL;
 }
 
+static tdm_error
+_tdm_vc4_display_set_fb(tdm_vc4_data *vc4_data, tbm_surface_h buffer, unsigned int *id)
+{
+       unsigned int width;
+       unsigned int height;
+       unsigned int format;
+       unsigned int handles[4] = {0,};
+       unsigned int pitches[4] = {0,};
+       unsigned int offsets[4] = {0,};
+       unsigned int size;
+       unsigned int fb_id;
+       int ret, count, i;
+
+       width = tbm_surface_get_width(buffer);
+       height = tbm_surface_get_height(buffer);
+       format = tbm_surface_get_format(buffer);
+       count = tbm_surface_internal_get_num_bos(buffer);
+       for (i = 0; i < count; i++) {
+               tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
+               handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+       }
+       count = tbm_surface_internal_get_num_planes(format);
+       for (i = 0; i < count; i++)
+               tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
+
+       TDM_DBG("AddFB2: drm_fd(%d) size(%dx%d) format(%c%c%c%c) handles(%d,%d,%d) pitches(%d,%d,%d) offsets(%d,%d,%d) buffer(%p)",
+                       vc4_data->drm_fd, width, height, FOURCC_STR(format),
+                       handles[0], handles[1], handles[2], pitches[0], pitches[1], pitches[2],
+                       offsets[0], offsets[1], offsets[2], buffer);
+
+       ret = drmModeAddFB2(vc4_data->drm_fd, width, height, format,
+                                               handles, pitches, offsets, &fb_id, 0);
+       if (ret < 0) {
+               TDM_ERR("add fb failed: %m");
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+       TDM_DBG("AddFB2 success: drm_fd(%d) fb_id(%u)", vc4_data->drm_fd, fb_id);
+
+       *id = fb_id;
+       return TDM_ERROR_NONE;
+}
+
+static tdm_error
+_tdm_vc4_display_set_crtc(tdm_vc4_data *vc4_data, tdm_vc4_output_data *output_data, int set)
+{
+       int ret;
+
+       output_data->mode_changed = 0;
+
+       if (set) {
+               tbm_surface_h buffer = NULL;
+               tbm_surface_info_s info;
+               drmModeModeInfoPtr mode;
+               unsigned int fb_id = 0;
+
+               if (!output_data->current_mode)
+                       return TDM_ERROR_OPERATION_FAILED;
+
+               mode = _tdm_vc4_display_get_mode(output_data);
+               if (!mode) {
+                       TDM_ERR("couldn't find proper mode");
+                       return TDM_ERROR_BAD_REQUEST;
+               }
+
+               buffer = tbm_surface_create(output_data->current_mode->hdisplay,
+                                                                       output_data->current_mode->vdisplay,
+                                                                       TBM_FORMAT_XRGB8888);
+               RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_OPERATION_FAILED);
+
+               tbm_surface_map(buffer, TBM_SURF_OPTION_WRITE, &info);
+               memset(info.planes[0].ptr, 0x0, info.size);
+
+               tbm_surface_unmap(buffer);
+
+               if (_tdm_vc4_display_set_fb(vc4_data, buffer, &fb_id) != TDM_ERROR_NONE) {
+                       tbm_surface_destroy(buffer);
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+
+               TDM_DBG("drmModeSetCrtc drm_fd(%d) crtc_id(%u) fb_id(%u) mode(%u,%u)",
+                               vc4_data->drm_fd, output_data->crtc_id, fb_id,
+                               mode->hdisplay, mode->vdisplay);
+               if (drmModeSetCrtc(vc4_data->drm_fd, output_data->crtc_id,
+                                                  fb_id, 0, 0,
+                                                  &output_data->connector_id, 1, mode)) {
+                       TDM_ERR("set crtc failed: %m");
+                       ret = drmModeRmFB(vc4_data->drm_fd, fb_id);
+                       if (ret < 0)
+                               TDM_ERR("rm fb failed fb_id(%u)", fb_id);
+                       tbm_surface_destroy(buffer);
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+
+               if (output_data->crtc_buffer) {
+                       ret = drmModeRmFB(vc4_data->drm_fd, output_data->crtc_fb_id);
+                       if (ret < 0)
+                               TDM_ERR("rm fb failed fb_id(%u)", output_data->crtc_fb_id);
+                       tbm_surface_destroy(output_data->crtc_buffer);
+               }
+               output_data->crtc_buffer = buffer;
+               output_data->crtc_fb_id = fb_id;
+       } else {
+               TDM_DBG("drmModeSetCrtc unset drm_fd(%d) crtc_id(%u)",
+                               vc4_data->drm_fd, output_data->crtc_id);
+               if (drmModeSetCrtc(vc4_data->drm_fd, output_data->crtc_id,
+                                                  0, 0, 0, NULL, 0, NULL)) {
+                       TDM_ERR("unset crtc failed: %m");
+                       return TDM_ERROR_OPERATION_FAILED;
+               }
+
+               if (output_data->crtc_buffer) {
+                       ret = drmModeRmFB(vc4_data->drm_fd, output_data->crtc_fb_id);
+                       if (ret < 0)
+                               TDM_ERR("rm fb failed fb_id(%u)", output_data->crtc_fb_id);
+                       tbm_surface_destroy(output_data->crtc_buffer);
+               }
+               output_data->crtc_buffer = NULL;
+               output_data->crtc_fb_id = 0;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
 static tdm_vc4_display_buffer *
 _tdm_vc4_display_find_buffer(tdm_vc4_data *vc4_data, tbm_surface_h buffer)
 {
@@ -207,80 +334,6 @@ _tdm_vc4_output_update_status(tdm_vc4_output_data *output_data,
 }
 
 static tdm_error
-_tdm_vc4_display_commit_primary_layer(tdm_vc4_layer_data *layer_data,
-                                                                         void *user_data, int *do_waitvblank)
-{
-       tdm_vc4_data *vc4_data = layer_data->vc4_data;
-       tdm_vc4_output_data *output_data = layer_data->output_data;
-
-       if (output_data->mode_changed && layer_data->display_buffer_changed) {
-               drmModeModeInfoPtr mode;
-
-               if (!layer_data->display_buffer) {
-                       TDM_ERR("primary layer should have a buffer for modestting");
-                       return TDM_ERROR_BAD_REQUEST;
-               }
-
-               output_data->mode_changed = 0;
-               layer_data->display_buffer_changed = 0;
-               layer_data->info_changed = 0;
-
-               mode = _tdm_vc4_display_get_mode(output_data);
-               if (!mode) {
-                       TDM_ERR("couldn't find proper mode");
-                       return TDM_ERROR_BAD_REQUEST;
-               }
-
-               if (drmModeSetCrtc(vc4_data->drm_fd, output_data->crtc_id,
-                                                  layer_data->display_buffer->fb_id, 0, 0,
-                                                  &output_data->connector_id, 1, mode)) {
-                       TDM_ERR("set crtc failed: %m");
-                       return TDM_ERROR_OPERATION_FAILED;
-               }
-
-               _tdm_vc4_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
-
-               *do_waitvblank = 1;
-               return TDM_ERROR_NONE;
-       } else if (layer_data->display_buffer_changed) {
-               layer_data->display_buffer_changed = 0;
-
-               if (!layer_data->display_buffer) {
-                       if (drmModeSetCrtc(vc4_data->drm_fd, output_data->crtc_id,
-                                                          0, 0, 0, NULL, 0, NULL)) {
-                               TDM_ERR("unset crtc failed: %m");
-                               return TDM_ERROR_OPERATION_FAILED;
-                       }
-
-                       if (output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
-                               _tdm_vc4_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_CONNECTED);
-
-                       *do_waitvblank = 1;
-               } else {
-                       tdm_vc4_event_data *event_data = calloc(1, sizeof(tdm_vc4_event_data));
-
-                       if (!event_data) {
-                               TDM_ERR("alloc failed");
-                               return TDM_ERROR_OUT_OF_MEMORY;
-                       }
-
-                       event_data->type = TDM_DRM_EVENT_TYPE_PAGEFLIP;
-                       event_data->output_data = output_data;
-                       event_data->user_data = user_data;
-                       if (drmModePageFlip(vc4_data->drm_fd, output_data->crtc_id,
-                                                               layer_data->display_buffer->fb_id, DRM_MODE_PAGE_FLIP_EVENT, event_data)) {
-                               TDM_ERR("pageflip failed: %m");
-                               free(event_data);
-                               return TDM_ERROR_OPERATION_FAILED;
-                       }
-                       *do_waitvblank = 0;
-               }
-       }
-
-       return TDM_ERROR_NONE;
-}
-
-static tdm_error
 _tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data)
 {
        tdm_vc4_data *vc4_data = layer_data->vc4_data;
@@ -291,6 +344,13 @@ _tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data)
        if (!layer_data->display_buffer_changed && !layer_data->info_changed)
                return TDM_ERROR_NONE;
 
+       if (!output_data->crtc_enabled || output_data->mode_changed) {
+               if (_tdm_vc4_display_set_crtc(vc4_data, output_data, 1) != TDM_ERROR_NONE)
+                       return TDM_ERROR_OPERATION_FAILED;
+
+               output_data->crtc_enabled = 1;
+       }
+
        if (output_data->current_mode)
                crtc_w = output_data->current_mode->hdisplay;
        else {
@@ -583,9 +643,11 @@ _tdm_vc4_display_create_layer_list_type(tdm_vc4_data *vc4_data)
                goto failed;
        }
 
-       opos_next = 1;
-       cpos_next = ovl_cnt;
-       for (i = 0; i < plane_cnt; i++) {
+       /* do not use primary plane(0) because of yuv format displaying problem */
+       /* set 2nd overlay plane to primary, 1st plane is for video */
+       opos_next = 0;
+       cpos_next = ovl_cnt - 1;
+       for (i = 1; i < plane_cnt; i++) {
                tdm_vc4_layer_data *layer_data;
 
                layer_data = calloc(1, sizeof(tdm_vc4_layer_data));
@@ -603,14 +665,19 @@ _tdm_vc4_display_create_layer_list_type(tdm_vc4_data *vc4_data)
                                                                           TDM_LAYER_CAPABILITY_GRAPHIC;
                        layer_data->zpos = cpos_next++;
                } else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
-                       layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
-                                                                          TDM_LAYER_CAPABILITY_GRAPHIC;
+                       if (i == 1) {
+                               layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
+                                                                                  TDM_LAYER_CAPABILITY_GRAPHIC |
+                                                                                  TDM_LAYER_CAPABILITY_SCALE;
+                       } else if (i == 2) {
+                               layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
+                                                                                  TDM_LAYER_CAPABILITY_GRAPHIC;
+                               output_data->primary_layer = layer_data;
+                       } else {
+                               layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
+                                                                                  TDM_LAYER_CAPABILITY_GRAPHIC;
+                       }
                        layer_data->zpos = opos_next++;
-               } else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
-                       layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
-                                                                          TDM_LAYER_CAPABILITY_GRAPHIC;
-                       layer_data->zpos = 0;
-                       output_data->primary_layer = layer_data;
                } else {
                        free(layer_data);
                        continue;
@@ -719,6 +786,11 @@ tdm_vc4_display_destroy_output_list(tdm_vc4_data *vc4_data)
                return;
 
        LIST_FOR_EACH_ENTRY_SAFE(o, oo, &vc4_data->output_list, link) {
+               if (o->crtc_enabled) {
+                       _tdm_vc4_display_set_crtc(vc4_data, o, 0);
+                       o->crtc_enabled = 0;
+               }
+
                LIST_DEL(&o->link);
                if (!LIST_IS_EMPTY(&o->layer_list)) {
                        tdm_vc4_layer_data *l = NULL, *ll = NULL;
@@ -1289,16 +1361,9 @@ vc4_output_commit(tdm_output *output, int sync, void *user_data)
        vc4_data = output_data->vc4_data;
 
        LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
-               if (layer_data == output_data->primary_layer) {
-                       ret = _tdm_vc4_display_commit_primary_layer(layer_data, user_data,
-                                                       &do_waitvblank);
-                       if (ret != TDM_ERROR_NONE)
-                               return ret;
-               } else {
-                       ret = _tdm_vc4_display_commit_layer(layer_data);
-                       if (ret != TDM_ERROR_NONE)
-                               return ret;
-               }
+               ret = _tdm_vc4_display_commit_layer(layer_data);
+               if (ret != TDM_ERROR_NONE)
+                       return ret;
        }
 
        if (do_waitvblank == 1) {