diff options
author | Chia-I Wu <olvaffe@gmail.com> | 2009-09-16 11:19:10 +0800 |
---|---|---|
committer | Chia-I Wu <olvaffe@gmail.com> | 2009-09-18 15:32:26 +0800 |
commit | 94f9330609ec305d998e58abfddfbbdf8ae51c9d (patch) | |
tree | 0455381840b1f481b3f946371f8efe0d93613f76 /src/egl/drivers/android/egl_android.c | |
parent | 08b9155eee16770c37acd126f5c542937e378e41 (diff) |
egl_android: New EGL driver for Android.
Diffstat (limited to 'src/egl/drivers/android/egl_android.c')
-rw-r--r-- | src/egl/drivers/android/egl_android.c | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/src/egl/drivers/android/egl_android.c b/src/egl/drivers/android/egl_android.c new file mode 100644 index 0000000000..10c0aea3ab --- /dev/null +++ b/src/egl/drivers/android/egl_android.c @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com> + * + * 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. + */ + +#include "glapi/glapi.h" + +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "egllog.h" +#include "eglsurface.h" +#include "eglimage.h" + +#include "EGL/internal/eglimage_dri.h" + +#include "droid.h" + +#ifndef DROID_DEVICE_PATH +#define DROID_DEVICE_PATH "/dev/dri/card0" +#endif + +struct droid_egl_driver +{ + _EGLDriver base; + + /* EGL_DEFAULT_DISPLAY */ + struct droid_egl_display *default_display; + void (*flush_current)(void); + void (*finish_current)(void); +}; + +struct droid_egl_display +{ + EGLint refcnt; + + EGLint apis; + EGLint major; + EGLint minor; + + struct droid_backend *backend; + struct droid_screen *screen; +}; + +struct droid_egl_context { + _EGLContext base; + struct droid_context *context; +}; + +struct droid_egl_surface { + _EGLSurface base; + struct droid_drawable *drawable; + struct droid_surface *surface; +}; + +struct droid_egl_config { + _EGLConfig base; + const __DRIconfig *config; +}; + +static INLINE struct droid_egl_driver * +lookup_driver(_EGLDriver *drv) +{ + return (struct droid_egl_driver *) drv; +} + +static INLINE struct droid_egl_display * +lookup_display(_EGLDisplay *dpy) +{ + return (struct droid_egl_display *) dpy->DriverData; +} + +static INLINE struct droid_egl_context * +lookup_context(_EGLContext *context) +{ + return (struct droid_egl_context *) context; +} + +static INLINE struct droid_egl_surface * +lookup_surface(_EGLSurface *surface) +{ + return (struct droid_egl_surface *) surface; +} + +static INLINE struct droid_egl_config * +lookup_config(_EGLConfig *conf) +{ + return (struct droid_egl_config *) conf; +} + +static void +droid_create_configs(_EGLDisplay *dpy, struct droid_egl_display *droid_dpy, + const __DRIconfig **configs, EGLint num_configs) +{ + EGLint i; + EGLint id = 1; + + for (i = 0; i < num_configs; i++) { + struct droid_egl_config *droid_conf = calloc(1, sizeof(*droid_conf)); + EGLint val; + + if (!droid_conf) + break; + + _eglInitConfig(&droid_conf->base, id); + droid_conf->config = configs[i]; + droid_screen_convert_config(droid_dpy->screen, droid_conf->config, + &droid_conf->base); + + val = GET_CONFIG_ATTRIB(&droid_conf->base, EGL_CONFIG_CAVEAT); + /* we do not want slow configs */ + if (val == EGL_SLOW_CONFIG) { + free(droid_conf); + } else { + _eglAddConfig(dpy, &droid_conf->base); + id++; + } + } +} + + +static EGLBoolean +droid_initialize_display(struct droid_egl_display *droid_dpy) +{ + const char *path = DROID_DEVICE_PATH; + + droid_dpy->backend = droid_backend_create_intel(path); + if (!droid_dpy->backend) + return EGL_FALSE; + + droid_dpy->screen = droid_screen_create(droid_dpy->backend); + if (!droid_dpy->screen) { + free(droid_dpy->backend); + droid_dpy->backend = NULL; + return EGL_FALSE; + } + + droid_dpy->apis = EGL_OPENGL_ES_BIT; + droid_dpy->major = 1; + droid_dpy->major = 4; + + return EGL_TRUE; +} + +static EGLBoolean +droid_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, + EGLint *major, EGLint *minor) +{ + struct droid_egl_driver *droid_drv = lookup_driver(drv); + struct droid_egl_display *droid_dpy; + + if (dpy->NativeDisplay != EGL_DEFAULT_DISPLAY) + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); + + /* the default display */ + droid_dpy = droid_drv->default_display; + if (!droid_dpy) { + droid_dpy = calloc(1, sizeof(*droid_dpy)); + if (!droid_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + if (!droid_initialize_display(droid_dpy)) + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); + + droid_create_configs(dpy, droid_dpy, droid_dpy->screen->dri_configs, + droid_dpy->screen->num_dri_configs); + + droid_drv->default_display = droid_dpy; + } + + dpy->DriverData = (void *) droid_dpy; + droid_dpy->refcnt++; + + *major = droid_dpy->major; + *minor = droid_dpy->minor; + + return EGL_TRUE; +} + +static EGLBoolean +droid_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct droid_egl_driver *droid_drv = lookup_driver(drv); + struct droid_egl_display *droid_dpy = lookup_display(dpy); + + dpy->DriverData = NULL; + droid_dpy->refcnt--; + if (!droid_dpy->refcnt) { + _eglReleaseDisplayResources(drv, dpy); + _eglCleanupDisplay(dpy); + + free(droid_dpy); + droid_drv->default_display = NULL; + } + + return EGL_TRUE; +} + +static _EGLProc +droid_eglGetProcAddress(const char *procname) +{ + return (_EGLProc) _glapi_get_proc_address(procname); +} + +static _EGLContext * +droid_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + _EGLContext *share_list, const EGLint *attrib_list) +{ + struct droid_egl_display *droid_dpy = lookup_display(dpy); + struct droid_egl_config *droid_conf = lookup_config(conf); + struct droid_egl_context *shared = lookup_context(share_list); + struct droid_egl_context *ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + return NULL; + } + + if (!_eglInitContext(drv, &ctx->base, &droid_conf->base, attrib_list)) { + free(ctx); + return NULL; + } + + ctx->context = + droid_screen_create_context(droid_dpy->screen, droid_conf->config, + (shared) ? shared->context : NULL); + if (!ctx->context) { + free(ctx); + return NULL; + } + + return &ctx->base; +} + +static EGLBoolean +droid_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + struct droid_egl_display *droid_dpy = lookup_display(dpy); + struct droid_egl_context *droid_ctx = lookup_context(ctx); + + if (!_eglIsContextBound(ctx)) + droid_screen_destroy_context(droid_dpy->screen, droid_ctx->context); + + return EGL_TRUE; +} + +static EGLBoolean +droid_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, + _EGLSurface *r, _EGLContext *ctx) +{ + struct droid_egl_driver *droid_drv = lookup_driver(drv); + struct droid_egl_display *droid_dpy = lookup_display(dpy); + struct droid_egl_surface *draw = lookup_surface(d); + struct droid_egl_surface *read = lookup_surface(r); + struct droid_egl_context *droid_ctx = lookup_context(ctx); + _EGLContext *old; + struct droid_egl_context *droid_old; + + old = _eglGetCurrentContext(); + /* an unlinked context will be invalid after context switch */ + if (!_eglIsContextLinked(old)) + old = NULL; + + droid_old = lookup_context(old); + + if (!_eglMakeCurrent(drv, dpy, d, r, ctx)) + return EGL_FALSE; + + if (droid_old && droid_old != droid_ctx && droid_drv->flush_current) + droid_drv->flush_current(); + + _glapi_check_multithread(); + + /* bind new context or unbind old one */ + if (droid_ctx) + droid_screen_bind_context(droid_dpy->screen, + draw->drawable, read->drawable, + droid_ctx->context); + else if (droid_old) + droid_screen_bind_context(droid_dpy->screen, + NULL, NULL, + droid_old->context); + + return EGL_TRUE; +} + +static _EGLSurface * +droid_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + NativeWindowType window, const EGLint *attrib_list) +{ + struct droid_egl_display *droid_dpy = lookup_display(dpy); + struct droid_egl_config *droid_conf = lookup_config(conf); + struct droid_egl_surface *surf; + + surf = calloc(1, sizeof(*surf)); + if (!surf) { + _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &surf->base, EGL_WINDOW_BIT, &droid_conf->base, attrib_list)) { + free(surf); + return NULL; + } + + surf->surface = + droid_dpy->backend->create_window_surface(droid_dpy->backend, + &surf->base, window); + if (!surf->surface) { + free(surf); + return NULL; + } + + surf->drawable = droid_screen_create_drawable(droid_dpy->screen, + droid_conf->config, + surf->surface); + if (!surf->drawable) { + droid_dpy->backend->destroy_surface(droid_dpy->backend, surf->surface); + free(surf); + return NULL; + } + + return &surf->base; +} + +static EGLBoolean +droid_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + struct droid_egl_display *droid_dpy = lookup_display(dpy); + struct droid_egl_surface *droid_surf = lookup_surface(surf); + + if (_eglIsSurfaceBound(&droid_surf->base)) + return EGL_TRUE; + + droid_screen_destroy_drawable(droid_dpy->screen, droid_surf->drawable); + droid_dpy->backend->destroy_surface(droid_dpy->backend, droid_surf->surface); + free(droid_surf); + + return EGL_TRUE; +} + +static EGLBoolean +droid_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + struct droid_egl_driver *droid_drv = lookup_driver(drv); + struct droid_egl_display *droid_dpy = lookup_display(dpy); + struct droid_egl_surface *droid_surf = lookup_surface(surf); + _EGLContext *ctx = _eglGetCurrentContext(); + struct droid_egl_context *droid_ctx = lookup_context(ctx); + + if (droid_ctx) { + if (droid_drv->flush_current) + droid_drv->flush_current(); + + droid_screen_swap_buffers(droid_dpy->screen, + droid_ctx->context, + droid_surf->drawable); + } + + return EGL_TRUE; +} + +static EGLBoolean +droid_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct droid_egl_driver *droid_drv = lookup_driver(drv); + _EGLContext *ctx = _eglGetCurrentContext(); + + if (!ctx || !droid_drv->finish_current) + return EGL_TRUE; + + if (!_eglIsSurfaceLinked(ctx->DrawSurface)) + return _eglError(EGL_BAD_CURRENT_SURFACE, "eglWaitClient"); + + droid_drv->finish_current(); + + return EGL_TRUE; +} + +static EGLBoolean +droid_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) +{ + struct droid_egl_display *droid_dpy = lookup_display(dpy); + _EGLContext *ctx = _eglGetCurrentContext(); + struct droid_egl_surface *droid_surf; + + if (engine != EGL_CORE_NATIVE_ENGINE) + return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); + + if (!ctx) + return EGL_TRUE; + + if (!_eglIsSurfaceLinked(ctx->DrawSurface)) + return _eglError(EGL_BAD_CURRENT_SURFACE, "eglWaitNative"); + + droid_surf = lookup_surface(ctx->DrawSurface); + droid_dpy->backend->swap_native_buffers(droid_dpy->backend, + droid_surf->surface); + + return EGL_TRUE; +} + +static void +droid_Unload(_EGLDriver *drv) +{ + struct droid_egl_driver *droid_drv = lookup_driver(drv); + free(droid_drv); +} + +_EGLDriver * +_eglMain(const char *args) +{ + struct droid_egl_driver *droid_drv = calloc(1, sizeof(*droid_drv)); + if (!droid_drv) + return NULL; + + _eglInitDriverFallbacks(&droid_drv->base); + droid_drv->base.API.Initialize = droid_eglInitialize; + droid_drv->base.API.Terminate = droid_eglTerminate; + + droid_drv->base.API.GetProcAddress = droid_eglGetProcAddress; + + droid_drv->base.API.CreateContext = droid_eglCreateContext; + droid_drv->base.API.DestroyContext = droid_eglDestroyContext; + droid_drv->base.API.MakeCurrent = droid_eglMakeCurrent; + droid_drv->base.API.CreateWindowSurface = droid_eglCreateWindowSurface; + droid_drv->base.API.DestroySurface = droid_eglDestroySurface; + droid_drv->base.API.SwapBuffers = droid_eglSwapBuffers; + droid_drv->base.API.WaitClient = droid_eglWaitClient; + droid_drv->base.API.WaitNative = droid_eglWaitNative; + + droid_drv->base.Name = "Android/i915"; + droid_drv->base.Unload = droid_Unload; + + /* we need a way to flush commands */ + droid_drv->flush_current = + (void (*)(void)) droid_eglGetProcAddress("glFlush"); + droid_drv->finish_current = + (void (*)(void)) droid_eglGetProcAddress("glFinish"); + + return &droid_drv->base; +} |