#include "tdm_vc4.h"
-static int tdm_vc4_buffer_key;
-#define TDM_VC4_BUFFER_KEY ((unsigned long)&tdm_vc4_buffer_key)
-
#define MIN_WIDTH 2
#define MODE_WIDTH_LIMIT 1280
return TDM_ERROR_NONE;
}
-static void
-_tdm_vc4_display_buffer_destroy(void *user_data)
-{
- tdm_vc4_display_buffer *display_buffer = (tdm_vc4_display_buffer *)user_data;
-
- if (display_buffer->fb_id > 0) {
- int ret = drmModeRmFB(display_buffer->vc4_data->drm_fd, display_buffer->fb_id);
- if (ret < 0) {
- TDM_ERR("rm fb failed");
- return;
- }
- 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);
-}
-
-static tdm_vc4_display_buffer *
-_tdm_vc4_display_get_buffer(tdm_vc4_data *vc4_data, tbm_surface_h buffer)
-{
- tdm_vc4_display_buffer *display_buffer = NULL;
-
- if (!tbm_surface_internal_get_user_data(buffer, TDM_VC4_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_vc4_display_buffer));
- RETURN_VAL_IF_FAIL(display_buffer != NULL, NULL);
-
- if (!tbm_surface_internal_add_user_data(buffer, TDM_VC4_BUFFER_KEY, _tdm_vc4_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_VC4_BUFFER_KEY, display_buffer)) {
- TDM_ERR("FAIL to set user_data for surface %p", buffer);
- tbm_surface_internal_delete_user_data(buffer, TDM_VC4_BUFFER_KEY);
- free(display_buffer);
- return NULL;
- }
-
- display_buffer->vc4_data = vc4_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]);
-
- ret = drmModeAddFB2(vc4_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("vc4_data->drm_fd : %d, display_buffer->fb_id:%u", vc4_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;
-}
-
static drmModeModeInfoPtr
_tdm_vc4_display_get_mode(tdm_vc4_output_data *output_data)
{
return TDM_ERROR_NONE;
}
+static tdm_vc4_display_buffer *
+_tdm_vc4_display_find_buffer(tdm_vc4_data *vc4_data, tbm_surface_h buffer)
+{
+ tdm_vc4_display_buffer *display_buffer = NULL;
+
+ LIST_FOR_EACH_ENTRY(display_buffer, &vc4_data->buffer_list, link) {
+ if (display_buffer->buffer == buffer)
+ return display_buffer;
+ }
+
+ return NULL;
+}
+
+static void
+_tdm_vc4_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
+{
+ tdm_vc4_data *vc4_data;
+ tdm_vc4_display_buffer *display_buffer;
+ char buf[256] = {0,};
+ char *ret_tmp;
+
+ if (!user_data) {
+ TDM_ERR("no user_data");
+ return;
+ }
+ if (!buffer) {
+ TDM_ERR("no buffer");
+ return;
+ }
+
+ vc4_data = (tdm_vc4_data *) user_data;
+
+ display_buffer = _tdm_vc4_display_find_buffer(vc4_data, buffer);
+ if (!display_buffer) {
+ TDM_ERR("no display_buffer");
+ return;
+ }
+
+ if (display_buffer->fb_id > 0) {
+ if (drmModeRmFB(vc4_data->drm_fd, display_buffer->fb_id) < 0) {
+ ret_tmp = strerror_r(errno, buf, sizeof(buf));
+ TDM_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
+ }
+ }
+
+ TDM_DBG("destroy buffer fd:%d", display_buffer->fds[0]);
+
+ LIST_DEL(&display_buffer->link);
+ free(display_buffer);
+}
+
+void
+tdm_vc4_data_destroy_buffer_list(tdm_vc4_data *vc4_data)
+{
+ tdm_vc4_display_buffer *b = NULL, *bb = NULL;
+
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &vc4_data->buffer_list, link) {
+ tdm_buffer_remove_destroy_handler(b->buffer, _tdm_vc4_display_cb_destroy_buffer, vc4_data);
+ _tdm_vc4_display_cb_destroy_buffer(b->buffer, vc4_data);
+ }
+}
+
tdm_error
vc4_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
{
tdm_vc4_layer_data *layer_data = layer;
tdm_vc4_data *vc4_data;
tdm_vc4_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);
- vc4_data = layer_data->vc4_data;
+ TDM_DBG("layer[%p]zpos[%d]", layer, layer_data->zpos);
- display_buffer = _tdm_vc4_display_get_buffer(vc4_data, buffer);
+ vc4_data = layer_data->vc4_data;
+ display_buffer = _tdm_vc4_display_find_buffer(vc4_data, buffer);
if (!display_buffer) {
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
+ display_buffer = calloc(1, sizeof(tdm_vc4_display_buffer));
+ if (!display_buffer) {
+ TDM_ERR("alloc failed");
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+ display_buffer->buffer = buffer;
- if (layer_data->display_buffer)
- tbm_surface_internal_unref(layer_data->display_buffer->buffer);
+ err = tdm_buffer_add_destroy_handler(buffer, _tdm_vc4_display_cb_destroy_buffer, vc4_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, &vc4_data->buffer_list);
+
+ if (!display_buffer->fb_id) {
+ display_buffer->width = tbm_surface_get_width(buffer);
+ display_buffer->height = tbm_surface_get_height(buffer);
+ display_buffer->format = tbm_surface_get_format(buffer);
+ display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
+ count = tbm_surface_internal_get_num_planes(display_buffer->format);
+ TDM_DBG("set buffer layer(%d): %dx%d %c%c%c%c bo_num:%d plane_num:%d",
+ layer_data->capabilities,
+ display_buffer->width, display_buffer->height,
+ FOURCC_STR(display_buffer->format), display_buffer->count, count);
+
+ for (i = 0; i < display_buffer->count; i++) {
+ tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
+ display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+ display_buffer->fds[i] = tbm_bo_get_handle(bo, TBM_DEVICE_MM).u32; /* ToDo */
+ TDM_DBG(" set buffer layer(%d): bo%d(fd:%d handle:%d)",
+ layer_data->capabilities,
+ i, display_buffer->fds[i], display_buffer->handles[i]);
+ }
+ for (i = 0; i < count; i++) {
+ tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
+ &display_buffer->offsets[i],
+ &display_buffer->pitches[i]);
+ TDM_DBG(" set buffer layer(%d): plane%d(size:%d offset:%d pitch:%d)",
+ layer_data->capabilities,
+ i, display_buffer->size, display_buffer->offsets[i],
+ display_buffer->pitches[i]);
+ }
- layer_data->display_buffer = display_buffer;
- tbm_surface_internal_ref(layer_data->display_buffer->buffer);
+ ret = drmModeAddFB2(vc4_data->drm_fd, display_buffer->width, display_buffer->height,
+ display_buffer->format, display_buffer->handles, display_buffer->pitches,
+ display_buffer->offsets, &display_buffer->fb_id, 0);
+ if (ret < 0) {
+ TDM_ERR("add fb failed: %m");
+ free(display_buffer);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+ TDM_DBG("vc4_data->drm_fd : %d, display_buffer->fb_id:%u", vc4_data->drm_fd,
+ display_buffer->fb_id);
- layer_data->display_buffer_changed = 1;
+ if (IS_RGB(display_buffer->format))
+ display_buffer->width = display_buffer->pitches[0] >> 2;
+ else
+ display_buffer->width = display_buffer->pitches[0];
+ }
+ }
+
+ if (layer_data->display_buffer != display_buffer) {
+ 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;
}