summaryrefslogtreecommitdiff
path: root/src/egl/drivers/android/droid_core.c
diff options
context:
space:
mode:
authorChia-I Wu <olv@lunarg.com>2010-10-11 17:58:10 +0800
committerChia-I Wu <olvaffe@gmail.com>2011-03-16 20:18:39 +0800
commitf60af24be798723829478f726da53471c38a20f1 (patch)
tree20f97de6a84d93617003b5c7fa5e0f38914e2319 /src/egl/drivers/android/droid_core.c
parent17cd318e4131454063fae3174be945450ec1e263 (diff)
android: Add new classic EGL driver for Android.
Diffstat (limited to 'src/egl/drivers/android/droid_core.c')
-rw-r--r--src/egl/drivers/android/droid_core.c327
1 files changed, 327 insertions, 0 deletions
diff --git a/src/egl/drivers/android/droid_core.c b/src/egl/drivers/android/droid_core.c
new file mode 100644
index 0000000000..82c21d4aa9
--- /dev/null
+++ b/src/egl/drivers/android/droid_core.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Kristian Høgsberg <krh@bitplanet.net>
+ */
+
+#include "droid.h"
+
+static _EGLContext *
+droid_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
+ _EGLContext *share_list, const EGLint *attrib_list)
+{
+ struct droid_egl_context *dctx;
+ struct droid_egl_display *ddpy = droid_egl_display(disp);
+ struct droid_egl_context *dctx_shared = droid_egl_context(share_list);
+ struct droid_egl_config *dconf = droid_egl_config(conf);
+ const __DRIconfig *dri_config;
+ int api;
+
+ (void) drv;
+
+ dctx = calloc(1, sizeof *dctx);
+ if (!dctx) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateContext");
+ return NULL;
+ }
+
+ if (!_eglInitContext(&dctx->base, disp, conf, attrib_list))
+ goto cleanup;
+
+ switch (dctx->base.ClientAPI) {
+ case EGL_OPENGL_ES_API:
+ switch (dctx->base.ClientVersion) {
+ case 1:
+ api = __DRI_API_GLES;
+ break;
+ case 2:
+ api = __DRI_API_GLES2;
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
+ return NULL;
+ }
+ break;
+ case EGL_OPENGL_API:
+ api = __DRI_API_OPENGL;
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
+ return NULL;
+ }
+
+ if (conf != NULL)
+ dri_config = dconf->dri_config;
+ else
+ dri_config = NULL;
+
+ if (ddpy->dri2->base.version >= 2) {
+ dctx->dri_context =
+ ddpy->dri2->createNewContextForAPI(ddpy->dri_screen,
+ api,
+ dri_config,
+ dctx_shared ?
+ dctx_shared->dri_context : NULL,
+ dctx);
+ } else if (api == __DRI_API_OPENGL) {
+ dctx->dri_context =
+ ddpy->dri2->createNewContext(ddpy->dri_screen,
+ dconf->dri_config,
+ dctx_shared ?
+ dctx_shared->dri_context : NULL,
+ dctx);
+ } else {
+ /* fail */
+ }
+
+ if (!dctx->dri_context)
+ goto cleanup;
+
+ return &dctx->base;
+
+ cleanup:
+ free(dctx);
+ return NULL;
+}
+
+static _EGLSurface *
+droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
+ _EGLConfig *conf, EGLNativeWindowType window,
+ const EGLint *attrib_list)
+{
+ struct droid_egl_display *ddpy = droid_egl_display(disp);
+ struct droid_egl_config *dconf = droid_egl_config(conf);
+ struct droid_egl_surface *dsurf;
+ int format, vis_type;
+
+ (void) drv;
+
+ if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
+ _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
+ return NULL;
+ }
+ if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) {
+ _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
+ return NULL;
+ }
+
+ vis_type = _eglGetConfigKey(&dconf->base, EGL_NATIVE_VISUAL_TYPE);
+ if (format != vis_type) {
+ _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",
+ format, vis_type);
+ }
+
+ dsurf = calloc(1, sizeof *dsurf);
+ if (!dsurf) {
+ _eglError(EGL_BAD_ALLOC, "droid_create_surface");
+ return NULL;
+ }
+
+ if (!_eglInitSurface(&dsurf->base, disp, type, conf, attrib_list))
+ goto cleanup_surf;
+
+ dsurf->dri_drawable =
+ (*ddpy->dri2->createNewDrawable) (ddpy->dri_screen,
+ dconf->dri_config, dsurf);
+ if (dsurf->dri_drawable == NULL) {
+ _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
+ goto cleanup_pixmap;
+ }
+
+ window->common.incRef(&window->common);
+ window->query(window, NATIVE_WINDOW_WIDTH, &dsurf->base.Width);
+ window->query(window, NATIVE_WINDOW_HEIGHT, &dsurf->base.Height);
+
+ dsurf->window = window;
+
+ return &dsurf->base;
+
+ cleanup_dri_drawable:
+ ddpy->core->destroyDrawable(dsurf->dri_drawable);
+ cleanup_pixmap:
+ cleanup_surf:
+ free(dsurf);
+
+ return NULL;
+}
+
+static _EGLSurface *
+droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
+ _EGLConfig *conf, EGLNativeWindowType window,
+ const EGLint *attrib_list)
+{
+ return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
+ window, attrib_list);
+}
+
+static _EGLSurface *
+droid_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
+ _EGLConfig *conf, EGLNativePixmapType pixmap,
+ const EGLint *attrib_list)
+{
+ return NULL;
+}
+
+static _EGLSurface *
+droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
+ _EGLConfig *conf, const EGLint *attrib_list)
+{
+ return NULL;
+}
+
+static EGLBoolean
+droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
+{
+ struct droid_egl_display *ddpy = droid_egl_display(disp);
+ struct droid_egl_surface *dsurf = droid_egl_surface(surf);
+
+ (void) drv;
+
+ if (!_eglPutSurface(surf))
+ return EGL_TRUE;
+
+ (*ddpy->core->destroyDrawable)(dsurf->dri_drawable);
+
+ droid_enqueue_buffer(dsurf);
+ dsurf->window->common.decRef(&dsurf->window->common);
+
+ free(surf);
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+droid_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
+ _EGLSurface *rsurf, _EGLContext *ctx)
+{
+ struct droid_egl_driver *ddrv = droid_egl_driver(drv);
+ struct droid_egl_display *ddpy = droid_egl_display(disp);
+ struct droid_egl_surface *droid_dsurf = droid_egl_surface(dsurf);
+ struct droid_egl_surface *droid_rsurf = droid_egl_surface(rsurf);
+ struct droid_egl_context *dctx = droid_egl_context(ctx);
+ _EGLContext *old_ctx;
+ _EGLSurface *old_dsurf, *old_rsurf;
+ __DRIdrawable *ddraw, *rdraw;
+ __DRIcontext *cctx;
+
+ /* make new bindings */
+ if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
+ return EGL_FALSE;
+
+ /* flush before context switch */
+ if (old_ctx && ddrv->glFlush)
+ ddrv->glFlush();
+
+ ddraw = (droid_dsurf) ? droid_dsurf->dri_drawable : NULL;
+ rdraw = (droid_rsurf) ? droid_rsurf->dri_drawable : NULL;
+ cctx = (dctx) ? dctx->dri_context : NULL;
+
+ if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
+ ddpy->core->bindContext(cctx, ddraw, rdraw)) {
+ droid_destroy_surface(drv, disp, old_dsurf);
+ droid_destroy_surface(drv, disp, old_rsurf);
+ if (old_ctx) {
+ /* unbind the old context only when there is no new context bound */
+ if (!ctx) {
+ __DRIcontext *old_cctx = droid_egl_context(old_ctx)->dri_context;
+ ddpy->core->unbindContext(old_cctx);
+ }
+ /* no destroy? */
+ _eglPutContext(old_ctx);
+ }
+
+ return EGL_TRUE;
+ } else {
+ /* undo the previous _eglBindContext */
+ _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
+ assert(&dctx->base == ctx &&
+ &droid_dsurf->base == dsurf &&
+ &droid_rsurf->base == rsurf);
+
+ _eglPutSurface(dsurf);
+ _eglPutSurface(rsurf);
+ _eglPutContext(ctx);
+
+ _eglPutSurface(old_dsurf);
+ _eglPutSurface(old_rsurf);
+ _eglPutContext(old_ctx);
+
+ return EGL_FALSE;
+ }
+}
+
+static EGLBoolean
+droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
+{
+ struct droid_egl_driver *ddrv = droid_egl_driver(drv);
+ struct droid_egl_display *ddpy = droid_egl_display(disp);
+ struct droid_egl_surface *dsurf = droid_egl_surface(draw);
+ _EGLContext *ctx;
+
+ if (ddrv->glFlush) {
+ ctx = _eglGetCurrentContext();
+ if (ctx && ctx->DrawSurface == &dsurf->base)
+ ddrv->glFlush();
+ }
+
+ (*ddpy->flush->flush)(dsurf->dri_drawable);
+
+ if (dsurf->buffer)
+ droid_enqueue_buffer(dsurf);
+
+ (*ddpy->flush->invalidate)(dsurf->dri_drawable);
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+droid_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
+{
+ struct droid_egl_driver *ddrv = droid_egl_driver(drv);
+ struct droid_egl_display *ddpy = droid_egl_display(disp);
+ struct droid_egl_surface *dsurf = droid_egl_surface(ctx->DrawSurface);
+
+ if (ddrv->glFinish)
+ ddrv->glFinish();
+
+ if (dsurf)
+ (*ddpy->flush->flush)(dsurf->dri_drawable);
+
+ return EGL_TRUE;
+}
+
+void
+droid_init_core_functions(_EGLDriver *drv)
+{
+ struct droid_egl_driver *ddrv = droid_egl_driver(drv);
+
+ ddrv->base.API.CreateContext = droid_create_context;
+ ddrv->base.API.CreateWindowSurface = droid_create_window_surface;
+ ddrv->base.API.CreatePixmapSurface = droid_create_pixmap_surface;
+ ddrv->base.API.CreatePbufferSurface = droid_create_pbuffer_surface;
+ ddrv->base.API.DestroySurface = droid_destroy_surface;
+ ddrv->base.API.MakeCurrent = droid_make_current;
+ ddrv->base.API.SwapBuffers = droid_swap_buffers;
+ ddrv->base.API.WaitClient = droid_wait_client;
+}