It implements the egl swrast related features for tizen platform on platform_tizen.c
It works with libtpl-egl (Tizen Porting Layer for egl) and libtbm (Tizen Buffer Manager) where back buffers of windows are backed by GEM objects. In Tizen a native window has a queue (tbm_surface_queue) of back buffers allocated by the WL_TBM (wayland client case, WL_TBM is abbreviation of wayland-tbm protocol) or gbm (tizen has implements gbm with tbm) or tbm through tbm_backend. For each frame, EGL needs to dequeue the next back buffer - tizen_window_dequeue_buffer() render to the buffer enqueue the buffer - tizen_window_enqueue_buffer() After enqueuing, the buffer is no longer valid to EGL. v2: - Fixes from Emil's review: a) Add a treating of fail case on tizen_window_enqueue_buffer_with_damage() b) Follow coding style c) Remove unneeded compiler pragma d) Use a stride helper for tizen_swrast_get_image() e) Fix tizen_swrast_get_image() as drm platform's implementation referenced commit: fe2a6281b3b299998fe7399e7dbcc2077d773824 f) Fix tizen_swrast_put_image2() as drm platform's implementation referenced commit: 3a5e3aa5a53cff55a5e31766d713a41ffa5a93d7 g) Add tizen_add_configs_for_surface_type() helper function which removes roundtrips. h) Refactor for tizen_add_configs() - Add image_image_lookup extension to tizen_swrast_loader_extensions Referenced documents: [1] https://www.x.org/wiki/Events/XDC2016/Program/XDC2016_Tizen_Window_System_EGL_Vulkan.pdf [2] https://wiki.tizen.org/wiki/3.0_Porting_Guide/Graphics_and_UI/libtpl-egl [3] https://wiki.tizen.org/wiki/TBM Signed-off-by: Mun Gwan-gyeong <elong...@gmail.com> --- src/egl/Makefile.am | 6 + src/egl/drivers/dri2/platform_tizen.c | 646 ++++++++++++++++++++++++++++++++++ 2 files changed, 652 insertions(+) create mode 100644 src/egl/drivers/dri2/platform_tizen.c diff --git a/src/egl/Makefile.am b/src/egl/Makefile.am index eeb745f973..648672998e 100644 --- a/src/egl/Makefile.am +++ b/src/egl/Makefile.am @@ -108,6 +108,12 @@ libEGL_common_la_LIBADD += $(ANDROID_LIBS) dri2_backend_FILES += drivers/dri2/platform_android.c endif +if HAVE_PLATFORM_TIZEN +AM_CFLAGS += $(TIZEN_CFLAGS) +libEGL_common_la_LIBADD += $(TIZEN_LIBS) +dri2_backend_FILES += drivers/dri2/platform_tizen.c +endif + AM_CFLAGS += \ -I$(top_srcdir)/src/loader \ -I$(top_builddir)/src/egl/drivers/dri2 \ diff --git a/src/egl/drivers/dri2/platform_tizen.c b/src/egl/drivers/dri2/platform_tizen.c new file mode 100644 index 0000000000..7cee03f784 --- /dev/null +++ b/src/egl/drivers/dri2/platform_tizen.c @@ -0,0 +1,646 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2017 Samsung Electronics co., Ltd. All Rights Reserved + * + * Based on platform_android, which has + * + * Copyright (C) 2010-2011 Chia-I Wu <olva...@gmail.com> + * Copyright (C) 2010-2011 LunarG Inc. + * 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 (including the next + * paragraph) 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. + * + * Authors: + * Gwan-gyeong Mun <elong...@gmail.com> + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <xf86drm.h> +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "egl_dri2.h" +#include "egl_dri2_fallbacks.h" +#include "loader.h" + +static EGLBoolean +tizen_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) +{ + int width, height; + + dri2_surf->tbm_surface = tpl_surface_dequeue_buffer(dri2_surf->tpl_surface); + + if (!dri2_surf->tbm_surface) + return EGL_FALSE; + + tbm_surface_internal_ref(dri2_surf->tbm_surface); + + tpl_surface_get_size(dri2_surf->tpl_surface, &width, &height); + if (dri2_surf->base.Width != width || dri2_surf->base.Height != height) { + dri2_surf->base.Width = width; + dri2_surf->base.Height = height; + } + + return EGL_TRUE; +} + +static EGLBoolean +tizen_window_enqueue_buffer_with_damage(_EGLDisplay *disp, + struct dri2_egl_surface *dri2_surf, + const EGLint *rects, + EGLint n_rects) +{ + tpl_result_t ret; + + /* To avoid blocking other EGL calls, release the display mutex before + * we enter tizen_window_enqueue_buffer() and re-acquire the mutex upon + * return. + */ + mtx_unlock(&disp->Mutex); + + if (n_rects < 1 || rects == NULL) { + /* if there is no damage, call the normal API tpl_surface_enqueue_buffer */ + ret = tpl_surface_enqueue_buffer(dri2_surf->tpl_surface, + dri2_surf->tbm_surface); + } else { + /* if there are rectangles of damage region, + call the API tpl_surface_enqueue_buffer_with_damage() */ + ret = tpl_surface_enqueue_buffer_with_damage(dri2_surf->tpl_surface, + dri2_surf->tbm_surface, + n_rects, rects); + } + + if (ret != TPL_ERROR_NONE) { + _eglLog(_EGL_WARNING, "%s : %d :tpl_surface_enqueue fail", __func__, __LINE__); + goto cleanup; + } + + tbm_surface_internal_unref(dri2_surf->tbm_surface); + dri2_surf->tbm_surface = NULL; + + mtx_lock(&disp->Mutex); + + return EGL_TRUE; + +cleanup: + tbm_surface_internal_unref(dri2_surf->tbm_surface); + dri2_surf->tbm_surface = NULL; + mtx_lock(&disp->Mutex); + + return EGL_FALSE; +} + +static EGLBoolean +tizen_window_enqueue_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf) +{ + return tizen_window_enqueue_buffer_with_damage(disp, dri2_surf, NULL, 0); +} + +static void +tizen_window_cancel_buffer(_EGLDisplay *disp, struct dri2_egl_surface *dri2_surf) +{ + tizen_window_enqueue_buffer(disp, dri2_surf); +} + +static _EGLSurface * +tizen_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, + _EGLConfig *conf, void *native_window, + const EGLint *attrib_list) +{ + __DRIcreateNewDrawableFunc createNewDrawable; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); + struct dri2_egl_surface *dri2_surf; + const __DRIconfig *config; + tpl_surface_type_t tpl_surf_type = TPL_SURFACE_ERROR; + tpl_result_t ret = TPL_ERROR_INVALID_PARAMETER; + + dri2_surf = calloc(1, sizeof *dri2_surf); + if (!dri2_surf) { + _eglError(EGL_BAD_ALLOC, "tizen_create_surface"); + return NULL; + } + + if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) + goto cleanup_surface; + + config = dri2_get_dri_config(dri2_conf, type, + dri2_surf->base.GLColorspace); + if (!config) + goto cleanup_surface; + + if (type == EGL_WINDOW_BIT) { + unsigned int alpha, depth; + + if (!native_window) { + _eglError(EGL_BAD_NATIVE_WINDOW, "tizen_create_surface needs vaild native window"); + goto cleanup_surface; + } + dri2_surf->native_win = native_window; + + dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_DEPTH_SIZE, &depth); + dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SIZE, &alpha); + + ret = tpl_display_get_native_window_info(dri2_dpy->tpl_display, + (tpl_handle_t)native_window, + &dri2_surf->base.Width, + &dri2_surf->base.Height, + &dri2_surf->tbm_format, + depth, alpha); + + if (ret != TPL_ERROR_NONE || dri2_surf->tbm_format == 0) { + _eglError(EGL_BAD_NATIVE_WINDOW, "tizen_create_surface fails on tpl_display_get_native_window_info()"); + goto cleanup_surface; + } + + tpl_surf_type = TPL_SURFACE_TYPE_WINDOW; + } else if (type == EGL_PIXMAP_BIT) { + + if (!native_window) { + _eglError(EGL_BAD_NATIVE_PIXMAP, "tizen_create_surface needs valid native pixmap"); + goto cleanup_surface; + } + ret = tpl_display_get_native_pixmap_info(dri2_dpy->tpl_display, + (tpl_handle_t)native_window, + &dri2_surf->base.Width, + &dri2_surf->base.Height, + &dri2_surf->tbm_format); + + if (ret != TPL_ERROR_NONE || dri2_surf->tbm_format == 0) { + _eglError(EGL_BAD_NATIVE_PIXMAP, "tizen_create_surface fails on tpl_display_get_native_pixmap_info"); + goto cleanup_surface; + } + + tpl_surf_type = TPL_SURFACE_TYPE_PIXMAP; + } else { + _eglError(EGL_BAD_NATIVE_WINDOW, "tizen_create_surface does not support PBuffer"); + goto cleanup_surface; + } + + dri2_surf->tpl_surface = tpl_surface_create(dri2_dpy->tpl_display, + (tpl_handle_t)native_window, + tpl_surf_type, + dri2_surf->tbm_format); + if (!dri2_surf->tpl_surface) + goto cleanup_surface; + + createNewDrawable = dri2_dpy->swrast->createNewDrawable; + + dri2_surf->dri_drawable = (*createNewDrawable)(dri2_dpy->dri_screen, config, + dri2_surf); + if (dri2_surf->dri_drawable == NULL) { + _eglError(EGL_BAD_ALLOC, "createNewDrawable"); + goto cleanup_tpl_surface; + } + + return &dri2_surf->base; + +cleanup_tpl_surface: + tpl_object_unreference((tpl_object_t *)dri2_surf->tpl_surface); +cleanup_surface: + free(dri2_surf); + + return NULL; +} + +static _EGLSurface * +tizen_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, void *native_window, + const EGLint *attrib_list) +{ + return tizen_create_surface(drv, disp, EGL_WINDOW_BIT, conf, + native_window, attrib_list); +} + +static _EGLSurface * +tizen_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, void *native_pixmap, + const EGLint *attrib_list) +{ + return tizen_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, + native_pixmap, attrib_list); +} + +static EGLBoolean +tizen_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); + + if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->tbm_surface) + tizen_window_cancel_buffer(disp, dri2_surf); + + dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); + + tpl_object_unreference((tpl_object_t *)dri2_surf->tpl_surface); + + free(dri2_surf); + + return EGL_TRUE; +} + +static int +update_buffers(struct dri2_egl_surface *dri2_surf) +{ + if (dri2_surf->base.Type != EGL_WINDOW_BIT) + return 0; + + /* try to dequeue the next back buffer */ + if (!dri2_surf->tbm_surface && !tizen_window_dequeue_buffer(dri2_surf)) { + _eglLog(_EGL_WARNING, "Could not dequeue buffer from native window"); + return -1; + } + + return 0; +} + +static EGLBoolean +tizen_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp, + _EGLSurface *draw, const EGLint *rects, + EGLint n_rects) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + + if (dri2_surf->base.Type != EGL_WINDOW_BIT) + return EGL_TRUE; + + if (dri2_surf->tbm_surface) + tizen_window_enqueue_buffer_with_damage(disp, dri2_surf, rects, n_rects); + + dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); + + return EGL_TRUE; +} + +static EGLBoolean +tizen_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) +{ + return tizen_swap_buffers_with_damage (drv, disp, draw, NULL, 0); +} + +static EGLBoolean +tizen_query_surface(_EGLDriver *drv, _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); + int width = 0, height = 0; + + if (dri2_surf->base.Type == EGL_WINDOW_BIT && dri2_surf->native_win) { + if (tpl_display_get_native_window_info(dri2_dpy->tpl_display, + dri2_surf->native_win, + &width, &height, + NULL, 0, 0) != TPL_ERROR_NONE) + return EGL_FALSE; + + switch (attribute) { + case EGL_WIDTH: + *value = width; + return EGL_TRUE; + case EGL_HEIGHT: + *value = height; + return EGL_TRUE; + default: + break; + } + } + + return _eglQuerySurface(drv, dpy, surf, attribute, value); +} + +static int +tizen_swrast_get_stride_for_format(tbm_format format, int w) +{ + switch (format) { + case TBM_FORMAT_RGB565: + return 2 * w; + case TBM_FORMAT_BGRA8888: + case TBM_FORMAT_RGBA8888: + case TBM_FORMAT_RGBX8888: + default: + return 4 * w; + } +} + +static void +tizen_swrast_get_drawable_info(__DRIdrawable * draw, + int *x, int *y, int *w, int *h, + void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + + if (update_buffers(dri2_surf) < 0) + return; + + *x = 0; + *y = 0; + *w = dri2_surf->base.Width; + *h = dri2_surf->base.Height; +} + +static void +tizen_swrast_get_image(__DRIdrawable * read, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + tbm_surface_info_s surf_info; + int ret = TBM_SURFACE_ERROR_NONE; + int internal_stride, stride, i; + int x_bytes, w_bytes; + char *src, *dst; + + if (update_buffers(dri2_surf) < 0) + return; + + ret = tbm_surface_map(dri2_surf->tbm_surface, TBM_SURF_OPTION_READ, &surf_info); + + if (ret != TBM_SURFACE_ERROR_NONE) { + _eglLog(_EGL_WARNING, "Could not tbm_surface_map"); + return; + } + + x_bytes = tizen_swrast_get_stride_for_format(dri2_surf->tbm_format, x); + w_bytes = tizen_swrast_get_stride_for_format(dri2_surf->tbm_format, w); + internal_stride = surf_info.planes[0].stride; + stride = w_bytes; + + dst = data; + src = (char*)surf_info.planes[0].ptr + x_bytes + (y * internal_stride); + + for (i = 0; i < h; i++) { + memcpy(dst, src, w_bytes); + dst += stride; + src += internal_stride; + } + + tbm_surface_unmap(dri2_surf->tbm_surface); +} + +static void +tizen_swrast_put_image2(__DRIdrawable * draw, int op, + int x, int y, int w, int h, int stride, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + tbm_surface_info_s surf_info; + int ret = TBM_SURFACE_ERROR_NONE; + int internal_stride, i; + int x_bytes, w_bytes; + char *src, *dst; + + if (op != __DRI_SWRAST_IMAGE_OP_DRAW && op != __DRI_SWRAST_IMAGE_OP_SWAP) + return; + + if (dri2_surf->base.Type == EGL_WINDOW_BIT) { + if (update_buffers(dri2_surf) < 0) { + _eglLog(_EGL_WARNING, "Could not get native buffer"); + return; + } + + ret = tbm_surface_map(dri2_surf->tbm_surface, TBM_SURF_OPTION_WRITE, &surf_info); + if (ret != TBM_SURFACE_ERROR_NONE) { + _eglLog(_EGL_WARNING, "Could not tbm_surface_map"); + return; + } + + x_bytes = tizen_swrast_get_stride_for_format(dri2_surf->tbm_format, x); + w_bytes = tizen_swrast_get_stride_for_format(dri2_surf->tbm_format, w); + internal_stride = surf_info.planes[0].stride; + + dst = (char*)surf_info.planes[0].ptr + x_bytes + (y * internal_stride); + src = data; + + for (i = 0; i < h; i++) { + memcpy(dst, src, w_bytes); + dst += internal_stride; + src += stride; + } + + tbm_surface_unmap(dri2_surf->tbm_surface); + } +} + +static void +tizen_swrast_put_image(__DRIdrawable * draw, int op, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + int stride; + + if (dri2_surf->base.Type == EGL_WINDOW_BIT) { + if (update_buffers(dri2_surf) < 0) { + _eglLog(_EGL_WARNING, "Could not get native buffer"); + return; + } + + stride = tizen_swrast_get_stride_for_format(dri2_surf->tbm_format, w); + tizen_swrast_put_image2(draw, op, x, y, w, h, stride, data, loaderPrivate); + } +} + +static int +tizen_add_configs_for_surface_type(_EGLDisplay *dpy, int surface_type, + int *idx, int cfg_cnt) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); + tpl_surface_type_t tpl_surface_type; + static const struct { + unsigned int rgba_masks[4]; + struct { + unsigned alpha; + unsigned red; + unsigned green; + unsigned blue; + } size; + } visuals[] = { + { { 0xff0000, 0xff00, 0x00ff, 0xff000000 }, { 0, 8, 8, 8 } }, + { { 0xff0000, 0xff00, 0x00ff, 0 }, { 8, 8, 8, 8 } }, + }; + int i; + + if (surface_type == EGL_WINDOW_BIT) + tpl_surface_type = TPL_SURFACE_TYPE_WINDOW; + else if (surface_type == EGL_PIXMAP_BIT) + tpl_surface_type = TPL_SURFACE_TYPE_PIXMAP; + else { + _eglLog(_EGL_WARNING, "Not surpported Surface Type: %d", surface_type); + return cfg_cnt; + } + + for (i = *idx; dri2_dpy->driver_configs[i]; i++) { + for (int j = 0; j < ARRAY_SIZE(visuals); j++) { + struct dri2_egl_config *dri2_conf; + unsigned int depth = 32; + tpl_bool_t is_slow; + EGLint config_attrs[] = { + EGL_NATIVE_VISUAL_ID, 0, + EGL_NONE, + }; + tpl_result_t res; + + res = tpl_display_query_config(dri2_dpy->tpl_display, tpl_surface_type, + visuals[j].size.red, visuals[j].size.green, + visuals[j].size.blue, visuals[j].size.alpha, + depth, &config_attrs[1], &is_slow); + + if (res != TPL_ERROR_NONE) + continue; + + dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[i], + cfg_cnt + 1, surface_type, config_attrs, + visuals[j].rgba_masks); + + if (dri2_conf && (dri2_conf->base.ConfigID == cfg_cnt + 1)) + cfg_cnt++; + } + } + + *idx = i; + return cfg_cnt; +} + +static EGLBoolean +tizen_add_configs(_EGLDriver *drv, _EGLDisplay *dpy) +{ + int idx = 0; + int cfg_cnt = 0; + + cfg_cnt = tizen_add_configs_for_surface_type(dpy, EGL_WINDOW_BIT, &idx, cfg_cnt); + cfg_cnt = tizen_add_configs_for_surface_type(dpy, EGL_PIXMAP_BIT, &idx, cfg_cnt); + + return (cfg_cnt != 0); +} + +static const struct dri2_egl_display_vtbl tizen_display_vtbl = { + .authenticate = NULL, + .create_window_surface = tizen_create_window_surface, + .create_pixmap_surface = tizen_create_pixmap_surface, + .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface, + .destroy_surface = tizen_destroy_surface, + .create_image = dri2_create_image_khr, + .swap_buffers = tizen_swap_buffers, + .swap_buffers_with_damage = tizen_swap_buffers_with_damage, + .swap_buffers_region = dri2_fallback_swap_buffers_region, + .post_sub_buffer = dri2_fallback_post_sub_buffer, + .copy_buffers = dri2_fallback_copy_buffers, + .query_buffer_age = dri2_fallback_query_buffer_age, + .query_surface = tizen_query_surface, + .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, + .get_sync_values = dri2_fallback_get_sync_values, + .get_dri_drawable = dri2_surface_get_dri_drawable, +}; + +static const __DRIswrastLoaderExtension tizen_swrast_loader_extension = { + .base = { __DRI_SWRAST_LOADER, 2 }, + + .getDrawableInfo = tizen_swrast_get_drawable_info, + .putImage = tizen_swrast_put_image, + .getImage = tizen_swrast_get_image, + .putImage2 = tizen_swrast_put_image2, +}; + +static const __DRIextension *tizen_swrast_loader_extensions[] = { + &tizen_swrast_loader_extension.base, + &image_lookup_extension.base, + NULL, +}; + +EGLBoolean +dri2_initialize_tizen(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct dri2_egl_display *dri2_dpy; + tpl_display_t *tpl_display = NULL; + const char *err; + int tbm_bufmgr_fd = -1; + + loader_set_logger(_eglLog); + + dri2_dpy = calloc(1, sizeof *dri2_dpy); + if (!dri2_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + dri2_dpy->fd = -1; + dpy->DriverData = (void *) dri2_dpy; + + /* The TPL_BACKEND_UNKNOWN type for tpl_display decides the tpl's "Display Backend" + * as a PlatformDiplay at runtime. + */ + tpl_display = tpl_display_create(TPL_BACKEND_UNKNOWN, dpy->PlatformDisplay); + if (!tpl_display) { + err = "DRI2: failed to create tpl_display"; + goto cleanup; + } + dri2_dpy->tpl_display = tpl_display; + + /* Get tbm_bufmgr's fd */ + tbm_bufmgr_fd = tbm_drm_helper_get_fd(); + + if (tbm_bufmgr_fd == -1) { + err = "DRI2: failed to get tbm_bufmgr fd"; + goto cleanup; + } + + dri2_dpy->fd = tbm_bufmgr_fd; + dri2_dpy->driver_name = strdup("swrast"); + if (!dri2_load_driver_swrast(dpy)) { + err = "DRI2: failed to load swrast driver"; + goto cleanup; + } + dri2_dpy->loader_extensions = tizen_swrast_loader_extensions; + + if (!dri2_create_screen(dpy)) { + err = "DRI2: failed to create screen"; + goto cleanup; + } + + if (!dri2_setup_extensions(dpy)) { + err = "DRI2: failed to setup extensions"; + goto cleanup; + } + + dri2_setup_screen(dpy); + + if (!tizen_add_configs(drv, dpy)) { + err = "DRI2: failed to add configs"; + goto cleanup; + } + + /* Fill vtbl last to prevent accidentally calling virtual function during + * initialization. + */ + dri2_dpy->vtbl = &tizen_display_vtbl; + + return EGL_TRUE; + +cleanup: + dri2_display_destroy(dpy); + + return _eglError(EGL_NOT_INITIALIZED, err); +} -- 2.14.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev