support Atomic Mode Setting 11/251811/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Thu, 14 Jan 2021 11:14:35 +0000 (20:14 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Fri, 15 Jan 2021 07:16:11 +0000 (16:16 +0900)
if DRM_CLIENT_CAP_ATOMIC is enable, hwc use Atomic Mode Setting

Change-Id: I8a1ffa0a5910ae19aef11c051b75b05ab85b4e0d

src/tdm_nexell.c
src/tdm_nexell_display.c
src/tdm_nexell_hwc.c
src/tdm_nexell_hwc_window.c
src/tdm_nexell_types.h

index cd195903e8584e912e4b33dd306e1020a806d0b1..7d001543c658c1aadd66912d0347ea501d757821 100644 (file)
@@ -249,12 +249,6 @@ tdm_nexell_init(tdm_display *dpy, tdm_error *error)
        tdm_error ret;
        char *str;
 
-#define TDM_CHANGE_DEBUG_LOGLEVEL
-#ifdef TDM_CHANGE_DEBUG_LOGLEVEL
-       // show DBG log level
-       tdm_log_set_debug_level(4);
-#endif
-
        if (!dpy) {
                TDM_ERR("display is null");
                if (error)
@@ -431,6 +425,13 @@ tdm_nexell_init(tdm_display *dpy, tdm_error *error)
                TDM_INFO("has universal planes");
                nexell_data->has_universal_plane = 1;
        }
+
+       if (drmSetClientCap(nexell_data->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) {
+               TDM_WRN("Set DRM_CLIENT_CAP_ATOMIC failed");
+       } else {
+               TDM_INFO("has atomic");
+               nexell_data->has_atomic = 1;
+       }
 #endif
 
        nexell_data->mode_res = drmModeGetResources(nexell_data->drm_fd);
index c2c794efbd0eff79c158ee7bd88c93c06e0790e6..139a61a292ddc53e07d9f4512b0146c805dc9fcc 100644 (file)
@@ -103,48 +103,6 @@ _tdm_nexell_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
        return TDM_ERROR_NONE;
 }
 
-static tdm_error
-_tdm_nexell_display_set_fb(tdm_nexell_data *nexell_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)",
-                       nexell_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(nexell_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)", nexell_data->drm_fd, fb_id);
-
-       *id = fb_id;
-       return TDM_ERROR_NONE;
-}
-
 static tdm_error
 _tdm_nexell_output_update_status(tdm_nexell_output_data *output_data,
                               tdm_output_conn_status status)
@@ -164,20 +122,23 @@ _tdm_nexell_output_update_status(tdm_nexell_output_data *output_data,
 }
 
 static tdm_error
