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();
}
......@@ -94,15 +123,48 @@ public:
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 @@ 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();
}
}
\ 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
}
......@@ -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;
......
......@@ -53,13 +53,13 @@ namespace
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace
}
}
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 @@ namespace es2
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
}
......@@ -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