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"
|
#include "ecore_drm2_private.h"
|
||||||
|
|
||||||
|
/* local variables */
|
||||||
static int _ecore_drm2_init_count = 0;
|
static int _ecore_drm2_init_count = 0;
|
||||||
static void *drm_lib = NULL;
|
|
||||||
|
|
||||||
|
/* external variables */
|
||||||
int _ecore_drm2_log_dom = -1;
|
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
|
EAPI int
|
||||||
ecore_drm2_init(void)
|
ecore_drm2_init(void)
|
||||||
{
|
{
|
||||||
|
@ -171,16 +39,8 @@ ecore_drm2_init(void)
|
||||||
goto log_err;
|
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;
|
return _ecore_drm2_init_count;
|
||||||
|
|
||||||
link_err:
|
|
||||||
eina_log_domain_unregister(_ecore_drm2_log_dom);
|
|
||||||
_ecore_drm2_log_dom = -1;
|
|
||||||
log_err:
|
log_err:
|
||||||
elput_shutdown();
|
elput_shutdown();
|
||||||
elput_err:
|
elput_err:
|
||||||
|
@ -204,9 +64,6 @@ ecore_drm2_shutdown(void)
|
||||||
|
|
||||||
if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count;
|
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);
|
eina_log_domain_unregister(_ecore_drm2_log_dom);
|
||||||
_ecore_drm2_log_dom = -1;
|
_ecore_drm2_log_dom = -1;
|
||||||
|
|
||||||
|
@ -217,18 +74,3 @@ ecore_drm2_shutdown(void)
|
||||||
|
|
||||||
return _ecore_drm2_init_count;
|
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"
|
# include "config.h"
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# include "Ecore.h"
|
/* include system headers */
|
||||||
# include "ecore_private.h"
|
|
||||||
# include "Eeze.h"
|
|
||||||
# include "Elput.h"
|
|
||||||
# include <Ecore_Drm2.h>
|
|
||||||
|
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <strings.h>
|
# include <strings.h>
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
|
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
|
|
||||||
|
/* include drm headers */
|
||||||
# include <drm.h>
|
# include <drm.h>
|
||||||
# include <drm_mode.h>
|
# include <drm_mode.h>
|
||||||
# include <drm_fourcc.h>
|
# include <drm_fourcc.h>
|
||||||
# include <xf86drm.h>
|
# include <xf86drm.h>
|
||||||
# include <xf86drmMode.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 int _ecore_drm2_log_dom;
|
||||||
extern Eina_Bool _ecore_drm2_use_atomic;
|
|
||||||
|
|
||||||
# ifdef ECORE_DRM2_DEFAULT_LOG_COLOR
|
# ifdef ECORE_DRM2_DEFAULT_LOG_COLOR
|
||||||
# undef ECORE_DRM2_DEFAULT_LOG_COLOR
|
# undef ECORE_DRM2_DEFAULT_LOG_COLOR
|
||||||
|
@ -59,298 +60,5 @@ extern Eina_Bool _ecore_drm2_use_atomic;
|
||||||
# undef CRIT
|
# undef CRIT
|
||||||
# endif
|
# endif
|
||||||
# define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_drm2_log_dom, __VA_ARGS__)
|
# 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
|
#endif
|
||||||
|
|
|
@ -7,10 +7,6 @@ ecore_drm2_header_src = [
|
||||||
]
|
]
|
||||||
|
|
||||||
ecore_drm2_src = files([
|
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.c',
|
||||||
'ecore_drm2_private.h'
|
'ecore_drm2_private.h'
|
||||||
])
|
])
|
||||||
|
|
Loading…
Reference in New Issue