-_tdm_nexell_display_set_crtc(tdm_nexell_data *nexell_data, tdm_nexell_output_data *output_data, int set)
+_tdm_nexell_display_commit_primary_layer(tdm_nexell_layer_data *layer_data,
+                                      void *user_data, int *do_waitvblank)
 {
-       int ret;
-
-       output_data->mode_changed = 0;
+       tdm_nexell_data *nexell_data = layer_data->nexell_data;
+       tdm_nexell_output_data *output_data = layer_data->output_data;
 
-       if (set) {
-               tbm_surface_h buffer = NULL;
-               tbm_surface_info_s info;
+       if (output_data->mode_changed && layer_data->display_buffer_changed) {
                drmModeModeInfoPtr mode;
-               unsigned int fb_id = 0;
 
-               if (!output_data->current_mode)
-                       return TDM_ERROR_OPERATION_FAILED;
+               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_nexell_display_get_mode(output_data);
                if (!mode) {
@@ -185,69 +146,42 @@ _tdm_nexell_display_set_crtc(tdm_nexell_data *nexell_data, tdm_nexell_output_dat
                        return TDM_ERROR_BAD_REQUEST;
                }
 
-               /* A buffer which is set to crtc should has TBM_BO_SCANOUT flag */
-               buffer = tbm_surface_internal_create_with_flags(output_data->current_mode->hdisplay,
-                                                                                       output_data->current_mode->vdisplay,
-                                                                                       TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
-               RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_OPERATION_FAILED);
-
-               if (tbm_surface_map(buffer, TBM_SURF_OPTION_WRITE, &info) != TBM_ERROR_NONE) {
-                       tbm_surface_destroy(buffer);
-                       return TDM_ERROR_OPERATION_FAILED;
-               }
-               memset(info.planes[0].ptr, 0x0, info.size);
-
-               tbm_surface_unmap(buffer);
-
-               if (_tdm_nexell_display_set_fb(nexell_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)",
-                               nexell_data->drm_fd, output_data->crtc_id, fb_id,
-                               mode->hdisplay, mode->vdisplay);
-
                if (drmModeSetCrtc(nexell_data->drm_fd, output_data->crtc_id,
-                                                  fb_id, 0, 0,
-                                                  &output_data->connector_id, 1, mode)) {
+                                  layer_data->display_buffer->fb_id, 0, 0,
+                                  &output_data->connector_id, 1, mode)) {
                        TDM_ERR("set crtc failed: %m");
-                       ret = drmModeRmFB(nexell_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;
                }
 
                _tdm_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
 
-               if (output_data->crtc_buffer) {
-                       ret = drmModeRmFB(nexell_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);
-               }
+               *do_waitvblank = 1;
+               return TDM_ERROR_NONE;
+       } else if (layer_data->display_buffer_changed) {
+               layer_data->display_buffer_changed = 0;
 
-               output_data->crtc_buffer = buffer;
-               output_data->crtc_fb_id = fb_id;
-       } else {
-               TDM_DBG("drmModeSetCrtc unset drm_fd(%d) crtc_id(%u)",
-                               nexell_data->drm_fd, output_data->crtc_id);
+               if (layer_data->display_buffer) {
+                       tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
 
-               if (drmModeSetCrtc(nexell_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 (!event_data) {
+                               TDM_ERR("alloc failed");
+                               return TDM_ERROR_OUT_OF_MEMORY;
+                       }
 
-               if (output_data->crtc_buffer) {
-                       ret = drmModeRmFB(nexell_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);
+                       event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
+                       event_data->output_data = output_data;
+                       event_data->user_data = user_data;
+                       if (drmModePageFlip(nexell_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;
                }
-               output_data->crtc_buffer = NULL;
-               output_data->crtc_fb_id = 0;
+       }else {
+               /* to call a user commit handler whenever committed */
+               *do_waitvblank = 1;
        }
 
        return TDM_ERROR_NONE;
@@ -264,17 +198,6 @@ _tdm_nexell_display_commit_layer(tdm_nexell_layer_data *layer_data)
        if (!layer_data->display_buffer_changed && !layer_data->info_changed)
                return TDM_ERROR_NONE;
 
-       // set crtc if crtc is not available and if mode is changed.
-       if (!output_data->crtc_enabled || output_data->mode_changed) {
-               if (_tdm_nexell_display_set_crtc(nexell_data, output_data, 1) != TDM_ERROR_NONE)
-                       return TDM_ERROR_OPERATION_FAILED;
-
-               output_data->crtc_enabled = 1;
-
-               return TDM_ERROR_NONE;
-       }
-
-       // check if the crtc is available
        if (output_data->current_mode)
                crtc_w = output_data->current_mode->hdisplay;
        else {
@@ -366,8 +289,6 @@ _tdm_nexell_display_cb_event(int fd, unsigned int sequence,
                                break;
                        }
 
-                       TDM_DBG("crtc_enable(%d), mode_changed(%d)\n", output_data->crtc_enabled, output_data->mode_changed);
-
                        if (hwc_data->commit_func)
                                hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec,
                                                                                 event_data->user_data);
@@ -489,6 +410,38 @@ _tdm_nexell_display_get_property(tdm_nexell_data *nexell_data,
        return TDM_ERROR_OPERATION_FAILED;
 }
 
+static tdm_error
+_nexell_output_get_atomic_prop_id(int drm_fd, uint32_t object_id, uint32_t object_type, const char *name, uint32_t *id)
+{
+       drmModeObjectPropertiesPtr properties = NULL;
+       drmModePropertyPtr property = NULL;
+       int i;
+
+       properties = drmModeObjectGetProperties(drm_fd, object_id, object_type);
+       if (properties == NULL) {
+               TDM_ERR("drmModeObjectGetProperties failed");
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       for (i = 0; i < properties->count_props; i++) {
+               property = drmModeGetProperty(drm_fd, properties->props[i]);
+               if (property == NULL) {
+                       continue;
+               }
+
+               if (strcmp(property->name, name) == 0) {
+                       *id = property->prop_id;
+                       drmModeFreeProperty(property);
+                       break;
+               }
+               drmModeFreeProperty(property);
+       }
+
+       drmModeFreeObjectProperties(properties);
+
+       return TDM_ERROR_NONE;
+}
+
 static tdm_error
 _tdm_nexell_display_create_layer_list_type(tdm_nexell_data *nexell_data)
 {
@@ -648,6 +601,79 @@ _tdm_nexell_display_create_layer_list_type(tdm_nexell_data *nexell_data)
                                 layer_data->zpos, layer_data->capabilities);
 
                LIST_ADDTAIL(&layer_data->link, &output_data->layer_list);
+
+               /* get the atomic prop ids*/
+               if (nexell_data->has_atomic) {
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "FB_ID", &layer_data->atomic_props_ids.fb_id);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_ID", &layer_data->atomic_props_ids.crtc_id);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "SRC_X", &layer_data->atomic_props_ids.src_x);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "SRC_Y", &layer_data->atomic_props_ids.src_y);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "SRC_W", &layer_data->atomic_props_ids.src_w);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "SRC_H", &layer_data->atomic_props_ids.src_h);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_X", &layer_data->atomic_props_ids.crtc_x);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_Y", &layer_data->atomic_props_ids.crtc_y);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_W", &layer_data->atomic_props_ids.crtc_w);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+
+                       ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, layer_data->plane_id,
+                                               DRM_MODE_OBJECT_PLANE, "CRTC_H", &layer_data->atomic_props_ids.crtc_h);
+                       if (ret != TDM_ERROR_NONE) {
+                               free(layer_data);
+                               goto failed;
+                       }
+               }
        }
 
        for (i = 0; i < plane_cnt; i++)
@@ -713,11 +739,6 @@ tdm_nexell_display_destroy_output_list(tdm_nexell_data *nexell_data)
                if (hwc_data && hwc_data->target_hwc_window)
                        nexell_hwc_window_destroy(hwc_data->target_hwc_window);
 
-               if (o->crtc_enabled) {
-                       _tdm_nexell_display_set_crtc(nexell_data, o, 0);
-                       o->crtc_enabled = 0;
-               }
-
                LIST_DEL(&o->link);
                if (!LIST_IS_EMPTY(&o->layer_list)) {
                        tdm_nexell_layer_data *l = NULL, *ll = NULL;
@@ -946,6 +967,24 @@ tdm_nexell_display_create_output_list(tdm_nexell_data *nexell_data)
        drmModeFreeEncoder(encoder);
        drmModeFreeConnector(connector);
 
+       /* get the atomic prop ids*/
+       if (nexell_data->has_atomic) {
+               ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->connector_id,
+                                       DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", &output_data->atomic_props_ids.crtc_id);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed_create;
+
+               ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->crtc_id,
+                                       DRM_MODE_OBJECT_CRTC, "MODE_ID", &output_data->atomic_props_ids.crtc_mode_id);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed_create;
+
+               ret = _nexell_output_get_atomic_prop_id(nexell_data->drm_fd, output_data->crtc_id,
+                               DRM_MODE_OBJECT_CRTC, "ACTIVE", &output_data->atomic_props_ids.crtc_active);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed_create;
+       }
+
        TDM_DBG("output count: %d", nexell_data->mode_res->count_connectors);
 
        return TDM_ERROR_NONE;
@@ -1348,8 +1387,215 @@ nexell_output_set_vblank_handler(tdm_output *output,
        return TDM_ERROR_NONE;
 }
 
-tdm_error
-nexell_output_commit(tdm_output *output, int sync, void *user_data)
+static tdm_error
+_nexell_layer_add_atomic_properties(tdm_nexell_layer_data *layer_data, drmModeAtomicReqPtr request,
+                       uint32_t fb_id, uint32_t crtc_id, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
+                       uint32_t crtc_x, uint32_t crtc_y, uint32_t crtc_w, uint32_t crtc_h)
+{
+       tdm_error ret = TDM_ERROR_NONE;
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.fb_id, fb_id);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. fb_id(%u)", fb_id);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_id, crtc_id);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_id(%u)", crtc_id);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_x, src_x);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. src_x(%u)", src_x);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_y, src_y);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. src_y(%u)", src_y);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_w, src_w);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. src_w(%u)", src_w);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.src_h, src_h);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. src_h(%u)", src_h);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_x, crtc_x);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_x(%u)", crtc_x);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_y, crtc_y);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_y(%u)", crtc_y);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_w, crtc_w);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_w(%u)", crtc_w);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       ret = drmModeAtomicAddProperty(request, layer_data->plane_id, layer_data->atomic_props_ids.crtc_h, crtc_h);
+       if (ret < 0) {
+               TDM_ERR("fail to add the atomic prop. crtc_h(%u)", crtc_h);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
+static tdm_error
+_nexell_layer_make_atomic_request(tdm_nexell_layer_data *layer_data, drmModeAtomicReqPtr request)
+{
+       tdm_nexell_data *nexell_data = layer_data->nexell_data;
+       tdm_nexell_output_data *output_data = layer_data->output_data;
+       uint32_t fx, fy, fw, fh;
+       tdm_info_layer layer_info = layer_data->info;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       if (!layer_data->display_buffer_changed && !layer_data->info_changed)
+               return TDM_ERROR_NONE;
+
+       layer_data->display_buffer_changed = 0;
+       layer_data->info_changed = 0;
+
+       if (!layer_data->display_buffer) {
+               TDM_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) crtc_id(%u) off",
+                               nexell_data->drm_fd, layer_data->plane_id, output_data->crtc_id);
+
+               ret = _nexell_layer_add_atomic_properties(layer_data, request, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("_nexell_layer_add_atomic_properties failed.");
+                       return ret;
+               }
+
+               return TDM_ERROR_NONE;
+       }
+
+       /* Source values are 16.16 fixed point */
+       fx = ((unsigned int)layer_info.src_config.pos.x) << 16;
+       fy = ((unsigned int)layer_info.src_config.pos.y) << 16;
+       fw = ((unsigned int)layer_info.src_config.pos.w) << 16;
+       fh = ((unsigned int)layer_info.src_config.pos.h) << 16;
+
+       TDM_DBG("MakeAtomicRequest: drm_fd(%d) plane_id(%u) zpos(%d) crtc_id(%u) fb_id(%u) src(%u,%u %ux%u) dst(%u,%u %ux%u)",
+                       nexell_data->drm_fd, layer_data->plane_id, layer_data->zpos,
+                       output_data->crtc_id, layer_data->display_buffer->fb_id,
+                       layer_info.src_config.pos.x, layer_info.src_config.pos.y,
+                       layer_info.src_config.pos.w, layer_info.src_config.pos.h,
+                       layer_info.dst_pos.x, layer_info.dst_pos.y,
+                       layer_info.dst_pos.w, layer_info.dst_pos.h);
+
+       ret = _nexell_layer_add_atomic_properties(layer_data, request,
+                                               layer_data->display_buffer->fb_id, output_data->crtc_id,
+                                               fx, fy, fw, fh,
+                                               layer_info.dst_pos.x, layer_info.dst_pos.y,
+                                               layer_info.dst_pos.w, layer_info.dst_pos.h);
+       if (ret != TDM_ERROR_NONE) {
+               TDM_ERR("MakeAtomicRequest failed");
+               return ret;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
+static tdm_error
+_nexell_output_atomic_commit(tdm_output *output, int sync, void *user_data)
+{
+       tdm_nexell_output_data *output_data = output;
+       tdm_nexell_layer_data *layer_data = NULL;
+       tdm_nexell_event_data *event_data;
+       drmModeAtomicReqPtr request;
+       uint32_t flags =  0;
+       tdm_error ret;
+
+       RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
+
+       if (!output_data->crtc_enabled || output_data->mode_changed) {
+               drmModeModeInfoPtr mode;
+
+               layer_data = output_data->primary_layer;
+               if (!layer_data->display_buffer) {
+                       TDM_ERR("primary layer should have a buffer for modestting");
+                       return TDM_ERROR_BAD_REQUEST;
+               }
+
+               mode = _tdm_nexell_display_get_mode(output_data);
+               if (!mode) {
+                       TDM_ERR("couldn't find proper mode");
+                       return TDM_ERROR_BAD_REQUEST;
+               }
+
+               if (drmModeSetCrtc(output_data->nexell_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_nexell_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_MODE_SETTED);
+
+               output_data->crtc_enabled = 1;
+               output_data->mode_changed = 0;
+       }
+
+       request = drmModeAtomicAlloc();
+       if (!request) {
+               TDM_ERR("drmModeAtomicAlloc failed.");
+               return TDM_ERROR_OUT_OF_MEMORY;
+       }
+
+       flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
+
+       LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
+               ret = _nexell_layer_make_atomic_request(layer_data, request);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("_nexell_layer_make_atomic_request failed.");
+                       drmModeAtomicFree(request);
+                       return ret;
+               }
+       }
+
+       event_data = calloc(1, sizeof(tdm_nexell_event_data));
+       if (!event_data) {
+               TDM_ERR("fail to alloc event_data.");
+               drmModeAtomicFree(request);
+               return TDM_ERROR_OUT_OF_MEMORY;
+       }
+
+       event_data->type = TDM_NEXELL_EVENT_TYPE_COMMIT;
+       event_data->output_data = output_data;
+       event_data->user_data = user_data;
+
+       TDM_DBG("==== Atomic Commit pipe, %u, crtc_id, %u connector_id, %u",
+                       output_data->pipe, output_data->crtc_id, output_data->connector_id);
+
+       if (drmModeAtomicCommit(output_data->nexell_data->drm_fd, request, flags, event_data) < 0) {
+               TDM_ERR("drmModeAtomicCommit failed.");
+               drmModeAtomicFree(request);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       drmModeAtomicFree(request);
+
+       return TDM_ERROR_NONE;
+}
+
+static tdm_error
+_nexell_output_layers_commit(tdm_output *output, int sync, void *user_data)
 {
        tdm_nexell_output_data *output_data = output;
        tdm_nexell_data *nexell_data;
@@ -1361,26 +1607,18 @@ nexell_output_commit(tdm_output *output, int sync, void *user_data)
 
        nexell_data = output_data->nexell_data;
 
-#if 0
        LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
                if (layer_data == output_data->primary_layer) {
-                       ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data,
-                                       &do_waitvblank);
-                       if (ret != TDM_ERROR_NONE)
-                               return ret;
-               } else {
+                       ret = _tdm_nexell_display_commit_primary_layer(layer_data, user_data,
+                                       &do_waitvblank);
+                       if (ret != TDM_ERROR_NONE)
+                               return ret;
+               } else {
                        ret = _tdm_nexell_display_commit_layer(layer_data);
                        if (ret != TDM_ERROR_NONE)
                                return ret;
                }
        }
