#include <tdm_helper.h>
#include "tdm_exynos.h"
+static int tdm_exynos_buffer_key;
+#define TDM_EXYNOS_BUFFER_KEY ((unsigned long)&tdm_exynos_buffer_key)
+
static void
-_tdm_exynos_layer_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
+_tdm_exynos_display_buffer_destroy(void *user_data)
{
- tdm_exynos_data *exynos_data;
- tdm_exynos_output_data *output_data = NULL;
- tdm_exynos_layer_data *layer_data = NULL;
- tdm_exynos_display_buffer *display_buffer;
- int ret;
-
- if (!user_data) {
- TDM_ERR("no user_data");
- return;
- }
- if (!buffer) {
- TDM_ERR("no buffer");
- return;
- }
-
- exynos_data = (tdm_exynos_data *)user_data;
-
- display_buffer = tdm_exynos_display_find_buffer(exynos_data, buffer);
- if (!display_buffer) {
- TDM_ERR("no display_buffer");
- return;
- }
- LIST_DEL(&display_buffer->link);
-
- if (exynos_data->hwc_mode) {
- /* pending to free the display buffer when the display buffer is set on the layer */
- LIST_FOR_EACH_ENTRY(output_data, &exynos_data->output_list, link) {
- if (!output_data->hwc_enable) continue;
-
- LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
- if (!layer_data->display_buffer) continue;
- if (layer_data->display_buffer->buffer == buffer && display_buffer->fb_id > 0) {
- TDM_DBG("drmModeRmFB is pending!!! fb_id:%d", display_buffer->fb_id);
- layer_data->pending_free_display_buffer = display_buffer;
- return;
- }
- }
- }
- }
+ tdm_exynos_display_buffer *display_buffer = (tdm_exynos_display_buffer *)user_data;
if (display_buffer->fb_id > 0) {
- ret = drmModeRmFB(exynos_data->drm_fd, display_buffer->fb_id);
+ int ret = drmModeRmFB(display_buffer->exynos_data->drm_fd, display_buffer->fb_id);
if (ret < 0) {
TDM_ERR("rm fb failed");
return;
free(display_buffer);
}
-void
-tdm_exynos_layer_destroy_buffer_list(tdm_exynos_data *exynos_data)
+static tdm_exynos_display_buffer *
+_tdm_exynos_display_get_buffer(tdm_exynos_data *exynos_data, tbm_surface_h buffer)
{
- tdm_exynos_display_buffer *b = NULL, *bb = NULL;
+ tdm_exynos_display_buffer *display_buffer = NULL;
+
+ if (!tbm_surface_internal_get_user_data(buffer, TDM_EXYNOS_BUFFER_KEY, (void **)&display_buffer)) {
+ 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;
+ tbm_bo bo;
+ int i, count, ret;
+
+ display_buffer = calloc(1, sizeof(tdm_exynos_display_buffer));
+ RETURN_VAL_IF_FAIL(display_buffer != NULL, NULL);
+
+ if (!tbm_surface_internal_add_user_data(buffer, TDM_EXYNOS_BUFFER_KEY, _tdm_exynos_display_buffer_destroy)) {
+ TDM_ERR("FAIL to create user_data for surface %p", buffer);
+ free(display_buffer);
+ return NULL;
+ }
+ if (!tbm_surface_internal_set_user_data(buffer, TDM_EXYNOS_BUFFER_KEY, display_buffer)) {
+ TDM_ERR("FAIL to set user_data for surface %p", buffer);
+ tbm_surface_internal_delete_user_data(buffer, TDM_EXYNOS_BUFFER_KEY);
+ free(display_buffer);
+ return NULL;
+ }
+
+ display_buffer->exynos_data = exynos_data;
+ display_buffer->buffer = buffer;
+
+ width = tbm_surface_get_width(buffer);
+ height = tbm_surface_get_height(buffer);
+ format = tbm_surface_get_format(buffer);
+ count = tbm_surface_internal_get_num_planes(format);
+ bo = tbm_surface_internal_get_bo(buffer, 0);
+ handles[0] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+ for (i = 1; i < count; i++)
+ handles[i] = handles[0];
+
+ for (i = 0; i < count; i++)
+ tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
- LIST_FOR_EACH_ENTRY_SAFE(b, bb, &exynos_data->buffer_list, link) {
- tdm_buffer_remove_destroy_handler(b->buffer, _tdm_exynos_layer_cb_destroy_buffer, exynos_data);
- _tdm_exynos_layer_cb_destroy_buffer(b->buffer, exynos_data);
+ ret = drmModeAddFB2(exynos_data->drm_fd, width, height, format,
+ handles, pitches, offsets, &display_buffer->fb_id, 0);
+ if (ret < 0) {
+ TDM_ERR("add fb failed: %m");
+ free(display_buffer);
+ return NULL;
+ }
+ TDM_DBG("exynos_data->drm_fd : %d, display_buffer->fb_id:%u", exynos_data->drm_fd,
+ display_buffer->fb_id);
+
+ if (IS_RGB(format))
+ display_buffer->width = pitches[0] >> 2;
+ else
+ display_buffer->width = pitches[0];
}
+
+ return display_buffer;
}
tdm_error
tdm_exynos_layer_data *layer_data = layer;
tdm_exynos_data *exynos_data;
tdm_exynos_display_buffer *display_buffer;
- tdm_error err = TDM_ERROR_NONE;
- int ret, i, count;
RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
exynos_data = layer_data->exynos_data;
- display_buffer = tdm_exynos_display_find_buffer(exynos_data, buffer);
+ display_buffer = _tdm_exynos_display_get_buffer(exynos_data, buffer);
if (!display_buffer) {
- display_buffer = calloc(1, sizeof(tdm_exynos_display_buffer));
- if (!display_buffer) {
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
- display_buffer->buffer = buffer;
-
- err = tdm_buffer_add_destroy_handler(buffer, _tdm_exynos_layer_cb_destroy_buffer, exynos_data);
- if (err != TDM_ERROR_NONE) {
- TDM_ERR("add destroy handler fail");
- free(display_buffer);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- LIST_ADDTAIL(&display_buffer->link, &exynos_data->buffer_list);
+ TDM_ERR("alloc failed");
+ return TDM_ERROR_OUT_OF_MEMORY;
}
- if (display_buffer->fb_id == 0) {
- 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;
-
- 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)",
- exynos_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(exynos_data->drm_fd, width, height, format,
- handles, pitches, offsets, &display_buffer->fb_id, 0);
- if (ret < 0) {
- TDM_ERR("add fb failed: %m");
- return TDM_ERROR_OPERATION_FAILED;
- }
- TDM_DBG("exynos_data->drm_fd: %d, plane_id:%u, zpos(%d) display_buffer->fb_id:%u",
- exynos_data->drm_fd, layer_data->plane_id, layer_data->zpos, display_buffer->fb_id);
-
- if (IS_RGB(format))
- display_buffer->width = pitches[0] >> 2;
- else
- display_buffer->width = pitches[0];
- }
+ if (layer_data->display_buffer)
+ tbm_surface_internal_unref(layer_data->display_buffer->buffer);
layer_data->display_buffer = display_buffer;
+ tbm_surface_internal_ref(layer_data->display_buffer->buffer);
+
layer_data->display_buffer_changed = 1;
return TDM_ERROR_NONE;
RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
- layer_data->display_buffer = NULL;
+ if (!(layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) {
+ tbm_surface_internal_unref(layer_data->display_buffer->buffer);
+ layer_data->display_buffer = NULL;
+ }
layer_data->display_buffer_changed = 1;
return TDM_ERROR_NONE;
info->dst_pos = dst_pos;
}
-static int
-_tdm_exynos_output_free_display_buffer(tdm_exynos_data *exynos_data, tdm_exynos_display_buffer *display_buffer)
-{
- int ret;
-
- if (display_buffer->fb_id > 0) {
- ret = drmModeRmFB(exynos_data->drm_fd, display_buffer->fb_id);
- if (ret < 0) {
- TDM_ERR("rm fb failed");
- return 0;
- }
- TDM_DBG("drmModeRmFB success!!! fb_id:%d", display_buffer->fb_id);
- } else
- TDM_DBG("drmModeRmFB not called fb_id:%d", display_buffer->fb_id);
-
- free(display_buffer);
-
- return 1;
-}
-
static tdm_error
_tdm_exynos_output_commit_primary_layer(tdm_exynos_layer_data *layer_data,
void *user_data, int *do_waitvblank)
*do_waitvblank = 1;
- /* free pending display buffer */
- if (layer_data->pending_free_display_buffer) {
- _tdm_exynos_output_free_display_buffer(output_data->exynos_data, layer_data->pending_free_display_buffer);
- layer_data->pending_free_display_buffer = NULL;
- }
-
return TDM_ERROR_NONE;
} else if (layer_data->display_buffer_changed) {
layer_data->display_buffer_changed = 0;
- if (!layer_data->display_buffer) {
- TDM_DBG("SetCrtc: drm_fd(%d) crtc_id(%u) off",
- exynos_data->drm_fd, output_data->crtc_id);
-
- if (drmModeSetCrtc(exynos_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_exynos_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_CONNECTED);
-
- *do_waitvblank = 0;
- } else {
+ if (layer_data->display_buffer) {
tbm_surface_info_s info;
int ret;
tdm_exynos_event_data *event_data = calloc(1, sizeof(tdm_exynos_event_data));
return TDM_ERROR_OPERATION_FAILED;
}
*do_waitvblank = 0;
-
- /* free pending display buffer */
- if (layer_data->pending_free_display_buffer) {
- _tdm_exynos_output_free_display_buffer(output_data->exynos_data, layer_data->pending_free_display_buffer);
- layer_data->pending_free_display_buffer = NULL;
- }
+ } else {
+ /* to call a user commit handler whenever committed */
+ *do_waitvblank = 1;
}
}
return TDM_ERROR_OPERATION_FAILED;
}
- /* free pending display buffer */
- if (layer_data->pending_free_display_buffer) {
- _tdm_exynos_output_free_display_buffer(output_data->exynos_data, layer_data->pending_free_display_buffer);
- layer_data->pending_free_display_buffer = NULL;
- }
-
return TDM_ERROR_NONE;
}