[Mesa-dev] [PATCH 08/18] st/egl: add android backend

Chia-I Wu olvaffe at gmail.com
Tue Aug 16 23:28:11 PDT 2011


From: Chia-I Wu <olv at lunarg.com>

This backend supports _EGL_PLATFORM_ANDROID with both HW and SW
rendering.
---
 .../state_trackers/egl/android/native_android.cpp  |  722 ++++++++++++++++++++
 src/gallium/state_trackers/egl/common/egl_g3d.c    |   11 +
 .../state_trackers/egl/common/egl_g3d_image.c      |   25 +
 src/gallium/state_trackers/egl/common/native.h     |    3 +
 .../state_trackers/egl/common/native_buffer.h      |    4 +
 src/gallium/targets/egl-static/egl.c               |   62 ++
 .../winsys/sw/android/android_sw_winsys.cpp        |  269 ++++++++
 src/gallium/winsys/sw/android/android_sw_winsys.h  |   49 ++
 8 files changed, 1145 insertions(+), 0 deletions(-)
 create mode 100644 src/gallium/state_trackers/egl/android/native_android.cpp
 create mode 100644 src/gallium/winsys/sw/android/android_sw_winsys.cpp
 create mode 100644 src/gallium/winsys/sw/android/android_sw_winsys.h

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 0000000..983c941
--- /dev/null
+++ b/src/gallium/state_trackers/egl/android/native_android.cpp
@@ -0,0 +1,722 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.12
+ *
+ * Copyright (C) 2010-2011 Chia-I Wu <olvaffe at gmail.com>
+ * Copyright (C) 2010-2011 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.
+ */
+
+#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;
+   const 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_drm_handle.h>
+static int
+get_handle_name(buffer_handle_t handle)
+{
+   struct gralloc_drm_handle_t *dh;
+
+   dh = gralloc_drm_handle(handle);
+
+   return (dh) ? dh->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))
+         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))
+         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)) {
+         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)) {
+         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_id = native_formats[i];
+      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, NULL, fd);
+   }
+
+   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 boolean
+android_display_init_screen(struct native_display *ndpy)
+{
+   struct android_display *adpy = android_display(ndpy);
+
+   if (adpy->use_drm)
+      android_display_init_drm(&adpy->base);
+   else
+      android_display_init_sw(&adpy->base);
+
+   if (!adpy->base.screen)
+      return FALSE;
+
+   if (!android_display_init_configs(&adpy->base)) {
+      adpy->base.screen->destroy(adpy->base.screen);
+      adpy->base.screen = NULL;
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+static void
+android_display_destroy(struct native_display *ndpy)
+{
+   struct android_display *adpy = android_display(ndpy);
+
+   FREE(adpy->configs);
+   if (adpy->base.screen)
+      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,
+                              struct native_buffer *nbuf)
+{
+   struct android_display *adpy = android_display(ndpy);
+   struct android_native_buffer_t *abuf;
+   enum pipe_format format;
+   struct pipe_resource templ;
+
+   if (nbuf->type != NATIVE_BUFFER_ANDROID)
+      return NULL;
+
+   abuf = nbuf->u.android;
+
+   if (!abuf || abuf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
+       abuf->common.version != sizeof(*abuf)) {
+      LOGE("invalid android native buffer");
+      return NULL;
+   }
+
+   format = get_pipe_format(abuf->format);
+   if (format == PIPE_FORMAT_NONE)
+      return NULL;
+
+   memset(&templ, 0, sizeof(templ));
+   templ.target = PIPE_TEXTURE_2D;
+   templ.format = format;
+   /* assume for texturing only */
+   templ.bind = PIPE_BIND_SAMPLER_VIEW;
+   templ.width0 = abuf->width;
+   templ.height0 = abuf->height;
+   templ.depth0 = 1;
+   templ.array_size = 1;
+
+   return import_buffer(adpy, &templ, abuf);
+}
+
+static boolean
+android_display_export_buffer(struct native_display *ndpy,
+                              struct pipe_resource *res,
+                              struct native_buffer *nbuf)
+{
+   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(const struct native_event_handler *event_handler,
+                       boolean use_sw)
+{
+   struct android_display *adpy;
+   char value[PROPERTY_VALUE_MAX];
+   boolean force_sw;
+
+   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 = TRUE;
+
+   adpy = CALLOC_STRUCT(android_display);
+   if (!adpy)
+      return NULL;
+
+   adpy->event_handler = event_handler;
+   adpy->use_drm = !use_sw;
+
+   adpy->base.init_screen = android_display_init_screen;
+   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 const struct native_event_handler *android_event_handler;
+
+static struct native_display *
+native_create_display(void *dpy, boolean use_sw)
+{
+   struct android_display *adpy;
+
+   adpy = android_display_create(android_event_handler, use_sw);
+
+   return (adpy) ? &adpy->base : NULL;
+}
+
+static const struct native_platform android_platform = {
+   "Android", /* name */
+   native_create_display
+};
+
+}; /* namespace android */
+
+using namespace android;
+
+static void
+android_log(EGLint level, const char *msg)
+{
+   switch (level) {
+   case _EGL_DEBUG:
+      LOGD("%s", msg);
+      break;
+   case _EGL_INFO:
+      LOGI("%s", msg);
+      break;
+   case _EGL_WARNING:
+      LOGW("%s", msg);
+      break;
+   case _EGL_FATAL:
+      LOG_FATAL("%s", msg);
+      break;
+   default:
+      break;
+   }
+}
+
+const struct native_platform *
+native_get_android_platform(const struct native_event_handler *event_handler)
+{
+   android_event_handler = event_handler;
+   _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 6649f02..b5e3d99 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -132,6 +132,12 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
          nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler);
 #endif
          break;
+      case _EGL_PLATFORM_ANDROID:
+         plat_name = "Android";
+#ifdef HAVE_ANDROID_BACKEND
+         nplat = native_get_android_platform(&egl_g3d_native_event_handler);
+#endif
+         break;
       default:
          break;
       }
@@ -572,6 +578,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
+
 #ifdef EGL_WL_bind_wayland_display
    if (gdpy->native->wayland_bufmgr)
       dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
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 7e9a29b..960a852 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c
@@ -202,6 +202,25 @@ egl_g3d_reference_wl_buffer(_EGLDisplay *dpy, struct wl_buffer *buffer,
 
 #endif /* EGL_WL_bind_wayland_display */
 
+#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;
+   struct native_buffer nbuf;
+
+   memset(&nbuf, 0, sizeof(nbuf));
+   nbuf.type = NATIVE_BUFFER_ANDROID;
+   nbuf.u.android = buf;
+    
+   return gdpy->native->buffer->import_buffer(gdpy->native, &nbuf);
+}
+
+#endif /* EGL_ANDROID_image_native_buffer */
+
 _EGLImage *
 egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
                      EGLenum target, EGLClientBuffer buffer,
@@ -239,6 +258,12 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
             (struct wl_buffer *) buffer, &gimg->base, attribs);
       break;
 #endif
+#ifdef EGL_ANDROID_image_native_buffer
+   case EGL_NATIVE_BUFFER_ANDROID:
+      ptex = egl_g3d_reference_android_native_buffer(dpy,
+            (struct android_native_buffer_t *) buffer);
+      break;
+#endif
    default:
       ptex = NULL;
       break;
diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h
index fc50ee4..58593a4 100644
--- a/src/gallium/state_trackers/egl/common/native.h
+++ b/src/gallium/state_trackers/egl/common/native.h
@@ -293,6 +293,9 @@ native_get_drm_platform(const struct native_event_handler *event_handler);
 const struct native_platform *
 native_get_fbdev_platform(const struct native_event_handler *event_handler);
 
+const struct native_platform *
+native_get_android_platform(const struct native_event_handler *event_handler);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gallium/state_trackers/egl/common/native_buffer.h b/src/gallium/state_trackers/egl/common/native_buffer.h
index b8a66d1..028f8c0 100644
--- a/src/gallium/state_trackers/egl/common/native_buffer.h
+++ b/src/gallium/state_trackers/egl/common/native_buffer.h
@@ -33,9 +33,11 @@
 #include "pipe/p_state.h"
 
 struct native_display;
+struct android_native_buffer_t;
 
 enum native_buffer_type {
    NATIVE_BUFFER_DRM,
+   NATIVE_BUFFER_ANDROID,
 
    NUM_NATIVE_BUFFERS
 };
@@ -50,6 +52,8 @@ struct native_buffer {
          unsigned handle; /**< the handle of the GEM object */
          unsigned stride;
       } drm;
+
+      struct android_native_buffer_t *android;
    } u;
 };
 
