1 #include "tpl_internal.h"
4 __tpl_surface_fini(tpl_surface_t *surface)
8 surface->backend.fini(surface);
9 __tpl_runtime_remove_surface(surface);
13 __tpl_surface_free(void *data)
17 __tpl_surface_fini((tpl_surface_t *) data);
19 TPL_LOG_F("tpl_surface_t(%p) free", data);
23 static tpl_surface_t *
24 __tpl_surface_internal_create(tpl_display_t *display, tpl_handle_t handle,
25 tpl_surface_type_t type, tbm_format format,
28 tpl_surface_t *surface = NULL;
31 TPL_ERR("Display is NULL!");
36 TPL_ERR("Handle is NULL!");
40 if (num_buffers < TPL_SURFACE_MIN_BUFFER_COUNT) {
41 TPL_ERR("num_buffers(%d) must be >= 2", num_buffers);
45 surface = (tpl_surface_t *) calloc(1, sizeof(tpl_surface_t));
47 TPL_ERR("Failed to allocate memory for surface!");
51 if (__tpl_object_init(&surface->base, TPL_OBJECT_SURFACE,
52 __tpl_surface_free) != TPL_ERROR_NONE) {
53 TPL_ERR("Failed to initialize surface's base class!");
58 surface->display = display;
59 surface->native_handle = handle;
61 surface->format = format;
63 surface->post_interval = 1;
65 surface->dump_count = 0;
66 surface->num_buffers = num_buffers;
68 /* Intialize backend. */
69 __tpl_surface_init_backend(surface, display->backend.type);
71 if ((!surface->backend.init)
72 || (surface->backend.init(surface) != TPL_ERROR_NONE)) {
73 TPL_ERR("Failed to initialize surface's backend!");
74 __tpl_object_fini(&surface->base);
80 /* vulkan can create more than one tpl_surface with one native surface
81 * for supporting oldSwapchain.
83 if (tpl_surface_get(display, handle) == NULL) {
84 tpl_result_t ret = TPL_ERROR_NONE;
85 /* Add it to the runtime. */
86 ret = __tpl_runtime_add_surface(surface);
87 if (ret != TPL_ERROR_NONE) {
88 TPL_ERR("Failed to add surface to runtime list!");
89 tpl_object_unreference((tpl_object_t *) surface);
98 tpl_surface_create(tpl_display_t *display, tpl_handle_t handle,
99 tpl_surface_type_t type, tbm_format format)
101 tpl_surface_t *surface = NULL;
103 surface = __tpl_surface_internal_create(display, handle,
105 TPL_SURFACE_DEFAULT_BUFFER_COUNT);
107 TPL_LOG_F("tpl_display_t(%p) tpl_surface_t(%p) native_handle(%p) format(%d) num_buffers(%d)",
108 display, surface, handle, format, TPL_SURFACE_DEFAULT_BUFFER_COUNT);
110 TPL_ERR("Failed to create tpl_surface with native window(%p)", handle);
115 tpl_surface_create_with_num_buffers(tpl_display_t *display, tpl_handle_t handle,
116 tpl_surface_type_t type, tbm_format format,
119 tpl_surface_t *surface = NULL;
121 surface = __tpl_surface_internal_create(display, handle,
125 TPL_LOG_F("tpl_display_t(%p) tpl_surface_t(%p) native_handle(%p) format(%d) num_buffers(%d)",
126 display, surface, handle, format, num_buffers);
128 TPL_ERR("Failed to create tpl_surface with native window(%p)", handle);
133 tpl_surface_get(tpl_display_t *display, tpl_handle_t handle)
135 tpl_surface_t *surface = NULL;
138 TPL_ERR("Display is NULL!");
143 TPL_ERR("Handle is NULL!");
147 surface = __tpl_runtime_find_surface(display->backend.type, handle);
149 TPL_LOG_F("[REUSE] tpl_display_t(%p) tpl_surface_t(%p) native_handle(%p)",
150 display, surface, handle);
157 tpl_surface_get_display(tpl_surface_t *surface)
160 TPL_ERR("Surface is NULL!");
164 return surface->display;
168 tpl_surface_get_native_handle(tpl_surface_t *surface)
171 TPL_ERR("Surface is NULL!");
175 return surface->native_handle;
179 tpl_surface_get_type(tpl_surface_t *surface)
182 TPL_ERR("Surface is NULL!");
183 return TPL_SURFACE_ERROR;
186 return surface->type;
190 tpl_surface_get_size(tpl_surface_t *surface, int *width, int *height)
193 TPL_ERR("Surface is NULL!");
194 return TPL_ERROR_INVALID_PARAMETER;
197 if (surface->backend.get_size) {
198 surface->backend.get_size(surface, width, height);
201 if (width) *width = surface->width;
202 if (height) *height = surface->height;
205 return TPL_ERROR_NONE;
209 tpl_surface_get_rotation(tpl_surface_t *surface, int *rotation)
212 TPL_ERR("Surface is NULL!");
213 return TPL_ERROR_INVALID_PARAMETER;
216 if (rotation) *rotation = surface->rotation;
218 return TPL_ERROR_NONE;
222 tpl_surface_validate(tpl_surface_t *surface)
224 tpl_bool_t was_valid = TPL_TRUE;
226 if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
227 TPL_ERR("Invalid surface!");
231 if (!surface->backend.validate) {
232 TPL_ERR("Backend for surface has not been initialized!");
236 TPL_OBJECT_LOCK(surface);
238 if (!surface->backend.validate(surface)) was_valid = TPL_FALSE;
240 TPL_OBJECT_UNLOCK(surface);
242 TPL_LOG_F("tpl_surface_t(%p) valid [%s]", surface,
243 was_valid ? "TRUE" : "FALSE");
249 tpl_surface_set_post_interval(tpl_surface_t *surface, int interval)
251 tpl_result_t ret = TPL_ERROR_NONE;
253 if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
254 TPL_ERR("Invalid surface!");
255 return TPL_ERROR_INVALID_PARAMETER;
259 return TPL_ERROR_NONE;
261 TPL_OBJECT_LOCK(surface);
263 if (surface->post_interval != interval) {
264 if (surface->backend.set_post_interval)
265 ret = surface->backend.set_post_interval(surface, interval);
267 if (ret == TPL_ERROR_NONE)
268 surface->post_interval = interval;
271 TPL_OBJECT_UNLOCK(surface);
273 TPL_LOG_F("tpl_surface_t(%p) post_interval(%d)", surface, surface->post_interval);
279 tpl_surface_get_post_interval(tpl_surface_t *surface)
283 if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
284 TPL_ERR("Invalid surface!");
288 TPL_OBJECT_LOCK(surface);
289 interval = surface->post_interval;
290 TPL_OBJECT_UNLOCK(surface);
292 TPL_LOG_F("tpl_surface_t(%p) post_interval(%d)", surface, interval);
299 tpl_surface_cancel_dequeued_buffer(tpl_surface_t *surface,
300 tbm_surface_h tbm_surface)
302 tpl_result_t ret = TPL_ERROR_NONE;
304 if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
305 TPL_ERR("Invalid surface(%p)", surface);
306 return TPL_ERROR_INVALID_PARAMETER;
309 if (!surface->backend.cancel_dequeued_buffer) {
310 TPL_ERR("TPL surface has not been initialized correctly!");
311 return TPL_ERROR_INVALID_PARAMETER;
315 TPL_ERR("Invalid parameter. tbm_surface(%p)", tbm_surface);
316 return TPL_ERROR_INVALID_PARAMETER;
319 TPL_LOG_F("tpl_surface_t(%p) tbm_surface(%p)", surface, tbm_surface);
321 TPL_OBJECT_LOCK(surface);
322 ret = surface->backend.cancel_dequeued_buffer(surface, tbm_surface);
323 TPL_OBJECT_UNLOCK(surface);
329 tpl_surface_dequeue_buffer(tpl_surface_t *surface)
331 return tpl_surface_dequeue_buffer_with_sync(surface, UINT64_MAX, NULL);
335 tpl_surface_dequeue_buffer_with_sync(tpl_surface_t *surface,
341 tbm_surface_h tbm_surface = NULL;
343 if (!surface->backend.dequeue_buffer) {
344 TPL_ERR("TPL surface has not been initialized correctly!");
348 TRACE_BEGIN("TPL:DEQUEUE_BUFFER");
349 TPL_OBJECT_LOCK(surface);
351 tbm_surface = surface->backend.dequeue_buffer(surface, timeout_ns, sync_fence);
354 /* Update size of the surface. */
355 surface->width = tbm_surface_get_width(tbm_surface);
356 surface->height = tbm_surface_get_height(tbm_surface);
359 TPL_OBJECT_UNLOCK(surface);
362 TPL_LOG_F("tpl_surface_t(%p) tbm_surface(%p) (%dx%d)", surface, tbm_surface,
363 surface->width, surface->height);
369 tpl_surface_enqueue_buffer(tpl_surface_t *surface, tbm_surface_h tbm_surface)
371 return tpl_surface_enqueue_buffer_with_damage_and_sync(surface, tbm_surface,
376 tpl_surface_enqueue_buffer_with_damage(tpl_surface_t *surface,
377 tbm_surface_h tbm_surface,
378 int num_rects, const int *rects)
380 return tpl_surface_enqueue_buffer_with_damage_and_sync(surface, tbm_surface,
381 num_rects, rects, -1);
385 tpl_surface_enqueue_buffer_with_damage_and_sync(tpl_surface_t *surface,
386 tbm_surface_h tbm_surface,
387 int num_rects, const int *rects,
390 tpl_result_t ret = TPL_ERROR_NONE;
392 if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
393 TPL_ERR("Invalid surface!");
394 return TPL_ERROR_INVALID_PARAMETER;
398 TPL_ERR("tbm surface is invalid.");
399 return TPL_ERROR_INVALID_PARAMETER;
402 TRACE_BEGIN("TPL:ENQUEUE_BUFFER_WITH_DAMAGE");
403 TPL_OBJECT_LOCK(surface);
405 TPL_LOG_F("tpl_surface_t(%p) tbm_surface(%p) (%dx%d)", surface, tbm_surface,
406 tbm_surface_get_width(tbm_surface),
407 tbm_surface_get_height(tbm_surface));
409 /* Call backend post */
410 ret = surface->backend.enqueue_buffer(surface, tbm_surface, num_rects, rects,
413 TPL_OBJECT_UNLOCK(surface);
420 tpl_surface_get_swapchain_buffers(tpl_surface_t *surface,
421 tbm_surface_h **buffers, int *buffer_count)
423 tpl_result_t ret = TPL_ERROR_INVALID_OPERATION;
425 if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
426 TPL_ERR("Invalid surface!");
427 return TPL_ERROR_INVALID_PARAMETER;
431 TPL_ERR("Invalid buffer_count!");
432 return TPL_ERROR_INVALID_PARAMETER;
435 if (!surface->backend.get_swapchain_buffers) {
436 TPL_ERR("Backend does not support!");
437 return TPL_ERROR_INVALID_OPERATION;
440 TPL_OBJECT_LOCK(surface);
442 ret = surface->backend.get_swapchain_buffers(surface, buffers, buffer_count);
444 TPL_OBJECT_UNLOCK(surface);
450 tpl_surface_create_swapchain(tpl_surface_t *surface, tbm_format format,
451 int width, int height, int buffer_count, int present_mode)
453 tpl_result_t ret = TPL_ERROR_INVALID_OPERATION;
456 TPL_ERR("Invalid surface!");
457 return TPL_ERROR_INVALID_PARAMETER;
460 if ((width <= 0) || (height <= 0)) {
461 TPL_ERR("Invalid width or height!");
462 return TPL_ERROR_INVALID_PARAMETER;
465 if (!surface->backend.create_swapchain) {
466 TPL_ERR("Backend does not support!");
467 return TPL_ERROR_INVALID_OPERATION;
470 TPL_LOG_F("tpl_surface_t(%p) format(%d) buffer_count(%d) (%dx%d)",
471 surface, format, buffer_count, width, height);
473 TPL_OBJECT_LOCK(surface);
475 ret = surface->backend.create_swapchain(surface, format, width, height,
476 buffer_count, present_mode);
478 TPL_OBJECT_UNLOCK(surface);
484 tpl_surface_destroy_swapchain(tpl_surface_t *surface)
486 tpl_result_t ret = TPL_ERROR_INVALID_OPERATION;
489 TPL_ERR("Invalid surface!");
490 return TPL_ERROR_INVALID_PARAMETER;
493 if (!surface->backend.destroy_swapchain) {
494 TPL_ERR("Backend does not support!");
495 return TPL_ERROR_INVALID_OPERATION;
498 TPL_LOG_F("tpl_surface_t(%p)", surface);
500 TPL_OBJECT_LOCK(surface);
502 ret = surface->backend.destroy_swapchain(surface);
504 TPL_OBJECT_UNLOCK(surface);
510 tpl_surface_set_frontbuffer_mode(tpl_surface_t *surface, tpl_bool_t set)
512 tpl_result_t ret = TPL_ERROR_NONE;
515 TPL_ERR("Invalid surface!");
516 return TPL_ERROR_INVALID_PARAMETER;
519 TPL_OBJECT_LOCK(surface);
521 if (surface->is_frontbuffer_mode == set) {
522 TPL_OBJECT_UNLOCK(surface);
525 surface->is_frontbuffer_mode = set;
527 surface->frontbuffer = NULL;
529 TPL_OBJECT_UNLOCK(surface);
531 TPL_LOG_F("tpl_surface_t(%p) frontbuffer_mode [%s]",
532 surface, set ? "ACTIVATED" : "DEACTIVATED");
537 tpl_surface_set_reset_cb(tpl_surface_t *surface, void *data, tpl_surface_cb_func_t reset_cb)
539 tpl_result_t ret = TPL_ERROR_NONE;
542 TPL_ERR("Invalid surface!");
543 return TPL_ERROR_INVALID_PARAMETER;
546 TPL_OBJECT_LOCK(surface);
548 surface->reset_data = data;
549 surface->reset_cb = reset_cb;
551 TPL_OBJECT_UNLOCK(surface);
557 tpl_surface_set_rotation_capability(tpl_surface_t *surface, tpl_bool_t set)
559 tpl_result_t ret = TPL_ERROR_NONE;
561 if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
562 TPL_ERR("Invalid surface!");
563 return TPL_ERROR_INVALID_PARAMETER;
566 TPL_OBJECT_LOCK(surface);
568 if (surface->backend.set_rotation_capability)
569 ret = surface->backend.set_rotation_capability(surface, set);
571 surface->rotation_capability = set;
573 TPL_OBJECT_UNLOCK(surface);
579 tpl_surface_fence_sync_is_available(tpl_surface_t *surface)
581 tpl_bool_t ret = TPL_FALSE;
583 if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) {
584 TPL_ERR("Invalid surface!");
588 TPL_OBJECT_LOCK(surface);
589 if (surface->backend.fence_sync_is_available)
590 ret = surface->backend.fence_sync_is_available(surface);
592 TPL_OBJECT_UNLOCK(surface);