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();