AM_CONDITIONAL([HAVE_BUFFERQUEUE], [test "x${BUFFERQUEUE}" = "xtrue"])
AC_E_OPTIONAL_MODULE([wl_desktop_shell], $have_wayland, [CHECK_MODULE_WL_DESKTOP_SHELL])
-AC_E_OPTIONAL_MODULE([wl_drm], $have_wayland, [CHECK_MODULE_WL_DRM])
+#AC_E_OPTIONAL_MODULE([wl_drm], $have_wayland, [CHECK_MODULE_WL_DRM])
AC_E_OPTIONAL_MODULE([bufferqueue], $have_wayland, [CHECK_MODULE_BUFFERQUEUE])
if test "x${have_wayland}" = "xyes"; then
src/bin/e_msgbus.h \
src/bin/e_obj_dialog.h \
src/bin/e_object.h \
+src/bin/e_output.h \
src/bin/e_path.h \
src/bin/e_pixmap.h \
src/bin/e_place.h \
src/bin/e_plane.h \
src/bin/e_pointer.h \
src/bin/e_prefix.h \
-src/bin/e_randr2.h \
src/bin/e_remember.h \
src/bin/e_resist.h \
src/bin/e_scale.h \
src/bin/e_zoomap.h \
src/bin/e_zone.h \
src/bin/e_util_transform.h \
-src/bin/e_comp_hwc.h
+src/bin/e_comp_hwc.h \
+src/bin/e_comp_drm.h
if HAVE_WAYLAND
ENLIGHTENMENTHEADERS += \
src/bin/e_comp_canvas.c \
src/bin/e_comp_cfdata.c \
src/bin/e_comp_object.c \
+src/bin/e_comp_drm.c \
src/bin/e_config.c \
src/bin/e_config_data.c \
src/bin/e_dbusmenu.c \
src/bin/e_plane.c \
src/bin/e_pointer.c \
src/bin/e_prefix.c \
-src/bin/e_randr2.c \
src/bin/e_remember.c \
src/bin/e_resist.c \
src/bin/e_scale.c \
src/bin/e_zone.c \
src/bin/e_util_transform.c \
src/bin/e_comp_hwc.c \
+src/bin/e_output.c \
$(ENLIGHTENMENTHEADERS)
if HAVE_WAYLAND
$(enlightenment_src)
src_bin_enlightenment_LDFLAGS = -export-dynamic
-src_bin_enlightenment_LDADD = @e_libs@ @dlopen_libs@ @cf_libs@ @VALGRIND_LIBS@ @WAYLAND_LIBS@ @WL_DRM_LIBS@ -lm @SHM_OPEN_LIBS@ $(TTRACE_LIBS)
+src_bin_enlightenment_LDADD = @e_libs@ @dlopen_libs@ @cf_libs@ @VALGRIND_LIBS@ @WAYLAND_LIBS@ -lm @SHM_OPEN_LIBS@ $(TTRACE_LIBS)
if HAVE_WAYLAND_TBM
src_bin_enlightenment_LDADD += @WAYLAND_TBM_LIBS@ @ECORE_DRM_LIBS@
endif
EINTERN Eina_Bool
e_comp_init(void)
{
- E_Module *_mod;
-
_e_comp_log_dom = eina_log_domain_register("e_comp", EINA_COLOR_YELLOW);
eina_log_domain_level_set("e_comp", EINA_LOG_LEVEL_INFO);
e_comp_new();
- _mod = e_module_new("wl_drm");
- EINA_SAFETY_ON_NULL_RETURN_VAL(_mod, EINA_FALSE);
-
- e_comp->comp_type = E_PIXMAP_TYPE_WL;
-
- if (!e_module_enable(_mod))
+ if (!e_comp_drm_init())
{
- ERR("Fail to enable wl_drm module");
+ ERR("Fail to init e_comp_drm");
+ e_object_del(E_OBJECT(e_comp));
+ E_FREE_FUNC(ignores, eina_hash_free);
return EINA_FALSE;
}
+ e_comp->comp_type = E_PIXMAP_TYPE_WL;
+
e_comp_canvas_fake_layers_init();
#ifdef HAVE_HWC
#endif
e_comp_wl_shutdown();
+ e_comp_drm_shutdown();
e_object_del(E_OBJECT(e_comp));
E_FREE_LIST(handlers, ecore_event_handler_del);
/* stop listening for screen events */
void (*shutdown)(void);
/* gather screen info */
- E_Randr2 *(*create)(void);
+ E_Drm_Output *(*create)(void);
/* apply current config */
void (*apply)(void);
/* set dpms (on, standby, suspend, off) */
static void
_e_comp_canvas_resize(Ecore_Evas *ee EINA_UNUSED)
{
- e_randr2_screens_setup(e_comp->w, e_comp->h);
+ e_drm_output_screens_setup(e_comp->w, e_comp->h);
e_comp_canvas_update();
}
--- /dev/null
+#include "e.h"
+#include <Ecore_Drm.h>
+
+static Eina_List *event_handlers = NULL;
+static Eina_Bool session_state = EINA_FALSE;
+
+static Eina_Bool dont_set_ecore_drm_keymap = EINA_FALSE;
+static Eina_Bool dont_use_xkb_cache = EINA_FALSE;
+
+static Eina_Bool
+_e_comp_drm_cb_activate(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+ Ecore_Drm_Event_Activate *e;
+
+ if (!(e = event)) goto end;
+
+ if (e->active)
+ {
+ E_Client *ec;
+
+ if (session_state) goto end;
+ session_state = EINA_TRUE;
+
+ ecore_evas_show(e_comp->ee);
+ E_CLIENT_FOREACH(ec)
+ {
+ if (ec->visible && (!ec->input_only))
+ e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
+ }
+ e_comp_render_queue();
+ e_comp_shape_queue_block(0);
+ ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
+ }
+ else
+ {
+ session_state = EINA_FALSE;
+ ecore_evas_hide(e_comp->ee);
+ edje_file_cache_flush();
+ edje_collection_cache_flush();
+ evas_image_cache_flush(e_comp->evas);
+ evas_font_cache_flush(e_comp->evas);
+ evas_render_dump(e_comp->evas);
+
+ e_comp_render_queue();
+ e_comp_shape_queue_block(1);
+ ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
+ }
+
+end:
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_comp_drm_cb_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+ const Eina_List *l;
+ E_Output_Screen *screen;
+ Ecore_Drm_Event_Output *e;
+
+ if (!(e = event)) goto end;
+
+ DBG("WL_DRM OUTPUT CHANGE");
+
+ EINA_LIST_FOREACH(e_drm_output->screens, l, screen)
+ {
+ if ((!strcmp(screen->info.name, e->name)) &&
+ (!strcmp(screen->info.screen, e->model)))
+ {
+ if (e->plug)
+ {
+ if (!e_comp_wl_output_init(screen->id, e->make, e->model,
+ e->x, e->y, e->w, e->h,
+ e->phys_width, e->phys_height,
+ e->refresh, e->subpixel_order,
+ e->transform))
+ {
+ ERR("Could not setup new output: %s", screen->id);
+ }
+ }
+ else
+ e_comp_wl_output_remove(screen->id);
+
+ break;
+ }
+ }
+
+ /* previous calculation of e_scale gave unsuitable value because
+ * there were no sufficient information to calculate dpi.
+ * so it's considerable to re-calculate e_scale with output geometry.
+ */
+ e_scale_manual_update(((e->w * 254 / e->phys_width) + 5) / 10);
+
+end:
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_comp_drm_cb_input_device_add(void *data, int type, void *event)
+{
+ Ecore_Drm_Event_Input_Device_Add *e;
+ E_Comp *comp = data;
+
+ if (!(e = event)) goto end;
+
+ if (e->caps & EVDEV_SEAT_POINTER)
+ {
+ if (comp->wl_comp_data->ptr.num_devices == 0)
+ {
+ e_pointer_object_set(comp->pointer, NULL, 0, 0);
+ e_comp_wl_input_pointer_enabled_set(EINA_TRUE);
+ }
+ comp->wl_comp_data->ptr.num_devices++;
+ }
+ if (e->caps & EVDEV_SEAT_KEYBOARD)
+ {
+ comp->wl_comp_data->kbd.num_devices++;
+ e_comp_wl_input_keyboard_enabled_set(EINA_TRUE);
+ }
+ if (e->caps & EVDEV_SEAT_TOUCH)
+ {
+ e_comp_wl_input_touch_enabled_set(EINA_TRUE);
+ comp->wl_comp_data->touch.num_devices++;
+ }
+
+end:
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_e_comp_drm_cb_input_device_del(void *data, int type, void *event)
+{
+ Ecore_Drm_Event_Input_Device_Del *e;
+ E_Comp *comp = data;
+
+ if (!(e = event)) goto end;
+
+ if (e->caps & EVDEV_SEAT_POINTER)
+ {
+ comp->wl_comp_data->ptr.num_devices--;
+ if (comp->wl_comp_data->ptr.num_devices == 0)
+ {
+ e_comp_wl_input_pointer_enabled_set(EINA_FALSE);
+ e_pointer_object_set(comp->pointer, NULL, 0, 0);
+ e_pointer_hide(e_comp->pointer);
+ }
+ }
+
+end:
+ if (!e_drm_output->ignore_hotplug_events)
+ e_drm_output_screen_refresh_queue(EINA_TRUE);
+
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_comp_drm_cb_ee_resize(Ecore_Evas *ee EINA_UNUSED)
+{
+ e_comp_canvas_update();
+}
+
+static Ecore_Drm_Output_Mode *
+_e_comp_drm_mode_screen_find(E_Output_Screen *s, Ecore_Drm_Output *output)
+{
+ Ecore_Drm_Output_Mode *mode, *m = NULL;
+ const Eina_List *l;
+ int diff, distance = 0x7fffffff;
+
+ EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), l, mode)
+ {
+ diff = (100 * abs(s->config.mode.w - mode->width)) +
+ (100 * abs(s->config.mode.h - mode->height)) +
+ fabs((100 * s->config.mode.refresh) - (100 * mode->refresh));
+ if (diff < distance)
+ {
+ m = mode;
+ distance = diff;
+ }
+ }
+
+ return m;
+}
+
+static Eina_Bool
+_e_comp_drm_output_exists(Ecore_Drm_Output *output, unsigned int crtc)
+{
+ /* find out if this output can go into the 'possibles' */
+ return ecore_drm_output_possible_crtc_get(output, crtc);
+}
+
+static char *
+_e_comp_drm_output_screen_get(Ecore_Drm_Output *output)
+{
+ const char *model;
+
+ model = ecore_drm_output_model_get(output);
+ if (!model) return NULL;
+
+ return strdup(model);
+}
+
+EINTERN E_Drm_Output *
+e_comp_drm_create(void)
+{
+ Ecore_Drm_Device *dev;
+ Ecore_Drm_Output *output;
+ const Eina_List *l, *ll;
+ E_Drm_Output *r = NULL;
+
+ r = E_NEW(E_Drm_Output, 1);
+ if (!r) return NULL;
+
+ EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+ {
+ EINA_LIST_FOREACH(dev->outputs, ll, output)
+ {
+ E_Output_Screen *s;
+ const Eina_List *m;
+ Ecore_Drm_Output_Mode *omode;
+ unsigned int j;
+ int priority;
+ Eina_Bool ok = EINA_FALSE;
+ Eina_Bool possible = EINA_FALSE;
+ int len = 0;
+
+ s = E_NEW(E_Output_Screen, 1);
+ if (!s) continue;
+
+ s->info.name = ecore_drm_output_name_get(output);
+ printf("COMP DRM: .... out %s\n", s->info.name);
+
+ s->info.connected = ecore_drm_output_connected_get(output);
+ printf("COMP DRM: ...... connected %i\n", s->info.connected);
+
+ s->info.screen = _e_comp_drm_output_screen_get(output);
+
+ s->info.edid = ecore_drm_output_edid_get(output);
+ if (s->info.edid)
+ s->id = malloc(strlen(s->info.name) + 1 + strlen(s->info.edid) + 1);
+ else
+ s->id = malloc(strlen(s->info.name) + 1 + 1);
+ if (!s->id)
+ {
+ free(s->info.screen);
+ free(s->info.edid);
+ free(s);
+ continue;
+ }
+ len = strlen(s->info.name);
+ strncpy(s->id, s->info.name, len + 1);
+ strncat(s->id, "/", 1);
+ if (s->info.edid) strncat(s->id, s->info.edid, strlen(s->info.edid));
+
+ printf("COMP DRM: ...... screen: %s\n", s->id);
+
+ ecore_drm_output_physical_size_get(output, &s->info.size.w,
+ &s->info.size.h);
+
+ EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), m, omode)
+ {
+ E_Output_Mode *rmode;
+
+ rmode = malloc(sizeof(E_Output_Mode));
+ if (!rmode) continue;
+
+ rmode->w = omode->width;
+ rmode->h = omode->height;
+ rmode->refresh = omode->refresh;
+ rmode->preferred = (omode->flags & DRM_MODE_TYPE_PREFERRED);
+
+ s->info.modes = eina_list_append(s->info.modes, rmode);
+ }
+
+ priority = 0;
+ if (ecore_drm_output_primary_get(dev) == output)
+ priority = 100;
+ s->config.priority = priority;
+
+ for (j = 0; j < dev->crtc_count; j++)
+ {
+ if (dev->crtcs[j] == ecore_drm_output_crtc_id_get(output))
+ {
+ ok = EINA_TRUE;
+ break;
+ }
+ }
+
+ if (!ok)
+ {
+ /* get possible crtcs, compare to output_crtc_id_get */
+ for (j = 0; j < dev->crtc_count; j++)
+ {
+ if (_e_comp_drm_output_exists(output, dev->crtcs[j]))
+ {
+ ok = EINA_TRUE;
+ possible = EINA_TRUE;
+ break;
+ }
+ }
+ }
+
+ if (ok)
+ {
+ if (!possible)
+ {
+ unsigned int refresh;
+
+ ecore_drm_output_position_get(output, &s->config.geom.x,
+ &s->config.geom.y);
+ ecore_drm_output_crtc_size_get(output, &s->config.geom.w,
+ &s->config.geom.h);
+
+ ecore_drm_output_current_resolution_get(output,
+ &s->config.mode.w,
+ &s->config.mode.h,
+ &refresh);
+ s->config.mode.refresh = refresh;
+ s->config.enabled =
+ ((s->config.mode.w != 0) && (s->config.mode.h != 0));
+
+ printf("COMP DRM: '%s' %i %i %ix%i\n", s->info.name,
+ s->config.geom.x, s->config.geom.y,
+ s->config.geom.w, s->config.geom.h);
+ }
+
+ /* TODO: are rotations possible ?? */
+ }
+
+ r->screens = eina_list_append(r->screens, s);
+ }
+ }
+
+ return r;
+}
+
+EINTERN Eina_Bool
+e_comp_drm_available(void)
+{
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_comp_drm_stub(void)
+{}
+
+EINTERN void
+e_comp_drm_apply(void)
+{
+ Ecore_Drm_Device *dev;
+ Ecore_Drm_Output *out;
+ E_Output_Screen *s;
+ const Eina_List *l, *ll;
+ int nw, nh, pw, ph, ww, hh;
+ int minw, minh, maxw, maxh;
+ int top_priority = 0;
+
+ /* TODO: what the actual fuck */
+ nw = e_drm_output->w;
+ nh = e_drm_output->h;
+ EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+ {
+ ecore_drm_screen_size_range_get(dev, &minw, &minh, &maxw, &maxh);
+ printf("COMP DRM: size range: %ix%i -> %ix%i\n", minw, minh, maxw, maxh);
+
+ ecore_drm_outputs_geometry_get(dev, NULL, NULL, &pw, &ph);
+ if (nw > maxw) nw = maxw;
+ if (nh > maxh) nh = maxh;
+ if (nw < minw) nw = minw;
+ if (nh < minh) nh = minh;
+ ww = nw;
+ hh = nh;
+ if (nw < pw) ww = pw;
+ if (nh < ph) hh = ph;
+
+ printf("COMP DRM: set vsize: %ix%i\n", ww, hh);
+
+ EINA_LIST_FOREACH(e_drm_output->screens, ll, s)
+ {
+ Ecore_Drm_Output_Mode *mode = NULL;
+ printf("COMP DRM: find output for '%s'\n", s->info.name);
+
+ out = ecore_drm_device_output_name_find(dev, s->info.name);
+ if (!out) continue;
+
+ if (s->config.configured)
+ {
+ printf("\tCOMP DRM: configured by E\n");
+
+ if (s->config.enabled)
+ {
+ printf("\tCOMP DRM: Enabled\n");
+ mode = _e_comp_drm_mode_screen_find(s, out);
+ }
+ else
+ {
+ printf("\tCOMP DRM: Disabled\n");
+ }
+
+ if (s->config.priority > top_priority)
+ top_priority = s->config.priority;
+
+ printf("\tCOMP DRM: Priority: %d\n", s->config.priority);
+
+ printf("\tCOMP DRM: Geom: %d %d %d %d\n",
+ s->config.geom.x, s->config.geom.y,
+ s->config.geom.w, s->config.geom.h);
+
+ if (mode)
+ {
+ printf("\tCOMP DRM: Found Valid Drm Mode\n");
+ printf("\t\tCOMP DRM: %dx%d\n", mode->width, mode->height);
+ }
+ else
+ printf("\tCOMP DRM: No Valid Drm Mode Found\n");
+
+ ecore_drm_output_mode_set(out, mode,
+ s->config.geom.x, s->config.geom.y);
+ if (s->config.priority == top_priority)
+ ecore_drm_output_primary_set(out);
+
+ if (s->config.enabled)
+ ecore_drm_output_enable(out);
+ else
+ ecore_drm_output_disable(out);
+
+ printf("\tCOMP DRM: Mode\n");
+ printf("\t\tCOMP DRM: Geom: %d %d\n",
+ s->config.mode.w, s->config.mode.h);
+ printf("\t\tCOMP DRM: Refresh: %f\n", s->config.mode.refresh);
+ printf("\t\tCOMP DRM: Preferred: %d\n",
+ s->config.mode.preferred);
+
+ }
+ }
+ }
+}
+
+EINTERN void
+e_comp_drm_dpms(int set)
+{
+ Ecore_Drm_Device *dev;
+ Ecore_Drm_Output *out;
+ E_Output_Screen *s;
+ const Eina_List *l, *ll;
+
+ EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+ {
+ EINA_LIST_FOREACH(e_drm_output->screens, ll, s)
+ {
+ out = ecore_drm_device_output_name_find(dev, s->info.name);
+ if (!out) continue;
+
+ if ((!s->config.configured) || s->config.enabled)
+ ecore_drm_output_dpms_set(out, set);
+ }
+ }
+}
+
+// TODO: will remove out after removing dependant e pkgs with E_Comp_Screen_Iface
+static E_Comp_Screen_Iface drmiface =
+{
+ .available = e_comp_drm_available,
+ .init = e_comp_drm_stub,
+ .shutdown = e_comp_drm_stub,
+ .create = e_comp_drm_create,
+ .apply = e_comp_drm_apply,
+ .dpms = e_comp_drm_dpms,
+};
+
+static void
+_drm_read_pixels(E_Comp_Wl_Output *output, void *pixels)
+{
+ Ecore_Drm_Device *dev;
+ Ecore_Drm_Fb *fb;
+ const Eina_List *drm_devs, *l;
+ int i = 0, bstride;
+ unsigned char *s, *d = pixels;
+
+ drm_devs = ecore_drm_devices_get();
+ EINA_LIST_FOREACH(drm_devs, l, dev)
+ {
+ fb = dev->next;
+ if (!fb) fb = dev->current;
+ if (fb) break;
+ }
+
+ if (!fb) return;
+
+ bstride = output->w * sizeof(int);
+
+ for (i = output->y; i < output->y + output->h; i++)
+ {
+ s = fb->mmap;
+ s += (fb->stride * i) + (output->x * sizeof(int));
+ memcpy(d, s, (output->w * sizeof(int)));
+ d += bstride;
+ }
+}
+
+E_API void
+_e_comp_drm_keymap_set(struct xkb_context **ctx, struct xkb_keymap **map)
+{
+ char *keymap_path = NULL;
+ struct xkb_context *context;
+ struct xkb_keymap *keymap;
+ struct xkb_rule_names names = {0,};
+
+ TRACE_INPUT_BEGIN(_e_comp_drm_keymap_set);
+
+ context = xkb_context_new(0);
+ EINA_SAFETY_ON_NULL_RETURN(context);
+
+ /* assemble xkb_rule_names so we can fetch keymap */
+ memset(&names, 0, sizeof(names));
+ names.rules = strdup("evdev");
+ names.model = strdup("pc105");
+ names.layout = strdup("us");
+
+ keymap = e_comp_wl_input_keymap_compile(context, names, &keymap_path);
+ eina_stringshare_del(keymap_path);
+ EINA_SAFETY_ON_NULL_GOTO(keymap, cleanup);
+
+ *ctx = context;
+ *map = keymap;
+
+ if (dont_set_ecore_drm_keymap == EINA_FALSE)
+ {
+ ecore_drm_device_keyboard_cached_context_set(*ctx);
+ ecore_drm_device_keyboard_cached_keymap_set(*map);
+ }
+
+cleanup:
+ free((char *)names.rules);
+ free((char *)names.model);
+ free((char *)names.layout);
+
+ TRACE_INPUT_END();
+}
+
+E_API Eina_Bool
+e_comp_drm_init()
+{
+ E_Comp *comp;
+ int w = 0, h = 0, scr_w = 0, scr_h = 0;
+ const char *env_w, *env_h;
+ struct xkb_context *ctx = NULL;
+ struct xkb_keymap *map = NULL;
+ char buf[1024];
+
+ e_main_ts("\te_comp_drm Init Begin");
+
+ dont_set_ecore_drm_keymap = getenv("NO_ECORE_DRM_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
+ dont_use_xkb_cache = getenv("NO_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
+
+ TRACE_DS_BEGIN(WL_DRM:INIT);
+
+ if (!(comp = e_comp))
+ {
+ comp = e_comp_new();
+ if (!comp)
+ {
+ TRACE_DS_END();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(comp, EINA_FALSE);
+ }
+
+ comp->comp_type = E_PIXMAP_TYPE_WL;
+ }
+
+ /* set gl available if we have ecore_evas support */
+ if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_DRM))
+ e_comp_gl_set(EINA_TRUE);
+
+ env_w = getenv("E_SCREEN_WIDTH");
+ if (env_w)
+ {
+ snprintf(buf, sizeof(buf), "%s", env_w);
+ scr_w = atoi(buf);
+ }
+
+ env_h = getenv("E_SCREEN_HEIGHT");
+ if (env_h)
+ {
+ snprintf(buf, sizeof(buf), "%s", env_h);
+ scr_h = atoi(buf);
+ }
+
+ if (scr_w <= 0) scr_w = 1;
+ if (scr_h <= 0) scr_h = 1;
+
+ //DBG("GL available:%d config engine:%d screen size:%dx%d",
+ INF("GL available:%d config engine:%d screen size:%dx%d",
+ e_comp_gl_get(), e_comp_config_get()->engine, scr_w, scr_h);
+
+ if (e_config->xkb.use_cache && !dont_use_xkb_cache)
+ {
+ e_main_ts("\tDRM Keymap Init");
+ _e_comp_drm_keymap_set(&ctx, &map);
+ e_main_ts("\tDRM Keymap Init Done");
+ }
+
+ if ((e_comp_gl_get()) &&
+ (e_comp_config_get()->engine == E_COMP_ENGINE_GL))
+ {
+ e_main_ts("\tEE_GL_DRM New");
+ comp->ee = ecore_evas_gl_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
+ snprintf(buf, sizeof(buf), "\tEE_GL_DRM New Done %p %dx%d", comp->ee, scr_w, scr_h);
+ e_main_ts(buf);
+
+ if (!comp->ee)
+ e_comp_gl_set(EINA_FALSE);
+ else
+ {
+ Evas_GL *evasgl = NULL;
+ Evas_GL_API *glapi = NULL;
+
+ e_main_ts("\tEvas_GL New");
+ evasgl = evas_gl_new(ecore_evas_get(comp->ee));
+ if (evasgl)
+ {
+ glapi = evas_gl_api_get(evasgl);
+ if (!((glapi) && (glapi->evasglBindWaylandDisplay)))
+ {
+ e_comp_gl_set(EINA_FALSE);
+ ecore_evas_free(comp->ee);
+ comp->ee = NULL;
+ e_main_ts("\tEvas_GL New Failed 1");
+ }
+ else
+ {
+ e_main_ts("\tEvas_GL New Done");
+ }
+ }
+ else
+ {
+ e_comp_gl_set(EINA_FALSE);
+ ecore_evas_free(comp->ee);
+ comp->ee = NULL;
+ e_main_ts("\tEvas_GL New Failed 2");
+ }
+ evas_gl_free(evasgl);
+ }
+ }
+
+ /* fallback to framebuffer drm (non-accel) */
+ if (!comp->ee)
+ {
+ e_main_ts("\tEE_DRM New");
+ comp->ee = ecore_evas_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
+ snprintf(buf, sizeof(buf), "\tEE_DRM New Done %p %dx%d", comp->ee, scr_w, scr_h);
+ e_main_ts(buf);
+ }
+
+ if (!comp->ee)
+ {
+ fprintf(stderr, "Could not create ecore_evas_drm canvas");
+ TRACE_DS_END();
+ return EINA_FALSE;
+ }
+
+ ecore_evas_data_set(e_comp->ee, "comp", e_comp);
+
+ /* get the current screen geometry */
+ ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
+
+ /* resize the canvas */
+ if (!((scr_w == w) && (scr_h == h)))
+ {
+ snprintf(buf, sizeof(buf), "\tEE Resize %dx%d -> %dx%d", scr_w, scr_h, w, h);
+ e_main_ts(buf);
+
+ ecore_evas_resize(comp->ee, w, h);
+
+ e_main_ts("\tEE Resize Done");
+ }
+
+ ecore_evas_callback_resize_set(e_comp->ee, _e_comp_drm_cb_ee_resize);
+
+ e_comp->screen = &drmiface;
+
+ e_main_ts("\tE_Comp_Wl Init");
+ if (!e_comp_wl_init())
+ {
+ TRACE_DS_END();
+ return EINA_FALSE;
+ }
+ e_main_ts("\tE_Comp_Wl Init Done");
+
+ e_main_ts("\tE_Comp_Canvas Init");
+ if (!e_comp_canvas_init(w, h))
+ {
+ TRACE_DS_END();
+ return EINA_FALSE;
+ }
+ e_main_ts("\tE_Comp_Canvas Init Done");
+
+ e_comp_wl->screenshooter.read_pixels = _drm_read_pixels;
+
+ ecore_evas_pointer_xy_get(e_comp->ee,
+ &e_comp_wl->ptr.x,
+ &e_comp_wl->ptr.y);
+
+ evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
+
+ /* comp->pointer = */
+ /* e_pointer_window_new(ecore_evas_window_get(comp->ee), 1); */
+ e_main_ts("\tE_Pointer New");
+ if ((comp->pointer = e_pointer_canvas_new(comp->ee, EINA_TRUE)))
+ {
+ comp->pointer->color = EINA_TRUE;
+ e_pointer_hide(comp->pointer);
+ }
+ e_main_ts("\tE_Pointer New Done");
+
+ /* FIXME: We need a way to trap for user changing the keymap inside of E
+ * without the event coming from X11 */
+
+ /* FIXME: We should make a decision here ...
+ *
+ * Fetch the keymap from drm, OR set this to what the E config is....
+ */
+
+ /* FIXME: This is just for testing at the moment....
+ * happens to jive with what drm does */
+ e_main_ts("\tE_Comp_WL Keymap Init");
+ e_comp_wl_input_keymap_set("evdev", "pc105", "us", ctx, map);
+ e_main_ts("\tE_Comp_WL Keymap Init Done");
+
+ E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_ACTIVATE, _e_comp_drm_cb_activate, comp);
+ E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_OUTPUT, _e_comp_drm_cb_output, comp);
+ E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_ADD, _e_comp_drm_cb_input_device_add, comp);
+ E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_DEL, _e_comp_drm_cb_input_device_del, comp);
+
+ TRACE_DS_END();
+
+ return EINA_TRUE;
+}
+
+E_API void
+e_comp_drm_shutdown()
+{
+ /* shutdown ecore_drm */
+ /* ecore_drm_shutdown(); */
+
+ dont_set_ecore_drm_keymap = EINA_FALSE;
+ dont_use_xkb_cache = EINA_FALSE;
+ E_FREE_LIST(event_handlers, ecore_event_handler_del);
+
+}
--- /dev/null
+#ifdef E_TYPEDEFS
+
+
+#else
+#ifndef E_COMP_DRM_H
+#define E_COMP_DRM_H
+
+
+EINTERN Eina_Bool e_comp_drm_available(void);
+EINTERN void e_comp_drm_stub(void);
+EINTERN void e_comp_drm_apply(void);
+EINTERN E_Drm_Output * e_comp_drm_create(void);
+EINTERN void e_comp_drm_dpms(int set);
+
+E_API Eina_Bool e_comp_drm_init(void);
+E_API void e_comp_drm_shutdown(void);
+
+#endif /*E_COMP_DRM_H*/
+
+#endif
{
Ecore_Drm_Device *dev;
Ecore_Drm_Output *drm_output;
- E_Randr2_Screen *s;
+ E_Output_Screen *s;
const Eina_List *l, *ll;
int x, y, w, h;
EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
{
- EINA_LIST_FOREACH(e_randr2->screens, ll, s)
+ EINA_LIST_FOREACH(e_drm_output->screens, ll, s)
{
ELOGF("HWC", "find output for '%s'", NULL, NULL, s->info.name);
E_Comp_Hwc_Output *hwc_output = NULL;
Ecore_Drm_Device *dev;
Ecore_Drm_Output *drm_output;
- E_Randr2_Screen *s;
+ E_Output_Screen *s;
const Eina_List *l, *ll;
E_Output * eout = NULL;
// TODO: canvas, zone shall match with one output
EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
{
- EINA_LIST_FOREACH(e_randr2->screens, ll, s)
+ EINA_LIST_FOREACH(e_drm_output->screens, ll, s)
{
int len;
_e_comp_wl_cb_randr_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
{
Eina_List *l;
- E_Randr2_Screen *screen;
+ E_Output_Screen *screen;
unsigned int transform = WL_OUTPUT_TRANSFORM_NORMAL;
- if (!e_randr2) return ECORE_CALLBACK_RENEW;
+ if (!e_drm_output) return ECORE_CALLBACK_RENEW;
- EINA_LIST_FOREACH(e_randr2->screens, l, screen)
+ EINA_LIST_FOREACH(e_drm_output->screens, l, screen)
{
if (!screen->config.enabled)
{
e_comp_wl_tbm_init();
#endif
- if (!e_randr2_init())
+ if (!e_drm_output_init())
{
- e_error_message_show(_("Enlightenment cannot initialize randr2!\n"));
+ e_error_message_show(_("Enlightenment cannot initialize drm output!\n"));
TRACE_DS_END();
return EINA_FALSE;
}
- e_randr2_screens_setup(-1, -1);
+ e_drm_output_screens_setup(-1, -1);
/* add event handlers to catch E events */
- E_LIST_HANDLER_APPEND(handlers, E_EVENT_RANDR_CHANGE, _e_comp_wl_cb_randr_change, NULL);
+ E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREEN_CHANGE, _e_comp_wl_cb_randr_change, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD, _e_comp_wl_cb_comp_object_add, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE, _e_comp_wl_cb_mouse_move, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_CANCEL, _e_comp_wl_cb_mouse_button_cancel, NULL);
#include "e_error.h"
#include "e_zone.h"
#include "e_desk.h"
-#include "e_randr2.h"
#include "e_pixmap.h"
#include "e_comp_object.h"
#include "e_util_transform.h"
#include "e_hints.h"
#include "e_plane.h"
#include "e_comp_hwc.h"
+#include "e_comp_drm.h"
+#include "e_output.h"
#ifdef HAVE_WAYLAND
# include "e_comp_wl.h"
--- /dev/null
+#include "e.h"
+
+
+/////////////////////////////////////////////////////////////////////////
+static void _animated_apply_abort(void);
+static Eina_Bool _cb_delay_timer(void *data);
+static Eina_Bool _cb_fade_animator(void *data);
+static void _animated_apply(void);
+static void _do_apply(void);
+static void _info_free(E_Drm_Output *r);
+static char *_screens_fingerprint(E_Drm_Output *r);
+static Eina_Bool _screens_differ(E_Drm_Output *r1, E_Drm_Output *r2);
+static Eina_Bool _cb_screen_change_delay(void *data);
+static void _screen_config_takeover(void);
+static void _screen_config_eval(void);
+static void _screen_config_maxsize(void);
+
+/////////////////////////////////////////////////////////////////////////
+
+static Eina_List *_ev_handlers = NULL;
+static Ecore_Timer *_screen_delay_timer = NULL;
+static Eina_Bool event_screen = EINA_FALSE;
+static Eina_Bool event_ignore = EINA_FALSE;
+
+/////////////////////////////////////////////////////////////////////////
+
+E_API E_Drm_Output *e_drm_output = NULL;
+
+E_API int E_EVENT_RANDR_CHANGE = 0;
+E_API int E_EVENT_SCREEN_CHANGE = 0;
+
+/////////////////////////////////////////////////////////////////////////
+EINTERN Eina_Bool
+e_drm_output_init(void)
+{
+ if (!E_EVENT_SCREEN_CHANGE) E_EVENT_SCREEN_CHANGE = ecore_event_type_new();
+ if (!e_comp_drm_available()) return EINA_FALSE;
+
+ _do_apply();
+
+ ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
+
+ return EINA_TRUE;
+}
+
+EINTERN int
+e_drm_output_shutdown(void)
+{
+ _animated_apply_abort();
+ // nuke any screen config delay handler
+ if (_screen_delay_timer) ecore_timer_del(_screen_delay_timer);
+ _screen_delay_timer = NULL;
+ // clear up all event handlers
+ E_FREE_LIST(_ev_handlers, ecore_event_handler_del);
+ // free up screen info
+ _info_free(e_drm_output);
+ e_drm_output = NULL;
+
+ return 1;
+}
+
+E_API void
+e_drm_output_config_apply(void)
+{
+ _animated_apply();
+}
+
+E_API void
+e_drm_output_screeninfo_update(void)
+{
+ // re-fetch/update current screen info
+ _info_free(e_drm_output);
+ e_drm_output = e_comp_drm_create();
+ _screen_config_maxsize();
+}
+
+/////////////////////////////////////////////////////////////////////////
+static double _start_time = 0.0;
+static Ecore_Animator *_fade_animator = NULL;
+static Ecore_Timer *_apply_delay = NULL;
+Eina_Bool _applying = EINA_FALSE;
+static int _target_from = 0;
+static int _target_to = 0;
+static Evas_Object *_fade_obj = NULL;
+
+static void
+_animated_apply_abort(void)
+{
+ if (_apply_delay) ecore_timer_del(_apply_delay);
+ if (_fade_animator) ecore_animator_del(_fade_animator);
+ _apply_delay = NULL;
+ _fade_animator = NULL;
+ _applying = EINA_FALSE;
+ _fade_obj = NULL;
+}
+
+static Eina_Bool
+_cb_delay_timer(void *data EINA_UNUSED)
+{
+ _apply_delay = NULL;
+ _target_from = 255;
+ _target_to = 0;
+ _start_time = ecore_loop_time_get();
+ _fade_animator = ecore_animator_add(_cb_fade_animator, NULL);
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_cb_fade_animator(void *data EINA_UNUSED)
+{
+ double t = ecore_loop_time_get() - _start_time;
+ int v;
+
+ t = t / 0.5;
+ if (t < 0.0) t = 0.0;
+ v = _target_from + ((_target_to - _target_from) * t);
+ if (t >= 1.0) v = _target_to;
+ evas_object_color_set(_fade_obj, 0, 0, 0, v);
+ if (v == _target_to)
+ {
+ if (_target_to == 255)
+ {
+ _apply_delay = ecore_timer_add(3.0, _cb_delay_timer, NULL);
+ _do_apply();
+ }
+ else
+ {
+ evas_object_del(_fade_obj);
+ _fade_obj = NULL;
+ _applying = EINA_FALSE;
+ }
+ _fade_animator = NULL;
+ return EINA_FALSE;
+ }
+ return EINA_TRUE;
+}
+
+static void
+_animated_apply(void)
+{
+ Evas *e;
+
+ // fade out, config, wait 3 seconds, fade back in
+ if (_applying) return;
+ _applying = EINA_TRUE;
+ _start_time = ecore_loop_time_get();
+ e = e_comp->evas;
+ _fade_obj = evas_object_rectangle_add(e);
+ evas_object_pass_events_set(_fade_obj, EINA_TRUE);
+ evas_object_color_set(_fade_obj, 0, 0, 0, 0);
+ evas_object_move(_fade_obj, 0, 0);
+ evas_object_resize(_fade_obj, 999999, 999999);
+ evas_object_layer_set(_fade_obj, EVAS_LAYER_MAX);
+ evas_object_show(_fade_obj);
+ _target_from = 0;
+ _target_to = 255;
+ _fade_animator = ecore_animator_add(_cb_fade_animator, NULL);
+}
+
+static void
+_do_apply(void)
+{
+ // take current screen config and apply it to the driver
+ printf("OUTPUT: re-get info before applying..\n");
+ _info_free(e_drm_output);
+ e_drm_output = e_comp_drm_create();
+ _screen_config_maxsize();
+ printf("OUTPUT: takeover config...\n");
+ _screen_config_takeover();
+ printf("OUTPUT: eval config...\n");
+ _screen_config_eval();
+ printf("OUTPUT: really apply config...\n");
+ e_comp_drm_apply();
+ printf("OUTPUT: done config...\n");
+}
+
+static void
+_info_free(E_Drm_Output *r)
+{
+ E_Output_Screen *s;
+ E_Output_Mode *m;
+
+ if (!r) return;
+ // free up our randr screen data
+ EINA_LIST_FREE(r->screens, s)
+ {
+ free(s->id);
+ free(s->info.screen);
+ free(s->info.name);
+ free(s->info.edid);
+ EINA_LIST_FREE(s->info.modes, m) free(m);
+ free(s);
+ }
+ free(r);
+}
+
+static char *
+_screens_fingerprint(E_Drm_Output *r)
+{
+ Eina_List *l;
+ E_Output_Screen *s;
+ Eina_Strbuf *buf;
+ char *str;
+
+ buf = eina_strbuf_new();
+ if (!buf) return NULL;
+ EINA_LIST_FOREACH(r->screens, l, s)
+ {
+ if (!s->id) eina_strbuf_append(buf, ":NULL:");
+ else
+ {
+ eina_strbuf_append(buf, ":");
+ eina_strbuf_append(buf, s->id);
+ eina_strbuf_append(buf, ":");
+ eina_strbuf_append(buf, ":LO:");
+ }
+ }
+ str = eina_strbuf_string_steal(buf);
+ eina_strbuf_free(buf);
+ return str;
+}
+
+static Eina_Bool
+_screens_differ(E_Drm_Output *r1, E_Drm_Output *r2)
+{
+ char *s1, *s2;
+ Eina_Bool changed = EINA_FALSE;
+ Eina_List *l, *ll;
+ E_Output_Screen *s, *ss;
+
+ // check monitor outputs and edids, plugged in things
+ s1 = _screens_fingerprint(r1);
+ s2 = _screens_fingerprint(r2);
+ if ((!s1) && (!s2)) return EINA_FALSE;
+ printf("OUTPUT: check fingerprint...\n");
+ if ((s1) && (s2) && (strcmp(s1, s2))) changed = EINA_TRUE;
+ printf("OUTPUT: ... fingerprint says %i\n", changed);
+ free(s1);
+ free(s2);
+ // check screen config
+ EINA_LIST_FOREACH(r2->screens, l, s)
+ {
+ if (!s->id) continue;
+ EINA_LIST_FOREACH(r2->screens, ll, ss)
+ {
+ if ((ss->id) && (!strcmp(s->id, ss->id))) break;
+ ss = NULL;
+ }
+ if (!ss) changed = EINA_TRUE;
+ else if ((s->config.geom.x != ss->config.geom.x) ||
+ (s->config.geom.y != ss->config.geom.y) ||
+ (s->config.geom.w != ss->config.geom.w) ||
+ (s->config.geom.h != ss->config.geom.h) ||
+ (s->config.mode.w != ss->config.mode.w) ||
+ (s->config.mode.h != ss->config.mode.h) ||
+ (s->config.enabled != ss->config.enabled))
+ changed = EINA_TRUE;
+ }
+ printf("OUTPUT: changed = %i\n", changed);
+ return changed;
+}
+
+static Eina_Bool
+_cb_screen_change_delay(void *data EINA_UNUSED)
+{
+ _screen_delay_timer = NULL;
+ printf("OUTPUT: ... %i %i\n", event_screen, event_ignore);
+ // if we had a screen plug/unplug etc. event and we shouldnt ignore it...
+ if ((event_screen) && (!event_ignore))
+ {
+ E_Drm_Output *rtemp;
+ Eina_Bool change = EINA_FALSE;
+
+ printf("OUTPUT: reconfigure screens due to event...\n");
+ rtemp = e_comp_drm_create();
+ if (rtemp)
+ {
+ if (_screens_differ(e_drm_output, rtemp)) change = EINA_TRUE;
+ _info_free(rtemp);
+ }
+ printf("OUTPUT: change = %i\n", change);
+ // we plugged or unplugged some monitor - re-apply config so
+ // known screens can be configured
+ if (change) e_drm_output_config_apply();
+ }
+ // update screen info after the above apply or due to external changes
+ e_drm_output_screeninfo_update();
+ e_comp_canvas_resize(e_drm_output->w, e_drm_output->h);
+ e_drm_output_screens_setup(e_comp->w, e_comp->h);
+ e_comp_canvas_update();
+ // tell the rest of e some screen reconfigure thing happened
+ ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
+ event_screen = EINA_FALSE;
+ event_ignore = EINA_FALSE;
+ return EINA_FALSE;
+}
+
+static void
+_screen_config_takeover(void)
+{
+ Eina_List *l;
+ E_Output_Screen *s;
+ EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+ {
+ s->config.configured = EINA_TRUE;
+ s->config.enabled = EINA_TRUE;
+ }
+}
+
+static void
+_screen_config_eval(void)
+{
+ Eina_List *l;
+ E_Output_Screen *s;
+ int minx, miny, maxx, maxy;
+
+ minx = 65535;
+ miny = 65535;
+ maxx = -65536;
+ maxy = -65536;
+
+ EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+ {
+ if (!s->config.enabled) continue;
+ if (s->config.geom.x < minx) minx = s->config.geom.x;
+ if (s->config.geom.y < miny) miny = s->config.geom.y;
+ if ((s->config.geom.x + s->config.geom.w) > maxx)
+ maxx = s->config.geom.x + s->config.geom.w;
+ if ((s->config.geom.y + s->config.geom.h) > maxy)
+ maxy = s->config.geom.y + s->config.geom.h;
+ printf("OUTPUT: s: '%s' @ %i %i - %ix%i\n",
+ s->info.name,
+ s->config.geom.x, s->config.geom.y,
+ s->config.geom.w, s->config.geom.h);
+ }
+ printf("OUTPUT:--- %i %i -> %i %i\n", minx, miny, maxx, maxy);
+ EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+ {
+ s->config.geom.x -= minx;
+ s->config.geom.y -= miny;
+ }
+ e_drm_output->w = maxx - minx;
+ e_drm_output->h = maxy - miny;
+}
+
+static void
+_screen_config_maxsize(void)
+{
+ Eina_List *l;
+ E_Output_Screen *s;
+ int maxx, maxy;
+
+ maxx = -65536;
+ maxy = -65536;
+ EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+ {
+ if (!s->config.enabled) continue;
+ if ((s->config.geom.x + s->config.geom.w) > maxx)
+ maxx = s->config.geom.x + s->config.geom.w;
+ if ((s->config.geom.y + s->config.geom.h) > maxy)
+ maxy = s->config.geom.y + s->config.geom.h;
+ printf("OUTPUT: '%s': %i %i %ix%i\n",
+ s->info.name,
+ s->config.geom.x, s->config.geom.y,
+ s->config.geom.w, s->config.geom.h);
+ }
+ printf("OUTPUT: result max: %ix%i\n", maxx, maxy);
+ e_drm_output->w = maxx;
+ e_drm_output->h = maxy;
+}
+
+static int
+_screen_sort_cb(const void *data1, const void *data2)
+{
+ const E_Output_Screen *s1 = data1, *s2 = data2;
+ int dif;
+
+ dif = -(s1->config.priority - s2->config.priority);
+ if (dif == 0)
+ {
+ dif = s1->config.geom.x - s2->config.geom.x;
+ if (dif == 0)
+ dif = s1->config.geom.y - s2->config.geom.y;
+ }
+ return dif;
+}
+
+E_API void
+e_drm_output_screen_refresh_queue(Eina_Bool lid_event)
+{
+ // delay handling of screen shances as they can come in in a series over
+ // time and thus we can batch up responding to them by waiting 1.0 sec
+ if (_screen_delay_timer)
+ ecore_timer_reset(_screen_delay_timer);
+ else
+ _screen_delay_timer = ecore_timer_add(1.0, _cb_screen_change_delay, NULL);
+ event_screen |= !!lid_event;
+}
+
+E_API void
+e_drm_output_screens_setup(int rw, int rh)
+{
+ int i;
+ E_Screen *screen;
+ Eina_List *screens = NULL, *screens_rem;
+ Eina_List *all_screens = NULL;
+ Eina_List *l, *ll;
+ E_Output_Screen *s, *s2, *s_chosen;
+ Eina_Bool removed;
+
+ if ((!e_drm_output) || (!e_drm_output->screens)) goto out;
+ // put screens in tmp list
+ EINA_LIST_FOREACH(e_drm_output->screens, l, s)
+ {
+ if ((s->config.enabled) &&
+ (s->config.geom.w > 0) &&
+ (s->config.geom.h > 0))
+ {
+ screens = eina_list_append(screens, s);
+ }
+ }
+ // remove overlapping screens - if a set of screens overlap, keep the
+ // smallest/lowest res
+ do
+ {
+ removed = EINA_FALSE;
+
+ EINA_LIST_FOREACH(screens, l, s)
+ {
+ screens_rem = NULL;
+
+ EINA_LIST_FOREACH(l->next, ll, s2)
+ {
+ if (E_INTERSECTS(s->config.geom.x, s->config.geom.y,
+ s->config.geom.w, s->config.geom.h,
+ s2->config.geom.x, s2->config.geom.y,
+ s2->config.geom.w, s2->config.geom.h))
+ {
+ if (!screens_rem)
+ screens_rem = eina_list_append(screens_rem, s);
+ screens_rem = eina_list_append(screens_rem, s2);
+ }
+ }
+ // we have intersecting screens - choose the lowest res one
+ if (screens_rem)
+ {
+ removed = EINA_TRUE;
+ // find the smallest screen (chosen one)
+ s_chosen = NULL;
+ EINA_LIST_FOREACH(screens_rem, ll, s2)
+ {
+ if (!s_chosen) s_chosen = s2;
+ else
+ {
+ if ((s_chosen->config.geom.w *
+ s_chosen->config.geom.h) >
+ (s2->config.geom.w *
+ s2->config.geom.h))
+ s_chosen = s2;
+ }
+ }
+ // remove all from screens but the chosen one
+ EINA_LIST_FREE(screens_rem, s2)
+ {
+ if (s2 != s_chosen)
+ screens = eina_list_remove_list(screens, l);
+ }
+ // break our list walk and try again
+ break;
+ }
+ }
+ }
+ while (removed);
+ // sort screens by priority etc.
+ screens = eina_list_sort(screens, 0, _screen_sort_cb);
+ i = 0;
+ EINA_LIST_FOREACH(screens, l, s)
+ {
+ screen = E_NEW(E_Screen, 1);
+ screen->escreen = screen->screen = i;
+ screen->x = s->config.geom.x;
+ screen->y = s->config.geom.y;
+ screen->w = s->config.geom.w;
+ screen->h = s->config.geom.h;
+ if (s->id) screen->id = strdup(s->id);
+
+ all_screens = eina_list_append(all_screens, screen);
+ printf("xinerama screen %i %i %ix%i\n", screen->x, screen->y, screen->w, screen->h);
+ INF("E INIT: XINERAMA SCREEN: [%i][%i], %ix%i+%i+%i",
+ i, i, screen->w, screen->h, screen->x, screen->y);
+ i++;
+ }
+ eina_list_free(screens);
+ // if we have NO screens at all (above - i will be 0) AND we have no
+ // existing screens set up in xinerama - then just say root window size
+ // is the entire screen. this should handle the case where you unplug ALL
+ // screens from an existing setup (unplug external monitors and/or close
+ // laptop lid), in which case as long as at least one screen is configured
+ // in xinerama, it will be left-as is until next time we re-eval screen
+ // setup and have at least one screen
+ printf("xinerama setup............... %i %p\n", i, e_xinerama_screens_all_get());
+ if ((i == 0) && (!e_xinerama_screens_all_get()))
+ {
+out:
+ screen = E_NEW(E_Screen, 1);
+ screen->escreen = screen->screen = 0;
+ screen->x = 0;
+ screen->y = 0;
+ if ((rw > 0) && (rh > 0))
+ screen->w = rw, screen->h = rh;
+ else
+ ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &screen->w, &screen->h);
+ all_screens = eina_list_append(all_screens, screen);
+ }
+ e_xinerama_screens_set(all_screens);
+}
--- /dev/null
+#ifdef E_TYPEDEFS
+
+typedef struct _E_Drm_Output E_Drm_Output;
+typedef struct _E_Output_Screen E_Output_Screen;
+typedef struct _E_Output_Mode E_Output_Mode;
+
+#else
+#ifndef E_OUTPUT_H
+#define E_OUTPUT_H
+
+struct _E_Drm_Output
+{
+ Eina_List *screens; // available screens
+ int w, h; // virtual resolution needed for screens (calculated)
+ unsigned char ignore_hotplug_events;
+ unsigned char ignore_acpi_events;
+};
+
+struct _E_Output_Mode
+{
+ int w, h; // resolution width and height
+ double refresh; // refresh in hz
+ Eina_Bool preferred : 1; // is this the preferred mode for the device?
+};
+
+struct _E_Output_Screen
+{
+ char *id; // string id which is "name/edid";
+ struct {
+ char *screen; // name of the screen device attached
+ char *name; // name of the output itself
+ char *edid; // full edid data
+ Eina_Bool connected : 1; // some screen is plugged in or not
+ Eina_List *modes; // available screen modes here
+ struct {
+ int w, h; // physical width and height in mm
+ } size;
+ } info;
+ struct {
+ Eina_Rectangle geom; // the geometry that is set (as a result)
+ E_Output_Mode mode; // screen res/refresh to use
+ int rotation; // 0, 90, 180, 270
+ int priority; // larger num == more important
+ Eina_Bool enabled : 1; // should this monitor be enabled?
+ Eina_Bool configured : 1; // has screen been configured by e?
+ } config;
+ Eina_List *planes;
+ int plane_count;
+ E_Zone *zone;
+};
+
+extern E_API E_Drm_Output *e_drm_output;
+extern E_API int E_EVENT_SCREEN_CHANGE;
+extern E_API int E_EVENT_RANDR_CHANGE; // x randr
+
+EINTERN Eina_Bool e_drm_output_init(void);
+EINTERN int e_drm_output_shutdown(void);
+E_API void e_drm_output_config_apply(void);
+E_API void e_drm_output_screeninfo_update(void);
+E_API void e_drm_output_screen_refresh_queue(Eina_Bool lid_event);
+E_API void e_drm_output_screens_setup(int rw, int rh);
+
+#endif
+#endif
MOD_LIBS = @e_libs@ @dlopen_libs@
-include src/modules/Makefile_wl_drm.mk
+#include src/modules/Makefile_wl_drm.mk
include src/modules/Makefile_wl_desktop_shell.mk
+++ /dev/null
-if USE_MODULE_WL_DRM
-wl_drmdir = $(MDIR)/wl_drm
-
-wl_drmpkgdir = $(MDIR)/wl_drm/$(MODULE_ARCH)
-wl_drmpkg_LTLIBRARIES = src/modules/wl_drm/module.la
-
-src_modules_wl_drm_module_la_DEPENDENCIES = $(MDEPENDENCIES)
-src_modules_wl_drm_module_la_CPPFLAGS = $(MOD_CPPFLAGS) @WL_DRM_CFLAGS@ @WAYLAND_CFLAGS@
-src_modules_wl_drm_module_la_LIBADD = $(LIBS) @WL_DRM_LIBS@ @WAYLAND_LIBS@
-src_modules_wl_drm_module_la_LDFLAGS = $(MOD_LDFLAGS)
-src_modules_wl_drm_module_la_SOURCES = src/modules/wl_drm/e_mod_main.c
-
-PHONIES += wl_drm install-wl_drm
-wl_drm: $(wl_drmpkg_LTLIBRARIES) $(wl_drm_DATA)
-install-wl_drm: install-wl_drmpkgLTLIBRARIES
-endif
+++ /dev/null
-#include "e.h"
-#include <Ecore_Drm.h>
-
-E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Drm" };
-
-static Eina_List *event_handlers = NULL;
-static Eina_Bool session_state = EINA_FALSE;
-
-static Eina_Bool dont_set_ecore_drm_keymap = EINA_FALSE;
-static Eina_Bool dont_use_xkb_cache = EINA_FALSE;
-
-static Eina_Bool
-_e_mod_drm_cb_activate(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
-{
- Ecore_Drm_Event_Activate *e;
-
- if (!(e = event)) goto end;
-
- if (e->active)
- {
- E_Client *ec;
-
- if (session_state) goto end;
- session_state = EINA_TRUE;
-
- ecore_evas_show(e_comp->ee);
- E_CLIENT_FOREACH(ec)
- {
- if (ec->visible && (!ec->input_only))
- e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
- }
- e_comp_render_queue();
- e_comp_shape_queue_block(0);
- ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
- }
- else
- {
- session_state = EINA_FALSE;
- ecore_evas_hide(e_comp->ee);
- edje_file_cache_flush();
- edje_collection_cache_flush();
- evas_image_cache_flush(e_comp->evas);
- evas_font_cache_flush(e_comp->evas);
- evas_render_dump(e_comp->evas);
-
- e_comp_render_queue();
- e_comp_shape_queue_block(1);
- ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
- }
-
-end:
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_mod_drm_cb_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
-{
- const Eina_List *l;
- E_Randr2_Screen *screen;
- Ecore_Drm_Event_Output *e;
-
- if (!(e = event)) goto end;
-
- DBG("WL_DRM OUTPUT CHANGE");
-
- EINA_LIST_FOREACH(e_randr2->screens, l, screen)
- {
- if ((!strcmp(screen->info.name, e->name)) &&
- (!strcmp(screen->info.screen, e->model)))
- {
- if (e->plug)
- {
- if (!e_comp_wl_output_init(screen->id, e->make, e->model,
- e->x, e->y, e->w, e->h,
- e->phys_width, e->phys_height,
- e->refresh, e->subpixel_order,
- e->transform))
- {
- ERR("Could not setup new output: %s", screen->id);
- }
- }
- else
- e_comp_wl_output_remove(screen->id);
-
- break;
- }
- }
-
- /* previous calculation of e_scale gave unsuitable value because
- * there were no sufficient information to calculate dpi.
- * so it's considerable to re-calculate e_scale with output geometry.
- */
- e_scale_manual_update(((e->w * 254 / e->phys_width) + 5) / 10);
-
-end:
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_mod_drm_cb_input_device_add(void *data, int type, void *event)
-{
- Ecore_Drm_Event_Input_Device_Add *e;
- E_Comp *comp = data;
-
- if (!(e = event)) goto end;
-
- if (e->caps & EVDEV_SEAT_POINTER)
- {
- if (comp->wl_comp_data->ptr.num_devices == 0)
- {
- e_pointer_object_set(comp->pointer, NULL, 0, 0);
- e_comp_wl_input_pointer_enabled_set(EINA_TRUE);
- }
- comp->wl_comp_data->ptr.num_devices++;
- }
- if (e->caps & EVDEV_SEAT_KEYBOARD)
- {
- comp->wl_comp_data->kbd.num_devices++;
- e_comp_wl_input_keyboard_enabled_set(EINA_TRUE);
- }
- if (e->caps & EVDEV_SEAT_TOUCH)
- {
- e_comp_wl_input_touch_enabled_set(EINA_TRUE);
- comp->wl_comp_data->touch.num_devices++;
- }
-
-end:
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_mod_drm_cb_input_device_del(void *data, int type, void *event)
-{
- Ecore_Drm_Event_Input_Device_Del *e;
- E_Comp *comp = data;
-
- if (!(e = event)) goto end;
-
- if (e->caps & EVDEV_SEAT_POINTER)
- {
- comp->wl_comp_data->ptr.num_devices--;
- if (comp->wl_comp_data->ptr.num_devices == 0)
- {
- e_comp_wl_input_pointer_enabled_set(EINA_FALSE);
- e_pointer_object_set(comp->pointer, NULL, 0, 0);
- e_pointer_hide(e_comp->pointer);
- }
- }
-
-end:
- if (!e_randr2_cfg->ignore_hotplug_events)
- e_randr2_screen_refresh_queue(EINA_TRUE);
-
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static void
-_e_mod_drm_cb_ee_resize(Ecore_Evas *ee EINA_UNUSED)
-{
- e_comp_canvas_update();
-}
-
-static Ecore_Drm_Output_Mode *
-_e_mod_drm_mode_screen_find(E_Randr2_Screen *s, Ecore_Drm_Output *output)
-{
- Ecore_Drm_Output_Mode *mode, *m = NULL;
- const Eina_List *l;
- int diff, distance = 0x7fffffff;
-
- EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), l, mode)
- {
- diff = (100 * abs(s->config.mode.w - mode->width)) +
- (100 * abs(s->config.mode.h - mode->height)) +
- fabs((100 * s->config.mode.refresh) - (100 * mode->refresh));
- if (diff < distance)
- {
- m = mode;
- distance = diff;
- }
- }
-
- return m;
-}
-
-static Eina_Bool
-_e_mod_drm_output_exists(Ecore_Drm_Output *output, unsigned int crtc)
-{
- /* find out if this output can go into the 'possibles' */
- return ecore_drm_output_possible_crtc_get(output, crtc);
-}
-
-static char *
-_e_mod_drm_output_screen_get(Ecore_Drm_Output *output)
-{
- const char *model;
-
- model = ecore_drm_output_model_get(output);
- if (!model) return NULL;
-
- return strdup(model);
-}
-
-static E_Randr2_Screen *
-_info_unconf_primary_find(E_Randr2 *r)
-{
- Eina_List *l;
- E_Randr2_Screen *s, *s_primary = NULL;
- int priority = 0;
-
- EINA_LIST_FOREACH(r->screens, l, s)
- {
- if (!((s->config.enabled) &&
- (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
- (s->config.geom.w > 0) && (s->config.geom.h > 0)))
- continue;
- if (s->config.priority > priority)
- {
- s_primary = s;
- priority = s->config.priority;
- }
- }
-
- return s_primary;
-}
-
-static E_Randr2_Screen *
-_info_unconf_left_find(E_Randr2 *r)
-{
- Eina_List *l;
- E_Randr2_Screen *s, *s_left = NULL;
- int left_x = 0x7fffffff;
- int left_size = 0;
-
- EINA_LIST_FOREACH(r->screens, l, s)
- {
- if (!((s->config.enabled) &&
- (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
- (s->config.geom.w > 0) && (s->config.geom.h > 0)))
- continue;
- if ((s->config.geom.x <= left_x) &&
- ((s->config.geom.w * s->config.geom.h) > left_size))
- {
- left_size = s->config.geom.w * s->config.geom.h;
- left_x = s->config.geom.x;
- s_left = s;
- }
- }
- return s_left;
-}
-
-static E_Randr2_Screen *
-_info_unconf_closest_find(E_Randr2 *r, E_Randr2_Screen *s2, Eina_Bool configured)
-{
- Eina_List *l;
- E_Randr2_Screen *s, *s_sel = NULL;
- int dist = 0x7fffffff;
- int dx, dy;
-
- EINA_LIST_FOREACH(r->screens, l, s)
- {
- if (s == s2) continue;
- if (!((s->config.enabled) &&
- (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
- (s->config.geom.w > 0) && (s->config.geom.h > 0)))
- continue;
- if ((!configured) &&
- (s->config.relative.mode != E_RANDR2_RELATIVE_UNKNOWN))
- continue;
- else if ((configured) &&
- (s->config.relative.mode == E_RANDR2_RELATIVE_UNKNOWN))
- continue;
- dx = (s->config.geom.x + (s->config.geom.w / 2)) -
- (s2->config.geom.x + (s2->config.geom.w / 2));
- dy = (s->config.geom.y + (s->config.geom.h / 2)) -
- (s2->config.geom.y + (s2->config.geom.h / 2));
- dx = sqrt((dx * dx) + (dy * dy));
- if (dx < dist)
- {
- s_sel = s;
- dist = dx;
- }
- }
- return s_sel;
-}
-
-static void
-_e_mod_drm_relative_fixup(E_Randr2 *r)
-{
- E_Randr2_Screen *s, *s2;
- int d, dx, dy;
-
- s = _info_unconf_primary_find(r);
- if (s)
- s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
- else
- {
- s = _info_unconf_left_find(r);
- if (!s) return;
- s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
- }
-
- for (;;)
- {
- // find the next screen that is closest to the last one we configured
- /// that is still not configured yet
- s = _info_unconf_closest_find(r, s, EINA_FALSE);
- if (!s) break;
- s2 = _info_unconf_closest_find(r, s, EINA_TRUE);
- // fix up s->config.relative.mode, s->config.relative.to and
- // s->config.relative.align to match (as closely as possible)
- // the geometry given - config s relative to s2
- if (!s2) s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
- else
- {
- s->config.relative.to = strdup(s2->id);
- s->config.relative.align = 0.0;
- s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
- if ((s->config.geom.x + s->config.geom.w) <=
- s2->config.geom.x)
- {
- s->config.relative.mode = E_RANDR2_RELATIVE_TO_LEFT;
- d = s->config.geom.h - s2->config.geom.h;
- dy = s2->config.geom.y - s->config.geom.y;
- if (d != 0)
- s->config.relative.align = ((double)dy) / ((double)d);
- }
- else if (s->config.geom.x >=
- (s2->config.geom.x + s2->config.geom.w))
- {
- s->config.relative.mode = E_RANDR2_RELATIVE_TO_RIGHT;
- d = s->config.geom.h - s2->config.geom.h;
- dy = s2->config.geom.y - s->config.geom.y;
- if (d != 0)
- s->config.relative.align = ((double)dy) / ((double)d);
- }
- else if ((s->config.geom.y + s->config.geom.h) <=
- s2->config.geom.y)
- {
- s->config.relative.mode = E_RANDR2_RELATIVE_TO_ABOVE;
- d = s->config.geom.w - s2->config.geom.w;
- dx = s2->config.geom.x - s->config.geom.x;
- if (d != 0)
- s->config.relative.align = ((double)dx) / ((double)d);
- }
- else if (s->config.geom.y >=
- (s2->config.geom.y + s2->config.geom.h))
- {
- s->config.relative.mode = E_RANDR2_RELATIVE_TO_BELOW;
- d = s->config.geom.w - s2->config.geom.w;
- dx = s2->config.geom.x - s->config.geom.x;
- if (d != 0)
- s->config.relative.align = ((double)dx) / ((double)d);
- }
- else if ((s->config.geom.x == s2->config.geom.x) &&
- (s->config.geom.y == s2->config.geom.y) &&
- (s->config.geom.w == s2->config.geom.w) &&
- (s->config.geom.h == s2->config.geom.h))
- {
- s->config.relative.mode = E_RANDR2_RELATIVE_CLONE;
- }
- if (s->config.relative.align < 0.0)
- s->config.relative.align = 0.0;
- else if (s->config.relative.align > 1.0)
- s->config.relative.align = 1.0;
- }
- }
-}
-
-static E_Randr2 *
-_drm_randr_create(void)
-{
- Ecore_Drm_Device *dev;
- Ecore_Drm_Output *output;
- const Eina_List *l, *ll;
- E_Randr2 *r = NULL;
- 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", "UNKNOWN"
- };
- E_Randr2_Connector rtype[] =
- {
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_DVI,
- E_RANDR2_CONNECTOR_DVI,
- E_RANDR2_CONNECTOR_DVI,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_DISPLAY_PORT,
- E_RANDR2_CONNECTOR_HDMI_A,
- E_RANDR2_CONNECTOR_HDMI_B,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_DISPLAY_PORT,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_UNDEFINED,
- E_RANDR2_CONNECTOR_UNDEFINED,
- };
- unsigned int type;
-
- printf("DRM RRR: ................. info get!\n");
-
- r = E_NEW(E_Randr2, 1);
- if (!r) return NULL;
-
- EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
- {
- EINA_LIST_FOREACH(dev->outputs, ll, output)
- {
- E_Randr2_Screen *s;
- E_Config_Randr2_Screen *cs;
- const Eina_List *m;
- Ecore_Drm_Output_Mode *omode;
- // size_t n, e = 0;
- unsigned int j;
- int priority;
- Eina_Bool ok = EINA_FALSE;
- Eina_Bool possible = EINA_FALSE;
- int len = 0;
-
- s = E_NEW(E_Randr2_Screen, 1);
- if (!s) continue;
-
- s->info.name = ecore_drm_output_name_get(output);
- printf("DRM RRR: .... out %s\n", s->info.name);
-
- s->info.connected = ecore_drm_output_connected_get(output);
- printf("DRM RRR: ...... connected %i\n", s->info.connected);
-
- s->info.screen = _e_mod_drm_output_screen_get(output);
-
- s->info.edid = ecore_drm_output_edid_get(output);
- if (s->info.edid)
- s->id = malloc(strlen(s->info.name) + 1 + strlen(s->info.edid) + 1);
- else
- s->id = malloc(strlen(s->info.name) + 1 + 1);
- if (!s->id)
- {
- free(s->info.screen);
- free(s->info.edid);
- free(s);
- continue;
- }
- len = strlen(s->info.name);
- strncpy(s->id, s->info.name, len + 1);
- strncat(s->id, "/", 1);
- if (s->info.edid) strncat(s->id, s->info.edid, strlen(s->info.edid));
-
- printf("DRM RRR: Created Screen: %s\n", s->id);
-
- type = MIN(ecore_drm_output_connector_type_get(output),
- EINA_C_ARRAY_LENGTH(conn_types) - 1);
- s->info.connector = rtype[type];
- s->info.is_lid = ((type == DRM_MODE_CONNECTOR_LVDS) ||
- (type == DRM_MODE_CONNECTOR_eDP));
- s->info.lid_closed = (s->info.is_lid && e_acpi_lid_is_closed());
- printf("DRM RRR: ...... lid_closed = %i (%i && %i)\n",
- s->info.lid_closed, s->info.is_lid, e_acpi_lid_is_closed());
-
- s->info.backlight = ecore_drm_output_backlight_get(output);
-
- ecore_drm_output_physical_size_get(output, &s->info.size.w,
- &s->info.size.h);
-
- EINA_LIST_FOREACH(ecore_drm_output_modes_get(output), m, omode)
- {
- E_Randr2_Mode *rmode;
-
- rmode = malloc(sizeof(E_Randr2_Mode));
- if (!rmode) continue;
-
- rmode->w = omode->width;
- rmode->h = omode->height;
- rmode->refresh = omode->refresh;
- rmode->preferred = (omode->flags & DRM_MODE_TYPE_PREFERRED);
-
- s->info.modes = eina_list_append(s->info.modes, rmode);
- }
-
- cs = NULL;
- priority = 0;
- if (e_randr2_cfg)
- cs = e_randr2_config_screen_find(s, e_randr2_cfg);
- if (cs)
- priority = cs->priority;
- else if (ecore_drm_output_primary_get(dev) == output)
- priority = 100;
- s->config.priority = priority;
-
- for (j = 0; j < dev->crtc_count; j++)
- {
- if (dev->crtcs[j] == ecore_drm_output_crtc_id_get(output))
- {
- ok = EINA_TRUE;
- break;
- }
- }
-
- if (!ok)
- {
- /* get possible crtcs, compare to output_crtc_id_get */
- for (j = 0; j < dev->crtc_count; j++)
- {
- if (_e_mod_drm_output_exists(output, dev->crtcs[j]))
- {
- ok = EINA_TRUE;
- possible = EINA_TRUE;
- break;
- }
- }
- }
-
- if (ok)
- {
- if (!possible)
- {
- unsigned int refresh;
-
- ecore_drm_output_position_get(output, &s->config.geom.x,
- &s->config.geom.y);
- ecore_drm_output_crtc_size_get(output, &s->config.geom.w,
- &s->config.geom.h);
-
- ecore_drm_output_current_resolution_get(output,
- &s->config.mode.w,
- &s->config.mode.h,
- &refresh);
- s->config.mode.refresh = refresh;
- s->config.enabled =
- ((s->config.mode.w != 0) && (s->config.mode.h != 0));
-
- printf("DRM RRR: '%s' %i %i %ix%i\n", s->info.name,
- s->config.geom.x, s->config.geom.y,
- s->config.geom.w, s->config.geom.h);
- }
-
- /* TODO: are rotations possible ?? */
- }
-
- r->screens = eina_list_append(r->screens, s);
- }
- }
-
- _e_mod_drm_relative_fixup(r);
-
- return r;
-}
-
-static Eina_Bool
-_drm_randr_available(void)
-{
- return EINA_TRUE;
-}
-
-static void
-_drm_randr_stub(void)
-{}
-
-static void
-_drm_randr_apply(void)
-{
- Ecore_Drm_Device *dev;
- Ecore_Drm_Output *out;
- E_Randr2_Screen *s;
- const Eina_List *l, *ll;
- int nw, nh, pw, ph, ww, hh;
- int minw, minh, maxw, maxh;
- int top_priority = 0;
-
- /* TODO: what the actual fuck */
-
- nw = e_randr2->w;
- nh = e_randr2->h;
- EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
- {
- ecore_drm_screen_size_range_get(dev, &minw, &minh, &maxw, &maxh);
- printf("DRM RRR: size range: %ix%i -> %ix%i\n", minw, minh, maxw, maxh);
-
- ecore_drm_outputs_geometry_get(dev, NULL, NULL, &pw, &ph);
- if (nw > maxw) nw = maxw;
- if (nh > maxh) nh = maxh;
- if (nw < minw) nw = minw;
- if (nh < minh) nh = minh;
- ww = nw;
- hh = nh;
- if (nw < pw) ww = pw;
- if (nh < ph) hh = ph;
-
- printf("DRM RRR: set vsize: %ix%i\n", ww, hh);
-
- EINA_LIST_FOREACH(e_randr2->screens, ll, s)
- {
- //int orient; // FIXME
- Ecore_Drm_Output_Mode *mode = NULL;
-
- printf("DRM RRR: find output for '%s'\n", s->info.name);
-
- out = ecore_drm_device_output_name_find(dev, s->info.name);
- if (!out) continue;
-
- if (s->config.configured)
- {
- printf("\tDRM RRR: configured by E\n");
-
- if (s->config.enabled)
- {
- printf("\tDRM RRR: Enabled\n");
- mode = _e_mod_drm_mode_screen_find(s, out);
- }
- else
- {
- printf("\tDRM RRR: Disabled\n");
- }
-
- if (s->config.priority > top_priority)
- top_priority = s->config.priority;
-
- printf("\tDRM RRR: Priority: %d\n", s->config.priority);
-
- printf("\tDRM RRR: Geom: %d %d %d %d\n",
- s->config.geom.x, s->config.geom.y,
- s->config.geom.w, s->config.geom.h);
-
- if (mode)
- {
- printf("\tDRM RRR: Found Valid Drm Mode\n");
- printf("\t\tDRM RRR: %dx%d\n", mode->width, mode->height);
- }
- else
- printf("\tDRM RRR: No Valid Drm Mode Found\n");
-
- // FIXME
- //if (s->config.rotation == 0)
- // orient = (1 << 0);
- //else if (s->config.rotation == 90)
- // orient = (1 << 1);
- //else if (s->config.rotation == 180)
- // orient = (1 << 2);
- //else if (s->config.rotation == 270)
- // orient = (1 << 3);
-
- ecore_drm_output_mode_set(out, mode,
- s->config.geom.x, s->config.geom.y);
- if (s->config.priority == top_priority)
- ecore_drm_output_primary_set(out);
-
- if (s->config.enabled)
- ecore_drm_output_enable(out);
- else
- ecore_drm_output_disable(out);
-
- printf("\tDRM RRR: Mode\n");
- printf("\t\tDRM RRR: Geom: %d %d\n",
- s->config.mode.w, s->config.mode.h);
- printf("\t\tDRM RRR: Refresh: %f\n", s->config.mode.refresh);
- printf("\t\tDRM RRR: Preferred: %d\n",
- s->config.mode.preferred);
-
- printf("\tDRM RRR: Rotation: %d\n", s->config.rotation);
-
- printf("\tDRM RRR: Relative Mode: %d\n",
- s->config.relative.mode);
- printf("\tDRM RRR: Relative To: %s\n",
- s->config.relative.to);
- printf("\tDRM RRR: Align: %f\n", s->config.relative.align);
- }
- }
- }
-}
-
-static void
-_drm_dpms(int set)
-{
- Ecore_Drm_Device *dev;
- Ecore_Drm_Output *out;
- E_Randr2_Screen *s;
- const Eina_List *l, *ll;
-
- EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
- {
- EINA_LIST_FOREACH(e_randr2->screens, ll, s)
- {
- out = ecore_drm_device_output_name_find(dev, s->info.name);
- if (!out) continue;
-
- if ((!s->config.configured) || s->config.enabled)
- ecore_drm_output_dpms_set(out, set);
- }
- }
-}
-
-static E_Comp_Screen_Iface drmiface =
-{
- .available = _drm_randr_available,
- .init = _drm_randr_stub,
- .shutdown = _drm_randr_stub,
- .create = _drm_randr_create,
- .apply = _drm_randr_apply,
- .dpms = _drm_dpms,
-};
-
-static void
-_drm_read_pixels(E_Comp_Wl_Output *output, void *pixels)
-{
- Ecore_Drm_Device *dev;
- Ecore_Drm_Fb *fb;
- const Eina_List *drm_devs, *l;
- int i = 0, bstride;
- unsigned char *s, *d = pixels;
-
- drm_devs = ecore_drm_devices_get();
- EINA_LIST_FOREACH(drm_devs, l, dev)
- {
- fb = dev->next;
- if (!fb) fb = dev->current;
- if (fb) break;
- }
-
- if (!fb) return;
-
- bstride = output->w * sizeof(int);
-
- for (i = output->y; i < output->y + output->h; i++)
- {
- s = fb->mmap;
- s += (fb->stride * i) + (output->x * sizeof(int));
- memcpy(d, s, (output->w * sizeof(int)));
- d += bstride;
- }
-}
-
-E_API void
-_e_mod_drm_keymap_set(struct xkb_context **ctx, struct xkb_keymap **map)
-{
- char *keymap_path = NULL;
- struct xkb_context *context;
- struct xkb_keymap *keymap;
- struct xkb_rule_names names = {0,};
-
- TRACE_INPUT_BEGIN(_e_mod_drm_keymap_set);
-
- context = xkb_context_new(0);
- EINA_SAFETY_ON_NULL_RETURN(context);
-
- /* assemble xkb_rule_names so we can fetch keymap */
- memset(&names, 0, sizeof(names));
- names.rules = strdup("evdev");
- names.model = strdup("pc105");
- names.layout = strdup("us");
-
- keymap = e_comp_wl_input_keymap_compile(context, names, &keymap_path);
- eina_stringshare_del(keymap_path);
- EINA_SAFETY_ON_NULL_GOTO(keymap, cleanup);
-
- *ctx = context;
- *map = keymap;
-
- if (dont_set_ecore_drm_keymap == EINA_FALSE)
- {
- ecore_drm_device_keyboard_cached_context_set(*ctx);
- ecore_drm_device_keyboard_cached_keymap_set(*map);
- }
-
-cleanup:
- free((char *)names.rules);
- free((char *)names.model);
- free((char *)names.layout);
-
- TRACE_INPUT_END();
-}
-
-E_API void *
-e_modapi_init(E_Module *m)
-{
- E_Comp *comp;
- int w = 0, h = 0, scr_w = 0, scr_h = 0;
- const char *env_w, *env_h;
- struct xkb_context *ctx = NULL;
- struct xkb_keymap *map = NULL;
- char buf[1024];
-
- e_main_ts("\twl_drm Init Begin");
-
- dont_set_ecore_drm_keymap = getenv("NO_ECORE_DRM_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
- dont_use_xkb_cache = getenv("NO_KEYMAP_CACHE") ? EINA_TRUE : EINA_FALSE;
-
- TRACE_DS_BEGIN(WL_DRM:INIT);
-
- if (!(comp = e_comp))
- {
- comp = e_comp_new();
- if (!comp)
- {
- TRACE_DS_END();
- EINA_SAFETY_ON_NULL_RETURN_VAL(comp, NULL);
- }
-
- comp->comp_type = E_PIXMAP_TYPE_WL;
- }
-
- /* set gl available if we have ecore_evas support */
- if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_DRM))
- e_comp_gl_set(EINA_TRUE);
-
- env_w = getenv("E_SCREEN_WIDTH");
- if (env_w)
- {
- snprintf(buf, sizeof(buf), "%s", env_w);
- scr_w = atoi(buf);
- }
-
- env_h = getenv("E_SCREEN_HEIGHT");
- if (env_h)
- {
- snprintf(buf, sizeof(buf), "%s", env_h);
- scr_h = atoi(buf);
- }
-
- if (scr_w <= 0) scr_w = 1;
- if (scr_h <= 0) scr_h = 1;
-
- DBG("GL available:%d config engine:%d screen size:%dx%d",
- e_comp_gl_get(), e_comp_config_get()->engine, scr_w, scr_h);
-
- if (e_config->xkb.use_cache && !dont_use_xkb_cache)
- {
- e_main_ts("\tDRM Keymap Init");
- _e_mod_drm_keymap_set(&ctx, &map);
- e_main_ts("\tDRM Keymap Init Done");
- }
-
- if ((e_comp_gl_get()) &&
- (e_comp_config_get()->engine == E_COMP_ENGINE_GL))
- {
- e_main_ts("\tEE_GL_DRM New");
- comp->ee = ecore_evas_gl_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
- snprintf(buf, sizeof(buf), "\tEE_GL_DRM New Done %p %dx%d", comp->ee, scr_w, scr_h);
- e_main_ts(buf);
-
- if (!comp->ee)
- e_comp_gl_set(EINA_FALSE);
- else
- {
- Evas_GL *evasgl = NULL;
- Evas_GL_API *glapi = NULL;
-
- e_main_ts("\tEvas_GL New");
- evasgl = evas_gl_new(ecore_evas_get(comp->ee));
- if (evasgl)
- {
- glapi = evas_gl_api_get(evasgl);
- if (!((glapi) && (glapi->evasglBindWaylandDisplay)))
- {
- e_comp_gl_set(EINA_FALSE);
- ecore_evas_free(comp->ee);
- comp->ee = NULL;
- e_main_ts("\tEvas_GL New Failed 1");
- }
- else
- {
- e_main_ts("\tEvas_GL New Done");
- }
- }
- else
- {
- e_comp_gl_set(EINA_FALSE);
- ecore_evas_free(comp->ee);
- comp->ee = NULL;
- e_main_ts("\tEvas_GL New Failed 2");
- }
- evas_gl_free(evasgl);
- }
- }
-
- /* fallback to framebuffer drm (non-accel) */
- if (!comp->ee)
- {
- e_main_ts("\tEE_DRM New");
- comp->ee = ecore_evas_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
- snprintf(buf, sizeof(buf), "\tEE_DRM New Done %p %dx%d", comp->ee, scr_w, scr_h);
- e_main_ts(buf);
- }
-
- if (!comp->ee)
- {
- fprintf(stderr, "Could not create ecore_evas_drm canvas");
- TRACE_DS_END();
- return NULL;
- }
-
- ecore_evas_data_set(e_comp->ee, "comp", e_comp);
-
- /* get the current screen geometry */
- ecore_evas_screen_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
-
- /* resize the canvas */
- if (!((scr_w == w) && (scr_h == h)))
- {
- snprintf(buf, sizeof(buf), "\tEE Resize %dx%d -> %dx%d", scr_w, scr_h, w, h);
- e_main_ts(buf);
-
- ecore_evas_resize(comp->ee, w, h);
-
- e_main_ts("\tEE Resize Done");
- }
-
- ecore_evas_callback_resize_set(e_comp->ee, _e_mod_drm_cb_ee_resize);
-
- e_comp->screen = &drmiface;
-
- e_main_ts("\tE_Comp_Wl Init");
- if (!e_comp_wl_init())
- {
- TRACE_DS_END();
- return NULL;
- }
- e_main_ts("\tE_Comp_Wl Init Done");
-
- e_main_ts("\tE_Comp_Canvas Init");
- if (!e_comp_canvas_init(w, h))
- {
- TRACE_DS_END();
- return NULL;
- }
- e_main_ts("\tE_Comp_Canvas Init Done");
-
- e_comp_wl->screenshooter.read_pixels = _drm_read_pixels;
-
- ecore_evas_pointer_xy_get(e_comp->ee,
- &e_comp_wl->ptr.x,
- &e_comp_wl->ptr.y);
-
- evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
-
- /* comp->pointer = */
- /* e_pointer_window_new(ecore_evas_window_get(comp->ee), 1); */
- e_main_ts("\tE_Pointer New");
- if ((comp->pointer = e_pointer_canvas_new(comp->ee, EINA_TRUE)))
- {
- comp->pointer->color = EINA_TRUE;
- e_pointer_hide(comp->pointer);
- }
- e_main_ts("\tE_Pointer New Done");
-
- /* FIXME: We need a way to trap for user changing the keymap inside of E
- * without the event coming from X11 */
-
- /* FIXME: We should make a decision here ...
- *
- * Fetch the keymap from drm, OR set this to what the E config is....
- */
-
- /* FIXME: This is just for testing at the moment....
- * happens to jive with what drm does */
- e_main_ts("\tE_Comp_WL Keymap Init");
- e_comp_wl_input_keymap_set("evdev", "pc105", "us", ctx, map);
- e_main_ts("\tE_Comp_WL Keymap Init Done");
-
- E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_ACTIVATE, _e_mod_drm_cb_activate, comp);
- E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_OUTPUT, _e_mod_drm_cb_output, comp);
- E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_ADD, _e_mod_drm_cb_input_device_add, comp);
- E_LIST_HANDLER_APPEND(event_handlers, ECORE_DRM_EVENT_INPUT_DEVICE_DEL, _e_mod_drm_cb_input_device_del, comp);
-
- TRACE_DS_END();
-
- return m;
-}
-
-E_API int
-e_modapi_shutdown(E_Module *m EINA_UNUSED)
-{
- /* shutdown ecore_drm */
- /* ecore_drm_shutdown(); */
-
- dont_set_ecore_drm_keymap = EINA_FALSE;
- dont_use_xkb_cache = EINA_FALSE;
- E_FREE_LIST(event_handlers, ecore_event_handler_del);
-
- return 1;
-}
-
-E_API int
-e_modapi_save(E_Module *m EINA_UNUSED)
-{
- // do nothing
- return 1;
-}