256 lines
6.5 KiB
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);
|
|
}
|