From 597cd0ebe3d0efac3024eddebae953fee83958a4 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Sat, 13 Feb 2016 14:24:59 +0900 Subject: [PATCH] apply libtdm Change-Id: I32186ffd4d5733eaf6f763251405a5459e85277d --- configure.ac | 8 + packaging/efl.spec | 2 + src/Makefile_Ecore_Drm.am | 1 + src/lib/ecore_drm/Ecore_Drm.h | 9 + src/lib/ecore_drm/ecore_drm_device.c | 80 ++ src/lib/ecore_drm/ecore_drm_display.c | 929 +++++++++++++++++++++ src/lib/ecore_drm/ecore_drm_fb.c | 30 + src/lib/ecore_drm/ecore_drm_logind.c | 4 + src/lib/ecore_drm/ecore_drm_output.c | 71 +- src/lib/ecore_drm/ecore_drm_private.h | 27 + src/lib/ecore_drm/ecore_drm_sprites.c | 9 +- .../ecore_evas/engines/drm/ecore_evas_drm.c | 4 + src/modules/evas/engines/gl_drm/evas_outbuf.c | 41 + 13 files changed, 1213 insertions(+), 2 deletions(-) create mode 100644 src/lib/ecore_drm/ecore_drm_display.c diff --git a/configure.ac b/configure.ac index ef32407..6c71e0e 100644 --- a/configure.ac +++ b/configure.ac @@ -3233,6 +3233,14 @@ if test "x${have_extra_touch_event}" = "xyes";then AC_DEFINE_UNQUOTED([LIBINPUT_SUPPORT_EXTRA_TOUCH_EVENT], [1], [libinput support extra touch event]) fi +EFL_DEPEND_PKG([ECORE_DRM], [TDM], [libtdm >= "1.0.0"], [have_tdm="yes"], [have_tdm="no"]) +AC_MSG_CHECKING([Use TDM]) +AC_MSG_RESULT([${have_tdm}]) +if test "x${have_tdm}" = "xyes" ; then + EFL_DEPEND_PKG([ECORE_DRM], [GBM], [gbm]) + AC_DEFINE_UNQUOTED(HAVE_TDM, 1, [Support for tizen display HAL]) +fi + EFL_EVAL_PKGS([ECORE_DRM]) # Check for ttrace diff --git a/packaging/efl.spec b/packaging/efl.spec index 36aa471..2b1d797 100644 --- a/packaging/efl.spec +++ b/packaging/efl.spec @@ -99,7 +99,9 @@ BuildRequires: pkgconfig(xcb) BuildRequires: pkgconfig(xcb-sync) BuildRequires: pkgconfig(xcb-dri3) %endif +BuildRequires: pkgconfig(gbm) BuildRequires: pkgconfig(libtbm) +BuildRequires: pkgconfig(libtdm) BuildRequires: pkgconfig(libdrm) BuildRequires: pkgconfig(wayland-client) BuildRequires: pkgconfig(wayland-server) diff --git a/src/Makefile_Ecore_Drm.am b/src/Makefile_Ecore_Drm.am index c8a1eef..ec399ec 100644 --- a/src/Makefile_Ecore_Drm.am +++ b/src/Makefile_Ecore_Drm.am @@ -9,6 +9,7 @@ dist_installed_ecoredrmmainheaders_DATA = \ lib/ecore_drm/Ecore_Drm.h lib_ecore_drm_libecore_drm_la_SOURCES = \ +lib/ecore_drm/ecore_drm_display.c \ lib/ecore_drm/ecore_drm_sprites.c \ lib/ecore_drm/ecore_drm_fb.c \ lib/ecore_drm/ecore_drm_evdev.c \ diff --git a/src/lib/ecore_drm/Ecore_Drm.h b/src/lib/ecore_drm/Ecore_Drm.h index 303d97a..34cc352 100644 --- a/src/lib/ecore_drm/Ecore_Drm.h +++ b/src/lib/ecore_drm/Ecore_Drm.h @@ -72,6 +72,8 @@ typedef struct _Ecore_Drm_Fb void *mmap; int w, h; Eina_Bool pending_flip : 1; + void *dev; + void *hal_buffer; } Ecore_Drm_Fb; struct _Ecore_Drm_Device @@ -131,6 +133,8 @@ struct _Ecore_Drm_Device Eina_Bool active : 1; Eina_Bool left_handed : 1; + + void *hal_display; }; struct _Ecore_Drm_Event_Activate @@ -179,6 +183,7 @@ typedef struct _Ecore_Drm_Output_Mode int width, height; unsigned int refresh; drmModeModeInfo info; + const void *hal_mode; } Ecore_Drm_Output_Mode; /* opaque structure to represent a drm output */ @@ -1025,6 +1030,10 @@ EAPI unsigned int ecore_drm_output_crtc_id_get(Ecore_Drm_Output *output); EAPI void ecore_drm_output_current_fb_info_set(Ecore_Drm_Output *output, unsigned int handle, int w, int h, unsigned int format); EAPI void ecore_drm_output_current_fb_info_get(Ecore_Drm_Output *output, unsigned int *handle, int *w, int *h, unsigned int *format); +EAPI Ecore_Drm_Fb *ecore_drm_display_output_primary_layer_fb_get(Ecore_Drm_Output *output); +EAPI void ecore_drm_display_fb_add(Ecore_Drm_Fb *fb); +EAPI void ecore_drm_display_fb_remove(Ecore_Drm_Fb *fb); + # ifdef __cplusplus } # endif diff --git a/src/lib/ecore_drm/ecore_drm_device.c b/src/lib/ecore_drm/ecore_drm_device.c index 8477366..a6a6e7e 100644 --- a/src/lib/ecore_drm/ecore_drm_device.c +++ b/src/lib/ecore_drm/ecore_drm_device.c @@ -10,6 +10,8 @@ ((x) >= (xx)) && ((y) >= (yy))) static Eina_List *drm_devices; + +#ifndef HAVE_TDM static int flip_count = 0; static void @@ -93,6 +95,7 @@ _ecore_drm_device_cb_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) return ECORE_CALLBACK_RENEW; } +#endif #if 0 static Eina_Bool @@ -328,6 +331,47 @@ ecore_drm_device_free(Ecore_Drm_Device *dev) EAPI Eina_Bool ecore_drm_device_open(Ecore_Drm_Device *dev) { +#ifdef HAVE_TDM + int events = 0; + drmVersionPtr ver; + + /* check for valid device */ + if ((!dev) || (!dev->drm.name)) return EINA_FALSE; + + TRACE_EFL_BEGIN(Device_Open); + + dev->drm.fd = -1; + if (!_ecore_drm_display_init(dev)) + { + TRACE_EFL_END(); + return EINA_FALSE; + } + + if ((ver = drmGetVersion(ecore_drm_device_fd_get(dev)))) + { + drmFreeVersion(ver); + dev->drm.fd = ecore_drm_device_fd_get(dev); + } + + /* try to create xkb context */ + if (!(dev->xkb_ctx = _ecore_drm_device_cached_context_get(0))) + { + ERR("Failed to create xkb context: %m"); + TRACE_EFL_END(); + return EINA_FALSE; + } + + events = (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE | + EEZE_UDEV_EVENT_CHANGE); + + dev->watch = + eeze_udev_watch_add(EEZE_UDEV_TYPE_DRM, events, + _ecore_drm_device_cb_output_event, dev); + + TRACE_EFL_END(); + + return EINA_TRUE; +#else uint64_t caps; int events = 0; drmVersionPtr ver; @@ -405,6 +449,7 @@ ecore_drm_device_open(Ecore_Drm_Device *dev) /* ecore_idle_enterer_add(_ecore_drm_device_cb_idle, dev); */ return EINA_TRUE; +#endif } EAPI Eina_Bool @@ -422,8 +467,14 @@ ecore_drm_device_close(Ecore_Drm_Device *dev) if (dev->drm.hdlr) ecore_main_fd_handler_del(dev->drm.hdlr); dev->drm.hdlr = NULL; +#ifdef HAVE_TDM + /* when we use TDM, dev->drm.fd comes from TDM. It will close in TDM. */ + dev->drm.fd = -1; +#endif _ecore_drm_launcher_device_close(dev->drm.name, dev->drm.fd); + _ecore_drm_display_destroy(dev); + /* reset device fd */ dev->drm.fd = -1; @@ -441,6 +492,12 @@ ecore_drm_device_master_get(Ecore_Drm_Device *dev) { drm_magic_t mag; +#ifdef HAVE_TDM + drmVersionPtr ver = drmGetVersion(ecore_drm_device_fd_get(dev)); + if (ver) drmFreeVersion(ver); + else return EINA_TRUE; +#endif + /* check for valid device */ if ((!dev) || (dev->drm.fd < 0)) return EINA_FALSE; @@ -455,6 +512,12 @@ ecore_drm_device_master_get(Ecore_Drm_Device *dev) EAPI Eina_Bool ecore_drm_device_master_set(Ecore_Drm_Device *dev) { +#ifdef HAVE_TDM + drmVersionPtr ver = drmGetVersion(ecore_drm_device_fd_get(dev)); + if (ver) drmFreeVersion(ver); + else return EINA_TRUE; +#endif + /* check for valid device */ if ((!dev) || (dev->drm.fd < 0)) return EINA_FALSE; @@ -468,6 +531,12 @@ ecore_drm_device_master_set(Ecore_Drm_Device *dev) EAPI Eina_Bool ecore_drm_device_master_drop(Ecore_Drm_Device *dev) { +#ifdef HAVE_TDM + drmVersionPtr ver = drmGetVersion(ecore_drm_device_fd_get(dev)); + if (ver) drmFreeVersion(ver); + else return EINA_TRUE; +#endif + /* check for valid device */ if ((!dev) || (dev->drm.fd < 0)) return EINA_FALSE; @@ -482,6 +551,11 @@ EAPI int ecore_drm_device_fd_get(Ecore_Drm_Device *dev) { EINA_SAFETY_ON_NULL_RETURN_VAL(dev, -1); + +#ifdef HAVE_TDM + return _ecore_drm_display_get_fd(dev); +#endif + return dev->drm.fd; } @@ -510,6 +584,12 @@ ecore_drm_device_name_get(Ecore_Drm_Device *dev) /* check for valid device */ EINA_SAFETY_ON_TRUE_RETURN_VAL((!dev) || (dev->drm.fd < 0), NULL); +#ifdef HAVE_TDM + /* Do we have to get drm.name from TDM? drm.path also? possible? + * I guess no. + */ +#endif + return dev->drm.name; } diff --git a/src/lib/ecore_drm/ecore_drm_display.c b/src/lib/ecore_drm/ecore_drm_display.c new file mode 100644 index 0000000..c5edc9a --- /dev/null +++ b/src/lib/ecore_drm/ecore_drm_display.c @@ -0,0 +1,929 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_TDM +# include + +#include "ecore_drm_private.h" + +typedef struct _Ecore_Drm_Hal_Display +{ + tdm_display *display; + + int fd; + Ecore_Fd_Handler *hdlr; +} Ecore_Drm_Hal_Display; + +typedef struct _Ecore_Drm_Hal_Output +{ + tdm_output *output; + tdm_layer *primary_layer; +} Ecore_Drm_Hal_Output; + +static const char *conn_types[] = +{ + "None", "VGA", "DVI-I", "DVI-D", "DVI-A", + "Composite", "S-Video", "LVDS", "Component", "DIN", + "DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual", + "DSI", +}; + +static int fb_data_key = 0; +static Eina_List *fb_list = NULL; + +static Eina_Bool +_ecore_drm_display_output_mode_set_with_fb(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, Ecore_Drm_Fb *fb, int x, int y); + +static void +_ecore_drm_display_output_cb_commit(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED, + unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED, + void *user_data) +{ + Ecore_Drm_Pageflip_Callback *cb; + static int flip_count = 0; + + if (!(cb = user_data)) return; + + flip_count++; + if (flip_count < cb->count) return; + + cb->dev->current = cb->dev->next; + cb->dev->next = NULL; + + flip_count = 0; + if (cb->func) cb->func(cb->data); + free(cb); +} + +static void +_ecore_drm_display_output_cb_vblank(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED, + unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED, + void *user_data) +{ + Ecore_Drm_VBlank_Callback *cb; + + if (!(cb = user_data)) return; + if (cb->func) cb->func(cb->data); + free(cb); +} + +static Eina_Bool +_ecore_drm_display_cb_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) +{ + Ecore_Drm_Hal_Display *hal_display; + tdm_error ret; + + if (!(hal_display = data)) return ECORE_CALLBACK_RENEW; + + ret = tdm_display_handle_events(hal_display->display); + if (ret != TDM_ERROR_NONE) + ERR("tdm_display_handle_events failed"); + + return ECORE_CALLBACK_RENEW; +} + +Eina_Bool +_ecore_drm_display_init(Ecore_Drm_Device *dev) +{ + Ecore_Drm_Hal_Display *hal_display; + + EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE); + + if (dev->hal_display) + return EINA_TRUE; + + hal_display = calloc(1, sizeof(Ecore_Drm_Hal_Display)); + EINA_SAFETY_ON_NULL_RETURN_VAL(hal_display, EINA_FALSE); + + hal_display->display = tdm_display_init(NULL); + if (!hal_display->display) + goto fail_init; + + hal_display->fd = -1; + tdm_display_get_fd(hal_display->display, &hal_display->fd); + if (hal_display->fd < 0) + goto fail_fd; + + hal_display->hdlr = + ecore_main_fd_handler_add(hal_display->fd, ECORE_FD_READ, + _ecore_drm_display_cb_event, hal_display, NULL, NULL); + if (!hal_display->hdlr) + goto fail_hdlr; + + dev->hal_display = hal_display; + + return EINA_TRUE; + +fail_hdlr: +fail_fd: + tdm_display_deinit(hal_display->display); +fail_init: + free(hal_display); + return EINA_FALSE; +} + +void +_ecore_drm_display_destroy(Ecore_Drm_Device *dev) +{ + Ecore_Drm_Hal_Display *hal_display; + + if (!dev || !(hal_display = dev->hal_display)) return; + + if (hal_display->hdlr) ecore_main_fd_handler_del(hal_display->hdlr); + tdm_display_deinit(hal_display->display); + + free(hal_display); + dev->hal_display = NULL; +} + +int +_ecore_drm_display_get_fd(Ecore_Drm_Device *dev) +{ + Ecore_Drm_Hal_Display *hal_display; + + if (!dev || !(hal_display = dev->hal_display)) return -1; + + return hal_display->fd; +} + +Ecore_Drm_Fb* +_ecore_drm_display_fb_find(void *hal_buffer) +{ + Ecore_Drm_Fb *fb; + Eina_List *l; + + EINA_LIST_FOREACH(fb_list, l, fb) + { + if (fb->hal_buffer == hal_buffer) + return fb; + } + + return NULL; +} + +Ecore_Drm_Fb* +_ecore_drm_display_fb_find_with_id(unsigned int id) +{ + Ecore_Drm_Fb *fb; + Eina_List *l; + + EINA_LIST_FOREACH(fb_list, l, fb) + { + if (fb->id == id) + return fb; + } + + return NULL; +} + +Ecore_Drm_Fb* +_ecore_drm_display_fb_create(Ecore_Drm_Device *dev, int width, int height) +{ + Ecore_Drm_Fb *fb; + tbm_bo bo; + tbm_surface_info_s info; + static unsigned int id = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL); + EINA_SAFETY_ON_TRUE_RETURN_VAL((width < 1) || (height < 1), NULL); + if (!(fb = calloc(1, sizeof(Ecore_Drm_Fb)))) return NULL; + + fb->dev = dev; + fb->hal_buffer = + tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT); + if (!fb->hal_buffer) + { + ERR("Could not create hal buffer"); + goto create_err; + } + + bo = tbm_surface_internal_get_bo(fb->hal_buffer, 0); + if (!bo) + { + ERR("Could not get tbm bo"); + goto get_bo; + } + + tbm_bo_add_user_data(bo, (unsigned long)&fb_data_key, NULL); + tbm_bo_set_user_data(bo, (unsigned long)&fb_data_key, fb); + + tbm_surface_get_info(fb->hal_buffer, &info); + + fb->from_client = EINA_TRUE; + fb->id = ++id; + fb->hdl = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32; + fb->stride = info.planes[0].stride; + fb->size = info.size; + fb->w = info.width; + fb->h = info.height; + fb->fd = ecore_drm_device_fd_get(dev); + fb->mmap = info.planes[0].ptr; + + memset(fb->mmap, 0, fb->size); + + ecore_drm_display_fb_add(fb); + + return fb; + +get_bo: + tbm_surface_destroy(fb->hal_buffer); +create_err: + free(fb); + return NULL; +} + +void +_ecore_drm_display_fb_destroy(Ecore_Drm_Fb *fb) +{ + if ((!fb) || (!fb->mmap)) return; + + ecore_drm_display_fb_remove(fb); + + if (fb->hal_buffer) tbm_surface_destroy(fb->hal_buffer); + + free(fb); +} + +EAPI void +ecore_drm_display_fb_add(Ecore_Drm_Fb *fb) +{ + fb_list = eina_list_append(fb_list, fb); +} + +EAPI void +ecore_drm_display_fb_remove(Ecore_Drm_Fb *fb) +{ + fb_list = eina_list_remove(fb_list, fb); +} + +void +_ecore_drm_display_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb) +{ + Ecore_Drm_Output *output; + Eina_List *l; + + EINA_SAFETY_ON_NULL_RETURN(dev); + EINA_SAFETY_ON_NULL_RETURN(fb); + + if (dev->dumb[0]) + { + if ((fb->w != dev->dumb[0]->w) || (fb->h != dev->dumb[0]->h)) + { + /* we need to copy from fb to dev->dumb */ + WRN("Trying to set a Framebuffer of improper size !!"); + return; + } + } + + if (!dev->next) dev->next = fb; + if (!dev->next) return; + + EINA_LIST_FOREACH(dev->outputs, l, output) + { + int x = 0, y = 0; + + if ((!output->enabled) || (!output->current_mode)) continue; + + if (!output->cloned) + { + x = output->x; + y = output->y; + } + + if ((!dev->current) || + (dev->current->stride != dev->next->stride)) + { + if (!_ecore_drm_display_output_mode_set_with_fb(output, output->current_mode, dev->next, x, y)) + { + ERR("Failed to set Mode %dx%d for Output %s: %m", + output->current_mode->width, output->current_mode->height, + output->name); + } + + /* TODO: set dpms on ?? */ + } + } +} + +void +_ecore_drm_display_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb func, void *data) +{ + Ecore_Drm_Output *output; + Eina_List *l; + Ecore_Drm_Pageflip_Callback *cb; + Ecore_Drm_Hal_Display *hal_display; + tdm_error ret; + + EINA_SAFETY_ON_NULL_RETURN(dev); + EINA_SAFETY_ON_NULL_RETURN(fb); + EINA_SAFETY_ON_NULL_RETURN(func); + + if (eina_list_count(dev->outputs) < 1) return; + + if (fb->pending_flip) return; + + hal_display = dev->hal_display; + EINA_SAFETY_ON_NULL_RETURN(hal_display); + + if (!(cb = calloc(1, sizeof(Ecore_Drm_Pageflip_Callback)))) + return; + + cb->dev = dev; + cb->func = func; + cb->data = data; + + EINA_LIST_FOREACH(dev->outputs, l, output) + if (output->enabled) cb->count++; + + EINA_LIST_FOREACH(dev->outputs, l, output) + { + Ecore_Drm_Hal_Output *hal_output; + tbm_surface_h tdm_buffer; + + if ((!output->enabled) || (!output->current_mode)) continue; + + hal_output = output->hal_output; + if (!hal_output || !hal_output->output) continue;; + + tdm_buffer = fb->hal_buffer; + + tdm_layer_set_buffer(hal_output->primary_layer, tdm_buffer); + ret = tdm_output_commit(hal_output->output, 0, _ecore_drm_display_output_cb_commit, cb); + if (ret != TDM_ERROR_NONE) + { + ERR("Cannot commit crtc %u: %m", output->crtc_id); + continue; + } + + fb->pending_flip = EINA_TRUE; + } + + while (fb->pending_flip) + { + ret = tdm_display_handle_events(hal_display->display); + if (ret != TDM_ERROR_NONE) + { + ERR("tdm_display_handle_events failed"); + free(cb); + break; + } + } +} + +static Ecore_Drm_Output_Mode* +_ecore_drm_display_output_mode_add(Ecore_Drm_Output *output, const tdm_output_mode *tdm_mode) +{ + Ecore_Drm_Output_Mode *mode; + uint64_t refresh; + + EINA_SAFETY_ON_NULL_RETURN_VAL(tdm_mode, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL((tdm_mode->htotal > 0), NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL((tdm_mode->vtotal > 0), NULL); + + /* try to allocate space for mode */ + if (!(mode = calloc(1, sizeof(Ecore_Drm_Output_Mode)))) + { + ERR("Could not allocate space for mode"); + return NULL; + } + + mode->flags = 0; + mode->width = tdm_mode->hdisplay; + mode->height = tdm_mode->vdisplay; + + refresh = (tdm_mode->clock * 1000000LL / tdm_mode->htotal + tdm_mode->vtotal / 2) / tdm_mode->vtotal; + if (tdm_mode->flags & TDM_OUTPUT_MODE_FLAG_INTERLACE) + refresh *= 2; + if (tdm_mode->flags & TDM_OUTPUT_MODE_FLAG_DBLSCAN) + refresh /= 2; + if (tdm_mode->vscan > 1) + refresh /= tdm_mode->vscan; + + mode->refresh = refresh; + mode->hal_mode = tdm_mode; + + if (tdm_mode->type & TDM_OUTPUT_MODE_TYPE_PREFERRED) + mode->flags |= TDM_OUTPUT_MODE_TYPE_PREFERRED; + + output->modes = eina_list_append(output->modes, mode); + + return mode; +} + +static Ecore_Drm_Output* +_ecore_drm_display_output_find(Ecore_Drm_Device *dev, unsigned int crtc_id) +{ + Ecore_Drm_Output *output; + Eina_List *l; + + EINA_LIST_FOREACH(dev->outputs, l, output) + { + if (output->crtc_id == crtc_id) + return output; + } + + return NULL; +} + +static Ecore_Drm_Output* +_ecore_drm_display_output_create(Ecore_Drm_Device *dev, unsigned int crtc_id, int x, int y, Eina_Bool cloned) +{ + Ecore_Drm_Output *output = NULL; + Ecore_Drm_Hal_Output *hal_output = NULL; + Ecore_Drm_Hal_Display *hal_display = dev->hal_display; + unsigned int mmWidth = 0, mmHeight = 0, subpixel = 0; + tdm_output *tdm_output_obj; + tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + const char *type; + const tdm_output_mode *tdm_modes = NULL; + const tdm_output_mode *tdm_mode = NULL; + int i, count; + Ecore_Drm_Output_Mode *mode, *current = NULL, *preferred = NULL, *best = NULL; + Eina_List *l; + char temp[TDM_NAME_LEN]; + const char *maker = NULL, *model = NULL, *name = NULL; + + tdm_output_obj = tdm_display_get_output(hal_display->display, crtc_id, NULL); + if (!tdm_output_obj) return NULL; + + tdm_output_get_conn_status(tdm_output_obj, &status); + if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) return NULL; + + if (!(output = calloc(1, sizeof(Ecore_Drm_Output)))) return NULL; + if (!(hal_output = calloc(1, sizeof(Ecore_Drm_Hal_Output)))) + goto fail_hal_output; + + output->hal_output = hal_output; + hal_output->output = tdm_output_obj; + + tdm_output_get_layer_count(hal_output->output, &count); + for (i = 0; i < count; i++) + { + tdm_layer *layer = tdm_output_get_layer(hal_output->output, i, NULL); + tdm_layer_capability capabilities = 0; + tdm_layer_get_capabilities(layer, &capabilities); + if (capabilities & TDM_LAYER_CAPABILITY_PRIMARY) + { + hal_output->primary_layer = layer; + break; + } + } + + if (!hal_output->primary_layer) + { + ERR("couldn't find primary layer"); + goto fail_primary_layer; + } + + output->x = x; + output->y = y; + output->dev = dev; + output->cloned = cloned; + + tdm_output_get_physical_size(hal_output->output, &mmWidth, &mmHeight); + output->phys_width = mmWidth; + output->phys_height = mmHeight; + output->subpixel = tdm_output_get_subpixel(hal_output->output, &subpixel); + + tdm_output_get_model_info(hal_output->output, &maker, &model, &name); + + output->make = eina_stringshare_add(maker); + output->model = eina_stringshare_add(model); + output->name = eina_stringshare_add(name); + + output->connected = (status > 0); + output->enabled = output->connected; + + tdm_output_get_output_type(hal_output->output, &output->conn_type); + if (output->conn_type < ALEN(conn_types)) + type = conn_types[output->conn_type]; + else + type = "UNKNOWN"; + + snprintf(temp, sizeof(temp), "%s-%d", type, 0); + eina_stringshare_replace(&output->name, temp); + + output->crtc_id = crtc_id; + output->pipe = crtc_id; + dev->crtc_allocator |= (1 << output->crtc_id); + output->conn_id = crtc_id; + dev->conn_allocator |= (1 << output->conn_id); + + output->crtc = NULL; + output->dpms = NULL; + + tdm_output_get_mode(hal_output->output, &tdm_mode); + + tdm_output_get_available_modes(hal_output->output, &tdm_modes, &count); + for (i = 0; i < count; i++) + if (!_ecore_drm_display_output_mode_add(output, &tdm_modes[i])) + goto fail_add_mode; + + EINA_LIST_REVERSE_FOREACH(output->modes, l, mode) + { + if (mode->hal_mode == tdm_mode) + current = mode; + if (mode->flags & TDM_OUTPUT_MODE_TYPE_PREFERRED) + preferred = mode; + best = mode; + } + + if (current) output->current_mode = current; + else if (preferred) output->current_mode = preferred; + else if (best) output->current_mode = best; + + if (!output->current_mode) goto fail_current; + + output->current_mode->flags |= TDM_OUTPUT_MODE_TYPE_DEFAULT; + + dev->outputs = eina_list_append(dev->outputs, output); + + /* NB: 'primary' output property is not supported in HW, so we need to + * implement it via software. As such, the First output which gets + * listed via libdrm will be assigned 'primary' until user changes + * it via config */ + if (eina_list_count(dev->outputs) == 1) + output->primary = EINA_TRUE; + + DBG("Created New Output At %d,%d", output->x, output->y); + DBG("\tCrtc Pos: %d %d", output->x, output->y); + DBG("\tCrtc: %d", output->crtc_id); + DBG("\tConn: %d", output->conn_id); + DBG("\tMake: %s", output->make); + DBG("\tModel: %s", output->model); + DBG("\tName: %s", output->name); + DBG("\tCloned: %d", output->cloned); + DBG("\tPrimary: %d", output->primary); + + EINA_LIST_FOREACH(output->modes, l, mode) + { + DBG("\tAdded Mode: %dx%d@%.1f%s%s%s", + mode->width, mode->height, (mode->refresh / 1000.0), + (mode->flags & DRM_MODE_TYPE_PREFERRED) ? ", preferred" : "", + (mode->flags & DRM_MODE_TYPE_DEFAULT) ? ", current" : "", + (count == 0) ? ", built-in" : ""); + } + + _ecore_drm_output_event_send(output, EINA_TRUE); + + return output; + +fail_current: +fail_add_mode: + EINA_LIST_FREE(output->modes, mode) + free(mode); + dev->crtc_allocator &= ~(1 << output->crtc_id); + dev->conn_allocator &= ~(1 << output->conn_id); + eina_stringshare_del(output->name); + eina_stringshare_del(output->model); + eina_stringshare_del(output->make); +fail_primary_layer: + free(hal_output); +fail_hal_output: + free(output); + return NULL; +} + +void +_ecore_drm_display_output_free(Ecore_Drm_Output *output) +{ + Ecore_Drm_Output_Mode *mode; + + /* check for valid output */ + if (!output) return; + + if (output->pending_flip) + { + output->pending_destroy = EINA_TRUE; + return; + } + + _ecore_drm_output_event_send(output, EINA_FALSE); + + output->dev->outputs = eina_list_remove(output->dev->outputs, output); + + /* free modes */ + EINA_LIST_FREE(output->modes, mode) + free(mode); + + /* free strings */ + if (output->name) eina_stringshare_del(output->name); + if (output->model) eina_stringshare_del(output->model); + if (output->make) eina_stringshare_del(output->make); + + free(output); +} + +Eina_Bool +_ecore_drm_display_outputs_create(Ecore_Drm_Device *dev) +{ + Eina_Bool ret = EINA_TRUE; + Ecore_Drm_Output *output = NULL; + int i = 0, x = 0, y = 0, count = 0; + Ecore_Drm_Hal_Display *hal_display; + + EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(dev->hal_display, EINA_FALSE); + + hal_display = dev->hal_display; + + tdm_display_get_output_count(hal_display->display, &count); + if (!(dev->crtcs = calloc(count, sizeof(unsigned int)))) + { + ERR("Could not allocate space for crtcs"); + return EINA_FALSE; + } + + dev->crtc_count = count; + for (i = 0; i < count; i++) + dev->crtcs[i] = i; + + dev->min_width = 0; + dev->min_height = 0; + dev->max_width = UINT32_MAX; + dev->max_height = UINT32_MAX; + + for (i = 0; i < count; i++) + { + if (!(output = _ecore_drm_display_output_create(dev, i, x, y, EINA_FALSE))) + continue; + + x += output->current_mode->width; + } + + ret = EINA_TRUE; + if (eina_list_count(dev->outputs) < 1) + ret = EINA_FALSE; + + return ret; +} + +void +_ecore_drm_display_outputs_update(Ecore_Drm_Device *dev) +{ + Ecore_Drm_Hal_Display *hal_display; + int i, count = 0, x = 0, y = 0; + Ecore_Drm_Output *output; + + EINA_SAFETY_ON_NULL_RETURN(dev); + EINA_SAFETY_ON_NULL_RETURN(dev->hal_display); + + hal_display = dev->hal_display; + + tdm_display_get_output_count(hal_display->display, &count); + + /* find any new connects */ + for (i = 0; i < count; i++) + { + tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + tdm_output *tdm_output_obj; + + tdm_output_obj = tdm_display_get_output(hal_display->display, i, NULL); + output = _ecore_drm_display_output_find(dev, i); + + tdm_output_get_conn_status(tdm_output_obj, &status); + + if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) + { + if (output) + _ecore_drm_display_output_free(output); + + continue; + } + + /* already created */ + if (output) continue; + + if (eina_list_count(dev->outputs) > 0) + { + Ecore_Drm_Output *last; + + if ((last = eina_list_last_data_get(dev->outputs))) + x = last->x + last->current_mode->width; + else + x = 0; + } + else + x = 0; + + /* try to create a new output */ + /* NB: hotplugged outputs will be set to cloned by default */ + _ecore_drm_display_output_create(dev, i, x, y, EINA_TRUE); + } +} + +void +_ecore_drm_display_output_render_enable(Ecore_Drm_Output *output) +{ + Ecore_Drm_Device *dev; + + EINA_SAFETY_ON_NULL_RETURN(output); + EINA_SAFETY_ON_NULL_RETURN(output->dev); + EINA_SAFETY_ON_NULL_RETURN(output->current_mode); + + if (!output->enabled) return; + + dev = output->dev; + + if (!dev->current) + { + /* schedule repaint */ + /* NB: this will trigger a redraw at next idle */ + output->need_repaint = EINA_TRUE; + return; + } + + ecore_drm_output_dpms_set(output, DRM_MODE_DPMS_ON); + + _ecore_drm_display_output_mode_set_with_fb(output, output->current_mode, + dev->current, output->x, output->y); +} + +void +_ecore_drm_display_output_render_disable(Ecore_Drm_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN(output); + + output->need_repaint = EINA_FALSE; + if (!output->enabled) return; + + ecore_drm_output_dpms_set(output, DRM_MODE_DPMS_OFF); +} + +void +_ecore_drm_display_output_dpms_set(Ecore_Drm_Output *output, int level) +{ + Ecore_Drm_Hal_Output *hal_output; + + EINA_SAFETY_ON_NULL_RETURN(output); + EINA_SAFETY_ON_NULL_RETURN(output->dev); + + hal_output = output->hal_output; + EINA_SAFETY_ON_NULL_RETURN(hal_output->output); + + tdm_output_set_dpms(hal_output->output, level); +} + +unsigned int +_ecore_drm_display_output_crtc_buffer_get(Ecore_Drm_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev->current, 0); + + return output->dev->current->id; +} + +void +_ecore_drm_display_output_size_get(Ecore_Drm_Device *dev EINA_UNUSED, int id, int *w, int *h) +{ + Ecore_Drm_Fb *fb; + + fb = _ecore_drm_display_fb_find_with_id(id); + + if (w) *w = fb->w; + if (h) *h = fb->h; +} + +void +_ecore_drm_display_output_crtc_size_get(Ecore_Drm_Output *output, int *width, int *height) +{ + if (width) *width = 0; + if (height) *height = 0; + + EINA_SAFETY_ON_NULL_RETURN(output); + EINA_SAFETY_ON_NULL_RETURN(output->current_mode); + + if (width) *width = output->current_mode->width; + if (height) *height = output->current_mode->height; +} + +static Eina_Bool +_ecore_drm_display_output_mode_set_with_fb(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, + Ecore_Drm_Fb *fb, int x, int y) +{ + Ecore_Drm_Hal_Output *hal_output; + Eina_Bool ret = EINA_TRUE; + + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev, EINA_FALSE); + + hal_output = output->hal_output; + EINA_SAFETY_ON_NULL_RETURN_VAL(hal_output->output, EINA_FALSE); + + output->x = x; + output->y = y; + output->current_mode = mode; + + if (mode && fb) + { + tdm_info_layer info; + tbm_surface_h tdm_buffer = NULL; + tbm_surface_info_s buffer_info; + + EINA_SAFETY_ON_NULL_RETURN_VAL(mode->hal_mode, EINA_FALSE); + + tdm_buffer = fb->hal_buffer; + + tbm_surface_get_info(tdm_buffer, &buffer_info); + info.src_config.size.h = buffer_info.planes[0].stride >> 2; + info.src_config.size.v = tbm_surface_get_height(tdm_buffer); + info.src_config.pos.x = output->x; + info.src_config.pos.y = output->y; + info.src_config.pos.w = mode->width; + info.src_config.pos.h = mode->height; + info.src_config.format = tbm_surface_get_format(tdm_buffer); + info.dst_pos.x = 0; + info.dst_pos.y = 0; + info.dst_pos.w = info.src_config.pos.w; + info.dst_pos.h = info.src_config.pos.h; + info.transform = 0; + + tdm_output_set_mode(hal_output->output, mode->hal_mode); + tdm_layer_set_info(hal_output->primary_layer, &info); + tdm_layer_set_buffer(hal_output->primary_layer, tdm_buffer); + TRACE_OUTPUT_BEGIN(Mode_Set); + tdm_output_commit(hal_output->output, 0, NULL, NULL); + TRACE_OUTPUT_END(); + } + else + { + tdm_layer_set_buffer(hal_output->primary_layer, NULL); + tdm_output_commit(hal_output->output, 0, NULL, NULL); + } + + return ret; +} + +Eina_Bool +_ecore_drm_display_output_mode_set(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, int x, int y) +{ + Ecore_Drm_Device *dev; + Ecore_Drm_Fb *fb = NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev, EINA_FALSE); + + dev = output->dev; + + if (dev->current) fb = dev->current; + else if (dev->next) fb = dev->next; + EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); + + return _ecore_drm_display_output_mode_set_with_fb(output, mode, fb, x, y); +} + +Eina_Bool +_ecore_drm_display_output_possible_crtc_get(Ecore_Drm_Output *output EINA_UNUSED, unsigned int crtc EINA_UNUSED) +{ + return EINA_TRUE; +} + +Eina_Bool +_ecore_drm_display_output_wait_vblank(Ecore_Drm_Output *output, int interval, Ecore_Drm_VBlank_Cb func, void *data) +{ + Ecore_Drm_Hal_Output *hal_output; + Ecore_Drm_VBlank_Callback *cb; + tdm_error ret; + + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE); + + hal_output = output->hal_output; + EINA_SAFETY_ON_NULL_RETURN_VAL(hal_output->output, EINA_FALSE); + + if (!(cb = calloc(1, sizeof(Ecore_Drm_VBlank_Callback)))) + return EINA_FALSE; + + cb->output = output; + cb->func = func; + cb->data = data; + + ret = tdm_output_wait_vblank(hal_output->output, interval, 0, _ecore_drm_display_output_cb_vblank, cb); + if (ret != TDM_ERROR_NONE) + { + ERR("Error Wait VBlank: %m"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Ecore_Drm_Fb* +ecore_drm_display_output_primary_layer_fb_get(Ecore_Drm_Output *output) +{ + Ecore_Drm_Device *dev; + + EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev, NULL); + + dev = output->dev; + + if (dev->current) return dev->current; + else if (dev->next) return dev->next; + + return NULL; +} + +#endif diff --git a/src/lib/ecore_drm/ecore_drm_fb.c b/src/lib/ecore_drm/ecore_drm_fb.c index f99a98e..2c7b631 100644 --- a/src/lib/ecore_drm/ecore_drm_fb.c +++ b/src/lib/ecore_drm/ecore_drm_fb.c @@ -2,6 +2,11 @@ # include #endif +#ifdef HAVE_TDM +# include +# include +#endif + #include "ecore_drm_private.h" /** @@ -11,6 +16,7 @@ * */ +#ifndef HAVE_TDM static Eina_Bool _ecore_drm_fb_create2(int fd, Ecore_Drm_Fb *fb) { @@ -46,10 +52,14 @@ _ecore_drm_fb_create2(int fd, Ecore_Drm_Fb *fb) return EINA_TRUE; } +#endif EAPI Ecore_Drm_Fb * ecore_drm_fb_create(Ecore_Drm_Device *dev, int width, int height) { +#ifdef HAVE_TDM + return _ecore_drm_display_fb_create(dev, width, height); +#else Ecore_Drm_Fb *fb; struct drm_mode_create_dumb carg; struct drm_mode_destroy_dumb darg; @@ -119,11 +129,15 @@ add_err: create_err: free(fb); return NULL; +#endif } EAPI void ecore_drm_fb_destroy(Ecore_Drm_Fb *fb) { +#ifdef HAVE_TDM + _ecore_drm_display_fb_destroy(fb); +#else struct drm_mode_destroy_dumb darg; if ((!fb) || (!fb->mmap)) return; @@ -134,6 +148,7 @@ ecore_drm_fb_destroy(Ecore_Drm_Fb *fb) darg.handle = fb->hdl; drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg); free(fb); +#endif } EAPI void @@ -143,6 +158,13 @@ ecore_drm_fb_dirty(Ecore_Drm_Fb *fb, Eina_Rectangle *rects, unsigned int count) if ((!rects) || (!count)) return; +#ifdef HAVE_TDM + drmVersionPtr ver = drmGetVersion(ecore_drm_device_fd_get(fb->dev)); + if (ver) drmFreeVersion(ver); + else return; + /* FIXME: need to let TDM know the dirty rects? */ +#endif + #ifdef DRM_MODE_FEATURE_DIRTYFB drmModeClip *clip; unsigned int i = 0; @@ -169,6 +191,9 @@ ecore_drm_fb_dirty(Ecore_Drm_Fb *fb, Eina_Rectangle *rects, unsigned int count) EAPI void ecore_drm_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb) { +#ifdef HAVE_TDM + _ecore_drm_display_fb_set(dev, fb); +#else Ecore_Drm_Output *output; Eina_List *l; @@ -215,11 +240,15 @@ ecore_drm_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb) /* TODO: set dpms on ?? */ } } +#endif } EAPI void ecore_drm_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb func, void *data) { +#ifdef HAVE_TDM + _ecore_drm_display_fb_send(dev, fb, func, data); +#else Ecore_Drm_Output *output; Eina_List *l; Ecore_Drm_Pageflip_Callback *cb; @@ -274,4 +303,5 @@ ecore_drm_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb break; } } +#endif } diff --git a/src/lib/ecore_drm/ecore_drm_logind.c b/src/lib/ecore_drm/ecore_drm_logind.c index 833e945..8124b06 100644 --- a/src/lib/ecore_drm/ecore_drm_logind.c +++ b/src/lib/ecore_drm/ecore_drm_logind.c @@ -158,7 +158,9 @@ _ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event) } else { +#ifndef HAVE_TDM Ecore_Drm_Sprite *sprite; +#endif /* disable inputs */ EINA_LIST_FOREACH(dev->inputs, l, input) @@ -168,9 +170,11 @@ _ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event) EINA_LIST_FOREACH(dev->outputs, l, output) _ecore_drm_output_render_disable(output); +#ifndef HAVE_TDM /* disable sprites */ EINA_LIST_FOREACH(dev->sprites, l, sprite) ecore_drm_sprites_fb_set(sprite, 0, 0); +#endif } return ECORE_CALLBACK_PASS_ON; diff --git a/src/lib/ecore_drm/ecore_drm_output.c b/src/lib/ecore_drm/ecore_drm_output.c index ae12dcd..252748d 100644 --- a/src/lib/ecore_drm/ecore_drm_output.c +++ b/src/lib/ecore_drm/ecore_drm_output.c @@ -5,6 +5,7 @@ #include "ecore_drm_private.h" #include +#ifndef HAVE_TDM #define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff @@ -20,6 +21,7 @@ static const char *conn_types[] = "DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual", "DSI", }; +#endif EAPI int ECORE_DRM_EVENT_OUTPUT = 0; @@ -34,7 +36,7 @@ _ecore_drm_output_event_free(void *data EINA_UNUSED, void *event) free(event); } -static void +void _ecore_drm_output_event_send(const Ecore_Drm_Output *output, Eina_Bool plug) { Ecore_Drm_Event_Output *e; @@ -68,6 +70,7 @@ _ecore_drm_output_event_send(const Ecore_Drm_Output *output, Eina_Bool plug) _ecore_drm_output_event_free, NULL); } +#ifndef HAVE_TDM static drmModePropertyPtr _ecore_drm_output_property_get(int fd, drmModeConnectorPtr conn, const char *name) { @@ -651,6 +654,7 @@ _ecore_drm_output_frame_finish(Ecore_Drm_Output *output) output->repaint_scheduled = EINA_FALSE; } +#endif void _ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb) @@ -662,6 +666,7 @@ _ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb) ecore_drm_fb_destroy(fb); } +#ifndef HAVE_TDM void _ecore_drm_output_repaint_start(Ecore_Drm_Output *output) { @@ -691,6 +696,7 @@ _ecore_drm_output_repaint_start(Ecore_Drm_Output *output) finish: _ecore_drm_output_frame_finish(output); } +#endif static void _ecore_drm_output_delete(Ecore_Drm_Device *dev, Ecore_Drm_Output *output) @@ -725,6 +731,9 @@ _ecore_drm_output_delete(Ecore_Drm_Device *dev, Ecore_Drm_Output *output) void _ecore_drm_outputs_update(Ecore_Drm_Device *dev) { +#ifdef HAVE_TDM + _ecore_drm_display_outputs_update(dev); +#else drmModeRes *res; drmModeConnector *conn; int i = 0, x = 0, y = 0; @@ -798,11 +807,15 @@ next: _ecore_drm_output_delete(dev, destory_output); } } +#endif } void _ecore_drm_output_render_enable(Ecore_Drm_Output *output) { +#ifdef HAVE_TDM + _ecore_drm_display_output_render_enable(output); +#else Ecore_Drm_Device *dev; Ecore_Drm_Output_Mode *mode; /* int x = 0, y = 0; */ @@ -839,19 +852,25 @@ _ecore_drm_output_render_enable(Ecore_Drm_Output *output) ERR("Failed to set Mode %dx%d for Output %s: %m", mode->width, mode->height, output->name); } +#endif } void _ecore_drm_output_render_disable(Ecore_Drm_Output *output) { +#ifdef HAVE_TDM + _ecore_drm_display_output_render_disable(output); +#else EINA_SAFETY_ON_NULL_RETURN(output); output->need_repaint = EINA_FALSE; if (!output->enabled) return; ecore_drm_output_cursor_size_set(output, 0, 0, 0); ecore_drm_output_dpms_set(output, DRM_MODE_DPMS_OFF); +#endif } +#ifndef HAVE_TDM static void _ecore_drm_output_planes_get(Ecore_Drm_Device *dev) { @@ -940,6 +959,7 @@ free_plane: drmModeFreePlaneResources(pres); } +#endif /* public functions */ @@ -953,6 +973,15 @@ free_plane: EAPI Eina_Bool ecore_drm_outputs_create(Ecore_Drm_Device *dev) { +#ifdef HAVE_TDM + Eina_Bool ret; + + TRACE_EFL_BEGIN(DRM OUTPUTS CREATE); + ret = _ecore_drm_display_outputs_create(dev); + TRACE_EFL_END(); + + return ret; +#else Eina_Bool ret = EINA_TRUE; Ecore_Drm_Output *output = NULL; drmModeConnector *conn; @@ -1030,14 +1059,20 @@ next: TRACE_EFL_END(); return ret; +#endif } EAPI void ecore_drm_output_free(Ecore_Drm_Output *output) { +#ifdef HAVE_TDM + _ecore_drm_display_output_free(output); +#else _ecore_drm_output_free(output); +#endif } +#ifndef HAVE_TDM EAPI void ecore_drm_output_cursor_size_set(Ecore_Drm_Output *output, int handle, int w, int h) { @@ -1045,6 +1080,7 @@ ecore_drm_output_cursor_size_set(Ecore_Drm_Output *output, int handle, int w, in if (!output->enabled) return; drmModeSetCursor(output->dev->drm.fd, output->crtc_id, handle, w, h); } +#endif EAPI Eina_Bool ecore_drm_output_enable(Ecore_Drm_Output *output) @@ -1078,6 +1114,7 @@ ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb) _ecore_drm_output_fb_release(output, fb); } +#ifndef HAVE_TDM EAPI void ecore_drm_output_repaint(Ecore_Drm_Output *output) { @@ -1173,10 +1210,14 @@ err: dev->next = NULL; } } +#endif EAPI void ecore_drm_output_size_get(Ecore_Drm_Device *dev, int output, int *w, int *h) { +#ifdef HAVE_TDM + _ecore_drm_display_output_size_get(dev, output, w, h); +#else drmModeFB *fb; if (w) *w = 0; @@ -1187,6 +1228,7 @@ ecore_drm_output_size_get(Ecore_Drm_Device *dev, int output, int *w, int *h) if (w) *w = fb->width; if (h) *h = fb->height; drmModeFreeFB(fb); +#endif } EAPI void @@ -1277,6 +1319,10 @@ ecore_drm_output_make_get(Ecore_Drm_Output *output) EAPI void ecore_drm_output_dpms_set(Ecore_Drm_Output *output, int level) { +#ifdef HAVE_TDM + _ecore_drm_display_output_dpms_set(output, level); + output->dpms_level = level; +#else EINA_SAFETY_ON_NULL_RETURN(output); EINA_SAFETY_ON_NULL_RETURN(output->dev); EINA_SAFETY_ON_NULL_RETURN(output->dpms); @@ -1284,6 +1330,7 @@ ecore_drm_output_dpms_set(Ecore_Drm_Output *output, int level) drmModeConnectorSetProperty(output->dev->drm.fd, output->conn_id, output->dpms->prop_id, level); output->dpms_level = level; +#endif } EAPI int @@ -1294,6 +1341,7 @@ ecore_drm_output_dpms_get(Ecore_Drm_Output *output) return output->dpms_level; } +#ifndef HAVE_TDM EAPI void ecore_drm_output_gamma_set(Ecore_Drm_Output *output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b) { @@ -1306,6 +1354,7 @@ ecore_drm_output_gamma_set(Ecore_Drm_Output *output, uint16_t size, uint16_t *r, if (drmModeCrtcSetGamma(output->dev->drm.fd, output->crtc_id, size, r, g, b)) ERR("Failed to set output gamma: %m"); } +#endif EAPI unsigned int ecore_drm_output_crtc_id_get(Ecore_Drm_Output *output) @@ -1318,6 +1367,9 @@ ecore_drm_output_crtc_id_get(Ecore_Drm_Output *output) EAPI unsigned int ecore_drm_output_crtc_buffer_get(Ecore_Drm_Output *output) { +#ifdef HAVE_TDM + return _ecore_drm_display_output_crtc_buffer_get(output); +#else drmModeCrtc *crtc; unsigned int id = 0; @@ -1332,6 +1384,7 @@ ecore_drm_output_crtc_buffer_get(Ecore_Drm_Output *output) drmModeFreeCrtc(crtc); return id; +#endif } EAPI unsigned int @@ -1441,6 +1494,9 @@ ecore_drm_output_primary_set(Ecore_Drm_Output *output) EAPI void ecore_drm_output_crtc_size_get(Ecore_Drm_Output *output, int *width, int *height) { +#ifdef HAVE_TDM + _ecore_drm_display_output_crtc_size_get(output, width, height); +#else if (width) *width = 0; if (height) *height = 0; @@ -1448,11 +1504,15 @@ ecore_drm_output_crtc_size_get(Ecore_Drm_Output *output, int *width, int *height if (width) *width = output->crtc->width; if (height) *height = output->crtc->height; +#endif } EAPI Eina_Bool ecore_drm_output_possible_crtc_get(Ecore_Drm_Output *output, unsigned int crtc) { +#ifdef HAVE_TDM + return _ecore_drm_display_output_possible_crtc_get(output, crtc); +#else Ecore_Drm_Device *dev; drmModeRes *res; drmModeConnector *conn; @@ -1518,11 +1578,15 @@ next: drmModeFreeResources(res); return ret; +#endif } EAPI Eina_Bool ecore_drm_output_mode_set(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, int x, int y) { +#ifdef HAVE_TDM + return _ecore_drm_display_output_mode_set(output, mode, x, y); +#else Ecore_Drm_Device *dev; Eina_Bool ret = EINA_TRUE; unsigned int buffer = 0; @@ -1566,6 +1630,7 @@ ecore_drm_output_mode_set(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, } return ret; +#endif } EAPI void @@ -1597,6 +1662,9 @@ ecore_drm_output_current_fb_info_get(Ecore_Drm_Output *output, unsigned int *han EAPI Eina_Bool ecore_drm_output_wait_vblank(Ecore_Drm_Output *output, int interval, Ecore_Drm_VBlank_Cb func, void *data) { +#ifdef HAVE_TDM + return _ecore_drm_display_output_wait_vblank(output, interval, func, data); +#else Ecore_Drm_Device *dev; Ecore_Drm_VBlank_Callback *cb; drmVBlank vbl; @@ -1628,4 +1696,5 @@ ecore_drm_output_wait_vblank(Ecore_Drm_Output *output, int interval, Ecore_Drm_V } return EINA_TRUE; +#endif } diff --git a/src/lib/ecore_drm/ecore_drm_private.h b/src/lib/ecore_drm/ecore_drm_private.h index 09ddfbe..d46a642 100644 --- a/src/lib/ecore_drm/ecore_drm_private.h +++ b/src/lib/ecore_drm/ecore_drm_private.h @@ -177,6 +177,8 @@ struct _Ecore_Drm_Output int curr_fb_w; int curr_fb_h; int curr_fb_format; + + void *hal_output; }; struct _Ecore_Drm_Seat @@ -294,6 +296,31 @@ int _ecore_drm_launcher_device_flags_set(int fd, int flags); Eina_Bool _ecore_drm_tty_switch(Ecore_Drm_Device *dev, int activate_vt); +#ifdef HAVE_TDM +void _ecore_drm_output_event_send(const Ecore_Drm_Output *output, Eina_Bool plug); + +Eina_Bool _ecore_drm_display_init(Ecore_Drm_Device *dev); +void _ecore_drm_display_destroy(Ecore_Drm_Device *dev); +int _ecore_drm_display_get_fd(Ecore_Drm_Device *dev); +Ecore_Drm_Fb* _ecore_drm_display_fb_find(void *hal_buffer); +Ecore_Drm_Fb* _ecore_drm_display_fb_create(Ecore_Drm_Device *dev, int width, int height); +void _ecore_drm_display_fb_destroy(Ecore_Drm_Fb *fb); +void _ecore_drm_display_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb); +void _ecore_drm_display_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb func, void *data); +Eina_Bool _ecore_drm_display_outputs_create(Ecore_Drm_Device *dev); +void _ecore_drm_display_output_free(Ecore_Drm_Output *output); +void _ecore_drm_display_outputs_update(Ecore_Drm_Device *dev); +void _ecore_drm_display_output_render_enable(Ecore_Drm_Output *output); +void _ecore_drm_display_output_render_disable(Ecore_Drm_Output *output); +void _ecore_drm_display_output_dpms_set(Ecore_Drm_Output *output, int level); +unsigned int _ecore_drm_display_output_crtc_buffer_get(Ecore_Drm_Output *output); +void _ecore_drm_display_output_size_get(Ecore_Drm_Device *dev, int id, int *w, int *h); +void _ecore_drm_display_output_crtc_size_get(Ecore_Drm_Output *output, int *width, int *height); +Eina_Bool _ecore_drm_display_output_mode_set(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, int x, int y); +Eina_Bool _ecore_drm_display_output_possible_crtc_get(Ecore_Drm_Output *output, unsigned int crtc); +Eina_Bool _ecore_drm_display_output_wait_vblank(Ecore_Drm_Output *output, int interval, Ecore_Drm_VBlank_Cb func, void *data); +#endif + Ecore_Drm_Evdev *_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, struct libinput_device *device); void _ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *evdev); Eina_Bool _ecore_drm_evdev_event_process(struct libinput_event *event); diff --git a/src/lib/ecore_drm/ecore_drm_sprites.c b/src/lib/ecore_drm/ecore_drm_sprites.c index d3fa71d..fcef5e6 100644 --- a/src/lib/ecore_drm/ecore_drm_sprites.c +++ b/src/lib/ecore_drm/ecore_drm_sprites.c @@ -16,6 +16,7 @@ EAPI Eina_Bool ecore_drm_sprites_create(Ecore_Drm_Device *dev) { +#ifndef HAVE_TDM drmModePlaneRes *res; drmModePlane *p; unsigned int i = 0; @@ -56,6 +57,7 @@ ecore_drm_sprites_create(Ecore_Drm_Device *dev) /* free resources */ drmModeFreePlaneResources(res); +#endif return EINA_TRUE; } @@ -63,6 +65,7 @@ ecore_drm_sprites_create(Ecore_Drm_Device *dev) EAPI void ecore_drm_sprites_destroy(Ecore_Drm_Device *dev) { +#ifndef HAVE_TDM Ecore_Drm_Sprite *sprite; /* check for valid device */ @@ -77,11 +80,13 @@ ecore_drm_sprites_destroy(Ecore_Drm_Device *dev) free(sprite); } +#endif } EAPI void ecore_drm_sprites_fb_set(Ecore_Drm_Sprite *sprite, int fb_id, int flags) { +#ifndef HAVE_TDM EINA_SAFETY_ON_TRUE_RETURN((!sprite) || (!sprite->output)); if (fb_id) @@ -98,11 +103,13 @@ ecore_drm_sprites_fb_set(Ecore_Drm_Sprite *sprite, int fb_id, int flags) sprite->output->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } +#endif } EAPI Eina_Bool ecore_drm_sprites_crtc_supported(Ecore_Drm_Output *output, unsigned int supported) { +#ifndef HAVE_TDM Ecore_Drm_Device *dev; unsigned int c = 0; @@ -115,6 +122,6 @@ ecore_drm_sprites_crtc_supported(Ecore_Drm_Output *output, unsigned int supporte if (dev->crtcs[c] != output->crtc_id) continue; if ((supported) && (1 << c)) return EINA_FALSE; } - +#endif return EINA_TRUE; } diff --git a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c index 791091f..7f9fc87 100644 --- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c +++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c @@ -549,12 +549,14 @@ _ecore_evas_drm_init(const char *device) goto dev_open_err; } +#ifndef HAVE_TDM /* try to create sprites */ if (!ecore_drm_sprites_create(dev)) { ERR("Could not create sprites: %m"); goto sprite_err; } +#endif /* try to create outputs */ if (!ecore_drm_outputs_create(dev)) @@ -579,7 +581,9 @@ output_err: ecore_drm_inputs_destroy(dev); input_err: ecore_drm_sprites_destroy(dev); +#ifndef HAVE_TDM sprite_err: +#endif ecore_drm_device_close(dev); dev_open_err: ecore_drm_launcher_disconnect(dev); diff --git a/src/modules/evas/engines/gl_drm/evas_outbuf.c b/src/modules/evas/engines/gl_drm/evas_outbuf.c index 839bb9d..2de4544 100644 --- a/src/modules/evas/engines/gl_drm/evas_outbuf.c +++ b/src/modules/evas/engines/gl_drm/evas_outbuf.c @@ -1,7 +1,12 @@ +#include "config.h" #include "evas_engine.h" #include #include "../gl_common/evas_gl_define.h" +#ifdef HAVE_TDM +#include +#endif + /* local variables */ static Outbuf *_evas_gl_drm_window = NULL; static EGLContext context = EGL_NO_CONTEXT; @@ -38,6 +43,16 @@ _evas_outbuf_gbm_surface_create(Outbuf *ob, int w, int h) static void _evas_outbuf_fb_cb_destroy(struct gbm_bo *bo, void *data) { +#ifdef HAVE_TDM + Ecore_Drm_Fb *fb; + + fb = data; + if (fb) + { + ecore_drm_display_fb_remove(fb); + free(fb); + } +#else Ecore_Drm_Fb *fb; fb = data; @@ -49,11 +64,36 @@ _evas_outbuf_fb_cb_destroy(struct gbm_bo *bo, void *data) drmModeRmFB(gbm_device_get_fd(gbm), fb->id); free(fb); } +#endif } static Ecore_Drm_Fb * _evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo) { +#ifdef HAVE_TDM + int ret; + Ecore_Drm_Fb *fb; + static unsigned int id = 0; + + fb = gbm_bo_get_user_data(bo); + if (fb) return fb; + + if (!(fb = calloc(1, sizeof(Ecore_Drm_Fb)))) return NULL; + + fb->id = ++id; + fb->w = gbm_bo_get_width(bo); + fb->h = gbm_bo_get_height(bo); + fb->hdl = gbm_bo_get_handle(bo).u32; + fb->stride = gbm_bo_get_stride(bo); + fb->size = fb->stride * fb->h; + fb->hal_buffer = gbm_tbm_get_surface(bo); + + gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy); + + ecore_drm_display_fb_add(fb); + + return fb; +#else int ret; Ecore_Drm_Fb *fb; uint32_t format; @@ -87,6 +127,7 @@ _evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo) gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy); return fb; +#endif } static void -- 2.7.4