summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Michael <cp.michael@samsung.com>2014-01-10 07:26:11 +0000
committerChris Michael <cp.michael@samsung.com>2014-01-29 15:27:23 +0000
commit0954fca98bfb34e22e7e5c52296be8b6f98c15da (patch)
tree125d2c4f1a61df21d4aa62d01c934d7b8f1ff8ad
parentc50fbc1e2cec57c71ebb2587f5f61b9c6cefc799 (diff)
downloadefl-0954fca98bfb34e22e7e5c52296be8b6f98c15da.tar.gz
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>
-rw-r--r--src/lib/ecore_drm/ecore_drm_output.c250
1 files changed, 238 insertions, 12 deletions
diff --git a/src/lib/ecore_drm/ecore_drm_output.c b/src/lib/ecore_drm/ecore_drm_output.c
index d027918161..b25cf79e0c 100644
--- a/src/lib/ecore_drm/ecore_drm_output.c
+++ b/src/lib/ecore_drm/ecore_drm_output.c
@@ -16,13 +16,50 @@ 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)
{
unsigned int i = 0;
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");
+ 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 surface: %m");
+ 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
@@ -289,16 +387,56 @@ mode_err:
}
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;
+ }
+}