forked from enlightenment/efl
204 lines
4.9 KiB
C
204 lines
4.9 KiB
C
#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;
|
|
}
|