#define MIN_WIDTH 32
+#define LIST_INSERT_AFTER(__after, __item) \
+ (__item)->prev = (__after); \
+ (__item)->next = (__after)->next; \
+ (__after)->next->prev = (__item); \
+ (__after)->next = (__item);
+
typedef struct _tdm_vc4_output_data tdm_vc4_output_data;
typedef struct _tdm_vc4_layer_data tdm_vc4_layer_data;
+typedef struct _tdm_vc4_hwc_window_data tdm_vc4_hwc_window_data;
typedef struct _tdm_vc4_event_data tdm_vc4_event_data;
typedef enum {
tbm_surface_h crtc_buffer;
int crtc_enabled;
unsigned int crtc_fb_id;
+
+ tdm_vc4_hwc_window_data *target_hwc_window;
+
+ int need_validate;
+ int need_target_buffer;
+ int hw_layer_count;
+ int need_set_crtc;
+ int top_layer_idx;
+ int hwc_enable;
+
+ struct list_head hwc_window_list;
};
struct _tdm_vc4_layer_data {
int display_buffer_changed;
};
+struct _tdm_vc4_hwc_window_data {
+ struct list_head link;
+
+ /* data which are fixed at initializing */
+ tdm_vc4_data *vc4_data;
+ tdm_vc4_output_data *output_data;
+
+ /* not fixed data below */
+ int zpos;
+
+ tdm_hwc_window_info info;
+ int info_changed;
+
+ tbm_surface_h surface;
+ 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;
+};
+
+tdm_hwc_window *
+_vc4_output_hwc_window_create(tdm_output *output, tdm_hwc_window_info *info,
+ tdm_error *error);
+
static drmModeModeInfoPtr
_tdm_vc4_display_get_mode(tdm_vc4_output_data *output_data)
{
return;
LIST_FOR_EACH_ENTRY_SAFE(o, oo, &vc4_data->output_list, link) {
+
+ if (o->target_hwc_window)
+ vc4_output_hwc_window_destroy(o, o->target_hwc_window);
+
if (o->crtc_enabled) {
_tdm_vc4_display_set_crtc(vc4_data, o, 0);
o->crtc_enabled = 0;
&output_data->output_modes[j]);
}
+ if (vc4_data->hwc_mode) {
+ output_data->hwc_enable = 1;
+ output_data->target_hwc_window = NULL;
+ LIST_INITHEAD(&output_data->hwc_window_list);
+ }
+
LIST_ADDTAIL(&output_data->link, &vc4_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);
return TDM_ERROR_NONE;
}
+tdm_vc4_layer_data *
+_vc4_output_get_layer(tdm_vc4_output_data *output_data, int index)
+{
+ tdm_vc4_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
+_vc4_layer_attach_window(tdm_vc4_layer_data *layer_data,
+ tdm_vc4_hwc_window_data *hwc_window_data)
+{
+ tdm_error ret;
+
+ if (hwc_window_data == NULL || !hwc_window_data->surface) {
+ ret = vc4_layer_unset_buffer(layer_data);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+ } else {
+ ret = vc4_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->surface != NULL, TDM_ERROR_INVALID_PARAMETER);
+ ret = vc4_layer_set_buffer(layer_data, hwc_window_data->surface);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+ }
+
+ return ret;
+}
+
+static int
+_get_primary_layer_index(tdm_vc4_output_data *vc4_output)
+{
+ int i = 0;
+ tdm_vc4_layer_data *layer = NULL;
+
+ LIST_FOR_EACH_ENTRY(layer, &vc4_output->layer_list, link) {
+ if (layer->capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
+ return i;
+ i++;
+ }
+
+ return 0;
+}
+
+static tdm_error
+_tdm_vc4_display_prepare_commit(tdm_vc4_output_data *output_data) {
+
+ tdm_vc4_layer_data * layer = NULL;
+ tdm_vc4_hwc_window_data *hw = NULL;
+ int num_hw_layer = 0;
+ int i;
+ int fb_idx = 0;
+
+ RETURN_VAL_IF_FAIL(output_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
+
+ i = output_data->top_layer_idx;
+ num_hw_layer = LIST_LENGTH(&output_data->layer_list);
+ fb_idx = _get_primary_layer_index(output_data);
+
+ //set target hwc window
+ if (output_data->need_target_buffer) {
+ layer = _vc4_output_get_layer(output_data, fb_idx);
+ _vc4_layer_attach_window(layer, output_data->target_hwc_window);
+ }
+
+ //set hwc windows
+ LIST_FOR_EACH_ENTRY_REV(hw, &output_data->hwc_window_list, link) {
+ if (output_data->need_target_buffer && i == fb_idx) {
+ i--;
+ }
+ if (hw->client_type != TDM_COMPOSITION_DEVICE)
+ continue;
+ RETURN_VAL_IF_FAIL(i >= 0, TDM_ERROR_OPERATION_FAILED);
+ layer = _vc4_output_get_layer(output_data, i--);
+ _vc4_layer_attach_window(layer, hw);
+ }
+
+ //disable unused layer
+ while (i >= 0) {
+ layer = _vc4_output_get_layer(output_data, i--);
+ _vc4_layer_attach_window(layer, NULL);
+ }
+
+ i = output_data->top_layer_idx + 1;
+ while (i < num_hw_layer) {
+ layer = _vc4_output_get_layer(output_data, i++);
+ _vc4_layer_attach_window(layer, NULL);
+ }
+
+ return TDM_ERROR_NONE;
+}
+
tdm_error
vc4_output_commit(tdm_output *output, int sync, void *user_data)
{
vc4_data = output_data->vc4_data;
+ if (output_data->hwc_enable) {
+ ret = _tdm_vc4_display_prepare_commit(output_data);
+ RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+ }
+
LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
ret = _tdm_vc4_display_commit_layer(layer_data);
if (ret != TDM_ERROR_NONE)
RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
+ if (output_data->hwc_enable) {
+
+ tdm_hwc_window_info info = {0};
+ tdm_error ret = TDM_ERROR_NONE;
+ tdm_vc4_hwc_window_data *target_hwc_window;
+
+ info.dst_pos.x = 0;
+ info.dst_pos.y = 0;
+ info.dst_pos.h = mode->vdisplay;;
+ info.dst_pos.w = mode->hdisplay;
+
+ info.src_config.pos.x = 0;
+ info.src_config.pos.y = 0;
+ info.src_config.pos.h = mode->vdisplay;
+ info.src_config.pos.w = mode->hdisplay;
+
+ info.src_config.size.h = mode->hdisplay;
+ info.src_config.size.v = mode->vdisplay;
+ info.src_config.format = TBM_FORMAT_ARGB8888;
+
+ target_hwc_window = _vc4_output_hwc_window_create(output_data, &info, &ret);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("create target hwc window failed (%d)", ret);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ if (output_data->target_hwc_window)
+ vc4_output_hwc_window_destroy(output, output_data->target_hwc_window);
+
+ output_data->target_hwc_window = target_hwc_window;
+ output_data->need_set_crtc = 1;
+ }
+
output_data->current_mode = mode;
output_data->mode_changed = 1;
-
return TDM_ERROR_NONE;
}
return TDM_ERROR_NONE;
}
+
+tdm_error
+tdm_vc4_output_insert_hwc_window(tdm_vc4_output_data *output, tdm_vc4_hwc_window_data *hwc_window)
+{
+ tdm_vc4_hwc_window_data *item = NULL;
+ LIST_FOR_EACH_ENTRY_REV(item, &output->hwc_window_list, link) {
+ if (item == hwc_window)
+ return TDM_ERROR_OPERATION_FAILED;
+
+ if (item->zpos <= hwc_window->zpos)
+ break;
+ }
+
+ LIST_INSERT_AFTER(&item->link, &hwc_window->link);
+
+ return TDM_ERROR_NONE;
+}
+
+int
+_vc4_output_get_changed_number(tdm_vc4_output_data *vc4_output)
+{
+ int num = 0;
+ tdm_vc4_hwc_window_data *hw = NULL;
+
+ LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+ if (hw->client_type != hw->validated_type)
+ num++;
+ }
+
+ return num;
+}
+
+tdm_hwc_window *
+_vc4_output_hwc_window_create(tdm_output *output, tdm_hwc_window_info *info, tdm_error *error)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
+ tdm_vc4_output_data *vc4_output = output;
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ if (!vc4_output) {
+ TDM_ERR("invalid params");
+ if (error)
+ *error = TDM_ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ vc4_hwc_window = calloc(1, sizeof(tdm_vc4_hwc_window_data));
+ if (!vc4_hwc_window) {
+ TDM_ERR("alloc failed");
+ if (error)
+ *error = TDM_ERROR_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ if ((vc4_hwc_window->vc4_data = vc4_output->vc4_data) == NULL) {
+ TDM_ERR("invalid params");
+ if (error)
+ *error = TDM_ERROR_INVALID_PARAMETER;
+ goto fail;
+ }
+
+ vc4_hwc_window->output_data = output;
+ vc4_hwc_window->zpos = 0;
+
+ if (info)
+ memcpy(&vc4_hwc_window->info, info, sizeof(tdm_hwc_window_info));
+
+ return vc4_hwc_window;
+fail:
+ if (vc4_hwc_window)
+ free(vc4_hwc_window);
+
+ return NULL;
+}
+
+tdm_hwc_window *
+vc4_output_hwc_window_create(tdm_output *output, tdm_error *error)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
+ tdm_vc4_output_data *vc4_output = output;
+ tdm_error err;
+
+ vc4_hwc_window = _vc4_output_hwc_window_create(vc4_output, NULL, error);
+ if (vc4_hwc_window == NULL)
+ return NULL;
+
+ err = tdm_vc4_output_insert_hwc_window(vc4_output, vc4_hwc_window);
+ if (err != TDM_ERROR_NONE) {
+ if (error)
+ *error = err;
+ free(vc4_hwc_window);
+ return NULL;
+ }
+
+ TDM_DBG("hwc_window(%p) create", vc4_hwc_window);
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return vc4_hwc_window;
+}
+
+tdm_error
+vc4_output_hwc_window_destroy(tdm_output *output, tdm_hwc_window *hwc_window)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
+
+ LIST_DEL(&vc4_hwc_window->link);
+
+ free(vc4_hwc_window);
+
+ return TDM_ERROR_NONE;
+}
+
+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_CANDIDATE)
+ return "DEVICE_CANDIDATE";
+ else if (composition_type == TDM_COMPOSITION_DEVICE)
+ return "DEVICE";
+ else if (composition_type == TDM_COMPOSITION_CURSOR)
+ return "CURSOR";
+
+ return "unknown";
+}
+
+tdm_error
+vc4_output_hwc_validate(tdm_output *output, uint32_t *num_types)
+{
+ tdm_vc4_output_data *vc4_output = output;
+ tdm_vc4_data *vc4_data = NULL;
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
+ tdm_vc4_hwc_window_data *hw = NULL;
+ int hw_layer_count = 0;
+ int need_target_buffer = 0;
+ int max_hw_layer = LIST_LENGTH(&vc4_output->layer_list);
+ int fb_index = _get_primary_layer_index(vc4_output);
+ int i = 0;
+ int top_layer_idx = fb_index;
+
+ vc4_data = vc4_output->vc4_data;
+ RETURN_VAL_IF_FAIL(vc4_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ if (vc4_output->need_set_crtc) {
+ need_target_buffer = 1;
+
+ LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+ hw->validated_type = TDM_COMPOSITION_CLIENT;
+ }
+ } else {
+ int layer_idx;
+ int num_hwc_windows = LIST_LENGTH(&vc4_output->hwc_window_list);
+
+ LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+ hw->validated_type = TDM_COMPOSITION_CLIENT;
+ }
+
+ /* mark the top window */
+ if (num_hwc_windows > 1) {
+ layer_idx = max_hw_layer;
+ LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link) {
+ layer_idx--;
+ if (hw->client_type == TDM_COMPOSITION_DEVICE && layer_idx != fb_index) {
+ //check format
+ if (IS_RGB(hw->info.src_config.format)) {
+ hw->validated_type = TDM_COMPOSITION_DEVICE;
+ hw_layer_count++;
+ top_layer_idx++;
+ continue;
+ }
+ }
+ break;
+ }
+ }
+
+ if ((num_hwc_windows - hw_layer_count) > (fb_index + 1))
+ need_target_buffer = 1;
+
+ max_hw_layer = fb_index + 1;
+ if (need_target_buffer)
+ max_hw_layer--;
+
+ /* mark the bottom windows */
+ layer_idx = -1;
+ LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+ layer_idx++;
+ /* break if the remaining windows are already marked */
+ if (hw->validated_type == TDM_COMPOSITION_DEVICE)
+ break;
+ if (hw->client_type == TDM_COMPOSITION_DEVICE && layer_idx < max_hw_layer) {
+ //check format
+ if (IS_RGB(hw->info.src_config.format)) {
+ hw->validated_type = TDM_COMPOSITION_DEVICE;
+ hw_layer_count++;
+ continue;
+ }
+ }
+
+ need_target_buffer = 1;
+ break;
+ }
+ }
+
+ LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+ if (need_target_buffer && fb_index == i++)
+ TDM_DBG(" window(%p) target", vc4_output->target_hwc_window);
+ else
+ TDM_DBG(" window(%p) type: %s -> %s", hw,
+ _comp_to_str(hw->client_type), _comp_to_str(hw->validated_type));
+ }
+
+ if (need_target_buffer)
+ hw_layer_count++;
+
+ vc4_output->need_target_buffer = need_target_buffer;
+ vc4_output->hw_layer_count = hw_layer_count;
+ vc4_output->top_layer_idx = top_layer_idx;
+
+ *num_types = _vc4_output_get_changed_number(vc4_output);
+
+ if (*num_types == 0)
+ vc4_output->need_validate = 0;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_output_hwc_get_changed_composition_types(tdm_output *output,
+ uint32_t *num_elements,
+ tdm_hwc_window **hwc_window,
+ tdm_hwc_window_composition *composition_types)
+{
+ tdm_vc4_output_data *vc4_output = output;
+ int num = 0;
+
+ RETURN_VAL_IF_FAIL(vc4_output != 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 = _vc4_output_get_changed_number(vc4_output);
+ return TDM_ERROR_NONE;
+ }
+
+ tdm_vc4_hwc_window_data *hw = NULL;
+ LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link) {
+
+ if (num >= *num_elements)
+ break;
+
+ if (hw->client_type != hw->validated_type) {
+ composition_types[num] = hw->validated_type;
+ hwc_window[num] = hw;
+ num++;
+ }
+ }
+
+ //set real num of changed composition types
+ *num_elements = num;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_output_hwc_accept_changes(tdm_output *output)
+{
+ tdm_vc4_output_data *vc4_output = output;
+
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ tdm_vc4_hwc_window_data *hw = NULL;
+ LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link)
+ hw->client_type = hw->validated_type;
+
+ vc4_output->need_validate = 0;
+
+ return TDM_ERROR_NONE;
+}
+
+tbm_surface_queue_h
+vc4_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error)
+{
+ tdm_vc4_output_data *vc4_output = output;
+ tbm_surface_queue_h tqueue = NULL;
+
+ if (error)
+ *error = TDM_ERROR_INVALID_PARAMETER;
+
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, NULL);
+
+ if (vc4_output->target_hwc_window == NULL) {
+ if (error)
+ *error = TDM_ERROR_OPERATION_FAILED;
+ return NULL;
+ }
+
+ tqueue = vc4_hwc_window_get_tbm_buffer_queue(vc4_output->target_hwc_window, error);
+ RETURN_VAL_IF_FAIL(tqueue, NULL);
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return tqueue;
+}
+
+tdm_error
+vc4_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h buffer,
+ tdm_hwc_region damage, tdm_hwc_window **composited_wnds,
+ uint32_t num_wnds)
+{
+ tdm_vc4_output_data *vc4_output = output;
+ tdm_error err;
+
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(vc4_output->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED);
+
+ err = vc4_hwc_window_set_buffer(vc4_output->target_hwc_window, buffer);
+ RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+ err = vc4_hwc_window_set_buffer_damage(vc4_output->target_hwc_window, damage);
+ RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+ return TDM_ERROR_NONE;
+}
+
+
+tbm_surface_queue_h
+vc4_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
+ tdm_vc4_output_data *vc4_output = NULL;
+ tbm_surface_queue_h tqueue = NULL;
+ tbm_format format;
+
+ if (error)
+ *error = TDM_ERROR_INVALID_PARAMETER;
+
+ RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
+ vc4_hwc_window = hwc_window;
+ vc4_output = vc4_hwc_window->output_data;
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, NULL);
+
+ int wight = vc4_hwc_window->info.src_config.size.h;
+ int hight = vc4_hwc_window->info.src_config.size.v;
+
+ format = vc4_hwc_window->info.src_config.format;
+
+ 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);
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return tqueue;
+
+}
+
+tdm_error
+vc4_hwc_window_set_zpos(tdm_hwc_window *hwc_window, uint32_t zpos)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
+ tdm_vc4_output_data *vc4_output;
+
+ RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(zpos < 256, TDM_ERROR_INVALID_PARAMETER);
+
+ vc4_output = vc4_hwc_window->output_data;
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ if (vc4_hwc_window->zpos == zpos)
+ return TDM_ERROR_NONE;
+
+ LIST_DEL(&vc4_hwc_window->link);
+
+ vc4_hwc_window->zpos = zpos;
+
+ tdm_vc4_output_insert_hwc_window(vc4_output, vc4_hwc_window);
+
+ vc4_output->need_validate = 1;
+
+ return TDM_ERROR_NONE;
+
+}
+
+tdm_error
+vc4_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
+ tdm_hwc_window_composition comp_type)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
+ tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
+
+ RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ if (vc4_hwc_window->client_type == comp_type)
+ return TDM_ERROR_NONE;
+
+ vc4_hwc_window->client_type = comp_type;
+ vc4_output->need_validate = 1;
+
+ return TDM_ERROR_NONE;
+
+}
+
+tdm_error
+vc4_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region damage)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
+ tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
+
+ RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ //TODO::
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
+ tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
+
+ RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ if (!memcmp(&vc4_hwc_window->info, info, sizeof(tdm_hwc_window_info)))
+ return TDM_ERROR_NONE;
+
+ vc4_hwc_window->info = *info;
+ vc4_output->need_validate = 1;
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
+{
+ tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
+ tdm_vc4_output_data *vc4_output;
+ tdm_vc4_data *vc4_data;
+ tdm_error err = TDM_ERROR_OPERATION_FAILED;
+
+ RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, err);
+
+ vc4_output = vc4_hwc_window->output_data;
+ vc4_data = vc4_hwc_window->vc4_data;
+
+ RETURN_VAL_IF_FAIL(vc4_output != NULL, err);
+ RETURN_VAL_IF_FAIL(vc4_data != NULL, err);
+
+ if (vc4_hwc_window->surface == surface)
+ return TDM_ERROR_NONE;
+
+ vc4_hwc_window->surface = surface;
+
+ return TDM_ERROR_NONE;
+}