static void _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data);
static void _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
unsigned int tv_sec, unsigned int tv_usec, void *user_data);
+static void _tdm_layer_reset_pending_data(tdm_private_layer *private_layer);
EXTERN tdm_error
tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities)
info->dst_pos.w, info->dst_pos.h,
info->transform);
- ret = func_layer->layer_set_info(private_layer->layer_backend, info);
- TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+ private_layer->pending_info_changed = 1;
+ private_layer->pending_info = *info;
_pthread_mutex_unlock(&private_display->lock);
LIST_INITHEAD(&clone_list);
+ _tdm_layer_reset_pending_data(private_layer);
+
if (private_layer->waiting_buffer) {
_tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
private_layer->waiting_buffer = NULL;
tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
{
tdm_func_layer *func_layer;
- tdm_private_layer_buffer *layer_buffer;
LAYER_FUNC_ENTRY();
return TDM_ERROR_NOT_IMPLEMENTED;
}
- layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
- if (!layer_buffer) {
- _pthread_mutex_unlock(&private_display->lock);
- TDM_ERR("alloc failed");
- return TDM_ERROR_OUT_OF_MEMORY;
- }
- LIST_INITHEAD(&layer_buffer->link);
+ private_layer->pending_buffer_changed = 1;
- ret = func_layer->layer_set_buffer(private_layer->layer_backend, buffer);
- TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+ if (private_layer->pending_buffer) {
+ tbm_surface_internal_unref(private_layer->pending_buffer);
- /* dump buffer */
- if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
- _tdm_layer_dump_buffer(layer, buffer);
+ if (tdm_debug_module & TDM_DEBUG_BUFFER)
+ TDM_INFO("layer(%p) pending_buffer(%p) skipped",
+ private_layer, private_layer->pending_buffer);
+ }
- if (ret == TDM_ERROR_NONE) {
- if (private_layer->waiting_buffer)
- _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
+ tbm_surface_internal_ref(buffer);
+ private_layer->pending_buffer = buffer;
- private_layer->waiting_buffer = layer_buffer;
- private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(buffer);
- if (tdm_debug_module & TDM_DEBUG_BUFFER)
- TDM_INFO("layer(%p) waiting_buffer(%p)",
- private_layer, private_layer->waiting_buffer->buffer);
- } else
- _tdm_layer_free_buffer(private_layer, layer_buffer);
+ if (tdm_debug_module & TDM_DEBUG_BUFFER)
+ TDM_INFO("layer(%p) pending_buffer(%p)",
+ private_layer, private_layer->pending_buffer);
_pthread_mutex_unlock(&private_display->lock);
return 1;
}
+static void
+_tdm_layer_reset_pending_data(tdm_private_layer *private_layer)
+{
+ private_layer->pending_info_changed = 0;
+ memset(&private_layer->pending_info, 0, sizeof private_layer->pending_info);
+
+ private_layer->pending_buffer_changed = 0;
+ if (private_layer->pending_buffer) {
+ tbm_surface_internal_unref(private_layer->pending_buffer);
+ private_layer->pending_buffer = NULL;
+ }
+}
+
+INTERN tdm_error
+tdm_layer_commit_pending_data(tdm_private_layer *private_layer)
+{
+ tdm_private_output *private_output = private_layer->private_output;
+ tdm_private_display *private_display = private_output->private_display;
+ tdm_func_layer *func_layer;
+ tdm_error ret = TDM_ERROR_NONE;
+
+ func_layer = &private_display->func_layer;
+
+ if (private_layer->pending_info_changed) {
+ ret = func_layer->layer_set_info(private_layer->layer_backend, &private_layer->pending_info);
+ TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done);
+ }
+
+ if (private_layer->pending_buffer_changed) {
+ tdm_private_layer_buffer *layer_buffer;
+
+ layer_buffer = calloc(1, sizeof(tdm_private_layer_buffer));
+ TDM_GOTO_IF_FAIL(layer_buffer != NULL, done);
+
+ LIST_INITHEAD(&layer_buffer->link);
+
+ ret = func_layer->layer_set_buffer(private_layer->layer_backend, private_layer->pending_buffer);
+ TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+
+ if (tdm_debug_module & TDM_DEBUG_BUFFER)
+ TDM_INFO("layer(%p) pending_buffer(%p) committed",
+ private_layer, private_layer->pending_buffer);
+
+ /* dump buffer */
+ if (tdm_dump_enable && !(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO))
+ _tdm_layer_dump_buffer(private_layer, private_layer->pending_buffer);
+
+ if (ret == TDM_ERROR_NONE) {
+ if (private_layer->waiting_buffer)
+ _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer);
+
+ private_layer->waiting_buffer = layer_buffer;
+ private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(private_layer->pending_buffer);
+ if (tdm_debug_module & TDM_DEBUG_BUFFER)
+ TDM_INFO("layer(%p) waiting_buffer(%p)",
+ private_layer, private_layer->waiting_buffer->buffer);
+ } else
+ _tdm_layer_free_buffer(private_layer, layer_buffer);
+ }
+
+done:
+ _tdm_layer_reset_pending_data(private_layer);
+
+ return ret;
+}
+
/* CAUTION: Once _tdm_layer_commit returns success, the layer commit handler MUST be called always.
* That is, even if we get error in _tdm_layer_got_output_vblank() function for some reasons,
* the layer commit handler MUST be called.
return TDM_ERROR_DPMS_OFF;
}
+ /* don't call this inside of _tdm_layer_commit */
+ ret = tdm_layer_commit_pending_data(private_layer);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("layer(%p) committing pending data failed", layer);
+ _pthread_mutex_unlock(&private_display->lock);
+ return ret;
+ }
+
ret = _tdm_layer_commit(private_layer, func, user_data);
_pthread_mutex_unlock(&private_display->lock);
return;
}
+ /* we don't need to handle pending data here because the changes in this function
+ * should be applied immediately. we can't expect calling tdm_layer_commit.
+ */
ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);