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_render_gpu, 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 fence_fd = dri2_surf->out_fence_fd;
302 if (fence_fd >= 0 && dri2_surf->is_frontbuffer_mode) {
307 dri2_surf->out_fence_fd = -1;
309 ret = tpl_surface_enqueue_buffer_with_damage_and_sync(dri2_surf->tpl_surface,
310 dri2_surf->tbm_surface,
314 if (ret != TPL_ERROR_NONE) {
315 _eglLog(_EGL_DEBUG, "%s : %d :tpl_surface_enqueue fail", __func__, __LINE__);
318 tbm_surface_internal_unref(dri2_surf->tbm_surface);
319 dri2_surf->tbm_surface = NULL;
320 dri2_surf->back = NULL;
322 if (dri2_surf->dri_image_back) {
323 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
324 dri2_surf->dri_image_back = NULL;
331 tizen_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
333 return tizen_window_enqueue_buffer_with_damage(disp, dri2_surf, NULL, 0);
337 tizen_window_cancel_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf)
339 tizen_window_enqueue_buffer(disp, dri2_surf);
343 tizen_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
344 unsigned int att, unsigned int format)
346 struct dri2_egl_display *dri2_dpy =
347 dri2_egl_display(dri2_surf->base.Resource.Display);
349 if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
352 if (!dri2_surf->local_buffers[att]) {
353 dri2_surf->local_buffers[att] =
354 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen_render_gpu, att, format,
355 dri2_surf->base.Width, dri2_surf->base.Height);
358 return dri2_surf->local_buffers[att];
362 tizen_free_local_buffers(struct dri2_egl_surface *dri2_surf)
364 struct dri2_egl_display *dri2_dpy =
365 dri2_egl_display(dri2_surf->base.Resource.Display);
368 for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
369 if (dri2_surf->local_buffers[i]) {
370 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen_render_gpu,
371 dri2_surf->local_buffers[i]);
372 dri2_surf->local_buffers[i] = NULL;
378 tizen_create_surface(_EGLDisplay *disp, EGLint type,
379 _EGLConfig *conf, void *native_window,
380 const EGLint *attrib_list)
382 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
383 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
384 struct dri2_egl_surface *dri2_surf;
385 const __DRIconfig *config;
386 tpl_surface_type_t tpl_surf_type = TPL_SURFACE_ERROR;
387 tpl_result_t ret = TPL_ERROR_INVALID_PARAMETER;
388 char *env = getenv("EGL_FRONTBUFFER_ENABLE");
390 dri2_surf = calloc(1, sizeof *dri2_surf);
392 _eglError(EGL_BAD_ALLOC, "tizen_create_surface");
396 if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,
397 true, native_window))
398 goto cleanup_surface;
400 config = dri2_get_dri_config(dri2_conf, type,
401 dri2_surf->base.GLColorspace);
403 goto cleanup_surface;
405 if (type == EGL_WINDOW_BIT) {
406 unsigned int alpha, depth;
408 if (!native_window) {
409 _eglError(EGL_BAD_NATIVE_WINDOW, "tizen_create_surface needs vaild native window");
410 goto cleanup_surface;
412 dri2_surf->native_win = native_window;
413 dri2_surf->valid = true;
414 dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_DEPTH_SIZE, &depth);
415 dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SIZE, &alpha);
417 ret = tpl_display_get_native_window_info(dri2_dpy->tpl_display,
418 (tpl_handle_t)native_window,
419 &dri2_surf->base.Width,
420 &dri2_surf->base.Height,
421 &dri2_surf->tbm_format,
424 if (ret != TPL_ERROR_NONE || dri2_surf->tbm_format == 0) {
425 _eglError(EGL_BAD_NATIVE_WINDOW, "tizen_create_surface fails on tpl_display_get_native_window_info()");
426 goto cleanup_surface;
429 tpl_surf_type = TPL_SURFACE_TYPE_WINDOW;
430 } else if (type == EGL_PIXMAP_BIT) {
432 if (!native_window) {
433 _eglError(EGL_BAD_NATIVE_PIXMAP, "tizen_create_surface needs valid native pixmap");
434 goto cleanup_surface;
437 ret = tpl_display_get_native_pixmap_info(dri2_dpy->tpl_display,
438 (tpl_handle_t)native_window,
439 &dri2_surf->base.Width,
440 &dri2_surf->base.Height,
441 &dri2_surf->tbm_format);
443 if (ret != TPL_ERROR_NONE || dri2_surf->tbm_format == 0) {
444 _eglError(EGL_BAD_NATIVE_PIXMAP, "tizen_create_surface fails on tpl_display_get_native_pixmap_info");
445 goto cleanup_surface;
448 tpl_surf_type = TPL_SURFACE_TYPE_PIXMAP;
451 if(type == EGL_WINDOW_BIT || type == EGL_PIXMAP_BIT) {
452 dri2_surf->tpl_surface = tpl_surface_create(dri2_dpy->tpl_display,
453 (tpl_handle_t)native_window,
455 dri2_surf->tbm_format);
456 if (!dri2_surf->tpl_surface)
457 goto cleanup_surface;
460 if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) {
461 _eglError(EGL_BAD_ALLOC, "createNewDrawable");
462 goto cleanup_tpl_surface;
465 dri2_surf->is_frontbuffer_mode = EGL_FALSE;
466 if (env != NULL && atoi(env))
468 tpl_result_t tpl_result = TPL_ERROR_NONE;
469 tpl_result = tpl_surface_set_frontbuffer_mode(dri2_surf->tpl_surface, TPL_TRUE);
470 if (tpl_result == TPL_ERROR_NONE)
471 dri2_surf->is_frontbuffer_mode = EGL_TRUE;
474 return &dri2_surf->base;
477 tpl_object_unreference((tpl_object_t *)dri2_surf->tpl_surface);
485 tizen_create_window_surface(_EGLDisplay *disp,
486 _EGLConfig *conf, void *native_window,
487 const EGLint *attrib_list)
489 return tizen_create_surface(disp, EGL_WINDOW_BIT, conf,
490 native_window, attrib_list);
494 tizen_create_pixmap_surface(_EGLDisplay *disp,
495 _EGLConfig *conf, void *native_pixmap,
496 const EGLint *attrib_list)
498 return tizen_create_surface(disp, EGL_PIXMAP_BIT, conf,
499 native_pixmap, attrib_list);
503 tizen_create_pbuffer_surface(_EGLDisplay *disp,
504 _EGLConfig *conf, const EGLint *attrib_list)
506 return tizen_create_surface(disp, EGL_PBUFFER_BIT, conf,
511 tizen_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
513 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
514 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
516 tizen_free_local_buffers(dri2_surf);
518 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
519 if (dri2_surf->tbm_surface)
520 tizen_window_cancel_buffer(disp, dri2_surf);
523 if (dri2_surf->dri_image_back) {
524 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_back", __func__, __LINE__);
525 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
526 dri2_surf->dri_image_back = NULL;
529 if (dri2_surf->dri_image_front) {
530 _eglLog(_EGL_DEBUG, "%s : %d : destroy dri_image_front", __func__, __LINE__);
531 dri2_dpy->image->destroyImage(dri2_surf->dri_image_front);
532 dri2_surf->dri_image_front = NULL;
535 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
537 if (dri2_surf->tpl_surface)
538 tpl_object_unreference((tpl_object_t *)dri2_surf->tpl_surface);
540 dri2_fini_surface(surf);
548 update_buffers(struct dri2_egl_surface *dri2_surf)
550 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
553 if (dri2_surf->valid == false) {
555 if (dri2_surf->tbm_surface) {
556 tpl_surface_cancel_dequeued_buffer(dri2_surf->tpl_surface,
557 dri2_surf->tbm_surface);
558 tbm_surface_internal_unref(dri2_surf->tbm_surface);
559 for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
560 dri2_surf->color_buffers[i].tbm_surface = NULL;
561 dri2_surf->color_buffers[i].age = 0;
564 dri2_surf->back = NULL;
565 dri2_surf->tbm_surface = NULL;
568 /* try to dequeue the next back buffer */
569 if (!dri2_surf->tbm_surface && !tizen_window_dequeue_buffer(dri2_surf)) {
570 _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window");
578 get_front_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)
580 struct dri2_egl_display *dri2_dpy =
581 dri2_egl_display(dri2_surf->base.Resource.Display);
583 if (dri2_surf->dri_image_front)
586 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
587 /* According current EGL spec, front buffer rendering
588 * for window surface is not supported now.
589 * and mesa doesn't have the implementation of this case.
590 * Add warning message, but not treat it as error.
592 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported front buffer for window surface");
593 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
594 dri2_surf->dri_image_front =
595 dri2_dpy->image->createImage(dri2_dpy->dri_screen_render_gpu,
596 dri2_surf->base.Width,
597 dri2_surf->base.Height,
601 if (!dri2_surf->dri_image_front) {
602 _eglLog(_EGL_WARNING, "dri2_image_front allocation failed");
611 get_back_bo(struct dri2_egl_surface *dri2_surf, unsigned int format)
613 struct dri2_egl_display *dri2_dpy =
614 dri2_egl_display(dri2_surf->base.Resource.Display);
617 tbm_surface_info_s surf_info;
621 if (dri2_surf->dri_image_back) {
622 query = dri2_dpy->image->queryImage(dri2_surf->dri_image_back, __DRI_IMAGE_ATTRIB_WIDTH, &width);
623 query &= dri2_dpy->image->queryImage(dri2_surf->dri_image_back, __DRI_IMAGE_ATTRIB_HEIGHT, &height);
625 if (width == dri2_surf->base.Width && height == dri2_surf->base.Height)
628 dri2_dpy->image->destroyImage(dri2_surf->dri_image_back);
629 dri2_surf->dri_image_back = NULL;
633 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
634 if (!dri2_surf->tbm_surface) {
635 _eglLog(_EGL_WARNING, "Could not get native buffer");
639 fd = get_native_buffer_fd(dri2_surf->tbm_surface);
641 _eglLog(_EGL_WARNING, "Could not get native buffer FD");
645 if (tbm_surface_get_info(dri2_surf->tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
646 _eglLog(_EGL_WARNING, "Could not get pitch");
650 pitch = surf_info.planes[0].stride;
651 fourcc = get_fourcc(dri2_surf->tbm_format);
653 if (fourcc == -1 || pitch == 0) {
654 _eglLog(_EGL_WARNING, "Invalid buffer fourcc(%x) or pitch(%d)",
659 dri2_surf->base.Width = surf_info.width;
660 dri2_surf->base.Height = surf_info.height;
662 dri2_surf->dri_image_back =
663 dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen_render_gpu,
664 dri2_surf->base.Width,
665 dri2_surf->base.Height,
673 if (!dri2_surf->dri_image_back) {
674 _eglLog(_EGL_WARNING, "failed to create DRI image from FD");
677 } else if (dri2_surf->base.Type == EGL_PBUFFER_BIT) {
678 /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
679 * the spec states that they have a back buffer but no front buffer, in
680 * contrast to pixmaps, which have a front buffer but no back buffer.
682 * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
683 * from the spec, following the precedent of Mesa's EGL X11 platform. The
684 * X11 platform correctly assigns pbuffers to single-buffered configs, but
685 * assigns the pbuffer a front buffer instead of a back buffer.
687 * Pbuffers in the X11 platform mostly work today, so let's just copy its
688 * behavior instead of trying to fix (and hence potentially breaking) the
691 _eglLog(_EGL_DEBUG, "DRI driver requested unsupported back buffer for pbuffer surface");
697 /* Some drivers will pass multiple bits in buffer_mask.
698 * For such case, will go through all the bits, and
699 * will not return error when unsupported buffer is requested, only
700 * return error when the allocation for supported buffer failed.
703 tizen_image_get_buffers(__DRIdrawable *driDrawable, unsigned int format,
704 uint32_t *stamp, void *loaderPrivate,
705 uint32_t buffer_mask, struct __DRIimageList *images)
707 struct dri2_egl_surface *dri2_surf = loaderPrivate;
709 images->image_mask = 0;
710 images->front = NULL;
713 if (update_buffers(dri2_surf) < 0)
716 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
717 if (get_front_bo(dri2_surf, format) < 0)
720 if (dri2_surf->dri_image_front) {
721 images->front = dri2_surf->dri_image_front;
722 images->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
726 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
727 if (get_back_bo(dri2_surf, format) < 0)
730 if (dri2_surf->dri_image_back) {
731 images->back = dri2_surf->dri_image_back;
732 images->image_mask |= __DRI_IMAGE_BUFFER_BACK;
740 tizen_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
742 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
744 if (update_buffers(dri2_surf) < 0) {
745 _eglError(EGL_BAD_ALLOC, "tizen_query_buffer_age");
749 return dri2_surf->back->age;
753 tizen_swap_buffers_with_damage(_EGLDisplay *disp,
754 _EGLSurface *draw, const EGLint *rects,
757 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
758 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
760 if (dri2_surf->base.Type != EGL_WINDOW_BIT)
763 for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
764 if (dri2_surf->color_buffers[i].age > 0)
765 dri2_surf->color_buffers[i].age++;
768 /* In case that application didn't draw anything before swapbuffer,
769 * dri2_surf->tbm_surface will be NULL here, but this should not be
771 if (dri2_surf->tbm_surface) {
772 /* Make sure we have a back buffer in case we're swapping without
774 if (get_back_bo(dri2_surf, 0) < 0) {
775 _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
781 dri2_surf->back->age = 1;
783 TRACE_BEGIN("DRI2_SWAP_BUFERS");
784 /* The buffer to enqueue should be the buffer in which
785 * the gpu drawing job is completed or after flush.
786 * If this is not guaranteed, it can lead to incorrect output.
788 if (dri2_dpy->swrast) {
789 dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
791 dri2_flush_drawable_for_swapbuffers(disp, draw);
792 dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
796 if (dri2_surf->tbm_surface)
797 tizen_window_enqueue_buffer_with_damage(disp, dri2_surf, rects, n_rects);
803 tizen_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
805 return tizen_swap_buffers_with_damage (disp, draw, NULL, 0);
809 tizen_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
810 tbm_surface_h tbm_surface)
813 tbm_surface_info_s surf_info;
814 tbm_fd bo_fd[TBM_SURF_PLANE_MAX];
815 tbm_bo bo[TBM_SURF_PLANE_MAX];
819 size_t offsets[3] = {0, 0, 0};
820 size_t pitches[3] = {0, 0, 0};
821 int fds[3] = {-1, -1, -1};
823 if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
824 _eglLog(_EGL_WARNING, "Could not get tbm_surface_info");
828 num_planes = surf_info.num_planes;
829 for (i = 0; i < num_planes; i++) {
830 tbm_bo_handle bo_handle;
831 int bo_idx = tbm_surface_internal_get_plane_bo_idx(tbm_surface, i);
832 bo[i] = tbm_surface_internal_get_bo (tbm_surface, bo_idx);
834 _eglLog(_EGL_WARNING, "Could not get tbm_surface_internal_bo");
837 bo_handle = tbm_bo_get_handle(bo[i], TBM_DEVICE_3D);
838 bo_fd[i] = bo_handle.u32;
841 fourcc = get_fourcc_yuv(tbm_surface_get_format(tbm_surface));
843 _eglLog(_EGL_WARNING, "Unsupported native yuv format");
848 case DRM_FORMAT_NV12:
851 offsets[0] = surf_info.planes[0].offset;
852 offsets[1] = surf_info.planes[1].offset;
853 pitches[0] = surf_info.planes[0].stride;
854 pitches[1] = surf_info.planes[1].stride;
856 case DRM_FORMAT_YUV420:
860 offsets[0] = surf_info.planes[0].offset;
861 offsets[1] = surf_info.planes[1].offset;
862 offsets[2] = surf_info.planes[2].offset;
863 pitches[0] = surf_info.planes[0].stride;
864 pitches[1] = surf_info.planes[1].stride;
865 pitches[2] = surf_info.planes[2].stride;
867 case DRM_FORMAT_YVU420:
871 offsets[0] = surf_info.planes[0].offset;
872 offsets[1] = surf_info.planes[2].offset;
873 offsets[2] = surf_info.planes[1].offset;
874 pitches[0] = surf_info.planes[0].stride;
875 pitches[1] = surf_info.planes[2].stride;
876 pitches[2] = surf_info.planes[1].stride;
879 _eglLog(_EGL_WARNING, "Unsupported native yuv format");
883 if (num_planes == 2) {
884 const EGLint attr_list_2plane[] = {
885 EGL_WIDTH, surf_info.width,
886 EGL_HEIGHT, surf_info.height,
887 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
888 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
889 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
890 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
891 EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
892 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
893 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
896 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_2plane);
897 } else if (num_planes == 3) {
898 const EGLint attr_list_3plane[] = {
899 EGL_WIDTH, surf_info.width,
900 EGL_HEIGHT, surf_info.height,
901 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
902 EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
903 EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
904 EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
905 EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
906 EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
907 EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
908 EGL_DMA_BUF_PLANE2_FD_EXT, fds[2],
909 EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2],
910 EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2],
913 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_3plane);
915 _eglLog(_EGL_WARNING, "Unsupported yuv planes");
921 tizen_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx,
922 tbm_surface_h tbm_surface , int fd)
925 tbm_surface_info_s surf_info;
926 //unsigned int flags = tbm_bo_get_flags(tbm_surface_internal_get_bo(tbm_surface, 0));
928 if (is_yuv_format(tbm_surface_get_format(tbm_surface)))
929 return tizen_create_image_from_prime_fd_yuv(disp, ctx, tbm_surface);
931 const int fourcc = get_fourcc(tbm_surface_get_format(tbm_surface));
933 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
937 if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
938 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
941 pitch = surf_info.planes[0].stride;
944 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
948 //TODO: get modifier from vendor driver/TBM
949 EGLint attr_list[50];
952 attr_list[atti++] = EGL_WIDTH;
953 attr_list[atti++] = surf_info.width;
954 attr_list[atti++] = EGL_HEIGHT;
955 attr_list[atti++] = surf_info.height;
956 attr_list[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
957 attr_list[atti++] = fourcc;
958 attr_list[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
959 attr_list[atti++] = fd;
960 attr_list[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
961 attr_list[atti++] = pitch;
962 attr_list[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
963 attr_list[atti++] = 0;
965 //TODO: v3d don't support this, need to check
966 /*if (flags == TBM_BO_TILED) {
967 attr_list[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
968 attr_list[atti++] = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED & 0xFFFFFFFF;
969 attr_list[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
970 attr_list[atti++] = DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED >> 32;
972 attr_list[atti++] = EGL_NONE;
973 attr_list[atti++] = 0;
975 return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list);
979 tizen_create_image_from_name(_EGLDisplay *disp, _EGLContext *ctx,
980 tbm_surface_h tbm_surface)
982 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
983 struct dri2_egl_image *dri2_img;
987 tbm_surface_info_s surf_info;
989 name = get_native_buffer_name(tbm_surface);
991 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
995 format = get_format(tbm_surface_get_format(tbm_surface));
999 if (tbm_surface_get_info(tbm_surface, &surf_info) != TBM_SURFACE_ERROR_NONE) {
1000 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1003 pitch = surf_info.planes[0].stride;
1006 _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
1010 dri2_img = calloc(1, sizeof(*dri2_img));
1012 _eglError(EGL_BAD_ALLOC, "tizen_create_image_mesa_drm");
1016 _eglInitImage(&dri2_img->base, disp);
1018 dri2_img->dri_image =
1019 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen_render_gpu,
1026 if (!dri2_img->dri_image) {
1028 _eglError(EGL_BAD_ALLOC, "tizen_create_image_mesa_drm");
1032 return &dri2_img->base;
1036 tizen_query_surface(_EGLDisplay *dpy, _EGLSurface *surf,
1037 EGLint attribute, EGLint *value)
1039 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1040 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1041 int width = 0, height = 0;
1043 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1044 if (tpl_display_get_native_window_info(dri2_dpy->tpl_display,
1045 dri2_surf->native_win,
1046 &width, &height, NULL, 0, 0) != TPL_ERROR_NONE)
1049 switch (attribute) {
1051 if (dri2_surf->native_win) {
1057 if (dri2_surf->native_win) {
1066 return _eglQuerySurface(dpy, surf, attribute, value);
1070 dri2_create_image_tizen_native_buffer(_EGLDisplay *disp,
1072 tbm_surface_h tbm_surface)
1076 fd = get_native_buffer_fd(tbm_surface);
1078 return tizen_create_image_from_prime_fd(disp, ctx, tbm_surface, fd);
1080 return tizen_create_image_from_name(disp, ctx, tbm_surface);
1084 dri2_create_image_tizen_wl_buffer(_EGLDisplay *disp,
1086 tpl_handle_t native_pixmap)
1088 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1090 tbm_surface_h tbm_surface = NULL;
1092 tbm_surface = tpl_display_get_buffer_from_native_pixmap(dri2_dpy->tpl_display,
1093 (tpl_handle_t)native_pixmap);
1097 fd = get_native_buffer_fd(tbm_surface);
1099 return tizen_create_image_from_prime_fd(disp, ctx, tbm_surface, fd);
1101 return tizen_create_image_from_name(disp, ctx, tbm_surface);
1105 tizen_create_image_khr(_EGLDisplay *disp,
1106 _EGLContext *ctx, EGLenum target,
1107 EGLClientBuffer buffer, const EGLint *attr_list)
1110 case EGL_NATIVE_SURFACE_TIZEN:
1111 return dri2_create_image_tizen_native_buffer(disp, ctx,
1112 (tbm_surface_h)buffer);
1113 case EGL_WAYLAND_BUFFER_WL:
1114 return dri2_create_image_tizen_wl_buffer(disp, ctx, (tpl_handle_t)buffer);
1116 return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
1121 tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
1126 tizen_validate_drawable(__DRIdrawable * driDrawable, void *loaderPrivate)
1128 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1130 tpl_result_t res = TPL_ERROR_NONE;
1133 res = tpl_surface_get_size(dri2_surf->tpl_surface, &width, &height);
1134 if (res != TPL_ERROR_NONE)
1137 if ((width != dri2_surf->base.Width) || (height != dri2_surf->base.Height))
1140 dri2_surf->valid = v;
1145 tizen_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
1146 unsigned int *attachments, int count)
1148 int num_buffers = 0, i;
1150 /* fill dri2_surf->buffers */
1151 for (i = 0; i < count * 2; i += 2) {
1152 __DRIbuffer *buf, *local;
1154 assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
1155 buf = &dri2_surf->buffers[num_buffers];
1157 switch (attachments[i]) {
1158 case __DRI_BUFFER_BACK_LEFT:
1159 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1160 buf->attachment = attachments[i];
1161 buf->name = get_native_buffer_name(dri2_surf->tbm_surface);
1162 buf->cpp = get_format_bpp(tbm_surface_get_format(dri2_surf->tbm_surface));
1163 buf->pitch = get_pitch(dri2_surf->tbm_surface);
1171 /* fall through for pbuffers */
1172 case __DRI_BUFFER_FRONT_LEFT:
1173 if (dri2_surf->base.Type != EGL_PBUFFER_BIT)
1175 case __DRI_BUFFER_DEPTH:
1176 case __DRI_BUFFER_STENCIL:
1177 case __DRI_BUFFER_ACCUM:
1178 case __DRI_BUFFER_DEPTH_STENCIL:
1179 case __DRI_BUFFER_HIZ:
1180 local = tizen_alloc_local_buffer(dri2_surf, attachments[i], attachments[i + 1]);
1187 case __DRI_BUFFER_FRONT_RIGHT:
1188 case __DRI_BUFFER_FAKE_FRONT_LEFT:
1189 case __DRI_BUFFER_FAKE_FRONT_RIGHT:
1190 case __DRI_BUFFER_BACK_RIGHT:
1192 /* no front or right buffers */
1200 static __DRIbuffer *
1201 tizen_get_buffers_with_format(__DRIdrawable * driDrawable,
1202 int *width, int *height,
1203 unsigned int *attachments, int count,
1204 int *out_count, void *loaderPrivate)
1206 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1208 if (update_buffers(dri2_surf) < 0)
1211 dri2_surf->buffer_count =
1212 tizen_get_buffers_parse_attachments(dri2_surf, attachments, count);
1215 *width = dri2_surf->base.Width;
1217 *height = dri2_surf->base.Height;
1219 *out_count = dri2_surf->buffer_count;
1221 return dri2_surf->buffers;
1225 tizen_swrast_get_stride_for_format(tbm_format format, int w)
1228 case TBM_FORMAT_RGB565:
1230 #pragma GCC diagnostic push
1231 #pragma GCC diagnostic ignored "-Wswitch"
1232 case TBM_FORMAT_BGRA8888:
1233 case TBM_FORMAT_RGBA8888:
1234 #pragma GCC diagnostic pop
1235 case TBM_FORMAT_RGBX8888:
1242 tizen_swrast_get_drawable_info(__DRIdrawable * draw,
1243 int *x, int *y, int *w, int *h,
1244 void *loaderPrivate)
1246 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1248 if (!dri2_surf->tbm_surface) {
1249 if (update_buffers(dri2_surf) < 0)
1255 *w = dri2_surf->base.Width;
1256 *h = dri2_surf->base.Height;
1260 tizen_swrast_get_image(__DRIdrawable * read,
1261 int x, int y, int w, int h,
1262 char *data, void *loaderPrivate)
1264 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1265 tbm_surface_info_s surf_info;
1266 int ret = TBM_SURFACE_ERROR_NONE;
1267 int internal_stride, stride, i;
1269 if (!dri2_surf->tbm_surface) {
1270 if (update_buffers(dri2_surf) < 0)
1274 ret = tbm_surface_map(dri2_surf->tbm_surface, TBM_SURF_OPTION_READ, &surf_info);
1276 if (ret != TBM_SURFACE_ERROR_NONE) {
1277 _eglLog(_EGL_WARNING, "Could not tbm_surface_map");
1281 internal_stride = surf_info.planes[0].stride;
1284 for (i = 0; i < h; i++) {
1285 memcpy(data + i * stride,
1286 surf_info.planes[0].ptr + (x + i) * internal_stride + y, stride);
1289 tbm_surface_unmap(dri2_surf->tbm_surface);
1293 tizen_swrast_put_image2(__DRIdrawable * draw, int op,
1294 int x, int y, int w, int h, int stride,
1295 char *data, void *loaderPrivate)
1297 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1298 tbm_surface_info_s surf_info;
1299 int ret = TBM_SURFACE_ERROR_NONE;
1300 int internal_stride, i;
1302 if (op != __DRI_SWRAST_IMAGE_OP_DRAW &&
1303 op != __DRI_SWRAST_IMAGE_OP_SWAP)
1306 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1307 if (!dri2_surf->tbm_surface) {
1308 if (update_buffers(dri2_surf) < 0) {
1309 _eglLog(_EGL_WARNING, "Could not get native buffer");
1314 ret = tbm_surface_map(dri2_surf->tbm_surface, TBM_SURF_OPTION_WRITE, &surf_info);
1315 if (ret != TBM_SURFACE_ERROR_NONE) {
1316 _eglLog(_EGL_WARNING, "Could not tbm_surface_map");
1320 internal_stride = surf_info.planes[0].stride;
1322 for (i = 0; i < h; i++) {
1323 memcpy(surf_info.planes[0].ptr + (x + i) * internal_stride + y,
1324 data + i * stride, stride);
1327 tbm_surface_unmap(dri2_surf->tbm_surface);
1328 tpl_surface_enqueue_buffer_with_damage_and_sync(dri2_surf->tpl_surface,
1329 dri2_surf->tbm_surface,
1331 tbm_surface_internal_unref(dri2_surf->tbm_surface);
1332 dri2_surf->tbm_surface = NULL;
1333 dri2_surf->back = NULL;
1338 tizen_swrast_put_image(__DRIdrawable * draw, int op,
1339 int x, int y, int w, int h,
1340 char *data, void *loaderPrivate)
1342 struct dri2_egl_surface *dri2_surf = loaderPrivate;
1345 if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
1346 if (!dri2_surf->tbm_surface) {
1347 if (update_buffers(dri2_surf) < 0) {
1348 _eglLog(_EGL_WARNING, "Could not get native buffer");
1353 stride = tizen_swrast_get_stride_for_format(dri2_surf->tbm_format, w);
1354 tizen_swrast_put_image2(draw, op, x, y, w, h, stride, data, loaderPrivate);
1359 tizen_add_configs(_EGLDisplay *dpy)
1361 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
1368 } pbuffer_masks[] = {
1369 { 0xff0000, 0xff00, 0xff, 0xff000000 }, /* ARGB8888 */
1370 { 0xff0000, 0xff00, 0xff, 0x0 }, /* RGB888 */
1371 { 0x00f800, 0x07e0, 0x1f, 0x0 }, /* RGB565 */
1374 for (i = 0, count = 0; dri2_dpy->driver_configs[i]; i++) {
1375 struct dri2_egl_config *dri2_cfg;
1376 unsigned int red, blue, green, alpha, depth;
1377 int surface_type = 0;
1379 EGLint attr_list[] = {
1380 EGL_NATIVE_VISUAL_ID, 0,
1384 struct rgba_masks masks;
1387 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1388 __DRI_ATTRIB_RED_SIZE, &red);
1389 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1390 __DRI_ATTRIB_GREEN_SIZE, &green);
1391 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1392 __DRI_ATTRIB_BLUE_SIZE, &blue);
1393 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1394 __DRI_ATTRIB_ALPHA_SIZE, &alpha);
1395 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1396 __DRI_ATTRIB_DEPTH_SIZE, &depth);
1398 res = tpl_display_query_config(dri2_dpy->tpl_display, TPL_SURFACE_TYPE_WINDOW,
1399 red, green, blue, alpha, depth,
1400 &attr_list[1], &is_slow);
1401 if (res == TPL_ERROR_NONE)
1402 surface_type |= EGL_WINDOW_BIT;
1404 res = tpl_display_query_config(dri2_dpy->tpl_display, TPL_SURFACE_TYPE_PIXMAP,
1405 red, green, blue, alpha, depth,
1406 &attr_list[1], &is_slow);
1407 if (res == TPL_ERROR_NONE)
1408 surface_type |= EGL_PIXMAP_BIT;
1410 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1411 __DRI_ATTRIB_RED_MASK, &masks.red);
1412 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1413 __DRI_ATTRIB_GREEN_MASK, &masks.green);
1414 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1415 __DRI_ATTRIB_BLUE_MASK, &masks.blue);
1416 dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
1417 __DRI_ATTRIB_ALPHA_MASK, &masks.alpha);
1419 for (j = 0; j < ARRAY_SIZE(pbuffer_masks); j++) {
1420 const struct rgba_masks *pbuffer_mask = &pbuffer_masks[j];
1422 if (pbuffer_mask->red == masks.red &&
1423 pbuffer_mask->green == masks.green &&
1424 pbuffer_mask->blue == masks.blue &&
1425 pbuffer_mask->alpha == masks.alpha) {
1426 surface_type |= EGL_PBUFFER_BIT;
1434 dri2_cfg = dri2_add_config(dpy, dri2_dpy->driver_configs[i], count + 1,
1435 surface_type, &attr_list[0], NULL, NULL);
1440 return (count != 0);
1443 static EGLBoolean tizen_set_swap_interval(_EGLDisplay *dpy,
1444 _EGLSurface *surf, EGLint interval)
1446 tpl_result_t res = TPL_ERROR_NONE;
1447 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1449 res = tpl_surface_set_post_interval(dri2_surf->tpl_surface, interval);
1451 if (res != TPL_ERROR_NONE)
1457 static struct dri2_egl_display_vtbl tizen_display_vtbl = {
1458 .authenticate = NULL,
1459 .create_window_surface = tizen_create_window_surface,
1460 .create_pixmap_surface = tizen_create_pixmap_surface,
1461 .create_pbuffer_surface = tizen_create_pbuffer_surface,
1462 .destroy_surface = tizen_destroy_surface,
1463 .create_image = tizen_create_image_khr,
1464 .swap_interval = tizen_set_swap_interval,
1465 .swap_buffers = tizen_swap_buffers,
1466 .swap_buffers_with_damage = tizen_swap_buffers_with_damage,
1467 .query_buffer_age = tizen_query_buffer_age,
1468 .query_surface = tizen_query_surface,
1469 .create_wayland_buffer_from_image = NULL,
1470 .get_dri_drawable = dri2_surface_get_dri_drawable,
1473 static const __DRIdri2LoaderExtension tizen_dri2_loader_extension = {
1474 .base = { __DRI_DRI2_LOADER, 3 },
1477 .getBuffersWithFormat = tizen_get_buffers_with_format,
1478 .flushFrontBuffer = tizen_flush_front_buffer,
1479 .validate = tizen_validate_drawable,
1482 static const __DRIimageLoaderExtension tizen_image_loader_extension = {
1483 .base = { __DRI_IMAGE_LOADER, 1 },
1485 .getBuffers = tizen_image_get_buffers,
1486 .flushFrontBuffer = tizen_flush_front_buffer,
1487 .validate = tizen_validate_drawable,
1490 static const __DRIswrastLoaderExtension tizen_swrast_loader_extension = {
1491 .base = { __DRI_SWRAST_LOADER, 2 },
1493 .getDrawableInfo = tizen_swrast_get_drawable_info,
1494 .putImage = tizen_swrast_put_image,
1495 .getImage = tizen_swrast_get_image,
1496 .putImage2 = tizen_swrast_put_image2,
1499 static const __DRIextension *tizen_dri2_loader_extensions[] = {
1500 &tizen_dri2_loader_extension.base,
1501 &tizen_image_loader_extension.base,
1502 &image_lookup_extension.base,
1503 &use_invalidate.base,
1507 static const __DRIextension *tizen_image_loader_extensions[] = {
1508 &tizen_image_loader_extension.base,
1509 &image_lookup_extension.base,
1510 &use_invalidate.base,
1514 static const __DRIextension *tizen_swrast_loader_extensions[] = {
1515 &tizen_swrast_loader_extension.base,
1516 &image_lookup_extension.base,
1521 tizen_swrast_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
1523 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1524 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
1526 dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
1530 static const struct dri2_egl_display_vtbl tizen_swrast_display_vtbl = {
1531 .authenticate = NULL,
1532 .create_window_surface = tizen_create_window_surface,
1533 .create_pixmap_surface = tizen_create_pixmap_surface,
1534 .create_pbuffer_surface = tizen_create_pbuffer_surface,
1535 .destroy_surface = tizen_destroy_surface,
1536 .create_image = tizen_create_image_khr,
1537 .swap_buffers = tizen_swrast_swap_buffers,
1538 .get_dri_drawable = dri2_surface_get_dri_drawable,
1543 dri2_initialize_tizen(_EGLDisplay *disp)
1546 struct dri2_egl_display *dri2_dpy;
1547 tpl_display_t *tpl_display = NULL;
1548 tpl_backend_type_t tpl_backend = TPL_BACKEND_UNKNOWN;
1550 int tbm_bufmgr_fd = -1;
1552 char *tbm_bufmgr_device_name = NULL;
1553 int hw_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
1555 loader_set_logger(_eglLog);
1557 dri2_dpy = dri2_display_create();
1559 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1561 disp->DriverData = (void *) dri2_dpy;
1563 /* Allocate an new native display, if argument passed to
1564 eglGetDisplay() is EGL_DEFAULT_DISPLAY, it will cause
1565 error in __tpl_wayland_egl_display_init() */
1566 if (disp->PlatformDisplay == NULL) {
1567 disp->PlatformDisplay = wl_display_connect(NULL);
1569 if (disp->PlatformDisplay == NULL) {
1570 err = "DRI2: failed to get native display";
1571 goto cleanup_display;
1573 dri2_dpy->own_device = 1;
1576 /* Can find the backend type of libtpl-egl through PlatformDisplay */
1577 tpl_backend = tpl_display_get_backend_type(disp->PlatformDisplay);
1578 /* If tpl_backend is a wayland client, thread backend should be used
1579 * to use dri2_surf->out_fence_fd. */
1580 if (tpl_backend == TPL_BACKEND_WAYLAND)
1581 tpl_backend = TPL_BACKEND_WAYLAND_THREAD;
1583 tpl_display = tpl_display_create(tpl_backend, disp->PlatformDisplay);
1586 err = "DRI2: failed to create tpl_display";
1587 goto cleanup_display;
1589 dri2_dpy->tpl_display = tpl_display;
1591 /* Get tbm_bufmgr's fd */
1592 tbm_bufmgr_fd = tbm_drm_helper_get_fd();
1594 if (tbm_bufmgr_fd == -1) {
1595 err = "DRI2: failed to get tbm_bufmgr fd";
1596 goto cleanup_device;
1600 #if 0//FOR REF: it's another way, to open v3d directly
1601 #define MAX_DRM_DEVICES 32
1602 drmDevicePtr device, devices[MAX_DRM_DEVICES] = { NULL };
1604 num_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
1605 for (int i = 0; i < num_devices; i++) {
1606 device = devices[i];
1608 if (!(device->available_nodes & (1 << DRM_NODE_RENDER)))
1611 dri2_dpy->fd = loader_open_device(device->nodes[DRM_NODE_RENDER]);
1612 if (dri2_dpy->fd < 0) {
1613 _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s",
1614 __func__, device->nodes[DRM_NODE_RENDER]);
1620 drmFreeDevices(devices, num_devices);
1623 if (drmGetNodeTypeFromFd(tbm_bufmgr_fd) == DRM_NODE_RENDER) {
1624 tbm_bufmgr_device_name = loader_get_device_name_for_fd(tbm_bufmgr_fd);
1625 if (tbm_bufmgr_device_name == NULL) {
1626 err = "DRI2: failed to get tbm_bufmgr device name";
1627 goto cleanup_device;
1629 dri2_dpy->fd_render_gpu = loader_open_device(tbm_bufmgr_device_name);
1630 } else if ((master_fd = tbm_drm_helper_get_master_fd()) >= 0) {
1632 // display server always has master_fd,
1633 // so tbm_bufmgr_fd is the master_fd if it can get the tbm_master_fd.
1634 tbm_bufmgr_device_name = loader_get_device_name_for_fd(tbm_bufmgr_fd);
1635 if (tbm_bufmgr_device_name == NULL) {
1636 err = "DRI2: failed to get tbm_bufmgr device name";
1637 goto cleanup_device;
1639 dri2_dpy->fd_render_gpu = loader_open_device(tbm_bufmgr_device_name);
1641 if (!tbm_drm_helper_get_auth_info(&dri2_dpy->fd_render_gpu, NULL, NULL)) {
1642 err = "DRI2: failed to get fd from tbm_drm_helper_get_auth_info()";
1643 goto cleanup_device;
1647 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd_render_gpu);
1648 if (dri2_dpy->driver_name == NULL) {
1649 err = "DRI2: failed to get driver name";
1650 goto cleanup_device;
1653 dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd_render_gpu) == DRM_NODE_RENDER;
1654 /* render nodes cannot use Gem names, and thus do not support
1655 * the __DRI_DRI2_LOADER extension */
1657 if (!dri2_dpy->is_render_node) {
1658 dri2_dpy->loader_extensions = tizen_dri2_loader_extensions;
1659 if (!dri2_load_driver(disp)) {
1660 err = "DRI2: failed to load driver";
1661 goto cleanup_driver_name;
1664 dri2_dpy->loader_extensions = tizen_image_loader_extensions;
1665 if (!dri2_load_driver_dri3(disp)) {
1666 err = "DRI3: failed to load driver";
1667 goto cleanup_driver_name;
1671 dri2_dpy->fd_render_gpu = tbm_bufmgr_fd;
1672 dri2_dpy->driver_name = strdup("swrast");
1673 if (!dri2_load_driver_swrast(disp)) {
1674 err = "DRI2: failed to load swrast driver";
1675 goto cleanup_device;
1677 dri2_dpy->loader_extensions = tizen_swrast_loader_extensions;
1680 dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu;
1682 if (!dri2_create_screen(disp)) {
1683 err = "DRI2: failed to create screen";
1684 goto cleanup_driver;
1687 if (!dri2_setup_device(disp, false)) {
1688 _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to setup EGLDevice");
1689 goto cleanup_driver;
1692 if (dri2_dpy->fd_render_gpu != tbm_bufmgr_fd) {
1693 close(tbm_bufmgr_fd);
1697 if (!dri2_setup_extensions(disp)) {
1698 err = "DRI2: failed to find required DRI extensions";
1699 goto cleanup_screen;
1702 dri2_setup_screen(disp);
1704 dri2_setup_swap_interval(disp, 1);
1706 if (!tizen_add_configs(disp)) {
1707 err = "DRI2: failed to add configs";
1708 goto cleanup_screen;
1711 /* Fill vtbl last to prevent accidentally calling virtual function during
1715 dri2_dpy->vtbl = &tizen_display_vtbl;
1717 dri2_dpy->vtbl = &tizen_swrast_display_vtbl;
1719 disp->Extensions.EXT_buffer_age = EGL_FALSE;
1720 disp->Extensions.EXT_swap_buffers_with_damage = EGL_FALSE; /*disable partial buffer swap*/
1721 disp->Extensions.TIZEN_image_native_surface = EGL_TRUE;
1722 disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
1723 disp->Extensions.WL_create_wayland_buffer_from_image = EGL_FALSE;
1724 disp->Extensions.KHR_fence_sync = EGL_TRUE;
1726 if (dri2_dpy->fence->base.version >= 2 &&
1727 dri2_dpy->fence->get_capabilities) {
1728 unsigned capabilities =
1729 dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen_render_gpu);
1730 disp->Extensions.TIZEN_native_fence_sync =
1731 (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0;
1732 disp->Extensions.ANDROID_native_fence_sync = disp->Extensions.TIZEN_native_fence_sync;
1738 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen_render_gpu);
1740 dlclose(dri2_dpy->driver);
1741 cleanup_driver_name:
1742 free(dri2_dpy->driver_name);
1744 tpl_object_unreference((tpl_object_t *)tpl_display);
1746 if (dri2_dpy->own_device) {
1747 wl_display_disconnect(disp->PlatformDisplay);
1748 disp->PlatformDisplay = NULL;
1750 if (tbm_bufmgr_fd != -1) {
1751 if (dri2_dpy->fd_render_gpu != -1 && dri2_dpy->fd_render_gpu != tbm_bufmgr_fd) {
1752 close(dri2_dpy->fd_render_gpu);
1753 dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu = -1;
1755 close(tbm_bufmgr_fd);
1759 disp->DriverData = NULL;
1761 return _eglError(EGL_NOT_INITIALIZED, err);
1765 dri2_teardown_tizen(_EGLDisplay *disp)
1767 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1769 if (dri2_dpy->tpl_display)
1770 tpl_object_unreference((tpl_object_t *)(dri2_dpy->tpl_display));
1772 if (tbm_bufmgr_fd > 0)
1773 close(tbm_bufmgr_fd);
1775 if (dri2_dpy->own_device)
1776 wl_display_disconnect(disp->PlatformDisplay);