diff --git a/src/gallium/targets/egl-static/egl.c b/src/gallium/targets/egl-static/egl.c
index 568f549..5176da3 100644
--- a/src/gallium/targets/egl-static/egl.c
+++ b/src/gallium/targets/egl-static/egl.c
@@ -109,6 +109,68 @@ out:
    return (*chip_id >= 0);
 }
 
+#elif defined(ANDROID)
+
+#include <xf86drm.h>
+/* for i915 */
+#include <i915_drm.h>
+/* for radeon */
+#include <radeon_drm.h>
+
+static boolean
+drm_fd_get_pci_id(int fd, int *vendor_id, int *chip_id)
+{
+   drmVersionPtr version;
+
+   *chip_id = -1;
+
+   version = drmGetVersion(fd);
+   if (!version) {
+      _eglLog(_EGL_WARNING, "invalid drm fd");
+      return FALSE;
+   }
+   if (!version->name) {
+      _eglLog(_EGL_WARNING, "unable to determine the driver name");
+      drmFreeVersion(version);
+      return FALSE;
+   }
+
+   if (strcmp(version->name, "i915") == 0) {
+      struct drm_i915_getparam gp;
+      int ret;
+
+      *vendor_id = 0x8086;
+
+      memset(&gp, 0, sizeof(gp));
+      gp.param = I915_PARAM_CHIPSET_ID;
+      gp.value = chip_id;
+      ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
+      if (ret) {
+         _eglLog(_EGL_WARNING, "failed to get param for i915");
+	 *chip_id = -1;
+      }
+   }
+   else if (strcmp(version->name, "radeon") == 0) {
+      struct drm_radeon_info info;
+      int ret;
+
+      *vendor_id = 0x1002;
+
+      memset(&info, 0, sizeof(info));
+      info.request = RADEON_INFO_DEVICE_ID;
+      info.value = (long) chip_id;
+      ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
+      if (ret) {
+         _eglLog(_EGL_WARNING, "failed to get info for radeon");
+	 *chip_id = -1;
+      }
+   }
+
+   drmFreeVersion(version);
+
+   return (*chip_id >= 0);
+}
+
 #else
 
 static boolean
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 0000000..fbe1499
--- /dev/null
+++ b/src/gallium/winsys/sw/android/android_sw_winsys.cpp
@@ -0,0 +1,269 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.12
+ *
+ * Copyright (C) 2010-2011 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 at 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 0000000..79392dc
--- /dev/null
+++ b/src/gallium/winsys/sw/android/android_sw_winsys.h
@@ -0,0 +1,49 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.12
+ *
+ * Copyright (C) 2010-2011 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 at 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 */
-- 
1.7.5.4



More information about the mesa-dev mailing list