aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/egl
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/egl')
-rw-r--r--src/gallium/state_trackers/egl/Android.mk54
-rw-r--r--src/gallium/state_trackers/egl/android/native_android.cpp835
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d.c11
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_image.c24
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_st.c7
-rw-r--r--src/gallium/state_trackers/egl/common/native.h3
-rw-r--r--src/gallium/state_trackers/egl/common/native_buffer.h4
-rw-r--r--src/gallium/state_trackers/egl/drm/native_drm.c23
-rw-r--r--src/gallium/state_trackers/egl/drm/native_drm.h4
9 files changed, 957 insertions, 8 deletions
diff --git a/src/gallium/state_trackers/egl/Android.mk b/src/gallium/state_trackers/egl/Android.mk
new file mode 100644
index 00000000000..e459bd4655e
--- /dev/null
+++ b/src/gallium/state_trackers/egl/Android.mk
@@ -0,0 +1,54 @@
+# Mesa 3-D graphics library
+#
+# Copyright (C) 2010-2011 Chia-I Wu <[email protected]>
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+common_SOURCES := \
+ common/egl_g3d.c \
+ common/egl_g3d_api.c \
+ common/egl_g3d_image.c \
+ common/egl_g3d_st.c \
+ common/egl_g3d_sync.c \
+ common/native_helper.c
+
+android_SOURCES := \
+ android/native_android.cpp
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(common_SOURCES) \
+ $(android_SOURCES)
+
+LOCAL_CFLAGS := -DHAVE_ANDROID_BACKEND
+
+LOCAL_C_INCLUDES := \
+ $(GALLIUM_TOP)/state_trackers/egl \
+ $(GALLIUM_TOP)/winsys/sw \
+ $(MESA_TOP)/src/egl/main \
+ $(DRM_GRALLOC_TOP)
+
+LOCAL_MODULE := libmesa_st_egl
+
+include $(GALLIUM_COMMON_MK)
+include $(BUILD_STATIC_LIBRARY)
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 00000000000..211d6a2aeef
--- /dev/null
+++ b/src/gallium/state_trackers/egl/android/native_android.cpp
@@ -0,0 +1,835 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.12
+ *
+ * Copyright (C) 2010-2011 Chia-I Wu <[email protected]>
+ * 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 "EGL-GALLIUM"
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <hardware/gralloc.h>
+#include <utils/Errors.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 "util/u_box.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;
+
+ /* staging color buffer for when buffer preserving is enabled */
+ struct pipe_resource *color_res;
+
+ uint stamp;
+ android_native_buffer_t *buf;
+ struct pipe_resource *buf_res;
+
+ /* cache the current back buffers */
+ struct {
+ int width;
+ int height;
+ int format;
+ } cache_key;
+ 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;
+
+ switch (native) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ fmt = PIPE_FORMAT_R8G8B8A8_UNORM;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ fmt = PIPE_FORMAT_R8G8B8X8_UNORM;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ fmt = PIPE_FORMAT_R8G8B8_UNORM;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ fmt = PIPE_FORMAT_B5G6R5_UNORM;
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ fmt = PIPE_FORMAT_B8G8R8A8_UNORM;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_5551:
+ /* fmt = PIPE_FORMAT_A1B5G5R5_UNORM; */
+ case HAL_PIXEL_FORMAT_RGBA_4444:
+ /* fmt = PIPE_FORMAT_A4B4G4R4_UNORM; */
+ 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;
+
+ /* check that the buffer is allocated by drm_gralloc and cast */
+ dh = gralloc_drm_handle(handle);
+
+ return (dh) ? dh->name : 0;
+}
+
+/**
+ * Import an android_native_buffer_t allocated by the server.
+ */
+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;
+ /* for DRM, we need the GEM name */
+ 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 void
+android_surface_clear_cache(struct native_surface *nsurf)
+{
+ struct android_surface *asurf = android_surface(nsurf);
+ int i;
+
+ for (i = 0; i < Elements(asurf->cache_handles); i++) {
+ asurf->cache_handles[i] = NULL;
+ pipe_resource_reference(&asurf->cache_resources[i], NULL);
+ }
+
+ memset(&asurf->cache_key, 0, sizeof(asurf->cache_key));
+}
+
+static struct pipe_resource *
+android_surface_add_cache(struct native_surface *nsurf,
+ struct android_native_buffer_t *abuf)
+{
+ struct android_surface *asurf = android_surface(nsurf);
+ void *handle;
+ int idx;
+
+ /* how about abuf->usage? */
+ if (asurf->cache_key.width != abuf->width ||
+ asurf->cache_key.height != abuf->height ||
+ asurf->cache_key.format != abuf->format)
+ android_surface_clear_cache(&asurf->base);
+
+ if (asurf->adpy->use_drm)
+ handle = (void *) get_handle_name(abuf->handle);
+ else
+ handle = (void *) abuf->handle;
+ /* NULL is invalid */
+ if (!handle) {
+ LOGE("invalid buffer native buffer %p", abuf);
+ return NULL;
+ }
+
+ /* 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)) {
+ LOGW("cache full: buf %p, width %d, height %d, format %d, usage 0x%x",
+ abuf, abuf->width, abuf->height, abuf->format, abuf->usage);
+ android_surface_clear_cache(&asurf->base);
+ idx = 0;
+ }
+
+ if (idx == 0) {
+ asurf->cache_key.width = abuf->width;
+ asurf->cache_key.height = abuf->height;
+ asurf->cache_key.format = abuf->format;
+ }
+
+ 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.format = get_pipe_format(asurf->buf->format);
+ templ.bind = PIPE_BIND_RENDER_TARGET;
+ if (!asurf->adpy->use_drm) {
+ templ.bind |= PIPE_BIND_TRANSFER_WRITE |
+ PIPE_BIND_TRANSFER_READ;
+ }
+
+ templ.width0 = asurf->buf->width;
+ templ.height0 = asurf->buf->height;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+
+ 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;
+ }
+
+ return asurf->cache_resources[idx];
+}
+
+/**
+ * Dequeue the next back buffer for rendering.
+ */
+static boolean
+android_surface_dequeue_buffer(struct native_surface *nsurf)
+{
+ struct android_surface *asurf = android_surface(nsurf);
+ struct pipe_resource *res;
+
+ 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);
+
+ res = android_surface_add_cache(&asurf->base, asurf->buf);
+ if (!res)
+ return FALSE;
+
+ pipe_resource_reference(&asurf->buf_res, res);
+
+ return TRUE;
+}
+
+/**
+ * Enqueue the back buffer. This will make it the next front buffer.
+ */
+static boolean
+android_surface_enqueue_buffer(struct native_surface *nsurf)
+{
+ struct android_surface *asurf = android_surface(nsurf);
+
+ pipe_resource_reference(&asurf->buf_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 TRUE;
+
+ android_surface_enqueue_buffer(&asurf->base);
+
+ asurf->stamp++;
+ adpy->event_handler->invalid_surface(&adpy->base,
+ &asurf->base, asurf->stamp);
+
+ return TRUE;
+}
+
+static void
+copy_resources(struct native_display *ndpy,
+ struct pipe_resource *src,
+ struct pipe_resource *dst)
+{
+ struct pipe_context *pipe;
+ struct pipe_box box;
+
+ pipe = ndpy_get_copy_context(ndpy);
+ if (!pipe)
+ return;
+
+ u_box_origin_2d(src->width0, src->height0, &box);
+ pipe->resource_copy_region(pipe, dst, 0, 0, 0, 0, src, 0, &box);
+ pipe->flush(pipe, NULL);
+}
+
+static boolean
+android_surface_present(struct native_surface *nsurf,
+ enum native_attachment natt,
+ boolean preserve,
+ uint swap_interval)
+{
+ struct android_surface *asurf = android_surface(nsurf);
+ struct android_display *adpy = asurf->adpy;
+ boolean ret;
+
+ if (swap_interval || natt != NATIVE_ATTACHMENT_BACK_LEFT)
+ return FALSE;
+
+ /* we always render to color_res first when it exists */
+ if (asurf->color_res) {
+ copy_resources(&adpy->base, asurf->color_res, asurf->buf_res);
+ if (!preserve)
+ pipe_resource_reference(&asurf->color_res, NULL);
+ }
+ else if (preserve) {
+ struct pipe_resource templ;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = asurf->buf_res->target;
+ templ.format = asurf->buf_res->format;
+ templ.bind = PIPE_BIND_RENDER_TARGET;
+ templ.width0 = asurf->buf_res->width0;
+ templ.height0 = asurf->buf_res->height0;
+ templ.depth0 = asurf->buf_res->depth0;
+ templ.array_size = asurf->buf_res->array_size;
+
+ asurf->color_res =
+ adpy->base.screen->resource_create(adpy->base.screen, &templ);
+ if (!asurf->color_res)
+ return FALSE;
+
+ /* preserve the contents */
+ copy_resources(&adpy->base, asurf->buf_res, asurf->color_res);
+ }
+
+ 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;
+
+ /* color_res must be compatible with buf_res */
+ if (asurf->color_res &&
+ (asurf->color_res->format != asurf->buf_res->format ||
+ asurf->color_res->width0 != asurf->buf_res->width0 ||
+ asurf->color_res->height0 != asurf->buf_res->height0))
+ pipe_resource_reference(&asurf->color_res, NULL);
+ }
+
+ if (textures) {
+ /* we have access to only the back buffer */
+ 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->color_res) ? asurf->color_res : asurf->buf_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;
+
+ pipe_resource_reference(&asurf->color_res, NULL);
+
+ if (asurf->buf)
+ android_surface_enqueue_buffer(&asurf->base);
+
+ android_surface_clear_cache(&asurf->base);
+
+ 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);
+
+ /* request buffers that are for CPU access */
+ 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[] = {
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ HAL_PIXEL_FORMAT_RGBX_8888,
+ HAL_PIXEL_FORMAT_RGB_888,
+ HAL_PIXEL_FORMAT_RGB_565,
+ HAL_PIXEL_FORMAT_BGRA_8888,
+ };
+ 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++];
+ /* only the back buffer */
+ 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;
+
+ /* get the authorized fd from gralloc */
+ 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 {
+ LOGW("failed to create DRM screen");
+ LOGW("will fall back to other EGL drivers if any");
+ 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) {
+ case NATIVE_PARAM_PRESERVE_BUFFER:
+ val = 1;
+ break;
+ 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;
+
+ /* check if SW renderer is forced */
+ 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;
+ /* use Android logger */
+ _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 6649f02b244..b5e3d99b811 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 7e9a29b0284..4d90c400319 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,24 @@ 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 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 +257,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/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c
index 60c3e332ac9..b839f848d7b 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c
@@ -126,7 +126,7 @@ pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf)
}
static void
-pbuffer_allocate_render_texture(struct egl_g3d_surface *gsurf)
+pbuffer_allocate_pbuffer_texture(struct egl_g3d_surface *gsurf)
{
struct egl_g3d_display *gdpy =
egl_g3d_display(gsurf->base.Resource.Display);
@@ -141,7 +141,8 @@ pbuffer_allocate_render_texture(struct egl_g3d_surface *gsurf)
templ.depth0 = 1;
templ.array_size = 1;
templ.format = gsurf->stvis.color_format;
- templ.bind = PIPE_BIND_RENDER_TARGET;
+ /* for rendering and binding to texture */
+ templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
ptex = screen->resource_create(screen, &templ);
gsurf->render_texture = ptex;
@@ -166,7 +167,7 @@ egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi,
if (!gsurf->render_texture) {
switch (gsurf->client_buffer_type) {
case EGL_NONE:
- pbuffer_allocate_render_texture(gsurf);
+ pbuffer_allocate_pbuffer_texture(gsurf);
break;
case EGL_OPENVG_IMAGE:
pbuffer_reference_openvg_image(gsurf);
diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h
index fc50ee485fe..58593a489cd 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 b8a66d17e12..503ed580b05 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; /**< opaque native buffer */
} u;
};
diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c
index 47910de8d3c..c013769e57d 100644
--- a/src/gallium/state_trackers/egl/drm/native_drm.c
+++ b/src/gallium/state_trackers/egl/drm/native_drm.c
@@ -134,8 +134,11 @@ drm_display_destroy(struct native_display *ndpy)
if (drmdpy->device_name)
FREE(drmdpy->device_name);
- if (drmdpy->fd >= 0)
- close(drmdpy->fd);
+ if (drmdpy->own_gbm) {
+ gbm_device_destroy(&drmdpy->gbmdrm->base.base);
+ if (drmdpy->fd >= 0)
+ close(drmdpy->fd);
+ }
FREE(drmdpy);
}
@@ -258,7 +261,7 @@ drm_display_init_screen(struct native_display *ndpy)
}
static struct native_display *
-drm_create_display(struct gbm_gallium_drm_device *gbmdrm,
+drm_create_display(struct gbm_gallium_drm_device *gbmdrm, int own_gbm,
const struct native_event_handler *event_handler)
{
struct drm_display *drmdpy;
@@ -267,6 +270,8 @@ drm_create_display(struct gbm_gallium_drm_device *gbmdrm,
if (!drmdpy)
return NULL;
+ drmdpy->gbmdrm = gbmdrm;
+ drmdpy->own_gbm = own_gbm;
drmdpy->fd = gbmdrm->base.base.fd;
drmdpy->device_name = drm_get_device_name(drmdpy->fd);
@@ -302,22 +307,30 @@ native_create_display(void *dpy, boolean use_sw)
{
struct gbm_gallium_drm_device *gbm;
int fd;
+ int own_gbm = 0;
gbm = dpy;
if (gbm == NULL) {
fd = open("/dev/dri/card0", O_RDWR);
+ /* FIXME: Use an internal constructor to create a gbm
+ * device with gallium backend directly, without setenv */
+ setenv("GBM_BACKEND", "gbm_gallium_drm.so", 1);
gbm = gbm_gallium_drm_device(gbm_create_device(fd));
+ own_gbm = 1;
}
if (gbm == NULL)
return NULL;
if (strcmp(gbm_device_get_backend_name(&gbm->base.base), "drm") != 0 ||
- gbm->base.type != GBM_DRM_DRIVER_TYPE_GALLIUM)
+ gbm->base.type != GBM_DRM_DRIVER_TYPE_GALLIUM) {
+ if (own_gbm)
+ gbm_device_destroy(&gbm->base.base);
return NULL;
+ }
- return drm_create_display(gbm, drm_event_handler);
+ return drm_create_display(gbm, own_gbm, drm_event_handler);
}
static const struct native_platform drm_platform = {
diff --git a/src/gallium/state_trackers/egl/drm/native_drm.h b/src/gallium/state_trackers/egl/drm/native_drm.h
index 675a58a1922..18cebf4e276 100644
--- a/src/gallium/state_trackers/egl/drm/native_drm.h
+++ b/src/gallium/state_trackers/egl/drm/native_drm.h
@@ -41,6 +41,8 @@
#include "common/native_wayland_drm_bufmgr_helper.h"
#endif
+#include "gbm_gallium_drmint.h"
+
struct drm_config;
struct drm_crtc;
struct drm_connector;
@@ -52,6 +54,8 @@ struct drm_display {
const struct native_event_handler *event_handler;
+ struct gbm_gallium_drm_device *gbmdrm;
+ int own_gbm;
int fd;
char *device_name;
struct drm_config *config;