Add code to create an EGL Context for an output.

Start on hardware rendering code (egl)

Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
Chris Michael 2014-01-10 07:26:11 +00:00
parent c50fbc1e2c
commit 0954fca98b
1 changed files with 238 additions and 12 deletions

View File

@ -15,6 +15,43 @@ static const char *conn_types[] =
/* local functions */
#ifdef HAVE_GBM
static Eina_Bool
_ecore_drm_output_context_create(Ecore_Drm_Device *dev, EGLSurface surface)
{
EGLBoolean r;
static const EGLint attribs[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
};
if ((!dev->egl.disp) || (!dev->egl.cfg)) return EINA_FALSE;
if (!eglBindAPI(EGL_OPENGL_ES_API))
{
ERR("Could not bind egl api");
return EINA_FALSE;
}
dev->egl.ctxt =
eglCreateContext(dev->egl.disp, dev->egl.cfg, EGL_NO_CONTEXT, attribs);
if (!dev->egl.ctxt)
{
ERR("Could not create Egl Context");
return EINA_FALSE;
}
r = eglMakeCurrent(dev->egl.disp, surface, surface, dev->egl.ctxt);
if (r == EGL_FALSE)
{
ERR("Could not make surface current");
return EINA_FALSE;
}
/* TODO: bind display, handle extensions, compile shaders, etc */
return EINA_TRUE;
}
static Eina_Bool
_ecore_drm_output_hardware_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output)
{
@ -22,7 +59,7 @@ _ecore_drm_output_hardware_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output
int flags = 0;
int w = 0, h = 0;
if ((!dev) || (!output) || (!dev->use_hw_accel)) return EINA_FALSE;
if ((!dev) || (!output)) return EINA_FALSE;
if (output->current_mode)
{
@ -38,12 +75,33 @@ _ecore_drm_output_hardware_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output
flags = (GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!(output->surface =
gbm_surface_create(dev->gbm, w, h, dev->format, flags)))
gbm_surface_create(dev->gbm, w, h, GBM_FORMAT_ARGB8888, flags)))
{
ERR("Could not create output surface: %m");
ERR("Could not create output surface");
return EINA_FALSE;
}
/* TODO: create egl window surface */
if (!(output->egl.surface =
eglCreateWindowSurface(dev->egl.disp, dev->egl.cfg,
output->surface, NULL)))
{
ERR("Could not create output egl surface");
gbm_surface_destroy(output->surface);
return EINA_FALSE;
}
if (!dev->egl.ctxt)
{
if (!_ecore_drm_output_context_create(dev, output->egl.surface))
{
ERR("Could not create context");
gbm_surface_destroy(output->surface);
return EINA_FALSE;
}
}
flags = (GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
for (i = 0; i < NUM_FRAME_BUFFERS; i++)
{
@ -51,7 +109,6 @@ _ecore_drm_output_hardware_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output
if (!(output->cursor[i] =
gbm_bo_create(dev->gbm, 64, 64, dev->format, flags)))
{
ERR("Could not create cursor surface: %m");
continue;
}
}
@ -64,6 +121,37 @@ _ecore_drm_output_hardware_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output
return EINA_TRUE;
}
static void
_ecore_drm_output_hardware_render(Ecore_Drm_Output *output)
{
struct gbm_bo *bo;
if (!output) return;
if (!output->current_mode) return;
glViewport(output->x, output->y,
output->current_mode->width, output->current_mode->height);
eglMakeCurrent(output->dev->egl.disp, output->egl.surface,
output->egl.surface, output->dev->egl.ctxt);
/* TODO: calculate damage */
/* TODO: repaint surfaces */
/* TODO: call egl functions to repaint */
eglSwapBuffers(output->dev->egl.disp, output->egl.surface);
if (!(bo = gbm_surface_lock_front_buffer(output->surface)))
{
ERR("Failed to lock front buffer");
return;
}
/* output->next = _get_from_bo(); */
}
#endif
static Eina_Bool
@ -87,7 +175,7 @@ _ecore_drm_output_software_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output
for (i = 0; i < NUM_FRAME_BUFFERS; i++)
{
if (!(output->dumb[i] = _ecore_drm_fb_create(dev, w, h)))
if (!(output->dumb[i] = ecore_drm_fb_create(dev, w, h)))
{
ERR("Could not create dumb framebuffer %d", i);
goto err;
@ -99,13 +187,20 @@ _ecore_drm_output_software_setup(Ecore_Drm_Device *dev, Ecore_Drm_Output *output
err:
for (i = 0; i < NUM_FRAME_BUFFERS; i++)
{
if (output->dumb[i]) _ecore_drm_fb_destroy(output->dumb[i]);
if (output->dumb[i]) ecore_drm_fb_destroy(output->dumb[i]);
output->dumb[i] = NULL;
}
return EINA_FALSE;
}
static void
_ecore_drm_output_software_render(Ecore_Drm_Output *output)
{
if (!output) return;
if (!output->current_mode) return;
}
static int
_ecore_drm_output_crtc_find(Ecore_Drm_Device *dev, drmModeRes *res, drmModeConnector *conn)
{
@ -201,6 +296,7 @@ _ecore_drm_output_create(Ecore_Drm_Device *dev, drmModeRes *res, drmModeConnecto
return NULL;
}
output->dev = dev;
output->x = x;
output->y = y;
@ -253,11 +349,12 @@ _ecore_drm_output_create(Ecore_Drm_Device *dev, drmModeRes *res, drmModeConnecto
output->current_mode = _ecore_drm_output_mode_add(output, &crtc_mode);
#ifdef HAVE_GBM
if (dev->use_hw_accel)
if ((dev->use_hw_accel) && (dev->gbm))
{
if (!_ecore_drm_output_hardware_setup(dev, output))
{
ERR("Could not setup output for hardware acceleration");
dev->use_hw_accel = EINA_FALSE;
if (!_ecore_drm_output_software_setup(dev, output))
goto mode_err;
else
@ -269,6 +366,7 @@ _ecore_drm_output_create(Ecore_Drm_Device *dev, drmModeRes *res, drmModeConnecto
else
#endif
{
dev->use_hw_accel = EINA_FALSE;
if (!_ecore_drm_output_software_setup(dev, output))
goto mode_err;
else
@ -288,17 +386,57 @@ mode_err:
return NULL;
}
void
_ecore_drm_output_frame_finish(Ecore_Drm_Output *output)
{
if (!output) return;
if (output->need_repaint) ecore_drm_output_repaint(output);
output->repaint_scheduled = EINA_FALSE;
}
void
_ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb)
{
if ((!output) || (!fb)) return;
if ((fb->mmap) && (fb != output->dumb[0]) && (fb != output->dumb[1]))
_ecore_drm_fb_destroy(fb);
#ifdef HAVE_GBM
else if (fb->bo)
gbm_bo_destroy(fb->bo);
#endif
ecore_drm_fb_destroy(fb);
/* #ifdef HAVE_GBM */
/* else if (fb->bo) */
/* gbm_bo_destroy(fb->bo); */
/* #endif */
}
void
_ecore_drm_output_repaint_start(Ecore_Drm_Output *output)
{
unsigned int fb;
DBG("Output Repaint Start");
if (!output) return;
if (!output->current)
{
DBG("\tNo Current FB");
goto finish;
}
fb = output->current->id;
if (drmModePageFlip(output->dev->drm.fd, output->crtc_id, fb,
DRM_MODE_PAGE_FLIP_EVENT, output) < 0)
{
ERR("Could not schedule output page flip event");
goto finish;
}
return;
finish:
_ecore_drm_output_frame_finish(output);
}
/**
@ -448,3 +586,91 @@ ecore_drm_output_enable(Ecore_Drm_Output *output)
return EINA_TRUE;
}
EAPI void
ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb)
{
if ((!output) || (!fb)) return;
if ((fb->mmap) && (fb != output->dumb[0]) && (fb != output->dumb[1]))
ecore_drm_fb_destroy(fb);
#ifdef HAVE_GBM
else if (fb->bo)
{
if (fb->from_client)
gbm_bo_destroy(fb->bo);
else
gbm_surface_release_buffer(output->surface, output->current->bo);
}
#endif
}
EAPI void
ecore_drm_output_repaint(Ecore_Drm_Output *output)
{
int ret = 0;
if (!output) return;
DBG("Output Repaint");
/* TODO: assign planes ? */
if (!output->next)
{
#ifdef HAVE_GBM
if (output->dev->use_hw_accel)
{
_ecore_drm_output_hardware_render(output);
}
else
#endif
{
_ecore_drm_output_software_render(output);
}
}
output->need_repaint = EINA_FALSE;
if (!output->next)
{
DBG("\tNo Next Fb");
return;
}
if (!output->current)
{
Ecore_Drm_Output_Mode *mode;
mode = output->current_mode;
ret = drmModeSetCrtc(output->dev->drm.fd, output->crtc_id,
output->next->id, 0, 0, &output->conn_id, 1,
&mode->info);
if (ret)
{
ERR("Setting output mode failed");
goto err;
}
}
if (drmModePageFlip(output->dev->drm.fd, output->crtc_id, output->next->id,
DRM_MODE_PAGE_FLIP_EVENT, output) < 0)
{
ERR("Scheduling pageflip failed");
goto err;
}
output->pending_flip = EINA_TRUE;
/* TODO: finish */
return;
err:
if (output->next)
{
ecore_drm_output_fb_release(output, output->next);
output->next = NULL;
}
}