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:
Christopher Michael 2022-08-16 09:31:44 -04:00
parent bcd0ae0b83
commit 1e6df64525
8 changed files with 14 additions and 5364 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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(){};

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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'
])