#include "config.h"
#endif
-#include <tdm_helper.h>
-#include <linux/fb.h>
-#include <drm.h>
-#include <video/sprdfb.h>
-#include <tbm_surface.h>
-#include <tbm_surface_queue.h>
#include "tdm_sprd.h"
-#define MIN_WIDTH 32
#ifdef HAVE_FB_VBLANK
/** @TODO fb event struct */
#else
(__after)->next->prev = (__item); \
(__after)->next = (__item);
-typedef struct _tdm_sprd_output_data tdm_sprd_output_data;
-typedef struct _tdm_sprd_layer_data tdm_sprd_layer_data;
-typedef struct _tdm_sprd_hwc_data tdm_sprd_hwc_data;
-typedef struct _tdm_sprd_hwc_window_data tdm_sprd_hwc_window_data;
-typedef struct _tdm_sprd_vblank_data_s tdm_sprd_vblank_data;
-
-typedef enum {
- VBLANK_TYPE_WAIT,
- VBLANK_TYPE_COMMIT,
-} vblank_type_t;
-
-struct _tdm_sprd_vblank_data_s {
- vblank_type_t type;
- tdm_sprd_output_data *output_data;
- int hwc_mode;
- void *user_data;
-};
-
-typedef struct _tdm_sprd_display_buffer {
- struct list_head link;
-
- unsigned int fb_id;
- tbm_surface_h buffer;
- int width;
- unsigned int height;
- unsigned int format;
- unsigned int handles[4];
- unsigned int name[4];
- unsigned int pitches[4];
- unsigned int offsets[4];
- unsigned int size;
- unsigned int count;
-} tdm_sprd_display_buffer;
-
-typedef struct _tdm_sprd_output_capture_data {
- tdm_capture * tdm_capture_p;
- struct list_head link;
-} tdm_sprd_output_capture_data;
-
-struct _tdm_sprd_output_data {
- struct list_head link;
-
- /* data which are fixed at initializing */
- tdm_sprd_data *sprd_data;
- uint32_t pipe;
- int count_modes;
- tdm_output_mode *output_modes;
- tdm_output_type connector_type;
- unsigned int connector_type_id;
- struct list_head layer_list;
-
- tdm_output_vblank_handler vblank_func;
- tdm_output_commit_handler commit_func;
- tdm_output_conn_status status;
-
- int mode_changed;
- const tdm_output_mode *current_mode;
-
- int waiting_vblank_event;
-
- char *fb_fd_name;
- int fb_fd;
-
- struct fb_var_screeninfo mi;
-
- tdm_output_dpms dpms_value;
-
- struct list_head capture_list;
-
- /* hwc data */
- tdm_sprd_hwc_data *hwc_data;
-};
-
-struct _tdm_sprd_layer_data {
- struct list_head link;
-
- /* data which are fixed at initializing */
- tdm_sprd_data *sprd_data;
- tdm_sprd_output_data *output_data;
- tdm_layer_capability capabilities;
- int zpos;
-
- //list of sprd formats
- int format_count;
- tbm_format *formats;
-
- /* not fixed data below */
- tdm_info_layer info;
- int info_changed;
-
- tdm_sprd_display_buffer *display_buffer;
- int display_buffer_changed;
- /* current hw overlay setting */
- overlay_info ovi;
- int enabled_flag;
-
- int need_unset;
-};
-
-struct _tdm_sprd_hwc_data {
- tdm_sprd_hwc_window_data *target_hwc_window;
-
- int need_validate;
- int need_target_window;
-
- int target_window_zpos;
-
- tdm_sprd_output_data *output_data;
- struct list_head hwc_window_list;
-
- tdm_hwc_commit_handler commit_func;
-};
-
-struct _tdm_sprd_hwc_window_data {
- struct list_head link;
-
- /* data which are fixed at initializing */
- tdm_sprd_hwc_data *hwc_data;
-
- /* not fixed data below */
- tdm_hwc_window_info info;
- int info_changed;
-
- tdm_sprd_display_buffer *display_buffer;
- int display_buffer_changed;
- int enabled_flag;
-
- /* client_type stores the initial type given to us by client(compositor) */
- tdm_hwc_window_composition client_type;
- /* validated_type stores the type after running Validate */
- tdm_hwc_window_composition validated_type;
-
- int constraints;
- tbm_surface_queue_h tqueue;
-
- int zpos;
-};
-
typedef struct _Drm_Event_Context {
void (*vblank_handler)(int fd, unsigned int sequence, unsigned int tv_sec,
unsigned int tv_usec, void *user_data);
TBM_FORMAT_ARGB8888
};
-tbm_format hwc_window_video_formats[] = {
- TBM_FORMAT_NV12,
- TBM_FORMAT_YUV420
-};
-#if 0
-static const char *
-_comp_to_str(tdm_hwc_window_composition composition_type)
-{
- if (composition_type == TDM_COMPOSITION_CLIENT)
- return "CLIENT";
- else if (composition_type == TDM_COMPOSITION_DEVICE)
- return "DEVICE";
- else if (composition_type == TDM_COMPOSITION_CURSOR)
- return "CURSOR";
- else if (composition_type == TDM_COMPOSITION_NONE)
- return "NONE";
-
- return "unknown";
-}
-#endif
-static tbm_surface_queue_h
-_sprd_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
- tbm_surface_queue_h tqueue = NULL;
-
- if (error)
- *error = TDM_ERROR_INVALID_PARAMETER;
-
- RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
- hwc_window_data = hwc_window;
-
- int wight = hwc_window_data->info.src_config.size.h;
- int hight = hwc_window_data->info.src_config.size.v;
- tbm_format format = hwc_window_data->info.src_config.format;
-
- if (!hwc_window_data->tqueue) {
- tqueue = tbm_surface_queue_create(3, wight, hight, format, TBM_BO_SCANOUT);
- if (error)
- *error = TDM_ERROR_OPERATION_FAILED;
- RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
-
- hwc_window_data->tqueue = tqueue;
- }
-
- if (error)
- *error = TDM_ERROR_NONE;
-
- return tqueue;
-}
-
-#if 0
-static tdm_error
-check_hw_restriction(unsigned int output_w, unsigned int buf_w,
- unsigned int src_x, unsigned int src_w, unsigned int dst_x, unsigned int dst_w,
- unsigned int *new_src_x, unsigned int *new_src_w,
- unsigned int *new_dst_x, unsigned int *new_dst_w)
-{
- int start, end, diff;
- int virtual_screen;
-
- *new_src_x = src_x;
- *new_src_w = src_w;
- *new_dst_x = dst_x;
- *new_dst_w = dst_w;
-
- if (buf_w < MIN_WIDTH || buf_w % 2) {
- TDM_ERR("buf_w(%d) not 2's multiple or less than %d", buf_w, MIN_WIDTH);
- return TDM_ERROR_BAD_REQUEST;
- }
-
- if (src_x > dst_x || ((dst_x - src_x) + buf_w) > output_w)
- virtual_screen = 1;
- else
- virtual_screen = 0;
-
- start = (dst_x < 0) ? 0 : dst_x;
- end = ((dst_x + dst_w) > output_w) ? output_w : (dst_x + dst_w);
-
- /* check window minimun width */
- if ((end - start) < MIN_WIDTH) {
- TDM_ERR("visible_w(%d) less than %d", end - start, MIN_WIDTH);
- return TDM_ERROR_BAD_REQUEST;
- }
-
- if (!virtual_screen) {
- /* Pagewidth of window (= 8 byte align / bytes-per-pixel ) */
- if ((end - start) % 2)
- end--;
- } else {
- /* You should align the sum of PAGEWIDTH_F and OFFSIZE_F double-word (8 byte) boundary. */
- if (end % 2)
- end--;
- }
-
- *new_dst_x = start;
- *new_dst_w = end - start;
- *new_src_w = *new_dst_w;
- diff = start - dst_x;
- *new_src_x += diff;
-
- RETURN_VAL_IF_FAIL(*new_src_w > 0, TDM_ERROR_BAD_REQUEST);
- RETURN_VAL_IF_FAIL(*new_dst_w > 0, TDM_ERROR_BAD_REQUEST);
-
- if (src_x != *new_src_x || src_w != *new_src_w || dst_x != *new_dst_x ||
- dst_w != *new_dst_w)
- TDM_DBG("=> buf_w(%d) src(%d,%d) dst(%d,%d), virt(%d) start(%d) end(%d)",
- buf_w, *new_src_x, *new_src_w, *new_dst_x, *new_dst_w, virtual_screen, start,
- end);
-
- return TDM_ERROR_NONE;
-}
-#endif
-
-static tdm_sprd_display_buffer *
-_tdm_sprd_display_find_buffer(tdm_sprd_data *sprd_data, tbm_surface_h buffer)
+tdm_sprd_display_buffer *
+tdm_sprd_display_find_buffer(tdm_sprd_data *sprd_data, tbm_surface_h buffer)
{
tdm_sprd_display_buffer *display_buffer = NULL;
return ret;
}
-static tdm_error
-_tdm_sprd_display_get_cur_msc(int fd, int pipe, uint *msc)
+tdm_error
+tdm_sprd_output_get_cur_msc(int fd, int pipe, uint *msc)
{
drmVBlank vbl;
return TDM_ERROR_NONE;
}
-static tdm_error
-_tdm_sprd_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
+tdm_error
+tdm_sprd_output_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
{
drmVBlank vbl;
return TDM_ERROR_NONE;
}
-static tdm_error
-_tdm_sprd_display_do_commit(tdm_sprd_output_data *output_data)
+tdm_error
+tdm_sprd_output_do_commit(tdm_sprd_output_data *output_data)
{
tdm_error res = TDM_ERROR_NONE;
tdm_sprd_layer_data *layer_data = NULL;
sprd_data = (tdm_sprd_data *) user_data;
- display_buffer = _tdm_sprd_display_find_buffer(sprd_data, buffer);
+ display_buffer = tdm_sprd_display_find_buffer(sprd_data, buffer);
if (!display_buffer) {
TDM_ERR("no display_buffer");
return;
return output_data;
}
-tdm_sprd_layer_data *
-_sprd_output_get_layer(tdm_sprd_output_data *output_data, int index)
-{
- RETURN_VAL_IF_FAIL(output_data, NULL);
-
- tdm_sprd_layer_data *l = NULL;
- LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link)
- if (l->zpos == index)
- return l;
- return NULL;
-}
-
-static tdm_error
-_sprd_layer_attach_window(tdm_sprd_layer_data *layer_data, tdm_sprd_hwc_window_data *hwc_window_data)
-{
- tdm_error ret = TDM_ERROR_NONE;
-
- RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
-
- if (hwc_window_data == NULL || hwc_window_data->display_buffer == NULL) {
- if (layer_data->display_buffer)
- ret = sprd_layer_unset_buffer(layer_data);
- RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
- } else {
- ret = sprd_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info));
- RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
- RETURN_VAL_IF_FAIL(hwc_window_data->display_buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
- ret = sprd_layer_set_buffer(layer_data, hwc_window_data->display_buffer->buffer);
- RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
- }
- return ret;
-}
-
-static int
-_get_number_of_visible_windows(tdm_sprd_hwc_data *hwc_data)
-{
- int number = 0;
- tdm_sprd_hwc_window_data *window = NULL;
-
- RETURN_VAL_IF_FAIL(hwc_data, 0);
-
- LIST_FOR_EACH_ENTRY(window, &hwc_data->hwc_window_list, link) {
- if (window->client_type == TDM_COMPOSITION_NONE)
- continue;
-
- number++;
- }
-
- return number;
-}
-
-static tdm_error
-_tdm_sprd_display_prepare_commit(tdm_sprd_output_data *output_data) {
-
- tdm_sprd_layer_data * layer = NULL;
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
- tdm_sprd_hwc_data *hwc_data = NULL;
- int osd_use = 0, img_use = 0;
-
- hwc_data = output_data->hwc_data;
- RETURN_VAL_IF_FAIL(hwc_data, 0);
- RETURN_VAL_IF_FAIL(hwc_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
-
- if (!_get_number_of_visible_windows(hwc_data))
- hwc_data->need_target_window = 1;
-
- /* set target hwc window */
- if (hwc_data->need_target_window) {
- layer = _sprd_output_get_layer(output_data, 1);
- _sprd_layer_attach_window(layer, hwc_data->target_hwc_window);
- osd_use = 1;
- }
-
- /* set hwc windows */
- LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
- if (hwc_window_data->client_type == TDM_COMPOSITION_DEVICE) {
- layer = _sprd_output_get_layer(output_data, 1);
- osd_use = 1;
- } else if (hwc_window_data->client_type == TDM_COMPOSITION_VIDEO) {
- layer = _sprd_output_get_layer(output_data, 0);
- img_use = 1;
- } else {
- continue;
- }
-
- _sprd_layer_attach_window(layer, hwc_window_data);
- }
-
- /* disable unused layer */
- if (!osd_use) {
- layer = _sprd_output_get_layer(output_data, 1);
- _sprd_layer_attach_window(layer, NULL);
- }
-
- if (!img_use) {
- layer = _sprd_output_get_layer(output_data, 0);
- _sprd_layer_attach_window(layer, NULL);
- }
-
- return TDM_ERROR_NONE;
-}
-
tdm_sprd_display_buffer *
-_tdm_sprd_display_creat_buffer(tdm_sprd_data *sprd_data, tbm_surface_h surface, tdm_error * err)
+tdm_sprd_display_creat_buffer(tdm_sprd_data *sprd_data, tbm_surface_h surface, tdm_error *err)
{
int i, count;
int bw, bh;
TDM_DBG("FLIP EVENT");
}
-#if 0
-static int
-_sprd_layer_is_supported_format(tdm_sprd_layer_data *layer_data, tbm_format format)
-{
- RETURN_VAL_IF_FAIL(layer_data, 0);
- return IS_RGB(format);
-}
-#endif
-
-static int
-_sprd_hwc_window_is_reserved_buffer(tdm_sprd_hwc_window_data *hwc_window_data) {
- tbm_bo bo = NULL;
- int falgs = 0;
-
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, 0);
- RETURN_VAL_IF_FAIL(hwc_window_data->display_buffer != NULL, 0);
-
- bo = tbm_surface_internal_get_bo(hwc_window_data->display_buffer->buffer, 0);
- RETURN_VAL_IF_FAIL(bo != NULL, 0);
-
- falgs = tbm_bo_get_flags(bo);
-
- return falgs & TBM_BO_SCANOUT;
-}
-
-int
-_sprd_output_get_changed_number(tdm_sprd_hwc_data *hwc_data)
-{
- int num = 0;
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
-
- LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
- if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
- continue;
-
- if (hwc_window_data->client_type != hwc_window_data->validated_type)
- num++;
- }
-
- return num;
-}
-
-static tdm_hwc_window *
-_sprd_hwc_create_window(tdm_sprd_hwc_data *hwc_data, tdm_hwc_window_info *info, tdm_error *error)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
-
- if (error)
- *error = TDM_ERROR_NONE;
-
- hwc_window_data = calloc(1, sizeof(tdm_sprd_hwc_window_data));
- if (!hwc_window_data) {
- TDM_ERR("alloc failed");
- if (error)
- *error = TDM_ERROR_OUT_OF_MEMORY;
- return NULL;
- }
-
- hwc_window_data->hwc_data = hwc_data;
-
- if (info)
- memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
-
- LIST_INITHEAD(&hwc_window_data->link);
-
- return hwc_window_data;
-}
-
void
tdm_sprd_display_destroy_output_list(tdm_sprd_data *sprd_data)
{
sprd_data = output_data->sprd_data;
- ret = _tdm_sprd_display_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
+ ret = tdm_sprd_output_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
if (ret != TDM_ERROR_NONE)
goto failed_vblank;
vblank_data->output_data = output_data;
vblank_data->user_data = user_data;
- ret = _tdm_sprd_display_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
+ ret = tdm_sprd_output_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
if (ret != TDM_ERROR_NONE)
goto failed_vblank;
sprd_data = output_data->sprd_data;
- _tdm_sprd_display_do_commit(output_data);
+ tdm_sprd_output_do_commit(output_data);
RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
tdm_sprd_vblank_data *vblank_data = calloc(1, sizeof(tdm_sprd_vblank_data));
return TDM_ERROR_OUT_OF_MEMORY;
}
- ret = _tdm_sprd_display_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
+ ret = tdm_sprd_output_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
if (ret != TDM_ERROR_NONE) {
free(vblank_data);
return ret;
vblank_data->output_data = output_data;
vblank_data->user_data = user_data;
- ret = _tdm_sprd_display_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
+ ret = tdm_sprd_output_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
if (ret != TDM_ERROR_NONE) {
free(vblank_data);
return ret;
/* create or replace the target_window when the output mode is set */
if (output_data->sprd_data->hwc_mode) {
- ret = sprd_hwc_initailize_target_window(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
+ ret = tdm_sprd_hwc_initailize_target_window(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
if (ret != TDM_ERROR_NONE) {
TDM_ERR("create target hwc window failed (%d)", ret);
return ret;
RETURN_VAL_IF_FAIL(surface, TDM_ERROR_INVALID_PARAMETER);
sprd_data = layer_data->sprd_data;
- display_buffer = _tdm_sprd_display_find_buffer(sprd_data, surface);
+ display_buffer = tdm_sprd_display_find_buffer(sprd_data, surface);
if (!display_buffer) {
- display_buffer = _tdm_sprd_display_creat_buffer(sprd_data, surface, &err);
+ display_buffer = tdm_sprd_display_creat_buffer(sprd_data, surface, &err);
RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
LIST_ADDTAIL(&display_buffer->link, &sprd_data->buffer_list);
}
return TDM_ERROR_NONE;
}
-tdm_hwc_window *
-sprd_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
- tdm_sprd_hwc_data *hwc_data = hwc;
-
- RETURN_VAL_IF_FAIL(hwc_data, NULL);
-
- hwc_window_data = _sprd_hwc_create_window(hwc_data, NULL, error);
- RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
-
- LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
-
- TDM_DBG("hwc_window(%p) create", hwc_window_data);
- if (error)
- *error = TDM_ERROR_NONE;
-
- return hwc_window_data;
-}
-
-void
-sprd_hwc_window_destroy(tdm_hwc_window *hwc_window)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
-
- if (!hwc_window_data)
- return;
-
- LIST_DEL(&hwc_window_data->link);
-
- free(hwc_window_data);
-}
-
-static int
-_can_set_hwc_window_on_hw_layer(tdm_sprd_hwc_window_data *hwc_window_data)
-{
- if (!hwc_window_data->display_buffer)
- return 0;
-
- if (!_sprd_hwc_window_is_reserved_buffer(hwc_window_data))
- return 0;
-
- if (hwc_window_data->info.transform != TDM_TRANSFORM_NORMAL)
- return 0;
-
- if (hwc_window_data->info.src_config.pos.w != hwc_window_data->info.dst_pos.w)
- return 0;
-
- if (hwc_window_data->info.src_config.pos.h != hwc_window_data->info.dst_pos.h)
- 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)
- return 0;
-
- if (hwc_window_data->info.src_config.pos.w < MIN_WIDTH || hwc_window_data->info.src_config.pos.w % 2)
- return 0;
-
- return 1;
-}
-
-tdm_error
-sprd_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
-{
- tdm_sprd_hwc_data *hwc_data = hwc;
- tdm_sprd_hwc_window_data **composited_list = NULL;
- int i = 0, zpos = 0;
-
- RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- composited_list = (tdm_sprd_hwc_window_data **)composited_wnds;
-
- hwc_data->need_target_window = 1;
-
- if (num_wnds == 0) {
- hwc_data->need_target_window = 1;
- } else if (num_wnds == 1) {
- if (composited_list[0]->client_type == TDM_COMPOSITION_DEVICE) {
- if (_can_set_hwc_window_on_hw_layer(composited_list[0])) {
- hwc_data->need_target_window = 0;
- composited_list[0]->validated_type = TDM_COMPOSITION_DEVICE;
- composited_list[0]->zpos = zpos;
- zpos++;
- } else {
- composited_list[0]->validated_type = TDM_COMPOSITION_CLIENT;
- composited_list[0]->zpos = -1;
- }
- composited_list[0]->constraints = TDM_CONSTRAINT_BUFFER_QUEUE;
- } else if (composited_list[0]->client_type == TDM_COMPOSITION_CLIENT) {
- composited_list[0]->validated_type = TDM_COMPOSITION_CLIENT;
- composited_list[0]->zpos = -1;
- } else if (composited_list[0]->client_type == TDM_COMPOSITION_VIDEO) {
- composited_list[0]->validated_type = TDM_COMPOSITION_VIDEO;
- composited_list[0]->zpos = zpos;
- zpos++;
- } else {
- composited_list[0]->validated_type = TDM_COMPOSITION_NONE;
- composited_list[0]->zpos = -1;
- }
- } else {
- int has_video = 0;
-
- for (i = 0; i < num_wnds; i++) {
- if (composited_list[i]->client_type == TDM_COMPOSITION_VIDEO)
- has_video++;
- }
-
- for (i = 0 ; i < num_wnds; i++) {
- if (num_wnds == 2 && has_video == 1) {
- if (composited_list[i]->client_type == TDM_COMPOSITION_DEVICE) {
- if (_can_set_hwc_window_on_hw_layer(composited_list[i])) {
- hwc_data->need_target_window = 0;
- composited_list[i]->validated_type = TDM_COMPOSITION_DEVICE;
- composited_list[i]->zpos = zpos;
- zpos++;
- } else {
- composited_list[0]->validated_type = TDM_COMPOSITION_CLIENT;
- composited_list[0]->zpos = -1;
- }
- } else if (composited_list[i]->client_type == TDM_COMPOSITION_CLIENT) {
- composited_list[i]->validated_type = TDM_COMPOSITION_CLIENT;
- composited_list[i]->zpos = -1;
- } else if (composited_list[i]->client_type == TDM_COMPOSITION_VIDEO) {
- composited_list[i]->validated_type = TDM_COMPOSITION_VIDEO;
- composited_list[i]->zpos = zpos;
- zpos++;
- } else {
- composited_list[i]->validated_type = TDM_COMPOSITION_NONE;
- composited_list[i]->zpos = -1;
- }
- } else {
- if (composited_list[i]->client_type == TDM_COMPOSITION_DEVICE ||
- composited_list[i]->client_type == TDM_COMPOSITION_CLIENT) {
- composited_list[i]->validated_type = TDM_COMPOSITION_CLIENT;
- composited_list[i]->zpos = -1;
- } else if (composited_list[i]->client_type == TDM_COMPOSITION_NONE) {
- composited_list[i]->validated_type = TDM_COMPOSITION_NONE;
- composited_list[i]->zpos = -1;
- }
- }
- }
- }
-
- *num_types = _sprd_output_get_changed_number(hwc_data);
- if (*num_types == 0)
- hwc_data->need_validate = 0;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
- tdm_hwc_window **hwc_window, tdm_hwc_window_composition *composition_types)
-{
- tdm_sprd_hwc_data *hwc_data = hwc;
- int num = 0;
-
- RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- if ((hwc_window == NULL) || (composition_types == NULL)) {
- *num_elements = _sprd_output_get_changed_number(hwc_data);
- return TDM_ERROR_NONE;
- }
-
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
- LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
- if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
- continue;
-
- if (num >= *num_elements)
- break;
-
- if (hwc_window_data->client_type != hwc_window_data->validated_type) {
- composition_types[num] = hwc_window_data->validated_type;
- hwc_window[num] = hwc_window_data;
- num++;
- }
- }
-
- /* set real num of changed composition types */
- *num_elements = num;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_accept_changes(tdm_hwc *hwc)
-{
- tdm_sprd_hwc_data *hwc_data = hwc;
-
- RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
- LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
- if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
- continue;
-
- hwc_window_data->client_type = hwc_window_data->validated_type;
- }
-
- hwc_data->need_validate = 0;
-
- return TDM_ERROR_NONE;
-}
-
-tbm_surface_queue_h
-sprd_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
-{
- tdm_sprd_hwc_data *hwc_data = hwc;
- tbm_surface_queue_h tqueue = NULL;
-
- if (error)
- *error = TDM_ERROR_INVALID_PARAMETER;
-
- RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
-
- if (hwc_data->target_hwc_window == NULL) {
- if (error)
- *error = TDM_ERROR_OPERATION_FAILED;
- return NULL;
- }
-
- tqueue = _sprd_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
- RETURN_VAL_IF_FAIL(tqueue, NULL);
-
- if (error)
- *error = TDM_ERROR_NONE;
- return tqueue;
-}
-
-tdm_error
-sprd_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
-{
- tdm_sprd_hwc_data *hwc_data = hwc;
- tdm_error err;
-
- /* TODO: as the sprd-driver currently doesn't support DEVICE to CLIENT transition.
- * we silence skip 'composited_wnds' */
-
- RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED);
-
- err = sprd_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
- RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
-
- err = sprd_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
- RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
-{
- RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- // TODO: fix these formats.
- *formats = hwc_window_video_formats;
- *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_get_video_capability(tdm_hwc *hwc, tdm_hwc_video_capability *video_capability)
-{
- RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(video_capability != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- *video_capability = TDM_HWC_VIDEO_CAPABILITY_SCANOUT;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
-{
- tdm_sprd_hwc_data *hwc_data = hwc;
-
- RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- // TODO:
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
- tdm_hwc_window_composition comp_type)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
- tdm_sprd_hwc_data *hwc_data = hwc_window_data->hwc_data;
-
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- hwc_window_data->constraints = TDM_CONSTRAINT_NONE;
-
- if (hwc_window_data->client_type == comp_type)
- return TDM_ERROR_NONE;
-
- hwc_window_data->client_type = comp_type;
-
- hwc_data->need_validate = 1;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
-
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- //TODO::
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
- tdm_sprd_hwc_data *hwc_data = hwc_window_data->hwc_data;
-
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- if (memcmp(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info)) == 0)
- return TDM_ERROR_NONE;
-
- hwc_window_data->info = *info;
- hwc_data->need_validate = 1;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
- tdm_sprd_hwc_data *hwc_data;
- tdm_sprd_output_data *output_data;
- tdm_sprd_data *sprd_data;
- tdm_error err = TDM_ERROR_OPERATION_FAILED;
-
- tdm_sprd_display_buffer *display_buffer = NULL;
-
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, err);
- hwc_data = hwc_window_data->hwc_data;
- RETURN_VAL_IF_FAIL(hwc_data != NULL, err);
- output_data = hwc_data->output_data;
- RETURN_VAL_IF_FAIL(hwc_data != NULL, err);
- sprd_data = output_data->sprd_data;
- RETURN_VAL_IF_FAIL(sprd_data != NULL, err);
-
- if (!surface) {
- hwc_window_data->display_buffer = NULL;
- return TDM_ERROR_NONE;
- }
-
- display_buffer = _tdm_sprd_display_find_buffer(sprd_data, surface);
- if (!display_buffer) {
- display_buffer = _tdm_sprd_display_creat_buffer(sprd_data, surface, &err);
- RETURN_VAL_IF_FAIL(display_buffer != NULL, err);
- LIST_ADDTAIL(&display_buffer->link, &sprd_data->buffer_list);
- }
-
- if (hwc_window_data->display_buffer == display_buffer)
- return TDM_ERROR_NONE;
-
- hwc_window_data->display_buffer = display_buffer;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_initailize_target_window(tdm_hwc *hwc, int width, int height)
-{
- tdm_hwc_window_info info = {0};
- tdm_error ret = TDM_ERROR_NONE;
- tdm_sprd_hwc_window_data *target_hwc_window;
- tdm_sprd_hwc_data *hwc_data = hwc;
-
- RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
-
- info.dst_pos.x = 0;
- info.dst_pos.y = 0;
- info.dst_pos.h = height;
- info.dst_pos.w = width;
-
- info.src_config.pos.x = 0;
- info.src_config.pos.y = 0;
- info.src_config.pos.h = height;
- info.src_config.pos.w = width;
-
- info.src_config.size.h = width;
- info.src_config.size.v = height;
- info.src_config.format = TBM_FORMAT_ARGB8888;
-
- target_hwc_window = _sprd_hwc_create_window(hwc_data, &info, &ret);
- if (ret != TDM_ERROR_NONE) {
- TDM_ERR("create target hwc window failed (%d)", ret);
- return TDM_ERROR_OPERATION_FAILED;
- }
-
- if (hwc_data->target_hwc_window)
- sprd_hwc_window_destroy(hwc_data->target_hwc_window);
-
- hwc_data->target_hwc_window = target_hwc_window;
-
- return TDM_ERROR_NONE;
-}
-
tdm_hwc *
sprd_output_get_hwc(tdm_output *output, tdm_error *error)
{
return hwc_data;
}
-tdm_error
-sprd_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
-{
- tdm_sprd_output_data *output_data = NULL;
- tdm_sprd_hwc_data *hwc_data = NULL;
- tdm_sprd_data *sprd_data = NULL;
- tdm_error ret = TDM_ERROR_NONE;
-
- RETURN_VAL_IF_FAIL(hwc, TDM_ERROR_INVALID_PARAMETER);
-
- hwc_data = (tdm_sprd_hwc_data *)hwc;
-
- output_data = hwc_data->output_data;
- RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
-
- sprd_data = output_data->sprd_data;
-
- ret = _tdm_sprd_display_prepare_commit(output_data);
- RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
-
- _tdm_sprd_display_do_commit(output_data);
- RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
-
- tdm_sprd_vblank_data *vblank_data = calloc(1, sizeof(tdm_sprd_vblank_data));
- uint target_msc;
-
- if (!vblank_data) {
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
-
- ret = _tdm_sprd_display_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
- if (ret != TDM_ERROR_NONE) {
- free(vblank_data);
- return ret;
- }
-
- target_msc++;
-
- vblank_data->type = VBLANK_TYPE_COMMIT;
- vblank_data->hwc_mode = 1;
- vblank_data->output_data = output_data;
- vblank_data->user_data = user_data;
-
- ret = _tdm_sprd_display_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
- if (ret != TDM_ERROR_NONE) {
- free(vblank_data);
- return ret;
- }
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
-{
- tdm_sprd_hwc_data *hwc_data = hwc;
-
- RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
-
- hwc_data->commit_func = func;
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
-
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- //TODO:
-
- return TDM_ERROR_NONE;
-}
-
-tdm_error
-sprd_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = hwc_window;
-
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- //TODO:
-
- return TDM_ERROR_NONE;
-}
-
-tbm_surface_queue_h
-sprd_hwc_window_acquire_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
-{
- tdm_sprd_hwc_data *hwc_data = NULL;
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
- tdm_sprd_hwc_window_data *target_hwc_window_data = NULL;
-
- if (error)
- *error = TDM_ERROR_INVALID_PARAMETER;
-
- hwc_window_data = (tdm_sprd_hwc_window_data *)hwc_window;
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, NULL);
-
- hwc_data = hwc_window_data->hwc_data;
- RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
-
- target_hwc_window_data = hwc_data->target_hwc_window;
- RETURN_VAL_IF_FAIL(target_hwc_window_data != NULL, NULL);
-
- RETURN_VAL_IF_FAIL(target_hwc_window_data->tqueue != NULL, NULL);
-
- if (error)
- *error = TDM_ERROR_NONE;
-
- return target_hwc_window_data->tqueue;
-}
-
-void
-sprd_hwc_window_release_buffer_queue(tdm_hwc_window *hwc_window, tbm_surface_queue_h queue)
-{
- return;
-}
-
-tdm_error
-sprd_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints)
-{
- tdm_sprd_hwc_window_data *hwc_window_data = NULL;
-
- hwc_window_data = (tdm_sprd_hwc_window_data *)hwc_window;
-
- RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
- RETURN_VAL_IF_FAIL(constraints != NULL, TDM_ERROR_INVALID_PARAMETER);
-
- *constraints = hwc_window_data->constraints;
-
- return TDM_ERROR_NONE;
-}
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tdm_sprd.h"
+
+#define MIN_WIDTH 32
+
+tbm_format hwc_window_video_formats[] = {
+ TBM_FORMAT_NV12,
+ TBM_FORMAT_YUV420
+};
+
+static int
+_sprd_hwc_window_is_reserved_buffer(tdm_sprd_hwc_window_data *hwc_window_data) {
+ tbm_bo bo = NULL;
+ int falgs = 0;
+
+ RETURN_VAL_IF_FAIL(hwc_window_data != NULL, 0);
+ RETURN_VAL_IF_FAIL(hwc_window_data->display_buffer != NULL, 0);
+
+ bo = tbm_surface_internal_get_bo(hwc_window_data->display_buffer->buffer, 0);
+ RETURN_VAL_IF_FAIL(bo != NULL, 0);
+
+ falgs = tbm_bo_get_flags(bo);
+
+ return falgs & TBM_BO_SCANOUT;
+}
+
+static int
+_sprd_can_set_hwc_window_on_hw_layer(tdm_sprd_hwc_window_data *hwc_window_data)
+{
+ if (!hwc_window_data->display_buffer)
+ return 0;
+
+ if (!_sprd_hwc_window_is_reserved_buffer(hwc_window_data))
+ return 0;
+
+ if (hwc_window_data->info.transform != TDM_TRANSFORM_NORMAL)
+ return 0;
+
+ if (hwc_window_data->info.src_config.pos.w != hwc_window_data->info.dst_pos.w)
+ return 0;
+
+ if (hwc_window_data->info.src_config.pos.h != hwc_window_data->info.dst_pos.h)
+ 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)
+ return 0;
+
+ if (hwc_window_data->info.src_config.pos.w < MIN_WIDTH || hwc_window_data->info.src_config.pos.w % 2)
+ return 0;
+
+ return 1;
+}
+
+static tbm_surface_queue_h
+_sprd_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
+{
+ tdm_sprd_hwc_window_data *hwc_window_data = NULL;
+ tbm_surface_queue_h tqueue = NULL;
+
+ if (error)
+ *error = TDM_ERROR_INVALID_PARAMETER;
+
+ RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
+ hwc_window_data = hwc_window;
+
+ int wight = hwc_window_data->info.src_config.size.h;
+ int hight = hwc_window_data->info.src_config.size.v;
+ tbm_format format = hwc_window_data->info.src_config.format;
+
+ if (!hwc_window_data->tqueue) {
+ tqueue = tbm_surface_queue_create(3, wight, hight, format, TBM_BO_SCANOUT);
+ if (error)
+ *error = TDM_ERROR_OPERATION_FAILED;
+ RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
+
+ hwc_window_data->tqueue = tqueue;
+ }
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return tqueue;
+}
+
+static tdm_error
+_sprd_layer_attach_window(tdm_sprd_layer_data *layer_data, tdm_sprd_hwc_window_data *hwc_window_data)
+{
+ tdm_error ret = TDM_ERROR_NONE;
+
+ RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
+
+ if (hwc_window_data == NULL || hwc_window_data->display_buffer == NULL) {
+ if (layer_data->display_buffer)
+ ret = sprd_layer_unset_buffer(layer_data);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+ } else {
+ ret = sprd_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info));
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+ RETURN_VAL_IF_FAIL(hwc_window_data->display_buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
+ ret = sprd_layer_set_buffer(layer_data, hwc_window_data->display_buffer->buffer);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+ }
+ return ret;
+}
+
+tdm_sprd_layer_data *
+_sprd_output_get_layer(tdm_sprd_output_data *output_data, int index)
+{
+ RETURN_VAL_IF_FAIL(output_data, NULL);
+
+ tdm_sprd_layer_data *l = NULL;
+ LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link)
+ if (l->zpos == index)
+ return l;
+ return NULL;
+}
+
+static int
+_sprd_get_number_of_visible_windows(tdm_sprd_hwc_data *hwc_data)
+{
+ int number = 0;
+ tdm_sprd_hwc_window_data *window = NULL;
+
+ RETURN_VAL_IF_FAIL(hwc_data, 0);
+
+ LIST_FOR_EACH_ENTRY(window, &hwc_data->hwc_window_list, link) {
+ if (window->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ number++;
+ }
+
+ return number;
+}
+
+static tdm_error
+_sprd_display_prepare_commit(tdm_sprd_output_data *output_data) {
+
+ tdm_sprd_layer_data * layer = NULL;
+ tdm_sprd_hwc_window_data *hwc_window_data = NULL;
+ tdm_sprd_hwc_data *hwc_data = NULL;
+ int osd_use = 0, img_use = 0;
+
+ hwc_data = output_data->hwc_data;
+ RETURN_VAL_IF_FAIL(hwc_data, 0);
+ RETURN_VAL_IF_FAIL(hwc_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
+
+ if (!_sprd_get_number_of_visible_windows(hwc_data))
+ hwc_data->need_target_window = 1;
+
+ /* set target hwc window */
+ if (hwc_data->need_target_window) {
+ layer = _sprd_output_get_layer(output_data, 1);
+ _sprd_layer_attach_window(layer, hwc_data->target_hwc_window);
+ osd_use = 1;
+ }
+
+ /* set hwc windows */
+ LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
+ if (hwc_window_data->client_type == TDM_COMPOSITION_DEVICE) {
+ layer = _sprd_output_get_layer(output_data, 1);
+ osd_use = 1;
+ } else if (hwc_window_data->client_type == TDM_COMPOSITION_VIDEO) {
+ layer = _sprd_output_get_layer(output_data, 0);
+ img_use = 1;
+ } else {
+ continue;
+ }
+
+ _sprd_layer_attach_window(layer, hwc_window_data);
+ }
+
+ /* disable unused layer */
+ if (!osd_use) {
+ layer = _sprd_output_get_layer(output_data, 1);
+ _sprd_layer_attach_window(layer, NULL);
+ }
+
+ if (!img_use) {
+ layer = _sprd_output_get_layer(output_data, 0);
+ _sprd_layer_attach_window(layer, NULL);
+ }
+
+ return TDM_ERROR_NONE;
+}
+
+int
+_sprd_output_get_changed_number(tdm_sprd_hwc_data *hwc_data)
+{
+ int num = 0;
+ tdm_sprd_hwc_window_data *hwc_window_data = NULL;
+
+ LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
+ if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ if (hwc_window_data->client_type != hwc_window_data->validated_type)
+ num++;
+ }
+
+ return num;
+}
+
+static tdm_hwc_window *
+_sprd_hwc_create_window(tdm_sprd_hwc_data *hwc_data, tdm_hwc_window_info *info, tdm_error *error)
+{
+ tdm_sprd_hwc_window_data *hwc_window_data = NULL;
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ hwc_window_data = calloc(1, sizeof(tdm_sprd_hwc_window_data));
+ if (!hwc_window_data) {
+ TDM_ERR("alloc failed");
+ if (error)
+ *error = TDM_ERROR_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ hwc_window_data->hwc_data = hwc_data;
+
+ if (info)
+ memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
+
+ LIST_INITHEAD(&hwc_window_data->link);
+
+ return hwc_window_data;
+}
+
+
+tdm_hwc_window *
+sprd_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
+{
+ tdm_sprd_hwc_window_data *hwc_window_data = NULL;
+ tdm_sprd_hwc_data *hwc_data = hwc;
+
+ RETURN_VAL_IF_FAIL(hwc_data, NULL);
+
+ hwc_window_data = _sprd_hwc_create_window(hwc_data, NULL, error);
+ RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
+
+ LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
+
+ TDM_DBG("hwc_window(%p) create", hwc_window_data);
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return hwc_window_data;
+}
+
+tdm_error
+sprd_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
+{
+ RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ // TODO: fix these formats.
+ *formats = hwc_window_video_formats;
+ *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+sprd_hwc_get_video_capability(tdm_hwc *hwc, tdm_hwc_video_capability *video_capability)
+{
+ RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(video_capability != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ *video_capability = TDM_HWC_VIDEO_CAPABILITY_SCANOUT;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+sprd_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
+{
+ tdm_sprd_hwc_data *hwc_data = hwc;
+
+ RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ // TODO:
+
+ return TDM_ERROR_NONE;
+}
+
+tbm_surface_queue_h
+sprd_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
+{
+ tdm_sprd_hwc_data *hwc_data = hwc;
+ tbm_surface_queue_h tqueue = NULL;
+
+ if (error)
+ *error = TDM_ERROR_INVALID_PARAMETER;
+
+ RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
+
+ if (hwc_data->target_hwc_window == NULL) {
+ if (error)
+ *error = TDM_ERROR_OPERATION_FAILED;
+ return NULL;
+ }
+
+ tqueue = _sprd_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
+ RETURN_VAL_IF_FAIL(tqueue, NULL);
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+ return tqueue;
+}
+
+tdm_error
+sprd_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
+{
+ tdm_sprd_hwc_data *hwc_data = hwc;
+ tdm_error err;
+
+ /* TODO: as the sprd-driver currently doesn't support DEVICE to CLIENT transition.
+ * we silence skip 'composited_wnds' */
+
+ RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED);
+
+ err = sprd_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
+ RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+ err = sprd_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
+ RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+sprd_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
+{
+ tdm_sprd_hwc_data *hwc_data = hwc;
+ tdm_sprd_hwc_window_data **composited_list = NULL;
+ int i = 0, zpos = 0;
+
+ RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ composited_list = (tdm_sprd_hwc_window_data **)composited_wnds;
+
+ hwc_data->need_target_window = 1;
+
+ if (num_wnds == 0) {
+ hwc_data->need_target_window = 1;
+ } else if (num_wnds == 1) {
+ if (composited_list[0]->client_type == TDM_COMPOSITION_DEVICE) {
+ if (_sprd_can_set_hwc_window_on_hw_layer(composited_list[0])) {
+ hwc_data->need_target_window = 0;
+ composited_list[0]->validated_type = TDM_COMPOSITION_DEVICE;
+ composited_list[0]->zpos = zpos;
+ zpos++;
+ } else {
+ composited_list[0]->validated_type = TDM_COMPOSITION_CLIENT;
+ composited_list[0]->zpos = -1;
+ }
+ composited_list[0]->constraints = TDM_CONSTRAINT_BUFFER_QUEUE;
+ } else if (composited_list[0]->client_type == TDM_COMPOSITION_CLIENT) {
+ composited_list[0]->validated_type = TDM_COMPOSITION_CLIENT;
+ composited_list[0]->zpos = -1;
+ } else if (composited_list[0]->client_type == TDM_COMPOSITION_VIDEO) {
+ composited_list[0]->validated_type = TDM_COMPOSITION_VIDEO;
+ composited_list[0]->zpos = zpos;
+ zpos++;
+ } else {
+ composited_list[0]->validated_type = TDM_COMPOSITION_NONE;
+ composited_list[0]->zpos = -1;
+ }
+ } else {
+ int has_video = 0;
+
+ for (i = 0; i < num_wnds; i++) {
+ if (composited_list[i]->client_type == TDM_COMPOSITION_VIDEO)
+ has_video++;
+ }
+
+ for (i = 0 ; i < num_wnds; i++) {
+ if (num_wnds == 2 && has_video == 1) {
+ if (composited_list[i]->client_type == TDM_COMPOSITION_DEVICE) {
+ if (_sprd_can_set_hwc_window_on_hw_layer(composited_list[i])) {
+ hwc_data->need_target_window = 0;
+ composited_list[i]->validated_type = TDM_COMPOSITION_DEVICE;
+ composited_list[i]->zpos = zpos;
+ zpos++;
+ } else {
+ composited_list[0]->validated_type = TDM_COMPOSITION_CLIENT;
+ composited_list[0]->zpos = -1;
+ }
+ } else if (composited_list[i]->client_type == TDM_COMPOSITION_CLIENT) {
+ composited_list[i]->validated_type = TDM_COMPOSITION_CLIENT;
+ composited_list[i]->zpos = -1;
+ } else if (composited_list[i]->client_type == TDM_COMPOSITION_VIDEO) {
+ composited_list[i]->validated_type = TDM_COMPOSITION_VIDEO;
+ composited_list[i]->zpos = zpos;
+ zpos++;
+ } else {
+ composited_list[i]->validated_type = TDM_COMPOSITION_NONE;
+ composited_list[i]->zpos = -1;
+ }
+ } else {
+ if (composited_list[i]->client_type == TDM_COMPOSITION_DEVICE ||
+ composited_list[i]->client_type == TDM_COMPOSITION_CLIENT) {
+ composited_list[i]->validated_type = TDM_COMPOSITION_CLIENT;
+ composited_list[i]->zpos = -1;
+ } else if (composited_list[i]->client_type == TDM_COMPOSITION_NONE) {
+ composited_list[i]->validated_type = TDM_COMPOSITION_NONE;
+ composited_list[i]->zpos = -1;
+ }
+ }
+ }
+ }
+
+ *num_types = _sprd_output_get_changed_number(hwc_data);
+ if (*num_types == 0)
+ hwc_data->need_validate = 0;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+sprd_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
+ tdm_hwc_window **hwc_window, tdm_hwc_window_composition *composition_types)
+{
+ tdm_sprd_hwc_data *hwc_data = hwc;
+ int num = 0;
+
+ RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ if ((hwc_window == NULL) || (composition_types == NULL)) {
+ *num_elements = _sprd_output_get_changed_number(hwc_data);
+ return TDM_ERROR_NONE;
+ }
+
+ tdm_sprd_hwc_window_data *hwc_window_data = NULL;
+ LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
+ if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ if (num >= *num_elements)
+ break;
+
+ if (hwc_window_data->client_type != hwc_window_data->validated_type) {
+ composition_types[num] = hwc_window_data->validated_type;
+ hwc_window[num] = hwc_window_data;
+ num++;
+ }
+ }
+
+ /* set real num of changed composition types */
+ *num_elements = num;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+sprd_hwc_accept_changes(tdm_hwc *hwc)
+{
+ tdm_sprd_hwc_data *hwc_data = hwc;
+
+ RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ tdm_sprd_hwc_window_data *hwc_window_data = NULL;
+ LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
+ if (hwc_window_data->client_type == TDM_COMPOSITION_NONE)
+ continue;
+
+ hwc_window_data->client_type = hwc_window_data->validated_type;
+ }
+
+ hwc_data->need_validate = 0;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+sprd_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
+{
+ tdm_sprd_output_data *output_data = NULL;
+ tdm_sprd_hwc_data *hwc_data = NULL;
+ tdm_sprd_data *sprd_data = NULL;
+ tdm_error ret = TDM_ERROR_NONE;
+
+ RETURN_VAL_IF_FAIL(hwc, TDM_ERROR_INVALID_PARAMETER);
+
+ hwc_data = (tdm_sprd_hwc_data *)hwc;
+
+ output_data = hwc_data->output_data;
+ RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
+
+ sprd_data = output_data->sprd_data;
+
+ ret = _sprd_display_prepare_commit(output_data);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+ tdm_sprd_output_do_commit(output_data);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+ tdm_sprd_vblank_data *vblank_data = calloc(1, sizeof(tdm_sprd_vblank_data));
+ uint target_msc;
+
+ if (!vblank_data) {
+ TDM_ERR("alloc failed");
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = tdm_sprd_output_get_cur_msc(sprd_data->drm_fd, output_data->pipe, &target_msc);
+ if (ret != TDM_ERROR_NONE) {
+ free(vblank_data);
+ return ret;
+ }
+
+ target_msc++;
+
+ vblank_data->type = VBLANK_TYPE_COMMIT;
+ vblank_data->hwc_mode = 1;
+ vblank_data->output_data = output_data;
+ vblank_data->user_data = user_data;
+
+ ret = tdm_sprd_output_wait_vblank(sprd_data->drm_fd, output_data->pipe, &target_msc, vblank_data);
+ if (ret != TDM_ERROR_NONE) {
+ free(vblank_data);
+ return ret;
+ }
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+sprd_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
+{
+ tdm_sprd_hwc_data *hwc_data = hwc;
+
+ RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
+
+ hwc_data->commit_func = func;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+tdm_sprd_hwc_initailize_target_window(tdm_hwc *hwc, int width, int height)
+{
+ tdm_hwc_window_info info = {0};
+ tdm_error ret = TDM_ERROR_NONE;
+ tdm_sprd_hwc_window_data *target_hwc_window;
+ tdm_sprd_hwc_data *hwc_data = hwc;
+
+ RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
+
+ info.dst_pos.x = 0;
+ info.dst_pos.y = 0;
+ info.dst_pos.h = height;
+ info.dst_pos.w = width;
+
+ info.src_config.pos.x = 0;
+ info.src_config.pos.y = 0;
+ info.src_config.pos.h = height;
+ info.src_config.pos.w = width;
+
+ info.src_config.size.h = width;
+ info.src_config.size.v = height;
+ info.src_config.format = TBM_FORMAT_ARGB8888;
+
+ target_hwc_window = _sprd_hwc_create_window(hwc_data, &info, &ret);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("create target hwc window failed (%d)", ret);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ if (hwc_data->target_hwc_window)
+ sprd_hwc_window_destroy(hwc_data->target_hwc_window);
+
+ hwc_data->target_hwc_window = target_hwc_window;
+
+ return TDM_ERROR_NONE;
+}