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 {
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)
{
}
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;
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 {
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));
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;
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;
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) {