-#else
-       LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
-               ret = _tdm_nexell_display_commit_layer(layer_data);
-               if (ret != TDM_ERROR_NONE)
-                       return ret;
-       }
-#endif
 
        if (do_waitvblank == 1) {
                tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
@@ -1415,6 +1653,35 @@ nexell_output_commit(tdm_output *output, int sync, void *user_data)
        return TDM_ERROR_NONE;
 }
 
+tdm_error
+nexell_output_commit(tdm_output *output, int sync, void *user_data)
+{
+       tdm_nexell_output_data *output_data = output;
+       tdm_nexell_data *nexell_data;
+       tdm_error ret;
+
+       RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
+
+       nexell_data = output_data->nexell_data;
+
+       /* check the atomic pageflip */
+       if (nexell_data->has_atomic) {
+               ret = _nexell_output_atomic_commit(output, sync, user_data);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("_nexell_output_atomic_commit failed.");
+                       return ret;
+               }
+       } else {
+               ret = _nexell_output_layers_commit(output, sync, user_data);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("_nexell_output_layers_commit failed.");
+                       return ret;
+               }
+       }
+
+       return TDM_ERROR_NONE;
+}
+
 tdm_error
 nexell_output_set_commit_handler(tdm_output *output,
                               tdm_output_commit_handler func)
