Implement basic ANDROID_image_native_buffer support.
Change-Id: I7e844eb7c313455d48cd2fc09440f10d639b4c77
Reviewed-on: https://swiftshader-review.googlesource.com/2758
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Greg Hartman <ghartman@google.com>
Reviewed-by: Ping-Hao Wu <pinghao@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libEGL/Image.hpp b/src/OpenGL/libEGL/Image.hpp
index f612c57..071cf7d 100644
--- a/src/OpenGL/libEGL/Image.hpp
+++ b/src/OpenGL/libEGL/Image.hpp
@@ -3,6 +3,11 @@
#include "Renderer/Surface.hpp"
+#if defined(__ANDROID__)
+#include <hardware/gralloc.h>
+#include <system/window.h>
+#endif
+
#include <assert.h>
namespace egl
@@ -23,6 +28,11 @@
, sw::Surface(resource, width, height, depth, internalFormat, true, true)
{
shared = false;
+
+ #if defined(__ANDROID__)
+ nativeBuffer = 0;
+ gralloc = 0;
+ #endif
}
Image(sw::Resource *resource, int width, int height, int depth, sw::Format internalFormat, bool lockable, bool renderTarget)
@@ -30,6 +40,11 @@
, sw::Surface(resource, width, height, depth, internalFormat, lockable, renderTarget)
{
shared = false;
+
+ #if defined(__ANDROID__)
+ nativeBuffer = 0;
+ gralloc = 0;
+ #endif
}
GLsizei getWidth() const
@@ -76,6 +91,13 @@
void *lock(unsigned int left, unsigned int top, sw::Lock lock)
{
+ #if defined(__ANDROID__)
+ if(nativeBuffer) // Lock the buffer from ANativeWindowBuffer
+ {
+ return lockNativeBuffer(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+ }
+ #endif
+
return lockExternal(left, top, 0, lock, sw::PUBLIC);
}
@@ -86,6 +108,13 @@
void unlock()
{
+ #if defined(__ANDROID__)
+ if(nativeBuffer) // Unlock the buffer from ANativeWindowBuffer
+ {
+ return unlockNativeBuffer();
+ }
+ #endif
+
unlockExternal();
}
@@ -94,15 +123,48 @@
virtual void unbind(const Texture *parent) = 0; // Break parent ownership and release
void destroyShared() // Release a shared image
- {
+ {
+ #if defined(__ANDROID__)
+ if(nativeBuffer)
+ {
+ nativeBuffer->common.decRef(&nativeBuffer->common);
+ }
+ #endif
+
assert(shared);
- shared = false;
+ shared = false;
release();
- }
+ }
virtual void loadImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLint unpackAlignment, const void *input) = 0;
virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0;
+ #if defined(__ANDROID__)
+ void setNativeBuffer(ANativeWindowBuffer* buffer)
+ {
+ nativeBuffer = buffer;
+ nativeBuffer->common.incRef(&nativeBuffer->common);
+ }
+
+ virtual void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client)
+ {
+ if(nativeBuffer) // Lock the buffer from ANativeWindowBuffer
+ {
+ return lockNativeBuffer(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+ }
+ return sw::Surface::lockInternal(x, y, z, lock, client);
+ }
+
+ virtual void unlockInternal()
+ {
+ if(nativeBuffer) // Unlock the buffer from ANativeWindowBuffer
+ {
+ return unlockNativeBuffer();
+ }
+ return sw::Surface::unlockInternal();
+ }
+ #endif
+
protected:
virtual ~Image()
{
@@ -116,6 +178,40 @@
const int depth;
bool shared; // Used as an EGLImage
+
+ #if defined(__ANDROID__)
+ ANativeWindowBuffer *nativeBuffer;
+ gralloc_module_t const *gralloc;
+
+ void initGralloc()
+ {
+ hw_module_t const *module;
+ hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ gralloc = reinterpret_cast<gralloc_module_t const*>(module);
+ }
+
+ void* lockNativeBuffer(int usage)
+ {
+ if(!gralloc)
+ {
+ initGralloc();
+ }
+
+ void *buffer = 0;
+ gralloc->lock(gralloc, nativeBuffer->handle, usage, 0, 0, nativeBuffer->width, nativeBuffer->height, &buffer);
+ return buffer;
+ }
+
+ void unlockNativeBuffer()
+ {
+ if(!gralloc)
+ {
+ initGralloc();
+ }
+
+ gralloc->unlock(gralloc, nativeBuffer->handle);
+ }
+ #endif
};
}
diff --git a/src/OpenGL/libEGL/libEGL.cpp b/src/OpenGL/libEGL/libEGL.cpp
index e016390..b053c94 100644
--- a/src/OpenGL/libEGL/libEGL.cpp
+++ b/src/OpenGL/libEGL/libEGL.cpp
@@ -20,6 +20,10 @@
#include "common/debug.h"
#include "Common/Version.h"
+#if defined(__ANDROID__)
+#include <system/window.h>
+#endif
+
#include <string.h>
static bool validateDisplay(egl::Display *display)
@@ -870,6 +874,15 @@
return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
}
+ #if defined(__ANDROID__)
+ if(target == EGL_NATIVE_BUFFER_ANDROID)
+ {
+ // When target is EGL_NATIVE_BUFFER_ANDROID, ctx is always EGL_NO_CONTEXT.
+ // Get the current context so that we can validate and create shared image
+ context = static_cast<egl::Context*>(egl::getCurrentContext());
+ }
+ #endif
+
EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
if(validationResult != EGL_SUCCESS)
diff --git a/src/OpenGL/libGLES_CM/Context.cpp b/src/OpenGL/libGLES_CM/Context.cpp
index c91f1dc..a784ded 100644
--- a/src/OpenGL/libGLES_CM/Context.cpp
+++ b/src/OpenGL/libGLES_CM/Context.cpp
@@ -2561,6 +2561,10 @@
break;
case EGL_GL_RENDERBUFFER_KHR:
break;
+ #if defined(__ANDROID__)
+ case EGL_NATIVE_BUFFER_ANDROID:
+ break;
+ #endif
default:
return EGL_BAD_PARAMETER;
}
@@ -2608,6 +2612,32 @@
return EGL_BAD_ACCESS;
}
}
+ #if defined(__ANDROID__)
+ else if(target == EGL_NATIVE_BUFFER_ANDROID)
+ {
+ ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(name);
+
+ if(nativeBuffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+ {
+ return EGL_BAD_PARAMETER;
+ }
+
+ if(nativeBuffer->common.version != sizeof(ANativeWindowBuffer))
+ {
+ return EGL_BAD_PARAMETER;
+ }
+
+ switch(nativeBuffer->format)
+ {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ break;
+ default:
+ return EGL_BAD_PARAMETER;
+ }
+ }
+ #endif
else UNREACHABLE();
return EGL_SUCCESS;
@@ -2627,6 +2657,22 @@
return renderbuffer->createSharedImage();
}
+ #if defined(__ANDROID__)
+ else if(target == EGL_NATIVE_BUFFER_ANDROID)
+ {
+ ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(name);
+ nativeBuffer->common.incRef(&nativeBuffer->common);
+
+ GLenum format = Image::getColorFormatFromAndroid(nativeBuffer->format);
+ GLenum type = Image::getPixelFormatFromAndroid(nativeBuffer->format);
+
+ es1::Image *image = new Image(0, nativeBuffer->width, nativeBuffer->height, format, type);
+ image->setNativeBuffer(nativeBuffer);
+ image->markShared();
+
+ return image;
+ }
+ #endif
else UNREACHABLE();
return 0;
diff --git a/src/OpenGL/libGLES_CM/Image.cpp b/src/OpenGL/libGLES_CM/Image.cpp
index 416b6b4..e025169 100644
--- a/src/OpenGL/libGLES_CM/Image.cpp
+++ b/src/OpenGL/libGLES_CM/Image.cpp
@@ -544,4 +544,46 @@
unlock();
}
-}
\ No newline at end of file
+
+ #if defined(__ANDROID__)
+ GLenum Image::getColorFormatFromAndroid(int format)
+ {
+ switch(format)
+ {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return GL_RGBA;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return GL_RGB;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return GL_RGB565_OES;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return GL_BGRA_EXT;
+ #if GCE_PLATFORM_SDK_VERSION >= 19
+ case HAL_PIXEL_FORMAT_sRGB_A_8888:
+ case HAL_PIXEL_FORMAT_sRGB_X_8888:
+ #endif
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_Y8:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_BLOB:
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ default:
+ UNIMPLEMENTED();
+ }
+ return GL_RGBA;
+ }
+
+ GLenum Image::getPixelFormatFromAndroid(int format)
+ {
+ if(format == HAL_PIXEL_FORMAT_Y16)
+ {
+ return GL_UNSIGNED_SHORT;
+ }
+
+ return GL_UNSIGNED_BYTE;
+ }
+ #endif
+}
diff --git a/src/OpenGL/libGLES_CM/Image.hpp b/src/OpenGL/libGLES_CM/Image.hpp
index a5b0251..223d6ce 100644
--- a/src/OpenGL/libGLES_CM/Image.hpp
+++ b/src/OpenGL/libGLES_CM/Image.hpp
@@ -37,6 +37,11 @@
static sw::Format selectInternalFormat(GLenum format, GLenum type);
+ #if defined(__ANDROID__)
+ static GLenum getColorFormatFromAndroid(int format);
+ static GLenum getPixelFormatFromAndroid(int format);
+ #endif
+
private:
virtual ~Image();
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 8692d16..2b099a2 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3522,6 +3522,10 @@
break;
case EGL_GL_RENDERBUFFER_KHR:
break;
+ #if defined(__ANDROID__)
+ case EGL_NATIVE_BUFFER_ANDROID:
+ break;
+ #endif
default:
return EGL_BAD_PARAMETER;
}
@@ -3569,6 +3573,32 @@
return EGL_BAD_ACCESS;
}
}
+ #if defined(__ANDROID__)
+ else if(target == EGL_NATIVE_BUFFER_ANDROID)
+ {
+ ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(name);
+
+ if(nativeBuffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC)
+ {
+ return EGL_BAD_PARAMETER;
+ }
+
+ if(nativeBuffer->common.version != sizeof(ANativeWindowBuffer))
+ {
+ return EGL_BAD_PARAMETER;
+ }
+
+ switch(nativeBuffer->format)
+ {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ break;
+ default:
+ return EGL_BAD_PARAMETER;
+ }
+ }
+ #endif
else UNREACHABLE();
return EGL_SUCCESS;
@@ -3601,6 +3631,22 @@
return renderbuffer->createSharedImage();
}
+ #if defined(__ANDROID__)
+ else if(target == EGL_NATIVE_BUFFER_ANDROID)
+ {
+ ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(name);
+ nativeBuffer->common.incRef(&nativeBuffer->common);
+
+ GLenum format = Image::getColorFormatFromAndroid(nativeBuffer->format);
+ GLenum type = Image::getPixelFormatFromAndroid(nativeBuffer->format);
+
+ es2::Image *image = new Image(0, nativeBuffer->width, nativeBuffer->height, format, type);
+ image->setNativeBuffer(nativeBuffer);
+ image->markShared();
+
+ return image;
+ }
+ #endif
else UNREACHABLE();
return 0;
diff --git a/src/OpenGL/libGLESv2/Image.cpp b/src/OpenGL/libGLESv2/Image.cpp
index 6a36db5..dd8acd7 100644
--- a/src/OpenGL/libGLESv2/Image.cpp
+++ b/src/OpenGL/libGLESv2/Image.cpp
@@ -53,13 +53,13 @@
UNIMPLEMENTED();
}
- template<>
+ template<>
void LoadImageRow<Alpha>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
memcpy(dest + xoffset, source, width);
}
- template<>
+ template<>
void LoadImageRow<AlphaFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const float *sourceF = reinterpret_cast<const float*>(source);
@@ -74,7 +74,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<AlphaHalfFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned short *sourceH = reinterpret_cast<const unsigned short*>(source);
@@ -89,13 +89,13 @@
}
}
- template<>
+ template<>
void LoadImageRow<Luminance>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
memcpy(dest + xoffset, source, width);
}
- template<>
+ template<>
void LoadImageRow<LuminanceFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const float *sourceF = reinterpret_cast<const float*>(source);
@@ -110,7 +110,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<LuminanceHalfFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned short *sourceH = reinterpret_cast<const unsigned short*>(source);
@@ -125,13 +125,13 @@
}
}
- template<>
+ template<>
void LoadImageRow<LuminanceAlpha>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
memcpy(dest + xoffset * 2, source, width * 2);
}
- template<>
+ template<>
void LoadImageRow<LuminanceAlphaFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const float *sourceF = reinterpret_cast<const float*>(source);
@@ -146,7 +146,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<LuminanceAlphaHalfFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned short *sourceH = reinterpret_cast<const unsigned short*>(source);
@@ -161,7 +161,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<RGBUByte>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
unsigned char *destB = dest + xoffset * 4;
@@ -175,7 +175,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<RGB565>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned short *source565 = reinterpret_cast<const unsigned short*>(source);
@@ -191,7 +191,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<RGBFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const float *sourceF = reinterpret_cast<const float*>(source);
@@ -206,7 +206,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<RGBHalfFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned short *sourceH = reinterpret_cast<const unsigned short*>(source);
@@ -221,7 +221,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<RGBAUByte>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned int *sourceI = reinterpret_cast<const unsigned int*>(source);
@@ -234,7 +234,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<RGBA4444>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned short *source4444 = reinterpret_cast<const unsigned short*>(source);
@@ -250,7 +250,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<RGBA5551>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned short *source5551 = reinterpret_cast<const unsigned short*>(source);
@@ -266,25 +266,25 @@
}
}
- template<>
+ template<>
void LoadImageRow<RGBAFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
memcpy(dest + xoffset * 16, source, width * 16);
}
- template<>
+ template<>
void LoadImageRow<RGBAHalfFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
memcpy(dest + xoffset * 8, source, width * 8);
}
- template<>
+ template<>
void LoadImageRow<BGRA>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
memcpy(dest + xoffset * 4, source, width * 4);
}
- template<>
+ template<>
void LoadImageRow<D16>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned short *sourceD16 = reinterpret_cast<const unsigned short*>(source);
@@ -296,7 +296,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<D24>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned int *sourceD24 = reinterpret_cast<const unsigned int*>(source);
@@ -308,7 +308,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<D32>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned int *sourceD32 = reinterpret_cast<const unsigned int*>(source);
@@ -320,7 +320,7 @@
}
}
- template<>
+ template<>
void LoadImageRow<S8>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
{
const unsigned int *sourceI = reinterpret_cast<const unsigned int*>(source);
@@ -670,4 +670,44 @@
unlock();
}
-}
\ No newline at end of file
+
+ #if defined(__ANDROID__)
+ GLenum Image::getColorFormatFromAndroid(int format)
+ {
+ switch(format)
+ {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return GL_RGBA;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return GL_RGB;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return GL_RGB565_OES;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return GL_BGRA_EXT;
+ case HAL_PIXEL_FORMAT_sRGB_A_8888:
+ case HAL_PIXEL_FORMAT_sRGB_X_8888:
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_Y8:
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_BLOB:
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ default:
+ UNIMPLEMENTED();
+ }
+ return GL_RGBA;
+ }
+
+ GLenum Image::getPixelFormatFromAndroid(int format)
+ {
+ if(format == HAL_PIXEL_FORMAT_Y16)
+ {
+ return GL_UNSIGNED_SHORT;
+ }
+
+ return GL_UNSIGNED_BYTE;
+ }
+ #endif
+}
diff --git a/src/OpenGL/libGLESv2/Image.hpp b/src/OpenGL/libGLESv2/Image.hpp
index 3824a8f..5cb9533 100644
--- a/src/OpenGL/libGLESv2/Image.hpp
+++ b/src/OpenGL/libGLESv2/Image.hpp
@@ -38,6 +38,11 @@
static sw::Format selectInternalFormat(GLenum format, GLenum type);
+ #if defined(__ANDROID__)
+ static GLenum getColorFormatFromAndroid(int format);
+ static GLenum getPixelFormatFromAndroid(int format);
+ #endif
+
private:
virtual ~Image();