efl/src/lib/ecore_drm2/ecore_drm2_crtcs.c

256 lines
6.5 KiB
C

#include "ecore_drm2_private.h"
static Eina_Thread_Queue *thq = NULL;
typedef struct
{
Eina_Thread_Queue_Msg head;
Eina_Bool fill : 1;
Eina_Bool commit : 1;
Eina_Bool debug : 1;
} Thread_Msg;
static void
_ecore_drm2_crtc_state_thread_send(Eina_Bool fill, Eina_Bool commit, Eina_Bool debug)
{
Thread_Msg *msg;
void *ref;
msg = eina_thread_queue_send(thq, sizeof(Thread_Msg), &ref);
msg->fill = fill;
msg->commit = commit;
msg->debug = debug;
eina_thread_queue_send_done(thq, ref);
}
static void
_ecore_drm2_crtc_state_debug(Ecore_Drm2_Crtc *crtc)
{
DBG("CRTC Atomic State Fill Complete");
DBG("\tCrtc: %d", crtc->state->obj_id);
DBG("\t\tMode: %d", crtc->state->mode.value);
DBG("\t\tActive: %lu", (long)crtc->state->active.value);
}
static void
_ecore_drm2_crtc_state_fill(Ecore_Drm2_Crtc *crtc)
{
Ecore_Drm2_Crtc_State *cstate;
drmModeObjectPropertiesPtr oprops;
unsigned int i = 0;
/* try to allocate space for CRTC Atomic state */
crtc->state = calloc(1, sizeof(Ecore_Drm2_Crtc_State));
if (!crtc->state)
{
ERR("Could not allocate space for CRTC state");
return;
}
cstate = crtc->state;
cstate->obj_id = crtc->drmCrtc->crtc_id;
/* get the properties of this crtc from drm */
oprops =
sym_drmModeObjectGetProperties(crtc->fd, cstate->obj_id,
DRM_MODE_OBJECT_CRTC);
if (!oprops)
{
free(crtc->state);
return;
}
for (; i < oprops->count_props; i++)
{
drmModePropertyPtr prop;
/* try to get this individual property */
prop = sym_drmModeGetProperty(crtc->fd, oprops->props[i]);
if (!prop) continue;
/* check for the properties we are interested in */
if (!strcmp(prop->name, "MODE_ID"))
{
drmModePropertyBlobPtr bp;
cstate->mode.id = prop->prop_id;
cstate->mode.value = oprops->prop_values[i];
if (!cstate->mode.value)
{
cstate->mode.len = 0;
goto cont;
}
bp = sym_drmModeGetPropertyBlob(crtc->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(crtc->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];
}
/* TODO: We don't actually use this value yet */
/* 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);
/* send message to thread for debug printing crtc state */
_ecore_drm2_crtc_state_thread_send(EINA_FALSE, EINA_FALSE, EINA_TRUE);
}
static void
_ecore_drm2_crtc_state_commit(Ecore_Drm2_Crtc *crtc EINA_UNUSED)
{
/* Ecore_Drm2_Crtc_State *cstate; */
/* cstate = crtc->state; */
/* DBG("CRTC State Commit"); */
}
static void
_ecore_drm2_crtc_state_thread(void *data, Ecore_Thread *thread)
{
Ecore_Drm2_Crtc *crtc;
Thread_Msg *msg;
void *ref;
crtc = data;
eina_thread_name_set(eina_thread_self(), "Ecore-drm2-crtc");
while (!ecore_thread_check(thread))
{
msg = eina_thread_queue_wait(thq, &ref);
if (msg)
{
if (msg->fill) _ecore_drm2_crtc_state_fill(crtc);
if (msg->commit) _ecore_drm2_crtc_state_commit(crtc);
if (msg->debug) _ecore_drm2_crtc_state_debug(crtc);
eina_thread_queue_wait_done(thq, ref);
}
}
}
static void
_ecore_drm2_crtc_state_thread_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void *msg)
{
/* Ecore_Drm2_Crtc *crtc; */
/* crtc = data; */
free(msg);
}
static Ecore_Drm2_Crtc *
_ecore_drm2_crtc_create(Ecore_Drm2_Device *dev, drmModeCrtcPtr dcrtc, uint32_t pipe)
{
Ecore_Drm2_Crtc *crtc;
/* try to allocate space for a crtc */
crtc = calloc(1, sizeof(Ecore_Drm2_Crtc));
if (!crtc)
{
ERR("Could not allocate space for CRTC");
goto err;
}
crtc->id = dcrtc->crtc_id;
crtc->fd = dev->fd;
crtc->pipe = pipe;
crtc->drmCrtc = dcrtc;
/* add this crtc to the list */
dev->crtcs = eina_list_append(dev->crtcs, crtc);
return crtc;
err:
free(crtc);
return NULL;
}
Eina_Bool
_ecore_drm2_crtcs_create(Ecore_Drm2_Device *dev)
{
Ecore_Drm2_Crtc *crtc;
drmModeCrtcPtr c;
drmModeRes *res;
int i = 0;
/* try to get drm resources */
res = sym_drmModeGetResources(dev->fd);
if (!res) return EINA_FALSE;
for (; i < res->count_crtcs; i++)
{
/* try to get this crtc from drm */
c = sym_drmModeGetCrtc(dev->fd, res->crtcs[i]);
/* try to create a crtc */
crtc = _ecore_drm2_crtc_create(dev, c, i);
if (!crtc) goto err;
/* NB: Use an explicit thread to fill crtc atomic state */
thq = eina_thread_queue_new();
crtc->thread =
ecore_thread_feedback_run(_ecore_drm2_crtc_state_thread,
_ecore_drm2_crtc_state_thread_notify,
NULL, NULL, crtc, EINA_TRUE);
}
sym_drmModeFreeResources(res);
return EINA_TRUE;
err:
_ecore_drm2_crtcs_destroy(dev);
sym_drmModeFreeCrtc(c);
sym_drmModeFreeResources(res);
return EINA_FALSE;
}
void
_ecore_drm2_crtcs_destroy(Ecore_Drm2_Device *dev)
{
Ecore_Drm2_Crtc *crtc;
EINA_LIST_FREE(dev->crtcs, crtc)
{
if (crtc->thread) ecore_thread_cancel(crtc->thread);
if (crtc->drmCrtc) sym_drmModeFreeCrtc(crtc->drmCrtc);
free(crtc->state);
free(crtc);
}
}
void
_ecore_drm2_crtc_mode_set(Ecore_Drm2_Crtc *crtc, Ecore_Drm2_Display_Mode *mode EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED)
{
/* TODO: add code to actually set crtc mode */
/* send message to thread queue that we have work to do */
_ecore_drm2_crtc_state_thread_send(EINA_FALSE, EINA_TRUE, EINA_FALSE);
}