Files
fml13v01-buildroot/package/mesa3d/0018-egl-add-Tizen-platform-support.patch
T
2022-08-16 17:38:05 +08:00

1637 lines
51 KiB
Diff

From a2fea4d0fb40d7bdfd2a3860132c37288f3d7864 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Fri, 6 Jan 2017 16:35:00 +0000
Subject: [PATCH 18/67] egl: add Tizen platform support
Add a new "tizen" platform to support drm/gbm and Wayland on Tizen.
The platform can be enabled by passing "-Dplatforms=tizen" to Meson.
---
meson.build | 25 +-
meson_options.txt | 2 +-
src/egl/drivers/dri2/egl_dri2.c | 182 ++++-
src/egl/drivers/dri2/egl_dri2.h | 59 +-
src/egl/drivers/dri2/platform_tizen.c | 980 ++++++++++++++++++++++++++
src/egl/main/eglapi.c | 7 +
src/egl/main/egldisplay.c | 32 +-
src/egl/main/egldisplay.h | 7 +
src/egl/main/egllog.c | 27 +-
src/egl/meson.build | 7 +-
10 files changed, 1313 insertions(+), 15 deletions(-)
create mode 100644 src/egl/drivers/dri2/platform_tizen.c
diff --git a/meson.build b/meson.build
index 968b4f5f499..3d9d345dbf2 100644
--- a/meson.build
+++ b/meson.build
@@ -358,6 +358,11 @@ with_platform_x11 = _platforms.contains('x11')
with_platform_wayland = _platforms.contains('wayland')
with_platform_haiku = _platforms.contains('haiku')
with_platform_windows = _platforms.contains('windows')
+with_platform_tizen = _platforms.contains('tizen')
+
+if with_platform_tizen and _platforms.length() != 1
+ error('tizen cannot be enabled at the same time as other platforms')
+endif
with_glx = get_option('glx')
if with_glx == 'auto'
@@ -910,7 +915,7 @@ else
pre_args += '-DEGL_NO_X11'
gl_pkgconfig_c_flags += '-DEGL_NO_X11'
endif
-if with_gbm and not with_platform_android
+if with_gbm and not with_platform_android and not with_platform_tizen
pre_args += '-DHAVE_DRM_PLATFORM'
endif
@@ -944,6 +949,15 @@ endif
if with_platform_haiku
pre_args += '-DHAVE_HAIKU_PLATFORM'
endif
+if with_platform_tizen
+ dep_dlog = dependency('dlog')
+ dep_tizen = [
+ dep_dlog,
+ dependency('libtbm'),
+ dependency('tpl-egl'),
+ ]
+ pre_args += '-DHAVE_TIZEN_PLATFORM'
+endif
prog_python = import('python').find_installation('python3')
has_mako = run_command(
@@ -1568,7 +1582,8 @@ with_gallium_drisw_kms = false
dep_libdrm = dependency(
'libdrm', version : '>=' + _drm_ver,
# GNU/Hurd includes egl_dri2, without drm.
- required : (with_dri2 and host_machine.system() != 'gnu') or with_dri3
+ required : (with_dri2 and host_machine.system() != 'gnu') or with_dri3 or
+ with_platform_tizen
)
if dep_libdrm.found()
pre_args += '-DHAVE_LIBDRM'
@@ -2187,8 +2202,10 @@ if with_egl
lines += 'EGL drivers: ' + ' '.join(egl_drivers)
endif
if with_egl or with_any_vk
- _platforms += 'surfaceless'
- if with_gbm and not with_platform_android
+ if not with_platform_tizen
+ _platforms += 'surfaceless'
+ endif
+ if with_gbm and not with_platform_android and not with_platform_tizen
_platforms += 'drm'
endif
lines += 'EGL/Vulkan/VL platforms: ' + ' '.join(_platforms)
diff --git a/meson_options.txt b/meson_options.txt
index dac791099a1..8230db93c70 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -23,7 +23,7 @@ option(
type : 'array',
value : ['auto'],
choices : [
- 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows',
+ 'auto', 'x11', 'wayland', 'haiku', 'android', 'windows', 'tizen',
],
description : 'window systems to support. If this is set to `auto`, all platforms applicable will be enabled.'
)
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index dea5899b3a8..6d34395d65d 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1179,6 +1179,11 @@ dri2_initialize(_EGLDisplay *disp)
case _EGL_PLATFORM_ANDROID:
ret = dri2_initialize_android(disp);
break;
+#ifdef HAVE_TIZEN_PLATFORM
+ case _EGL_PLATFORM_TIZEN:
+ ret = dri2_initialize_tizen(disp);
+ break;
+#endif
default:
unreachable("Callers ensure we cannot get here.");
return EGL_FALSE;
@@ -1253,6 +1258,12 @@ dri2_display_destroy(_EGLDisplay *disp)
case _EGL_PLATFORM_WAYLAND:
dri2_teardown_wayland(dri2_dpy);
break;
+#ifdef HAVE_TIZEN_PLATFORM
+ case _EGL_PLATFORM_TIZEN:
+ if (dri2_dpy->tpl_dpy)
+ tpl_object_unreference((tpl_object_t *) dri2_dpy->tpl_dpy);
+ break;
+#endif
default:
/* TODO: add teardown for other platforms */
break;
@@ -2293,8 +2304,96 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
return dri2_create_image_from_dri(disp, dri_image);
}
-#ifdef HAVE_WAYLAND_PLATFORM
+#ifdef HAVE_TIZEN_PLATFORM
+int
+dri2_fourcc_from_tbm_format(tbm_format format)
+{
+ switch (format) {
+ case TBM_FORMAT_ARGB8888:
+ return DRM_FORMAT_ARGB8888;
+ case TBM_FORMAT_XRGB8888:
+ return DRM_FORMAT_XRGB8888;
+ case TBM_FORMAT_RGB565:
+ return DRM_FORMAT_RGB565;
+ default:
+ _eglLog(_EGL_DEBUG, "%s: unsupported tbm format %#x", __func__, format);
+ return 0;
+ }
+}
+static _EGLImage *
+dri2_create_image_wayland_wl_buffer_tizen(_EGLDisplay *disp, _EGLContext *ctx,
+ EGLClientBuffer _buffer,
+ const EGLint *attr_list)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ __DRIimage *dri_image;
+ _EGLImageAttribs attrs;
+ tbm_surface_h tbm_surf;
+ tbm_bo tbm_buf;
+ tbm_surface_info_s info;
+ int fourcc, fd, pitch, offset;
+
+ tbm_surf = tpl_display_get_buffer_from_native_pixmap(dri2_dpy->tpl_dpy,
+ (tpl_handle_t) _buffer);
+ if (!tbm_surf) {
+ _eglError(EGL_BAD_PARAMETER, "tpl_display_get_buffer_from_native_pixmap");
+ return NULL;
+ }
+
+ if (!_eglParseImageAttribList(&attrs, disp, attr_list)) {
+ _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer_tizen");
+ return NULL;
+ }
+
+ if (tbm_surface_get_info(tbm_surf, &info)) {
+ _eglError(EGL_BAD_PARAMETER, "tbm_surface_get_info");
+ return NULL;
+ }
+
+ if (info.num_planes > 1) {
+ _eglError(EGL_BAD_PARAMETER,
+ "dri2_create_image_wayland_wl_buffer_tizen (multi-plane format)");
+ return NULL;
+ }
+
+ if (attrs.PlaneWL < 0 || attrs.PlaneWL >= info.num_planes) {
+ _eglError(EGL_BAD_PARAMETER,
+ "dri2_create_image_wayland_wl_buffer_tizen (plane out of bounds)");
+ return NULL;
+ }
+
+ tbm_buf = tbm_surface_internal_get_bo(tbm_surf, attrs.PlaneWL);
+ if (!tbm_buf) {
+ _eglError(EGL_BAD_PARAMETER, "tbm_surface_internal_get_bo");
+ return NULL;
+ }
+
+ fourcc = dri2_fourcc_from_tbm_format(info.format);
+ pitch = info.planes[attrs.PlaneWL].stride;
+ offset = info.planes[attrs.PlaneWL].offset;
+ fd = tbm_bo_export_fd(tbm_buf);
+
+ dri_image = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
+ info.width,
+ info.height,
+ fourcc,
+ &fd,
+ 1,
+ &pitch,
+ &offset,
+ tbm_surf);
+ close(fd);
+ if (dri_image == NULL) {
+ _eglError(EGL_BAD_PARAMETER, "createImageFromFds");
+ return NULL;
+ }
+
+ return dri2_create_image_from_dri(disp, dri_image);
+}
+#endif
+
+#ifdef HAVE_WAYLAND_PLATFORM
/* This structure describes how a wl_buffer maps to one or more
* __DRIimages. A wl_drm_buffer stores the wl_drm format code and the
* offsets and strides of the planes in the buffer. This table maps a
@@ -3193,6 +3292,10 @@ dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
#ifdef HAVE_WAYLAND_PLATFORM
case EGL_WAYLAND_BUFFER_WL:
return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
+#endif
+#ifdef HAVE_TIZEN_PLATFORM
+ case EGL_WAYLAND_BUFFER_WL:
+ return dri2_create_image_wayland_wl_buffer_tizen(disp, ctx, buffer, attr_list);
#endif
case EGL_CL_IMAGE_IMG:
return dri2_create_image_img_buffer(disp, ctx, target, buffer, attr_list);
@@ -3214,6 +3317,78 @@ dri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image)
return EGL_TRUE;
}
+#ifdef HAVE_TIZEN_PLATFORM
+
+static EGLint get_texture_format_from_gbm_format(tbm_format format)
+{
+ switch (format) {
+ case TBM_FORMAT_ARGB8888:
+ return EGL_TEXTURE_RGBA;
+ default:
+ _eglLog(_EGL_DEBUG, "%s: unsupported tbm format %#x", __func__, format);
+ return 0;
+ }
+}
+
+static EGLBoolean
+dri2_bind_wayland_display_wl_tizen(_EGLDisplay *disp, struct wl_display *wl_dpy)
+{
+ (void) disp;
+ (void) wl_dpy;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_unbind_wayland_display_wl_tizen(_EGLDisplay *disp,
+ struct wl_display *wl_dpy)
+{
+ (void) disp;
+ (void) wl_dpy;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_query_wayland_buffer_wl_tizen(_EGLDisplay *disp,
+ struct wl_resource *buffer_resource,
+ EGLint attribute, EGLint *value)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ tpl_handle_t pixmap = (tpl_handle_t) buffer_resource;
+ tbm_surface_h tbm_surf;
+ tbm_format format;
+ EGLint tex_format;
+
+ tbm_surf = tpl_display_get_buffer_from_native_pixmap(dri2_dpy->tpl_dpy,
+ pixmap);
+ if (!tbm_surf)
+ return EGL_FALSE;
+
+ switch (attribute) {
+ case EGL_TEXTURE_FORMAT:
+ format = tbm_surface_get_format(tbm_surf);
+ tex_format = get_texture_format_from_gbm_format(format);
+ if (!tex_format)
+ return EGL_FALSE;
+
+ *value = tex_format;
+ break;
+ case EGL_WIDTH:
+ *value = tbm_surface_get_width(tbm_surf);
+ break;
+ case EGL_HEIGHT:
+ *value = tbm_surface_get_height(tbm_surf);
+ break;
+ default:
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
+
+#endif
+
#ifdef HAVE_WAYLAND_PLATFORM
static void
@@ -3755,6 +3930,11 @@ const _EGLDriver _eglDriver = {
.BindWaylandDisplayWL = dri2_bind_wayland_display_wl,
.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl,
.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl,
+#endif
+#ifdef HAVE_TIZEN_PLATFORM
+ .BindWaylandDisplayWL = dri2_bind_wayland_display_wl_tizen,
+ .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl_tizen,
+ .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl_tizen,
#endif
.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium,
.CreateSyncKHR = dri2_create_sync,
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 6a7eedea112..a8bfe45b1f5 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -62,9 +62,9 @@ struct zwp_linux_dmabuf_v1;
#include <gbm_driint.h>
#endif
-#ifdef HAVE_ANDROID_PLATFORM
#define LOG_TAG "EGL-DRI2"
+#ifdef HAVE_ANDROID_PLATFORM
#include <hardware/gralloc.h>
#if ANDROID_API_LEVEL >= 26
@@ -75,6 +75,12 @@ struct zwp_linux_dmabuf_v1;
#endif /* HAVE_ANDROID_PLATFORM */
+#ifdef HAVE_TIZEN_PLATFORM
+#include <pthread.h>
+#include <tpl.h>
+#include <tbm_surface_internal.h>
+#endif
+
#include "eglconfig.h"
#include "eglcontext.h"
#include "egldevice.h"
@@ -259,6 +265,10 @@ struct dri2_egl_display
bool is_render_node;
bool is_different_gpu;
+
+#ifdef HAVE_TIZEN_PLATFORM
+ tpl_display_t *tpl_dpy;
+#endif
};
struct dri2_egl_context
@@ -276,6 +286,18 @@ enum wayland_buffer_type {
};
#endif
+#define DRI2_SURFACE_NUM_COLOR_BUFFERS 4
+
+#ifdef HAVE_TIZEN_PLATFORM
+struct tpl_swap_queue_elem
+{
+ tbm_surface_h tbm_surf;
+ EGLint *rects;
+ EGLint n_rects_max;
+ EGLint n_rects;
+};
+#endif
+
struct dri2_egl_surface
{
_EGLSurface base;
@@ -308,15 +330,33 @@ struct dri2_egl_surface
struct gbm_dri_surface *gbm_surf;
#endif
+#ifdef HAVE_TIZEN_PLATFORM
+ tpl_surface_t *tpl_surf;
+ bool reset;
+ /*
+ * Protects swap_queue_idx_head, swap_queue_idx_tail and
+ * color_buffers.locked.
+ */
+ pthread_mutex_t mutex;
+ pthread_cond_t swap_queue_cond;
+ struct tpl_swap_queue_elem swap_queue[DRI2_SURFACE_NUM_COLOR_BUFFERS];
+ int swap_queue_idx_head;
+ int swap_queue_idx_tail;
+ pthread_t swap_queue_processor;
+#endif
+
/* EGL-owned buffers */
__DRIbuffer *local_buffers[__DRI_BUFFER_COUNT];
-#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM)
+#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM) || \
+ defined(HAVE_TIZEN_PLATFORM)
struct {
+#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_TIZEN_PLATFORM)
+ __DRIimage *dri_image;
+#endif
#ifdef HAVE_WAYLAND_PLATFORM
struct wl_buffer *wl_buffer;
bool wl_release;
- __DRIimage *dri_image;
/* for is_different_gpu case. NULL else */
__DRIimage *linear_copy;
/* for swrast */
@@ -325,6 +365,9 @@ struct dri2_egl_surface
#endif
#ifdef HAVE_DRM_PLATFORM
struct gbm_bo *bo;
+#endif
+#ifdef HAVE_TIZEN_PLATFORM
+ tbm_surface_h tbm_surf;
#endif
bool locked;
int age;
@@ -525,6 +568,11 @@ dri2_initialize_android(_EGLDisplay *disp)
EGLBoolean
dri2_initialize_surfaceless(_EGLDisplay *disp);
+#ifdef HAVE_TIZEN_PLATFORM
+EGLBoolean
+dri2_initialize_tizen(_EGLDisplay *disp);
+#endif
+
EGLBoolean
dri2_initialize_device(_EGLDisplay *disp);
static inline void
@@ -559,6 +607,11 @@ dri2_set_WL_bind_wayland_display(_EGLDisplay *disp)
#endif
}
+#ifdef HAVE_TIZEN_PLATFORM
+int
+dri2_fourcc_from_tbm_format(tbm_format format);
+#endif
+
void
dri2_display_destroy(_EGLDisplay *disp);
diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c
new file mode 100644
index 00000000000..a08bc8c07bf
--- /dev/null
+++ b/src/egl/drivers/dri2/platform_tizen.c
@@ -0,0 +1,980 @@
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <tpl.h>
+#include <xf86drm.h>
+
+#include "egl_dri2.h"
+#include "loader.h"
+
+#define TIZEN_DRM_RENDER_MINOR_START 128
+#define TIZEN_DRM_RENDER_MINOR_MAX 191
+
+#define TIZEN_SWAP_N_RECTS_MIN 32
+
+struct rgba_shifts_and_sizes {
+ int shifts[4];
+ unsigned int sizes[4];
+};
+
+static void *swap_queue_processor_worker(void *data)
+{
+ struct dri2_egl_surface *dri2_surf = data;
+
+ pthread_mutex_lock(&dri2_surf->mutex);
+ while (1) {
+ struct tpl_swap_queue_elem *queue_elem;
+ int i;
+ tpl_result_t res;
+
+ if (dri2_surf->swap_queue_idx_head == dri2_surf->swap_queue_idx_tail) {
+ /* Wait for new swaps to be added to the queue */
+ pthread_cond_wait(&dri2_surf->swap_queue_cond, &dri2_surf->mutex);
+ continue;
+ }
+
+ queue_elem = &dri2_surf->swap_queue[dri2_surf->swap_queue_idx_head];
+ pthread_mutex_unlock(&dri2_surf->mutex);
+
+ res = tpl_surface_enqueue_buffer_with_damage(dri2_surf->tpl_surf,
+ queue_elem->tbm_surf,
+ queue_elem->n_rects,
+ queue_elem->rects);
+ if (res != TPL_ERROR_NONE)
+ return NULL;
+
+ pthread_mutex_lock(&dri2_surf->mutex);
+ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+ if (dri2_surf->color_buffers[i].tbm_surf == queue_elem->tbm_surf) {
+ dri2_surf->color_buffers[i].locked = false;
+ break;
+ }
+ }
+
+ dri2_surf->swap_queue_idx_head++;
+ dri2_surf->swap_queue_idx_head %= ARRAY_SIZE(dri2_surf->swap_queue);
+
+ /*
+ * Notify get_back_bo that a buffer has become available, reset_surface_cb
+ * that it may be able to reset the surface or dri2_tizen_destroy_surface
+ * that it may be able to proceed with surface destruction.
+ */
+ pthread_cond_signal(&dri2_surf->swap_queue_cond);
+ }
+ pthread_mutex_unlock(&dri2_surf->mutex);
+
+ return NULL;
+}
+
+static __DRIimage *
+create_image_from_native(struct dri2_egl_surface *dri2_surf,
+ tbm_surface_h tbm_surf,
+ int *width, int *height,
+ void *loaderPrivate)
+{
+ _EGLSurface *surf = &dri2_surf->base;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(surf->Resource.Display);
+ tbm_bo tbm_buf;
+ tbm_surface_info_s info;
+ int fd, fourcc, offset, pitch;
+ __DRIimage *dri_image;
+
+ tbm_buf = tbm_surface_internal_get_bo(tbm_surf, 0);
+ if (!tbm_buf) {
+ _eglLog(_EGL_DEBUG, "%s: failed to get bo for tbm surface", __func__);
+ return NULL;
+ }
+
+ if (tbm_surface_get_info(tbm_surf, &info)) {
+ _eglLog(_EGL_DEBUG, "%s: failed to get tbm surface info", __func__);
+ return NULL;
+ }
+
+ fd = tbm_bo_export_fd(tbm_buf);
+ fourcc = dri2_fourcc_from_tbm_format(info.format);
+ offset = info.planes[0].offset;
+ pitch = info.planes[0].stride;
+
+ dri_image = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
+ info.width,
+ info.height,
+ fourcc,
+ &fd,
+ 1,
+ &pitch,
+ &offset,
+ loaderPrivate);
+ close(fd);
+
+ if (!dri_image) {
+ _eglLog(_EGL_DEBUG, "%s: failed to create dri image from tbm bo", __func__);
+ return NULL;
+ }
+
+ if (width)
+ *width = info.width;
+
+ if (height)
+ *height = info.height;
+
+ return dri_image;
+}
+
+static int
+get_back_bo(struct dri2_egl_surface *dri2_surf, bool allow_update)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ tbm_surface_h tbm_surf;
+ tpl_bool_t tpl_surf_valid;
+ int i;
+
+ if (dri2_surf->base.Type == EGL_PIXMAP_BIT) {
+ _eglLog(_EGL_DEBUG, "%s: can't get back bo for pixmap surface", __func__);
+ return -1;
+ }
+
+ if (dri2_surf->back && !allow_update)
+ return 0;
+
+ /*
+ * If the tpl surface is no longer valid, e.g. it has been resized, then
+ * we should get a new back buffer.
+ */
+ tpl_surf_valid = tpl_surface_validate(dri2_surf->tpl_surf);
+ if (dri2_surf->back && tpl_surf_valid == TPL_TRUE)
+ return 0;
+
+ tbm_surf = tpl_surface_dequeue_buffer(dri2_surf->tpl_surf);
+ if (!tbm_surf) {
+ _eglLog(_EGL_DEBUG, "%s: surface buffer dequeue failed", __func__);
+ return -1;
+ }
+
+ pthread_mutex_lock(&dri2_surf->mutex);
+ /*
+ * If the tpl surface is no longer valid, e.g. it has been resized, then the
+ * call to tpl_surface should've resulted in a call to reset_surface_cb,
+ * which sets the dri2_surf reset flag. In this case we need to reset the
+ * color_buffer state.
+ *
+ * Note: we can't rely on the return value of tpl_surface_validate
+ * since the surface may have become invalid between this call and
+ * tpl_surface_dequeue_buffer.
+ */
+ if (dri2_surf->reset) {
+ /* Wait for any outstanding swaps to complete */
+ while (dri2_surf->swap_queue_idx_head != dri2_surf->swap_queue_idx_tail)
+ pthread_cond_wait(&dri2_surf->swap_queue_cond, &dri2_surf->mutex);
+
+ /* Cancel the old back buffer */
+ if (dri2_surf->back) {
+ tbm_surface_internal_unref(dri2_surf->back->tbm_surf);
+ dri2_surf->back->locked = false;
+ dri2_surf->back = NULL;
+ }
+
+ /* Reset the color buffers */
+ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+ assert(!dri2_surf->color_buffers[i].locked);
+
+ if (dri2_surf->color_buffers[i].dri_image) {
+ dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
+ dri2_surf->color_buffers[i].dri_image = NULL;
+ }
+
+ dri2_surf->color_buffers[i].tbm_surf = NULL;
+ dri2_surf->color_buffers[i].age = 0;
+ }
+
+ dri2_surf->back = NULL;
+ dri2_surf->current = NULL;
+ dri2_surf->reset = false;
+ }
+
+ assert(!dri2_surf->back);
+
+ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+ if (dri2_surf->color_buffers[i].tbm_surf == tbm_surf) {
+ dri2_surf->back = &dri2_surf->color_buffers[i];
+ assert(!dri2_surf->back->locked);
+ break;
+ }
+ }
+
+ while (!dri2_surf->back) {
+ int age;
+
+ /*
+ * Search for a free color buffer. Free the oldest buffer if one
+ * cannot be found.
+ */
+ for (i = 0, age = -1; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+ if (dri2_surf->color_buffers[i].locked)
+ continue;
+ if (!dri2_surf->color_buffers[i].dri_image) {
+ dri2_surf->back = &dri2_surf->color_buffers[i];
+ break;
+ }
+
+ if (dri2_surf->color_buffers[i].age > age) {
+ dri2_surf->back = &dri2_surf->color_buffers[i];
+ age = dri2_surf->color_buffers[i].age;
+ }
+ }
+
+ if (!dri2_surf->back) {
+ /*
+ * There aren't any available back buffers so wait for
+ * swap_queue_processor_worker to make one available.
+ */
+ pthread_cond_wait(&dri2_surf->swap_queue_cond, &dri2_surf->mutex);
+ continue;
+ }
+
+ if (dri2_surf->back->dri_image)
+ dri2_dpy->image->destroyImage(dri2_surf->back->dri_image);
+
+ dri2_surf->back->dri_image =
+ create_image_from_native(dri2_surf, tbm_surf,
+ &dri2_surf->base.Width,
+ &dri2_surf->base.Height,
+ dri2_surf);
+ if (!dri2_surf->back->dri_image) {
+ dri2_surf->back = NULL;
+ pthread_mutex_unlock(&dri2_surf->mutex);
+ return -1;
+ }
+ }
+
+ dri2_surf->back->tbm_surf = tbm_surf;
+ dri2_surf->back->locked = true;
+
+ if (dri2_surf->base.SwapBehavior == EGL_BUFFER_PRESERVED &&
+ dri2_surf->current) {
+ _EGLContext *ctx = _eglGetCurrentContext();
+ struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
+
+ if (dri2_ctx)
+ {
+ dri2_dpy->image->blitImage(dri2_ctx->dri_context,
+ dri2_surf->back->dri_image,
+ dri2_surf->current->dri_image,
+ 0, 0, dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ 0, 0, dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ __BLIT_FLAG_FLUSH);
+ }
+ }
+
+ pthread_mutex_unlock(&dri2_surf->mutex);
+
+ return 0;
+}
+
+static int
+get_front_bo(struct dri2_egl_surface *dri2_surf)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+
+ if (dri2_surf->front)
+ return 0;
+
+ if (dri2_surf->base.Type == EGL_PIXMAP_BIT) {
+ tbm_surface_h tbm_surf;
+
+ tbm_surf = tpl_surface_dequeue_buffer(dri2_surf->tpl_surf);
+ if (!tbm_surf)
+ return -1;
+
+ dri2_surf->front = create_image_from_native(dri2_surf, tbm_surf,
+ &dri2_surf->base.Width,
+ &dri2_surf->base.Height,
+ dri2_surf);
+ } else {
+ dri2_surf->front = dri2_dpy->image->createImage(dri2_dpy->dri_screen,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ dri2_surf->visual,
+ 0,
+ dri2_surf);
+ }
+
+ return dri2_surf->front ? 0 : -1;
+}
+
+static _EGLSurface *
+create_surface(_EGLDisplay *dpy, _EGLConfig *config, EGLint type,
+ const EGLint *attrib_list)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+ struct dri2_egl_config *dri2_config = dri2_egl_config(config);
+ struct dri2_egl_surface *dri2_surf;
+ const __DRIconfig *dri_config;
+
+ dri2_surf = calloc(1, sizeof(*dri2_surf));
+ if (!dri2_surf) {
+ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create surface");
+ return NULL;
+ }
+
+ if (!dri2_init_surface(&dri2_surf->base, dpy, type, config, attrib_list,
+ false, NULL))
+ goto err_free_surface;
+
+ dri_config = dri2_get_dri_config(dri2_config, type,
+ dri2_surf->base.GLColorspace);
+ if (!dri_config) {
+ _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
+ goto err_free_surface;
+ }
+
+ dri2_surf->dri_drawable =
+ dri2_dpy->image_driver->createNewDrawable(dri2_dpy->dri_screen,
+ dri_config, dri2_surf);
+ if (!dri2_surf->dri_drawable) {
+ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create drawable");
+ goto err_free_surface;
+ }
+
+ pthread_mutex_init(&dri2_surf->mutex, NULL);
+ pthread_cond_init(&dri2_surf->swap_queue_cond, NULL);
+
+ return &dri2_surf->base;
+
+err_free_surface:
+ free(dri2_surf);
+ return NULL;
+}
+
+static void
+destroy_surface(_EGLSurface *surf)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(surf->Resource.Display);
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+
+ pthread_cond_destroy(&dri2_surf->swap_queue_cond);
+ pthread_mutex_destroy(&dri2_surf->mutex);
+ dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
+ free(dri2_surf);
+}
+
+static void
+reset_surface_cb(void *data)
+{
+ struct dri2_egl_surface *dri2_surf = data;
+
+ dri2_surf->reset = true;
+}
+
+static _EGLSurface *
+dri2_tizen_create_window_surface(_EGLDisplay *dpy, _EGLConfig *config,
+ void *native_window, const EGLint *attrib_list)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+ struct dri2_egl_surface *dri2_surf;
+ _EGLSurface *surf;
+ int width, height;
+ tbm_format format;
+ tpl_result_t res;
+ int err;
+
+ surf = create_surface(dpy, config, EGL_WINDOW_BIT, attrib_list);
+ if (!surf)
+ return NULL;
+
+ res = tpl_display_get_native_window_info(dri2_dpy->tpl_dpy, native_window,
+ &width, &height, &format,
+ config->RedSize +
+ config->GreenSize +
+ config->BlueSize +
+ config->AlphaSize,
+ config->AlphaSize);
+ if (res != TPL_ERROR_NONE) {
+ _eglError(EGL_BAD_NATIVE_WINDOW, "DRI2: failed to get window info");
+ goto err_destroy_surface;
+ }
+
+ dri2_surf = dri2_egl_surface(surf);
+ dri2_surf->base.Width = width;
+ dri2_surf->base.Height = height;
+
+ dri2_surf->tpl_surf = tpl_surface_create(dri2_dpy->tpl_dpy, native_window,
+ TPL_SURFACE_TYPE_WINDOW, format);
+ if (!dri2_surf->tpl_surf) {
+ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create TPL window surface");
+ goto err_destroy_surface;
+ }
+
+ res = tpl_surface_set_reset_cb(dri2_surf->tpl_surf, dri2_surf,
+ reset_surface_cb);
+ if (res != TPL_ERROR_NONE) {
+ _eglError(EGL_BAD_NATIVE_WINDOW,
+ "DRI2: failed to register TPL window surface reset callback");
+ goto err_tpl_surface_destroy;
+ }
+
+ err = pthread_create(&dri2_surf->swap_queue_processor, NULL,
+ swap_queue_processor_worker, dri2_surf);
+ if (err) {
+ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create TPL window thread");
+ goto err_tpl_surface_destroy;
+ }
+
+ return surf;
+
+err_tpl_surface_destroy:
+ tpl_object_unreference((tpl_object_t *) dri2_surf->tpl_surf);
+err_destroy_surface:
+ destroy_surface(surf);
+ return NULL;
+}
+
+static _EGLSurface *
+dri2_tizen_create_pixmap_surface(_EGLDisplay *dpy, _EGLConfig *config,
+ void *native_pixmap, const EGLint *attrib_list)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+ struct dri2_egl_surface *dri2_surf;
+ _EGLSurface *surf;
+ int width, height;
+ tbm_format format;
+ tpl_result_t res;
+
+ surf = create_surface(dpy, config, EGL_PIXMAP_BIT, attrib_list);
+ if (!surf)
+ return NULL;
+
+ res = tpl_display_get_native_pixmap_info(dri2_dpy->tpl_dpy, native_pixmap,
+ &width, &height, &format);
+ if (res != TPL_ERROR_NONE) {
+ _eglError(EGL_BAD_NATIVE_PIXMAP, "DRI2: failed to get pixmap info");
+ goto err_destroy_surface;
+ }
+
+ dri2_surf = dri2_egl_surface(surf);
+ dri2_surf->base.Width = width;
+ dri2_surf->base.Height = height;
+
+ dri2_surf->tpl_surf = tpl_surface_create(dri2_dpy->tpl_dpy, native_pixmap,
+ TPL_SURFACE_TYPE_PIXMAP, format);
+ if (!dri2_surf->tpl_surf) {
+ _eglError(EGL_BAD_ALLOC, "DRI2: failed to create TPL pixmap surface");
+ goto err_destroy_surface;
+ }
+
+ return surf;
+
+err_destroy_surface:
+ destroy_surface(surf);
+ return NULL;
+}
+
+static _EGLSurface *
+dri2_tizen_create_pbuffer_surface(_EGLDisplay *dpy, _EGLConfig *config,
+ const EGLint *attrib_list)
+{
+ struct dri2_egl_surface *dri2_surf;
+ _EGLSurface *surf;
+
+ surf = create_surface(dpy, config, EGL_PBUFFER_BIT, attrib_list);
+ if (!surf)
+ return NULL;
+
+ dri2_surf = dri2_egl_surface(surf);
+
+ if (config->RedSize == 5)
+ dri2_surf->visual = __DRI_IMAGE_FORMAT_RGB565;
+ else if (config->AlphaSize)
+ dri2_surf->visual = __DRI_IMAGE_FORMAT_ARGB8888;
+ else
+ dri2_surf->visual = __DRI_IMAGE_FORMAT_XRGB8888;
+
+ return surf;
+}
+
+static EGLBoolean
+dri2_tizen_destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+ int i;
+
+ if (dri2_surf->swap_queue_processor) {
+ /* Wait for any outstanding swaps to complete */
+ pthread_mutex_lock(&dri2_surf->mutex);
+ while (dri2_surf->swap_queue_idx_head != dri2_surf->swap_queue_idx_tail)
+ pthread_cond_wait(&dri2_surf->swap_queue_cond, &dri2_surf->mutex);
+ pthread_mutex_unlock(&dri2_surf->mutex);
+
+ pthread_cancel(dri2_surf->swap_queue_processor);
+ pthread_join(dri2_surf->swap_queue_processor, NULL);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dri2_surf->swap_queue); i++)
+ free(dri2_surf->swap_queue[i].rects);
+
+ if (dri2_surf->front)
+ dri2_dpy->image->destroyImage(dri2_surf->front);
+
+ if (dri2_surf->back) {
+ tbm_surface_internal_unref(dri2_surf->back->tbm_surf);
+ dri2_surf->back->locked = false;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+ if (dri2_surf->color_buffers[i].dri_image)
+ dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
+ assert(!dri2_surf->color_buffers[i].locked);
+ }
+
+ if (dri2_surf->tpl_surf)
+ tpl_object_unreference((tpl_object_t *) dri2_surf->tpl_surf);
+
+ destroy_surface(surf);
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_tizen_swap_interval(_EGLDisplay *dpy, _EGLSurface *surf, EGLint interval)
+{
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+ tpl_result_t res;
+
+ if (interval > surf->Config->MaxSwapInterval)
+ interval = surf->Config->MaxSwapInterval;
+ else if (interval < surf->Config->MinSwapInterval)
+ interval = surf->Config->MinSwapInterval;
+
+ if (interval == surf->SwapInterval)
+ return EGL_TRUE;
+
+ res = tpl_surface_set_post_interval(dri2_surf->tpl_surf, interval);
+ if (res == TPL_ERROR_NONE) {
+ surf->SwapInterval = interval;
+ return EGL_TRUE;
+ }
+
+ return EGL_FALSE;
+}
+
+static EGLBoolean
+dri2_tizen_swap_buffers_with_damage(_EGLDisplay *dpy, _EGLSurface *draw,
+ const EGLint *rects, EGLint n_rects)
+{
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
+ struct tpl_swap_queue_elem *queue_elem;
+ int i;
+
+ if (dri2_surf->base.Type != EGL_WINDOW_BIT)
+ return EGL_TRUE;
+
+ for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
+ if (draw->SwapBehavior == EGL_BUFFER_PRESERVED)
+ dri2_surf->color_buffers[i].age = 1;
+ else if (dri2_surf->color_buffers[i].age > 0)
+ dri2_surf->color_buffers[i].age++;
+ }
+
+ /*
+ * Make sure we have a back buffer in case we're swapping without ever
+ * rendering.
+ */
+ if (get_back_bo(dri2_surf, false) < 0) {
+ _eglError(EGL_BAD_ALLOC, "DRI2: failed to get back buffer");
+ return EGL_FALSE;
+ }
+
+ dri2_flush_drawable_for_swapbuffers(dpy, draw);
+
+ pthread_mutex_lock(&dri2_surf->mutex);
+ queue_elem =
+ &dri2_surf->swap_queue[dri2_surf->swap_queue_idx_tail];
+
+ queue_elem->tbm_surf = dri2_surf->back->tbm_surf;
+
+ /* Allocate space for damage rectangles in swap queue element if necessary */
+ if (queue_elem->n_rects_max < n_rects) {
+ free(queue_elem->rects);
+
+ if (!queue_elem->n_rects_max)
+ queue_elem->n_rects_max = TIZEN_SWAP_N_RECTS_MIN;
+
+ while (queue_elem->n_rects_max <= n_rects)
+ queue_elem->n_rects_max *= 2;
+
+ queue_elem->rects =
+ malloc(sizeof(*queue_elem->rects) * queue_elem->n_rects_max);
+ if (!queue_elem->rects) {
+ _eglError(EGL_BAD_ALLOC,
+ "DRI2: failed to allocate space for damage rects");
+ queue_elem->n_rects_max = 0;
+ pthread_mutex_unlock(&dri2_surf->mutex);
+ return EGL_FALSE;
+ }
+ }
+
+ /* Copy damage rectangles into swap queue element */
+ STATIC_ASSERT(sizeof(*queue_elem->rects) == sizeof(*rects));
+ memcpy(&queue_elem->rects[0], &rects[0], sizeof(*rects) * n_rects);
+ queue_elem->n_rects = n_rects;
+
+ dri2_surf->swap_queue_idx_tail++;
+ dri2_surf->swap_queue_idx_tail %= ARRAY_SIZE(dri2_surf->color_buffers);
+
+ /* Notify swap_queue_processor_worker that there's new work */
+ pthread_cond_signal(&dri2_surf->swap_queue_cond);
+ pthread_mutex_unlock(&dri2_surf->mutex);
+
+ dri2_surf->back->age = 1;
+ dri2_surf->current = dri2_surf->back;
+ dri2_surf->back = NULL;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_tizen_swap_buffers(_EGLDisplay *dpy, _EGLSurface *draw)
+{
+ return dri2_tizen_swap_buffers_with_damage(dpy, draw, NULL, 0);
+}
+
+static EGLint
+dri2_tizen_query_buffer_age(_EGLDisplay *dpy, _EGLSurface *surface)
+{
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
+
+ if (get_back_bo(dri2_surf, false) < 0) {
+ _eglError(EGL_BAD_ALLOC, "DRI2: failed to get back buffer");
+ return -1;
+ }
+
+ return dri2_surf->back->age;
+}
+
+
+static EGLBoolean
+dri2_tizen_query_surface(_EGLDisplay *dpy, _EGLSurface *surf,
+ EGLint attribute, EGLint *value)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+ struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
+
+ switch (attribute) {
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
+ tpl_handle_t window;
+ int width, height;
+ tbm_format format;
+ tpl_result_t res;
+
+ window = tpl_surface_get_native_handle(dri2_surf->tpl_surf);
+
+ res = tpl_display_get_native_window_info(dri2_dpy->tpl_dpy, window,
+ &width, &height, &format,
+ surf->Config->RedSize +
+ surf->Config->GreenSize +
+ surf->Config->BlueSize +
+ surf->Config->AlphaSize,
+ surf->Config->AlphaSize);
+ if (res == TPL_ERROR_NONE) {
+ surf->Width = width;
+ surf->Height = height;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return _eglQuerySurface(dpy, surf, attribute, value);
+}
+
+
+static struct dri2_egl_display_vtbl dri2_tizen_display_vtbl = {
+ .create_window_surface = dri2_tizen_create_window_surface,
+ .create_pixmap_surface = dri2_tizen_create_pixmap_surface,
+ .create_pbuffer_surface = dri2_tizen_create_pbuffer_surface,
+ .destroy_surface = dri2_tizen_destroy_surface,
+ .create_image = dri2_create_image_khr,
+ .swap_interval = dri2_tizen_swap_interval,
+ .swap_buffers = dri2_tizen_swap_buffers,
+ .swap_buffers_with_damage = dri2_tizen_swap_buffers_with_damage,
+ .query_buffer_age = dri2_tizen_query_buffer_age,
+ .query_surface = dri2_tizen_query_surface,
+ .get_dri_drawable = dri2_surface_get_dri_drawable,
+};
+
+static int
+dri2_tizen_get_buffers(__DRIdrawable *driDrawable,
+ unsigned int format,
+ uint32_t *stamp,
+ void *loaderPrivate,
+ uint32_t buffer_mask,
+ struct __DRIimageList *buffers)
+{
+ struct dri2_egl_surface *dri2_surf = loaderPrivate;
+
+ buffers->image_mask = 0;
+ buffers->front = NULL;
+ buffers->back = NULL;
+
+ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT)
+ if (get_front_bo(dri2_surf) < 0)
+ return 0;
+
+ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK)
+ if (get_back_bo(dri2_surf, true) < 0)
+ return 0;
+
+ if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
+ buffers->front = dri2_surf->front;
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
+ }
+
+ if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
+ buffers->back = dri2_surf->back->dri_image;
+ buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
+ }
+
+ return 1;
+}
+
+static void
+dri2_tizen_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+{
+}
+
+static const __DRIimageLoaderExtension tizen_image_loader_extension = {
+ .base = { __DRI_IMAGE_LOADER, 1 },
+ .getBuffers = dri2_tizen_get_buffers,
+ .flushFrontBuffer = dri2_tizen_flush_front_buffer,
+};
+
+static const __DRIextension *image_loader_extensions[] = {
+ &tizen_image_loader_extension.base,
+ &image_lookup_extension.base,
+ NULL,
+};
+
+static EGLBoolean
+dri2_tizen_add_configs(_EGLDisplay *dpy)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+ int count = 0;
+
+ for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {
+ static const struct rgba_shifts_and_sizes pbuffer_sasa[] = {
+ {
+ /* ARGB8888 */
+ { 16, 8, 0, 24 },
+ { 8, 8, 8, 8 },
+ },
+ {
+ /* RGB888 */
+ { 16, 8, 0, -1 },
+ { 8, 8, 8, 0 },
+ },
+ {
+ /* RGB565 */
+ { 11, 5, 0, -1 },
+ { 5, 6, 5, 0 },
+ },
+ };
+ struct dri2_egl_config *dri2_cfg;
+ int shifts[4];
+ unsigned int sizes[4];
+ unsigned int caveat = 0;
+ int surface_type = 0;
+ tpl_bool_t is_slow;
+ EGLint attr_list[] = {
+ EGL_NATIVE_VISUAL_ID, 0,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE,
+ };
+ tpl_result_t res;
+
+ dri2_get_shifts_and_sizes(dri2_dpy->core, dri2_dpy->driver_configs[i],
+ shifts, sizes);
+
+ dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
+ __DRI_ATTRIB_BUFFER_SIZE, &depth);
+
+ dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
+ __DRI_ATTRIB_CONFIG_CAVEAT, &caveat);
+
+ res = tpl_display_query_config(dri2_dpy->tpl_dpy, TPL_SURFACE_TYPE_WINDOW,
+ sizes[0], sizes[1], sizes[2], sizes[3],
+ depth, &attr_list[1], &is_slow);
+ if (res != TPL_ERROR_NONE)
+ continue;
+ surface_type |= EGL_WINDOW_BIT;
+
+ if (is_slow)
+ caveat |= __DRI_ATTRIB_SLOW_BIT;
+
+ res = tpl_display_query_config(dri2_dpy->tpl_dpy, TPL_SURFACE_TYPE_PIXMAP,
+ sizes[0], sizes[1], sizes[2], sizes[3],
+ depth, NULL, &is_slow);
+ if (res == TPL_ERROR_NONE) {
+ surface_type |= EGL_PIXMAP_BIT;
+
+ if (is_slow)
+ caveat |= __DRI_ATTRIB_SLOW_BIT;
+ }
+
+ for (unsigned j = 0; j < ARRAY_SIZE(pbuffer_sasa); j++) {
+ const struct rgba_shifts_and_sizes *pbuffer_sas = &pbuffer_sasa[j];
+
+ if (shifts[0] == pbuffer_sas->shifts[0] &&
+ shifts[1] == pbuffer_sas->shifts[1] &&
+ shifts[2] == pbuffer_sas->shifts[2] &&
+ shifts[3] == pbuffer_sas->shifts[3] &&
+ sizes[0] == pbuffer_sas->sizes[0] &&
+ sizes[1] == pbuffer_sas->sizes[1] &&
+ sizes[2] == pbuffer_sas->sizes[2] &&
+ sizes[3] == pbuffer_sas->sizes[3]) {
+ surface_type |= EGL_PBUFFER_BIT;
+ break;
+ }
+ }
+
+ if (dri2_dpy->image->base.version >= 9 && dri2_dpy->image->blitImage)
+ surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+
+ if (caveat & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
+ attr_list[3] = EGL_NON_CONFORMANT_CONFIG;
+ else if (caveat & __DRI_ATTRIB_SLOW_BIT)
+ attr_list[3] = EGL_SLOW_CONFIG;
+
+ dri2_cfg = dri2_add_config(dpy, dri2_dpy->driver_configs[i], count + 1,
+ surface_type, &attr_list[0], NULL, NULL);
+ if (dri2_cfg)
+ count++;
+ }
+
+ return count != 0;
+}
+
+EGLBoolean
+dri2_initialize_tizen(_EGLDisplay *dpy)
+{
+ struct dri2_egl_display *dri2_dpy;
+ int i;
+
+ dri2_dpy = calloc(1, sizeof(*dri2_dpy));
+ if (!dri2_dpy)
+ return _eglError(EGL_BAD_ALLOC, "DRI2: failed to create display");
+
+ dpy->DriverData = (void *) dri2_dpy;
+ dri2_dpy->fd = -1;
+
+ dri2_dpy->tpl_dpy =
+ tpl_display_create(TPL_BACKEND_UNKNOWN, dpy->PlatformDisplay);
+ if (!dri2_dpy->tpl_dpy) {
+ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to create tpl display");
+ goto cleanup;
+ }
+
+ for (i = TIZEN_DRM_RENDER_MINOR_START; i <= TIZEN_DRM_RENDER_MINOR_MAX; i++) {
+ char *render_path;
+
+ if (asprintf(&render_path, DRM_RENDER_DEV_NAME, DRM_DIR_NAME, i) < 0)
+ continue;
+
+ dri2_dpy->fd = loader_open_device(render_path);
+ free(render_path);
+ if (dri2_dpy->fd < 0)
+ continue;
+
+ dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
+ if (dri2_dpy->driver_name) {
+ if (dri2_load_driver_dri3(dpy)) {
+ _EGLDevice *dev = _eglAddDevice(dri2_dpy->fd, false);
+ if (!dev) {
+ dlclose(dri2_dpy->driver);
+ _eglLog(_EGL_WARNING, "DRI2: failed to find EGLDevice");
+ } else {
+ dri2_dpy->own_device = 1;
+ dpy->Device = dev;
+ break;
+ }
+ }
+
+ free(dri2_dpy->driver_name);
+ dri2_dpy->driver_name = NULL;
+ }
+
+ close(dri2_dpy->fd);
+ dri2_dpy->fd = -1;
+ }
+
+ if (dri2_dpy->fd < 0) {
+ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to load driver");
+ goto cleanup;
+ }
+
+ dri2_dpy->loader_extensions = &image_loader_extensions[0];
+
+ if (!dri2_create_screen(dpy)) {
+ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to create screen");
+ goto cleanup;
+ }
+
+ if (!dri2_setup_extensions(dpy))
+ goto cleanup;
+
+ dri2_setup_screen(dpy);
+
+ if (!dri2_tizen_add_configs(dpy)) {
+ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to add configs");
+ goto cleanup;
+ }
+
+ dpy->Extensions.EXT_buffer_age = EGL_TRUE;
+ dpy->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE;
+ dpy->Extensions.KHR_image_base = EGL_TRUE;
+ dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
+
+ /*
+ * Fill vtbl last to prevent accidentally calling virtual function during
+ * initialization.
+ */
+ dri2_dpy->vtbl = &dri2_tizen_display_vtbl;
+
+ return EGL_TRUE;
+
+cleanup:
+ dri2_display_destroy(dpy);
+ return EGL_FALSE;
+}
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 234449adf64..43c7b917909 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -416,6 +416,13 @@ _eglGetPlatformDisplayCommon(EGLenum platform, void *native_display,
case EGL_PLATFORM_DEVICE_EXT:
disp = _eglGetDeviceDisplay(native_display, attrib_list);
break;
+#ifdef HAVE_TIZEN_PLATFORM
+ case EGL_PLATFORM_GBM_MESA:
+ case EGL_PLATFORM_WAYLAND_EXT:
+ disp = _eglGetTizenDisplay((struct gbm_device*) native_display,
+ attrib_list);
+ break;
+#endif
default:
RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
}
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
index 765618f0dd0..486ac3b0557 100644
--- a/src/egl/main/egldisplay.c
+++ b/src/egl/main/egldisplay.c
@@ -77,6 +77,7 @@ static const struct {
{ _EGL_PLATFORM_HAIKU, "haiku" },
{ _EGL_PLATFORM_SURFACELESS, "surfaceless" },
{ _EGL_PLATFORM_DEVICE, "device" },
+ { _EGL_PLATFORM_TIZEN, "tizen" },
};
@@ -107,6 +108,17 @@ _eglGetNativePlatformFromEnv(void)
}
}
+#ifdef HAVE_TIZEN_PLATFORM
+ switch (plat) {
+ case _EGL_PLATFORM_DRM:
+ case _EGL_PLATFORM_WAYLAND:
+ plat = _EGL_PLATFORM_TIZEN;
+ break;
+ default:
+ break;
+ }
+#endif
+
if (plat == _EGL_INVALID_PLATFORM)
_eglLog(_EGL_WARNING, "invalid EGL_PLATFORM given");
@@ -120,6 +132,7 @@ _eglGetNativePlatformFromEnv(void)
static _EGLPlatformType
_eglNativePlatformDetectNativeDisplay(void *nativeDisplay)
{
+#ifndef HAVE_TIZEN_PLATFORM
if (nativeDisplay == EGL_DEFAULT_DISPLAY)
return _EGL_INVALID_PLATFORM;
@@ -141,7 +154,7 @@ _eglNativePlatformDetectNativeDisplay(void *nativeDisplay)
return _EGL_PLATFORM_DRM;
#endif
}
-
+#endif
return _EGL_INVALID_PLATFORM;
}
@@ -595,6 +608,23 @@ _eglGetAndroidDisplay(void *native_display,
}
#endif /* HAVE_ANDROID_PLATFORM */
+#ifdef HAVE_TIZEN_PLATFORM
+_EGLDisplay*
+_eglGetTizenDisplay(void *native_display,
+ const EGLint *attrib_list)
+{
+ /* EGL_MESA_platform_gbm and EGL_EXT_platform_wayland recognizes no
+ * attributes. */
+ if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+ return NULL;
+ }
+
+ return _eglFindDisplay(_EGL_PLATFORM_TIZEN, native_display,
+ attrib_list);
+}
+#endif /* HAVE_TIZEN_PLATFORM */
+
_EGLDisplay*
_eglGetDeviceDisplay(void *native_display,
const EGLAttrib *attrib_list)
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 5b05dcc1e6d..cbb098331bf 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -52,6 +52,7 @@ enum _egl_platform_type {
_EGL_PLATFORM_HAIKU,
_EGL_PLATFORM_SURFACELESS,
_EGL_PLATFORM_DEVICE,
+ _EGL_PLATFORM_TIZEN,
_EGL_NUM_PLATFORMS,
_EGL_INVALID_PLATFORM = -1
@@ -329,6 +330,12 @@ _eglGetAndroidDisplay(void *native_display,
const EGLAttrib *attrib_list);
#endif
+#ifdef HAVE_TIZEN_PLATFORM
+_EGLDisplay*
+_eglGetTizenDisplay(void *native_display,
+ const EGLint *attrib_list);
+#endif
+
_EGLDisplay*
_eglGetDeviceDisplay(void *native_display,
const EGLAttrib *attrib_list);
diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c
index 6a91952577f..973b7600ab1 100644
--- a/src/egl/main/egllog.c
+++ b/src/egl/main/egllog.c
@@ -46,15 +46,17 @@
#include "egllog.h"
-#ifdef HAVE_ANDROID_PLATFORM
#define LOG_TAG "EGL-MAIN"
+
+#ifdef HAVE_ANDROID_PLATFORM
#if ANDROID_API_LEVEL >= 26
#include <log/log.h>
#else
#include <cutils/log.h>
#endif /* use log/log.h start from android 8 major version */
-
-#endif /* HAVE_ANDROID_PLATFORM */
+#elif defined(HAVE_TIZEN_PLATFORM)
+#include <dlog.h>
+#endif /* HAVE_TIZEN_PLATFORM */
#define MAXSTRING 1000
#define FALLBACK_LOG_LEVEL _EGL_WARNING
@@ -93,9 +95,26 @@ _eglDefaultLogger(EGLint level, const char *msg)
[_EGL_DEBUG] = ANDROID_LOG_DEBUG,
};
LOG_PRI(egl2alog[level], LOG_TAG, "%s", msg);
+#elif defined(HAVE_TIZEN_PLATFORM)
+ switch (level) {
+ case _EGL_DEBUG:
+ LOGD("%s", msg);
+ break;
+ case _EGL_INFO:
+ LOGI("%s", msg);
+ break;
+ case _EGL_WARNING:
+ LOGW("%s", msg);
+ break;
+ case _EGL_FATAL:
+ LOGF("%s", msg);
+ break;
+ default:
+ break;
+ }
#else
fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg);
-#endif /* HAVE_ANDROID_PLATFORM */
+#endif /* HAVE_TIZEN_PLATFORM */
}
diff --git a/src/egl/meson.build b/src/egl/meson.build
index ab8f4e1fdbe..5749ec88f89 100644
--- a/src/egl/meson.build
+++ b/src/egl/meson.build
@@ -106,7 +106,7 @@ if with_dri2
endif
deps_for_egl += [dep_x11_xcb, dep_xcb_dri2, dep_xcb_xfixes]
endif
- if with_gbm and not with_platform_android
+ if with_gbm and not with_platform_android and not with_platform_tizen
files_egl += files('drivers/dri2/platform_drm.c')
link_for_egl += libgbm
incs_for_egl += [inc_gbm, include_directories('../gbm/main')]
@@ -141,6 +141,11 @@ elif with_platform_haiku
link_for_egl += libgl
deps_for_egl += cpp.find_library('be')
endif
+if with_platform_tizen
+ files_egl += files('drivers/dri2/platform_tizen.c')
+ incs_for_egl += [inc_loader]
+ deps_for_egl += [dep_tizen, dep_libdrm]
+endif
if cc.has_function('mincore')
c_args_for_egl += '-DHAVE_MINCORE'
--
2.25.1