@@ -1531,6 +1798,7 @@ nexell_output_get_hwc(tdm_output *output, tdm_error *error)
        tdm_nexell_hwc_data *hwc_data = NULL;
        tdm_nexell_output_data *output_data = output;
        tdm_error ret = TDM_ERROR_NONE;
+       int i;
 
        if (!output_data) {
                TDM_ERR("invalid params");
@@ -1553,10 +1821,12 @@ nexell_output_get_hwc(tdm_output *output, tdm_error *error)
                        *error = TDM_ERROR_OUT_OF_MEMORY;
                return NULL;
        }
-       for (int i = 0; i < NUM_LAYERS; i++) {
+
+       for (i = 0; i < NUM_LAYERS; i++) {
                hwc_data->ui_buffer_queue[i].tqueue = NULL;
-               hwc_data->ui_buffer_queue[i].ref_cnt= 0;
+               hwc_data->ui_buffer_queue[i].ref_cnt = 0;
        }
+
        hwc_data->output_data = output_data;
 
        LIST_INITHEAD(&hwc_data->hwc_window_list);
index d80dedbb0eb62a90cb40bda2148797768210ee6a..58dc3ac08140621eef62f3a55c39946cef22f38c 100644 (file)
@@ -142,7 +142,7 @@ _print_validate_result(tdm_nexell_hwc_data *hwc_data, tdm_hwc_window **composite
                lzpos_queue = hwc_window_data->lzpos_queue;
                switch (hwc_window_data->validated_type) {
                case TDM_HWC_WIN_COMPOSITION_CLIENT:
-                       TDM_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p, ref_cnt:%d] -- {%s} on TARGET WINDOW", hwc_window_data,
+                       TDM_DBG(" window(%p) %s -> %s : lzpos(%d) lzpos_queue(%d)[tqueue:%p ref_cnt:%d] -- {%s} on TARGET WINDOW", hwc_window_data,
                                        _comp_to_str(hwc_window_data->client_type),
                                        _comp_to_str(hwc_window_data->validated_type),
                                        hwc_data->target_hwc_window->lzpos,
@@ -185,7 +185,7 @@ _nexell_hwc_window_has_reserved_buffer(tdm_nexell_hwc_window_data *hwc_window_da
 }
 
 static int
-_nexell_hwc_window_can_set_on_hw_layer(tdm_nexell_hwc_window_data *hwc_window_data)
+_nexell_hwc_window_can_set_on_hw_layer(tdm_nexell_hwc_window_data *hwc_window_data, int bottom)
 {
        if (!hwc_window_data->surface)
                return 0;
@@ -202,12 +202,15 @@ _nexell_hwc_window_can_set_on_hw_layer(tdm_nexell_hwc_window_data *hwc_window_da
        if (!IS_RGB(hwc_window_data->info.src_config.format))
                return 0;
 
-       if (hwc_window_data->info.dst_pos.x > hwc_window_data->hwc_data->output_data->current_mode->hdisplay ||
-               hwc_window_data->info.dst_pos.y > hwc_window_data->hwc_data->output_data->current_mode->vdisplay)
+       if ((hwc_window_data->info.dst_pos.x > hwc_window_data->hwc_data->output_data->current_mode->hdisplay) ||
+               (hwc_window_data->info.dst_pos.y > hwc_window_data->hwc_data->output_data->current_mode->vdisplay))
                return 0;
 
-       if (hwc_window_data->info.src_config.pos.w < MIN_WIDTH || hwc_window_data->info.src_config.pos.w % 2)
+       if (bottom) {
+               if ((hwc_window_data->info.dst_pos.w != hwc_window_data->hwc_data->output_data->current_mode->hdisplay) ||
+                       (hwc_window_data->info.dst_pos.h != hwc_window_data->hwc_data->output_data->current_mode->vdisplay))
                return 0;
+       }
 
        return 1;
 }
@@ -227,8 +230,8 @@ tdm_nexell_hwc_window_create_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_er
 
        hwc_window_data = hwc_window;
 
-       width = hwc_window_data->info.src_config.size.h;
-       height = hwc_window_data->info.src_config.size.v;
+       width = hwc_window_data->info.src_config.pos.w;
+       height = hwc_window_data->info.src_config.pos.h;
        format = hwc_window_data->info.src_config.format;
 
        tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT);
@@ -341,36 +344,20 @@ _nexell_hwc_apply_policy(tdm_nexell_hwc_data *hwc_data , tdm_hwc_window **compos
        int device_count = 0;
        int video_count = 0;
        int cursor_count = 0;
+       int ui_lzpos_top = ZPOS_2;
+       int ui_lzpos_bottom = ZPOS_1;
+       int num_ui_layers = NUM_UI_LAYERS;
+       int set_clients_below = 0;
        int i = 0;
-       int top_index = 0; // index of top in composited_wnds
-       int bottom_index = num_wnds - 1; // index of bottom in comopsited_wnds
-       int available_device_num = NUM_LAYERS;
-       int use_hw_layers[NUM_LAYERS] = {0, }; // 2 is top, 0 is bottom
 
        composited_list = (tdm_nexell_hwc_window_data **)composited_wnds;
 
-static int cnt = 0;
-
-       // for debugging
-       for (i = 0; i < num_wnds; i++) {
-               TDM_DBG("  [%d] name(%s)", i, composited_list[i]->name);
-               composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_NONE;
-               composited_list[i]->lzpos = -1;
-               composited_list[i]->lzpos_queue = -1;
-
-               ++cnt;
-               if (cnt < 10)
-                       goto set_clients_below;
-       }
-
        /* initialize the need_target_window */
        hwc_data->need_target_window = 0;
 
        /* initialize the validated_types and constraints */
        LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
                hwc_window_data->constraints = TDM_HWC_WIN_CONSTRAINT_NONE;
-               if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_NONE)
-                       continue;
                hwc_window_data->validated_type = TDM_HWC_WIN_COMPOSITION_NONE;
                hwc_window_data->lzpos = -1;
                hwc_window_data->lzpos_queue = -1;
@@ -379,111 +366,92 @@ static int cnt = 0;
        /* use the target_window to commit when there is no window. */
        if (num_wnds == 0) {
                hwc_data->need_target_window = 1;
-               hwc_data->target_hwc_window->lzpos = ZPOS_1;
-               hwc_data->target_hwc_window->lzpos_queue = ZPOS_1;
+               hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom;
+               hwc_data->target_hwc_window->lzpos_queue = ui_lzpos_bottom;
                return;
        }
 
-       /* count the composited(visible) windows */
+       /* 1. first check validate_type without target_window */
        for (i = 0; i < num_wnds; i++) {
-               if (composited_list[i]->client_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
-                       cursor_count++;
-               if (composited_list[i]->client_type == TDM_HWC_WIN_COMPOSITION_CLIENT)
-                       client_count++;
-               if (client_count == 0 && composited_list[i]->client_type == TDM_HWC_WIN_COMPOSITION_DEVICE)
-                       device_count++;
-               if (composited_list[i]->client_type == TDM_HWC_WIN_COMPOSITION_VIDEO)
+               switch (composited_list[i]->client_type) {
+               case TDM_HWC_WIN_COMPOSITION_VIDEO:
+                       composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_VIDEO;
                        video_count++;
-       }
+                       continue;
+               case TDM_HWC_WIN_COMPOSITION_CURSOR:
+                       if (set_clients_below) break;
+                       if (num_ui_layers <= 0) break;
 
-       /* set the cursor layer pos and validated_type */
-       if (cursor_count > 0) {
-               composited_list[top_index]->validated_type = TDM_HWC_WIN_COMPOSITION_CURSOR;
-               composited_list[top_index]->lzpos = ZPOS_2;
-               use_hw_layers[ZPOS_2] = 1;
-               available_device_num--;
-       }
+                       composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CURSOR;
+                       cursor_count++;
+                       num_ui_layers--;
+                       continue;
+               case TDM_HWC_WIN_COMPOSITION_DEVICE:
+                       if (set_clients_below) break;
+                       if (num_ui_layers <= 0) break;
+
+                       if (!_nexell_hwc_window_can_set_on_hw_layer(composited_list[i], (i == num_wnds - 1)))
+                               break;
+
+                       if (!_nexell_hwc_window_has_reserved_buffer(composited_list[i])) {
+                               composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE;
+                               break;
+                       }
 
-       /* set the video layer pos and validated_type */
-       if (video_count > 0) {
-               composited_list[bottom_index]->validated_type = TDM_HWC_WIN_COMPOSITION_VIDEO;
-               composited_list[bottom_index]->lzpos = ZPOS_0;
-               use_hw_layers[ZPOS_0] = 1;
-               available_device_num--;
+                       composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_DEVICE;
+                       composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE;
+                       device_count++;
+                       num_ui_layers--;
+                       continue;
+               default:
+                       break;
+               }
+
+               composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
+               client_count++;
+               set_clients_below = 1;
        }
 
-       /* check if target_window is needed */
+       /* 2. check need target window and set ui_lzpos top and bottom */
+       num_ui_layers = NUM_UI_LAYERS;
        if (client_count > 0) {
                hwc_data->need_target_window = 1;
-               use_hw_layers[ZPOS_1] = 1; // target_window must set to ZPOS_1 because it is primary layer.
-               available_device_num--;
+               hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom;
+               ui_lzpos_bottom++;
+               num_ui_layers--;
        }
 
-       /* set all client types when the number of devide types is over than available device_num */
-       if (available_device_num <= 0)
-               goto set_clients_below;
+       if (num_ui_layers > (device_count + cursor_count))
+               ui_lzpos_top = ui_lzpos_bottom + device_count + cursor_count - 1;
 
-       int lzpos = -1;
-       int j;
+       /* 3. set lzpos and modify validate_type with target_window */
        for (i = 0; i < num_wnds; i++) {
-               if (composited_list[i]->client_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
+               switch (composited_list[i]->validated_type) {
+               case TDM_HWC_WIN_COMPOSITION_VIDEO:
+                       composited_list[i]->lzpos = ZPOS_VIDEO1;
                        continue;
-               if (composited_list[i]->client_type == TDM_HWC_WIN_COMPOSITION_CLIENT)
-                       goto set_clients_below;
-               if (composited_list[i]->client_type == TDM_HWC_WIN_COMPOSITION_VIDEO)
-                       break;
-
-               /* set clients below when nexell can not set the window to the hw layer */
-               if (!_nexell_hwc_window_can_set_on_hw_layer(composited_list[i]))
-                       goto set_clients_below;
-
-               //lzpos = _nexell_hwc_window_get_lzpos(composited_list[i]);
-               //if (lzpos == -1) break;
-
-               for (j = ZPOS_2; j >= ZPOS_0; j--) {
-                       if (use_hw_layers[j]) continue;
-                       lzpos = j;
-                       break;
-               }
-               /* check no available hw_layer */
-               if (lzpos == -1) break;
+               case TDM_HWC_WIN_COMPOSITION_CURSOR:
+               case TDM_HWC_WIN_COMPOSITION_DEVICE:
+                       if (num_ui_layers <= 0) break;
 
-               /* set clients below when the hwc_window does not have the reserved buffer */
-               if (!_nexell_hwc_window_has_reserved_buffer(composited_list[i]))
-               {
-                       /* set the buffer_queue constraint */
-                       composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE;
-                       composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
-                       composited_list[i]->lzpos = -1;
-                       composited_list[i]->lzpos_queue = lzpos;
-                       hwc_data->need_target_window = 1;
-                       TDM_DBG(" NO reserved_buffer.(%s) Request acquire_buffer_queue(lzpos_queue:%d) for SCANOUT Buffer.", composited_list[i]->name, lzpos);
+                       composited_list[i]->lzpos = ui_lzpos_top;
+                       composited_list[i]->lzpos_queue = ui_lzpos_top;
+                       ui_lzpos_top--;
+                       num_ui_layers--;
+                       continue;
+               default:
                        break;
                }
 
-               /* set the constraint_buffer_queue, validated_type, lzpos, lqueue of the UI layer */
-               composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE;
-               composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_DEVICE;
-               composited_list[i]->lzpos = lzpos;
-               composited_list[i]->lzpos_queue = lzpos;
-               use_hw_layers[lzpos] = 1;
-               TDM_DBG("YES reserved_buffer.(%s) Set the DEVICE_TYPE.", composited_list[i]->name);
-       }
-
-set_clients_below:
-       for (i = 0; i < num_wnds; i++) {
-               if (composited_list[i]->validated_type != TDM_HWC_WIN_COMPOSITION_NONE)
-                       continue;
-
-               composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_NONE;
                composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
-               composited_list[i]->lzpos = -1;
-               composited_list[i]->lzpos_queue = -1;
 
-               if (!hwc_data->need_target_window) {
-                       hwc_data->need_target_window = 1;
-                       hwc_data->target_hwc_window->lzpos = ZPOS_1;
-                       hwc_data->target_hwc_window->lzpos_queue = ZPOS_1;
+               if (composited_list[i]->constraints == TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE) {
+                       if (i == num_wnds - 1) //set target window queue zpos
+                               composited_list[i]->lzpos_queue = ui_lzpos_top;
+                       else if(num_ui_layers > 0)
+                               composited_list[i]->lzpos_queue = ui_lzpos_top + 1;
+                       else
+                               composited_list[i]->constraints = TDM_HWC_WIN_CONSTRAINT_NONE;
                }
        }
 }
@@ -619,19 +587,11 @@ nexell_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
        tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_data->target_hwc_window, error);
        RETURN_VAL_IF_FAIL(tqueue, NULL);
 
-       if (error) {
+       hwc_data->ui_buffer_queue[ZPOS_1].tqueue = tqueue;
+       hwc_data->ui_buffer_queue[ZPOS_1].ref_cnt = 1;
+
+       if (error)
                *error = TDM_ERROR_NONE;
-               /* reference the target_buffer queue */
-               hwc_data->ui_buffer_queue[ZPOS_1].tqueue = tqueue;
-               hwc_data->ui_buffer_queue[ZPOS_1].ref_cnt = 1;
-
-               for (int i = NUM_LAYERS-1; i >= 0; i--) {
-                       TDM_ERR("[%d]: lzpos_queue:%d tqueue:%p, ref_cnt:%d",
-                                       i, i,
-                                       hwc_data->ui_buffer_queue[i].tqueue,
-                                       hwc_data->ui_buffer_queue[i].ref_cnt);
-               }
-       }
 
        return tqueue;
 }
@@ -666,7 +626,7 @@ nexell_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num
        output_data = hwc_data->output_data;
        RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
 
-       TDM_INFO(" ==============Validate=================================");
+       TDM_DBG(" ==============Validate=================================");
 
        /* adapt policy */
        _nexell_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
@@ -743,7 +703,7 @@ nexell_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
        output_data = hwc_data->output_data;
        RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
 
-       TDM_INFO(" ==============COMMIT=================================");
+       TDM_DBG(" ==============COMMIT=================================");
 
        ret = nexell_output_commit(output_data, sync, user_data);
        RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
index 6ab54a98bec945f7c5a576da0246a7e757d286da..d1736ad6303996aaeec9e9d6998208ea71137648 100644 (file)
@@ -11,6 +11,7 @@ nexell_hwc_window_acquire_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *er
        tdm_nexell_hwc_data *hwc_data = NULL;
        tdm_nexell_hwc_window_data *hwc_window_data = NULL;
        tbm_surface_queue_h tqueue = NULL;
+       int width, height;
 
        if (error)
                *error = TDM_ERROR_INVALID_PARAMETER;
@@ -24,25 +25,41 @@ nexell_hwc_window_acquire_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *er
        if (error)
                *error = TDM_ERROR_NONE;
 
+       if ((hwc_window_data->lzpos_queue < 0) || (hwc_window_data->lzpos_queue > NUM_LAYERS)) {
+               TDM_ERR("invliad hwc_window:%p lzpos_queue:%d", hwc_window_data, hwc_window_data->lzpos);
+               if (error)
+                       *error = TDM_ERROR_OPERATION_FAILED;
+
+               return NULL;
+       }
+
        if (hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue) {
-               /* reference the ui_buffer queue */
                tqueue = hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue;
                hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++;
-               TDM_ERR(" Acquire BUFFER_QUEUE[reference]: lzpos_queue:%d tqueue:%p ref_cnt:%d",
-                               hwc_window_data->lzpos_queue,
-                               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue,
-                               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt);
        } else {
-               /* create a ui_buffer_queue */
-               tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_window_data, error);
-               RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
+               tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_window, error);
+               if (*error != TDM_ERROR_NONE) {
+                       TDM_ERR("fail to create buffer queue");
+                       return NULL;
+               }
 
                hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue = tqueue;
-               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt = 1;
-               TDM_ERR(" Acquire BUFFER_QUEUE[create]: lzpos_queue:%d tqueue:%p ref_cnt:%d",
-                               hwc_window_data->lzpos_queue,
-                               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue,
-                               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt);
+               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++;
+       }
+
+       // target buffer queue can't be reset
+       if (hwc_window_data->lzpos_queue != ZPOS_1) {
+               width = tbm_surface_queue_get_width(tqueue);
+               height = tbm_surface_queue_get_height(tqueue);
+
+               if ((hwc_window_data->info.src_config.pos.w != width) ||
+                       (hwc_window_data->info.src_config.pos.h != height))
+                       {
+                               tbm_surface_queue_reset(tqueue,
+                                                       hwc_window_data->info.src_config.pos.w,
+                                                       hwc_window_data->info.src_config.pos.h,
+                                                       hwc_window_data->info.src_config.format);
+                       }
        }
 
        return tqueue;
@@ -53,6 +70,7 @@ nexell_hwc_window_release_buffer_queue(tdm_hwc_window *hwc_window, tbm_surface_q
 {
        tdm_nexell_hwc_data *hwc_data = NULL;
        tdm_nexell_hwc_window_data *hwc_window_data = NULL;
+       int i;
 
        hwc_window_data = (tdm_nexell_hwc_window_data *)hwc_window;
        RETURN_IF_FAIL(hwc_window_data != NULL);
@@ -60,20 +78,17 @@ nexell_hwc_window_release_buffer_queue(tdm_hwc_window *hwc_window, tbm_surface_q
        hwc_data = hwc_window_data->hwc_data;
        RETURN_IF_FAIL(hwc_data != NULL);
 
-       if (hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt > 0) {
-               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt--;
-
-               TDM_ERR(" Release BUFFER_QUEUE[dereference]: lzpos_queue:%d tqueue:%p ref_cnt:%d",
-                               hwc_window_data->lzpos_queue,
-                               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue,
-                               hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt);
+       for (i = 0; i < NUM_LAYERS; i++) {
+               if (hwc_data->ui_buffer_queue[i].tqueue == queue) {
+                       if (hwc_data->ui_buffer_queue[i].ref_cnt > 0)
+                               hwc_data->ui_buffer_queue[i].ref_cnt--;
 
-               /* destroy a ui_buffer_queue when ref_cnt is 0 */
-               if (hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt == 0) {
-                       TDM_ERR(" Release BUFFER_QUEUE", "destroy buffer_queue(%p)", hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue);
+                       if ((i != ZPOS_1) && (hwc_data->ui_buffer_queue[i].ref_cnt == 0)) {
+                               tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->ui_buffer_queue[i].tqueue);
+                               hwc_data->ui_buffer_queue[i].tqueue = NULL;
+                       }
 
-                       tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue);
-                       hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].tqueue = NULL;
+                       break;
                }
        }
 }
index 2cba880210c5ab0dfee10061c64270b794c8ab04..9a0f5cd794ba2716ebfc286109861eeda3995509 100644 (file)
@@ -112,6 +112,7 @@ struct _tdm_nexell_data
 
 #if LIBDRM_MAJOR_VERSION >= 2 && LIBDRM_MINOR_VERSION >= 4  && LIBDRM_MICRO_VERSION >= 47
        int has_universal_plane;
+       int has_atomic;
 #endif
 
 #if HAVE_UDEV
@@ -150,6 +151,23 @@ struct _tdm_nexell_event_data {
        void *user_data;
 };
 
+struct display_properties_ids {
+       uint32_t connector_crtc_id;
+       uint32_t crtc_mode_id;
+       uint32_t crtc_active;
+       uint32_t plane_fb_id;
+       uint32_t plane_crtc_id;
+       uint32_t plane_src_x;
+       uint32_t plane_src_y;
+       uint32_t plane_src_w;
+       uint32_t plane_src_h;
+       uint32_t plane_crtc_x;
+       uint32_t plane_crtc_y;
+       uint32_t plane_crtc_w;
+       uint32_t plane_crtc_h;
+       uint32_t plane_zpos;
+};
+
 struct _tdm_nexell_output_data {
        struct list_head link;
 
@@ -179,9 +197,16 @@ struct _tdm_nexell_output_data {
        int mode_changed;
        const tdm_output_mode *current_mode;
 
-       tbm_surface_h crtc_buffer;
+       struct display_properties_ids props;
+
        int crtc_enabled;
-       unsigned int crtc_fb_id;
+
+       /* atomic prop ids*/
+       struct {
+               uint32_t crtc_id;
+               uint32_t crtc_mode_id;
+               uint32_t crtc_active;
+       } atomic_props_ids;
 
        /* hwc */
        int hwc_enable;
@@ -204,6 +229,21 @@ struct _tdm_nexell_layer_data {
 
        tdm_nexell_display_buffer *display_buffer;
        int display_buffer_changed;
+
+       /* atomic prop ids*/
+       struct {
+               uint32_t fb_id;
+               uint32_t crtc_id;
+               uint32_t src_x;
+               uint32_t src_y;
+               uint32_t src_w;
+               uint32_t src_h;
+               uint32_t crtc_x;
+               uint32_t crtc_y;
+               uint32_t crtc_w;
+               uint32_t crtc_h;
+               uint32_t zpos;
+       } atomic_props_ids;
 };
 
 struct _tdm_nexell_hwc_data {
@@ -252,7 +292,6 @@ struct _tdm_nexell_hwc_window_data {
        int cursor_img_refresh;
 
        int constraints;
-       tbm_surface_queue_h tqueue;
 };
 
 #endif /* _TDM_NEXELL_TYPES_H_ */