Commit c99c22bb by Mohan Maiya Committed by Commit Bot

EGL: Add support for EGL_ANDROID_create_native_client_buffer

This EGL extension will add support for creating EGLClientBuffer backed by an Android window buffer (struct ANativeWindowBuffer) which can be later used to create an EGLImage. Bug: angleproject:5018 Tests: angle_end2end_tests --gtest_filter=ImageTest.SourceNativeClientBufferTarget* Change-Id: If78ed7b80ad09629b8c5f5b5a0eb07a548e82e6e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2404320Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Mohan Maiya <m.maiya@samsung.com>
parent 83c7e1ae
......@@ -10,25 +10,25 @@
"scripts/gl_angle_ext.xml":
"5b91263f1099308e4e75f89d85be564e",
"scripts/registry_xml.py":
"40961fa253854a2e9644c0c5d78daae9",
"9fb89d0ee43040ddf1aa5899abfca7af",
"scripts/wgl.xml":
"aa96419c582af2f6673430e2847693f4",
"src/libEGL/egl_loader_autogen.cpp":
"394c31d7e61b285be5bc6a2cb8325a8d",
"419041385faafafc4299cd6b5b8da642",
"src/libEGL/egl_loader_autogen.h":
"343b43d7318884204c0699cfaa8ef2dc",
"01035f491f6692446c882504c3d20792",
"src/tests/perf_tests/restricted_traces/trace_egl_loader_autogen.cpp":
"fa2cce11eef7e995c62c31da0658a5da",
"929f135ba9ba7717e76552c9e76f0f2f",
"src/tests/perf_tests/restricted_traces/trace_egl_loader_autogen.h":
"389cf2453f8359538c391e58cd6a84d2",
"af2eb06cc8de3456b7bfde497b04c0c4",
"src/tests/perf_tests/restricted_traces/trace_gles_loader_autogen.cpp":
"f989f0d3e94d1ae985cfc9514cea8d48",
"src/tests/perf_tests/restricted_traces/trace_gles_loader_autogen.h":
"90da6d113a8248e148bf3a3853192292",
"util/egl_loader_autogen.cpp":
"6eb720862e78992d0ed3abfe50bfa0ff",
"e10da66fdf789e6c52dee1f9e1cd5a68",
"util/egl_loader_autogen.h":
"591c6d6b1ae0a90758204993ca2638a0",
"5e2ac71185c91139c6768adf8615b3c7",
"util/gles_loader_autogen.cpp":
"4fb108c57db72c07d72883ec7c9e2286",
"util/gles_loader_autogen.h":
......
......@@ -12,7 +12,7 @@
"scripts/gl_angle_ext.xml":
"5b91263f1099308e4e75f89d85be564e",
"scripts/registry_xml.py":
"40961fa253854a2e9644c0c5d78daae9",
"9fb89d0ee43040ddf1aa5899abfca7af",
"scripts/wgl.xml":
"aa96419c582af2f6673430e2847693f4",
"src/libANGLE/Context_gl_1_0_autogen.h":
......@@ -256,9 +256,9 @@
"src/libGLESv2/libGLESv2_autogen.cpp":
"980929401e0c450b481ff9e5f91ced41",
"src/libGLESv2/libGLESv2_autogen.def":
"b0be95ed88c909eca24e1da272fdc0df",
"0b5301a0cfda69c876cc88563883199a",
"src/libGLESv2/libGLESv2_no_capture_autogen.def":
"11eb5d8818ae828bd27594f31cdfb6bc",
"0a8cf9e24d7caf60e103e91ff7cd7bbe",
"src/libGLESv2/libGLESv2_with_capture_autogen.def":
"bc9de308d0e85b4ee6922a490397bcb8"
"78c3ebee64c4ff3e278a8c8abb802218"
}
\ No newline at end of file
......@@ -6,7 +6,7 @@
"scripts/gl_angle_ext.xml":
"5b91263f1099308e4e75f89d85be564e",
"scripts/registry_xml.py":
"40961fa253854a2e9644c0c5d78daae9",
"9fb89d0ee43040ddf1aa5899abfca7af",
"src/libANGLE/gl_enum_utils_autogen.cpp":
"adc5a5fa540a850ab15e563477cafc47",
"src/libANGLE/gl_enum_utils_autogen.h":
......
......@@ -10,11 +10,11 @@
"scripts/gl_angle_ext.xml":
"5b91263f1099308e4e75f89d85be564e",
"scripts/registry_xml.py":
"40961fa253854a2e9644c0c5d78daae9",
"9fb89d0ee43040ddf1aa5899abfca7af",
"scripts/wgl.xml":
"aa96419c582af2f6673430e2847693f4",
"src/libGL/proc_table_wgl_autogen.cpp":
"253f59ef3aa9ccfcab1364ae5101dbe2",
"src/libGLESv2/proc_table_egl_autogen.cpp":
"75ca26f352fe69504fdcdc6d778aad08"
"32466f80e116effea6793b04ffdbac8d"
}
\ No newline at end of file
......@@ -120,6 +120,7 @@ supported_extensions = sorted(angle_extensions + gles1_extensions + gles_extensi
supported_egl_extensions = [
"EGL_ANDROID_blob_cache",
"EGL_ANDROID_create_native_client_buffer",
"EGL_ANDROID_framebuffer_target",
"EGL_ANDROID_get_frame_timestamps",
"EGL_ANDROID_get_native_client_buffer",
......
......@@ -11,6 +11,12 @@
#include <cstdint>
#if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
# define ANGLE_AHARDWARE_BUFFER_SUPPORT
// NDK header file for access to Android Hardware Buffers
# include <android/hardware_buffer.h>
#endif
// Taken from cutils/native_handle.h:
// https://android.googlesource.com/platform/system/core/+/master/libcutils/include/cutils/native_handle.h
typedef struct native_handle
......@@ -78,6 +84,8 @@ typedef struct ANativeWindowBuffer
* Buffer pixel formats.
*/
enum {
#ifndef ANGLE_AHARDWARE_BUFFER_SUPPORT
/**
* Corresponding formats:
* Vulkan: VK_FORMAT_R8G8B8A8_UNORM
......@@ -107,10 +115,13 @@ enum {
* OpenGL ES: GL_RGB565
*/
AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4,
#endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM = 5,
AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM = 6,
AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM = 7,
#ifndef ANGLE_AHARDWARE_BUFFER_SUPPORT
/**
* Corresponding formats:
* Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT
......@@ -180,6 +191,8 @@ enum {
* cube-maps or multi-layered textures.
*/
AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23,
#endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
};
// clang-format on
......@@ -219,6 +232,55 @@ ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuf
return reinterpret_cast<ANativeWindowBuffer *>(clientBuffer);
}
uint64_t GetAHBUsage(int eglNativeBufferUsage)
{
uint64_t ahbUsage = 0;
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID)
{
ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
}
if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID)
{
ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
}
if (eglNativeBufferUsage & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)
{
ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
}
#endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
return ahbUsage;
}
EGLClientBuffer CreateEGLClientBufferFromAHardwareBuffer(int width,
int height,
int depth,
int androidFormat,
int usage)
{
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
// The height and width are number of pixels of size format
AHardwareBuffer_Desc aHardwareBufferDescription = {};
aHardwareBufferDescription.width = static_cast<uint32_t>(width);
aHardwareBufferDescription.height = static_cast<uint32_t>(height);
aHardwareBufferDescription.layers = static_cast<uint32_t>(depth);
aHardwareBufferDescription.format = androidFormat;
aHardwareBufferDescription.usage = GetAHBUsage(usage);
// Allocate memory from Android Hardware Buffer
AHardwareBuffer *aHardwareBuffer = nullptr;
int res = AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer);
if (res != 0)
{
return nullptr;
}
return AHardwareBufferToClientBuffer(aHardwareBuffer);
#endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
return nullptr;
}
void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer,
int *width,
int *height,
......
......@@ -10,6 +10,11 @@
#define COMMON_ANDROIDUTIL_H_
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdint.h>
#include <array>
#include "angle_gl.h"
struct ANativeWindowBuffer;
......@@ -21,9 +26,17 @@ namespace angle
namespace android
{
constexpr std::array<GLenum, 3> kSupportedSizedInternalFormats = {GL_RGBA8, GL_RGB8, GL_RGB565};
ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer);
EGLClientBuffer AHardwareBufferToClientBuffer(const AHardwareBuffer *hardwareBuffer);
EGLClientBuffer CreateEGLClientBufferFromAHardwareBuffer(int width,
int height,
int depth,
int androidFormat,
int usage);
void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer,
int *width,
int *height,
......@@ -34,6 +47,8 @@ int GLInternalFormatToNativePixelFormat(GLenum internalFormat);
AHardwareBuffer *ANativeWindowBufferToAHardwareBuffer(ANativeWindowBuffer *windowBuffer);
uint64_t GetAHBUsage(int eglNativeBufferUsage);
} // namespace android
} // namespace angle
......
......@@ -1392,6 +1392,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_ANDROID_recordable", recordable, &extensionStrings);
InsertExtensionString("EGL_ANGLE_power_preference", powerPreference, &extensionStrings);
InsertExtensionString("EGL_ANGLE_image_d3d11_texture", imageD3D11Texture, &extensionStrings);
InsertExtensionString("EGL_ANDROID_create_native_client_buffer", createNativeClientBufferANDROID, &extensionStrings);
InsertExtensionString("EGL_ANDROID_get_native_client_buffer", getNativeClientBufferANDROID, &extensionStrings);
InsertExtensionString("EGL_ANDROID_native_fence_sync", nativeFenceSyncANDROID, &extensionStrings);
InsertExtensionString("EGL_ANGLE_create_context_backwards_compatible", createContextBackwardsCompatible, &extensionStrings);
......
......@@ -1051,6 +1051,9 @@ struct DisplayExtensions
// EGL_ANDROID_get_native_client_buffer
bool getNativeClientBufferANDROID = false;
// EGL_ANDROID_create_native_client_buffer
bool createNativeClientBufferANDROID = false;
// EGL_ANDROID_native_fence_sync
bool nativeFenceSyncANDROID = false;
......
......@@ -1470,6 +1470,28 @@ EGLClientBuffer Display::GetNativeClientBuffer(const AHardwareBuffer *buffer)
return angle::android::AHardwareBufferToClientBuffer(buffer);
}
// static
Error Display::CreateNativeClientBuffer(const egl::AttributeMap &attribMap,
EGLClientBuffer *eglClientBuffer)
{
int androidHardwareBufferFormat = gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap);
int width = attribMap.getAsInt(EGL_WIDTH, 0);
int height = attribMap.getAsInt(EGL_HEIGHT, 0);
int usage = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
// https://developer.android.com/ndk/reference/group/a-hardware-buffer#ahardwarebuffer_lock
// for AHardwareBuffer_lock()
// The passed AHardwareBuffer must have one layer, otherwise the call will fail.
constexpr int kLayerCount = 1;
*eglClientBuffer = angle::android::CreateEGLClientBufferFromAHardwareBuffer(
width, height, kLayerCount, androidHardwareBufferFormat, usage);
return (*eglClientBuffer == nullptr)
? egl::EglBadParameter() << "native client buffer allocation failed."
: NoError();
}
Error Display::waitClient(const gl::Context *context)
{
return mImplementation->waitClient(context);
......
......@@ -199,6 +199,8 @@ class Display final : public LabeledObject,
BlobCache &getBlobCache() { return mBlobCache; }
static EGLClientBuffer GetNativeClientBuffer(const struct AHardwareBuffer *buffer);
static Error CreateNativeClientBuffer(const egl::AttributeMap &attribMap,
EGLClientBuffer *eglClientBuffer);
Error waitClient(const gl::Context *context);
Error waitNative(const gl::Context *context, EGLint engine);
......
......@@ -1116,6 +1116,32 @@ const InternalFormatInfoMap &GetInternalFormatMap()
return *formatMap;
}
int GetAndroidHardwareBufferFormatFromChannelSizes(const egl::AttributeMap &attribMap)
{
// Retrieve channel size from attribute map. The default value should be 0, per spec.
GLuint redSize = static_cast<GLuint>(attribMap.getAsInt(EGL_RED_SIZE, 0));
GLuint greenSize = static_cast<GLuint>(attribMap.getAsInt(EGL_GREEN_SIZE, 0));
GLuint blueSize = static_cast<GLuint>(attribMap.getAsInt(EGL_BLUE_SIZE, 0));
GLuint alphaSize = static_cast<GLuint>(attribMap.getAsInt(EGL_ALPHA_SIZE, 0));
GLenum glInternalFormat = 0;
for (GLenum sizedInternalFormat : angle::android::kSupportedSizedInternalFormats)
{
const gl::InternalFormat &internalFormat = GetSizedInternalFormatInfo(sizedInternalFormat);
ASSERT(internalFormat.internalFormat != GL_NONE && internalFormat.sized);
if (internalFormat.isChannelSizeCompatible(redSize, greenSize, blueSize, alphaSize))
{
glInternalFormat = sizedInternalFormat;
break;
}
}
return (glInternalFormat != 0)
? angle::android::GLInternalFormatToNativePixelFormat(glInternalFormat)
: 0;
}
static FormatSet BuildAllSizedInternalFormatSet()
{
FormatSet result;
......
......@@ -179,6 +179,16 @@ struct InternalFormat
// Support upload a portion of image?
bool supportSubImage() const;
ANGLE_INLINE bool isChannelSizeCompatible(GLuint redSize,
GLuint greenSize,
GLuint blueSize,
GLuint alphaSize) const
{
// We only check for equality in all channel sizes
return ((redSize == redBits) && (greenSize == greenBits) && (blueSize == blueBits) &&
(alphaSize == alphaBits));
}
// Return true if the format is a required renderbuffer format in the given version of the core
// spec. Note that it isn't always clear whether all the rules that apply to core required
// renderbuffer formats also apply to additional formats added by extensions. Because of this
......@@ -278,6 +288,8 @@ typedef std::unordered_map<GLenum, std::unordered_map<GLenum, InternalFormat>>
InternalFormatInfoMap;
const InternalFormatInfoMap &GetInternalFormatMap();
int GetAndroidHardwareBufferFormatFromChannelSizes(const egl::AttributeMap &attribMap);
ANGLE_INLINE int GetNativeVisualID(const InternalFormat &internalFormat)
{
int nativeVisualId = 0;
......
......@@ -666,6 +666,9 @@ void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
outExtensions->getNativeClientBufferANDROID =
mEGL->hasExtension("EGL_ANDROID_get_native_client_buffer");
outExtensions->createNativeClientBufferANDROID =
mEGL->hasExtension("EGL_ANDROID_create_native_client_buffer");
outExtensions->nativeFenceSyncANDROID = mEGL->hasExtension("EGL_ANDROID_native_fence_sync");
outExtensions->noConfigContext = mEGL->hasExtension("EGL_KHR_no_config_context");
......
......@@ -4520,6 +4520,65 @@ Error ValidateGetNativeClientBufferANDROID(const AHardwareBuffer *buffer)
return NoError();
}
Error ValidateCreateNativeClientBufferANDROID(const egl::AttributeMap &attribMap)
{
int width = attribMap.getAsInt(EGL_WIDTH, 0);
int height = attribMap.getAsInt(EGL_HEIGHT, 0);
int redSize = attribMap.getAsInt(EGL_RED_SIZE, 0);
int greenSize = attribMap.getAsInt(EGL_GREEN_SIZE, 0);
int blueSize = attribMap.getAsInt(EGL_BLUE_SIZE, 0);
int alphaSize = attribMap.getAsInt(EGL_ALPHA_SIZE, 0);
int usage = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
for (AttributeMap::const_iterator attributeIter = attribMap.begin();
attributeIter != attribMap.end(); attributeIter++)
{
EGLAttrib attribute = attributeIter->first;
switch (attribute)
{
case EGL_WIDTH:
case EGL_HEIGHT:
// Validation done after the switch statement
break;
case EGL_RED_SIZE:
case EGL_GREEN_SIZE:
case EGL_BLUE_SIZE:
case EGL_ALPHA_SIZE:
if (redSize < 0 || greenSize < 0 || blueSize < 0 || alphaSize < 0)
{
return EglBadParameter() << "incorrect channel size requested";
}
break;
case EGL_NATIVE_BUFFER_USAGE_ANDROID:
// The buffer must be used for either a texture or a renderbuffer.
if ((usage & ~(EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID |
EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID |
EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) != 0)
{
return EglBadParameter() << "invalid usage flag";
}
break;
case EGL_NONE:
break;
default:
return EglBadAttribute() << "invalid attribute";
}
}
// Validate EGL_WIDTH and EGL_HEIGHT values passed in. Done here to account
// for the case where EGL_WIDTH and EGL_HEIGHT were not part of the attribute list.
if (width <= 0 || height <= 0)
{
return EglBadParameter() << "incorrect buffer dimensions requested";
}
if (gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap) == 0)
{
return EglBadParameter() << "unsupported format";
}
return NoError();
}
Error ValidateDupNativeFenceFDANDROID(const Display *display, const Sync *sync)
{
ANGLE_TRY(ValidateDisplay(display));
......
......@@ -336,6 +336,9 @@ Error ValidateQueryDisplayAttribANGLE(const Display *display, const EGLint attri
// EGL_ANDROID_get_native_client_buffer
Error ValidateGetNativeClientBufferANDROID(const struct AHardwareBuffer *buffer);
// EGL_ANDROID_create_native_client_buffer
Error ValidateCreateNativeClientBufferANDROID(const egl::AttributeMap &attribMap);
// EGL_ANDROID_native_fence_sync
Error ValidateDupNativeFenceFDANDROID(const Display *display, const Sync *sync);
......
......@@ -55,6 +55,7 @@ PFNEGLCREATEPLATFORMWINDOWSURFACEPROC l_EGL_CreatePlatformWindowSurface;
PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC l_EGL_CreatePlatformPixmapSurface;
PFNEGLWAITSYNCPROC l_EGL_WaitSync;
PFNEGLSETBLOBCACHEFUNCSANDROIDPROC l_EGL_SetBlobCacheFuncsANDROID;
PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC l_EGL_CreateNativeClientBufferANDROID;
PFNEGLGETCOMPOSITORTIMINGANDROIDPROC l_EGL_GetCompositorTimingANDROID;
PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROIDPROC l_EGL_GetCompositorTimingSupportedANDROID;
PFNEGLGETFRAMETIMESTAMPSUPPORTEDANDROIDPROC l_EGL_GetFrameTimestampSupportedANDROID;
......@@ -174,6 +175,9 @@ void LoadEGL_EGL(LoadProc loadProc)
l_EGL_WaitSync = reinterpret_cast<PFNEGLWAITSYNCPROC>(loadProc("EGL_WaitSync"));
l_EGL_SetBlobCacheFuncsANDROID = reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>(
loadProc("EGL_SetBlobCacheFuncsANDROID"));
l_EGL_CreateNativeClientBufferANDROID =
reinterpret_cast<PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC>(
loadProc("EGL_CreateNativeClientBufferANDROID"));
l_EGL_GetCompositorTimingANDROID = reinterpret_cast<PFNEGLGETCOMPOSITORTIMINGANDROIDPROC>(
loadProc("EGL_GetCompositorTimingANDROID"));
l_EGL_GetCompositorTimingSupportedANDROID =
......
......@@ -60,6 +60,7 @@
#define EGL_CreatePlatformPixmapSurface l_EGL_CreatePlatformPixmapSurface
#define EGL_WaitSync l_EGL_WaitSync
#define EGL_SetBlobCacheFuncsANDROID l_EGL_SetBlobCacheFuncsANDROID
#define EGL_CreateNativeClientBufferANDROID l_EGL_CreateNativeClientBufferANDROID
#define EGL_GetCompositorTimingANDROID l_EGL_GetCompositorTimingANDROID
#define EGL_GetCompositorTimingSupportedANDROID l_EGL_GetCompositorTimingSupportedANDROID
#define EGL_GetFrameTimestampSupportedANDROID l_EGL_GetFrameTimestampSupportedANDROID
......@@ -157,6 +158,8 @@ ANGLE_NO_EXPORT extern PFNEGLCREATEPLATFORMWINDOWSURFACEPROC l_EGL_CreatePlatfor
ANGLE_NO_EXPORT extern PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC l_EGL_CreatePlatformPixmapSurface;
ANGLE_NO_EXPORT extern PFNEGLWAITSYNCPROC l_EGL_WaitSync;
ANGLE_NO_EXPORT extern PFNEGLSETBLOBCACHEFUNCSANDROIDPROC l_EGL_SetBlobCacheFuncsANDROID;
ANGLE_NO_EXPORT extern PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC
l_EGL_CreateNativeClientBufferANDROID;
ANGLE_NO_EXPORT extern PFNEGLGETCOMPOSITORTIMINGANDROIDPROC l_EGL_GetCompositorTimingANDROID;
ANGLE_NO_EXPORT extern PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROIDPROC
l_EGL_GetCompositorTimingSupportedANDROID;
......
......@@ -715,6 +715,12 @@ EGLClientBuffer EGLAPIENTRY eglGetNativeClientBufferANDROID(const struct AHardwa
return EGL_GetNativeClientBufferANDROID(buffer);
}
EGLClientBuffer EGLAPIENTRY eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
{
EnsureEGLLoaded();
return EGL_CreateNativeClientBufferANDROID(attrib_list);
}
EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
{
EnsureEGLLoaded();
......
......@@ -1513,6 +1513,31 @@ EGLClientBuffer EGLAPIENTRY EGL_GetNativeClientBufferANDROID(const struct AHardw
return egl::Display::GetNativeClientBuffer(buffer);
}
EGLClientBuffer EGLAPIENTRY EGL_CreateNativeClientBufferANDROID(const EGLint *attrib_list)
{
ANGLE_SCOPED_GLOBAL_LOCK();
FUNC_EVENT("const EGLint *attrib_list = 0x%016" PRIxPTR, (uintptr_t)attrib_list);
Thread *thread = egl::GetCurrentThread();
ANGLE_EGL_TRY_RETURN(thread,
(attrib_list == nullptr || attrib_list[0] == EGL_NONE)
? egl::EglBadParameter() << "invalid attribute list."
: NoError(),
"eglCreateNativeClientBufferANDROID", nullptr, nullptr);
const AttributeMap &attribMap = AttributeMap::CreateFromIntArray(attrib_list);
ANGLE_EGL_TRY_RETURN(thread, ValidateCreateNativeClientBufferANDROID(attribMap),
"eglCreateNativeClientBufferANDROID", nullptr, nullptr);
EGLClientBuffer eglClientBuffer = nullptr;
ANGLE_EGL_TRY_RETURN(thread,
egl::Display::CreateNativeClientBuffer(attribMap, &eglClientBuffer),
"eglCreateNativeClientBufferANDROID", nullptr, nullptr);
thread->setSuccess();
return eglClientBuffer;
}
EGLint EGLAPIENTRY EGL_DupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
{
ANGLE_SCOPED_GLOBAL_LOCK();
......
......@@ -220,6 +220,10 @@ ANGLE_EXPORT const char *EGLAPIENTRY EGL_QueryStringiANGLE(EGLDisplay dpy,
ANGLE_EXPORT EGLClientBuffer EGLAPIENTRY
EGL_GetNativeClientBufferANDROID(const struct AHardwareBuffer *buffer);
// EGL_ANDROID_create_native_client_buffer
ANGLE_EXPORT EGLClientBuffer EGLAPIENTRY
EGL_CreateNativeClientBufferANDROID(const EGLint *attrib_list);
// EGL_ANDROID_native_fence_sync
ANGLE_EXPORT EGLint EGLAPIENTRY EGL_DupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync);
......
......@@ -1662,6 +1662,9 @@ EXPORTS
; EGL_ANDROID_blob_cache
EGL_SetBlobCacheFuncsANDROID
; EGL_ANDROID_create_native_client_buffer
EGL_CreateNativeClientBufferANDROID
; EGL_ANDROID_get_frame_timestamps
EGL_GetCompositorTimingANDROID
EGL_GetCompositorTimingSupportedANDROID
......
......@@ -1662,6 +1662,9 @@ EXPORTS
; EGL_ANDROID_blob_cache
EGL_SetBlobCacheFuncsANDROID
; EGL_ANDROID_create_native_client_buffer
EGL_CreateNativeClientBufferANDROID
; EGL_ANDROID_get_frame_timestamps
EGL_GetCompositorTimingANDROID
EGL_GetCompositorTimingSupportedANDROID
......
......@@ -1662,6 +1662,9 @@ EXPORTS
; EGL_ANDROID_blob_cache
EGL_SetBlobCacheFuncsANDROID
; EGL_ANDROID_create_native_client_buffer
EGL_CreateNativeClientBufferANDROID
; EGL_ANDROID_get_frame_timestamps
EGL_GetCompositorTimingANDROID
EGL_GetCompositorTimingSupportedANDROID
......
......@@ -39,6 +39,7 @@ const ProcEntry g_procTable[] = {
{"eglCreateDeviceANGLE", P(EGL_CreateDeviceANGLE)},
{"eglCreateImage", P(EGL_CreateImage)},
{"eglCreateImageKHR", P(EGL_CreateImageKHR)},
{"eglCreateNativeClientBufferANDROID", P(EGL_CreateNativeClientBufferANDROID)},
{"eglCreatePbufferFromClientBuffer", P(EGL_CreatePbufferFromClientBuffer)},
{"eglCreatePbufferSurface", P(EGL_CreatePbufferSurface)},
{"eglCreatePixmapSurface", P(EGL_CreatePixmapSurface)},
......@@ -1626,5 +1627,5 @@ const ProcEntry g_procTable[] = {
{"glWeightPointerOES", P(gl::WeightPointerOES)},
{"glWeightPointerOESContextANGLE", P(gl::WeightPointerOESContextANGLE)}};
const size_t g_numProcs = 1529;
const size_t g_numProcs = 1530;
} // namespace egl
......@@ -43,6 +43,38 @@ constexpr EGLint kDefaultAttribs[] = {
constexpr EGLint kColorspaceAttribs[] = {
EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB_KHR, EGL_NONE,
};
constexpr EGLint kNativeClientBufferAttribs_RGBA8_Texture[] = {
EGL_WIDTH,
1,
EGL_HEIGHT,
1,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_NATIVE_BUFFER_USAGE_ANDROID,
EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID,
EGL_NONE};
constexpr EGLint kNativeClientBufferAttribs_RGBA8_Renderbuffer[] = {
EGL_WIDTH,
1,
EGL_HEIGHT,
1,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_NATIVE_BUFFER_USAGE_ANDROID,
EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID,
EGL_NONE};
} // anonymous namespace
class ImageTest : public ANGLETest
......@@ -475,6 +507,60 @@ class ImageTest : public ANGLETest
*outSourceAHB = aHardwareBuffer;
*outSourceImage = image;
}
void createEGLImageANWBClientBufferSource(size_t width,
size_t height,
size_t depth,
const EGLint *attribsANWB,
const EGLint *attribsImage,
const GLubyte *data,
size_t bytesPerPixel,
EGLImageKHR *outSourceImage)
{
// Set Android Memory
EGLClientBuffer eglClientBuffer = eglCreateNativeClientBufferANDROID(attribsANWB);
EXPECT_NE(eglClientBuffer, nullptr);
// allocate AHB memory
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
AHardwareBuffer *pAHardwareBuffer = angle::android::ANativeWindowBufferToAHardwareBuffer(
angle::android::ClientBufferToANativeWindowBuffer(eglClientBuffer));
void *mappedMemory = nullptr;
int res = AHardwareBuffer_lock(pAHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1,
nullptr, &mappedMemory);
EXPECT_EQ(res, 0);
// Need to grab the stride the implementation might have enforced
AHardwareBuffer_Desc aHardwareBufferDescription = {};
AHardwareBuffer_describe(pAHardwareBuffer, &aHardwareBufferDescription);
const uint32_t stride = aHardwareBufferDescription.stride;
uint32_t rowSize = stride * height;
for (uint32_t i = 0; i < height; i++)
{
uint32_t dstPtrOffset = stride * i * (uint32_t)bytesPerPixel;
uint32_t srcPtrOffset = width * i * (uint32_t)bytesPerPixel;
void *dst = reinterpret_cast<uint8_t *>(mappedMemory) + dstPtrOffset;
memcpy(dst, data + srcPtrOffset, rowSize);
}
res = AHardwareBuffer_unlock(pAHardwareBuffer, nullptr);
EXPECT_EQ(res, 0);
#endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
// Create an image from the source eglClientBuffer
EGLWindow *window = getEGLWindow();
EGLImageKHR image =
eglCreateImageKHR(window->getDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
eglClientBuffer, attribsImage);
ASSERT_EGL_SUCCESS();
*outSourceImage = image;
}
void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint *outTargetRenderbuffer)
{
// Create a target texture from the image
......@@ -493,6 +579,8 @@ class ImageTest : public ANGLETest
void SourceAHBTarget2DArray_helper(const EGLint *attribs);
void SourceAHBTargetExternal_helper(const EGLint *attribs);
void SourceAHBTargetExternalESSL3_helper(const EGLint *attribs);
void SourceNativeClientBufferTargetExternal_helper(const EGLint *attribs);
void SourceNativeClientBufferTargetRenderbuffer_helper(const EGLint *attribs);
void Source2DTarget2D_helper(const EGLint *attribs);
void Source2DTarget2DArray_helper(const EGLint *attribs);
void Source2DTargetRenderbuffer_helper(const EGLint *attribs);
......@@ -1759,6 +1847,96 @@ void ImageTest::Source2DTargetRenderbuffer_helper(const EGLint *attribs)
glDeleteRenderbuffers(1, &target);
}
// Testing source native client buffer EGL image, target external texture
// where source native client buffer is created using EGL_ANDROID_create_native_client_buffer API
TEST_P(ImageTest, SourceNativeClientBufferTargetExternal)
{
ANGLE_SKIP_TEST_IF(!IsAndroid());
SourceNativeClientBufferTargetExternal_helper(kDefaultAttribs);
}
// Testing source native client buffer EGL image with colorspace, target external texture
// where source native client buffer is created using EGL_ANDROID_create_native_client_buffer API
TEST_P(ImageTest, SourceNativeClientBufferTargetExternal_Colorspace)
{
ANGLE_SKIP_TEST_IF(!IsAndroid());
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
SourceNativeClientBufferTargetExternal_helper(kColorspaceAttribs);
}
void ImageTest::SourceNativeClientBufferTargetExternal_helper(const EGLint *attribs)
{
EGLWindow *window = getEGLWindow();
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
GLubyte data[] = {0, 125, 64, 250};
// Create an Image backed by a native client buffer allocated using
// EGL_ANDROID_create_native_client_buffer API
EGLImageKHR image;
createEGLImageANWBClientBufferSource(1, 1, 1, kNativeClientBufferAttribs_RGBA8_Texture, attribs,
data, 4, &image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target texture when sampled has the same color as the source image
verifyResultsExternal(target, data);
// Clean up
glDeleteTextures(1, &target);
eglDestroyImageKHR(window->getDisplay(), image);
}
// Testing source native client buffer EGL image, target Renderbuffer
// where source native client buffer is created using EGL_ANDROID_create_native_client_buffer API
TEST_P(ImageTest, SourceNativeClientBufferTargetRenderbuffer)
{
ANGLE_SKIP_TEST_IF(!IsAndroid());
SourceNativeClientBufferTargetRenderbuffer_helper(kDefaultAttribs);
}
// Testing source native client buffer EGL image with colorspace, target Renderbuffer
// where source native client buffer is created using EGL_ANDROID_create_native_client_buffer API
TEST_P(ImageTest, SourceNativeClientBufferTargetRenderbuffer_Colorspace)
{
ANGLE_SKIP_TEST_IF(!IsAndroid());
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
SourceNativeClientBufferTargetRenderbuffer_helper(kColorspaceAttribs);
}
void ImageTest::SourceNativeClientBufferTargetRenderbuffer_helper(const EGLint *attribs)
{
EGLWindow *window = getEGLWindow();
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
GLubyte data[] = {0, 125, 64, 250};
// Create an Image backed by a native client buffer allocated using
// EGL_ANDROID_create_native_client_buffer API
EGLImageKHR image;
createEGLImageANWBClientBufferSource(1, 1, 1, kNativeClientBufferAttribs_RGBA8_Renderbuffer,
attribs, data, 4, &image);
// Create the target
GLuint target;
createEGLImageTargetRenderbuffer(image, &target);
// Expect that the target renderbuffer has the same color as the source texture
verifyResultsRenderbuffer(target, data);
// Clean up
glDeleteRenderbuffers(1, &target);
eglDestroyImageKHR(window->getDisplay(), image);
}
TEST_P(ImageTest, Source2DTargetExternal)
{
Source2DTargetExternal_helper(kDefaultAttribs);
......
......@@ -55,6 +55,7 @@ ANGLE_TRACE_EXPORT PFNEGLCREATEPLATFORMWINDOWSURFACEPROC t_eglCreatePlatformWind
ANGLE_TRACE_EXPORT PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC t_eglCreatePlatformPixmapSurface;
ANGLE_TRACE_EXPORT PFNEGLWAITSYNCPROC t_eglWaitSync;
ANGLE_TRACE_EXPORT PFNEGLSETBLOBCACHEFUNCSANDROIDPROC t_eglSetBlobCacheFuncsANDROID;
ANGLE_TRACE_EXPORT PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC t_eglCreateNativeClientBufferANDROID;
ANGLE_TRACE_EXPORT PFNEGLGETCOMPOSITORTIMINGANDROIDPROC t_eglGetCompositorTimingANDROID;
ANGLE_TRACE_EXPORT PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROIDPROC
t_eglGetCompositorTimingSupportedANDROID;
......@@ -175,6 +176,9 @@ void LoadEGL(LoadProc loadProc)
t_eglWaitSync = reinterpret_cast<PFNEGLWAITSYNCPROC>(loadProc("eglWaitSync"));
t_eglSetBlobCacheFuncsANDROID = reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>(
loadProc("eglSetBlobCacheFuncsANDROID"));
t_eglCreateNativeClientBufferANDROID =
reinterpret_cast<PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC>(
loadProc("eglCreateNativeClientBufferANDROID"));
t_eglGetCompositorTimingANDROID = reinterpret_cast<PFNEGLGETCOMPOSITORTIMINGANDROIDPROC>(
loadProc("eglGetCompositorTimingANDROID"));
t_eglGetCompositorTimingSupportedANDROID =
......
......@@ -61,6 +61,7 @@
#define eglCreatePlatformPixmapSurface t_eglCreatePlatformPixmapSurface
#define eglWaitSync t_eglWaitSync
#define eglSetBlobCacheFuncsANDROID t_eglSetBlobCacheFuncsANDROID
#define eglCreateNativeClientBufferANDROID t_eglCreateNativeClientBufferANDROID
#define eglGetCompositorTimingANDROID t_eglGetCompositorTimingANDROID
#define eglGetCompositorTimingSupportedANDROID t_eglGetCompositorTimingSupportedANDROID
#define eglGetFrameTimestampSupportedANDROID t_eglGetFrameTimestampSupportedANDROID
......@@ -159,6 +160,8 @@ ANGLE_TRACE_EXPORT extern PFNEGLCREATEPLATFORMWINDOWSURFACEPROC t_eglCreatePlatf
ANGLE_TRACE_EXPORT extern PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC t_eglCreatePlatformPixmapSurface;
ANGLE_TRACE_EXPORT extern PFNEGLWAITSYNCPROC t_eglWaitSync;
ANGLE_TRACE_EXPORT extern PFNEGLSETBLOBCACHEFUNCSANDROIDPROC t_eglSetBlobCacheFuncsANDROID;
ANGLE_TRACE_EXPORT extern PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC
t_eglCreateNativeClientBufferANDROID;
ANGLE_TRACE_EXPORT extern PFNEGLGETCOMPOSITORTIMINGANDROIDPROC t_eglGetCompositorTimingANDROID;
ANGLE_TRACE_EXPORT extern PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROIDPROC
t_eglGetCompositorTimingSupportedANDROID;
......
......@@ -55,6 +55,7 @@ ANGLE_UTIL_EXPORT PFNEGLCREATEPLATFORMWINDOWSURFACEPROC l_eglCreatePlatformWindo
ANGLE_UTIL_EXPORT PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC l_eglCreatePlatformPixmapSurface;
ANGLE_UTIL_EXPORT PFNEGLWAITSYNCPROC l_eglWaitSync;
ANGLE_UTIL_EXPORT PFNEGLSETBLOBCACHEFUNCSANDROIDPROC l_eglSetBlobCacheFuncsANDROID;
ANGLE_UTIL_EXPORT PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC l_eglCreateNativeClientBufferANDROID;
ANGLE_UTIL_EXPORT PFNEGLGETCOMPOSITORTIMINGANDROIDPROC l_eglGetCompositorTimingANDROID;
ANGLE_UTIL_EXPORT PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROIDPROC
l_eglGetCompositorTimingSupportedANDROID;
......@@ -175,6 +176,9 @@ void LoadEGL(LoadProc loadProc)
l_eglWaitSync = reinterpret_cast<PFNEGLWAITSYNCPROC>(loadProc("eglWaitSync"));
l_eglSetBlobCacheFuncsANDROID = reinterpret_cast<PFNEGLSETBLOBCACHEFUNCSANDROIDPROC>(
loadProc("eglSetBlobCacheFuncsANDROID"));
l_eglCreateNativeClientBufferANDROID =
reinterpret_cast<PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC>(
loadProc("eglCreateNativeClientBufferANDROID"));
l_eglGetCompositorTimingANDROID = reinterpret_cast<PFNEGLGETCOMPOSITORTIMINGANDROIDPROC>(
loadProc("eglGetCompositorTimingANDROID"));
l_eglGetCompositorTimingSupportedANDROID =
......
......@@ -61,6 +61,7 @@
#define eglCreatePlatformPixmapSurface l_eglCreatePlatformPixmapSurface
#define eglWaitSync l_eglWaitSync
#define eglSetBlobCacheFuncsANDROID l_eglSetBlobCacheFuncsANDROID
#define eglCreateNativeClientBufferANDROID l_eglCreateNativeClientBufferANDROID
#define eglGetCompositorTimingANDROID l_eglGetCompositorTimingANDROID
#define eglGetCompositorTimingSupportedANDROID l_eglGetCompositorTimingSupportedANDROID
#define eglGetFrameTimestampSupportedANDROID l_eglGetFrameTimestampSupportedANDROID
......@@ -158,6 +159,8 @@ ANGLE_UTIL_EXPORT extern PFNEGLCREATEPLATFORMWINDOWSURFACEPROC l_eglCreatePlatfo
ANGLE_UTIL_EXPORT extern PFNEGLCREATEPLATFORMPIXMAPSURFACEPROC l_eglCreatePlatformPixmapSurface;
ANGLE_UTIL_EXPORT extern PFNEGLWAITSYNCPROC l_eglWaitSync;
ANGLE_UTIL_EXPORT extern PFNEGLSETBLOBCACHEFUNCSANDROIDPROC l_eglSetBlobCacheFuncsANDROID;
ANGLE_UTIL_EXPORT extern PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC
l_eglCreateNativeClientBufferANDROID;
ANGLE_UTIL_EXPORT extern PFNEGLGETCOMPOSITORTIMINGANDROIDPROC l_eglGetCompositorTimingANDROID;
ANGLE_UTIL_EXPORT extern PFNEGLGETCOMPOSITORTIMINGSUPPORTEDANDROIDPROC
l_eglGetCompositorTimingSupportedANDROID;
......
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