2 * Mesa 3-D graphics library
4 * Copyright (C) 2017 Samsung Electronics co., Ltd. All Rights Reserved
6 * Based on platform_android, which has
8 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
9 * Copyright (C) 2010-2011 LunarG Inc.
10 * Copyright © 2011 Intel Corporation
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice (including the next
20 * paragraph) shall be included in all copies or substantial portions of the
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 * DEALINGS IN THE SOFTWARE.
33 * Gwan-gyeong Mun <kk.moon@samsung.com>
41 #include <sys/types.h>
48 #include "util/u_atomic.h"
50 #include <wayland-client.h>
51 #include <drm-uapi/drm_fourcc.h>
53 #include <drm_fourcc.h>
55 #include "tizen/tizen_utils.h"
57 int tbm_bufmgr_fd = -1;
59 static void tizen_free_local_buffers(struct dri2_egl_surface *dri2_surf);
61 /* createImageFromFds requires fourcc format */
62 static int get_fourcc(tbm_format format)
65 case TBM_FORMAT_RGB565: return DRM_FORMAT_RGB565;
66 case TBM_FORMAT_BGRA8888: return DRM_FORMAT_ARGB8888;
67 case TBM_FORMAT_RGBA8888: return DRM_FORMAT_ABGR8888;
68 case TBM_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888;
69 case TBM_FORMAT_ABGR8888: return DRM_FORMAT_ABGR8888;
70 case TBM_FORMAT_RGBX8888: return DRM_FORMAT_XBGR8888;
71 case TBM_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888;
73 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
78 static int get_fourcc_yuv(tbm_format format)
81 case TBM_FORMAT_NV12: return DRM_FORMAT_NV12;
82 case TBM_FORMAT_NV21: return DRM_FORMAT_NV12;
83 case TBM_FORMAT_YUV420: return DRM_FORMAT_YUV420;
84 case TBM_FORMAT_YVU420: return DRM_FORMAT_YVU420;
86 _eglLog(_EGL_WARNING, "unsupported native yuv buffer format 0x%x", format);
91 static bool is_yuv_format(tbm_format format)
93 if (get_fourcc_yuv(format) == -1)
99 static int get_format(tbm_format format)
102 case TBM_FORMAT_RGB565: return __DRI_IMAGE_FORMAT_RGB565;
103 case TBM_FORMAT_BGRA8888: return __DRI_IMAGE_FORMAT_ARGB8888;
104 case TBM_FORMAT_RGBA8888: return __DRI_IMAGE_FORMAT_ABGR8888;
105 case TBM_FORMAT_ARGB8888: return __DRI_IMAGE_FORMAT_ARGB8888;
106 case TBM_FORMAT_ABGR8888: return __DRI_IMAGE_FORMAT_ABGR8888;
107 case TBM_FORMAT_RGBX8888: return __DRI_IMAGE_FORMAT_XBGR8888;
108 case TBM_FORMAT_XRGB8888: return __DRI_IMAGE_FORMAT_XRGB8888;
110 _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", format);
115 static int get_format_bpp(tbm_format format)
120 #pragma GCC diagnostic push
121 #pragma GCC diagnostic ignored "-Wswitch"
122 case TBM_FORMAT_BGRA8888:
123 case TBM_FORMAT_RGBA8888:
124 case TBM_FORMAT_RGBX8888:
125 case TBM_FORMAT_ARGB8888:
126 #pragma GCC diagnostic pop
127 case TBM_FORMAT_XRGB8888:
130 case TBM_FORMAT_RGB565:
141 static int get_pitch(tbm_surface_h tbm_surface)
143 tbm_surface_info_s surf_info;
145 if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
149 return surf_info.planes[0].stride;
153 get_native_buffer_fd(tbm_surface_h tbm_surface)
155 tbm_bo_handle bo_handle;
156 bo_handle = tbm_bo_get_handle(tbm_surface_internal_get_bo(tbm_surface, 0),
159 return (bo_handle.ptr != NULL) ? (int)bo_handle.u32 : -1;
163 get_native_buffer_name(tbm_surface_h tbm_surface)
167 bo_name = tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0));
169 return (bo_name != 0 ) ? (int)bo_name : -1;
173 tizen_internal_wait_sync_for_release_fence(struct dri2_egl_surface *dri2_surf,
174 int32_t release_fence_fd)
176 _EGLContext *ctx = _eglGetCurrentContext();
177 _EGLDisplay *disp = dri2_surf->base.Resource.Display;
179 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
180 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
181 struct dri2_egl_sync *dri2_sync;
183 EGLAttrib attrib_list[] = {
184 EGL_SYNC_NATIVE_FENCE_FD_TIZEN,
189 dri2_sync = calloc(1, sizeof(struct dri2_egl_sync));
191 close(release_fence_fd);
195 if (!_eglInitSync(&dri2_sync->base, disp,
196 EGL_SYNC_NATIVE_FENCE_TIZEN,
199 close(release_fence_fd);
203 if (dri2_dpy->fence->create_fence_fd) {
204 dri2_sync->fence = dri2_dpy->fence->create_fence_fd(
205 dri2_ctx->dri_context,
206 dri2_sync->base.SyncFd);
209 if (!dri2_sync->fence) {
211 close(release_fence_fd);
215 dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context,
216 dri2_sync->fence, 0);
218 close(dri2_sync->base.SyncFd);
219 if (dri2_sync->fence)
220 dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence);
227 tizen_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
230 int32_t release_fence;
232 TRACE_BEGIN("DEQUEUE_BUFFER");
233 dri2_surf->tbm_surface = tpl_surface_dequeue_buffer_with_sync(
234 dri2_surf->tpl_surface,
239 if (!dri2_surf->tbm_surface)
242 dri2_surf->valid = true;
243 tbm_surface_internal_ref(dri2_surf->tbm_surface);
245 if (release_fence != -1) {
247 ret = tizen_internal_wait_sync_for_release_fence(dri2_surf, release_fence);
249 _eglLog(_EGL_WARNING, "%s : %d : failed to create sync fence.", __func__, __LINE__);
253 tpl_surface_get_size(dri2_surf->tpl_surface, &width, &height);
254 if (dri2_surf->base.Width != width ||
255 dri2_surf->base.Height != height) {
256 dri2_surf->base.Width = width;
257 dri2_surf->base.Height = height;
258 tizen_free_local_buffers(dri2_surf);
261 /* Record all the buffers created by tpl_surface (tbm_surface_queue)
262 * and update back buffer * for updating buffer's age in swap_buffers.
264 EGLBoolean updated = EGL_FALSE;
265 for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
266 if (!dri2_surf->color_buffers[i].tbm_surface) {
267 dri2_surf->color_buffers[i].tbm_surface = dri2_surf->tbm_surface;
268 dri2_surf->color_buffers[i].age = 0;
270 if (dri2_surf->color_buffers[i].tbm_surface == dri2_surf->tbm_surface) {
271 dri2_surf->back = &dri2_surf->color_buffers[i];
278 /* In case of all the buffers were recreated , reset the color_buffers */
279 for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
280 dri2_surf->color_buffers[i].tbm_surface = NULL;
281 dri2_surf->color_buffers[i].age = 0;
283 dri2_surf->color_buffers[0].tbm_surface = dri2_surf->tbm_surface;
284 dri2_surf->back = &dri2_surf->color_buffers[0];
291 tizen_window_enqueue_buffer_with_damage(_EGLDisplay *disp,
292 struct dri2_egl_surface *dri2_surf,
297 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
300 /* To avoid blocking other EGL calls, release the display mutex before
301 * we enter tizen_window_enqueue_buffer() and re-acquire the mutex upon
304 simple_mtx_unlock(&disp->Mutex);
306 fence_fd = dri2_surf->out_fence_fd;
308 if (fence_fd >= 0 && dri2_surf->is_frontbuffer_mode) {
313 dri2_surf->out_fence_fd = -1;
315 ret = tpl_surface_enqueue_buffer_with_damage_and_sync(dri2_surf->tpl_surface,
316 dri2_surf->tbm_surface,
320 if (ret != TPL_ERROR_NONE) {
321 _eglLog(_EGL_DEBUG, "%s : %d :tpl_surface_enqueue fail", __func__, __LINE__);
324 tbm_surface_internal_unref(dri2_surf->tbm_surface);
325 dri2_surf->tbm_surface = NULL;
326 dri2_surf->back = NULL;
328 simple_mtx_unlock(&disp->Mutex);
330 if (dri2_surf->dri_image_back) {
331 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
332 dri2_surf->dri_image_back = NULL;
339 tizen_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
341 return tizen_window_enqueue_buffer_with_damage(disp, dri2_surf, NULL, 0);
345 tizen_window_cancel_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
347 tizen_window_enqueue_buffer(disp, dri2_surf);
351 tizen_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
352 unsigned int att, unsigned int format)
354 struct dri2_egl_display *dri2_dpy =
355 dri2_egl_display(dri2_surf->base.Resource.Display);
357 if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
360 if (!dri2_surf->local_buffers[att]) {
361 dri2_surf->local_buffers[att] =
362 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
363 dri2_surf->base.Width, dri2_surf->base.Height);
366 return dri2_surf->local_buffers[att];
370 tizen_free_local_buffers(struct dri2_egl_surface *dri2_surf)
372 struct dri2_egl_display *dri2_dpy =
373 dri2_egl_display(dri2_surf->base.Resource.Display);
376 for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
377 if (dri2_surf->local_buffers[i]) {
378 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
379 dri2_surf->local_buffers[i]);
380 dri2_surf->local_buffers[i] = NULL;
386 tizen_create_surface(_EGLDisplay *disp, EGLint type,
387 _EGLConfig *conf, void *native_window,
388 const EGLint *attrib_list)
390 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
391 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
392 struct dri2_egl_surface *dri2_surf;
393 const __DRIconfig *config;
394 tpl_surface_type_t tpl_surf_type = TPL_SURFACE_ERROR;
395 tpl_result_t ret = TPL_ERROR_INVALID_PARAMETER;
396 char *env = getenv("EGL_FRONTBUFFER_ENABLE");
398 dri2_surf = calloc(1, sizeof *dri2_surf);
400 _eglError(EGL_BAD_ALLOC, "tizen_create_surface");
404 if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,
405 true, native_window))
406 goto cleanup_surface;
408 config = dri2_get_dri_config(dri2_conf, type,
409 dri2_surf->base.GLColorspace);
411 goto cleanup_surface;
413 if (type == EGL_WINDOW_BIT) {
414 unsigned int alpha, depth;
416 if (!native_window) {
417 _eglError(EGL_BAD_NATIVE_WINDOW, "tizen_create_surface needs vaild native window");
418 goto cleanup_surface;
420 dri2_surf->native_win = native_window;
421 dri2_surf->valid = true;
422 dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_DEPTH_SIZE, &depth);
423 dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SIZE, &alpha);
425 ret = tpl_display_get_native_window_info(dri2_dpy->tpl_display,
426 (tpl_handle_t)native_window,
427 &dri2_surf->base.Width,
428 &dri2_surf->base.Height,
429 &dri2_surf->tbm_format,
432 if (ret != TPL_ERROR_NONE || dri2_surf->tbm_format == 0) {
433 _eglError(EGL_BAD_NATIVE_WINDOW, "tizen_create_surface fails on tpl_display_get_native_window_info()");
434 goto cleanup_surface;
437 tpl_surf_type = TPL_SURFACE_TYPE_WINDOW;
438 } else if (type == EGL_PIXMAP_BIT) {
440 if (!native_window) {
441 _eglError(EGL_BAD_NATIVE_PIXMAP, "tizen_create_surface needs valid native pixmap");
442 goto cleanup_surface;
445 ret = tpl_display_get_native_pixmap_info(dri2_dpy->tpl_display,
446 (tpl_handle_t)native_window,
447 &dri2_surf->base.Width,
448 &dri2_surf->base.Height,
449 &dri2_surf->tbm_format);
451 if (ret != TPL_ERROR_NONE || dri2_surf->tbm_format == 0) {
452 _eglError(EGL_BAD_NATIVE_PIXMAP, "tizen_create_surface fails on tpl_display_get_native_pixmap_info");
453 goto cleanup_surface;
456 tpl_surf_type = TPL_SURFACE_TYPE_PIXMAP;
459 if(type == EGL_WINDOW_BIT || type == EGL_PIXMAP_BIT) {
460 dri2_surf->tpl_surface = tpl_surface_create(dri2_dpy->tpl_display,
461 (tpl_handle_t)native_window,
463 dri2_surf->tbm_format);
464 if (!dri2_surf->tpl_surface)
465 goto cleanup_surface;
468 if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) {
469 _eglError(EGL_BAD_ALLOC, "createNewDrawable");
470 goto cleanup_tpl_surface;
473 dri2_surf->is_frontbuffer_mode = EGL_FALSE;
474 if (env != NULL && atoi(env))
476 tpl_result_t tpl_result = TPL_ERROR_NONE;
477 tpl_result = tpl_surface_set_frontbuffer_mode(dri2_surf->tpl_surface, TPL_TRUE);
478 if (tpl_result == TPL_ERROR_NONE)
479 dri2_surf->is_frontbuffer_mode = EGL_TRUE;
482 return &dri2_surf->base;
485 tpl_object_unreference((tpl_object_t *)dri2_surf->tpl_surface);
493 tizen_create_window_surface(_EGLDisplay *disp,
494 _EGLConfig *conf, void *native_window,
495 const EGLint *attrib_list)
497 return tizen_create_surface(disp, EGL_WINDOW_BIT, conf,
498 native_window, attrib_list);
502 tizen_create_pixmap_surface(_EGLDisplay *disp,
503 _EGLConfig *conf, void *native_pixmap,
504 const EGLint *attrib_list)
506 return tizen_create_surface(disp, EGL_PIXMAP_BIT, conf,
507 native_pixmap, attrib_list);
511 tizen_create_pbuffer_surface(_EGLDisplay *disp,
512 _EGLConfig *conf, const EGLint *attrib_list)
514 return tizen_create_surface(disp, EGL_PBUFFER_BIT, conf,
519 tizen_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
521 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
522 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
524 tizen_free_local_buffers(dri2_surf);
526 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
527 if (dri2_surf->tbm_surface)
528 tizen_window_cancel_buffer(disp, dri2_surf);
531 if (dri2_surf->dri_image_back) {
532 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__);
533 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
534 dri2_surf->dri_image_back = NULL;
537 if (dri2_surf->dri_image_front) {
538 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__);
539 dri2_dpy->image->destroyImage(dri2_surf->dri_image_front);
540 dri2_surf->dri_image_front = NULL;
543 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
545 if (dri2_surf->tpl_surface)
546 tpl_object_unreference((tpl_object_t *)dri2_surf->tpl_surface);
548 dri2_fini_surface(surf);
556 update_buffers(struct dri2_egl_surface *dri2_surf)
558 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
561 if (dri2_surf->valid == false) {
563 if (dri2_surf->tbm_surface) {
564 tpl_surface_cancel_dequeued_buffer(dri2_surf->tpl_surface,
565 dri2_surf->tbm_surface);
566 tbm_surface_internal_unref(dri2_surf->tbm_surface);
567 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
568 dri2_surf->color_buffers[i].tbm_surface = NULL;
569 dri2_surf->color_buffers[i].age = 0;
572 dri2_surf->back = NULL;
573 dri2_surf->tbm_surface = NULL;
576 /* try to dequeue the next back buffer */
577 if (!dri2_surf->tbm_surface && !tizen_window_dequeue_buffer(dri2_surf)) {
578 _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window");
586 get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)
588 struct dri2_egl_display *dri2_dpy =
589 dri2_egl_display(dri2_surf->base.Resource.Display);
591 if (dri2_surf->dri_image_front)
594 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
595 /* According current EGL spec, front buffer rendering
596 * for window surface is not supported now.
597 * and mesa doesn't have the implementation of this case.
598 * Add warning message, but not treat it as error.
600 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface");
601 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
602 dri2_surf->dri_image_front =
603 dri2_dpy->image->createImage(dri2_dpy->dri_screen,
604 dri2_surf->base.Width,
605 dri2_surf->base.Height,
609 if (!dri2_surf->dri_image_front) {
610 _eglLog(_EGL_WARNING, "dri2_image_front allocation failed");
619 get_back_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)
621 struct dri2_egl_display *dri2_dpy =
622 dri2_egl_display(dri2_surf->base.Resource.Display);
625 tbm_surface_info_s surf_info;
629 if (dri2_surf->dri_image_back) {
630 query = dri2_dpy->image->queryImage(dri2_surf->dri_image_back, __DRI_IMAGE_ATTRIB_WIDTH, &width);
631 query &= dri2_dpy->image->queryImage(dri2_surf->dri_image_back, __DRI_IMAGE_ATTRIB_HEIGHT, &height);
633 if (width == dri2_surf->base.Width && height == dri2_surf->base.Height)
636 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
637 dri2_surf->dri_image_back = NULL;
641 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
642 if (!dri2_surf->tbm_surface) {
643 _eglLog(_EGL_WARNING, "Could not get native buffer");
647 fd = get_native_buffer_fd(dri2_surf->tbm_surface);
649 _eglLog(_EGL_WARNING, "Could not get native buffer FD");
653 if (tbm_surface_get_info(dri2_surf->tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
654 _eglLog(_EGL_WARNING, "Could not get pitch");
658 pitch = surf_info.planes[0].stride;
659 fourcc = get_fourcc(dri2_surf->tbm_format);
661 if (fourcc == -1 || pitch == 0) {
662 _eglLog(_EGL_WARNING, "Invalid buffer fourcc(%x) or pitch(%d)",
667 dri2_surf->base.Width = surf_info.width;
668 dri2_surf->base.Height = surf_info.height;
670 dri2_surf->dri_image_back =
671 dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
672 dri2_surf->base.Width,
673 dri2_surf->base.Height,
681 if (!dri2_surf->dri_image_back) {
682 _eglLog(_EGL_WARNING, "failed to create DRI image from FD");
685 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
686 /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
687 * the spec states that they have a back buffer but no front buffer, in
688 * contrast to pixmaps, which have a front buffer but no back buffer.
690 * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
691 * from the spec, following the precedent of Mesa's EGL X11 platform. The
692 * X11 platform correctly assigns pbuffers to single-buffered configs, but
693 * assigns the pbuffer a front buffer instead of a back buffer.
695 * Pbuffers in the X11 platform mostly work today, so let's just copy its
696 * behavior instead of trying to fix (and hence potentially breaking) the
699 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface");
705 /* Some drivers will pass multiple bits in buffer_mask.
706 * For such case, will go through all the bits, and
707 * will not return error when unsupported buffer is requested, only
708 * return error when the allocation for supported buffer failed.
711 tizen_image_get_buffers(__DRIdrawable *driDrawable, unsigned int format,
712 uint32_t *stamp, void *loaderPrivate,
713 uint32_t buffer_mask, struct __DRIimageList *images)
715 struct dri2_egl_surface *dri2_surf = loaderPrivate;
717 images->image_mask = 0;
718 images->front = NULL;
721 if (update_buffers(dri2_surf) < 0)
724 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
725 if (get_front_bo(dri2_surf, format) < 0)
728 if (dri2_surf->dri_image_front) {
729 images->front = dri2_surf->dri_image_front;
730 images->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
734 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
735 if (get_back_bo(dri2_surf, format) < 0)
738 if (dri2_surf->dri_image_back) {
739 images->back = dri2_surf->dri_image_back;
740 images->image_mask |= __DRI_IMAGE_BUFFER_BACK;
748 tizen_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
750 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
752 if (update_buffers(dri2_surf) < 0) {
753 _eglError(EGL_BAD_ALLOC, "tizen_query_buffer_age");
757 return dri2_surf->back->age;
761 tizen_swap_buffers_with_damage(_EGLDisplay *disp,
762 _EGLSurface *draw, const EGLint *rects,
765 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
766 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
768 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
771 for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
772 if (dri2_surf->color_buffers[i].age > 0)
773 dri2_surf->color_buffers[i].age++;
776 /* In case that application didn't draw anything before swapbuffer,
777 * dri2_surf->tbm_surface will be NULL here, but this should not be
779 if (dri2_surf->tbm_surface) {
780 /* Make sure we have a back buffer in case we're swapping without
782 if (get_back_bo(dri2_surf, 0) < 0) {
783 _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
789 dri2_surf->back->age = 1;
791 TRACE_BEGIN("DRI2_SWAP_BUFERS");
792 /* The buffer to enqueue should be the buffer in which
793 * the gpu drawing job is completed or after flush.
794 * If this is not guaranteed, it can lead to incorrect output.
796 if (dri2_dpy->swrast) {
797 dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
799 dri2_flush_drawable_for_swapbuffers(disp, draw);
800 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
804 if (dri2_surf->tbm_surface)
805 tizen_window_enqueue_buffer_with_damage(disp, dri2_surf, rects, n_rects);
811 tizen_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
813 return tizen_swap_buffers_with_damage (disp, draw, NULL, 0);
817 tizen_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
818 tbm_surface_h tbm_surface)
821 tbm_surface_info_s surf_info;
822 tbm_fd bo_fd[TBM_SURF_PLANE_MAX];
823 tbm_bo bo[TBM_SURF_PLANE_MAX];
827 size_t offsets[3] = {0, 0, 0};
828 size_t pitches[3] = {0, 0, 0};
829 int fds[3] = {-1, -1, -1};
831 if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
832 _eglLog(_EGL_WARNING, "Could not get tbm_surface_info");
836 num_planes = surf_info.num_planes;
837 for (i = 0; i < num_planes; i++) {
838 tbm_bo_handle bo_handle;
839 int bo_idx = tbm_surface_internal_get_plane_bo_idx(tbm_surface, i);
840 bo[i] = tbm_surface_internal_get_bo (tbm_surface, bo_idx);
842 _eglLog(_EGL_WARNING, "Could not get tbm_surface_internal_bo");
845 bo_handle = tbm_bo_get_handle(bo[i], TBM_DEVICE_3D);
846 bo_fd[i] = bo_handle.u32;
849 fourcc = get_fourcc_yuv(tbm_surface_get_format(tbm_surface));
851 _eglLog(_EGL_WARNING, "Unsupported native yuv format");
856 case DRM_FORMAT_NV12:
859 offsets[0] = surf_info.planes[0].offset;
860 offsets[1] = surf_info.planes[1].offset;
861 pitches[0] = surf_info.planes[0].stride;
862 pitches[1] = surf_info.planes[1].stride;
864 case DRM_FORMAT_YUV420:
868 offsets[0] = surf_info.planes[0].offset;
869 offsets[1] = surf_info.planes[1].offset;
870 offsets[2] = surf_info.planes[2].offset;
871 pitches[0] = surf_info.planes[0].stride;
872 pitches[1] = surf_info.planes[1].stride;
873 pitches[2] = surf_info.planes[2].stride;
875 case DRM_FORMAT_YVU420:
879 offsets[0] = surf_info.planes[0].offset;
880 offsets[1] = surf_info.planes[2].offset;
881 offsets[2] = surf_info.planes[1].offset;
882 pitches[0] = surf_info.planes[0].stride;
883 pitches[1] = surf_info.planes[2].stride;
884 pitches[2] = surf_info.planes[1].stride;
887 _eglLog(_EGL_WARNING, "Unsupported native yuv format");
891 if (num_planes == 2) {
892 const EGLint attr_list_2plane[] = {
893 EGL_WIDTH, surf_info.width,
894 EGL_HEIGHT, surf_info.height,
895 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
896 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
897 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
898 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
899 EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
900 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
901 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
904 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_2plane);
905 } else if (num_planes == 3) {
906 const EGLint attr_list_3plane[] = {
907 EGL_WIDTH, surf_info.width,
908 EGL_HEIGHT, surf_info.height,
909 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
910 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
911 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
912 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
913 EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
914 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
915 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
916 EGL_DMA_BUF_PLANE2_FD_EXT, fds[2],
917 EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2],
918 EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2],
921 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_3plane);
923 _eglLog(_EGL_WARNING, "Unsupported yuv planes");
929 tizen_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx,
930 tbm_surface_h tbm_surface , int fd)
933 tbm_surface_info_s surf_info;
934 //unsigned int flags = tbm_bo_get_flags(tbm_surface_internal_get_bo(tbm_surface, 0));
936 if (is_yuv_format(tbm_surface_get_format(tbm_surface)))
937 return tizen_create_image_from_prime_fd_yuv(disp, ctx, tbm_surface);
939 const int fourcc = get_fourcc(tbm_surface_get_format(tbm_surface));
941 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
945 if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
946 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
949 pitch = surf_info.planes[0].stride;
952 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
956 //TODO: get modifier from vendor driver/TBM
957 EGLint attr_list[50];
960 attr_list[atti++] = EGL_WIDTH;
961 attr_list[atti++] = surf_info.width;
962 attr_list[atti++] = EGL_HEIGHT;
963 attr_list[atti++] = surf_info.height;
964 attr_list[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
965 attr_list[atti++] = fourcc;
966 attr_list[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
967 attr_list[atti++] = fd;
968 attr_list[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
969 attr_list[atti++] = pitch;
970 attr_list[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
971 attr_list[atti++] = 0;
973 //TODO: v3d don't support this, need to check
974 /*if (flags == TBM_BO_TILED) {
975 attr_list[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
976 attr_list[atti++] = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED & 0xFFFFFFFF;
977 attr_list[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
978 attr_list[atti++] = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED >> 32;
980 attr_list[atti++] = EGL_NONE;
981 attr_list[atti++] = 0;
983 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list);
987 tizen_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx,
988 tbm_surface_h tbm_surface)
990 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
991 struct dri2_egl_image *dri2_img;
995 tbm_surface_info_s surf_info;
997 name = get_native_buffer_name(tbm_surface);
999 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1003 format = get_format(tbm_surface_get_format(tbm_surface));
1007 if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
1008 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1011 pitch = surf_info.planes[0].stride;
1014 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1018 dri2_img = calloc(1, sizeof(*dri2_img));
1020 _eglError(EGL_BAD_ALLOC, "tizen_create_image_mesa_drm");
1024 _eglInitImage(&dri2_img->base, disp);
1026 dri2_img->dri_image =
1027 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
1034 if (!dri2_img->dri_image) {
1036 _eglError(EGL_BAD_ALLOC, "tizen_create_image_mesa_drm");
1040 return &dri2_img->base;
1044 tizen_query_surface(_EGLDisplay *dpy, _EGLSurface *surf,
1045 EGLint attribute, EGLint *value)
1047 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1048 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1049 int width = 0, height = 0;
1051 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1052 if (tpl_display_get_native_window_info(dri2_dpy->tpl_display,
1053 dri2_surf->native_win,
1054 &width, &height, NULL, 0, 0) != TPL_ERROR_NONE)
1057 switch (attribute) {
1059 if (dri2_surf->native_win) {
1065 if (dri2_surf->native_win) {
1074 return _eglQuerySurface(dpy, surf, attribute, value);
1078 dri2_create_image_tizen_native_buffer(_EGLDisplay *disp,
1080 tbm_surface_h tbm_surface)
1084 fd = get_native_buffer_fd(tbm_surface);
1086 return tizen_create_image_from_prime_fd(disp, ctx, tbm_surface, fd);
1088 return tizen_create_image_from_name(disp, ctx, tbm_surface);
1092 dri2_create_image_tizen_wl_buffer(_EGLDisplay *disp,
1094 tpl_handle_t native_pixmap)
1096 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1098 tbm_surface_h tbm_surface = NULL;
1100 tbm_surface = tpl_display_get_buffer_from_native_pixmap(dri2_dpy->tpl_display,
1101 (tpl_handle_t)native_pixmap);
1105 fd = get_native_buffer_fd(tbm_surface);
1107 return tizen_create_image_from_prime_fd(disp, ctx, tbm_surface, fd);
1109 return tizen_create_image_from_name(disp, ctx, tbm_surface);
1113 tizen_create_image_khr(_EGLDisplay *disp,
1114 _EGLContext *ctx, EGLenum target,
1115 EGLClientBuffer buffer, const EGLint *attr_list)
1118 case EGL_NATIVE_SURFACE_TIZEN:
1119 return dri2_create_image_tizen_native_buffer(disp, ctx,
1120 (tbm_surface_h)buffer);
1121 case EGL_WAYLAND_BUFFER_WL:
1122 return dri2_create_image_tizen_wl_buffer(disp, ctx, (tpl_handle_t)buffer);
1124 return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
1129 tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
1134 tizen_validate_drawable(__DRIdrawable * driDrawable, void *loaderPrivate)
1136 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1138 tpl_result_t res = TPL_ERROR_NONE;
1141 res = tpl_surface_get_size(dri2_surf->tpl_surface, &width, &height);
1142 if (res != TPL_ERROR_NONE)
1145 if ((width != dri2_surf->base.Width) || (height != dri2_surf->base.Height))
1148 dri2_surf->valid = v;
1153 tizen_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
1154 unsigned int *attachments, int count)
1156 int num_buffers = 0, i;
1158 /* fill dri2_surf->buffers */
1159 for (i = 0; i < count * 2; i += 2) {
1160 __DRIbuffer *buf, *local;
1162 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
1163 buf = &dri2_surf->buffers[num_buffers];
1165 switch (attachments[i]) {
1166 case __DRI_BUFFER_BACK_LEFT:
1167 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1168 buf->attachment = attachments[i];
1169 buf->name = get_native_buffer_name(dri2_surf->tbm_surface);
1170 buf->cpp = get_format_bpp(tbm_surface_get_format(dri2_surf->tbm_surface));
1171 buf->pitch = get_pitch(dri2_surf->tbm_surface);
1179 /* fall through for pbuffers */
1180 case __DRI_BUFFER_FRONT_LEFT:
1181 if (dri2_surf->base.Type != EGL_PBUFFER_BIT)
1183 case __DRI_BUFFER_DEPTH:
1184 case __DRI_BUFFER_STENCIL:
1185 case __DRI_BUFFER_ACCUM:
1186 case __DRI_BUFFER_DEPTH_STENCIL:
1187 case __DRI_BUFFER_HIZ:
1188 local = tizen_alloc_local_buffer(dri2_surf, attachments[i], attachments[i + 1]);
1195 case __DRI_BUFFER_FRONT_RIGHT:
1196 case __DRI_BUFFER_FAKE_FRONT_LEFT:
1197 case __DRI_BUFFER_FAKE_FRONT_RIGHT:
1198 case __DRI_BUFFER_BACK_RIGHT:
1200 /* no front or right buffers */
1208 static __DRIbuffer *
1209 tizen_get_buffers_with_format(__DRIdrawable * driDrawable,
1210 int *width, int *height,
1211 unsigned int *attachments, int count,
1212 int *out_count, void *loaderPrivate)
1214 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1216 if (update_buffers(dri2_surf) < 0)
1219 dri2_surf->buffer_count =
1220 tizen_get_buffers_parse_attachments(dri2_surf, attachments, count);
1223 *width = dri2_surf->base.Width;
1225 *height = dri2_surf->base.Height;
1227 *out_count = dri2_surf->buffer_count;
1229 return dri2_surf->buffers;
1233 tizen_swrast_get_stride_for_format(tbm_format format, int w)
1236 case TBM_FORMAT_RGB565:
1238 #pragma GCC diagnostic push
1239 #pragma GCC diagnostic ignored "-Wswitch"
1240 case TBM_FORMAT_BGRA8888:
1241 case TBM_FORMAT_RGBA8888:
1242 #pragma GCC diagnostic pop
1243 case TBM_FORMAT_RGBX8888:
1250 tizen_swrast_get_drawable_info(__DRIdrawable * draw,
1251 int *x, int *y, int *w, int *h,
1252 void *loaderPrivate)
1254 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1256 if (!dri2_surf->tbm_surface) {
1257 if (update_buffers(dri2_surf) < 0)
1263 *w = dri2_surf->base.Width;
1264 *h = dri2_surf->base.Height;
1268 tizen_swrast_get_image(__DRIdrawable * read,
1269 int x, int y, int w, int h,
1270 char *data, void *loaderPrivate)
1272 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1273 tbm_surface_info_s surf_info;
1274 int ret = TBM_SURFACE_ERROR_NONE;
1275 int internal_stride, stride, i;
1277 if (!dri2_surf->tbm_surface) {
1278 if (update_buffers(dri2_surf) < 0)
1282 ret = tbm_surface_map(dri2_surf->tbm_surface, TBM_SURF_OPTION_READ, &surf_info);
1284 if (ret != TBM_SURFACE_ERROR_NONE) {
1285 _eglLog(_EGL_WARNING, "Could not tbm_surface_map");
1289 internal_stride = surf_info.planes[0].stride;
1292 for (i = 0; i < h; i++) {
1293 memcpy(data + i * stride,
1294 surf_info.planes[0].ptr + (x + i) * internal_stride + y, stride);
1297 tbm_surface_unmap(dri2_surf->tbm_surface);
1301 tizen_swrast_put_image2(__DRIdrawable * draw, int op,
1302 int x, int y, int w, int h, int stride,
1303 char *data, void *loaderPrivate)
1305 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1306 tbm_surface_info_s surf_info;
1307 int ret = TBM_SURFACE_ERROR_NONE;
1308 int internal_stride, i;
1310 if (op != __DRI_SWRAST_IMAGE_OP_DRAW &&
1311 op != __DRI_SWRAST_IMAGE_OP_SWAP)
1314 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1315 if (!dri2_surf->tbm_surface) {
1316 if (update_buffers(dri2_surf) < 0) {
1317 _eglLog(_EGL_WARNING, "Could not get native buffer");
1322 ret = tbm_surface_map(dri2_surf->tbm_surface, TBM_SURF_OPTION_WRITE, &surf_info);
1323 if (ret != TBM_SURFACE_ERROR_NONE) {
1324 _eglLog(_EGL_WARNING, "Could not tbm_surface_map");
1328 internal_stride = surf_info.planes[0].stride;
1330 for (i = 0; i < h; i++) {
1331 memcpy(surf_info.planes[0].ptr + (x + i) * internal_stride + y,
1332 data + i * stride, stride);
1335 tbm_surface_unmap(dri2_surf->tbm_surface);
1336 tpl_surface_enqueue_buffer_with_damage_and_sync(dri2_surf->tpl_surface,
1337 dri2_surf->tbm_surface,
1339 tbm_surface_internal_unref(dri2_surf->tbm_surface);
1340 dri2_surf->tbm_surface = NULL;
1341 dri2_surf->back = NULL;
1346 tizen_swrast_put_image(__DRIdrawable * draw, int op,
1347 int x, int y, int w, int h,
1348 char *data, void *loaderPrivate)
1350 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1353 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1354 if (!dri2_surf->tbm_surface) {
1355 if (update_buffers(dri2_surf) < 0) {
1356 _eglLog(_EGL_WARNING, "Could not get native buffer");
1361 stride = tizen_swrast_get_stride_for_format(dri2_surf->tbm_format, w);
1362 tizen_swrast_put_image2(draw, op, x, y, w, h, stride, data, loaderPrivate);
1367 tizen_add_configs(_EGLDisplay *dpy)
1369 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1376 } pbuffer_masks[] = {
1377 { 0xff0000, 0xff00, 0xff, 0xff000000 }, /* ARGB8888 */
1378 { 0xff0000, 0xff00, 0xff, 0x0 }, /* RGB888 */
1379 { 0x00f800, 0x07e0, 0x1f, 0x0 }, /* RGB565 */
1382 for (i = 0, count = 0; dri2_dpy->driver_configs[i]; i++) {
1383 struct dri2_egl_config *dri2_cfg;
1384 unsigned int red, blue, green, alpha, depth;
1385 int surface_type = 0;
1387 EGLint attr_list[] = {
1388 EGL_NATIVE_VISUAL_ID, 0,
1392 struct rgba_masks masks;
1395 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1396 __DRI_ATTRIB_RED_SIZE, &red);
1397 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1398 __DRI_ATTRIB_GREEN_SIZE, &green);
1399 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1400 __DRI_ATTRIB_BLUE_SIZE, &blue);
1401 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1402 __DRI_ATTRIB_ALPHA_SIZE, &alpha);
1403 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1404 __DRI_ATTRIB_DEPTH_SIZE, &depth);
1406 res = tpl_display_query_config(dri2_dpy->tpl_display, TPL_SURFACE_TYPE_WINDOW,
1407 red, green, blue, alpha, depth,
1408 &attr_list[1], &is_slow);
1409 if (res == TPL_ERROR_NONE)
1410 surface_type |= EGL_WINDOW_BIT;
1412 res = tpl_display_query_config(dri2_dpy->tpl_display, TPL_SURFACE_TYPE_PIXMAP,
1413 red, green, blue, alpha, depth,
1414 &attr_list[1], &is_slow);
1415 if (res == TPL_ERROR_NONE)
1416 surface_type |= EGL_PIXMAP_BIT;
1418 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1419 __DRI_ATTRIB_RED_MASK, &masks.red);
1420 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1421 __DRI_ATTRIB_GREEN_MASK, &masks.green);
1422 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1423 __DRI_ATTRIB_BLUE_MASK, &masks.blue);
1424 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1425 __DRI_ATTRIB_ALPHA_MASK, &masks.alpha);
1427 for (j = 0; j < ARRAY_SIZE(pbuffer_masks); j++) {
1428 const struct rgba_masks *pbuffer_mask = &pbuffer_masks[j];
1430 if (pbuffer_mask->red == masks.red &&
1431 pbuffer_mask->green == masks.green &&
1432 pbuffer_mask->blue == masks.blue &&
1433 pbuffer_mask->alpha == masks.alpha) {
1434 surface_type |= EGL_PBUFFER_BIT;
1442 dri2_cfg = dri2_add_config(dpy, dri2_dpy->driver_configs[i], count + 1,
1443 surface_type, &attr_list[0], NULL, NULL);
1448 return (count != 0);
1451 static EGLBoolean tizen_set_swap_interval(_EGLDisplay *dpy,
1452 _EGLSurface *surf, EGLint interval)
1454 tpl_result_t res = TPL_ERROR_NONE;
1455 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1457 res = tpl_surface_set_post_interval(dri2_surf->tpl_surface, interval);
1459 if (res != TPL_ERROR_NONE)
1465 static struct dri2_egl_display_vtbl tizen_display_vtbl = {
1466 .authenticate = NULL,
1467 .create_window_surface = tizen_create_window_surface,
1468 .create_pixmap_surface = tizen_create_pixmap_surface,
1469 .create_pbuffer_surface = tizen_create_pbuffer_surface,
1470 .destroy_surface = tizen_destroy_surface,
1471 .create_image = tizen_create_image_khr,
1472 .swap_interval = tizen_set_swap_interval,
1473 .swap_buffers = tizen_swap_buffers,
1474 .swap_buffers_with_damage = tizen_swap_buffers_with_damage,
1475 .query_buffer_age = tizen_query_buffer_age,
1476 .query_surface = tizen_query_surface,
1477 .create_wayland_buffer_from_image = NULL,
1478 .get_dri_drawable = dri2_surface_get_dri_drawable,
1481 static const __DRIdri2LoaderExtension tizen_dri2_loader_extension = {
1482 .base = { __DRI_DRI2_LOADER, 3 },
1485 .getBuffersWithFormat = tizen_get_buffers_with_format,
1486 .flushFrontBuffer = tizen_flush_front_buffer,
1487 .validate = tizen_validate_drawable,
1490 static const __DRIimageLoaderExtension tizen_image_loader_extension = {
1491 .base = { __DRI_IMAGE_LOADER, 1 },
1493 .getBuffers = tizen_image_get_buffers,
1494 .flushFrontBuffer = tizen_flush_front_buffer,
1495 .validate = tizen_validate_drawable,
1498 static const __DRIswrastLoaderExtension tizen_swrast_loader_extension = {
1499 .base = { __DRI_SWRAST_LOADER, 2 },
1501 .getDrawableInfo = tizen_swrast_get_drawable_info,
1502 .putImage = tizen_swrast_put_image,
1503 .getImage = tizen_swrast_get_image,
1504 .putImage2 = tizen_swrast_put_image2,
1507 static const __DRIextension *tizen_dri2_loader_extensions[] = {
1508 &tizen_dri2_loader_extension.base,
1509 &tizen_image_loader_extension.base,
1510 &image_lookup_extension.base,
1511 &use_invalidate.base,
1515 static const __DRIextension *tizen_image_loader_extensions[] = {
1516 &tizen_image_loader_extension.base,
1517 &image_lookup_extension.base,
1518 &use_invalidate.base,
1522 static const __DRIextension *tizen_swrast_loader_extensions[] = {
1523 &tizen_swrast_loader_extension.base,
1524 &image_lookup_extension.base,
1529 tizen_swrast_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
1531 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1532 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
1534 dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
1538 static const struct dri2_egl_display_vtbl tizen_swrast_display_vtbl = {
1539 .authenticate = NULL,
1540 .create_window_surface = tizen_create_window_surface,
1541 .create_pixmap_surface = tizen_create_pixmap_surface,
1542 .create_pbuffer_surface = tizen_create_pbuffer_surface,
1543 .destroy_surface = tizen_destroy_surface,
1544 .create_image = tizen_create_image_khr,
1545 .swap_buffers = tizen_swrast_swap_buffers,
1546 .get_dri_drawable = dri2_surface_get_dri_drawable,
1551 dri2_initialize_tizen(_EGLDisplay *disp)
1554 struct dri2_egl_display *dri2_dpy;
1555 tpl_display_t *tpl_display = NULL;
1556 tpl_backend_type_t tpl_backend = TPL_BACKEND_UNKNOWN;
1558 int tbm_bufmgr_fd = -1;
1560 char *tbm_bufmgr_device_name = NULL;
1561 int hw_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
1563 loader_set_logger(_eglLog);
1565 dri2_dpy = calloc(1, sizeof *dri2_dpy);
1567 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1569 disp->DriverData = (void *) dri2_dpy;
1571 /* Allocate an new native display, if argument passed to
1572 eglGetDisplay() is EGL_DEFAULT_DISPLAY, it will cause
1573 error in __tpl_wayland_egl_display_init() */
1574 if (disp->PlatformDisplay == NULL) {
1575 disp->PlatformDisplay = wl_display_connect(NULL);
1576 if (disp->PlatformDisplay == NULL) {
1577 err = "DRI2: failed to get native display";
1578 goto cleanup_display;
1580 dri2_dpy->own_device = 1;
1583 /* Can find the backend type of libtpl-egl through PlatformDisplay */
1584 tpl_backend = tpl_display_get_backend_type(disp->PlatformDisplay);
1585 /* If tpl_backend is a wayland client, thread backend should be used
1586 * to use dri2_surf->out_fence_fd. */
1587 if (tpl_backend == TPL_BACKEND_WAYLAND)
1588 tpl_backend = TPL_BACKEND_WAYLAND_THREAD;
1590 tpl_display = tpl_display_create(tpl_backend, disp->PlatformDisplay);
1592 err = "DRI2: failed to create tpl_display";
1593 goto cleanup_display;
1595 dri2_dpy->tpl_display = tpl_display;
1597 /* Get tbm_bufmgr's fd */
1598 tbm_bufmgr_fd = tbm_drm_helper_get_fd();
1599 if (tbm_bufmgr_fd == -1) {
1600 err = "DRI2: failed to get tbm_bufmgr fd";
1601 goto cleanup_device;
1605 #if 0//FOR REF: it's another way, to open v3d directly
1606 #define MAX_DRM_DEVICES 32
1607 drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL };
1609 num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
1610 for (int i = 0; i < num_devices; i++) {
1611 device = devices[i];
1613 if (!(device->available_nodes & (1 << DRM_NODE_RENDER)))
1616 dri2_dpy->fd = loader_open_device(device->nodes[DRM_NODE_RENDER]);
1617 if (dri2_dpy->fd < 0) {
1618 _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s",
1619 __func__, device->nodes[DRM_NODE_RENDER]);
1625 drmFreeDevices(devices, num_devices);
1628 if (drmGetNodeTypeFromFd(tbm_bufmgr_fd) == DRM_NODE_RENDER) {
1630 tbm_bufmgr_device_name = loader_get_device_name_for_fd(tbm_bufmgr_fd);
1631 if (tbm_bufmgr_device_name == NULL) {
1632 err = "DRI2: failed to get tbm_bufmgr device name";
1633 goto cleanup_device;
1635 dri2_dpy->fd = loader_open_device(tbm_bufmgr_device_name);
1637 } else if ((master_fd = tbm_drm_helper_get_master_fd()) >= 0) {
1639 // display server always has master_fd,
1640 // so tbm_bufmgr_fd is the master_fd if it can get the tbm_master_fd.
1641 tbm_bufmgr_device_name = loader_get_device_name_for_fd(tbm_bufmgr_fd);
1642 if (tbm_bufmgr_device_name == NULL) {
1643 err = "DRI2: failed to get tbm_bufmgr device name";
1644 goto cleanup_device;
1646 dri2_dpy->fd = loader_open_device(tbm_bufmgr_device_name);
1648 if (!tbm_drm_helper_get_auth_info(&dri2_dpy->fd, NULL, NULL)) {
1649 err = "DRI2: failed to get fd from tbm_drm_helper_get_auth_info()";
1650 goto cleanup_device;
1654 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
1655 if (dri2_dpy->driver_name == NULL) {
1656 err = "DRI2: failed to get driver name";
1657 goto cleanup_device;
1660 dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
1661 /* render nodes cannot use Gem names, and thus do not support
1662 * the __DRI_DRI2_LOADER extension */
1664 if (!dri2_dpy->is_render_node) {
1665 dri2_dpy->loader_extensions = tizen_dri2_loader_extensions;
1666 if (!dri2_load_driver(disp)) {
1667 err = "DRI2: failed to load driver";
1668 goto cleanup_driver_name;
1671 dri2_dpy->loader_extensions = tizen_image_loader_extensions;
1672 if (!dri2_load_driver_dri3(disp)) {
1673 err = "DRI3: failed to load driver";
1674 goto cleanup_driver_name;
1678 dri2_dpy->fd = tbm_bufmgr_fd;
1679 dri2_dpy->driver_name = strdup("swrast");
1680 if (!dri2_load_driver_swrast(disp)) {
1681 err = "DRI2: failed to load swrast driver";
1682 goto cleanup_device;
1684 dri2_dpy->loader_extensions = tizen_swrast_loader_extensions;
1687 if (!dri2_create_screen(disp)) {
1688 err = "DRI2: failed to create screen";
1689 goto cleanup_driver;
1693 dev = _eglAddDevice(dri2_dpy->fd, false);
1695 err = "DRI2: failed to find EGLDevice";
1696 goto cleanup_screen;;
1701 if(dri2_dpy->fd != tbm_bufmgr_fd) {
1702 close(dri2_dpy->fd);
1704 close(tbm_bufmgr_fd);
1708 if (!dri2_setup_extensions(disp)) {
1709 err = "DRI2: failed to find required DRI extensions";
1710 goto cleanup_screen;
1713 dri2_setup_screen(disp);
1715 dri2_setup_swap_interval(disp, 1);
1717 if (!tizen_add_configs(disp)) {
1718 err = "DRI2: failed to add configs";
1719 goto cleanup_screen;
1722 /* Fill vtbl last to prevent accidentally calling virtual function during
1726 dri2_dpy->vtbl = &tizen_display_vtbl;
1728 dri2_dpy->vtbl = &tizen_swrast_display_vtbl;
1730 disp->Extensions.EXT_buffer_age = EGL_FALSE;
1731 disp->Extensions.EXT_swap_buffers_with_damage = EGL_FALSE; /*disable partial buffer swap*/
1732 disp->Extensions.TIZEN_image_native_surface = EGL_TRUE;
1733 disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
1734 disp->Extensions.WL_create_wayland_buffer_from_image = EGL_FALSE;
1735 disp->Extensions.KHR_fence_sync = EGL_TRUE;
1737 if (dri2_dpy->fence->base.version >= 2 &&
1738 dri2_dpy->fence->get_capabilities) {
1739 unsigned capabilities =
1740 dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen);
1741 disp->Extensions.TIZEN_native_fence_sync =
1742 (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0;
1743 disp->Extensions.ANDROID_native_fence_sync = disp->Extensions.TIZEN_native_fence_sync;
1749 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1751 dlclose(dri2_dpy->driver);
1752 cleanup_driver_name:
1753 free(dri2_dpy->driver_name);
1755 tpl_object_unreference((tpl_object_t *)tpl_display);
1757 if (dri2_dpy->own_device) {
1758 wl_display_disconnect(disp->PlatformDisplay);
1759 disp->PlatformDisplay = NULL;
1762 disp->DriverData = NULL;
1764 return _eglError(EGL_NOT_INITIALIZED, err);
1768 dri2_teardown_tizen(_EGLDisplay *disp)
1770 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1772 if (dri2_dpy->tpl_display)
1773 tpl_object_unreference((tpl_object_t *)(dri2_dpy->tpl_display));
1775 if (tbm_bufmgr_fd > 0)
1776 close(tbm_bufmgr_fd);
1778 if (dri2_dpy->own_device)
1779 wl_display_disconnect(disp->PlatformDisplay);