summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olv@lunarg.com>2010-10-11 17:58:10 +0800
committerChia-I Wu <olvaffe@gmail.com>2010-12-09 20:01:35 -0500
commit121fc671f48f6fe5b58d44d55ef9ec421f6abde1 (patch)
treef2fa0535fd046628659ca46707ffeb1c918e88b1
parent8148db591a7b0e7a51f664930301cc8d774a90a8 (diff)
android: Add new classic EGL driver for Android.
-rw-r--r--src/egl/drivers/android/droid.c649
-rw-r--r--src/egl/drivers/android/droid.h126
-rw-r--r--src/egl/drivers/android/droid_core.c327
-rw-r--r--src/egl/drivers/android/droid_image.c132
-rw-r--r--src/egl/drivers/android/egl_android.c42
5 files changed, 1276 insertions, 0 deletions
diff --git a/src/egl/drivers/android/droid.c b/src/egl/drivers/android/droid.c
new file mode 100644
index 0000000000..60c100bb13
--- /dev/null
+++ b/src/egl/drivers/android/droid.c
@@ -0,0 +1,649 @@
+/*
+ * 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>
+ */
+
+#define LOG_TAG "MESA-EGL"
+
+#include <cutils/log.h>
+
+#include "glapi/glapi.h"
+#include "droid.h"
+
+static const __DRIuseInvalidateExtension use_invalidate = {
+ { __DRI_USE_INVALIDATE, 1 }
+};
+
+static __DRIimage *
+droid_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
+{
+ _EGLDisplay *disp = data;
+ struct droid_egl_image *dimg;
+ _EGLImage *img;
+
+ (void) screen;
+
+ img = _eglLookupImage(image, disp);
+ if (img == NULL) {
+ _eglError(EGL_BAD_PARAMETER, "droid_lookup_egl_image");
+ return NULL;
+ }
+
+ dimg = droid_egl_image(image);
+
+ return dimg->dri_image;
+}
+
+static const __DRIimageLookupExtension image_lookup_extension = {
+ { __DRI_IMAGE_LOOKUP, 1 },
+ droid_lookup_egl_image
+};
+
+static int
+get_format_bpp(int native)
+{
+ int bpp;
+
+ /* see libpixelflinger/format.cpp */
+ switch (native) {
+ case GGL_PIXEL_FORMAT_RGBA_8888:
+ case GGL_PIXEL_FORMAT_RGBX_8888:
+ case GGL_PIXEL_FORMAT_BGRA_8888:
+ bpp = 4;
+ break;
+ case GGL_PIXEL_FORMAT_RGB_888:
+ bpp = 3;
+ break;
+ case GGL_PIXEL_FORMAT_RGB_565:
+ case GGL_PIXEL_FORMAT_RGBA_5551:
+ case GGL_PIXEL_FORMAT_RGBA_4444:
+ case GGL_PIXEL_FORMAT_LA_88:
+ bpp = 2;
+ break;
+ case GGL_PIXEL_FORMAT_RGB_332:
+ case GGL_PIXEL_FORMAT_A_8:
+ case GGL_PIXEL_FORMAT_L_8:
+ bpp = 1;
+ break;
+ default:
+ bpp = 0;
+ break;
+ }
+
+ return bpp;
+}
+
+#include <gralloc_gem.h>
+int
+get_native_buffer_name(struct android_native_buffer_t *buf)
+{
+ struct drm_bo_t *bo;
+
+ bo = drm_gem_get(buf->handle);
+
+ return (bo) ? bo->name : 0;
+}
+
+EGLBoolean
+droid_dequeue_buffer(struct droid_egl_surface *dsurf)
+{
+ __DRIbuffer *buf = &dsurf->dri_buffer;
+
+ if (dsurf->window->dequeueBuffer(dsurf->window, &dsurf->buffer))
+ return EGL_FALSE;
+
+ dsurf->buffer->common.incRef(&dsurf->buffer->common);
+ dsurf->window->lockBuffer(dsurf->window, dsurf->buffer);
+
+ buf->attachment = __DRI_BUFFER_FAKE_FRONT_LEFT;
+ buf->name = get_native_buffer_name(dsurf->buffer);
+ buf->cpp = get_format_bpp(dsurf->buffer->format);
+ buf->pitch = dsurf->buffer->stride * buf->cpp;
+ buf->flags = 0;
+
+ return EGL_TRUE;
+}
+
+EGLBoolean
+droid_enqueue_buffer(struct droid_egl_surface *dsurf)
+{
+ dsurf->window->queueBuffer(dsurf->window, dsurf->buffer);
+
+ dsurf->buffer->common.decRef(&dsurf->buffer->common);
+ dsurf->buffer = NULL;
+
+ return EGL_TRUE;
+}
+
+static void
+droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+{
+}
+
+static __DRIbuffer *
+droid_get_buffers_with_format(__DRIdrawable * driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
+{
+ struct droid_egl_surface *dsurf = loaderPrivate;
+ struct droid_egl_display *ddpy =
+ droid_egl_display(dsurf->base.Resource.Display);
+
+ if (!dsurf->buffer) {
+ if (!droid_dequeue_buffer(dsurf))
+ return NULL;
+ }
+
+ if (width)
+ *width = dsurf->buffer->width;
+ if (height)
+ *height = dsurf->buffer->height;
+
+ *out_count = 1;
+
+ return &dsurf->dri_buffer;
+}
+
+static const EGLint droid_to_egl_attribute_map[] = {
+ 0,
+ EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */
+ EGL_LEVEL, /* __DRI_ATTRIB_LEVEL */
+ EGL_RED_SIZE, /* __DRI_ATTRIB_RED_SIZE */
+ EGL_GREEN_SIZE, /* __DRI_ATTRIB_GREEN_SIZE */
+ EGL_BLUE_SIZE, /* __DRI_ATTRIB_BLUE_SIZE */
+ EGL_LUMINANCE_SIZE, /* __DRI_ATTRIB_LUMINANCE_SIZE */
+ EGL_ALPHA_SIZE, /* __DRI_ATTRIB_ALPHA_SIZE */
+ 0, /* __DRI_ATTRIB_ALPHA_MASK_SIZE */
+ EGL_DEPTH_SIZE, /* __DRI_ATTRIB_DEPTH_SIZE */
+ EGL_STENCIL_SIZE, /* __DRI_ATTRIB_STENCIL_SIZE */
+ 0, /* __DRI_ATTRIB_ACCUM_RED_SIZE */
+ 0, /* __DRI_ATTRIB_ACCUM_GREEN_SIZE */
+ 0, /* __DRI_ATTRIB_ACCUM_BLUE_SIZE */
+ 0, /* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */
+ EGL_SAMPLE_BUFFERS, /* __DRI_ATTRIB_SAMPLE_BUFFERS */
+ EGL_SAMPLES, /* __DRI_ATTRIB_SAMPLES */
+ 0, /* __DRI_ATTRIB_RENDER_TYPE, */
+ 0, /* __DRI_ATTRIB_CONFIG_CAVEAT */
+ 0, /* __DRI_ATTRIB_CONFORMANT */
+ 0, /* __DRI_ATTRIB_DOUBLE_BUFFER */
+ 0, /* __DRI_ATTRIB_STEREO */
+ 0, /* __DRI_ATTRIB_AUX_BUFFERS */
+ 0, /* __DRI_ATTRIB_TRANSPARENT_TYPE */
+ 0, /* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */
+ 0, /* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */
+ 0, /* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */
+ 0, /* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */
+ 0, /* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */
+ 0, /* __DRI_ATTRIB_FLOAT_MODE */
+ 0, /* __DRI_ATTRIB_RED_MASK */
+ 0, /* __DRI_ATTRIB_GREEN_MASK */
+ 0, /* __DRI_ATTRIB_BLUE_MASK */
+ 0, /* __DRI_ATTRIB_ALPHA_MASK */
+ EGL_MAX_PBUFFER_WIDTH, /* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */
+ EGL_MAX_PBUFFER_HEIGHT, /* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */
+ EGL_MAX_PBUFFER_PIXELS, /* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */
+ 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */
+ 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */
+ 0, /* __DRI_ATTRIB_VISUAL_SELECT_GROUP */
+ 0, /* __DRI_ATTRIB_SWAP_METHOD */
+ EGL_MAX_SWAP_INTERVAL, /* __DRI_ATTRIB_MAX_SWAP_INTERVAL */
+ EGL_MIN_SWAP_INTERVAL, /* __DRI_ATTRIB_MIN_SWAP_INTERVAL */
+ 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */
+ 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
+ 0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
+ 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
+ EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */
+};
+
+static struct droid_egl_config *
+droid_add_config(_EGLDisplay *dpy, const __DRIconfig *dri_config, int id,
+ int depth, EGLint surface_type, int rgba_masks[4])
+{
+ struct droid_egl_config *conf;
+ struct droid_egl_display *ddpy;
+ _EGLConfig base;
+ unsigned int attrib, value, double_buffer;
+ EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
+ int dri_masks[4] = { 0, 0, 0, 0 };
+ int i;
+
+ ddpy = dpy->DriverData;
+ _eglInitConfig(&base, dpy, id);
+
+ i = 0;
+ double_buffer = 0;
+ bind_to_texture_rgb = 0;
+ bind_to_texture_rgba = 0;
+
+ while (ddpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) {
+ switch (attrib) {
+ case __DRI_ATTRIB_RENDER_TYPE:
+ if (value & __DRI_ATTRIB_RGBA_BIT)
+ value = EGL_RGB_BUFFER;
+ else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
+ value = EGL_LUMINANCE_BUFFER;
+ else
+ assert(0);
+ _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
+ break;
+
+ case __DRI_ATTRIB_CONFIG_CAVEAT:
+ if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
+ value = EGL_NON_CONFORMANT_CONFIG;
+ else if (value & __DRI_ATTRIB_SLOW_BIT)
+ value = EGL_SLOW_CONFIG;
+ else
+ value = EGL_NONE;
+ _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
+ break;
+
+ case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
+ bind_to_texture_rgb = value;
+ break;
+
+ case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
+ bind_to_texture_rgba = value;
+ break;
+
+ case __DRI_ATTRIB_DOUBLE_BUFFER:
+ double_buffer = value;
+ break;
+
+ case __DRI_ATTRIB_RED_MASK:
+ dri_masks[0] = value;
+ break;
+
+ case __DRI_ATTRIB_GREEN_MASK:
+ dri_masks[1] = value;
+ break;
+
+ case __DRI_ATTRIB_BLUE_MASK:
+ dri_masks[2] = value;
+ break;
+
+ case __DRI_ATTRIB_ALPHA_MASK:
+ dri_masks[3] = value;
+ break;
+
+ default:
+ key = droid_to_egl_attribute_map[attrib];
+ if (key != 0)
+ _eglSetConfigKey(&base, key, value);
+ break;
+ }
+ }
+
+ /* In EGL, double buffer or not isn't a config attribute. Pixmaps
+ * surfaces are always single buffered, pbuffer surfaces are always
+ * back buffers and windows can be either, selected by passing an
+ * attribute at window surface construction time. To support this
+ * we ignore all double buffer configs and manipulate the buffer we
+ * return in the getBuffer callback to get the behaviour we want. */
+
+ if (double_buffer)
+ return NULL;
+
+ if (depth > 0 && depth != _eglGetConfigKey(&base, EGL_BUFFER_SIZE))
+ return NULL;
+
+ if (memcmp(dri_masks, rgba_masks, sizeof(rgba_masks)))
+ return NULL;
+
+ _eglSetConfigKey(&base, EGL_NATIVE_RENDERABLE, EGL_TRUE);
+
+ _eglSetConfigKey(&base, EGL_SURFACE_TYPE, surface_type);
+ if (surface_type & (EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)) {
+ _eglSetConfigKey(&base, EGL_BIND_TO_TEXTURE_RGB, bind_to_texture_rgb);
+ if (_eglGetConfigKey(&base, EGL_ALPHA_SIZE) > 0)
+ _eglSetConfigKey(&base,
+ EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba);
+ }
+
+ _eglSetConfigKey(&base, EGL_RENDERABLE_TYPE, dpy->ClientAPIsMask);
+ _eglSetConfigKey(&base, EGL_CONFORMANT, dpy->ClientAPIsMask);
+
+ if (!_eglValidateConfig(&base, EGL_FALSE)) {
+ _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
+ return NULL;
+ }
+
+ conf = calloc(1, sizeof(*conf));
+ if (conf != NULL) {
+ memcpy(&conf->base, &base, sizeof(base));
+ conf->dri_config = dri_config;
+ _eglLinkConfig(&conf->base);
+ }
+
+ return conf;
+}
+
+static EGLBoolean
+droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct droid_egl_display *ddpy = droid_egl_display(dpy);
+ const struct {
+ int format;
+ int size;
+ int rgba_masks[4];
+ } visuals[] = {
+ { GGL_PIXEL_FORMAT_RGBA_8888, 32, { 0xff, 0xff00, 0xff0000, 0xff000000 } },
+ { GGL_PIXEL_FORMAT_RGBX_8888, 32, { 0xff, 0xff00, 0xff0000, 0x0 } },
+ { GGL_PIXEL_FORMAT_RGB_888, 24, { 0xff, 0xff00, 0xff0000, 0x0 } },
+ { GGL_PIXEL_FORMAT_RGB_565, 16, { 0xf800, 0x7e0, 0x1f, 0x0 } },
+ { GGL_PIXEL_FORMAT_BGRA_8888, 32, { 0xff0000, 0xff00, 0xff, 0xff000000 } },
+ { GGL_PIXEL_FORMAT_A_8, 8, { 0xf800, 0x7e0, 0x1f, 0x0 } },
+ { 0, 0, { 0, 0, 0, 0 } }
+ };
+ int count, i, j;
+
+ count = 0;
+ for (i = 0; visuals[i].format; i++) {
+ int format_count = 0;
+
+ for (j = 0; ddpy->dri_configs[j]; j++) {
+ struct droid_egl_config *dconf;
+
+ dconf = droid_add_config(dpy, ddpy->dri_configs[j], count + 1,
+ visuals[i].size, EGL_WINDOW_BIT, visuals[i].rgba_masks);
+ if (dconf) {
+ _eglSetConfigKey(&dconf->base,
+ EGL_NATIVE_VISUAL_TYPE, visuals[i].format);
+ count++;
+ format_count++;
+ }
+ }
+
+ if (!format_count) {
+ _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
+ visuals[i].format);
+ }
+ }
+
+ return (count != 0);
+}
+
+struct droid_extension_match {
+ const char *name;
+ int version;
+ int offset;
+};
+
+static struct droid_extension_match droid_driver_extensions[] = {
+ { __DRI_CORE, 1, offsetof(struct droid_egl_display, core) },
+ { __DRI_DRI2, 1, offsetof(struct droid_egl_display, dri2) },
+ { NULL, 0, 0 }
+};
+
+static struct droid_extension_match droid_core_extensions[] = {
+ { __DRI2_FLUSH, 1, offsetof(struct droid_egl_display, flush) },
+ { __DRI_IMAGE, 1, offsetof(struct droid_egl_display, image) },
+ { NULL, 0, 0 }
+};
+
+extern const __DRIextension *__driDriverExtensions[];
+
+static EGLBoolean
+droid_bind_extensions(struct droid_egl_display *ddpy,
+ struct droid_extension_match *matches,
+ const __DRIextension **extensions)
+{
+ int i, j, ret = EGL_TRUE;
+ void *field;
+
+ for (i = 0; extensions[i]; i++) {
+ _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
+ for (j = 0; matches[j].name; j++) {
+ if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
+ extensions[i]->version >= matches[j].version) {
+ field = ((char *) ddpy + matches[j].offset);
+ *(const __DRIextension **) field = extensions[i];
+ _eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
+ extensions[i]->name, extensions[i]->version);
+ }
+ }
+ }
+
+ for (j = 0; matches[j].name; j++) {
+ field = ((char *) ddpy + matches[j].offset);
+ if (*(const __DRIextension **) field == NULL) {
+ _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d",
+ matches[j].name, matches[j].version);
+ ret = EGL_FALSE;
+ }
+ }
+
+ return ret;
+}
+
+static EGLBoolean
+droid_create_screen(_EGLDisplay *dpy)
+{
+ struct droid_egl_display *ddpy = droid_egl_display(dpy);
+ const __DRIextension **extensions;
+ unsigned int api_mask;
+
+ ddpy->dri_screen =
+ ddpy->dri2->createNewScreen(0, ddpy->fd, ddpy->extensions,
+ &ddpy->dri_configs, dpy);
+ if (ddpy->dri_screen == NULL) {
+ _eglLog(_EGL_WARNING, "failed to create dri screen");
+ return EGL_FALSE;
+ }
+
+ extensions = ddpy->core->getExtensions(ddpy->dri_screen);
+ if (!droid_bind_extensions(ddpy, droid_core_extensions, extensions)) {
+ ddpy->core->destroyScreen(ddpy->dri_screen);
+ return EGL_FALSE;
+ }
+
+ if (ddpy->dri2->base.version >= 2)
+ api_mask = ddpy->dri2->getAPIMask(ddpy->dri_screen);
+ else
+ api_mask = __DRI_API_OPENGL;
+
+ dpy->ClientAPIsMask = 0;
+ if (api_mask & (1 <<__DRI_API_OPENGL))
+ dpy->ClientAPIsMask |= EGL_OPENGL_BIT;
+ if (api_mask & (1 <<__DRI_API_GLES))
+ dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
+ if (api_mask & (1 << __DRI_API_GLES2))
+ dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
+
+ if (ddpy->dri2->base.version >= 2) {
+ dpy->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
+ dpy->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
+ dpy->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
+ }
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+droid_load_driver(_EGLDisplay *disp)
+{
+ struct droid_egl_display *ddpy = disp->DriverData;
+ const __DRIextension **extensions;
+
+ extensions = __driDriverExtensions;
+
+ if (!droid_bind_extensions(ddpy, droid_driver_extensions, extensions))
+ return EGL_FALSE;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+droid_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy,
+ EGLint *major, EGLint *minor)
+{
+ struct droid_egl_display *ddpy;
+ int fd = -1, err, i;
+ const hw_module_t *mod;
+
+ err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod);
+ if (!err) {
+ const gralloc_module_t *gr = (gralloc_module_t *) mod;
+
+ err = -EINVAL;
+ if (gr->perform)
+ err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd);
+ }
+ if (err || fd < 0) {
+ _eglLog(_EGL_WARNING, "fail to get drm fd");
+ return EGL_FALSE;
+ }
+
+ ddpy = calloc(1, sizeof(*ddpy));
+ if (!ddpy)
+ return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+ dpy->DriverData = (void *) ddpy;
+
+ ddpy->fd = fd;
+ if (!droid_load_driver(dpy))
+ return EGL_FALSE;
+
+ ddpy->loader_extension.base.name = __DRI_DRI2_LOADER;
+ ddpy->loader_extension.base.version = 3;
+ ddpy->loader_extension.getBuffers = NULL;
+ ddpy->loader_extension.flushFrontBuffer = droid_flush_front_buffer;
+ ddpy->loader_extension.getBuffersWithFormat =
+ droid_get_buffers_with_format;
+
+ ddpy->extensions[0] = &ddpy->loader_extension.base;
+ ddpy->extensions[1] = &image_lookup_extension.base;
+ ddpy->extensions[2] = &use_invalidate.base;
+ ddpy->extensions[3] = NULL;
+
+ if (!droid_create_screen(dpy)) {
+ free(ddpy);
+ return EGL_FALSE;
+ }
+
+ if (!droid_add_configs_for_visuals(drv, dpy)) {
+ ddpy->core->destroyScreen(ddpy->dri_screen);
+ free(ddpy);
+ }
+
+ dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
+ dpy->Extensions.KHR_image_base = EGL_TRUE;
+
+ /* we're supporting EGL 1.4 */
+ *major = 1;
+ *minor = 4;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+droid_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
+{
+ struct droid_egl_display *ddpy = droid_egl_display(dpy);
+
+ _eglReleaseDisplayResources(drv, dpy);
+ _eglCleanupDisplay(dpy);
+
+ ddpy->core->destroyScreen(ddpy->dri_screen);
+ free(ddpy);
+ dpy->DriverData = NULL;
+
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+droid_initialize(_EGLDriver *drv, _EGLDisplay *dpy,
+ EGLint *major, EGLint *minor)
+{
+ switch (dpy->Platform) {
+ case _EGL_PLATFORM_ANDROID:
+ return droid_initialize_android(drv, dpy, major, minor);
+ default:
+ return EGL_FALSE;
+ }
+}
+
+static _EGLProc
+droid_get_proc_address(_EGLDriver *drv, const char *procname)
+{
+ return (_EGLProc) _glapi_get_proc_address(procname);
+}
+
+
+static void
+droid_unload(_EGLDriver *drv)
+{
+ struct droid_egl_driver *ddrv = droid_egl_driver(drv);
+
+ free(ddrv);
+}
+
+static void
+droid_log(EGLint level, const char *msg)
+{
+ switch (level) {
+ case _EGL_DEBUG:
+ LOGD(msg);
+ break;
+ case _EGL_INFO:
+ LOGI(msg);
+ break;
+ case _EGL_WARNING:
+ LOGW(msg);
+ break;
+ case _EGL_FATAL:
+ LOG_FATAL(msg);
+ break;
+ default:
+ break;
+ }
+}
+
+_EGLDriver *
+droid_create_driver(void)
+{
+ struct droid_egl_driver *ddrv;
+
+ ddrv = calloc(1, sizeof(*ddrv));
+ if (!ddrv)
+ return NULL;
+
+ _eglSetLogProc(droid_log);
+
+ ddrv->base.Name = "Droid";
+ ddrv->base.Unload = droid_unload;
+
+ _eglInitDriverFallbacks(&ddrv->base);
+ ddrv->base.API.Initialize = droid_initialize;
+ ddrv->base.API.Terminate = droid_terminate;
+ ddrv->base.API.GetProcAddress = droid_get_proc_address;
+
+ ddrv->glFlush =
+ (void (*)(void)) droid_get_proc_address(&ddrv->base, "glFlush");
+ ddrv->glFinish =
+ (void (*)(void)) droid_get_proc_address(&ddrv->base, "glFinish");
+
+ return &ddrv->base;
+}
diff --git a/src/egl/drivers/android/droid.h b/src/egl/drivers/android/droid.h
new file mode 100644
index 0000000000..20e32a6588
--- /dev/null
+++ b/src/egl/drivers/android/droid.h
@@ -0,0 +1,126 @@
+/*
+ * 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>
+ */
+
+#ifndef _DROID_H_
+#define _DROID_H_
+
+#include <errno.h>
+
+#include <ui/egl/android_natives.h>
+#include <ui/android_native_buffer.h>
+#include <pixelflinger/format.h>
+
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+
+#include "egldriver.h"
+#include "egldisplay.h"
+#include "eglcontext.h"
+#include "eglsurface.h"
+#include "eglconfig.h"
+#include "eglimage.h"
+#include "eglcurrent.h"
+#include "egllog.h"
+
+struct droid_egl_driver
+{
+ _EGLDriver base;
+
+ void (*glFlush)(void);
+ void (*glFinish)(void);
+};
+
+struct droid_egl_display
+{
+ int fd;
+
+ __DRIscreen *dri_screen;
+ const __DRIconfig **dri_configs;
+ __DRIcoreExtension *core;
+ __DRIdri2Extension *dri2;
+ __DRI2flushExtension *flush;
+ __DRIimageExtension *image;
+
+ __DRIdri2LoaderExtension loader_extension;
+ const __DRIextension *extensions[8];
+};
+
+struct droid_egl_context
+{
+ _EGLContext base;
+
+ __DRIcontext *dri_context;
+};
+
+struct droid_egl_surface
+{
+ _EGLSurface base;
+
+ __DRIdrawable *dri_drawable;
+ __DRIbuffer dri_buffer;
+
+ android_native_window_t *window;
+ android_native_buffer_t *buffer;
+};
+
+struct droid_egl_config
+{
+ _EGLConfig base;
+
+ const __DRIconfig *dri_config;
+};
+
+struct droid_egl_image
+{
+ _EGLImage base;
+
+ __DRIimage *dri_image;
+};
+
+/* standard typecasts */
+_EGL_DRIVER_STANDARD_TYPECASTS(droid_egl)
+_EGL_DRIVER_TYPECAST(droid_egl_image, _EGLImage, obj)
+
+_EGLDriver *
+droid_create_driver(void);
+
+void
+droid_init_core_functions(_EGLDriver *drv);
+
+void
+droid_init_image_functions(_EGLDriver *drv);
+
+EGLBoolean
+droid_dequeue_buffer(struct droid_egl_surface *dsurf);
+
+EGLBoolean
+droid_enqueue_buffer(struct droid_egl_surface *dsurf);
+
+int
+get_native_buffer_name(struct android_native_buffer_t *buf);
+
+#endif /* _DROID_H_ */
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;
+}
diff --git a/src/egl/drivers/android/droid_image.c b/src/egl/drivers/android/droid_image.c
new file mode 100644
index 0000000000..509335bce6
--- /dev/null
+++ b/src/egl/drivers/android/droid_image.c
@@ -0,0 +1,132 @@
+/*
+ * 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 _EGLImage *
+droid_create_image_android_native_buffer(_EGLDisplay *disp,
+ EGLClientBuffer buffer)
+{
+ struct droid_egl_display *ddpy = droid_egl_display(disp);
+ struct android_native_buffer_t *buf =
+ (struct android_native_buffer_t *) buffer;
+ struct droid_egl_image *dimg;
+ EGLint format, name;
+
+ if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
+ buf->common.version != sizeof(*buf)) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ return NULL;
+ }
+
+ name = get_native_buffer_name(buf);
+ if (!name) {
+ _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
+ return NULL;
+ }
+
+ switch (buf->format) {
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ format = __DRI_IMAGE_FORMAT_ARGB8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ format = __DRI_IMAGE_FORMAT_RGB565;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ /* unsupported */
+ default:
+ _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", buf->format);
+ return NULL;
+ break;
+ }
+
+ dimg = calloc(1, sizeof(*dimg));
+ if (!dimg) {
+ _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
+ return NULL;
+ }
+
+ if (!_eglInitImage(&dimg->base, disp)) {
+ free(dimg);
+ return NULL;
+ }
+
+ dimg->dri_image =
+ ddpy->image->createImageFromName(ddpy->dri_screen,
+ buf->width,
+ buf->height,
+ format,
+ name,
+ buf->stride,
+ dimg);
+ if (!dimg->dri_image) {
+ free(dimg);
+ _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
+ return NULL;
+ }
+
+ return &dimg->base;
+}
+
+static _EGLImage *
+droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
+ _EGLContext *ctx, EGLenum target,
+ EGLClientBuffer buffer, const EGLint *attr_list)
+{
+ switch (target) {
+ case EGL_NATIVE_BUFFER_ANDROID:
+ return droid_create_image_android_native_buffer(disp, buffer);
+ default:
+ _eglError(EGL_BAD_PARAMETER, "droid_create_image_khr");
+ return EGL_NO_IMAGE_KHR;
+ }
+}
+
+static EGLBoolean
+droid_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
+{
+ struct droid_egl_display *ddpy = droid_egl_display(disp);
+ struct droid_egl_image *dimg = droid_egl_image(image);
+
+ ddpy->image->destroyImage(dimg->dri_image);
+ free(dimg);
+
+ return EGL_TRUE;
+}
+
+void
+droid_init_image_functions(_EGLDriver *drv)
+{
+ struct droid_egl_driver *ddrv = droid_egl_driver(drv);
+
+ ddrv->base.API.CreateImageKHR = droid_create_image_khr;
+ ddrv->base.API.DestroyImageKHR = droid_destroy_image_khr;
+}
diff --git a/src/egl/drivers/android/egl_android.c b/src/egl/drivers/android/egl_android.c
new file mode 100644
index 0000000000..3f1cb36b78
--- /dev/null
+++ b/src/egl/drivers/android/egl_android.c
@@ -0,0 +1,42 @@
+/*
+ * 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"
+
+_EGLDriver *
+_eglMain(const char *args)
+{
+ _EGLDriver *drv;
+
+ drv = droid_create_driver();
+ if (drv) {
+ droid_init_core_functions(drv);
+ droid_init_image_functions(drv);
+ }
+
+ return drv;
+}