From f60af24be798723829478f726da53471c38a20f1 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 11 Oct 2010 17:58:10 +0800 Subject: android: Add new classic EGL driver for Android. --- src/egl/drivers/android/droid_core.c | 327 +++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 src/egl/drivers/android/droid_core.c (limited to 'src/egl/drivers/android/droid_core.c') 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 + */ + +#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; +} -- cgit v1.2.3