diff options
author | Chia-I Wu <olv@lunarg.com> | 2010-10-11 16:30:03 +0800 |
---|---|---|
committer | Chia-I Wu <olvaffe@gmail.com> | 2011-03-16 20:18:39 +0800 |
commit | 17cd318e4131454063fae3174be945450ec1e263 (patch) | |
tree | 463258d2c944b661d3d30a4279ec72bfa3eddd8e | |
parent | f2d8241f014ea0f7f0a82cda9992986c93ed7962 (diff) |
android: Add android backend for st/egl.
-rw-r--r-- | src/gallium/state_trackers/egl/android/native_android.cpp | 695 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d.c | 11 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d.h | 3 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d_image.c | 83 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/native.h | 3 | ||||
-rw-r--r-- | src/gallium/winsys/sw/android/android_sw_winsys.cpp | 269 | ||||
-rw-r--r-- | src/gallium/winsys/sw/android/android_sw_winsys.h | 49 |
7 files changed, 1113 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/egl/android/native_android.cpp b/src/gallium/state_trackers/egl/android/native_android.cpp new file mode 100644 index 0000000000..8e964be97d --- /dev/null +++ b/src/gallium/state_trackers/egl/android/native_android.cpp @@ -0,0 +1,695 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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 shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#define LOG_TAG "MESA-EGL" +#include <cutils/log.h> +#include <cutils/properties.h> +#include <ui/PixelFormat.h> +#include <ui/android_native_buffer.h> + +extern "C" { +#include "egllog.h" +} +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "common/native.h" +#include "common/native_helper.h" +#include "android/android_sw_winsys.h" +#include "state_tracker/drm_driver.h" + +struct android_config; + +struct android_display { + struct native_display base; + + boolean use_drm; + struct native_event_handler *event_handler; + struct android_config *configs; + int num_configs; +}; + +struct android_surface { + struct native_surface base; + + struct android_display *adpy; + android_native_window_t *win; + + uint stamp; + android_native_buffer_t *buf; + struct pipe_resource *res; + + /* cache the current front and back resources */ + void *cache_handles[2]; + struct pipe_resource *cache_resources[2]; +}; + +struct android_config { + struct native_config base; +}; + +static INLINE struct android_display * +android_display(const struct native_display *ndpy) +{ + return (struct android_display *) ndpy; +} + +static INLINE struct android_surface * +android_surface(const struct native_surface *nsurf) +{ + return (struct android_surface *) nsurf; +} + +static INLINE struct android_config * +android_config(const struct native_config *nconf) +{ + return (struct android_config *) nconf; +} + +namespace android { + +static enum pipe_format +get_pipe_format(int native) +{ + enum pipe_format fmt; + + /* see libpixelflinger/format.cpp */ + switch (native) { + case PIXEL_FORMAT_RGBA_8888: + fmt = PIPE_FORMAT_R8G8B8A8_UNORM; + break; + case PIXEL_FORMAT_RGBX_8888: + fmt = PIPE_FORMAT_R8G8B8X8_UNORM; + break; + case PIXEL_FORMAT_RGB_888: + fmt = PIPE_FORMAT_R8G8B8_UNORM; + break; + case PIXEL_FORMAT_RGB_565: + fmt = PIPE_FORMAT_B5G6R5_UNORM; + break; + case PIXEL_FORMAT_BGRA_8888: + fmt = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case PIXEL_FORMAT_A_8: + fmt = PIPE_FORMAT_A8_UNORM; + break; + case PIXEL_FORMAT_L_8: + fmt = PIPE_FORMAT_L8_UNORM; + break; + case PIXEL_FORMAT_LA_88: + fmt = PIPE_FORMAT_L8A8_UNORM; + break; + case PIXEL_FORMAT_NONE: + case PIXEL_FORMAT_RGBA_5551: + case PIXEL_FORMAT_RGBA_4444: + case PIXEL_FORMAT_RGB_332: + default: + LOGE("unsupported native format 0x%x", native); + fmt = PIPE_FORMAT_NONE; + break; + } + + return fmt; +} + +#include <gralloc_gem.h> +static int +get_handle_name(buffer_handle_t handle) +{ + struct drm_bo_t *bo; + + bo = drm_gem_get(handle); + + return (bo) ? bo->name : 0; +} + +static struct pipe_resource * +import_buffer(struct android_display *adpy, const struct pipe_resource *templ, + struct android_native_buffer_t *abuf) +{ + struct pipe_screen *screen = adpy->base.screen; + struct pipe_resource *res; + + if (templ->bind & PIPE_BIND_RENDER_TARGET) { + if (!screen->is_format_supported(screen, templ->format, + templ->target, 0, PIPE_BIND_RENDER_TARGET, 0)) + LOGW("importing unsupported buffer as render target"); + } + if (templ->bind & PIPE_BIND_SAMPLER_VIEW) { + if (!screen->is_format_supported(screen, templ->format, + templ->target, 0, PIPE_BIND_SAMPLER_VIEW, 0)) + LOGW("importing unsupported buffer as sampler view"); + } + + if (adpy->use_drm) { + struct winsys_handle handle; + + memset(&handle, 0, sizeof(handle)); + handle.type = DRM_API_HANDLE_TYPE_SHARED; + handle.handle = get_handle_name(abuf->handle); + if (!handle.handle) { + LOGE("unable to import invalid buffer %p", abuf); + return NULL; + } + + handle.stride = + abuf->stride * util_format_get_blocksize(templ->format); + + res = screen->resource_from_handle(screen, templ, &handle); + } + else { + struct android_winsys_handle handle; + + memset(&handle, 0, sizeof(handle)); + handle.handle = abuf->handle; + handle.stride = + abuf->stride * util_format_get_blocksize(templ->format); + + res = screen->resource_from_handle(screen, + templ, (struct winsys_handle *) &handle); + } + + if (!res) + LOGE("failed to import buffer %p", abuf); + + return res; +} + +static boolean +android_surface_dequeue_buffer(struct native_surface *nsurf) +{ + struct android_surface *asurf = android_surface(nsurf); + void *handle; + int idx; + + if (asurf->win->dequeueBuffer(asurf->win, &asurf->buf) != NO_ERROR) { + LOGE("failed to dequeue window %p", asurf->win); + return FALSE; + } + + asurf->buf->common.incRef(&asurf->buf->common); + asurf->win->lockBuffer(asurf->win, asurf->buf); + + if (asurf->adpy->use_drm) + handle = (void *) get_handle_name(asurf->buf->handle); + else + handle = (void *) asurf->buf->handle; + /* NULL is invalid */ + if (!handle) { + LOGE("window %p returned an invalid buffer", asurf->win); + return TRUE; + } + + /* find the slot to use */ + for (idx = 0; idx < Elements(asurf->cache_handles); idx++) { + if (asurf->cache_handles[idx] == handle || !asurf->cache_handles[idx]) + break; + } + if (idx == Elements(asurf->cache_handles)) { + /* buffer reallocated; clear the cache */ + for (idx = 0; idx < Elements(asurf->cache_handles); idx++) { + asurf->cache_handles[idx] = 0; + pipe_resource_reference(&asurf->cache_resources[idx], NULL); + } + idx = 0; + } + + /* update the cache */ + if (!asurf->cache_handles[idx]) { + struct pipe_resource templ; + + assert(!asurf->cache_resources[idx]); + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = asurf->buf->width; + templ.height0 = asurf->buf->height; + templ.depth0 = 1; + templ.bind = PIPE_BIND_RENDER_TARGET; + if (!asurf->adpy->use_drm) { + templ.bind |= PIPE_BIND_TRANSFER_WRITE | + PIPE_BIND_TRANSFER_READ; + } + + templ.format = get_pipe_format(asurf->buf->format); + if (templ.format != PIPE_FORMAT_NONE) { + asurf->cache_resources[idx] = + import_buffer(asurf->adpy, &templ, asurf->buf); + } + else { + asurf->cache_resources[idx] = NULL; + } + + asurf->cache_handles[idx] = handle; + } + + pipe_resource_reference(&asurf->res, asurf->cache_resources[idx]); + + return TRUE; +} + +static boolean +android_surface_enqueue_buffer(struct native_surface *nsurf) +{ + struct android_surface *asurf = android_surface(nsurf); + + pipe_resource_reference(&asurf->res, NULL); + + asurf->win->queueBuffer(asurf->win, asurf->buf); + + asurf->buf->common.decRef(&asurf->buf->common); + asurf->buf = NULL; + + return TRUE; +} + +static boolean +android_surface_swap_buffers(struct native_surface *nsurf) +{ + struct android_surface *asurf = android_surface(nsurf); + struct android_display *adpy = asurf->adpy; + + if (!asurf->buf) + return FALSE; + + android_surface_enqueue_buffer(&asurf->base); + + asurf->stamp++; + adpy->event_handler->invalid_surface(&adpy->base, + &asurf->base, asurf->stamp); + + return TRUE; +} + +static boolean +android_surface_present(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval) +{ + boolean ret; + + if (swap_interval || natt != NATIVE_ATTACHMENT_BACK_LEFT) + return FALSE; + + return android_surface_swap_buffers(nsurf); +} + +static boolean +android_surface_validate(struct native_surface *nsurf, uint attachment_mask, + unsigned int *seq_num, struct pipe_resource **textures, + int *width, int *height) +{ + struct android_surface *asurf = android_surface(nsurf); + struct winsys_handle handle; + + if (!asurf->buf) { + if (!android_surface_dequeue_buffer(&asurf->base)) + return FALSE; + } + + if (textures) { + const enum native_attachment att = NATIVE_ATTACHMENT_BACK_LEFT; + + if (native_attachment_mask_test(attachment_mask, att)) { + textures[att] = NULL; + pipe_resource_reference(&textures[att], asurf->res); + } + } + + if (seq_num) + *seq_num = asurf->stamp; + if (width) + *width = asurf->buf->width; + if (height) + *height = asurf->buf->height; + + return TRUE; +} + +static void +android_surface_wait(struct native_surface *nsurf) +{ +} + +static void +android_surface_destroy(struct native_surface *nsurf) +{ + struct android_surface *asurf = android_surface(nsurf); + int i; + + if (asurf->buf) + android_surface_enqueue_buffer(&asurf->base); + + for (i = 0; i < Elements(asurf->cache_handles); i++) + pipe_resource_reference(&asurf->cache_resources[i], NULL); + + asurf->win->common.decRef(&asurf->win->common); + + FREE(asurf); +} + +static struct native_surface * +android_display_create_window_surface(struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf) +{ + struct android_display *adpy = android_display(ndpy); + struct android_config *aconf = android_config(nconf); + struct android_surface *asurf; + enum pipe_format format; + int val; + + if (win->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { + LOGE("invalid native window with magic 0x%x", win->common.magic); + return NULL; + } + if (win->query(win, NATIVE_WINDOW_FORMAT, &val)) { + LOGE("failed to query native window format"); + return NULL; + } + format = get_pipe_format(val); + if (format != nconf->color_format) { + LOGW("native window format 0x%x != config format 0x%x", + format, nconf->color_format); + if (!adpy->base.screen->is_format_supported(adpy->base.screen, + format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, 0)) { + LOGE("and the native window cannot be used as a render target"); + return NULL; + } + } + + asurf = CALLOC_STRUCT(android_surface); + if (!asurf) + return NULL; + + asurf->adpy = adpy; + asurf->win = win; + + asurf->win->common.incRef(&asurf->win->common); + if (!adpy->use_drm) { + native_window_set_usage(asurf->win, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + } + + asurf->base.destroy = android_surface_destroy; + asurf->base.present = android_surface_present; + asurf->base.validate = android_surface_validate; + asurf->base.wait = android_surface_wait; + + return &asurf->base; +} + +static boolean +android_display_init_configs(struct native_display *ndpy) +{ + struct android_display *adpy = android_display(ndpy); + const int native_formats[] = { + PIXEL_FORMAT_RGBA_8888, + PIXEL_FORMAT_RGBX_8888, + PIXEL_FORMAT_RGB_888, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGRA_8888, + PIXEL_FORMAT_A_8 + }; + int i; + + adpy->configs = (struct android_config *) + CALLOC(Elements(native_formats), sizeof(*adpy->configs)); + if (!adpy->configs) + return FALSE; + + for (i = 0; i < Elements(native_formats); i++) { + enum pipe_format color_format; + struct android_config *aconf; + + color_format = get_pipe_format(native_formats[i]); + if (color_format == PIPE_FORMAT_NONE || + !adpy->base.screen->is_format_supported(adpy->base.screen, + color_format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, 0)) { + LOGI("skip unsupported native format 0x%x", native_formats[i]); + continue; + } + + aconf = &adpy->configs[adpy->num_configs++]; + aconf->base.buffer_mask = 1 << NATIVE_ATTACHMENT_BACK_LEFT; + aconf->base.color_format = color_format; + aconf->base.window_bit = TRUE; + + aconf->base.native_visual_type = native_formats[i]; + } + + return TRUE; +} + +static boolean +android_display_init_drm(struct native_display *ndpy) +{ + struct android_display *adpy = android_display(ndpy); + const hw_module_t *mod; + int fd, err; + + err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); + if (!err) { + const gralloc_module_t *gr = (gralloc_module_t *) mod; + + err = -EINVAL; + if (gr->perform) + err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd); + } + if (!err && fd >= 0) { + adpy->base.screen = + adpy->event_handler->new_drm_screen(&adpy->base, "i915", fd); + if (adpy->base.screen) + adpy->use_drm = TRUE; + } + + if (adpy->base.screen) { + LOGI("using DRM screen"); + return TRUE; + } + else { + LOGE("failed to create DRM screen"); + return FALSE; + } +} + +static boolean +android_display_init_sw(struct native_display *ndpy) +{ + struct android_display *adpy = android_display(ndpy); + struct sw_winsys *ws; + + ws = android_create_sw_winsys(); + if (ws) { + adpy->base.screen = + adpy->event_handler->new_sw_screen(&adpy->base, ws); + } + + if (adpy->base.screen) { + LOGI("using SW screen"); + return TRUE; + } + else { + LOGE("failed to create SW screen"); + return FALSE; + } +} + +static void +android_display_destroy(struct native_display *ndpy) +{ + struct android_display *adpy = android_display(ndpy); + + FREE(adpy->configs); + adpy->base.screen->destroy(adpy->base.screen); + FREE(adpy); +} + +static const struct native_config ** +android_display_get_configs(struct native_display *ndpy, int *num_configs) +{ + struct android_display *adpy = android_display(ndpy); + const struct native_config **configs; + int i; + + configs = (const struct native_config **) + MALLOC(adpy->num_configs * sizeof(*configs)); + if (configs) { + for (i = 0; i < adpy->num_configs; i++) + configs[i] = (const struct native_config *) &adpy->configs[i]; + if (num_configs) + *num_configs = adpy->num_configs; + } + + return configs; +} + +static int +android_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + default: + val = 0; + break; + } + + return val; +} + +static struct pipe_resource * +android_display_import_buffer(struct native_display *ndpy, + const struct pipe_resource *templ, + void *buf) +{ + struct android_display *adpy = android_display(ndpy); + struct android_native_buffer_t *abuf = + (struct android_native_buffer_t *) buf; + + return import_buffer(adpy, templ, abuf); +} + +static boolean +android_display_export_buffer(struct native_display *ndpy, + struct pipe_resource *res, + void *buf) +{ + return FALSE; +} + +static struct native_display_buffer android_display_buffer = { + android_display_import_buffer, + android_display_export_buffer +}; + +static struct android_display * +android_display_create(struct native_event_handler *event_handler, + boolean use_sw, void *user_data) +{ + struct android_display *adpy; + char value[PROPERTY_VALUE_MAX]; + boolean force_sw; + + adpy = CALLOC_STRUCT(android_display); + if (!adpy) + return NULL; + + adpy->event_handler = event_handler; + adpy->base.user_data = user_data; + + if (property_get("debug.mesa.software", value, NULL)) + force_sw = (atoi(value) != 0); + else + force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); + + if (force_sw || use_sw) + android_display_init_sw(&adpy->base); + else + android_display_init_drm(&adpy->base); + + if (!adpy->base.screen) { + FREE(adpy); + return NULL; + } + + if (!android_display_init_configs(&adpy->base)) { + adpy->base.screen->destroy(adpy->base.screen); + FREE(adpy); + return NULL; + } + + adpy->base.destroy = android_display_destroy; + adpy->base.get_param = android_display_get_param; + adpy->base.get_configs = android_display_get_configs; + adpy->base.create_window_surface = android_display_create_window_surface; + + adpy->base.buffer = &android_display_buffer; + + return adpy; +} + +static struct native_event_handler *android_event_handler; + +static void +native_set_event_handler(struct native_event_handler *event_handler) +{ + android_event_handler = event_handler; +} + +static struct native_display * +native_create_display(void *dpy, boolean use_sw, void *user_data) +{ + struct android_display *adpy; + + adpy = android_display_create(android_event_handler, use_sw, user_data); + + return (adpy) ? &adpy->base : NULL; +} + +static const struct native_platform android_platform = { + "Android", /* name */ + native_set_event_handler, + native_create_display +}; + +}; /* namespace android */ + +using namespace android; + +static void +android_log(EGLint level, const char *msg) +{ + switch (level) { + case _EGL_DEBUG: + LOGD(msg); + break; + case _EGL_INFO: + LOGI(msg); + break; + case _EGL_WARNING: + LOGW(msg); + break; + case _EGL_FATAL: + LOG_FATAL(msg); + break; + default: + break; + } +} + +const struct native_platform * +native_get_android_platform(void) +{ + _eglSetLogProc(android_log); + + return &android_platform; +} diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 2c7f3bde4f..e455167473 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -121,6 +121,12 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) nplat = native_get_fbdev_platform(); #endif break; + case _EGL_PLATFORM_ANDROID: + plat_name = "Android"; +#ifdef HAVE_ANDROID_BACKEND + nplat = native_get_android_platform(); +#endif + break; default: break; } @@ -552,6 +558,11 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy) if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer) dpy->Extensions.MESA_drm_image = EGL_TRUE; +#ifdef EGL_ANDROID_image_native_buffer + if (dpy->Platform == _EGL_PLATFORM_ANDROID && gdpy->native->buffer) + dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE; +#endif + if (egl_g3d_add_configs(drv, dpy, 1) == 1) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); goto fail; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index 301db3128f..2292d611fc 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -93,6 +93,9 @@ struct egl_g3d_image { struct pipe_resource *texture; unsigned level; unsigned layer; + + EGLenum target; + EGLClientBuffer buffer; }; /* standard typecasts */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c index e1c83168b3..5971ff5cf9 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -40,6 +40,11 @@ /* for struct winsys_handle */ #include "state_tracker/drm_driver.h" +#ifdef EGL_ANDROID_image_native_buffer +#include <ui/android_native_buffer.h> +#include "android/android_sw_winsys.h" +#endif + /** * Reference and return the front left buffer of the native pixmap. */ @@ -179,6 +184,67 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name, #endif /* EGL_MESA_drm_image */ +#ifdef EGL_ANDROID_image_native_buffer + +static struct pipe_resource * +egl_g3d_reference_android_native_buffer(_EGLDisplay *dpy, + struct android_native_buffer_t *buf) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct pipe_screen *screen = gdpy->native->screen; + enum pipe_format format; + struct pipe_resource templ, *res; + struct android_winsys_handle handle; + + if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || + buf->common.version != sizeof(*buf)) { + _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); + return NULL; + } + + switch (buf->format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + format = PIPE_FORMAT_R8G8B8A8_UNORM; + break; + case HAL_PIXEL_FORMAT_RGBX_8888: + format = PIPE_FORMAT_R8G8B8X8_UNORM; + break; + case HAL_PIXEL_FORMAT_RGB_888: + format = PIPE_FORMAT_R8G8B8_UNORM; + break; + case HAL_PIXEL_FORMAT_RGB_565: + format = PIPE_FORMAT_B5G6R5_UNORM; + break; + case HAL_PIXEL_FORMAT_BGRA_8888: + format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + /* unsupported */ + default: + _eglLog(_EGL_WARNING, "unsupported native format 0x%x", buf->format); + return NULL; + break; + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.format = format; + templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + templ.width0 = buf->width; + templ.height0 = buf->height; + templ.depth0 = 1; + + res = gdpy->native->buffer->import_buffer(gdpy->native, + &templ, (void *) buf); + if (res) + buf->common.incRef(&buf->common); + + return res; +} + +#endif /* EGL_ANDROID_image_native_buffer */ + _EGLImage * egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, @@ -199,6 +265,8 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, return NULL; } + gimg->target = target; + switch (target) { case EGL_NATIVE_PIXMAP_KHR: ptex = egl_g3d_reference_native_pixmap(dpy, @@ -210,6 +278,13 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, (EGLint) buffer, &gimg->base, attribs); break; #endif +#ifdef EGL_ANDROID_image_native_buffer + case EGL_NATIVE_BUFFER_ANDROID: + gimg->buffer = buffer; + ptex = egl_g3d_reference_android_native_buffer(dpy, + (struct android_native_buffer_t *) buffer); + break; +#endif default: ptex = NULL; break; @@ -246,6 +321,14 @@ egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img) { struct egl_g3d_image *gimg = egl_g3d_image(img); +#ifdef EGL_ANDROID_image_native_buffer + if (gimg->target == EGL_NATIVE_BUFFER_ANDROID) { + struct android_native_buffer_t * buf = + (struct android_native_buffer_t *) gimg->buffer; + buf->common.decRef(&buf->common); + } +#endif + pipe_resource_reference(&gimg->texture, NULL); FREE(gimg); diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 9246f8c32a..9e9cd3fd05 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -275,6 +275,9 @@ native_get_drm_platform(void); const struct native_platform * native_get_fbdev_platform(void); +const struct native_platform * +native_get_android_platform(void); + #ifdef __cplusplus } #endif diff --git a/src/gallium/winsys/sw/android/android_sw_winsys.cpp b/src/gallium/winsys/sw/android/android_sw_winsys.cpp new file mode 100644 index 0000000000..1c3c9f81be --- /dev/null +++ b/src/gallium/winsys/sw/android/android_sw_winsys.cpp @@ -0,0 +1,269 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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 shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" +#include "util/u_memory.h" +#include "util/u_format.h" +#include "state_tracker/sw_winsys.h" + +#include <ui/PixelFormat.h> +#include <private/ui/sw_gralloc_handle.h> +#include <hardware/gralloc.h> + +#include "android_sw_winsys.h" + +struct android_sw_winsys +{ + struct sw_winsys base; + + const gralloc_module_t *grmod; +}; + +struct android_sw_displaytarget +{ + buffer_handle_t handle; + int stride; + int width, height, usage; + + void *mapped; +}; + +static INLINE struct android_sw_winsys * +android_sw_winsys(struct sw_winsys *ws) +{ + return (struct android_sw_winsys *) ws; +} + +static INLINE struct android_sw_displaytarget * +android_sw_displaytarget(struct sw_displaytarget *dt) +{ + return (struct android_sw_displaytarget *) dt; +} + +namespace android { + +static void +android_displaytarget_display(struct sw_winsys *ws, + struct sw_displaytarget *dt, + void *context_private) +{ +} + +static struct sw_displaytarget * +android_displaytarget_create(struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + return NULL; +} + +static void +android_displaytarget_destroy(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct android_sw_displaytarget *adt = android_sw_displaytarget(dt); + + assert(!adt->mapped); + FREE(adt); +} + +static void +android_displaytarget_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct android_sw_winsys *droid = android_sw_winsys(ws); + struct android_sw_displaytarget *adt = android_sw_displaytarget(dt); + + if (adt->mapped) { + if (sw_gralloc_handle_t::validate(adt->handle) >= 0) { + adt->mapped = NULL; + } + else { + droid->grmod->unlock(droid->grmod, adt->handle); + adt->mapped = NULL; + } + } +} + +static void * +android_displaytarget_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, + unsigned flags) +{ + struct android_sw_winsys *droid = android_sw_winsys(ws); + struct android_sw_displaytarget *adt = android_sw_displaytarget(dt); + + if (!adt->mapped) { + if (sw_gralloc_handle_t::validate(adt->handle) >= 0) { + const sw_gralloc_handle_t *swhandle = + reinterpret_cast<const sw_gralloc_handle_t *>(adt->handle); + adt->mapped = reinterpret_cast<void *>(swhandle->base); + } + else { + droid->grmod->lock(droid->grmod, adt->handle, + adt->usage, 0, 0, adt->width, adt->height, &adt->mapped); + } + } + + return adt->mapped; +} + +static struct sw_displaytarget * +android_displaytarget_from_handle(struct sw_winsys *ws, + const struct pipe_resource *templ, + struct winsys_handle *whandle, + unsigned *stride) +{ + struct android_winsys_handle *ahandle = + (struct android_winsys_handle *) whandle; + struct android_sw_displaytarget *adt; + + adt = CALLOC_STRUCT(android_sw_displaytarget); + if (!adt) + return NULL; + + adt->handle = ahandle->handle; + adt->stride = ahandle->stride; + adt->width = templ->width0; + adt->height = templ->height0; + + if (templ->usage & PIPE_BIND_RENDER_TARGET) + adt->usage |= GRALLOC_USAGE_HW_RENDER; + if (templ->usage & PIPE_BIND_SAMPLER_VIEW) + adt->usage |= GRALLOC_USAGE_HW_TEXTURE; + if (templ->usage & PIPE_BIND_SCANOUT) + adt->usage |= GRALLOC_USAGE_HW_FB; + + if (templ->usage & PIPE_BIND_TRANSFER_READ) + adt->usage |= GRALLOC_USAGE_SW_READ_OFTEN; + if (templ->usage & PIPE_BIND_TRANSFER_WRITE) + adt->usage |= GRALLOC_USAGE_SW_WRITE_OFTEN; + + if (stride) + *stride = adt->stride; + + return reinterpret_cast<struct sw_displaytarget *>(adt); +} + +static boolean +android_displaytarget_get_handle(struct sw_winsys *ws, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) +{ + return FALSE; +} + +static boolean +android_is_displaytarget_format_supported(struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format) +{ + struct android_sw_winsys *droid = android_sw_winsys(ws); + int fmt; + + switch (format) { + case PIPE_FORMAT_R8G8B8A8_UNORM: + fmt = PIXEL_FORMAT_RGBA_8888; + break; + case PIPE_FORMAT_R8G8B8X8_UNORM: + fmt = PIXEL_FORMAT_RGBX_8888; + break; + case PIPE_FORMAT_R8G8B8_UNORM: + fmt = PIXEL_FORMAT_RGB_888; + break; + case PIPE_FORMAT_B5G6R5_UNORM: + fmt = PIXEL_FORMAT_RGB_565; + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + fmt = PIXEL_FORMAT_BGRA_8888; + break; + case PIPE_FORMAT_A8_UNORM: + fmt = PIXEL_FORMAT_A_8; + break; + case PIPE_FORMAT_L8_UNORM: + fmt = PIXEL_FORMAT_L_8; + break; + case PIPE_FORMAT_L8A8_UNORM: + fmt = PIXEL_FORMAT_LA_88; + break; + default: + fmt = PIXEL_FORMAT_NONE; + break; + } + + return (fmt != PIXEL_FORMAT_NONE); +} + +static void +android_destroy(struct sw_winsys *ws) +{ + struct android_sw_winsys *droid = android_sw_winsys(ws); + + FREE(droid); +} + +}; /* namespace android */ + +using namespace android; + +struct sw_winsys * +android_create_sw_winsys(void) +{ + struct android_sw_winsys *droid; + const hw_module_t *mod; + + droid = CALLOC_STRUCT(android_sw_winsys); + if (!droid) + return NULL; + + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod)) { + FREE(droid); + return NULL; + } + + droid->grmod = (const gralloc_module_t *) mod; + + droid->base.destroy = android_destroy; + droid->base.is_displaytarget_format_supported = + android_is_displaytarget_format_supported; + + droid->base.displaytarget_create = android_displaytarget_create; + droid->base.displaytarget_destroy = android_displaytarget_destroy; + droid->base.displaytarget_from_handle = android_displaytarget_from_handle; + droid->base.displaytarget_get_handle = android_displaytarget_get_handle; + + droid->base.displaytarget_map = android_displaytarget_map; + droid->base.displaytarget_unmap = android_displaytarget_unmap; + droid->base.displaytarget_display = android_displaytarget_display; + + return &droid->base; +} diff --git a/src/gallium/winsys/sw/android/android_sw_winsys.h b/src/gallium/winsys/sw/android/android_sw_winsys.h new file mode 100644 index 0000000000..8bb1dc91d4 --- /dev/null +++ b/src/gallium/winsys/sw/android/android_sw_winsys.h @@ -0,0 +1,49 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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 shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef ANDROID_SW_WINSYS +#define ANDROID_SW_WINSYS + +#include <sys/cdefs.h> +#include <hardware/gralloc.h> + +__BEGIN_DECLS + +struct sw_winsys; + +struct android_winsys_handle { + buffer_handle_t handle; + int stride; +}; + +struct sw_winsys * +android_create_sw_winsys(void); + +__END_DECLS + +#endif /* ANDROID_SW_WINSYS */ |