forked from enlightenment/efl
ecore-drm2: Add support for putting dmabuf clients into hardware planes
Small patch set which adds necessary API functions that we can use in order to allow placing dmabuf clients into a hardware plane based on supported format, size, etc. Merge branch 'devs/devilhorns/planes'
This commit is contained in:
commit
2badf1e706
|
@ -9,6 +9,7 @@ dist_installed_ecoredrm2mainheaders_DATA = \
|
|||
lib/ecore_drm2/Ecore_Drm2.h
|
||||
|
||||
lib_ecore_drm2_libecore_drm2_la_SOURCES = \
|
||||
lib/ecore_drm2/ecore_drm2_plane.c \
|
||||
lib/ecore_drm2/ecore_drm2_fb.c \
|
||||
lib/ecore_drm2/ecore_drm2_outputs.c \
|
||||
lib/ecore_drm2/ecore_drm2_device.c \
|
||||
|
|
|
@ -49,6 +49,9 @@ typedef struct _Ecore_Drm2_Output Ecore_Drm2_Output;
|
|||
/* opaque structure to represent an output mode */
|
||||
typedef struct _Ecore_Drm2_Output_Mode Ecore_Drm2_Output_Mode;
|
||||
|
||||
/* opaque structure to represent a hardware plane */
|
||||
typedef struct _Ecore_Drm2_Plane Ecore_Drm2_Plane;
|
||||
|
||||
/* structure to represent event for output changes */
|
||||
typedef struct _Ecore_Drm2_Event_Output_Changed
|
||||
{
|
||||
|
@ -96,6 +99,7 @@ typedef void (*Ecore_Drm2_Release_Handler)(void *data, Ecore_Drm2_Fb *b);
|
|||
* @li @ref Ecore_Drm2_Device_Group
|
||||
* @li @ref Ecore_Drm2_Output_Group
|
||||
* @li @ref Ecore_Drm2_Fb_Group
|
||||
* @li @ref Ecore_Drm2_Plane_Group
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -366,6 +370,12 @@ EAPI Eina_Bool ecore_drm2_device_vt_set(Ecore_Drm2_Device *device, int vt);
|
|||
*/
|
||||
EAPI Eina_Bool ecore_drm2_device_prefer_shadow(Ecore_Drm2_Device *device);
|
||||
|
||||
/* TODO: doxy */
|
||||
EAPI Eina_Bool ecore_drm2_atomic_commit_test(Ecore_Drm2_Device *device);
|
||||
|
||||
/* TODO: doxy */
|
||||
EAPI Eina_Bool ecore_drm2_atomic_commit(Ecore_Drm2_Device *device);
|
||||
|
||||
/**
|
||||
* @defgroup Ecore_Drm2_Output_Group Drm output functions
|
||||
*
|
||||
|
@ -964,6 +974,60 @@ EAPI void ecore_drm2_output_release_handler_set(Ecore_Drm2_Output *output, Ecore
|
|||
*/
|
||||
EAPI void *ecore_drm2_fb_bo_get(Ecore_Drm2_Fb *fb);
|
||||
|
||||
/**
|
||||
* Import a dmabuf object as a Framebuffer
|
||||
*
|
||||
* @param fd
|
||||
* @param width
|
||||
* @param height
|
||||
* @param depth
|
||||
* @param bpp
|
||||
* @param format
|
||||
* @param stride
|
||||
* @param dmabuf_fd
|
||||
* @param dmabuf_fd_count
|
||||
*
|
||||
* @return A newly created framebuffer object, or NULL on failure
|
||||
*
|
||||
* @ingroup Ecore_Drm2_Fb_Group
|
||||
* @since 1.20
|
||||
*
|
||||
*/
|
||||
EAPI Ecore_Drm2_Fb *ecore_drm2_fb_dmabuf_import(int fd, int width, int height, int depth, int bpp, unsigned int format, unsigned int strides[4], int dmabuf_fd[4], int dmabuf_fd_count);
|
||||
|
||||
/**
|
||||
* @defgroup Ecore_Drm2_Plane_Group Functions that deal with hardware planes
|
||||
*
|
||||
* Functions that deal with hardware plane manipulation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Find a hardware plane where a given Ecore_Drm2_Fb can go based on format and size
|
||||
*
|
||||
* @param output
|
||||
* @param fb
|
||||
*
|
||||
* @return A newly allocated plane object, or NULL otherwise
|
||||
*
|
||||
* @ingroup Ecore_Drm2_Plane_Group
|
||||
* @since 1.20
|
||||
*/
|
||||
EAPI Ecore_Drm2_Plane *ecore_drm2_plane_assign(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb);
|
||||
|
||||
/**
|
||||
* Set plane destination values
|
||||
*
|
||||
* @param plane
|
||||
* @param x
|
||||
* @param y
|
||||
* @param w
|
||||
* @param h
|
||||
*
|
||||
* @ingroup Ecore_Drm2_Plane_Group
|
||||
* @since 1.20
|
||||
*/
|
||||
EAPI void ecore_drm2_plane_destination_set(Ecore_Drm2_Plane *plane, int x, int y, int w, int h);
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@ 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);
|
||||
# endif
|
||||
void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id) = NULL;
|
||||
void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr) = NULL;
|
||||
|
@ -41,10 +42,12 @@ 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;
|
||||
|
||||
EAPI int ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
|
||||
EAPI int ECORE_DRM2_EVENT_ACTIVATE = -1;
|
||||
|
@ -99,6 +102,7 @@ _ecore_drm2_link(void)
|
|||
SYM(drm_lib, drmModeAtomicAddProperty);
|
||||
SYM(drm_lib, drmModeAtomicCommit);
|
||||
SYM(drm_lib, drmModeAtomicSetCursor);
|
||||
SYM(drm_lib, drmModeAtomicMerge);
|
||||
#endif
|
||||
SYM(drm_lib, drmModeGetEncoder);
|
||||
SYM(drm_lib, drmModeFreeEncoder);
|
||||
|
@ -117,10 +121,12 @@ _ecore_drm2_link(void)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
#include "ecore_drm2_private.h"
|
||||
|
||||
#ifndef DRM_CAP_CURSOR_WIDTH
|
||||
# define DRM_CAP_CURSOR_WIDTH 0x8
|
||||
#endif
|
||||
|
||||
#ifndef DRM_CAP_CURSOR_HEIGHT
|
||||
# define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||
#endif
|
||||
|
||||
#ifndef DRM_CAP_DUMB_PREFER_SHADOW
|
||||
# define DRM_CAP_DUMB_PREFER_SHADOW 0x4
|
||||
#endif
|
||||
|
@ -16,7 +8,7 @@
|
|||
# include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
Eina_Bool _ecore_drm2_use_atomic = EINA_FALSE;
|
||||
Eina_Bool _ecore_drm2_use_atomic = EINA_TRUE;
|
||||
|
||||
static Eina_Bool
|
||||
_cb_session_active(void *data, int type EINA_UNUSED, void *event)
|
||||
|
@ -154,6 +146,8 @@ out:
|
|||
}
|
||||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
|
||||
# if 0
|
||||
static Eina_Bool
|
||||
_drm2_atomic_usable(int fd)
|
||||
{
|
||||
|
@ -195,6 +189,7 @@ _drm2_atomic_usable(int fd)
|
|||
|
||||
return ret;
|
||||
}
|
||||
# endif
|
||||
|
||||
static void
|
||||
_drm2_atomic_state_crtc_fill(Ecore_Drm2_Crtc_State *cstate, int fd)
|
||||
|
@ -543,6 +538,9 @@ _drm2_atomic_state_fill(Ecore_Drm2_Atomic_State *state, int fd)
|
|||
pstate = &state->plane_states[i];
|
||||
pstate->obj_id = pres->planes[i];
|
||||
pstate->mask = plane->possible_crtcs;
|
||||
pstate->num_formats = plane->count_formats;
|
||||
memcpy(pstate->formats, plane->formats,
|
||||
plane->count_formats * sizeof(plane->formats[0]));
|
||||
|
||||
sym_drmModeFreePlane(plane);
|
||||
|
||||
|
@ -615,9 +613,11 @@ ecore_drm2_device_open(Ecore_Drm2_Device *device)
|
|||
DBG("Device Fd: %d", device->fd);
|
||||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
# if 0
|
||||
/* check that this system can do atomic */
|
||||
_ecore_drm2_use_atomic = _drm2_atomic_usable(device->fd);
|
||||
if (_ecore_drm2_use_atomic)
|
||||
# endif
|
||||
{
|
||||
if (sym_drmSetClientCap(device->fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0)
|
||||
{
|
||||
|
@ -628,7 +628,10 @@ ecore_drm2_device_open(Ecore_Drm2_Device *device)
|
|||
{
|
||||
if (sym_drmSetClientCap(device->fd,
|
||||
DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0)
|
||||
WRN("Could not enable Universal Plane support");
|
||||
{
|
||||
WRN("Could not enable Universal Plane support");
|
||||
_ecore_drm2_use_atomic = EINA_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* atomic & planes are usable */
|
||||
|
@ -673,7 +676,11 @@ ecore_drm2_device_free(Ecore_Drm2_Device *device)
|
|||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
if (_ecore_drm2_use_atomic)
|
||||
_drm2_atomic_state_free(device->state);
|
||||
{
|
||||
_drm2_atomic_state_free(device->state);
|
||||
if (device->atomic_req)
|
||||
sym_drmModeAtomicFree(device->atomic_req);
|
||||
}
|
||||
#endif
|
||||
|
||||
ecore_event_handler_del(device->active_hdlr);
|
||||
|
@ -711,13 +718,21 @@ ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *he
|
|||
{
|
||||
*width = 64;
|
||||
ret = sym_drmGetCap(device->fd, DRM_CAP_CURSOR_WIDTH, &caps);
|
||||
if (ret == 0) *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) *height = caps;
|
||||
if (ret == 0)
|
||||
{
|
||||
device->cursor.height = caps;
|
||||
*height = caps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -837,3 +852,160 @@ ecore_drm2_device_prefer_shadow(Ecore_Drm2_Device *device)
|
|||
else
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_atomic_commit_test(Ecore_Drm2_Device *device)
|
||||
{
|
||||
Eina_Bool res = EINA_FALSE;
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
int ret = 0;
|
||||
Eina_List *l, *ll;
|
||||
Ecore_Drm2_Output *output;
|
||||
Ecore_Drm2_Plane *plane;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
Ecore_Drm2_Crtc_State *cstate;
|
||||
drmModeAtomicReq *req = NULL;
|
||||
uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET |
|
||||
DRM_MODE_ATOMIC_TEST_ONLY;
|
||||
#endif
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL((device->fd < 0), EINA_FALSE);
|
||||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
req = sym_drmModeAtomicAlloc();
|
||||
if (!req) return EINA_FALSE;
|
||||
|
||||
sym_drmModeAtomicSetCursor(req, 0);
|
||||
|
||||
EINA_LIST_FOREACH(device->outputs, l, output)
|
||||
{
|
||||
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;
|
||||
|
||||
EINA_LIST_FOREACH(output->planes, ll, plane)
|
||||
{
|
||||
pstate = plane->state;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ret =
|
||||
sym_drmModeAtomicCommit(device->fd, req, flags, NULL);
|
||||
if (ret < 0) ERR("Failed Atomic Commit Test: %m");
|
||||
else res = EINA_TRUE;
|
||||
|
||||
if (res)
|
||||
{
|
||||
if (device->atomic_req)
|
||||
{
|
||||
/* merge this test commit with previous */
|
||||
ret = sym_drmModeAtomicMerge(device->atomic_req, req);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* we failed to merge for some reason. */
|
||||
|
||||
/* clear any previous request */
|
||||
sym_drmModeAtomicFree(device->atomic_req);
|
||||
|
||||
/* just use the new request */
|
||||
device->atomic_req = req;
|
||||
}
|
||||
}
|
||||
else
|
||||
device->atomic_req = req;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
err:
|
||||
sym_drmModeAtomicFree(req);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_drm2_atomic_commit(Ecore_Drm2_Device *device)
|
||||
{
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
int res = 0;
|
||||
uint32_t flags =
|
||||
DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT |
|
||||
DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
#endif
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL((device->fd < 0), EINA_FALSE);
|
||||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
if (!device->atomic_req) return EINA_FALSE;
|
||||
|
||||
res =
|
||||
sym_drmModeAtomicCommit(device->fd, device->atomic_req, flags, NULL);
|
||||
if (res < 0)
|
||||
ERR("Failed Atomic Commit Test: %m");
|
||||
else
|
||||
return EINA_TRUE;
|
||||
#endif
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
|
|
@ -3,107 +3,18 @@
|
|||
static Eina_Bool
|
||||
_fb2_create(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
drm_mode_fb_cmd2 cmd;
|
||||
uint32_t hdls[4] = { 0 }, pitches[4] = { 0 }, offsets[4] = { 0 };
|
||||
uint64_t modifiers[4] = { 0 };
|
||||
uint32_t offsets[4] = { 0 };
|
||||
int r;
|
||||
|
||||
hdls[0] = fb->hdl;
|
||||
pitches[0] = fb->stride;
|
||||
offsets[0] = 0;
|
||||
modifiers[0] = 0;
|
||||
r = sym_drmModeAddFB2(fb->fd, fb->w, fb->h, fb->format, fb->handles,
|
||||
fb->strides, offsets, &fb->id, 0);
|
||||
|
||||
memset(&cmd, 0, sizeof(drm_mode_fb_cmd2));
|
||||
cmd.fb_id = 0;
|
||||
cmd.width = fb->w;
|
||||
cmd.height = fb->h;
|
||||
cmd.pixel_format = fb->format;
|
||||
cmd.flags = 0;
|
||||
memcpy(cmd.handles, hdls, 4 * sizeof(hdls[0]));
|
||||
memcpy(cmd.pitches, pitches, 4 * sizeof(pitches[0]));
|
||||
memcpy(cmd.offsets, offsets, 4 * sizeof(offsets[0]));
|
||||
memcpy(cmd.modifier, modifiers, 4 * sizeof(modifiers[0]));
|
||||
|
||||
if (sym_drmIoctl(fb->fd, DRM_IOCTL_MODE_ADDFB2, &cmd))
|
||||
if (r)
|
||||
return EINA_FALSE;
|
||||
|
||||
fb->id = cmd.fb_id;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
static int
|
||||
_fb_atomic_flip(Ecore_Drm2_Output *output, Ecore_Drm2_Plane_State *pstate, uint32_t flags)
|
||||
{
|
||||
int ret = 0;
|
||||
drmModeAtomicReq *req = NULL;
|
||||
Ecore_Drm2_Crtc_State *cstate;
|
||||
|
||||
req = sym_drmModeAtomicAlloc();
|
||||
if (!req) return -1;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
ret = sym_drmModeAtomicCommit(output->fd, req, flags, output->user_data);
|
||||
if (ret < 0) ERR("Failed to commit Atomic FB Flip: %m");
|
||||
else ret = 0;
|
||||
|
||||
err:
|
||||
sym_drmModeAtomicFree(req);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
EAPI Ecore_Drm2_Fb *
|
||||
ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned int format)
|
||||
{
|
||||
|
@ -133,15 +44,15 @@ ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned
|
|||
ret = sym_drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &carg);
|
||||
if (ret) goto err;
|
||||
|
||||
fb->hdl = carg.handle;
|
||||
fb->size = carg.size;
|
||||
fb->stride = carg.pitch;
|
||||
fb->handles[0] = carg.handle;
|
||||
fb->sizes[0] = carg.size;
|
||||
fb->strides[0] = carg.pitch;
|
||||
|
||||
if (!_fb2_create(fb))
|
||||
{
|
||||
ret =
|
||||
sym_drmModeAddFB(fd, width, height, depth, bpp,
|
||||
fb->stride, fb->hdl, &fb->id);
|
||||
fb->strides[0], fb->handles[0], &fb->id);
|
||||
if (ret)
|
||||
{
|
||||
ERR("Could not add framebuffer: %m");
|
||||
|
@ -150,7 +61,7 @@ ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned
|
|||
}
|
||||
|
||||
memset(&marg, 0, sizeof(drm_mode_map_dumb));
|
||||
marg.handle = fb->hdl;
|
||||
marg.handle = fb->handles[0];
|
||||
ret = sym_drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &marg);
|
||||
if (ret)
|
||||
{
|
||||
|
@ -158,7 +69,7 @@ ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned
|
|||
goto map_err;
|
||||
}
|
||||
|
||||
fb->mmap = mmap(NULL, fb->size, PROT_WRITE, MAP_SHARED, fd, marg.offset);
|
||||
fb->mmap = mmap(NULL, fb->sizes[0], PROT_WRITE, MAP_SHARED, fd, marg.offset);
|
||||
if (fb->mmap == MAP_FAILED)
|
||||
{
|
||||
ERR("Could not mmap framebuffer memory: %m");
|
||||
|
@ -171,7 +82,7 @@ map_err:
|
|||
sym_drmModeRmFB(fd, fb->id);
|
||||
add_err:
|
||||
memset(&darg, 0, sizeof(drm_mode_destroy_dumb));
|
||||
darg.handle = fb->hdl;
|
||||
darg.handle = fb->handles[0];
|
||||
sym_drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
|
||||
err:
|
||||
free(fb);
|
||||
|
@ -199,14 +110,14 @@ ecore_drm2_fb_gbm_create(int fd, int width, int height, int depth, int bpp, unsi
|
|||
fb->bpp = bpp;
|
||||
fb->depth = depth;
|
||||
fb->format = format;
|
||||
fb->stride = stride;
|
||||
fb->size = fb->stride * fb->h;
|
||||
fb->hdl = handle;
|
||||
fb->strides[0] = stride;
|
||||
fb->sizes[0] = fb->strides[0] * fb->h;
|
||||
fb->handles[0] = handle;
|
||||
|
||||
if (!_fb2_create(fb))
|
||||
{
|
||||
if (sym_drmModeAddFB(fd, width, height, depth, bpp,
|
||||
fb->stride, fb->hdl, &fb->id))
|
||||
fb->strides[0], fb->handles[0], &fb->id))
|
||||
{
|
||||
ERR("Could not add framebuffer: %m");
|
||||
goto err;
|
||||
|
@ -215,11 +126,11 @@ ecore_drm2_fb_gbm_create(int fd, int width, int height, int depth, int bpp, unsi
|
|||
|
||||
/* mmap it if we can so screenshots are easy */
|
||||
memset(&marg, 0, sizeof(drm_mode_map_dumb));
|
||||
marg.handle = fb->hdl;
|
||||
marg.handle = fb->handles[0];
|
||||
ret = sym_drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &marg);
|
||||
if (!ret)
|
||||
{
|
||||
fb->mmap = mmap(NULL, fb->size, PROT_WRITE, MAP_SHARED, fd, marg.offset);
|
||||
fb->mmap = mmap(NULL, fb->sizes[0], PROT_WRITE, MAP_SHARED, fd, marg.offset);
|
||||
if (fb->mmap == MAP_FAILED) fb->mmap = NULL;
|
||||
}
|
||||
return fb;
|
||||
|
@ -234,7 +145,7 @@ ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb)
|
|||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(fb);
|
||||
|
||||
if (fb->mmap) munmap(fb->mmap, fb->size);
|
||||
if (fb->mmap) munmap(fb->mmap, fb->sizes[0]);
|
||||
|
||||
if (fb->id) sym_drmModeRmFB(fb->fd, fb->id);
|
||||
|
||||
|
@ -243,7 +154,7 @@ ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb)
|
|||
drm_mode_destroy_dumb darg;
|
||||
|
||||
memset(&darg, 0, sizeof(drm_mode_destroy_dumb));
|
||||
darg.handle = fb->hdl;
|
||||
darg.handle = fb->handles[0];
|
||||
sym_drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
|
||||
}
|
||||
|
||||
|
@ -261,14 +172,14 @@ EAPI unsigned int
|
|||
ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
|
||||
return fb->size;
|
||||
return fb->sizes[0];
|
||||
}
|
||||
|
||||
EAPI unsigned int
|
||||
ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
|
||||
return fb->stride;
|
||||
return fb->strides[0];
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -320,6 +231,8 @@ ecore_drm2_fb_flip_complete(Ecore_Drm2_Output *output)
|
|||
EAPI int
|
||||
ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output)
|
||||
{
|
||||
Eina_Bool repeat;
|
||||
int count = 0;
|
||||
int ret = 0;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(output, -1);
|
||||
|
@ -348,136 +261,87 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output)
|
|||
/* If we don't have an fb to set by now, BAIL! */
|
||||
if (!fb) return -1;
|
||||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
if (_ecore_drm2_use_atomic)
|
||||
if ((!output->current) ||
|
||||
(output->current->strides[0] != fb->strides[0]))
|
||||
{
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
uint32_t flags =
|
||||
DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT |
|
||||
DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
|
||||
pstate = output->plane_state;
|
||||
|
||||
pstate->cid.value = output->crtc_id;
|
||||
pstate->fid.value = fb->id;
|
||||
|
||||
pstate->sx.value = 0;
|
||||
pstate->sy.value = 0;
|
||||
pstate->sw.value = fb->w << 16;
|
||||
pstate->sh.value = fb->h << 16;
|
||||
pstate->cx.value = output->x;
|
||||
pstate->cy.value = output->y;
|
||||
pstate->cw.value = output->current_mode->width;
|
||||
pstate->ch.value = output->current_mode->height;
|
||||
|
||||
ret = _fb_atomic_flip(output, pstate, flags);
|
||||
if ((ret < 0) && (errno != EBUSY))
|
||||
ret =
|
||||
sym_drmModeSetCrtc(fb->fd, output->crtc_id, fb->id,
|
||||
output->x, output->y, &output->conn_id, 1,
|
||||
&output->current_mode->info);
|
||||
if (ret)
|
||||
{
|
||||
ERR("Atomic Pageflip Failed for Crtc %u on Connector %u: %m",
|
||||
output->crtc_id, output->conn_id);
|
||||
ERR("Failed to set Mode %dx%d for Output %s: %m",
|
||||
output->current_mode->width, output->current_mode->height,
|
||||
output->name);
|
||||
return ret;
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
output->next = fb;
|
||||
if (output->next) output->next->busy = EINA_TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
output->pending = fb;
|
||||
output->pending->busy = EINA_TRUE;
|
||||
|
||||
return 0;
|
||||
if (output->current) _release_buffer(output, output->current);
|
||||
output->current = fb;
|
||||
output->current->busy = EINA_TRUE;
|
||||
output->next = 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 the the flip path to make sure
|
||||
* even this first set can cause a flip callback.
|
||||
*/
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
Eina_Bool repeat;
|
||||
int count = 0;
|
||||
|
||||
if ((!output->current) ||
|
||||
(output->current->stride != fb->stride))
|
||||
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->user_data);
|
||||
/* 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))
|
||||
{
|
||||
ret =
|
||||
sym_drmModeSetCrtc(fb->fd, output->crtc_id, fb->id,
|
||||
output->x, output->y, &output->conn_id, 1,
|
||||
&output->current_mode->info);
|
||||
if (ret)
|
||||
repeat = EINA_TRUE;
|
||||
if (count == 0 && !bugged_about_bug)
|
||||
{
|
||||
ERR("Failed to set Mode %dx%d for Output %s: %m",
|
||||
output->current_mode->width, output->current_mode->height,
|
||||
output->name);
|
||||
return ret;
|
||||
ERR("Pageflip fail - EBUSY from drmModePageFlip - "
|
||||
"This is either a kernel bug or an EFL one.");
|
||||
bugged_about_bug = EINA_TRUE;
|
||||
}
|
||||
|
||||
if (output->current) _release_buffer(output, output->current);
|
||||
output->current = fb;
|
||||
output->current->busy = EINA_TRUE;
|
||||
output->next = 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 the 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->user_data);
|
||||
/* 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))
|
||||
count++;
|
||||
if (count > 500)
|
||||
{
|
||||
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);
|
||||
ERR("Pageflip EBUSY for %i tries - give up", count);
|
||||
break;
|
||||
}
|
||||
usleep(100);
|
||||
}
|
||||
while (repeat);
|
||||
}
|
||||
while (repeat);
|
||||
|
||||
if ((ret == 0) && (count > 0))
|
||||
DBG("Pageflip finally succeeded after %i tries due to EBUSY", count);
|
||||
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;
|
||||
output->next->busy = EINA_TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
output->pending = fb;
|
||||
output->pending->busy = EINA_TRUE;
|
||||
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;
|
||||
output->next->busy = EINA_TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
output->pending = fb;
|
||||
output->pending->busy = EINA_TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
|
@ -538,3 +402,29 @@ ecore_drm2_fb_bo_get(Ecore_Drm2_Fb *fb)
|
|||
EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
|
||||
return fb->gbm_bo;
|
||||
}
|
||||
|
||||
EAPI Ecore_Drm2_Fb *
|
||||
ecore_drm2_fb_dmabuf_import(int fd, 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;
|
||||
|
||||
fb = calloc(1, sizeof(Ecore_Drm2_Fb));
|
||||
if (!fb) return NULL;
|
||||
|
||||
for (i = 0; i < dmabuf_fd_count; i++)
|
||||
if (sym_drmPrimeFDToHandle(fd, dmabuf_fd[i], &fb->handles[i])) goto fail;
|
||||
|
||||
fb->fd = fd;
|
||||
fb->w = width;
|
||||
fb->h = height;
|
||||
fb->bpp = bpp;
|
||||
fb->depth = depth;
|
||||
fb->format = format;
|
||||
memcpy(&fb->strides, strides, sizeof(fb->strides));
|
||||
if (_fb2_create(fb)) return fb;
|
||||
|
||||
fail:
|
||||
free(fb);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ _output_debug(Ecore_Drm2_Output *output, const drmModeConnector *conn)
|
|||
{
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Output_Mode *omode;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
|
||||
DBG("Created New Output At %d,%d", output->x, output->y);
|
||||
DBG("\tCrtc Pos: %d %d", output->ocrtc->x, output->ocrtc->y);
|
||||
|
@ -56,6 +57,14 @@ _output_debug(Ecore_Drm2_Output *output, const drmModeConnector *conn)
|
|||
DBG("\t\tPath: %s", output->backlight.path);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
EINA_LIST_FOREACH(output->plane_states, l, pstate)
|
||||
DBG("\tPossible Plane: %d", pstate->obj_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
EINA_LIST_FOREACH(output->modes, l, omode)
|
||||
{
|
||||
DBG("\tAdded Mode: %dx%d@%d%s%s%s",
|
||||
|
@ -655,23 +664,30 @@ _atomic_state_plane_duplicate(Ecore_Drm2_Plane_State *state)
|
|||
return pstate;
|
||||
}
|
||||
|
||||
/* NB: For now, this function will only return primary planes.
|
||||
* We may need to adjust this later to pass in a desired plane type */
|
||||
static Ecore_Drm2_Plane_State *
|
||||
_output_plane_state_get(Ecore_Drm2_Atomic_State *state, unsigned int id)
|
||||
static Eina_List *
|
||||
_output_plane_states_get(Ecore_Drm2_Atomic_State *state, unsigned int crtc_id, int index)
|
||||
{
|
||||
Eina_List *states = NULL;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i < state->planes; i++)
|
||||
{
|
||||
pstate = &state->plane_states[i];
|
||||
if (pstate->type.value != DRM_PLANE_TYPE_PRIMARY) continue;
|
||||
if (pstate->cid.value != id) continue;
|
||||
return _atomic_state_plane_duplicate(pstate);
|
||||
if (pstate->cid.value == crtc_id)
|
||||
{
|
||||
states =
|
||||
eina_list_append(states, _atomic_state_plane_duplicate(pstate));
|
||||
}
|
||||
else if (pstate->mask & (1 << index))
|
||||
{
|
||||
states =
|
||||
eina_list_append(states, _atomic_state_plane_duplicate(pstate));
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return states;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -745,8 +761,8 @@ _output_create(Ecore_Drm2_Device *dev, const drmModeRes *res, const drmModeConne
|
|||
_output_crtc_state_get(dev->state, output->crtc_id);
|
||||
output->conn_state =
|
||||
_output_conn_state_get(dev->state, output->conn_id);
|
||||
output->plane_state =
|
||||
_output_plane_state_get(dev->state, output->crtc_id);
|
||||
output->plane_states =
|
||||
_output_plane_states_get(dev->state, output->crtc_id, output->pipe);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -887,6 +903,23 @@ _output_destroy(Ecore_Drm2_Device *dev, Ecore_Drm2_Output *output)
|
|||
{
|
||||
Ecore_Drm2_Output_Mode *mode;
|
||||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
Ecore_Drm2_Plane *plane;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
|
||||
EINA_LIST_FREE(output->plane_states, pstate)
|
||||
free(pstate);
|
||||
|
||||
EINA_LIST_FREE(output->planes, plane)
|
||||
free(plane);
|
||||
|
||||
free(output->conn_state);
|
||||
free(output->crtc_state);
|
||||
}
|
||||
#endif
|
||||
|
||||
EINA_LIST_FREE(output->modes, mode)
|
||||
{
|
||||
if (mode->id)
|
||||
|
@ -1524,7 +1557,17 @@ ecore_drm2_output_supported_rotations_get(Ecore_Drm2_Output *output)
|
|||
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
if (_ecore_drm2_use_atomic)
|
||||
ret = output->plane_state->supported_rotations;
|
||||
{
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
|
||||
EINA_LIST_FOREACH(output->plane_states, l, pstate)
|
||||
{
|
||||
if (pstate->type.value != DRM_PLANE_TYPE_PRIMARY) continue;
|
||||
ret = pstate->supported_rotations;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
@ -1540,35 +1583,42 @@ ecore_drm2_output_rotation_set(Ecore_Drm2_Output *output, int rotation)
|
|||
#ifdef HAVE_ATOMIC_DRM
|
||||
if (_ecore_drm2_use_atomic)
|
||||
{
|
||||
Ecore_Drm2_Plane_State *pstate;
|
||||
Eina_List *l;
|
||||
Ecore_Drm2_Plane_State *pstate = NULL;
|
||||
drmModeAtomicReq *req = NULL;
|
||||
int res = 0;
|
||||
uint32_t flags =
|
||||
DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT |
|
||||
DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
|
||||
pstate = output->plane_state;
|
||||
if ((pstate->supported_rotations & rotation) == 0)
|
||||
EINA_LIST_FOREACH(output->plane_states, l, pstate)
|
||||
{
|
||||
WRN("Unsupported rotation");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
if (pstate->type.value != DRM_PLANE_TYPE_PRIMARY) continue;
|
||||
|
||||
req = sym_drmModeAtomicAlloc();
|
||||
if (!req) return EINA_FALSE;
|
||||
if ((pstate->supported_rotations & rotation) == 0)
|
||||
{
|
||||
WRN("Unsupported rotation");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
sym_drmModeAtomicSetCursor(req, 0);
|
||||
req = sym_drmModeAtomicAlloc();
|
||||
if (!req) return EINA_FALSE;
|
||||
|
||||
res = sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->rotation.id, rotation);
|
||||
if (res < 0) goto err;
|
||||
sym_drmModeAtomicSetCursor(req, 0);
|
||||
|
||||
res = sym_drmModeAtomicCommit(output->fd, req, flags, output->user_data);
|
||||
if (res < 0) goto err;
|
||||
else
|
||||
{
|
||||
ret = EINA_TRUE;
|
||||
pstate->rotation.value = rotation;
|
||||
res = sym_drmModeAtomicAddProperty(req, pstate->obj_id,
|
||||
pstate->rotation.id, rotation);
|
||||
if (res < 0) goto err;
|
||||
|
||||
res = sym_drmModeAtomicCommit(output->fd, req, flags,
|
||||
output->user_data);
|
||||
if (res < 0)
|
||||
goto err;
|
||||
else
|
||||
{
|
||||
ret = EINA_TRUE;
|
||||
pstate->rotation.value = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
#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)
|
||||
{
|
||||
#ifdef HAVE_ATOMIC_DRM
|
||||
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)
|
||||
{
|
||||
/* 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->cid.value = output->crtc_id;
|
||||
pstate->fid.value = fb->id;
|
||||
|
||||
pstate->sx.value = 0;
|
||||
pstate->sy.value = 0;
|
||||
pstate->sw.value = fb->w << 16;
|
||||
pstate->sh.value = fb->h << 16;
|
||||
|
||||
plane->state = pstate;
|
||||
plane->type = pstate->type.value;
|
||||
plane->current = fb;
|
||||
|
||||
DBG("FB %d assigned to Plane %d", fb->id, pstate->obj_id);
|
||||
output->planes = eina_list_append(output->planes, plane);
|
||||
|
||||
return plane;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
plane->state->cx.value = x;
|
||||
plane->state->cy.value = y;
|
||||
plane->state->cw.value = w;
|
||||
plane->state->ch.value = h;
|
||||
}
|
|
@ -647,6 +647,9 @@ typedef struct _Ecore_Drm2_Plane_State
|
|||
* 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[];
|
||||
} Ecore_Drm2_Plane_State;
|
||||
|
||||
struct _Ecore_Drm2_Atomic_State
|
||||
|
@ -658,6 +661,14 @@ struct _Ecore_Drm2_Atomic_State
|
|||
};
|
||||
# endif
|
||||
|
||||
# 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,
|
||||
|
@ -682,8 +693,8 @@ struct _Ecore_Drm2_Fb
|
|||
int fd;
|
||||
int w, h;
|
||||
int depth, bpp;
|
||||
uint32_t id, hdl;
|
||||
uint32_t stride, size;
|
||||
uint32_t id, handles[4];
|
||||
uint32_t strides[4], sizes[4];
|
||||
uint32_t format;
|
||||
|
||||
void *gbm_bo;
|
||||
|
@ -694,6 +705,15 @@ struct _Ecore_Drm2_Fb
|
|||
void *mmap;
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Plane
|
||||
{
|
||||
int type;
|
||||
Ecore_Drm2_Fb *current, *next, *pending;
|
||||
# ifdef HAVE_ATOMIC_DRM
|
||||
Ecore_Drm2_Plane_State *state;
|
||||
# endif
|
||||
};
|
||||
|
||||
struct _Ecore_Drm2_Output_Mode
|
||||
{
|
||||
uint32_t id;
|
||||
|
@ -753,7 +773,8 @@ struct _Ecore_Drm2_Output
|
|||
# ifdef HAVE_ATOMIC_DRM
|
||||
Ecore_Drm2_Crtc_State *crtc_state;
|
||||
Ecore_Drm2_Connector_State *conn_state;
|
||||
Ecore_Drm2_Plane_State *plane_state;
|
||||
Eina_List *plane_states;
|
||||
Eina_List *planes;
|
||||
# endif
|
||||
|
||||
Eina_Bool connected : 1;
|
||||
|
@ -782,12 +803,18 @@ struct _Ecore_Drm2_Device
|
|||
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;
|
||||
|
||||
# ifdef HAVE_ATOMIC_DRM
|
||||
Ecore_Drm2_Atomic_State *state;
|
||||
drmModeAtomicReq *atomic_req;
|
||||
# endif
|
||||
|
||||
Eina_List *outputs;
|
||||
|
@ -813,6 +840,7 @@ 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);
|
||||
# endif
|
||||
extern void *(*sym_drmModeGetEncoder)(int fd, uint32_t encoder_id);
|
||||
extern void (*sym_drmModeFreeEncoder)(drmModeEncoderPtr ptr);
|
||||
|
@ -831,9 +859,11 @@ 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
|
||||
|
|
Loading…
Reference in New Issue