12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634 |
- From 70abef4d4511b1e25ab3b4746644e5324140d9d7 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] 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 968b4f5..3d9d345 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 dac7910..8230db9 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 dea5899..6d34395 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 6a7eede..a8bfe45 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 0000000..a08bc8c
- --- /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 234449a..43c7b91 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 765618f..486ac3b 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 5b05dcc..cbb0983 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 6a91952..973b760 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 ab8f4e1..5749ec8 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'
|