From 94f9330609ec305d998e58abfddfbbdf8ae51c9d Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 16 Sep 2009 11:19:10 +0800 Subject: egl_android: New EGL driver for Android. --- src/egl/Android.mk | 41 +++ src/egl/drivers/android/droid.h | 125 +++++++++ src/egl/drivers/android/droid_intel.c | 410 ++++++++++++++++++++++++++++ src/egl/drivers/android/droid_loader.c | 474 +++++++++++++++++++++++++++++++++ src/egl/drivers/android/droid_ui.cpp | 54 ++++ src/egl/drivers/android/droid_ui.h | 40 +++ src/egl/drivers/android/egl_android.c | 462 ++++++++++++++++++++++++++++++++ src/egl/main/egldriver.c | 6 +- src/egl/main/egltypedefs.h | 56 ++++ 9 files changed, 1667 insertions(+), 1 deletion(-) create mode 100644 src/egl/Android.mk create mode 100644 src/egl/drivers/android/droid.h create mode 100644 src/egl/drivers/android/droid_intel.c create mode 100644 src/egl/drivers/android/droid_loader.c create mode 100644 src/egl/drivers/android/droid_ui.cpp create mode 100644 src/egl/drivers/android/droid_ui.h create mode 100644 src/egl/drivers/android/egl_android.c 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 + * + * 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 + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* dri_interface.h uses some GL integer types... */ +#include +#include + +#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 + * + * 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 + +#include +#include +#include +#include + +#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 + * + * 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 +#include + +#include "droid_ui.h" + +using namespace android; + +namespace android { + const sp& _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 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 + * + * 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 + +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 + * + * 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 #include +#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; -- cgit v1.2.3