Commit b508ff81 by Ping-Hao Wu Committed by Nicolas Capens

Implement basic ANDROID_image_native_buffer support.

Change-Id: I7e844eb7c313455d48cd2fc09440f10d639b4c77 Reviewed-on: https://swiftshader-review.googlesource.com/2758Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-by: 's avatarGreg Hartman <ghartman@google.com> Reviewed-by: 's avatarPing-Hao Wu <pinghao@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 4e0d6f60
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
#include "Renderer/Surface.hpp" #include "Renderer/Surface.hpp"
#if defined(__ANDROID__)
#include <hardware/gralloc.h>
#include <system/window.h>
#endif
#include <assert.h> #include <assert.h>
namespace egl namespace egl
...@@ -23,6 +28,11 @@ public: ...@@ -23,6 +28,11 @@ public:
, sw::Surface(resource, width, height, depth, internalFormat, true, true) , sw::Surface(resource, width, height, depth, internalFormat, true, true)
{ {
shared = false; 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) Image(sw::Resource *resource, int width, int height, int depth, sw::Format internalFormat, bool lockable, bool renderTarget)
...@@ -30,6 +40,11 @@ public: ...@@ -30,6 +40,11 @@ public:
, sw::Surface(resource, width, height, depth, internalFormat, lockable, renderTarget) , sw::Surface(resource, width, height, depth, internalFormat, lockable, renderTarget)
{ {
shared = false; shared = false;
#if defined(__ANDROID__)
nativeBuffer = 0;
gralloc = 0;
#endif
} }
GLsizei getWidth() const GLsizei getWidth() const
...@@ -76,6 +91,13 @@ public: ...@@ -76,6 +91,13 @@ public:
void *lock(unsigned int left, unsigned int top, sw::Lock lock) 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); return lockExternal(left, top, 0, lock, sw::PUBLIC);
} }
...@@ -86,6 +108,13 @@ public: ...@@ -86,6 +108,13 @@ public:
void unlock() void unlock()
{ {
#if defined(__ANDROID__)
if(nativeBuffer) // Unlock the buffer from ANativeWindowBuffer
{
return unlockNativeBuffer();
}
#endif
unlockExternal(); unlockExternal();
} }
...@@ -95,6 +124,13 @@ public: ...@@ -95,6 +124,13 @@ public:
void destroyShared() // Release a shared image void destroyShared() // Release a shared image
{ {
#if defined(__ANDROID__)
if(nativeBuffer)
{
nativeBuffer->common.decRef(&nativeBuffer->common);
}
#endif
assert(shared); assert(shared);
shared = false; shared = false;
release(); release();
...@@ -103,6 +139,32 @@ public: ...@@ -103,6 +139,32 @@ public:
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 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; 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: protected:
virtual ~Image() virtual ~Image()
{ {
...@@ -116,6 +178,40 @@ protected: ...@@ -116,6 +178,40 @@ protected:
const int depth; const int depth;
bool shared; // Used as an EGLImage 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
}; };
} }
......
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
#include "common/debug.h" #include "common/debug.h"
#include "Common/Version.h" #include "Common/Version.h"
#if defined(__ANDROID__)
#include <system/window.h>
#endif
#include <string.h> #include <string.h>
static bool validateDisplay(egl::Display *display) static bool validateDisplay(egl::Display *display)
...@@ -870,6 +874,15 @@ EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenu ...@@ -870,6 +874,15 @@ EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenu
return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 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); EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
if(validationResult != EGL_SUCCESS) if(validationResult != EGL_SUCCESS)
......
...@@ -2561,6 +2561,10 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture ...@@ -2561,6 +2561,10 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture
break; break;
case EGL_GL_RENDERBUFFER_KHR: case EGL_GL_RENDERBUFFER_KHR:
break; break;
#if defined(__ANDROID__)
case EGL_NATIVE_BUFFER_ANDROID:
break;
#endif
default: default:
return EGL_BAD_PARAMETER; return EGL_BAD_PARAMETER;
} }
...@@ -2608,6 +2612,32 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture ...@@ -2608,6 +2612,32 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture
return EGL_BAD_ACCESS; 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(); else UNREACHABLE();
return EGL_SUCCESS; return EGL_SUCCESS;
...@@ -2627,6 +2657,22 @@ egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textu ...@@ -2627,6 +2657,22 @@ egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textu
return renderbuffer->createSharedImage(); 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(); else UNREACHABLE();
return 0; return 0;
......
...@@ -544,4 +544,46 @@ namespace es1 ...@@ -544,4 +544,46 @@ namespace es1
unlock(); unlock();
} }
#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
} }
...@@ -37,6 +37,11 @@ namespace es1 ...@@ -37,6 +37,11 @@ namespace es1
static sw::Format selectInternalFormat(GLenum format, GLenum type); static sw::Format selectInternalFormat(GLenum format, GLenum type);
#if defined(__ANDROID__)
static GLenum getColorFormatFromAndroid(int format);
static GLenum getPixelFormatFromAndroid(int format);
#endif
private: private:
virtual ~Image(); virtual ~Image();
......
...@@ -3522,6 +3522,10 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture ...@@ -3522,6 +3522,10 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture
break; break;
case EGL_GL_RENDERBUFFER_KHR: case EGL_GL_RENDERBUFFER_KHR:
break; break;
#if defined(__ANDROID__)
case EGL_NATIVE_BUFFER_ANDROID:
break;
#endif
default: default:
return EGL_BAD_PARAMETER; return EGL_BAD_PARAMETER;
} }
...@@ -3569,6 +3573,32 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture ...@@ -3569,6 +3573,32 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture
return EGL_BAD_ACCESS; 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(); else UNREACHABLE();
return EGL_SUCCESS; return EGL_SUCCESS;
...@@ -3601,6 +3631,22 @@ egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textu ...@@ -3601,6 +3631,22 @@ egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textu
return renderbuffer->createSharedImage(); 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(); else UNREACHABLE();
return 0; return 0;
......
...@@ -670,4 +670,44 @@ namespace es2 ...@@ -670,4 +670,44 @@ namespace es2
unlock(); unlock();
} }
#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
} }
...@@ -38,6 +38,11 @@ namespace es2 ...@@ -38,6 +38,11 @@ namespace es2
static sw::Format selectInternalFormat(GLenum format, GLenum type); static sw::Format selectInternalFormat(GLenum format, GLenum type);
#if defined(__ANDROID__)
static GLenum getColorFormatFromAndroid(int format);
static GLenum getPixelFormatFromAndroid(int format);
#endif
private: private:
virtual ~Image(); virtual ~Image();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment