#include "tdm_nexell.h"
#include "tdm_nexell_pp.h"
-static int tdm_nexell_buffer_key;
-#define TDM_NEXELL_BUFFER_KEY ((unsigned long)&tdm_nexell_buffer_key)
-
#define MIN_WIDTH 32
-typedef struct _tdm_nexell_output_data tdm_nexell_output_data;
-typedef struct _tdm_nexell_layer_data tdm_nexell_layer_data;
-typedef struct _tdm_nexell_event_data tdm_nexell_event_data;
-
-typedef enum {
- TDM_NEXELL_EVENT_TYPE_WAIT,
- TDM_NEXELL_EVENT_TYPE_COMMIT,
- TDM_NEXELL_EVENT_TYPE_PAGEFLIP,
-} tdm_nexell_event_type;
-
-typedef struct _tdm_nexell_display_buffer {
- tdm_nexell_data *nexell_data;
- unsigned int fb_id;
- tbm_surface_h buffer;
- int width;
-} tdm_nexell_display_buffer;
-
-struct _tdm_nexell_event_data {
- tdm_nexell_event_type type;
- tdm_nexell_output_data *output_data;
- void *user_data;
-};
-
-struct _tdm_nexell_output_data {
- struct list_head link;
-
- /* data which are fixed at initializing */
- tdm_nexell_data *nexell_data;
- uint32_t connector_id;
- uint32_t encoder_id;
- uint32_t crtc_id;
- uint32_t pipe;
- uint32_t dpms_prop_id;
- int count_modes;
- drmModeModeInfoPtr drm_modes;
- tdm_output_mode *output_modes;
- tdm_output_type connector_type;
- unsigned int connector_type_id;
- struct list_head layer_list;
- tdm_nexell_layer_data *primary_layer;
-
- /* not fixed data below */
- tdm_output_vblank_handler vblank_func;
- tdm_output_commit_handler commit_func;
-
- tdm_output_conn_status status;
- tdm_output_status_handler status_func;
- void *status_user_data;
-
- int mode_changed;
- const tdm_output_mode *current_mode;
-};
-
-struct _tdm_nexell_layer_data {
- struct list_head link;
-
- /* data which are fixed at initializing */
- tdm_nexell_data *nexell_data;
- tdm_nexell_output_data *output_data;
- uint32_t plane_id;
- tdm_layer_capability capabilities;
- int zpos;
-
- /* not fixed data below */
- tdm_info_layer info;
- int info_changed;
-
- tdm_nexell_display_buffer *display_buffer;
- int display_buffer_changed;
-};
-
-static void
-_tdm_nexell_display_buffer_destroy(void *user_data)
-{
- tdm_nexell_display_buffer *display_buffer = (tdm_nexell_display_buffer *)user_data;
-
- if (display_buffer->fb_id > 0) {
- int ret = drmModeRmFB(display_buffer->nexell_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_nexell_display_buffer *
-_tdm_nexell_display_get_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer)
-{
- tdm_nexell_display_buffer *display_buffer = NULL;
-
- if (!tbm_surface_internal_get_user_data(buffer, TDM_NEXELL_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_nexell_display_buffer));
- RETURN_VAL_IF_FAIL(display_buffer != NULL, NULL);
-
- if (!tbm_surface_internal_add_user_data(buffer, TDM_NEXELL_BUFFER_KEY, _tdm_nexell_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_NEXELL_BUFFER_KEY, display_buffer)) {
- TDM_ERR("FAIL to set user_data for surface %p", buffer);
- tbm_surface_internal_delete_user_data(buffer, TDM_NEXELL_BUFFER_KEY);
- free(display_buffer);
- return NULL;
- }
-
- display_buffer->nexell_data = nexell_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(nexell_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("nexell_data->drm_fd : %d, display_buffer->fb_id:%u", nexell_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_nexell_display_get_mode(tdm_nexell_output_data *output_data)
{
}
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_commit_primary_layer(tdm_nexell_layer_data *layer_data,
- void *user_data, int *do_waitvblank)
+_tdm_nexell_display_set_crtc(tdm_nexell_data *nexell_data, tdm_nexell_output_data *output_data, int set)
{
- tdm_nexell_data *nexell_data = layer_data->nexell_data;
- tdm_nexell_output_data *output_data = layer_data->output_data;
+ int ret;
- if (output_data->mode_changed && layer_data->display_buffer_changed) {
- drmModeModeInfoPtr mode;
+ output_data->mode_changed = 0;
- if (!layer_data->display_buffer) {
- TDM_ERR("primary layer should have a buffer for modestting");
- return TDM_ERROR_BAD_REQUEST;
- }
+ if (set) {
+ tbm_surface_h buffer = NULL;
+ tbm_surface_info_s info;
+ drmModeModeInfoPtr mode;
+ unsigned int fb_id = 0;
- output_data->mode_changed = 0;
- layer_data->display_buffer_changed = 0;
- layer_data->info_changed = 0;
+ if (!output_data->current_mode)
+ return TDM_ERROR_OPERATION_FAILED;
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,
- layer_data->display_buffer->fb_id, 0, 0,
- &output_data->connector_id, 1, mode)) {
+ 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);
- *do_waitvblank = 1;
- return TDM_ERROR_NONE;
- } else if (layer_data->display_buffer_changed) {
- layer_data->display_buffer_changed = 0;
+ 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);
+ }
- if (layer_data->display_buffer) {
- tdm_nexell_event_data *event_data = calloc(1, sizeof(tdm_nexell_event_data));
+ 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 (!event_data) {
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
+ 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;
+ }
- event_data->type = TDM_NEXELL_EVENT_TYPE_PAGEFLIP;
- 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;
+ 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);
}
- }else {
- /* to call a user commit handler whenever committed */
- *do_waitvblank = 1;
+ output_data->crtc_buffer = NULL;
+ output_data->crtc_fb_id = 0;
}
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 {
drmModeFreeCrtc(crtc);
}
+ // reset the changed flags
layer_data->display_buffer_changed = 0;
layer_data->info_changed = 0;
- if (!layer_data->display_buffer) {
+ if (layer_data->display_buffer) { // set plane
+ /* Source values are 16.16 fixed point */
+ fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
+ fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
+ fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
+ fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
+
+ TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
+ layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
+ layer_data->display_buffer->fb_id,
+ layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
+ layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
+ layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
+ layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
+
+ if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
+ output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
+ layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
+ layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
+ fx, fy, fw, fh) < 0) {
+ TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+ } else { // unset plane
+ TDM_DBG("plane(%d) crtc(%d) pos(%d) : unset plane\n",
+ layer_data->plane_id, output_data->crtc_id, layer_data->zpos);
+
if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
output_data->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
TDM_ERR("unset plane(%d) filed: %m", layer_data->plane_id);
-
- return TDM_ERROR_NONE;
}
- /* Source values are 16.16 fixed point */
- fx = ((unsigned int)layer_data->info.src_config.pos.x) << 16;
- fy = ((unsigned int)layer_data->info.src_config.pos.y) << 16;
- fw = ((unsigned int)layer_data->info.src_config.pos.w) << 16;
- fh = ((unsigned int)layer_data->info.src_config.pos.h) << 16;
-
- if (drmModeSetPlane(nexell_data->drm_fd, layer_data->plane_id,
- output_data->crtc_id, layer_data->display_buffer->fb_id, 0,
- layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
- layer_data->info.dst_pos.w, layer_data->info.dst_pos.h,
- fx, fy, fw, fh) < 0) {
- TDM_ERR("set plane(%d) failed: %m", layer_data->plane_id);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- TDM_DBG("plane(%d) crtc(%d) pos(%d) on: fb(%d,[%d,%d %dx%d]=>[%d,%d %dx%d])\n",
- layer_data->plane_id, output_data->crtc_id, layer_data->zpos,
- layer_data->display_buffer->fb_id,
- layer_data->info.src_config.pos.x, layer_data->info.src_config.pos.y,
- layer_data->info.src_config.pos.w, layer_data->info.src_config.pos.h,
- layer_data->info.dst_pos.x, layer_data->info.dst_pos.y,
- layer_data->info.dst_pos.w, layer_data->info.dst_pos.h);
-
return TDM_ERROR_NONE;
}
{
tdm_nexell_event_data *event_data = user_data;
tdm_nexell_output_data *output_data;
+ tdm_nexell_hwc_data *hwc_data;
if (!event_data) {
TDM_ERR("no event data");
event_data->user_data);
break;
case TDM_NEXELL_EVENT_TYPE_COMMIT:
- if (output_data->commit_func)
- output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
- event_data->user_data);
+ if (output_data->hwc_enable) {
+ hwc_data = output_data->hwc_data;
+ if (!hwc_data) {
+ TDM_ERR("no hwc_data");
+ 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);
+ } else {
+ if (output_data->commit_func)
+ output_data->commit_func(output_data, sequence, tv_sec, tv_usec,
+ event_data->user_data);
+ }
break;
default:
break;
TDM_LAYER_CAPABILITY_GRAPHIC |
TDM_LAYER_CAPABILITY_SCANOUT;
layer_data->zpos = cpos_next++;
+ TDM_INFO("layer_data(%p): cursor zpos(%d)", layer_data, layer_data->zpos);
} else if (types[i] == DRM_PLANE_TYPE_OVERLAY) {
if (opos_next == 0) {
layer_data->capabilities = TDM_LAYER_CAPABILITY_OVERLAY |
} else {
layer_data->zpos = opos_next++;
}
+
+ TDM_INFO("layer_data(%p): overlay zpos(%d)", layer_data, layer_data->zpos);
} else if (types[i] == DRM_PLANE_TYPE_PRIMARY) {
layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY |
TDM_LAYER_CAPABILITY_GRAPHIC |
TDM_LAYER_CAPABILITY_SCANOUT;
layer_data->zpos = 1;
output_data->primary_layer = layer_data;
+
+ TDM_INFO("layer_data(%p): primary zpos(%d)", layer_data, layer_data->zpos);
} else {
free(layer_data);
continue;
tdm_nexell_display_destroy_output_list(tdm_nexell_data *nexell_data)
{
tdm_nexell_output_data *o = NULL, *oo = NULL;
+ tdm_nexell_hwc_data *hwc_data = NULL;
if (LIST_IS_EMPTY(&nexell_data->output_list))
return;
LIST_FOR_EACH_ENTRY_SAFE(o, oo, &nexell_data->output_list, link) {
+ hwc_data = o->hwc_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;
&output_data->output_modes[j]);
}
+ if (nexell_data->hwc_mode)
+ output_data->hwc_enable = 1;
+
LIST_ADDTAIL(&output_data->link, &nexell_data->output_list);
TDM_DBG("output_data(%p) connector_id(%d:%d:%d-%d) encoder_id(%d) crtc_id(%d) pipe(%d) dpms_id(%d)",
drmModeFreeProperty(prop);
}
+ if (output_data->hwc_enable) {
+ caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
+ }
+
drmModeFreeObjectProperties(props);
drmModeFreeCrtc(crtc);
drmModeFreeConnector(connector);
LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
(*count)++;
+ if (output_data->hwc_enable) {
+ *count = 0;
+ ret = TDM_ERROR_NONE;
+ goto failed_get;
+ }
+
if (*count == 0) {
ret = TDM_ERROR_NONE;
goto failed_get;
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,
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));
nexell_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
{
tdm_nexell_output_data *output_data = output;
+ tdm_error ret = TDM_ERROR_NONE;
RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
+ /* create or replace the target_window when the output mode is set */
+ if (output_data->hwc_enable) {
+ ret = nexell_hwc_target_window_set_info(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("set info target hwc window failed (%d)", ret);
+ return ret;
+ }
+ }
+
output_data->current_mode = mode;
output_data->mode_changed = 1;
+ TDM_INFO("Set the output mode: %s, %d, %d, %d, %d, %d",
+ mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
+
return TDM_ERROR_NONE;
}
return TDM_ERROR_NONE;
}
+tdm_hwc *
+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;
+
+ if (!output_data) {
+ TDM_ERR("invalid params");
+ if (error)
+ *error = TDM_ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ if (output_data->hwc_data) {
+ TDM_INFO("hwc_data already exists");
+ if (error)
+ *error = TDM_ERROR_NONE;
+ return output_data->hwc_data;
+ }
+
+ hwc_data = calloc(1, sizeof(tdm_nexell_hwc_data));
+ if (!hwc_data) {
+ TDM_ERR("alloc failed");
+ if (error)
+ *error = TDM_ERROR_OUT_OF_MEMORY;
+ return NULL;
+ }
+ for (int 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->output_data = output_data;
+
+ LIST_INITHEAD(&hwc_data->hwc_window_list);
+
+ output_data->hwc_data = hwc_data;
+
+ ret = nexell_hwc_initailize_target_window(output_data->hwc_data);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("create target hwc window failed (%d)", ret);
+ free(hwc_data);
+ if (error)
+ *error = ret;
+ return NULL;
+ }
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return hwc_data;
+}
+
tdm_error
nexell_output_set_status_handler(tdm_output *output,
tdm_output_status_handler func,
return TDM_ERROR_NONE;
}
+static tdm_nexell_display_buffer *
+_tdm_nexell_display_find_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer)
+{
+ tdm_nexell_display_buffer *display_buffer = NULL;
+
+ LIST_FOR_EACH_ENTRY(display_buffer, &nexell_data->buffer_list, link) {
+ if (display_buffer->buffer == buffer)
+ return display_buffer;
+ }
+
+ return NULL;
+}
+
+static void
+_tdm_nexell_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
+{
+ tdm_nexell_data *nexell_data;
+ tdm_nexell_display_buffer *display_buffer;
+ tdm_nexell_layer_data *layer_data = NULL;
+ tdm_nexell_output_data *output_data = NULL;
+ char buf[256] = {0,};
+ char *ret_tmp;
+
+ if (!user_data) {
+ TDM_ERR("no user_data");
+ return;
+ }
+ if (!buffer) {
+ TDM_ERR("no buffer");
+ return;
+ }
+
+ nexell_data = (tdm_nexell_data *) user_data;
+
+ display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer);
+ if (!display_buffer) {
+ TDM_ERR("no display_buffer");
+ return;
+ }
+
+ LIST_FOR_EACH_ENTRY(output_data, &nexell_data->output_list, link) {
+ LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
+ if (display_buffer == layer_data->display_buffer)
+ layer_data->display_buffer = NULL;
+ }
+ }
+
+ if (display_buffer->fb_id > 0) {
+ if (drmModeRmFB(nexell_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:%p", display_buffer->buffer);
+
+ LIST_DEL(&display_buffer->link);
+ free(display_buffer);
+}
+
+static tdm_nexell_display_buffer *
+_tdm_nexell_display_create_buffer(tdm_nexell_data *nexell_data, tbm_surface_h buffer, tdm_error *err)
+{
+ tdm_nexell_display_buffer *display_buffer = NULL;
+ tdm_error res = TDM_ERROR_NONE;
+ int count, i, ret;
+
+ display_buffer = calloc(1, sizeof(tdm_nexell_display_buffer));
+ if (!display_buffer) {
+ TDM_ERR("alloc failed");
+ if (err)
+ *err = TDM_ERROR_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ display_buffer->buffer = buffer;
+
+ res = tdm_buffer_add_destroy_handler(buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data);
+ if (res != TDM_ERROR_NONE) {
+ TDM_ERR("add destroy handler fail");
+ free(display_buffer);
+ if (err)
+ *err = res;
+ return NULL;
+ }
+
+ 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(" display_buffer:%p %dx%d %c%c%c%c bo_num:%d plane_num:%d",
+ buffer, display_buffer->width, display_buffer->height,
+ FOURCC_STR(display_buffer->format), display_buffer->count, count);
+
+ for (i = 0; i < count; i++) {
+ int bo_idx = 0;
+ tbm_bo bo = NULL;
+
+ bo_idx = tbm_surface_internal_get_plane_bo_idx(buffer, i);
+ bo = tbm_surface_internal_get_bo(buffer, bo_idx);
+ display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+
+ tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
+ &display_buffer->offsets[i],
+ &display_buffer->pitches[i]);
+ TDM_DBG("\tplane%d(size:%d offset:%d pitch:%d) bo%d(handle:%d)",
+ i, display_buffer->size, display_buffer->offsets[i],
+ display_buffer->pitches[i], bo_idx, display_buffer->handles[i]);
+ }
+
+ ret = drmModeAddFB2(nexell_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);
+ if (err)
+ *err = TDM_ERROR_OPERATION_FAILED;
+ return NULL;
+ }
+
+ TDM_DBG("nexell_data->drm_fd : %d, display_buffer->fb_id:%u", nexell_data->drm_fd,
+ display_buffer->fb_id);
+
+ if (IS_RGB(display_buffer->format))
+ display_buffer->width = display_buffer->pitches[0] >> 2;
+ else
+ display_buffer->width = display_buffer->pitches[0];
+
+ LIST_ADDTAIL(&display_buffer->link, &nexell_data->buffer_list);
+
+ if (err)
+ *err = TDM_ERROR_NONE;
+
+ return display_buffer;
+}
+
+void
+tdm_nexell_data_destroy_buffer_list(tdm_nexell_data *nexell_data)
+{
+ tdm_nexell_display_buffer *b = NULL, *bb = NULL;
+
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &nexell_data->buffer_list, link) {
+ tdm_buffer_remove_destroy_handler(b->buffer, _tdm_nexell_display_cb_destroy_buffer, nexell_data);
+ _tdm_nexell_display_cb_destroy_buffer(b->buffer, nexell_data);
+ }
+}
+
tdm_error
nexell_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
{
tdm_nexell_layer_data *layer_data = layer;
tdm_nexell_data *nexell_data;
tdm_nexell_display_buffer *display_buffer;
+ tdm_error err = TDM_ERROR_NONE;
RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER);
nexell_data = layer_data->nexell_data;
-
- display_buffer = _tdm_nexell_display_get_buffer(nexell_data, buffer);
+ display_buffer = _tdm_nexell_display_find_buffer(nexell_data, buffer);
if (!display_buffer) {
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
+ display_buffer = _tdm_nexell_display_create_buffer(nexell_data, buffer, &err);
+ RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
}
- 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);
+ 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_changed = 1;
+ 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 TDM_ERROR_NONE;
}
+
+tdm_nexell_layer_data *
+nexell_output_data_get_layer_data(tdm_nexell_output_data *output_data, int layer_zpos)
+{
+ tdm_nexell_layer_data *l = NULL;
+
+ RETURN_VAL_IF_FAIL(output_data, NULL);
+
+ LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
+ if (l->zpos == layer_zpos)
+ return l;
+ }
+
+ return NULL;
+}
\ No newline at end of file