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 @@
#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 @@ public:
, 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 @@ public:
, 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 @@ public:
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 @@ public:
void unlock()
{
#if defined(__ANDROID__)
if(nativeBuffer) // Unlock the buffer from ANativeWindowBuffer
{
return unlockNativeBuffer();
}
#endif
unlockExternal();
}
......@@ -95,6 +124,13 @@ public:
void destroyShared() // Release a shared image
{
#if defined(__ANDROID__)
if(nativeBuffer)
{
nativeBuffer->common.decRef(&nativeBuffer->common);
}
#endif
assert(shared);
shared = false;
release();
......@@ -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 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 @@ protected:
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
};
}
......
......@@ -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 @@ EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenu
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)
......
......@@ -2561,6 +2561,10 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture
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 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture
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 @@ egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textu
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;
......
......@@ -544,4 +544,46 @@ namespace es1
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
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();
......
......@@ -3522,6 +3522,10 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture
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 @@ EGLenum Context::validateSharedImage(EGLenum target, GLuint name, GLuint texture
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 @@ egl::Image *Context::createSharedImage(EGLenum target, GLuint name, GLuint textu
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;
......
......@@ -670,4 +670,44 @@ namespace es2
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
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();
......
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