summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olvaffe@gmail.com>2009-09-16 11:19:10 +0800
committerChia-I Wu <olvaffe@gmail.com>2009-09-18 15:32:26 +0800
commit94f9330609ec305d998e58abfddfbbdf8ae51c9d (patch)
tree0455381840b1f481b3f946371f8efe0d93613f76
parent08b9155eee16770c37acd126f5c542937e378e41 (diff)
egl_android: New EGL driver for Android.
-rw-r--r--src/egl/Android.mk41
-rw-r--r--src/egl/drivers/android/droid.h125
-rw-r--r--src/egl/drivers/android/droid_intel.c410
-rw-r--r--src/egl/drivers/android/droid_loader.c474
-rw-r--r--src/egl/drivers/android/droid_ui.cpp54
-rw-r--r--src/egl/drivers/android/droid_ui.h40
-rw-r--r--src/egl/drivers/android/egl_android.c462
-rw-r--r--src/egl/main/egldriver.c6
-rw-r--r--src/egl/main/egltypedefs.h56
9 files changed, 1667 insertions, 1 deletions
diff --git a/src/egl/Android.mk b/src/egl/Android.mk
new file mode 100644
index 0000000000..2dd4df9c17
--- /dev/null
+++ b/src/egl/Android.mk
@@ -0,0 +1,41 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ main/eglapi.c \
+ main/eglclient.c \
+ main/eglconfig.c \
+ main/eglconfigutil.c \
+ main/eglcontext.c \
+ main/eglcurrent.c \
+ main/egldisplay.c \
+ main/egldriver.c \
+ main/eglglobals.c \
+ main/eglimage.c \
+ main/egllog.c \
+ main/eglmisc.c \
+ main/eglmode.c \
+ main/eglscreen.c \
+ main/eglstring.c \
+ main/eglsurface.c
+
+LOCAL_SRC_FILES += \
+ drivers/android/egl_android.c \
+ drivers/android/droid_loader.c \
+ drivers/android/droid_ui.cpp \
+ drivers/android/droid_intel.c
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/main \
+ external/mesa/include \
+ external/mesa/src/mesa \
+ external/drm/shared-core
+
+LOCAL_CFLAGS += -DPTHREADS -D_EGL_PLATFORM_X=1
+LOCAL_SHARED_LIBRARIES := libdl libui libutils
+LOCAL_STATIC_LIBRARIES := libes1api
+
+LOCAL_MODULE := libhgl
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/src/egl/drivers/android/droid.h b/src/egl/drivers/android/droid.h
new file mode 100644
index 0000000000..bed5e8cd75
--- /dev/null
+++ b/src/egl/drivers/android/droid.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ *
+ * This is based on the work of eagle, by
+ * Copyright © 2008, 2009 Kristian Høgsberg
+ *
+ * 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.
+ */
+
+#ifndef _DROID_H_
+#define _DROID_H_
+
+#include "GL/gl.h"
+#include "GL/internal/dri_interface.h"
+
+#include "eglcurrent.h"
+#include "egldisplay.h"
+#include "eglcontext.h"
+#include "eglsurface.h"
+#include "eglconfig.h"
+
+/* opaque types */
+struct droid_loader;
+struct droid_context;
+struct droid_drawable;
+struct droid_surface;
+
+struct droid_backend {
+ /* these are usually used by a loader */
+ const char *driver_name;
+ int (*initialize)(struct droid_backend *backend, int *fd, int *screen_number);
+ void (*destroy)(struct droid_backend *backend);
+
+ __DRIbuffer *(*get_native_buffer)(struct droid_backend *backend,
+ struct droid_surface *surf,
+ int *width, int *height);
+ __DRIbuffer *(*get_surface_buffers)(struct droid_backend *backend,
+ struct droid_surface *surf,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, int has_format);
+
+ /* public methods */
+ struct droid_surface *(*create_window_surface)(struct droid_backend *backend,
+ _EGLSurface *surf,
+ NativeWindowType win);
+ void (*destroy_surface)(struct droid_backend *backend, struct droid_surface *surf);
+ void (*swap_native_buffers)(struct droid_backend *backend,
+ struct droid_surface *surf);
+};
+
+struct droid_screen {
+ struct droid_loader *loader;
+
+ __DRIscreen *dri_screen;
+ __DRItexBufferExtension *tex_buffer;
+ __DRIcopyBufferExtension *copy_buffer;
+
+ const __DRIconfig **dri_configs;
+ int num_dri_configs;
+};
+
+struct droid_backend *
+droid_backend_create_intel(const char *dev);
+
+void
+droid_backend_destroy(struct droid_backend *backend);
+
+struct droid_screen *
+droid_screen_create(struct droid_backend *backend);
+
+void
+droid_screen_destroy(struct droid_screen *screen);
+
+void
+droid_screen_convert_config(struct droid_screen *screen,
+ const __DRIconfig *conf, _EGLConfig *egl_conf);
+
+struct droid_context *
+droid_screen_create_context(struct droid_screen *screen,
+ const __DRIconfig *conf,
+ struct droid_context *shared);
+
+void
+droid_screen_destroy_context(struct droid_screen *screen,
+ struct droid_context *ctx);
+
+struct droid_drawable *
+droid_screen_create_drawable(struct droid_screen *screen,
+ const __DRIconfig *conf,
+ struct droid_surface *surf);
+
+void
+droid_screen_destroy_drawable(struct droid_screen *screen,
+ struct droid_drawable *drawable);
+
+int
+droid_screen_bind_context(struct droid_screen *screen,
+ struct droid_drawable *draw,
+ struct droid_drawable *read,
+ struct droid_context *ctx);
+
+int
+droid_screen_swap_buffers(struct droid_screen *screen,
+ struct droid_context *ctx,
+ struct droid_drawable *drawable);
+
+#endif /* _DROID_H_ */
diff --git a/src/egl/drivers/android/droid_intel.c b/src/egl/drivers/android/droid_intel.c
new file mode 100644
index 0000000000..18fe3bfc95
--- /dev/null
+++ b/src/egl/drivers/android/droid_intel.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ *
+ * This is based on the work of eagle, by
+ * Copyright © 2008, 2009 Kristian Høgsberg
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#define LOG_TAG "DROID-INTEL"
+#include <utils/Log.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <i915_drm.h>
+#include <GL/gl.h> /* dri_interface.h uses some GL integer types... */
+#include <GL/internal/dri_interface.h>
+#include <EGL/egl.h>
+
+#include "droid.h"
+#include "droid_ui.h"
+
+#define INTEL_STRIDE_ALIGNMENT 64
+
+enum {
+ INTEL_SURFACE_TYPE_WINDOW,
+};
+
+struct droid_backend_intel {
+ struct droid_backend base;
+ int fd;
+ int screen_number;
+};
+
+struct droid_surface_intel {
+ int type;
+ union {
+ NativeWindowType win;
+ } native;
+ __DRIbuffer native_buffer;
+ unsigned int native_width, native_height;
+ int native_changed;
+
+ unsigned int attachments[20];
+ __DRIbuffer buffers[10];
+ uint32_t handles[10];
+ int num_buffers;
+ int depth_idx;
+
+ _EGLSurface *surf;
+};
+
+static INLINE struct droid_backend_intel *
+lookup_backend(struct droid_backend *backend)
+{
+ return (struct droid_backend_intel *) backend;
+}
+
+static INLINE struct droid_surface_intel *
+lookup_surface(struct droid_surface *surface)
+{
+ return (struct droid_surface_intel *) surface;
+}
+
+static __DRIbuffer *
+intel_get_native_buffer(struct droid_backend *backend,
+ struct droid_surface *surf,
+ int *width, int *height)
+{
+ struct droid_surface_intel *isurf = lookup_surface(surf);
+
+ if (!isurf->native_buffer.name)
+ return NULL;
+
+ if (width)
+ *width = isurf->native_width;
+ if (height)
+ *height = isurf->native_height;
+
+ return &isurf->native_buffer;
+}
+
+static inline uint32_t
+align_to(uint32_t value, uint32_t align)
+{
+ return (value + align - 1) & ~(align - 1);
+}
+
+static int
+create_buffer(int fd, GLint width, GLint height, GLint cpp, __DRIbuffer *buffer)
+{
+ struct drm_i915_gem_create create;
+ struct drm_gem_flink flink;
+ uint32_t size;
+
+ buffer->pitch = align_to(width * cpp, INTEL_STRIDE_ALIGNMENT);
+ size = buffer->pitch * height;
+ create.size = size;
+ if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create)) {
+ LOGE("failed to create buffer");
+ return 0;
+ }
+
+ flink.handle = create.handle;
+ if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
+ LOGE("failed to flink buffer");
+ return 0;
+ }
+
+ buffer->name = flink.name;
+ buffer->cpp = cpp;
+
+ return create.handle;
+}
+
+static void
+delete_buffers(struct droid_backend *backend, struct droid_surface *surf)
+{
+ struct droid_backend_intel *intel = lookup_backend(backend);
+ struct droid_surface_intel *isurf = lookup_surface(surf);
+ int i;
+
+ for (i = 0; i < isurf->num_buffers; i++) {
+ if (isurf->handles[i]) {
+ struct drm_gem_close close;
+
+ close.handle = isurf->handles[i];
+ if (ioctl(intel->fd, DRM_IOCTL_GEM_CLOSE, &close) < 0)
+ LOGE("failed to close bo %d", close.handle);
+ isurf->handles[i] = 0;
+ }
+ }
+
+ isurf->num_buffers = 0;
+}
+
+static __DRIbuffer *
+intel_get_surface_buffers(struct droid_backend *backend,
+ struct droid_surface *surf,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, int has_format)
+{
+ struct droid_backend_intel *intel = lookup_backend(backend);
+ struct droid_surface_intel *isurf = lookup_surface(surf);
+ unsigned int att_size;
+ __DRIbuffer buffers[10];
+ uint32_t handles[10];
+ int num = 0;
+
+ if (count > 10) {
+ LOGW("too many buffers requested");
+ count = 10;
+ }
+
+ att_size = sizeof(attachments[0]) * count * ((has_format) ? 2 : 1);
+
+ if (isurf->native_changed) {
+ delete_buffers(backend, surf);
+ isurf->native_changed = 0;
+ }
+
+ /* same buffers requested */
+ if (isurf->num_buffers == count &&
+ memcmp(isurf->attachments, attachments, att_size) == 0) {
+ num = isurf->num_buffers;
+ goto end;
+ }
+ memcpy(isurf->attachments, attachments, att_size);
+
+ while (count-- > 0) {
+ unsigned int att = *attachments++;
+ unsigned int format = (has_format) ? *attachments++ : 0;
+ unsigned int cpp = (format) ? format / 8 : isurf->native_buffer.cpp;
+ __DRIbuffer *buf = NULL;
+ int reuse;
+
+ /* re-use buffer */
+ for (reuse = 0; reuse < isurf->num_buffers; reuse++) {
+ if (isurf->buffers[reuse].attachment == att) {
+ if (isurf->buffers[reuse].cpp == cpp &&
+ isurf->handles[reuse])
+ buf = &isurf->buffers[reuse];
+ break;
+ }
+ }
+
+ if (0)
+ LOGD("%s buffer %d: att %d cpp %d",
+ (buf) ? "reuse" : "create", num, att, cpp);
+
+ if (buf) {
+ buffers[num] = isurf->buffers[reuse];
+ handles[num] = isurf->handles[reuse];
+ isurf->handles[reuse] = 0;
+ }
+ else {
+ buffers[num].attachment = att;
+ handles[num] = create_buffer(intel->fd,
+ isurf->native_width,
+ isurf->native_height,
+ cpp,
+ &buffers[num]);
+ }
+ num++;
+ }
+
+ /* delete buffers that are not re-used */
+ delete_buffers(backend, surf);
+
+ memcpy(isurf->buffers, buffers, sizeof(buffers[0]) * num);
+ memcpy(isurf->handles, handles, sizeof(handles[0]) * num);
+ isurf->num_buffers = num;
+
+end:
+ *out_count = num;
+ *width = isurf->native_width;
+ *height = isurf->native_height;
+
+ return isurf->buffers;
+}
+
+static void
+update_native_buffer(struct droid_surface *surf)
+{
+ struct droid_surface_intel *isurf = lookup_surface(surf);
+ unsigned int name, cpp, pitch, width, height;
+
+ switch (isurf->type) {
+ case INTEL_SURFACE_TYPE_WINDOW:
+ /* oem[0] always point to the buffer that a client is drawing to */
+ name = isurf->native.win->oem[0];
+ cpp = ui_bytes_per_pixel(isurf->native.win->format);
+ pitch = isurf->native.win->stride * cpp;
+ width = isurf->native.win->width;
+ height = isurf->native.win->height;
+ break;
+ default:
+ name = cpp = pitch = width = height = 0;
+ break;
+ }
+
+ isurf->native_buffer.attachment = __DRI_BUFFER_FRONT_LEFT;
+ isurf->native_buffer.name = name;
+ isurf->native_buffer.cpp = cpp;
+ isurf->native_buffer.pitch = pitch;
+ isurf->native_buffer.flags = 0;
+
+ isurf->native_width = width;
+ isurf->native_height = height;
+
+ isurf->native_changed = 1;
+}
+
+static struct droid_surface *
+intel_create_window_surface(struct droid_backend *backend,
+ _EGLSurface *surf,
+ NativeWindowType win)
+{
+ struct droid_surface_intel *isurf;
+ uint32_t pitch, cpp;
+
+ if (!win) {
+ LOGE("invalid native window");
+ _eglError(EGL_BAD_NATIVE_WINDOW, "eglCreateWindowSurface");
+ return NULL;
+ }
+
+ /* TODO lift this limitation */
+ if (!win->oem[0]) {
+ LOGE("TODO support for non-gem based window");
+ _eglError(EGL_BAD_NATIVE_WINDOW, "eglCreateWindowSurface");
+ return NULL;
+ }
+
+ cpp = ui_bytes_per_pixel(win->format);
+ pitch = win->stride * cpp;
+
+ isurf = calloc(1, sizeof(*isurf));
+ if (!isurf) {
+ _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
+ return NULL;
+ }
+
+ isurf->type = INTEL_SURFACE_TYPE_WINDOW;
+ isurf->native.win = win;
+
+ surf->Width = win->width;
+ surf->Height = win->height;
+ /* always back buffer */
+ surf->RenderBuffer = EGL_BACK_BUFFER;
+
+ isurf->surf = surf;
+
+ update_native_buffer((struct droid_surface *) isurf);
+
+ return (struct droid_surface *) isurf;
+}
+
+static void
+intel_destroy_surface(struct droid_backend *backend, struct droid_surface *surf)
+{
+ struct droid_surface_intel *isurf = lookup_surface(surf);
+ delete_buffers(backend, surf);
+ free(isurf);
+}
+
+static void
+intel_swap_native_buffers(struct droid_backend *backend,
+ struct droid_surface *surf)
+{
+ struct droid_surface_intel *isurf = lookup_surface(surf);
+
+ if (isurf->type == INTEL_SURFACE_TYPE_WINDOW) {
+ uint32_t flags;
+
+ flags = isurf->native.win->swapBuffers(isurf->native.win);
+ if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) {
+ update_native_buffer(surf);
+ } else {
+ /* oem[0] is changed after buffer swap */
+ isurf->native_buffer.name = isurf->native.win->oem[0];
+ }
+ }
+}
+
+static int
+intel_initialize(struct droid_backend *backend, int *fd, int *screen_number)
+{
+ struct droid_backend_intel *intel = lookup_backend(backend);
+ drm_auth_t auth;
+ int err;
+
+ err = ioctl(intel->fd, DRM_IOCTL_GET_MAGIC, &auth);
+ if (!err)
+ err = ui_auth_gpu(auth.magic);
+
+ if (err) {
+ LOGE("failed to authenticate");
+ return 0;
+ }
+
+ if (fd)
+ *fd = intel->fd;
+ if (screen_number)
+ *screen_number = intel->screen_number;
+
+ return 1;
+}
+
+static void
+intel_destroy(struct droid_backend *backend)
+{
+ struct droid_backend_intel *intel = lookup_backend(backend);
+ close(intel->fd);
+ free(intel);
+}
+
+struct droid_backend *
+droid_backend_create_intel(const char *dev)
+{
+ struct droid_backend_intel *intel;
+
+ intel = calloc(1, sizeof(*intel));
+ if (!intel)
+ return NULL;
+
+ intel->fd = open(dev, O_RDWR);
+ if (intel->fd < 0) {
+ LOGE("failed to open %s", dev);
+ free(intel);
+ return NULL;
+ }
+
+ intel->screen_number = 0;
+ intel->base.driver_name = "i915";
+ intel->base.initialize = intel_initialize;
+ intel->base.destroy = intel_destroy;
+
+ intel->base.get_native_buffer = intel_get_native_buffer;
+ intel->base.get_surface_buffers = intel_get_surface_buffers;
+
+ intel->base.create_window_surface = intel_create_window_surface;
+ intel->base.destroy_surface = intel_destroy_surface;
+ intel->base.swap_native_buffers = intel_swap_native_buffers;
+
+ return &intel->base;
+}
diff --git a/src/egl/drivers/android/droid_loader.c b/src/egl/drivers/android/droid_loader.c
new file mode 100644
index 0000000000..1d02b49322
--- /dev/null
+++ b/src/egl/drivers/android/droid_loader.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
+ *
+ * This is based on the work of eagle, by
+ * Copyright © 2008, 2009 Kristian Høgsberg
+ *
+ * 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.
+ */
+
+#define LOG_TAG "DROID-LOADER"
+#include <utils/Log.h>
+
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <assert.h>
+
+#include "droid.h"
+
+#ifndef DROID_DRIVER_PATH
+#define DROID_DRIVER_PATH "/system/lib"
+#endif
+
+struct droid_loader {
+ struct droid_backend *backend;
+
+ char *filename;
+ void *handle;
+
+ __DRIcoreExtension *core;
+ __DRIdri2Extension *dri2;
+};
+
+struct droid_context {
+ __DRIcontext *dri_context;
+};
+
+struct droid_drawable {
+ struct droid_loader *loader;
+ struct droid_surface *surface;
+
+ __DRIdrawable *dri_drawable;
+};
+
+static __DRIbuffer *
+loader_ext_get_buffers_with_format(__DRIdrawable *driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
+{
+ struct droid_drawable *drawable = (struct droid_drawable *) loaderPrivate;
+ struct droid_loader *loader = drawable->loader;
+ __DRIbuffer *buffers;
+
+ buffers = loader->backend->get_surface_buffers(loader->backend,
+ drawable->surface,
+ width, height,
+ attachments, count,
+ out_count, 1);
+
+ return buffers;
+}
+
+static const __DRIdri2LoaderExtension loader_ext_dri2_loader = {
+ { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
+ NULL,
+ NULL,
+ loader_ext_get_buffers_with_format,
+};
+
+static int
+loader_ext_get_ust(int64_t *ust)
+{
+ struct timeval tv;
+
+ if (ust == NULL)
+ return -EFAULT;
+
+ if (gettimeofday(&tv, NULL) == 0) {
+ ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
+ return 0;
+ } else {
+ return -errno;
+ }
+}
+
+static const __DRIsystemTimeExtension loader_ext_system_time = {
+ { __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION },
+ loader_ext_get_ust,
+ NULL,
+};
+
+static const __DRIextension *loader_extensions[] = {
+ &loader_ext_dri2_loader.base,
+ &loader_ext_system_time.base,
+ NULL
+};
+
+static struct droid_loader *
+loader_create(struct droid_backend *backend)
+{
+ struct droid_loader *loader;
+
+ loader = calloc(1, sizeof(*loader));
+ if (!loader)
+ return NULL;
+
+ loader->backend = backend;
+
+ return loader;
+}
+
+static void
+loader_destroy(struct droid_loader *loader)
+{
+ if (loader->filename)
+ free(loader->filename);
+ if (loader->handle)
+ dlclose(loader->handle);
+ free(loader);
+}
+
+static int
+loader_load(struct droid_loader *loader, const char *filename)
+{
+ const __DRIextension **extensions;
+ const char *path = NULL;
+ int i;
+
+ LOGD("Loading DRI driver %s", filename);
+
+ loader->handle = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
+ if (loader->handle == NULL) {
+ LOGE("dlopen: %s", dlerror());
+ return 0;
+ }
+
+ extensions = dlsym(loader->handle, __DRI_DRIVER_EXTENSIONS);
+ if (extensions == NULL) {
+ LOGE("dlsym: %s", dlerror());
+ dlclose(loader->handle);
+ loader->handle = NULL;
+ return 0;
+ }
+
+ for (i = 0; extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
+ extensions[i]->version >= __DRI_CORE_VERSION) {
+ loader->core = (__DRIcoreExtension *) extensions[i];
+ }
+
+ if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
+ extensions[i]->version >= __DRI_DRI2_VERSION) {
+ loader->dri2 = (__DRIdri2Extension *) extensions[i];
+ }
+ }
+
+ if (loader->core == NULL || loader->dri2 == NULL) {
+ LOGE("missing required DRI extensions");
+ dlclose(loader->handle);
+ loader->handle = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+loader_init(struct droid_loader *loader)
+{
+ char filename[1024];
+ const char *path;
+
+ path = DROID_DRIVER_PATH;
+ snprintf(filename, sizeof(filename), "%s/%s_dri.so",
+ path, loader->backend->driver_name);
+
+ if (!loader_load(loader, filename))
+ return 0;
+
+ loader->filename = strdup(filename);
+
+ return 1;
+}
+
+void
+droid_backend_destroy(struct droid_backend *backend)
+{
+ backend->destroy(backend);
+}
+
+struct droid_screen *
+droid_screen_create(struct droid_backend *backend)
+{
+ struct droid_screen *screen = NULL;
+ struct droid_loader *loader;
+ const __DRIextension **extensions;
+ int fd, screen_number;
+ int i;
+
+ loader = loader_create(backend);
+ if (!loader || !loader_init(loader)) {
+ LOGE("failed to initialize loader");
+ goto fail;
+ }
+
+ screen = calloc(1, sizeof(*screen));
+ if (!screen) {
+ LOGE("failed to allocate new screen");
+ goto fail;
+ }
+
+ if (!loader->backend->initialize(loader->backend, &fd, &screen_number)) {
+ LOGE("failed to initialize backend");
+ goto fail;
+ }
+
+ screen->loader = loader;
+ screen->dri_screen =
+ loader->dri2->createNewScreen(screen_number, fd,
+ loader_extensions,
+ &screen->dri_configs, NULL);
+ if (!screen->dri_screen) {
+ LOGE("failed to create DRI screen");
+ goto fail;
+ }
+
+ extensions = loader->core->getExtensions(screen->dri_screen);
+
+ for (i = 0; extensions && extensions[i]; i++) {
+ if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0 &&
+ extensions[i]->version >= __DRI_TEX_BUFFER_VERSION)
+ screen->tex_buffer = (__DRItexBufferExtension *) extensions[i];
+
+ if (strcmp(extensions[i]->name, __DRI_COPY_BUFFER) == 0 &&
+ extensions[i]->version >= __DRI_COPY_BUFFER_VERSION)
+ screen->copy_buffer = (__DRIcopyBufferExtension *) extensions[i];
+ }
+
+ if (!screen->tex_buffer) {
+ LOGE("DRI driver has no TexBuffer extension");
+ goto fail;
+ }
+
+ if (!screen->tex_buffer) {
+ LOGE("DRI driver has no CopyBuffer extension");
+ goto fail;
+ }
+
+ for (i = 0; screen->dri_configs[i]; i++)
+ ;
+ screen->num_dri_configs = i;
+
+ return screen;
+
+fail:
+ if (screen)
+ droid_screen_destroy(screen);
+ if (loader)
+ loader_destroy(loader);
+
+ return NULL;
+}
+
+void
+droid_screen_destroy(struct droid_screen *screen)
+{
+ struct droid_loader *loader = screen->loader;
+ if (screen->dri_screen)
+ loader->core->destroyScreen(screen->dri_screen);
+ free(screen);
+}
+
+static const struct {
+ EGLenum egl_attrib;
+ unsigned int dri_attrib;
+} droid_attrib_map[] = {
+ { EGL_BUFFER_SIZE, __DRI_ATTRIB_BUFFER_SIZE },
+ { EGL_RED_SIZE, __DRI_ATTRIB_RED_SIZE },
+ { EGL_GREEN_SIZE, __DRI_ATTRIB_GREEN_SIZE },
+ { EGL_BLUE_SIZE, __DRI_ATTRIB_BLUE_SIZE },
+ { EGL_ALPHA_SIZE, __DRI_ATTRIB_ALPHA_SIZE },
+ { EGL_BIND_TO_TEXTURE_RGB, __DRI_ATTRIB_BIND_TO_TEXTURE_RGB },
+ { EGL_BIND_TO_TEXTURE_RGBA, __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA },
+ { EGL_CONFIG_CAVEAT, __DRI_ATTRIB_CONFIG_CAVEAT },
+ { EGL_DEPTH_SIZE, __DRI_ATTRIB_DEPTH_SIZE },
+ { EGL_LEVEL, __DRI_ATTRIB_LEVEL },
+ { 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 },
+ { EGL_SAMPLE_BUFFERS, __DRI_ATTRIB_SAMPLE_BUFFERS },
+ { EGL_SAMPLES, __DRI_ATTRIB_SAMPLES },
+ { EGL_STENCIL_SIZE, __DRI_ATTRIB_STENCIL_SIZE },
+};
+
+void
+droid_screen_convert_config(struct droid_screen *screen,
+ const __DRIconfig *conf, _EGLConfig *egl_conf)
+{
+ struct droid_loader *loader = screen->loader;
+ const int num_attrs =
+ sizeof(droid_attrib_map) / sizeof(droid_attrib_map[0]);
+ int i;
+
+ for (i = 0; i < num_attrs; i++) {
+ unsigned int dri_attrib = droid_attrib_map[i].dri_attrib;
+ unsigned int dri_value;
+ EGLenum egl_attrib = droid_attrib_map[i].egl_attrib;
+ EGLint egl_value;
+
+ if (!loader->core->getConfigAttrib(conf, dri_attrib, &dri_value)) {
+ LOGE("failed to get attribute %02d for %p", dri_attrib, conf);
+ continue;
+ }
+
+ switch (egl_attrib) {
+ case EGL_CONFIG_CAVEAT:
+ if (dri_value & __DRI_ATTRIB_SLOW_BIT)
+ egl_value = EGL_SLOW_CONFIG;
+ else if (dri_value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
+ egl_value = EGL_NON_CONFORMANT_CONFIG;
+ else
+ egl_value = EGL_NONE;
+ break;
+ default:
+ egl_value = (EGLint) dri_value;
+ break;
+ }
+ SET_CONFIG_ATTRIB(egl_conf, egl_attrib, egl_value);
+ }
+}
+
+struct droid_context *
+droid_screen_create_context(struct droid_screen *screen,
+ const __DRIconfig *conf,
+ struct droid_context *shared)
+{
+ struct droid_loader *loader = screen->loader;
+ struct droid_context *ctx;
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (!ctx) {
+ LOGE("failed to allocate context");
+ return NULL;
+ }
+
+ ctx->dri_context =
+ loader->dri2->createNewContext(screen->dri_screen, conf,
+ (shared) ? shared->dri_context : NULL,
+ NULL);
+ if (!ctx->dri_context) {
+ LOGE("failed to create DRI context");
+ free(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+void
+droid_screen_destroy_context(struct droid_screen *screen,
+ struct droid_context *ctx)
+{
+ struct droid_loader *loader = screen->loader;
+ loader->core->destroyContext(ctx->dri_context);
+ free(ctx);
+}
+
+struct droid_drawable *
+droid_screen_create_drawable(struct droid_screen *screen,
+ const __DRIconfig *conf,
+ struct droid_surface *surf)
+{
+ struct droid_loader *loader = screen->loader;
+ struct droid_drawable *drawable;
+
+ drawable = calloc(1, sizeof(*drawable));
+ if (!drawable) {
+ LOGE("failed to allocate drawable");
+ return NULL;
+ }
+
+ /* needed in GetBuffers */
+ drawable->loader = loader;
+ drawable->surface = surf;
+
+ drawable->dri_drawable =
+ loader->dri2->createNewDrawable(screen->dri_screen,
+ conf, (void *) drawable);
+ if (!drawable->dri_drawable) {
+ LOGE("failed to create DRI drawable");
+ free(drawable);
+ return NULL;
+ }
+
+ return drawable;
+}
+
+void
+droid_screen_destroy_drawable(struct droid_screen *screen,
+ struct droid_drawable *drawable)
+{
+ struct droid_loader *loader = screen->loader;
+ loader->core->destroyDrawable(drawable->dri_drawable);
+ free(drawable);
+}
+
+int
+droid_screen_bind_context(struct droid_screen *screen,
+ struct droid_drawable *draw,
+ struct droid_drawable *read,
+ struct droid_context *ctx)
+{
+ struct droid_loader *loader = screen->loader;
+ int ret = 0;
+
+ if (ctx) {
+ if (draw && read)
+ ret = loader->core->bindContext(ctx->dri_context,
+ draw->dri_drawable,
+ read->dri_drawable);
+ else if (!draw && !read)
+ ret = loader->core->unbindContext(ctx->dri_context);
+ }
+
+ if (!ret)
+ LOGE("failed to bind context %p", ctx);
+
+ return ret;
+}
+
+int
+droid_screen_swap_buffers(struct droid_screen *screen,
+ struct droid_context *ctx,
+ struct droid_drawable *drawable)
+{
+ struct droid_loader *loader = screen->loader;
+ __DRIbuffer *native;
+ int width, height;
+ int err = 0;
+
+ native = loader->backend->get_native_buffer(loader->backend,
+ drawable->surface,
+ &width, &height);
+
+ /* copy from front buffer to native buffer */
+ if (native)
+ err = screen->copy_buffer->copyBuffer(ctx->dri_context, native, 0, 0,
+ drawable->dri_drawable,
+ __DRI_BUFFER_FRONT_LEFT, 0, 0,
+ width, height);
+
+ if (!err)
+ loader->backend->swap_native_buffers(loader->backend, drawable->surface);
+
+ return (!err);
+}
diff --git a/src/egl/drivers/android/droid_ui.cpp b/src/egl/drivers/android/droid_ui.cpp
new file mode 100644
index 0000000000..6ceff1b5fb
--- /dev/null
+++ b/src/egl/drivers/android/droid_ui.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 <ui/PixelFormat.h>
+#include <ui/ISurfaceComposer.h>
+
+#include "droid_ui.h"
+
+using namespace android;
+
+namespace android {
+ const sp<ISurfaceComposer>& _get_surface_manager();
+};
+
+int
+ui_auth_gpu(drm_magic_t magic)
+{
+ /*
+ * surface flinger itself or root; we might want something like
+ * getSurfaceFlinger() from libEGL
+ */
+ if (getuid() == 1000 || getuid() == 0)
+ return 0;
+
+ sp<ISurfaceComposer> sm(_get_surface_manager());
+ if (sm == NULL)
+ return -ENODEV;
+ return sm->authGPU(magic);
+}
+
+int ui_bytes_per_pixel(int format)
+{
+ return bytesPerPixel(format);
+}
diff --git a/src/egl/drivers/android/droid_ui.h b/src/egl/drivers/android/droid_ui.h
new file mode 100644
index 0000000000..3153ec849f
--- /dev/null
+++ b/src/egl/drivers/android/droid_ui.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef _DROID_UI_H
+#define _DROID_UI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus */
+
+#include <drm.h>
+
+int ui_auth_gpu(drm_magic_t magic);
+int ui_bytes_per_pixel(int format);
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus */
+
+#endif /* _DROID_UI_H */
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;
+}
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index 89e04a7130..f693b304d4 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -195,7 +195,11 @@ _eglLoadDriver(char *path, char *args)
lib_handle lib;
_EGLDriver *drv = NULL;
- mainFunc = _eglOpenLibrary(path, &lib);
+ /* temporary hack */
+ (void) _eglOpenLibrary;
+ mainFunc = _eglMain;
+ lib = (lib_handle) 0;
+
if (!mainFunc)
return NULL;
diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h
index b6321716d3..a62d1edc27 100644
--- a/src/egl/main/egltypedefs.h
+++ b/src/egl/main/egltypedefs.h
@@ -6,6 +6,62 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#ifndef EGL_MESA_screen_surface
+#define EGL_MESA_screen_surface 1
+
+#define EGL_BAD_SCREEN_MESA 0x4000
+#define EGL_BAD_MODE_MESA 0x4001
+#define EGL_SCREEN_COUNT_MESA 0x4002
+#define EGL_SCREEN_POSITION_MESA 0x4003
+#define EGL_SCREEN_POSITION_GRANULARITY_MESA 0x4004
+#define EGL_MODE_ID_MESA 0x4005
+#define EGL_REFRESH_RATE_MESA 0x4006
+#define EGL_OPTIMAL_MESA 0x4007
+#define EGL_INTERLACED_MESA 0x4008
+#define EGL_SCREEN_BIT_MESA 0x08
+
+typedef uint32_t EGLScreenMESA;
+typedef uint32_t EGLModeMESA;
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
+EGLAPI EGLSurface EGLAPIENTRY eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
+EGLAPI const char * EGLAPIENTRY eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCHOOSEMODEMESA) (EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETMODESMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGetModeATTRIBMESA) (EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSCRREENSMESA) (EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESCREENSURFACEMESA) (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSHOWSCREENSURFACEMESA) (EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSCREENPOSIITONMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSCREENMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSCREENSURFACEMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSCREENMODEMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
+typedef const char * (EGLAPIENTRYP PFNEGLQUERYMODESTRINGMESA) (EGLDisplay dpy, EGLModeMESA mode);
+
+#endif /* EGL_MESA_screen_surface */
+
+#ifndef EGL_MESA_copy_context
+#define EGL_MESA_copy_context 1
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOPYCONTEXTMESA) (EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
+
+#endif /* EGL_MESA_copy_context */
+
#include "eglcompiler.h"
typedef struct _egl_api _EGLAPI;