ecore_drm2: Start rework of Ecore_Drm2 library
This removes all old code and starts fresh with just simple ecore_drm2_init & ecore_drm2_shutdown functions
This commit is contained in:
parent
bcd0ae0b83
commit
1e6df64525
File diff suppressed because it is too large
Load Diff
|
@ -1,143 +1,11 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
/* local variables */
|
||||
static int _ecore_drm2_init_count = 0;
|
||||
static void *drm_lib = NULL;
|
||||
|
||||
/* external variables */
|
||||
int _ecore_drm2_log_dom = -1;
|
||||
|
||||
int (*sym_drmHandleEvent)(int fd, drmEventContext *evctx) = NULL;
|
||||
void *(*sym_drmGetVersion)(int fd) = NULL;
|
||||
void (*sym_drmFreeVersion)(void *drmver) = NULL;
|
||||
void *(*sym_drmModeGetProperty)(int fd, uint32_t propertyId) = NULL;
|
||||
void (*sym_drmModeFreeProperty)(drmModePropertyPtr ptr) = NULL;
|
||||
void *(*sym_drmModeGetPropertyBlob)(int fd, uint32_t blob_id) = NULL;
|
||||
void (*sym_drmModeFreePropertyBlob)(drmModePropertyBlobPtr ptr) = NULL;
|
||||
int (*sym_drmModeDestroyPropertyBlob)(int fd, uint32_t id) = NULL;
|
||||
int (*sym_drmIoctl)(int fd, unsigned long request, void *arg) = NULL;
|
||||
void *(*sym_drmModeObjectGetProperties)(int fd, uint32_t object_id, uint32_t object_type) = NULL;
|
||||
void (*sym_drmModeFreeObjectProperties)(drmModeObjectPropertiesPtr ptr) = NULL;
|
||||
int (*sym_drmModeCreatePropertyBlob)(int fd, const void *data, size_t size, uint32_t *id) = NULL;
|
||||
void *(*sym_drmModeAtomicAlloc)(void) = NULL;
|
||||
void (*sym_drmModeAtomicFree)(drmModeAtomicReqPtr req) = NULL;
|
||||
int (*sym_drmModeAtomicAddProperty)(drmModeAtomicReqPtr req, uint32_t object_id, uint32_t property_id, uint64_t value) = NULL;
|
||||
int (*sym_drmModeAtomicCommit)(int fd, drmModeAtomicReqPtr req, uint32_t flags, void *user_data) = NULL;
|
||||
void (*sym_drmModeAtomicSetCursor)(drmModeAtomicReqPtr req, int cursor) = NULL;
|
||||
int (*sym_drmModeAtomicMerge)(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment);
|
||||
void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id) = NULL;
|
||||
void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr) = NULL;
|
||||
void *(*sym_drmModeGetCrtc)(int fd, uint32_t crtcId) = NULL;
|
||||
void (*sym_drmModeFreeCrtc)(drmModeCrtcPtr ptr) = NULL;
|
||||
int (*sym_drmModeSetCrtc)(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode) = NULL;
|
||||
void *(*sym_drmModeGetResources)(int fd) = NULL;
|
||||
void (*sym_drmModeFreeResources)(drmModeResPtr ptr) = NULL;
|
||||
void *(*sym_drmModeGetConnector)(int fd, uint32_t connectorId) = NULL;
|
||||
void (*sym_drmModeFreeConnector)(drmModeConnectorPtr ptr) = NULL;
|
||||
int (*sym_drmModeConnectorSetProperty)(int fd, uint32_t connector_id, uint32_t property_id, uint64_t value) = NULL;
|
||||
int (*sym_drmGetCap)(int fd, uint64_t capability, uint64_t *value) = NULL;
|
||||
int (*sym_drmSetClientCap)(int fd, uint64_t capability, uint64_t value) = NULL;
|
||||
void *(*sym_drmModeGetPlaneResources)(int fd) = NULL;
|
||||
void (*sym_drmModeFreePlaneResources)(drmModePlaneResPtr ptr) = NULL;
|
||||
void *(*sym_drmModeGetPlane)(int fd, uint32_t plane_id) = NULL;
|
||||
void (*sym_drmModeFreePlane)(drmModePlanePtr ptr) = NULL;
|
||||
int (*sym_drmModeAddFB)(int fd, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id) = NULL;
|
||||
int (*sym_drmModeAddFB2)(int fd, uint32_t width, uint32_t height, uint32_t pixel_format, uint32_t bo_handles[4], uint32_t pitches[4], uint32_t offsets[4], uint32_t *buf_id, uint32_t flags) = NULL;
|
||||
int (*sym_drmModeRmFB)(int fd, uint32_t bufferId) = NULL;
|
||||
int (*sym_drmModePageFlip)(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data) = NULL;
|
||||
int (*sym_drmModeDirtyFB)(int fd, uint32_t bufferId, drmModeClipPtr clips, uint32_t num_clips) = NULL;
|
||||
int (*sym_drmModeCrtcSetGamma)(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue) = NULL;
|
||||
int (*sym_drmPrimeFDToHandle)(int fd, int prime_fd, uint32_t *handle) = NULL;
|
||||
int (*sym_drmWaitVBlank)(int fd, drmVBlank *vbl) = NULL;
|
||||
|
||||
EAPI int ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
|
||||
EAPI int ECORE_DRM2_EVENT_ACTIVATE = -1;
|
||||
|
||||
static Eina_Bool
|
||||
_ecore_drm2_link(void)
|
||||
{
|
||||
int i, fail;
|
||||
const char *drm_libs[] =
|
||||
{
|
||||
"libdrm.so.2",
|
||||
"libdrm.so.1",
|
||||
"libdrm.so.0",
|
||||
"libdrm.so",
|
||||
NULL,
|
||||
};
|
||||
|
||||
#define SYM(lib, xx) \
|
||||
do { \
|
||||
sym_ ## xx = dlsym(lib, #xx); \
|
||||
if (!(sym_ ## xx)) { \
|
||||
fail = 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
if (drm_lib) return EINA_TRUE;
|
||||
|
||||
for (i = 0; drm_libs[i]; i++)
|
||||
{
|
||||
drm_lib = dlopen(drm_libs[i], RTLD_LOCAL | RTLD_LAZY);
|
||||
if (!drm_lib) continue;
|
||||
|
||||
fail = 0;
|
||||
|
||||
SYM(drm_lib, drmIoctl);
|
||||
/* SYM(drm_lib, drmClose); */
|
||||
SYM(drm_lib, drmWaitVBlank);
|
||||
SYM(drm_lib, drmHandleEvent);
|
||||
SYM(drm_lib, drmGetVersion);
|
||||
SYM(drm_lib, drmFreeVersion);
|
||||
SYM(drm_lib, drmModeGetProperty);
|
||||
SYM(drm_lib, drmModeFreeProperty);
|
||||
SYM(drm_lib, drmModeGetPropertyBlob);
|
||||
SYM(drm_lib, drmModeFreePropertyBlob);
|
||||
SYM(drm_lib, drmModeDestroyPropertyBlob);
|
||||
SYM(drm_lib, drmModeObjectGetProperties);
|
||||
SYM(drm_lib, drmModeFreeObjectProperties);
|
||||
SYM(drm_lib, drmModeCreatePropertyBlob);
|
||||
SYM(drm_lib, drmModeAtomicAlloc);
|
||||
SYM(drm_lib, drmModeAtomicFree);
|
||||
SYM(drm_lib, drmModeAtomicAddProperty);
|
||||
SYM(drm_lib, drmModeAtomicCommit);
|
||||
SYM(drm_lib, drmModeAtomicSetCursor);
|
||||
SYM(drm_lib, drmModeAtomicMerge);
|
||||
SYM(drm_lib, drmModeGetEncoder);
|
||||
SYM(drm_lib, drmModeFreeEncoder);
|
||||
SYM(drm_lib, drmModeGetCrtc);
|
||||
SYM(drm_lib, drmModeFreeCrtc);
|
||||
SYM(drm_lib, drmModeSetCrtc);
|
||||
SYM(drm_lib, drmModeGetResources);
|
||||
SYM(drm_lib, drmModeFreeResources);
|
||||
SYM(drm_lib, drmModeGetConnector);
|
||||
SYM(drm_lib, drmModeFreeConnector);
|
||||
SYM(drm_lib, drmModeConnectorSetProperty);
|
||||
SYM(drm_lib, drmGetCap);
|
||||
SYM(drm_lib, drmSetClientCap);
|
||||
SYM(drm_lib, drmModeGetPlaneResources);
|
||||
SYM(drm_lib, drmModeFreePlaneResources);
|
||||
SYM(drm_lib, drmModeGetPlane);
|
||||
SYM(drm_lib, drmModeFreePlane);
|
||||
SYM(drm_lib, drmModeAddFB);
|
||||
SYM(drm_lib, drmModeAddFB2);
|
||||
SYM(drm_lib, drmModeRmFB);
|
||||
SYM(drm_lib, drmModePageFlip);
|
||||
SYM(drm_lib, drmModeDirtyFB);
|
||||
SYM(drm_lib, drmModeCrtcSetGamma);
|
||||
SYM(drm_lib, drmPrimeFDToHandle);
|
||||
|
||||
if (fail)
|
||||
{
|
||||
dlclose(drm_lib);
|
||||
drm_lib = NULL;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (!drm_lib) return EINA_FALSE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_init(void)
|
||||
{
|
||||
|
@ -171,16 +39,8 @@ ecore_drm2_init(void)
|
|||
goto log_err;
|
||||
}
|
||||
|
||||
ECORE_DRM2_EVENT_OUTPUT_CHANGED = ecore_event_type_new();
|
||||
ECORE_DRM2_EVENT_ACTIVATE = ecore_event_type_new();
|
||||
|
||||
if (!_ecore_drm2_link()) goto link_err;
|
||||
|
||||
return _ecore_drm2_init_count;
|
||||
|
||||
link_err:
|
||||
eina_log_domain_unregister(_ecore_drm2_log_dom);
|
||||
_ecore_drm2_log_dom = -1;
|
||||
log_err:
|
||||
elput_shutdown();
|
||||
elput_err:
|
||||
|
@ -204,9 +64,6 @@ ecore_drm2_shutdown(void)
|
|||
|
||||
if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count;
|
||||
|
||||
ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
|
||||
ECORE_DRM2_EVENT_ACTIVATE = -1;
|
||||
|
||||
eina_log_domain_unregister(_ecore_drm2_log_dom);
|
||||
_ecore_drm2_log_dom = -1;
|
||||
|
||||
|
@ -217,18 +74,3 @@ ecore_drm2_shutdown(void)
|
|||
|
||||
return _ecore_drm2_init_count;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_event_handle(Ecore_Drm2_Device *dev, Ecore_Drm2_Context *drmctx)
|
||||
{
|
||||
drmEventContext ctx;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, -1);
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
ctx.version = 2;
|
||||
ctx.page_flip_handler = drmctx->page_flip_handler;
|
||||
ctx.vblank_handler = drmctx->vblank_handler;
|
||||
|
||||
return sym_drmHandleEvent(dev->fd, &ctx);
|
||||
}
|
||||
|
|
|
@ -1,933 +0,0 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
#ifndef DRM_CAP_DUMB_PREFERRED_DEPTH
|
||||
# define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
|
||||
#endif
|
||||
|
||||
#ifndef DRM_CAP_DUMB_PREFER_SHADOW
|
||||
# define DRM_CAP_DUMB_PREFER_SHADOW 0x4
|
||||
#endif
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
Eina_Bool _ecore_drm2_use_atomic = EINA_TRUE;
|
||||
|
||||
static Eina_Bool
|
||||
_cb_session_active(void *data, int type EINA_UNUSED, void *event)
|
||||
{
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Device *device;
|
||||
Ecore_Drm2_Output *output;
|
||||
Elput_Event_Session_Active *ev;
|
||||
Ecore_Drm2_Event_Activate *ea;
|
||||
|
||||
ev = event;
|
||||
device = data;
|
||||
|
||||
if (ev->active)
|
||||
EINA_LIST_FOREACH(device->outputs, l, output)
|
||||
ecore_drm2_output_dpms_set(output, DRM_MODE_DPMS_ON);
|
||||
|
||||
ea = calloc(1, sizeof(Ecore_Drm2_Event_Activate));
|
||||
if (!ea) return ECORE_CALLBACK_RENEW;
|
||||
|
||||
ea->active = ev->active;
|
||||
|
||||
ecore_event_add(ECORE_DRM2_EVENT_ACTIVATE, ea, NULL, NULL);
|
||||
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_cb_device_change(void *data, int type EINA_UNUSED, void *event)
|
||||
{
|
||||
Elput_Event_Device_Change *ev = event;
|
||||
Ecore_Drm2_Device *device = data;
|
||||
|
||||
if (ev->type == ELPUT_DEVICE_ADDED)
|
||||
{
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Output *output;
|
||||
Eina_Stringshare *name;
|
||||
|
||||
name = elput_device_output_name_get(ev->device);
|
||||
if (!name)
|
||||
{
|
||||
output = eina_list_data_get(device->outputs);
|
||||
if (output)
|
||||
ecore_drm2_device_calibrate(device,
|
||||
output->w, output->h);
|
||||
}
|
||||
else
|
||||
{
|
||||
EINA_LIST_FOREACH(device->outputs, l, output)
|
||||
{
|
||||
if (eina_streq(output->name, name))
|
||||
{
|
||||
ecore_drm2_device_calibrate(device,
|
||||
output->w, output->h);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_drm2_device_modeset_capable(int fd)
|
||||
{
|
||||
int ret = EINA_TRUE;
|
||||
drmModeRes *res;
|
||||
|
||||
res = sym_drmModeGetResources(fd);
|
||||
if (!res)
|
||||
return EINA_FALSE;
|
||||
|
||||
if (res->count_crtcs <= 0 ||
|
||||
res->count_connectors <= 0 ||
|
||||
res->count_encoders <= 0)
|
||||
ret = EINA_FALSE;
|
||||
|
||||
sym_drmModeFreeResources(res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *
|
||||
_drm2_device_find(Elput_Manager *em, const char *seat)
|
||||
{
|
||||
Eina_List *devs, *l;
|
||||
const char *dev, *ret = NULL, *chosen_dev = NULL, *d = NULL;
|
||||
Eina_Bool found = EINA_FALSE;
|
||||
Eina_Bool modeset;
|
||||
int fd;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
|
||||
|
||||
d = getenv("ECORE_DRM2_CARD");
|
||||
if (d)
|
||||
devs = eeze_udev_find_by_subsystem_sysname("drm", d);
|
||||
else
|
||||
devs = eeze_udev_find_by_subsystem_sysname("drm", "card[0-9]*");
|
||||
|
||||
if (!devs) return NULL;
|
||||
|
||||
EINA_LIST_FOREACH(devs, l, dev)
|
||||
{
|
||||
const char *dpath, *dseat, *dparent;
|
||||
|
||||
dpath = eeze_udev_syspath_get_devpath(dev);
|
||||
if (!dpath) continue;
|
||||
|
||||
dseat = eeze_udev_syspath_get_property(dev, "ID_SEAT");
|
||||
if (!dseat) dseat = eina_stringshare_add("seat0");
|
||||
|
||||
if (strcmp(seat, dseat))
|
||||
goto cont;
|
||||
|
||||
fd = elput_manager_open(em, dpath, -1);
|
||||
if (fd < 0)
|
||||
goto cont;
|
||||
modeset = _drm2_device_modeset_capable(fd);
|
||||
elput_manager_close(em, fd);
|
||||
if (!modeset)
|
||||
goto cont;
|
||||
|
||||
chosen_dev = dev;
|
||||
|
||||
dparent = eeze_udev_syspath_get_parent_filtered(dev, "pci", NULL);
|
||||
if (dparent)
|
||||
{
|
||||
const char *id;
|
||||
|
||||
id = eeze_udev_syspath_get_sysattr(dparent, "boot_vga");
|
||||
if (id)
|
||||
{
|
||||
if (!strcmp(id, "1")) found = EINA_TRUE;
|
||||
eina_stringshare_del(id);
|
||||
}
|
||||
|
||||
eina_stringshare_del(dparent);
|
||||
}
|
||||
|
||||
cont:
|
||||
eina_stringshare_del(dpath);
|
||||
eina_stringshare_del(dseat);
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
if (chosen_dev)
|
||||
ret = eeze_udev_syspath_get_devpath(chosen_dev);
|
||||
|
||||
EINA_LIST_FREE(devs, dev)
|
||||
eina_stringshare_del(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
# if 0
|
||||
static Eina_Bool
|
||||
_drm2_atomic_usable(int fd)
|
||||
{
|
||||
drmVersion *drmver;
|
||||
Eina_Bool ret = EINA_FALSE;
|
||||
|
||||
drmver = sym_drmGetVersion(fd);
|
||||
if (!drmver) return EINA_FALSE;
|
||||
|
||||
/* detect driver */
|
||||
if ((!strcmp(drmver->name, "i915")) &&
|
||||
(!strcmp(drmver->desc, "Intel Graphics")))
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
/* detect kernel version
|
||||
* NB: In order for atomic modesetting to work properly for Intel,
|
||||
* we need to be using a kernel >= 4.8.0 */
|
||||
|
||||
fp = fopen("/proc/sys/kernel/osrelease", "rb");
|
||||
if (fp)
|
||||
{
|
||||
char buff[512];
|
||||
int maj = 0, min = 0;
|
||||
|
||||
if (fgets(buff, sizeof(buff), fp))
|
||||
{
|
||||
if (sscanf(buff, "%i.%i.%*s", &maj, &min) == 2)
|
||||
{
|
||||
if ((maj >= 4) && (min >= 8))
|
||||
ret = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
sym_drmFreeVersion(drmver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
# endif
|
||||
|
||||
static void
|
||||
_drm2_atomic_state_crtc_fill(Ecore_Drm2_Crtc_State *cstate, int fd)
|
||||
{
|
||||
drmModeObjectPropertiesPtr oprops;
|
||||
unsigned int i = 0;
|
||||
|
||||
DBG("Atomic State Crtc Fill");
|
||||
|
||||
oprops =
|
||||
sym_drmModeObjectGetProperties(fd, cstate->obj_id, DRM_MODE_OBJECT_CRTC);
|
||||
if (!oprops) return;
|
||||
|
||||
DBG("\tCrtc %d", cstate->obj_id);
|
||||
|
||||
for (i = 0; i < oprops->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
prop = sym_drmModeGetProperty(fd, oprops->props[i]);
|
||||
if (!prop) continue;
|
||||
|
||||
DBG("\t\tProperty: %s %d", prop->name, i);
|
||||
|
||||
if (!strcmp(prop->name, "MODE_ID"))
|
||||
{
|
||||
drmModePropertyBlobPtr bp;
|
||||
|
||||
cstate->mode.id = prop->prop_id;
|
||||
cstate->mode.value = oprops->prop_values[i];
|
||||
DBG("\t\t\tValue: %d", cstate->mode.value);
|
||||
|
||||
if (!cstate->mode.value)
|
||||
{
|
||||
cstate->mode.len = 0;
|
||||
goto cont;
|
||||
}
|
||||
|
||||
bp = sym_drmModeGetPropertyBlob(fd, cstate->mode.value);
|
||||
if (!bp) goto cont;
|
||||
|
||||
if ((!cstate->mode.data) ||
|
||||
memcmp(cstate->mode.data, bp->data, bp->length) != 0)
|
||||
{
|
||||
cstate->mode.data =
|
||||
eina_memdup(bp->data, bp->length, 1);
|
||||
}
|
||||
|
||||
cstate->mode.len = bp->length;
|
||||
|
||||
if (cstate->mode.value != 0)
|
||||
sym_drmModeCreatePropertyBlob(fd, bp->data, bp->length,
|
||||
&cstate->mode.value);
|
||||
|
||||
sym_drmModeFreePropertyBlob(bp);
|
||||
}
|
||||
else if (!strcmp(prop->name, "ACTIVE"))
|
||||
{
|
||||
cstate->active.id = prop->prop_id;
|
||||
cstate->active.value = oprops->prop_values[i];
|
||||
DBG("\t\t\tValue: %lu", (long)cstate->active.value);
|
||||
}
|
||||
else if (!strcmp(prop->name, "BACKGROUND_COLOR"))
|
||||
{
|
||||
cstate->background.id = prop->prop_id;
|
||||
cstate->background.value = oprops->prop_values[i];
|
||||
}
|
||||
cont:
|
||||
sym_drmModeFreeProperty(prop);
|
||||
}
|
||||
|
||||
sym_drmModeFreeObjectProperties(oprops);
|
||||
}
|
||||
|
||||
static void
|
||||
_drm2_atomic_state_conn_fill(Ecore_Drm2_Connector_State *cstate, int fd)
|
||||
{
|
||||
drmModeObjectPropertiesPtr oprops;
|
||||
unsigned int i = 0;
|
||||
|
||||
DBG("Atomic State Connector Fill");
|
||||
|
||||
oprops =
|
||||
sym_drmModeObjectGetProperties(fd, cstate->obj_id, DRM_MODE_OBJECT_CONNECTOR);
|
||||
if (!oprops) return;
|
||||
|
||||
DBG("\tConnector: %d", cstate->obj_id);
|
||||
|
||||
for (i = 0; i < oprops->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
prop = sym_drmModeGetProperty(fd, oprops->props[i]);
|
||||
if (!prop) continue;
|
||||
|
||||
DBG("\t\tProperty: %s", prop->name);
|
||||
|
||||
if (!strcmp(prop->name, "CRTC_ID"))
|
||||
{
|
||||
cstate->crtc.id = prop->prop_id;
|
||||
cstate->crtc.value = oprops->prop_values[i];
|
||||
DBG("\t\t\tValue: %lu", (long)cstate->crtc.value);
|
||||
}
|
||||
else if (!strcmp(prop->name, "DPMS"))
|
||||
{
|
||||
cstate->dpms.id = prop->prop_id;
|
||||
cstate->dpms.value = oprops->prop_values[i];
|
||||
DBG("\t\t\tValue: %lu", (long)cstate->dpms.value);
|
||||
}
|
||||
else if (!strcmp(prop->name, "EDID"))
|
||||
{
|
||||
drmModePropertyBlobPtr bp;
|
||||
|
||||
cstate->edid.id = oprops->prop_values[i];
|
||||
if (!cstate->edid.id)
|
||||
{
|
||||
cstate->edid.len = 0;
|
||||
goto cont;
|
||||
}
|
||||
|
||||
bp = sym_drmModeGetPropertyBlob(fd, cstate->edid.id);
|
||||
if (!bp) goto cont;
|
||||
|
||||
if ((!cstate->edid.data) ||
|
||||
memcmp(cstate->edid.data, bp->data, bp->length) != 0)
|
||||
{
|
||||
cstate->edid.data =
|
||||
eina_memdup(bp->data, bp->length, 1);
|
||||
}
|
||||
|
||||
cstate->edid.len = bp->length;
|
||||
|
||||
if (cstate->edid.id != 0)
|
||||
sym_drmModeCreatePropertyBlob(fd, bp->data, bp->length,
|
||||
&cstate->edid.id);
|
||||
|
||||
sym_drmModeFreePropertyBlob(bp);
|
||||
}
|
||||
else if (!strcmp(prop->name, "aspect ratio"))
|
||||
{
|
||||
cstate->aspect.id = prop->prop_id;
|
||||
cstate->aspect.value = oprops->prop_values[i];
|
||||
DBG("\t\t\tValue: %lu", (long)cstate->aspect.value);
|
||||
}
|
||||
else if (!strcmp(prop->name, "scaling mode"))
|
||||
{
|
||||
cstate->scaling.id = prop->prop_id;
|
||||
cstate->scaling.value = oprops->prop_values[i];
|
||||
DBG("\t\t\tValue: %lu", (long)cstate->scaling.value);
|
||||
}
|
||||
|
||||
cont:
|
||||
sym_drmModeFreeProperty(prop);
|
||||
}
|
||||
|
||||
sym_drmModeFreeObjectProperties(oprops);
|
||||
}
|
||||
|
||||
static void
|
||||
_drm2_atomic_state_plane_fill(Ecore_Drm2_Plane_State *pstate, int fd)
|
||||
{
|
||||
drmModeObjectPropertiesPtr oprops;
|
||||
unsigned int i = 0;
|
||||
int k = 0;
|
||||
|
||||
DBG("Atomic State Plane Fill");
|
||||
|
||||
oprops =
|
||||
sym_drmModeObjectGetProperties(fd, pstate->obj_id, DRM_MODE_OBJECT_PLANE);
|
||||
if (!oprops) return;
|
||||
|
||||
DBG("\tPlane: %d", pstate->obj_id);
|
||||
|
||||
for (i = 0; i < oprops->count_props; i++)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
|
||||
prop = sym_drmModeGetProperty(fd, oprops->props[i]);
|
||||
if (!prop) continue;
|
||||
|
||||
DBG("\t\tProperty: %s", prop->name);
|
||||
|
||||
if (!strcmp(prop->name, "CRTC_ID"))
|
||||
{
|
||||
pstate->cid.id = prop->prop_id;
|
||||
pstate->cid.value = oprops->prop_values[i];
|
||||
DBG("\t\t\tValue: %lu", (long)pstate->cid.value);
|
||||
}
|
||||
else if (!strcmp(prop->name, "FB_ID"))
|
||||
{
|
||||
pstate->fid.id = prop->prop_id;
|
||||
pstate->fid.value = oprops->prop_values[i];
|
||||
DBG("\t\t\tValue: %lu", (long)pstate->fid.value);
|
||||
}
|
||||
else if (!strcmp(prop->name, "CRTC_X"))
|
||||
{
|
||||
pstate->cx.id = prop->prop_id;
|
||||
pstate->cx.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "CRTC_Y"))
|
||||
{
|
||||
pstate->cy.id = prop->prop_id;
|
||||
pstate->cy.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "CRTC_W"))
|
||||
{
|
||||
pstate->cw.id = prop->prop_id;
|
||||
pstate->cw.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "CRTC_H"))
|
||||
{
|
||||
pstate->ch.id = prop->prop_id;
|
||||
pstate->ch.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "SRC_X"))
|
||||
{
|
||||
pstate->sx.id = prop->prop_id;
|
||||
pstate->sx.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "SRC_Y"))
|
||||
{
|
||||
pstate->sy.id = prop->prop_id;
|
||||
pstate->sy.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "SRC_W"))
|
||||
{
|
||||
pstate->sw.id = prop->prop_id;
|
||||
pstate->sw.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "SRC_H"))
|
||||
{
|
||||
pstate->sh.id = prop->prop_id;
|
||||
pstate->sh.value = oprops->prop_values[i];
|
||||
}
|
||||
else if (!strcmp(prop->name, "type"))
|
||||
{
|
||||
pstate->type.id = prop->prop_id;
|
||||
pstate->type.value = oprops->prop_values[i];
|
||||
switch (pstate->type.value)
|
||||
{
|
||||
case DRM_PLANE_TYPE_OVERLAY:
|
||||
DBG("\t\t\tOverlay Plane");
|
||||
break;
|
||||
case DRM_PLANE_TYPE_PRIMARY:
|
||||
DBG("\t\t\tPrimary Plane");
|
||||
break;
|
||||
case DRM_PLANE_TYPE_CURSOR:
|
||||
DBG("\t\t\tCursor Plane");
|
||||
break;
|
||||
default:
|
||||
DBG("\t\t\tValue: %lu", (long)pstate->type.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(prop->name, "rotation"))
|
||||
{
|
||||
pstate->rotation.id = prop->prop_id;
|
||||
pstate->rotation.value = oprops->prop_values[i];
|
||||
|
||||
for (k = 0; k < prop->count_enums; k++)
|
||||
{
|
||||
int r = -1;
|
||||
|
||||
DBG("\t\t\tRotation: %s", prop->enums[k].name);
|
||||
if (!strcmp(prop->enums[k].name, "rotate-0"))
|
||||
r = ECORE_DRM2_ROTATION_NORMAL;
|
||||
else if (!strcmp(prop->enums[k].name, "rotate-90"))
|
||||
r = ECORE_DRM2_ROTATION_90;
|
||||
else if (!strcmp(prop->enums[k].name, "rotate-180"))
|
||||
r = ECORE_DRM2_ROTATION_180;
|
||||
else if (!strcmp(prop->enums[k].name, "rotate-270"))
|
||||
r = ECORE_DRM2_ROTATION_270;
|
||||
else if (!strcmp(prop->enums[k].name, "reflect-x"))
|
||||
r = ECORE_DRM2_ROTATION_REFLECT_X;
|
||||
else if (!strcmp(prop->enums[k].name, "reflect-y"))
|
||||
r = ECORE_DRM2_ROTATION_REFLECT_Y;
|
||||
|
||||
if (r != -1)
|
||||
{
|
||||
pstate->supported_rotations |= r;
|
||||
pstate->rotation_map[ffs(r)] =
|
||||
1ULL << prop->enums[k].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sym_drmModeFreeProperty(prop);
|
||||
}
|
||||
|
||||
sym_drmModeFreeObjectProperties(oprops);
|
||||
}
|
||||
|
||||
static void
|
||||
_drm2_atomic_state_fill(Ecore_Drm2_Atomic_State *state, int fd)
|
||||
{
|
||||
int i = 0;
|
||||
drmModeResPtr res;
|
||||
drmModePlaneResPtr pres;
|
||||
|
||||
res = sym_drmModeGetResources(fd);
|
||||
if (!res) return;
|
||||
|
||||
pres = sym_drmModeGetPlaneResources(fd);
|
||||
if (!pres) goto err;
|
||||
|
||||
state->crtcs = res->count_crtcs;
|
||||
state->crtc_states = calloc(state->crtcs, sizeof(Ecore_Drm2_Crtc_State));
|
||||
if (state->crtc_states)
|
||||
{
|
||||
for (i = 0; i < state->crtcs; i++)
|
||||
{
|
||||
Ecore_Drm2_Crtc_State *cstate;
|
||||
|
||||
cstate = &state->crtc_states[i];
|
||||
cstate->obj_id = res->crtcs[i];
|
||||
cstate->index = i;
|
||||
|
||||
_drm2_atomic_state_crtc_fill(cstate, fd);
|
||||
}
|
||||
}
|
||||
|
||||
state->conns = res->count_connectors;
|
||||
state->conn_states =
|
||||
calloc(state->conns, sizeof(Ecore_Drm2_Connector_State));
|
||||
if (state->conn_states)
|
||||
{
|
||||
for (i = 0; i < state->conns; i++)
|
||||
{
|
||||
Ecore_Drm2_Connector_State *cstate;
|
||||
|
||||
cstate = &state->conn_states[i];
|
||||
cstate->obj_id = res->connectors[i];
|
||||
|
||||
_drm2_atomic_state_conn_fill(cstate, fd);
|
||||
}
|
||||
}
|
||||
|
||||
state->planes = pres->count_planes;
|
||||
state->plane_states = calloc(state->planes, sizeof(Ecore_Drm2_Plane_State));
|
||||
if (state->plane_states)
|
||||
{
|
||||
unsigned int f = 0;
|
||||
|
||||
for (i = 0; i < state->planes; i++)
|
||||
{
|
||||
drmModePlanePtr plane;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
|
||||
plane = sym_drmModeGetPlane(fd, pres->planes[i]);
|
||||
if (!plane) continue;
|
||||
|
||||
pstate = &state->plane_states[i];
|
||||
pstate->obj_id = pres->planes[i];
|
||||
pstate->mask = plane->possible_crtcs;
|
||||
pstate->num_formats = plane->count_formats;
|
||||
|
||||
pstate->formats = calloc(plane->count_formats, sizeof(uint32_t));
|
||||
|
||||
for (f = 0; f < plane->count_formats; f++)
|
||||
pstate->formats[f] = plane->formats[f];
|
||||
|
||||
sym_drmModeFreePlane(plane);
|
||||
|
||||
_drm2_atomic_state_plane_fill(pstate, fd);
|
||||
}
|
||||
}
|
||||
|
||||
sym_drmModeFreePlaneResources(pres);
|
||||
|
||||
err:
|
||||
sym_drmModeFreeResources(res);
|
||||
}
|
||||
|
||||
static void
|
||||
_drm2_atomic_state_free(Ecore_Drm2_Atomic_State *state)
|
||||
{
|
||||
free(state->plane_states);
|
||||
free(state->conn_states);
|
||||
free(state->crtc_states);
|
||||
free(state);
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Device *
|
||||
ecore_drm2_device_open(const char *seat, unsigned int tty)
|
||||
{
|
||||
Ecore_Drm2_Device *device;
|
||||
|
||||
device = calloc(1, sizeof(Ecore_Drm2_Device));
|
||||
if (!device) return NULL;
|
||||
|
||||
device->em = elput_manager_connect(seat, tty);
|
||||
if (!device->em)
|
||||
{
|
||||
ERR("Could not connect to input manager");
|
||||
goto man_err;
|
||||
}
|
||||
|
||||
device->path = _drm2_device_find(device->em, seat);
|
||||
if (!device->path)
|
||||
{
|
||||
ERR("Could not find drm device on seat %s", seat);
|
||||
goto path_err;
|
||||
}
|
||||
|
||||
device->fd = elput_manager_open(device->em, device->path, -1);
|
||||
if (device->fd < 0) goto path_err;
|
||||
|
||||
if (!elput_input_init(device->em))
|
||||
{
|
||||
ERR("Could not initialize Elput Input");
|
||||
goto input_err;
|
||||
}
|
||||
|
||||
DBG("Device Path: %s", device->path);
|
||||
DBG("Device Fd: %d", device->fd);
|
||||
|
||||
# if 0
|
||||
/* check that this system can do atomic */
|
||||
_ecore_drm2_use_atomic = _drm2_atomic_usable(device->fd);
|
||||
# endif
|
||||
|
||||
if (getenv("ECORE_DRM2_ATOMIC_DISABLE"))
|
||||
_ecore_drm2_use_atomic = EINA_FALSE;
|
||||
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
if (sym_drmSetClientCap(device->fd,
|
||||
DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0)
|
||||
{
|
||||
WRN("Could not enable Universal Plane support");
|
||||
_ecore_drm2_use_atomic = EINA_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sym_drmSetClientCap(device->fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0)
|
||||
{
|
||||
WRN("Could not enable Atomic Modesetting support");
|
||||
_ecore_drm2_use_atomic = EINA_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
device->state = calloc(1, sizeof(Ecore_Drm2_Atomic_State));
|
||||
if (device->state)
|
||||
_drm2_atomic_state_fill(device->state, device->fd);
|
||||
}
|
||||
|
||||
device->active_hdlr =
|
||||
ecore_event_handler_add(ELPUT_EVENT_SESSION_ACTIVE,
|
||||
_cb_session_active, device);
|
||||
|
||||
device->device_change_hdlr =
|
||||
ecore_event_handler_add(ELPUT_EVENT_DEVICE_CHANGE,
|
||||
_cb_device_change, device);
|
||||
|
||||
return device;
|
||||
|
||||
input_err:
|
||||
elput_manager_close(device->em, device->fd);
|
||||
path_err:
|
||||
elput_manager_disconnect(device->em);
|
||||
man_err:
|
||||
free(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_close(Ecore_Drm2_Device *device)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_shutdown(device->em);
|
||||
elput_manager_close(device->em, device->fd);
|
||||
if (_ecore_drm2_use_atomic)
|
||||
_drm2_atomic_state_free(device->state);
|
||||
|
||||
ecore_event_handler_del(device->active_hdlr);
|
||||
ecore_event_handler_del(device->device_change_hdlr);
|
||||
eina_stringshare_del(device->path);
|
||||
free(device);
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_device_clock_id_get(Ecore_Drm2_Device *device)
|
||||
{
|
||||
uint64_t caps;
|
||||
int ret;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1);
|
||||
|
||||
ret = sym_drmGetCap(device->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &caps);
|
||||
if ((ret == 0) && (caps == 1))
|
||||
return CLOCK_MONOTONIC;
|
||||
else
|
||||
return CLOCK_REALTIME;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *height)
|
||||
{
|
||||
uint64_t caps;
|
||||
int ret;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
if (width)
|
||||
{
|
||||
*width = 64;
|
||||
ret = sym_drmGetCap(device->fd, DRM_CAP_CURSOR_WIDTH, &caps);
|
||||
if (ret == 0)
|
||||
{
|
||||
device->cursor.width = caps;
|
||||
*width = caps;
|
||||
}
|
||||
}
|
||||
if (height)
|
||||
{
|
||||
*height = 64;
|
||||
ret = sym_drmGetCap(device->fd, DRM_CAP_CURSOR_HEIGHT, &caps);
|
||||
if (ret == 0)
|
||||
{
|
||||
device->cursor.height = caps;
|
||||
*height = caps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device *device, int *x, int *y)
|
||||
{
|
||||
if (x) *x = 0;
|
||||
if (y) *y = 0;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_pointer_xy_get(device->em, NULL, x, y);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_pointer_xy_set(device->em, NULL, x, y);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_device_pointer_left_handed_set(Ecore_Drm2_Device *device, Eina_Bool left)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
|
||||
|
||||
return elput_input_pointer_left_handed_set(device->em, NULL, left);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_device_pointer_rotation_set(Ecore_Drm2_Device *device, int rotation)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
|
||||
|
||||
return elput_input_pointer_rotation_set(device->em, rotation);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_pointer_accel_speed_set(Ecore_Drm2_Device *device, double speed)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_pointer_accel_speed_set(device->em, NULL, speed);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_pointer_accel_profile_set(Ecore_Drm2_Device *device, uint32_t profile)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_pointer_accel_profile_set(device->em, NULL, profile);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_touch_tap_to_click_enabled_set(Ecore_Drm2_Device *device, Eina_Bool enabled)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_touch_tap_to_click_enabled_set(device->em, NULL, enabled);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int window)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
EINA_SAFETY_ON_NULL_RETURN(device->em);
|
||||
elput_manager_window_set(device->em, window);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
EINA_SAFETY_ON_NULL_RETURN(device->em);
|
||||
|
||||
elput_input_pointer_max_set(device->em, w, h);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_keyboard_info_set(Ecore_Drm2_Device *device, void *context, void *keymap, int group)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_keyboard_info_set(device->em, context, keymap, group);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_keyboard_group_set(Ecore_Drm2_Device *device, int group)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_keyboard_group_set(device->em, group);
|
||||
}
|
||||
|
||||
EAPI unsigned int *
|
||||
ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL);
|
||||
|
||||
if (num) *num = device->num_crtcs;
|
||||
return device->crtcs;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device *device, int *minw, int *minh, int *maxw, int *maxh)
|
||||
{
|
||||
if (minw) *minw = 0;
|
||||
if (minh) *minh = 0;
|
||||
if (maxw) *maxw = 0;
|
||||
if (maxh) *maxh = 0;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
if (minw) *minw = device->min.width;
|
||||
if (minh) *minh = device->min.height;
|
||||
if (maxw) *maxw = device->max.width;
|
||||
if (maxh) *maxh = device->max.height;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_calibrate(Ecore_Drm2_Device *device, int w, int h)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
elput_input_devices_calibrate(device->em, w, h);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_device_vt_set(Ecore_Drm2_Device *device, int vt)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
|
||||
|
||||
return elput_manager_vt_set(device->em, vt);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_device_prefer_shadow(Ecore_Drm2_Device *device)
|
||||
{
|
||||
uint64_t caps;
|
||||
int ret;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
|
||||
|
||||
ret = sym_drmGetCap(device->fd, DRM_CAP_DUMB_PREFER_SHADOW, &caps);
|
||||
if ((ret == 0) && (caps == 1))
|
||||
return EINA_TRUE;
|
||||
else
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_device_preferred_depth_get(Ecore_Drm2_Device *device, int *depth, int *bpp)
|
||||
{
|
||||
uint64_t caps;
|
||||
int ret;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(device);
|
||||
|
||||
ret = sym_drmGetCap(device->fd, DRM_CAP_DUMB_PREFERRED_DEPTH, &caps);
|
||||
if (ret == 0)
|
||||
{
|
||||
if (depth) *depth = caps;
|
||||
if (bpp) *bpp = caps;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_device_fd_get(Ecore_Drm2_Device *device)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1);
|
||||
|
||||
return device->fd;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_vblank_supported(Ecore_Drm2_Device *dev)
|
||||
{
|
||||
drmVBlank tmp;
|
||||
int ret = 0;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
|
||||
|
||||
memset(&tmp, 0, sizeof(drmVBlank));
|
||||
tmp.request.type = DRM_VBLANK_RELATIVE;
|
||||
|
||||
ret = sym_drmWaitVBlank(dev->fd, &tmp);
|
||||
|
||||
if (ret != 0) return EINA_FALSE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
/* prevent crashing with old apps compiled against these functions */
|
||||
EAPI void ecore_drm2_device_keyboard_cached_context_set(){};
|
||||
EAPI void ecore_drm2_device_keyboard_cached_keymap_set(){};
|
|
@ -1,799 +0,0 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
#define FLIP_TIMEOUT 1.0
|
||||
|
||||
static Eina_Bool
|
||||
_fb2_create(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
uint32_t offsets[4] = { 0 };
|
||||
int r;
|
||||
|
||||
r = sym_drmModeAddFB2(fb->fd, fb->w, fb->h, fb->format, fb->handles,
|
||||
fb->strides, offsets, &fb->id, 0);
|
||||
|
||||
if (r)
|
||||
return EINA_FALSE;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Fb *
|
||||
ecore_drm2_fb_create(Ecore_Drm2_Device *dev, int width, int height, int depth, int bpp, unsigned int format)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
struct drm_mode_create_dumb carg;
|
||||
struct drm_mode_destroy_dumb darg;
|
||||
struct drm_mode_map_dumb marg;
|
||||
int ret;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL);
|
||||
|
||||
fb = calloc(1, sizeof(Ecore_Drm2_Fb));
|
||||
if (!fb) return NULL;
|
||||
|
||||
fb->fd = dev->fd;
|
||||
fb->w = width;
|
||||
fb->h = height;
|
||||
fb->bpp = bpp;
|
||||
fb->depth = depth;
|
||||
fb->format = format;
|
||||
fb->ref = 1;
|
||||
|
||||
memset(&carg, 0, sizeof(struct drm_mode_create_dumb));
|
||||
carg.bpp = bpp;
|
||||
carg.width = width;
|
||||
carg.height = height;
|
||||
|
||||
ret = sym_drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATE_DUMB, &carg);
|
||||
if (ret) goto err;
|
||||
|
||||
fb->handles[0] = carg.handle;
|
||||
fb->sizes[0] = carg.size;
|
||||
fb->strides[0] = carg.pitch;
|
||||
|
||||
if (!_fb2_create(fb))
|
||||
{
|
||||
ret =
|
||||
sym_drmModeAddFB(dev->fd, width, height, depth, bpp,
|
||||
fb->strides[0], fb->handles[0], &fb->id);
|
||||
if (ret)
|
||||
{
|
||||
ERR("Could not add framebuffer: %m");
|
||||
goto add_err;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&marg, 0, sizeof(struct drm_mode_map_dumb));
|
||||
marg.handle = fb->handles[0];
|
||||
ret = sym_drmIoctl(dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &marg);
|
||||
if (ret)
|
||||
{
|
||||
ERR("Could not map framebuffer: %m");
|
||||
goto map_err;
|
||||
}
|
||||
|
||||
fb->mmap = mmap(NULL, fb->sizes[0], PROT_WRITE, MAP_SHARED, dev->fd, marg.offset);
|
||||
if (fb->mmap == MAP_FAILED)
|
||||
{
|
||||
ERR("Could not mmap framebuffer memory: %m");
|
||||
goto map_err;
|
||||
}
|
||||
|
||||
return fb;
|
||||
|
||||
map_err:
|
||||
sym_drmModeRmFB(dev->fd, fb->id);
|
||||
add_err:
|
||||
memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb));
|
||||
darg.handle = fb->handles[0];
|
||||
sym_drmIoctl(dev->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
|
||||
err:
|
||||
free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Fb *
|
||||
ecore_drm2_fb_gbm_create(Ecore_Drm2_Device *dev, int width, int height, int depth, int bpp, unsigned int format, unsigned int handle, unsigned int stride, void *bo)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL);
|
||||
|
||||
fb = calloc(1, sizeof(Ecore_Drm2_Fb));
|
||||
if (!fb) return NULL;
|
||||
|
||||
fb->gbm = EINA_TRUE;
|
||||
fb->gbm_bo = bo;
|
||||
|
||||
fb->fd = dev->fd;
|
||||
fb->w = width;
|
||||
fb->h = height;
|
||||
fb->bpp = bpp;
|
||||
fb->depth = depth;
|
||||
fb->format = format;
|
||||
fb->strides[0] = stride;
|
||||
fb->sizes[0] = fb->strides[0] * fb->h;
|
||||
fb->handles[0] = handle;
|
||||
fb->ref = 1;
|
||||
|
||||
if (!_fb2_create(fb))
|
||||
{
|
||||
if (sym_drmModeAddFB(dev->fd, width, height, depth, bpp,
|
||||
fb->strides[0], fb->handles[0], &fb->id))
|
||||
{
|
||||
ERR("Could not add framebuffer: %m");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return fb;
|
||||
|
||||
err:
|
||||
free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(fb);
|
||||
|
||||
if (!fb->dead) WRN("Destroying an fb that hasn't been discarded");
|
||||
|
||||
if (fb->scanout_count)
|
||||
WRN("Destroyed fb on scanout %d times.", fb->scanout_count);
|
||||
|
||||
if (fb->mmap) munmap(fb->mmap, fb->sizes[0]);
|
||||
|
||||
if (fb->id) sym_drmModeRmFB(fb->fd, fb->id);
|
||||
|
||||
if (!fb->gbm && !fb->dmabuf)
|
||||
{
|
||||
struct drm_mode_destroy_dumb darg;
|
||||
|
||||
memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb));
|
||||
darg.handle = fb->handles[0];
|
||||
sym_drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
|
||||
}
|
||||
|
||||
free(fb);
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_drm2_fb_ref(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
fb->ref++;
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_drm2_fb_deref(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
fb->ref--;
|
||||
if (fb->ref) return;
|
||||
|
||||
if (fb->status_handler)
|
||||
fb->status_handler(fb, ECORE_DRM2_FB_STATUS_DELETED, fb->status_data);
|
||||
|
||||
_ecore_drm2_fb_destroy(fb);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_fb_discard(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(fb);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(fb->ref < 1);
|
||||
|
||||
fb->dead = EINA_TRUE;
|
||||
_ecore_drm2_fb_deref(fb);
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, NULL);
|
||||
return fb->mmap;
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, 0);
|
||||
return fb->sizes[0];
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, 0);
|
||||
|
||||
return fb->strides[0];
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(fb);
|
||||
EINA_SAFETY_ON_NULL_RETURN(rects);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(fb->dead);
|
||||
|
||||
#ifdef DRM_MODE_FEATURE_DIRTYFB
|
||||
drmModeClip *clip;
|
||||
unsigned int i = 0;
|
||||
int ret;
|
||||
|
||||
clip = alloca(count * sizeof(drmModeClip));
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
clip[i].x1 = rects[i].x;
|
||||
clip[i].y1 = rects[i].y;
|
||||
clip[i].x2 = rects[i].w;
|
||||
clip[i].y2 = rects[i].h;
|
||||
}
|
||||
|
||||
ret = sym_drmModeDirtyFB(fb->fd, fb->id, clip, count);
|
||||
if ((ret) && (ret == -EINVAL))
|
||||
WRN("Could not mark framebuffer as dirty: %m");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* perhaps output is no longer a necessary parameter for this function */
|
||||
void
|
||||
_ecore_drm2_fb_buffer_release(Ecore_Drm2_Output *output EINA_UNUSED, Ecore_Drm2_Output_State *s)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb = s->fb;
|
||||
|
||||
if (fb->status_handler)
|
||||
fb->status_handler(fb, ECORE_DRM2_FB_STATUS_RELEASE, fb->status_data);
|
||||
|
||||
_ecore_drm2_fb_deref(fb);
|
||||
s->fb = NULL;
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
if (s->atomic_req)
|
||||
sym_drmModeAtomicFree(s->atomic_req);
|
||||
s->atomic_req = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_mainloop_async_timer_del(void *data)
|
||||
{
|
||||
Ecore_Drm2_Output *output = data;
|
||||
|
||||
ecore_timer_del(output->flip_timeout);
|
||||
output->flip_timeout = NULL;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_fb_flip_complete(Ecore_Drm2_Output *output)
|
||||
{
|
||||
Eina_Bool plane_scanout;
|
||||
Ecore_Drm2_Fb *fb;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
|
||||
|
||||
if (output->flip_timeout)
|
||||
{
|
||||
// XXX: output ref++
|
||||
ecore_main_loop_thread_safe_call_async
|
||||
(_cb_mainloop_async_timer_del, output);
|
||||
}
|
||||
if (!output->pending.fb) fprintf(stderr, "XXX--XXX eeeeek pending fb is NULL so current would become null ----------------------------------\n");
|
||||
if (output->current.fb && (output->current.fb != output->pending.fb))
|
||||
_ecore_drm2_fb_buffer_release(output, &output->current);
|
||||
|
||||
output->current.fb = output->pending.fb;
|
||||
output->pending.fb = NULL;
|
||||
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
Eina_List *l, *ll;
|
||||
Ecore_Drm2_Plane *plane;
|
||||
|
||||
output->current.atomic_req = output->pending.atomic_req;
|
||||
output->pending.atomic_req = NULL;
|
||||
|
||||
EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
|
||||
{
|
||||
fb = plane->fb;
|
||||
plane_scanout = plane->scanout;
|
||||
if (!plane->dead)
|
||||
{
|
||||
/* First time this plane is scanned out */
|
||||
if (!plane->scanout)
|
||||
fb->scanout_count++;
|
||||
|
||||
plane->scanout = EINA_TRUE;
|
||||
if (fb->status_handler && (fb->scanout_count == 1) &&
|
||||
(plane_scanout != plane->scanout))
|
||||
fb->status_handler(fb, ECORE_DRM2_FB_STATUS_SCANOUT_ON,
|
||||
fb->status_data);
|
||||
continue;
|
||||
}
|
||||
output->planes = eina_list_remove_list(output->planes, l);
|
||||
free(plane);
|
||||
if (!plane_scanout) continue;
|
||||
|
||||
fb->scanout_count--;
|
||||
if (fb->status_handler && (fb->scanout_count == 0))
|
||||
fb->status_handler(fb, ECORE_DRM2_FB_STATUS_SCANOUT_OFF,
|
||||
fb->status_data);
|
||||
}
|
||||
}
|
||||
|
||||
EINA_LIST_FREE(output->fbs, fb)
|
||||
_ecore_drm2_fb_deref(fb);
|
||||
output->fbs = NULL;
|
||||
|
||||
return !!output->next.fb;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
_fb_atomic_flip_test(Ecore_Drm2_Output *output)
|
||||
{
|
||||
int ret = 0;
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Crtc_State *cstate;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
Ecore_Drm2_Plane *plane;
|
||||
drmModeAtomicReq *req = NULL;
|
||||
uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET |
|
||||
DRM_MODE_ATOMIC_TEST_ONLY;
|
||||
|
||||
if (!_ecore_drm2_use_atomic) return EINA_FALSE;
|
||||
|
||||
req = sym_drmModeAtomicAlloc();
|
||||
if (!req) return EINA_FALSE;
|
||||
|
||||
sym_drmModeAtomicSetCursor(req, 0);
|
||||
|
||||
cstate = output->crtc_state;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, cstate->obj_id, cstate->mode.id,
|
||||
cstate->mode.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, cstate->obj_id, cstate->active.id,
|
||||
cstate->active.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
if (cstate->background.id)
|
||||
{
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, cstate->obj_id,
|
||||
cstate->background.id,
|
||||
cstate->background.value);
|
||||
if (ret < 0) goto err;
|
||||
}
|
||||
|
||||
EINA_LIST_FOREACH(output->planes, l, plane)
|
||||
{
|
||||
pstate = plane->state;
|
||||
|
||||
if (!pstate->in_use)
|
||||
{
|
||||
pstate->cid.value = 0;
|
||||
pstate->fid.value = 0;
|
||||
pstate->sw.value = 0;
|
||||
pstate->sh.value = 0;
|
||||
pstate->cx.value = 0;
|
||||
pstate->cy.value = 0;
|
||||
pstate->cw.value = 0;
|
||||
pstate->ch.value = 0;
|
||||
}
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->cid.id, pstate->cid.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->fid.id, pstate->fid.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->sx.id, pstate->sx.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->sy.id, pstate->sy.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->sw.id, pstate->sw.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->sh.id, pstate->sh.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->cx.id, pstate->cx.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->cy.id, pstate->cy.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->cw.id, pstate->cw.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->ch.id, pstate->ch.value);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
#if 0
|
||||
/* XXX: Disable hardware plane rotation for now as this has broken
|
||||
* recently. The break happens because of an invalid argument,
|
||||
* ie: the value being sent from pstate->rotation_map ends up being
|
||||
* incorrect for some reason. I suspect the breakage to be from
|
||||
* kernel drivers (linux 4.20.0) but have not confirmed that version */
|
||||
if ((pstate->rotation.id) &&
|
||||
(pstate->type.value == DRM_PLANE_TYPE_PRIMARY))
|
||||
{
|
||||
DBG("Plane %d Atomic Rotation: %lu",
|
||||
pstate->obj_id, pstate->rotation.value);
|
||||
ret =
|
||||
sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->rotation.id,
|
||||
pstate->rotation_map[pstate->rotation.value]);
|
||||
if (ret < 0) goto err;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicCommit(output->fd, req, flags, output);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
/* clear any previous request */
|
||||
if (output->prep.atomic_req)
|
||||
sym_drmModeAtomicFree(output->prep.atomic_req);
|
||||
|
||||
output->prep.atomic_req = req;
|
||||
return EINA_TRUE;
|
||||
|
||||
err:
|
||||
DBG("Failed Atomic Test: %m");
|
||||
sym_drmModeAtomicFree(req);
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static int _fb_atomic_flip(Ecore_Drm2_Output *output);
|
||||
static int _fb_flip(Ecore_Drm2_Output *output);
|
||||
|
||||
static Eina_Bool
|
||||
_cb_flip_timeout(void *data)
|
||||
{
|
||||
Ecore_Drm2_Output *output = data;
|
||||
|
||||
output->flip_timeout = NULL;
|
||||
ERR("flip event callback timout %0.2fsec - try again", FLIP_TIMEOUT);
|
||||
if (_ecore_drm2_use_atomic) _fb_atomic_flip(output);
|
||||
else _fb_flip(output);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_mainloop_async_timer_reset(void *data)
|
||||
{
|
||||
Ecore_Drm2_Output *output = data;
|
||||
if (output->flip_timeout) ecore_timer_del(output->flip_timeout);
|
||||
output->flip_timeout = ecore_timer_add(FLIP_TIMEOUT, _cb_flip_timeout, output);
|
||||
}
|
||||
|
||||
static int
|
||||
_fb_atomic_flip(Ecore_Drm2_Output *output)
|
||||
{
|
||||
int res = 0;
|
||||
uint32_t flags =
|
||||
DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT |
|
||||
DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
|
||||
if (!_ecore_drm2_use_atomic) return -1;
|
||||
|
||||
/* If we have no req yet, we're flipping to current state.
|
||||
* rebuild the current state in the prep state */
|
||||
if (!output->prep.atomic_req) _fb_atomic_flip_test(output);
|
||||
|
||||
/* Still no req is a bad situation */
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output->prep.atomic_req, -1);
|
||||
|
||||
// sometimes we get a EBUSY ... so try again a few times.
|
||||
int i;
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
res =
|
||||
sym_drmModeAtomicCommit(output->fd, output->prep.atomic_req, flags,
|
||||
output);
|
||||
if (res == 0) break;
|
||||
else ERR("DRM atomic commit failed - retry #%i", i + 1);
|
||||
usleep(100);
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
ERR("Failed Atomic Commit: %m");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: output ref++
|
||||
ecore_main_loop_thread_safe_call_async
|
||||
(_cb_mainloop_async_timer_reset, output);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_fb_flip(Ecore_Drm2_Output *output)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
Eina_Bool repeat;
|
||||
int count = 0;
|
||||
int ret = 0;
|
||||
|
||||
fb = output->prep.fb;
|
||||
if (!fb)
|
||||
{
|
||||
fb = output->pending.fb;
|
||||
ERR("Trying to flip NULL fb - fallback to pending fb");
|
||||
}
|
||||
if (!fb)
|
||||
{
|
||||
ERR("Pending fb is also NULL, give up flipping");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((!output->current.fb) ||
|
||||
(output->current.fb->strides[0] != fb->strides[0]))
|
||||
{
|
||||
ret =
|
||||
sym_drmModeSetCrtc(fb->fd, output->crtc_id, fb->id,
|
||||
0, 0, &output->conn_id, 1,
|
||||
&output->current_mode->info);
|
||||
if (ret)
|
||||
{
|
||||
ERR("Failed to set Mode %dx%d for Output %s: %m",
|
||||
output->current_mode->width, output->current_mode->height,
|
||||
output->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (output->current.fb)
|
||||
_ecore_drm2_fb_buffer_release(output, &output->current);
|
||||
output->current.fb = fb;
|
||||
_ecore_drm2_fb_ref(output->current.fb);
|
||||
output->next.fb = NULL;
|
||||
/* We used to return here, but now that the ticker is fixed this
|
||||
* can leave us hanging waiting for a tick to happen forever.
|
||||
* Instead, we now fall through to the flip path to make sure
|
||||
* even this first set can cause a flip callback.
|
||||
*/
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
static Eina_Bool bugged_about_bug = EINA_FALSE;
|
||||
repeat = EINA_FALSE;
|
||||
ret = sym_drmModePageFlip(fb->fd, output->crtc_id, fb->id,
|
||||
DRM_MODE_PAGE_FLIP_EVENT, output);
|
||||
/* Some drivers (RPI - looking at you) are broken and produce
|
||||
* flip events before they are ready for another flip, so be
|
||||
* a little robust in the face of badness and try a few times
|
||||
* until we can flip or we give up (100 tries with a yield
|
||||
* between each try). We can't expect everyone to run the
|
||||
* latest bleeding edge kernel IF a workaround is possible
|
||||
* in userspace, so do this.
|
||||
* We only report this as an ERR once since if it will
|
||||
* generate a huge amount of spam otherwise. */
|
||||
if ((ret < 0) && (errno == EBUSY))
|
||||
{
|
||||
repeat = EINA_TRUE;
|
||||
if (count == 0 && !bugged_about_bug)
|
||||
{
|
||||
ERR("Pageflip fail - EBUSY from drmModePageFlip - "
|
||||
"This is either a kernel bug or an EFL one.");
|
||||
bugged_about_bug = EINA_TRUE;
|
||||
}
|
||||
count++;
|
||||
if (count > 500)
|
||||
{
|
||||
ERR("Pageflip EBUSY for %i tries - give up", count);
|
||||
break;
|
||||
}
|
||||
usleep(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: output ref++
|
||||
ecore_main_loop_thread_safe_call_async
|
||||
(_cb_mainloop_async_timer_reset, output);
|
||||
}
|
||||
}
|
||||
while (repeat);
|
||||
|
||||
if ((ret == 0) && (count > 0))
|
||||
DBG("Pageflip finally succeeded after %i tries due to EBUSY", count);
|
||||
|
||||
if ((ret < 0) && (errno != EBUSY))
|
||||
{
|
||||
ERR("Pageflip Failed for Crtc %u on Connector %u: %m",
|
||||
output->crtc_id, output->conn_id);
|
||||
return ret;
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
output->next.fb = fb;
|
||||
_ecore_drm2_fb_ref(output->next.fb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output, -1);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output->current_mode, -1);
|
||||
|
||||
if (!output->enabled) return -1;
|
||||
|
||||
if (fb) _ecore_drm2_fb_ref(fb);
|
||||
|
||||
if (output->pending.fb)
|
||||
{
|
||||
if (output->next.fb)
|
||||
_ecore_drm2_fb_buffer_release(output, &output->next);
|
||||
output->next.fb = fb;
|
||||
return 0;
|
||||
}
|
||||
if (!fb)
|
||||
{
|
||||
fb = output->next.fb;
|
||||
output->next.fb = NULL;
|
||||
}
|
||||
|
||||
/* So we can generate a tick by flipping to the current fb */
|
||||
if (!fb) fb = output->current.fb;
|
||||
|
||||
if (output->next.fb)
|
||||
_ecore_drm2_fb_buffer_release(output, &output->next);
|
||||
|
||||
/* If we don't have an fb to set by now, BAIL! */
|
||||
if (!fb) return -1;
|
||||
|
||||
output->prep.fb = fb;
|
||||
|
||||
if (_ecore_drm2_use_atomic)
|
||||
ret = _fb_atomic_flip(output);
|
||||
else
|
||||
ret = _fb_flip(output);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if (output->prep.fb != output->current.fb)
|
||||
_ecore_drm2_fb_buffer_release(output, &output->prep);
|
||||
return ret;
|
||||
}
|
||||
output->pending.fb = output->prep.fb;
|
||||
output->prep.fb = NULL;
|
||||
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
output->pending.atomic_req = output->prep.atomic_req;
|
||||
output->prep.atomic_req = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_fb_busy_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, EINA_FALSE);
|
||||
|
||||
return !!(fb->ref - 1);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_fb_release(Ecore_Drm2_Output *o, Eina_Bool panic)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(o, EINA_FALSE);
|
||||
|
||||
if (o->next.fb)
|
||||
{
|
||||
_ecore_drm2_fb_buffer_release(o, &o->next);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
if (!panic) return EINA_FALSE;
|
||||
|
||||
/* This has been demoted to DBG from WRN because we
|
||||
* call this function to reclaim all buffers on a
|
||||
* surface resize.
|
||||
*/
|
||||
DBG("Buffer release request when no next buffer");
|
||||
/* If we have to release these we're going to see tearing.
|
||||
* Try to reclaim in decreasing order of visual awfulness
|
||||
*/
|
||||
if (o->current.fb)
|
||||
{
|
||||
_ecore_drm2_fb_buffer_release(o, &o->current);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
if (o->pending.fb)
|
||||
{
|
||||
_ecore_drm2_fb_buffer_release(o, &o->pending);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
ecore_drm2_fb_bo_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(fb->dead, NULL);
|
||||
|
||||
return fb->gbm_bo;
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Fb *
|
||||
ecore_drm2_fb_dmabuf_import(Ecore_Drm2_Device *dev, int width, int height, int depth, int bpp, unsigned int format, unsigned int strides[4], int dmabuf_fd[4], int dmabuf_fd_count)
|
||||
{
|
||||
int i;
|
||||
Ecore_Drm2_Fb *fb;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL);
|
||||
|
||||
fb = calloc(1, sizeof(Ecore_Drm2_Fb));
|
||||
if (!fb) return NULL;
|
||||
|
||||
for (i = 0; i < dmabuf_fd_count; i++)
|
||||
if (sym_drmPrimeFDToHandle(dev->fd, dmabuf_fd[i], &fb->handles[i]))
|
||||
goto fail;
|
||||
|
||||
fb->dmabuf = EINA_TRUE;
|
||||
fb->fd = dev->fd;
|
||||
fb->w = width;
|
||||
fb->h = height;
|
||||
fb->bpp = bpp;
|
||||
fb->depth = depth;
|
||||
fb->format = format;
|
||||
fb->ref = 1;
|
||||
|
||||
memcpy(&fb->strides, strides, sizeof(fb->strides));
|
||||
if (_fb2_create(fb)) return fb;
|
||||
|
||||
fail:
|
||||
free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_fb_status_handler_set(Ecore_Drm2_Fb *fb, Ecore_Drm2_Fb_Status_Handler handler, void *data)
|
||||
{
|
||||
fb->status_handler = handler;
|
||||
fb->status_data = data;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,203 +0,0 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
static Eina_Bool
|
||||
_plane_format_supported(Ecore_Drm2_Plane_State *pstate, uint32_t format)
|
||||
{
|
||||
Eina_Bool ret = EINA_FALSE;
|
||||
unsigned int i = 0;
|
||||
|
||||
for (; i < pstate->num_formats; i++)
|
||||
{
|
||||
if (pstate->formats[i] == format)
|
||||
{
|
||||
ret = EINA_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
_plane_cursor_size_get(int fd, int *width, int *height)
|
||||
{
|
||||
uint64_t caps;
|
||||
int ret;
|
||||
|
||||
if (width)
|
||||
{
|
||||
*width = 64;
|
||||
ret = sym_drmGetCap(fd, DRM_CAP_CURSOR_WIDTH, &caps);
|
||||
if (ret == 0) *width = caps;
|
||||
}
|
||||
if (height)
|
||||
{
|
||||
*height = 64;
|
||||
ret = sym_drmGetCap(fd, DRM_CAP_CURSOR_HEIGHT, &caps);
|
||||
if (ret == 0) *height = caps;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Plane *
|
||||
ecore_drm2_plane_assign(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb, int x, int y)
|
||||
{
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Plane *plane;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
|
||||
if (!_ecore_drm2_use_atomic) return NULL;
|
||||
|
||||
/* use algo based on format, size, etc to find a plane this FB can go in */
|
||||
EINA_LIST_FOREACH(output->plane_states, l, pstate)
|
||||
{
|
||||
if (pstate->in_use)
|
||||
continue;
|
||||
|
||||
/* test if this plane supports the given format */
|
||||
if (!_plane_format_supported(pstate, fb->format))
|
||||
continue;
|
||||
|
||||
if (pstate->type.value == DRM_PLANE_TYPE_CURSOR)
|
||||
{
|
||||
int cw, ch;
|
||||
|
||||
_plane_cursor_size_get(output->fd, &cw, &ch);
|
||||
|
||||
/* check that this fb can fit in cursor plane */
|
||||
if ((fb->w != cw) || (fb->h != ch))
|
||||
continue;
|
||||
|
||||
/* if we reach here, this FB can go on the cursor plane */
|
||||
goto out;
|
||||
}
|
||||
else if (pstate->type.value == DRM_PLANE_TYPE_OVERLAY)
|
||||
{
|
||||
/* there are no size checks for an overlay plane */
|
||||
goto out;
|
||||
}
|
||||
else if (pstate->type.value == DRM_PLANE_TYPE_PRIMARY)
|
||||
{
|
||||
if ((fb->w > output->current_mode->width) ||
|
||||
(fb->h > output->current_mode->height))
|
||||
continue;
|
||||
|
||||
/* if we reach here, this FB can go on the primary plane */
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
out:
|
||||
/* create plane */
|
||||
plane = calloc(1, sizeof(Ecore_Drm2_Plane));
|
||||
if (!plane) return NULL;
|
||||
|
||||
pstate->in_use = EINA_TRUE;
|
||||
pstate->cid.value = output->crtc_id;
|
||||
pstate->fid.value = fb->id;
|
||||
plane->fb = fb;
|
||||
|
||||
pstate->sx.value = 0;
|
||||
pstate->sy.value = 0;
|
||||
pstate->sw.value = fb->w << 16;
|
||||
pstate->sh.value = fb->h << 16;
|
||||
|
||||
pstate->cx.value = x;
|
||||
pstate->cy.value = y;
|
||||
pstate->cw.value = fb->w;
|
||||
pstate->ch.value = fb->h;
|
||||
|
||||
plane->state = pstate;
|
||||
plane->type = pstate->type.value;
|
||||
plane->output = output;
|
||||
|
||||
output->planes = eina_list_append(output->planes, plane);
|
||||
|
||||
if (!_fb_atomic_flip_test(output))
|
||||
{
|
||||
output->planes = eina_list_remove(output->planes, plane);
|
||||
plane->state->in_use = EINA_FALSE;
|
||||
free(plane);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_ecore_drm2_fb_ref(fb);
|
||||
DBG("FB %d assigned to Plane %d", fb->id, pstate->obj_id);
|
||||
|
||||
if (fb->status_handler)
|
||||
fb->status_handler(fb,
|
||||
ECORE_DRM2_FB_STATUS_PLANE_ASSIGN,
|
||||
fb->status_data);
|
||||
return plane;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_plane_release(Ecore_Drm2_Plane *plane)
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(plane);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(plane->dead);
|
||||
|
||||
fb = plane->fb;
|
||||
|
||||
plane->output->fbs =
|
||||
eina_list_append(plane->output->fbs, fb);
|
||||
|
||||
plane->dead = EINA_TRUE;
|
||||
plane->state->in_use = EINA_FALSE;
|
||||
_fb_atomic_flip_test(plane->output);
|
||||
|
||||
if (fb->status_handler)
|
||||
fb->status_handler(fb,
|
||||
ECORE_DRM2_FB_STATUS_PLANE_RELEASE,
|
||||
fb->status_data);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_drm2_plane_destination_set(Ecore_Drm2_Plane *plane, int x, int y, int w, int h)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(plane);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(plane->dead);
|
||||
|
||||
plane->state->cx.value = x;
|
||||
plane->state->cy.value = y;
|
||||
plane->state->cw.value = w;
|
||||
plane->state->ch.value = h;
|
||||
|
||||
_fb_atomic_flip_test(plane->output);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_plane_fb_set(Ecore_Drm2_Plane *plane, Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
uint32_t fallback_id;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(plane, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(plane->dead, EINA_FALSE);
|
||||
|
||||
fallback_id = plane->state->fid.value;
|
||||
plane->state->fid.value = fb->id;
|
||||
|
||||
/* Update plane state based on fb */
|
||||
plane->state->sw.value = fb->w << 16;
|
||||
plane->state->sh.value = fb->h << 16;
|
||||
plane->state->cw.value = fb->w;
|
||||
plane->state->ch.value = fb->h;
|
||||
|
||||
if (_fb_atomic_flip_test(plane->output))
|
||||
{
|
||||
_ecore_drm2_fb_ref(fb);
|
||||
|
||||
plane->output->fbs =
|
||||
eina_list_append(plane->output->fbs, plane->fb);
|
||||
|
||||
plane->fb = fb;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
plane->state->fid.value = fallback_id;
|
||||
return EINA_FALSE;
|
||||
}
|
|
@ -5,30 +5,31 @@
|
|||
# include "config.h"
|
||||
# endif
|
||||
|
||||
# include "Ecore.h"
|
||||
# include "ecore_private.h"
|
||||
# include "Eeze.h"
|
||||
# include "Elput.h"
|
||||
# include <Ecore_Drm2.h>
|
||||
|
||||
/* include system headers */
|
||||
# include <unistd.h>
|
||||
# include <strings.h>
|
||||
# include <sys/mman.h>
|
||||
# include <fcntl.h>
|
||||
# include <ctype.h>
|
||||
|
||||
# include <sys/ioctl.h>
|
||||
# include <dlfcn.h>
|
||||
|
||||
/* include drm headers */
|
||||
# include <drm.h>
|
||||
# include <drm_mode.h>
|
||||
# include <drm_fourcc.h>
|
||||
# include <xf86drm.h>
|
||||
# include <xf86drmMode.h>
|
||||
|
||||
#ifndef DRM2_NODEFS
|
||||
/* include needed EFL headers */
|
||||
# include "Ecore.h"
|
||||
# include "ecore_private.h"
|
||||
# include "Eeze.h"
|
||||
# include "Elput.h"
|
||||
# include <Ecore_Drm2.h>
|
||||
|
||||
/* define necessary vars/macros for ecore_drm2 log domain */
|
||||
extern int _ecore_drm2_log_dom;
|
||||
extern Eina_Bool _ecore_drm2_use_atomic;
|
||||
|
||||
# ifdef ECORE_DRM2_DEFAULT_LOG_COLOR
|
||||
# undef ECORE_DRM2_DEFAULT_LOG_COLOR
|
||||
|
@ -59,298 +60,5 @@ extern Eina_Bool _ecore_drm2_use_atomic;
|
|||
# undef CRIT
|
||||
# endif
|
||||
# define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_drm2_log_dom, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
typedef struct _Ecore_Drm2_Atomic_State Ecore_Drm2_Atomic_State;
|
||||
|
||||
typedef struct _Ecore_Drm2_Atomic_Blob
|
||||
{
|
||||
uint32_t id, value;
|
||||
size_t len;
|
||||
void *data;
|
||||
} Ecore_Drm2_Atomic_Blob;
|
||||
|
||||
typedef struct _Ecore_Drm2_Atomic_Property
|
||||
{
|
||||
uint32_t id;
|
||||
uint64_t value;
|
||||
} Ecore_Drm2_Atomic_Property;
|
||||
|
||||
typedef struct _Ecore_Drm2_Connector_State
|
||||
{
|
||||
uint32_t obj_id;
|
||||
Ecore_Drm2_Atomic_Property crtc;
|
||||
Ecore_Drm2_Atomic_Property dpms;
|
||||
Ecore_Drm2_Atomic_Property aspect;
|
||||
Ecore_Drm2_Atomic_Property scaling;
|
||||
Ecore_Drm2_Atomic_Blob edid;
|
||||
} Ecore_Drm2_Connector_State;
|
||||
|
||||
typedef struct _Ecore_Drm2_Crtc_State
|
||||
{
|
||||
uint32_t obj_id;
|
||||
int index;
|
||||
Ecore_Drm2_Atomic_Property active;
|
||||
Ecore_Drm2_Atomic_Property background;
|
||||
Ecore_Drm2_Atomic_Blob mode;
|
||||
} Ecore_Drm2_Crtc_State;
|
||||
|
||||
typedef struct _Ecore_Drm2_Plane_State
|
||||
{
|
||||
uint32_t obj_id, mask;
|
||||
Ecore_Drm2_Atomic_Property type;
|
||||
Ecore_Drm2_Atomic_Property cid, fid;
|
||||
Ecore_Drm2_Atomic_Property sx, sy, sw, sh;
|
||||
Ecore_Drm2_Atomic_Property cx, cy, cw, ch;
|
||||
Ecore_Drm2_Atomic_Property rotation;
|
||||
|
||||
/* these are not part of an atomic state, but we store these here
|
||||
* so that we do not have to refetch properties when iterating planes */
|
||||
uint32_t rotation_map[6];
|
||||
uint32_t supported_rotations;
|
||||
|
||||
uint32_t num_formats;
|
||||
uint32_t *formats;
|
||||
|
||||
Eina_Bool in_use;
|
||||
} Ecore_Drm2_Plane_State;
|
||||
|
||||
struct _Ecore_Drm2_Atomic_State
|
||||
{
|
||||
int crtcs, conns, planes;
|
||||
Ecore_Drm2_Crtc_State *crtc_states;
|
||||
Ecore_Drm2_Connector_State *conn_states;
|
||||
Ecore_Drm2_Plane_State *plane_states;
|
||||
};
|
||||
|
||||
# ifndef DRM_CAP_CURSOR_WIDTH
|
||||
# define DRM_CAP_CURSOR_WIDTH 0x8
|
||||
# endif
|
||||
|
||||
# ifndef DRM_CAP_CURSOR_HEIGHT
|
||||
# define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||
# endif
|
||||
|
||||
typedef enum _Ecore_Drm2_Backlight_Type
|
||||
{
|
||||
ECORE_DRM2_BACKLIGHT_RAW,
|
||||
ECORE_DRM2_BACKLIGHT_PLATFORM,
|
||||
ECORE_DRM2_BACKLIGHT_FIRMWARE
|
||||
} Ecore_Drm2_Backlight_Type;
|
||||
|
||||
typedef enum _Ecore_Drm2_Transform
|
||||
{
|
||||
ECORE_DRM2_TRANSFORM_NORMAL,
|
||||
ECORE_DRM2_TRANSFORM_90,
|
||||
ECORE_DRM2_TRANSFORM_180,
|
||||
ECORE_DRM2_TRANSFORM_270,
|
||||
ECORE_DRM2_TRANSFORM_FLIPPED,
|
||||
ECORE_DRM2_TRANSFORM_FLIPPED_90,
|
||||
ECORE_DRM2_TRANSFORM_FLIPPED_180,
|
||||
ECORE_DRM2_TRANSFORM_FLIPPED_270
|
||||
} Ecore_Drm2_Transform;
|
||||
|
||||
struct _Ecore_Drm2_Fb
|
||||
{
|
||||
int fd;
|
||||
int w, h;
|
||||
int depth, bpp;
|
||||
short ref;
|
||||
int scanout_count;
|
||||
uint32_t id, handles[4];
|
||||
uint32_t strides[4], sizes[4];
|
||||
uint32_t format;
|
||||
|
||||
void *gbm_bo;
|
||||
void *mmap;
|
||||
|
||||
Ecore_Drm2_Fb_Status_Handler status_handler;
|
||||
void *status_data;
|
||||
|
||||
Eina_Bool gbm : 1;
|
||||
Eina_Bool dmabuf : 1;
|
||||
Eina_Bool dead : 1;
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Plane
|
||||
{
|
||||
int type;
|
||||
Ecore_Drm2_Plane_State *state;
|
||||
Ecore_Drm2_Output *output;
|
||||
Ecore_Drm2_Fb *fb;
|
||||
Eina_Bool dead;
|
||||
Eina_Bool scanout;
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Output_Mode
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t flags;
|
||||
int32_t width, height;
|
||||
uint32_t refresh;
|
||||
drmModeModeInfo info;
|
||||
};
|
||||
|
||||
/* A half step - we still keep an fb for the canvas
|
||||
* and an atomic_req for all atomic state (including
|
||||
* the canvas fb).
|
||||
* The non atomic code only uses the canvas fb.
|
||||
*/
|
||||
typedef struct _Ecore_Drm2_Output_State
|
||||
{
|
||||
Ecore_Drm2_Fb *fb;
|
||||
drmModeAtomicReq *atomic_req;
|
||||
} Ecore_Drm2_Output_State;
|
||||
|
||||
struct _Ecore_Drm2_Output
|
||||
{
|
||||
Eina_Stringshare *name;
|
||||
Eina_Stringshare *make, *model, *serial;
|
||||
|
||||
int fd;
|
||||
int pipe;
|
||||
int x, y, w, h, pw, ph;
|
||||
int rotation;
|
||||
|
||||
long fallback_sec, fallback_usec;
|
||||
|
||||
uint32_t subpixel;
|
||||
uint32_t crtc_id, conn_id, conn_type;
|
||||
uint32_t scale;
|
||||
uint16_t gamma;
|
||||
|
||||
struct
|
||||
{
|
||||
char eisa[13];
|
||||
char monitor[13];
|
||||
char pnp[5];
|
||||
char serial[13];
|
||||
unsigned char *blob; // unused when doing atomic
|
||||
} edid;
|
||||
|
||||
struct
|
||||
{
|
||||
const char *path;
|
||||
double value, max;
|
||||
Ecore_Drm2_Backlight_Type type;
|
||||
} backlight;
|
||||
|
||||
struct
|
||||
{
|
||||
const char *to;
|
||||
Ecore_Drm2_Relative_Mode mode;
|
||||
} relative;
|
||||
|
||||
drmModeCrtcPtr ocrtc;
|
||||
|
||||
/* prep is for state we're preparing and have never
|
||||
* attempted to commit */
|
||||
Ecore_Drm2_Output_State prep;
|
||||
|
||||
Ecore_Drm2_Output_State current, next, pending;
|
||||
|
||||
Eina_Matrix4 matrix, inverse;
|
||||
Ecore_Drm2_Transform transform;
|
||||
|
||||
/* unused when doing atomic */
|
||||
drmModePropertyPtr dpms;
|
||||
|
||||
Ecore_Timer *flip_timeout;
|
||||
|
||||
Ecore_Drm2_Output_Mode *current_mode;
|
||||
Eina_List *modes;
|
||||
|
||||
void *user_data;
|
||||
|
||||
Ecore_Drm2_Crtc_State *crtc_state;
|
||||
Ecore_Drm2_Connector_State *conn_state;
|
||||
|
||||
Eina_List *plane_states;
|
||||
Eina_List *planes;
|
||||
Eina_List *fbs;
|
||||
|
||||
Eina_Bool connected : 1;
|
||||
Eina_Bool primary : 1;
|
||||
Eina_Bool cloned : 1;
|
||||
Eina_Bool enabled : 1;
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Device
|
||||
{
|
||||
Elput_Manager *em;
|
||||
|
||||
int fd;
|
||||
const char *path;
|
||||
|
||||
int num_crtcs;
|
||||
uint32_t *crtcs;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t width, height;
|
||||
} min, max;
|
||||
|
||||
struct
|
||||
{
|
||||
int width, height;
|
||||
} cursor;
|
||||
|
||||
Eeze_Udev_Watch *watch;
|
||||
Ecore_Event_Handler *active_hdlr;
|
||||
Ecore_Event_Handler *device_change_hdlr;
|
||||
|
||||
Ecore_Drm2_Atomic_State *state;
|
||||
|
||||
Eina_List *outputs;
|
||||
};
|
||||
|
||||
Eina_Bool _fb_atomic_flip_test(Ecore_Drm2_Output *output);
|
||||
void _ecore_drm2_fb_ref(Ecore_Drm2_Fb *);
|
||||
void _ecore_drm2_fb_deref(Ecore_Drm2_Fb *);
|
||||
void _ecore_drm2_fb_buffer_release(Ecore_Drm2_Output *output, Ecore_Drm2_Output_State *s);
|
||||
|
||||
/* extern int (*sym_drmClose)(int fd); */
|
||||
extern int (*sym_drmWaitVBlank)(int fd, drmVBlank *vbl);
|
||||
extern int (*sym_drmHandleEvent)(int fd, drmEventContext *evctx);
|
||||
extern void *(*sym_drmGetVersion)(int fd);
|
||||
extern void (*sym_drmFreeVersion)(void *drmver);
|
||||
extern void *(*sym_drmModeGetProperty)(int fd, uint32_t propertyId);
|
||||
extern void (*sym_drmModeFreeProperty)(drmModePropertyPtr ptr);
|
||||
extern void *(*sym_drmModeGetPropertyBlob)(int fd, uint32_t blob_id);
|
||||
extern void (*sym_drmModeFreePropertyBlob)(drmModePropertyBlobPtr ptr);
|
||||
extern int (*sym_drmModeDestroyPropertyBlob)(int fd, uint32_t id);
|
||||
extern int (*sym_drmIoctl)(int fd, unsigned long request, void *arg);
|
||||
extern void *(*sym_drmModeObjectGetProperties)(int fd, uint32_t object_id, uint32_t object_type);
|
||||
extern void (*sym_drmModeFreeObjectProperties)(drmModeObjectPropertiesPtr ptr);
|
||||
extern int (*sym_drmModeCreatePropertyBlob)(int fd, const void *data, size_t size, uint32_t *id);
|
||||
extern void *(*sym_drmModeAtomicAlloc)(void);
|
||||
extern void (*sym_drmModeAtomicFree)(drmModeAtomicReqPtr req);
|
||||
extern int (*sym_drmModeAtomicAddProperty)(drmModeAtomicReqPtr req, uint32_t object_id, uint32_t property_id, uint64_t value);
|
||||
extern int (*sym_drmModeAtomicCommit)(int fd, drmModeAtomicReqPtr req, uint32_t flags, void *user_data);
|
||||
extern void (*sym_drmModeAtomicSetCursor)(drmModeAtomicReqPtr req, int cursor);
|
||||
extern int (*sym_drmModeAtomicMerge)(drmModeAtomicReqPtr base, drmModeAtomicReqPtr augment);
|
||||
extern void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id);
|
||||
extern void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr);
|
||||
extern void *(*sym_drmModeGetCrtc)(int fd, uint32_t crtcId);
|
||||
extern void (*sym_drmModeFreeCrtc)(drmModeCrtcPtr ptr);
|
||||
extern int (*sym_drmModeSetCrtc)(int fd, uint32_t crtcId, uint32_t bufferId, uint32_t x, uint32_t y, uint32_t *connectors, int count, drmModeModeInfoPtr mode);
|
||||
extern void *(*sym_drmModeGetResources)(int fd);
|
||||
extern void (*sym_drmModeFreeResources)(drmModeResPtr ptr);
|
||||
extern void *(*sym_drmModeGetConnector)(int fd, uint32_t connectorId);
|
||||
extern void (*sym_drmModeFreeConnector)(drmModeConnectorPtr ptr);
|
||||
extern int (*sym_drmModeConnectorSetProperty)(int fd, uint32_t connector_id, uint32_t property_id, uint64_t value);
|
||||
extern int (*sym_drmGetCap)(int fd, uint64_t capability, uint64_t *value);
|
||||
extern int (*sym_drmSetClientCap)(int fd, uint64_t capability, uint64_t value);
|
||||
extern void *(*sym_drmModeGetPlaneResources)(int fd);
|
||||
extern void (*sym_drmModeFreePlaneResources)(drmModePlaneResPtr ptr);
|
||||
extern void *(*sym_drmModeGetPlane)(int fd, uint32_t plane_id);
|
||||
extern void (*sym_drmModeFreePlane)(drmModePlanePtr ptr);
|
||||
extern int (*sym_drmModeAddFB)(int fd, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint32_t *buf_id);
|
||||
extern int (*sym_drmModeAddFB2)(int fd, uint32_t width, uint32_t height, uint32_t pixel_format, uint32_t bo_handles[4], uint32_t pitches[4], uint32_t offsets[4], uint32_t *buf_id, uint32_t flags);
|
||||
extern int (*sym_drmModeRmFB)(int fd, uint32_t bufferId);
|
||||
extern int (*sym_drmModePageFlip)(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data);
|
||||
extern int (*sym_drmModeDirtyFB)(int fd, uint32_t bufferId, drmModeClipPtr clips, uint32_t num_clips);
|
||||
extern int (*sym_drmModeCrtcSetGamma)(int fd, uint32_t crtc_id, uint32_t size, uint16_t *red, uint16_t *green, uint16_t *blue);
|
||||
extern int (*sym_drmPrimeFDToHandle)(int fd, int prime_fd, uint32_t *handle);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,10 +7,6 @@ ecore_drm2_header_src = [
|
|||
]
|
||||
|
||||
ecore_drm2_src = files([
|
||||
'ecore_drm2_plane.c',
|
||||
'ecore_drm2_fb.c',
|
||||
'ecore_drm2_outputs.c',
|
||||
'ecore_drm2_device.c',
|
||||
'ecore_drm2.c',
|
||||
'ecore_drm2_private.h'
|
||||
])
|
||||
|
|
Loading…
Reference in New Issue