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)
}
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) {
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;
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 {
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);
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)
{
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++)
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;
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;
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;
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));
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)
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");
*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);
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,
}
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;
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;
}
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);
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;
/* 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;
}
}
}
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;
}
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);
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);