Skip to content

Commit dd2316d

Browse files
Mohan MaiyaCommit Bot
Mohan Maiya
authored and
Commit Bot
committed
EGL: Add image test for AHB based EGLImages
Add new end2end test where the source for EGL images is an Android Hardware Buffer Bug: angleproject:4810 Tests: angle_end2end_tests --gtest_filter=ImageTest.SourceAHBTarget* Change-Id: I20f303c6ad839ac2e65d407cfe3813a8be4c1cfa Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2231884 Commit-Queue: Mohan Maiya <[email protected]> Reviewed-by: Jamie Madill <[email protected]> Reviewed-by: Geoff Lang <[email protected]>
1 parent 05e2fe7 commit dd2316d

File tree

2 files changed

+309
-12
lines changed

2 files changed

+309
-12
lines changed

src/tests/BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ if (is_win || is_linux || is_mac || is_android || is_fuchsia) {
166166
"$angle_root:angle_image_util",
167167
]
168168

169+
if (is_android) {
170+
include_dirs += [ "${android_ndk_root}/sysroot/usr/includes" ]
171+
}
172+
169173
data_deps = [
170174
"$angle_root:libEGL",
171175
"$angle_root:libGLESv1_CM",

src/tests/gl_tests/ImageTest.cpp

Lines changed: 305 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,31 @@
1111
#include "test_utils/gl_raii.h"
1212
#include "util/EGLWindow.h"
1313

14+
#include "common/android_util.h"
15+
16+
#if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
17+
# define ANGLE_AHARDWARE_BUFFER_SUPPORT
18+
// NDK header file for access to Android Hardware Buffers
19+
# include <android/hardware_buffer.h>
20+
#endif
21+
1422
namespace angle
1523
{
1624
namespace
1725
{
18-
constexpr char kOESExt[] = "GL_OES_EGL_image";
19-
constexpr char kExternalExt[] = "GL_OES_EGL_image_external";
20-
constexpr char kExternalESSL3Ext[] = "GL_OES_EGL_image_external_essl3";
21-
constexpr char kBaseExt[] = "EGL_KHR_image_base";
22-
constexpr char k2DTextureExt[] = "EGL_KHR_gl_texture_2D_image";
23-
constexpr char k3DTextureExt[] = "EGL_KHR_gl_texture_3D_image";
24-
constexpr char kPixmapExt[] = "EGL_KHR_image_pixmap";
25-
constexpr char kRenderbufferExt[] = "EGL_KHR_gl_renderbuffer_image";
26-
constexpr char kCubemapExt[] = "EGL_KHR_gl_texture_cubemap_image";
27-
constexpr char kImageGLColorspaceExt[] = "EGL_EXT_image_gl_colorspace";
28-
constexpr char kEGLImageArrayExt[] = "GL_EXT_EGL_image_array";
29-
constexpr EGLint kDefaultAttribs[] = {
26+
constexpr char kOESExt[] = "GL_OES_EGL_image";
27+
constexpr char kExternalExt[] = "GL_OES_EGL_image_external";
28+
constexpr char kExternalESSL3Ext[] = "GL_OES_EGL_image_external_essl3";
29+
constexpr char kBaseExt[] = "EGL_KHR_image_base";
30+
constexpr char k2DTextureExt[] = "EGL_KHR_gl_texture_2D_image";
31+
constexpr char k3DTextureExt[] = "EGL_KHR_gl_texture_3D_image";
32+
constexpr char kPixmapExt[] = "EGL_KHR_image_pixmap";
33+
constexpr char kRenderbufferExt[] = "EGL_KHR_gl_renderbuffer_image";
34+
constexpr char kCubemapExt[] = "EGL_KHR_gl_texture_cubemap_image";
35+
constexpr char kImageGLColorspaceExt[] = "EGL_EXT_image_gl_colorspace";
36+
constexpr char kEGLImageArrayExt[] = "GL_EXT_EGL_image_array";
37+
constexpr char kEGLAndroidImageNativeBufferExt[] = "EGL_ANDROID_image_native_buffer";
38+
constexpr EGLint kDefaultAttribs[] = {
3039
EGL_IMAGE_PRESERVED,
3140
EGL_TRUE,
3241
EGL_NONE,
@@ -382,6 +391,91 @@ class ImageTest : public ANGLETest
382391
*outTargetTexture = target;
383392
}
384393

394+
AHardwareBuffer *createAndroidHardwareBuffer(size_t width,
395+
size_t height,
396+
size_t depth,
397+
int androidFormat,
398+
const GLubyte *data,
399+
size_t bytesPerPixel)
400+
{
401+
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
402+
// The height and width are number of pixels of size format
403+
AHardwareBuffer_Desc aHardwareBufferDescription = {};
404+
aHardwareBufferDescription.width = width;
405+
aHardwareBufferDescription.height = height;
406+
aHardwareBufferDescription.layers = depth;
407+
aHardwareBufferDescription.format = androidFormat;
408+
aHardwareBufferDescription.usage =
409+
AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
410+
aHardwareBufferDescription.stride = 0;
411+
aHardwareBufferDescription.rfu0 = 0;
412+
aHardwareBufferDescription.rfu1 = 0;
413+
414+
// Allocate memory from Android Hardware Buffer
415+
AHardwareBuffer *aHardwareBuffer = nullptr;
416+
EXPECT_EQ(0, AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer));
417+
418+
void *mappedMemory = nullptr;
419+
EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY,
420+
-1, nullptr, &mappedMemory));
421+
422+
// Need to grab the stride the implementation might have enforced
423+
AHardwareBuffer_describe(aHardwareBuffer, &aHardwareBufferDescription);
424+
const uint32_t stride = aHardwareBufferDescription.stride;
425+
426+
const uint32_t rowSize = bytesPerPixel * width;
427+
for (uint32_t i = 0; i < height; i++)
428+
{
429+
uint32_t dstPtrOffset = stride * i * bytesPerPixel;
430+
uint32_t srcPtrOffset = width * i * bytesPerPixel;
431+
432+
void *dst = reinterpret_cast<uint8_t *>(mappedMemory) + dstPtrOffset;
433+
memcpy(dst, data + srcPtrOffset, rowSize);
434+
}
435+
436+
EXPECT_EQ(0, AHardwareBuffer_unlock(aHardwareBuffer, nullptr));
437+
AHardwareBuffer_acquire(aHardwareBuffer);
438+
return aHardwareBuffer;
439+
#else
440+
return nullptr;
441+
#endif // ANGLE_PLATFORM_ANDROID
442+
}
443+
444+
void destroyAndroidHardwareBuffer(AHardwareBuffer *aHardwarebuffer)
445+
{
446+
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
447+
AHardwareBuffer_release(aHardwarebuffer);
448+
#endif
449+
}
450+
451+
void createEGLImageAndroidHardwareBufferSource(size_t width,
452+
size_t height,
453+
size_t depth,
454+
GLenum sizedInternalFormat,
455+
const EGLint *attribs,
456+
const GLubyte *data,
457+
size_t bytesPerPixel,
458+
AHardwareBuffer **outSourceAHB,
459+
EGLImageKHR *outSourceImage)
460+
{
461+
// Set Android Memory
462+
AHardwareBuffer *aHardwareBuffer = createAndroidHardwareBuffer(
463+
width, height, depth,
464+
angle::android::GLInternalFormatToNativePixelFormat(sizedInternalFormat), data,
465+
bytesPerPixel);
466+
EXPECT_NE(aHardwareBuffer, nullptr);
467+
468+
// Create an image from the source AHB
469+
EGLWindow *window = getEGLWindow();
470+
471+
EGLImageKHR image = eglCreateImageKHR(
472+
window->getDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
473+
angle::android::AHardwareBufferToClientBuffer(aHardwareBuffer), attribs);
474+
ASSERT_EGL_SUCCESS();
475+
476+
*outSourceAHB = aHardwareBuffer;
477+
*outSourceImage = image;
478+
}
385479
void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint *outTargetRenderbuffer)
386480
{
387481
// Create a target texture from the image
@@ -396,6 +490,10 @@ class ImageTest : public ANGLETest
396490
}
397491

398492
void ValidationGLEGLImage_helper(const EGLint *attribs);
493+
void SourceAHBTarget2D_helper(const EGLint *attribs);
494+
void SourceAHBTarget2DArray_helper(const EGLint *attribs);
495+
void SourceAHBTargetExternal_helper(const EGLint *attribs);
496+
void SourceAHBTargetExternalESSL3_helper(const EGLint *attribs);
399497
void Source2DTarget2D_helper(const EGLint *attribs);
400498
void Source2DTarget2DArray_helper(const EGLint *attribs);
401499
void Source2DTargetRenderbuffer_helper(const EGLint *attribs);
@@ -484,6 +582,21 @@ class ImageTest : public ANGLETest
484582
return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kImageGLColorspaceExt);
485583
}
486584

585+
bool hasAndroidImageNativeBufferExt() const
586+
{
587+
return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
588+
kEGLAndroidImageNativeBufferExt);
589+
}
590+
591+
bool hasAndroidHardwareBufferSupport() const
592+
{
593+
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
594+
return true;
595+
#else
596+
return false;
597+
#endif
598+
}
599+
487600
bool hasEglImageArrayExt() const { return IsGLExtensionEnabled(kEGLImageArrayExt); }
488601

489602
bool hasOESExt() const { return IsGLExtensionEnabled(kOESExt); }
@@ -1242,6 +1355,7 @@ TEST_P(ImageTest, Source2DTarget2DArray_Colorspace)
12421355
ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
12431356
Source2DTarget2DArray_helper(kColorspaceAttribs);
12441357
}
1358+
12451359
void ImageTest::Source2DTarget2DArray_helper(const EGLint *attribs)
12461360
{
12471361
ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
@@ -1269,6 +1383,185 @@ void ImageTest::Source2DTarget2DArray_helper(const EGLint *attribs)
12691383
glDeleteTextures(1, &target);
12701384
}
12711385

1386+
// Testing source AHB EGL image, target 2D texture
1387+
TEST_P(ImageTest, SourceAHBTarget2D)
1388+
{
1389+
ANGLE_SKIP_TEST_IF(!IsAndroid());
1390+
SourceAHBTarget2D_helper(kDefaultAttribs);
1391+
}
1392+
1393+
// Testing source AHB EGL image with colorspace, target 2D texture
1394+
TEST_P(ImageTest, SourceAHBTarget2D_Colorspace)
1395+
{
1396+
ANGLE_SKIP_TEST_IF(!IsAndroid());
1397+
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1398+
ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1399+
SourceAHBTarget2D_helper(kColorspaceAttribs);
1400+
}
1401+
1402+
void ImageTest::SourceAHBTarget2D_helper(const EGLint *attribs)
1403+
{
1404+
EGLWindow *window = getEGLWindow();
1405+
1406+
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
1407+
ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1408+
1409+
GLubyte data[4] = {7, 51, 197, 231};
1410+
1411+
// Create the Image
1412+
AHardwareBuffer *source;
1413+
EGLImageKHR image;
1414+
createEGLImageAndroidHardwareBufferSource(1, 1, 1, GL_RGBA8, attribs, data, 4, &source, &image);
1415+
1416+
// Create a texture target to bind the egl image
1417+
GLuint target;
1418+
createEGLImageTargetTexture2D(image, &target);
1419+
1420+
// Use texture target bound to egl image as source and render to framebuffer
1421+
// Verify that data in framebuffer matches that in the egl image
1422+
verifyResults2D(target, data);
1423+
1424+
// Clean up
1425+
eglDestroyImageKHR(window->getDisplay(), image);
1426+
destroyAndroidHardwareBuffer(source);
1427+
glDeleteTextures(1, &target);
1428+
}
1429+
1430+
// Testing source AHB EGL image, target 2D array texture
1431+
TEST_P(ImageTest, SourceAHBTarget2DArray)
1432+
{
1433+
ANGLE_SKIP_TEST_IF(!IsAndroid());
1434+
SourceAHBTarget2DArray_helper(kDefaultAttribs);
1435+
}
1436+
1437+
// Testing source AHB EGL image with colorspace, target 2D array texture
1438+
TEST_P(ImageTest, SourceAHBTarget2DArray_Colorspace)
1439+
{
1440+
ANGLE_SKIP_TEST_IF(!IsAndroid());
1441+
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1442+
ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1443+
SourceAHBTarget2DArray_helper(kColorspaceAttribs);
1444+
}
1445+
1446+
void ImageTest::SourceAHBTarget2DArray_helper(const EGLint *attribs)
1447+
{
1448+
EGLWindow *window = getEGLWindow();
1449+
1450+
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
1451+
!hasEglImageArrayExt());
1452+
ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1453+
1454+
GLubyte data[4] = {7, 51, 197, 231};
1455+
1456+
// Create the Image
1457+
AHardwareBuffer *source;
1458+
EGLImageKHR image;
1459+
createEGLImageAndroidHardwareBufferSource(1, 1, 1, GL_RGBA8, attribs, data, 4, &source, &image);
1460+
1461+
// Create a texture target to bind the egl image
1462+
GLuint target;
1463+
createEGLImageTargetTexture2DArray(image, &target);
1464+
1465+
// Use texture target bound to egl image as source and render to framebuffer
1466+
// Verify that data in framebuffer matches that in the egl image
1467+
verifyResults2DArray(target, data);
1468+
1469+
// Clean up
1470+
eglDestroyImageKHR(window->getDisplay(), image);
1471+
destroyAndroidHardwareBuffer(source);
1472+
glDeleteTextures(1, &target);
1473+
}
1474+
1475+
// Testing source AHB EGL image, target external texture
1476+
TEST_P(ImageTest, SourceAHBTargetExternal)
1477+
{
1478+
ANGLE_SKIP_TEST_IF(!IsAndroid());
1479+
SourceAHBTargetExternal_helper(kDefaultAttribs);
1480+
}
1481+
1482+
// Testing source AHB EGL image with colorspace, target external texture
1483+
TEST_P(ImageTest, SourceAHBTargetExternal_Colorspace)
1484+
{
1485+
ANGLE_SKIP_TEST_IF(!IsAndroid());
1486+
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1487+
ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1488+
SourceAHBTargetExternal_helper(kColorspaceAttribs);
1489+
}
1490+
1491+
void ImageTest::SourceAHBTargetExternal_helper(const EGLint *attribs)
1492+
{
1493+
EGLWindow *window = getEGLWindow();
1494+
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasExternalExt());
1495+
ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1496+
1497+
// Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
1498+
ANGLE_SKIP_TEST_IF(IsOzone());
1499+
1500+
GLubyte data[4] = {7, 51, 197, 231};
1501+
1502+
// Create the Image
1503+
AHardwareBuffer *source;
1504+
EGLImageKHR image;
1505+
createEGLImageAndroidHardwareBufferSource(1, 1, 1, GL_RGBA8, attribs, data, 4, &source, &image);
1506+
1507+
// Create a texture target to bind the egl image
1508+
GLuint target;
1509+
createEGLImageTargetTextureExternal(image, &target);
1510+
1511+
// Use texture target bound to egl image as source and render to framebuffer
1512+
// Verify that data in framebuffer matches that in the egl image
1513+
verifyResultsExternal(target, data);
1514+
1515+
// Clean up
1516+
eglDestroyImageKHR(window->getDisplay(), image);
1517+
destroyAndroidHardwareBuffer(source);
1518+
glDeleteTextures(1, &target);
1519+
}
1520+
1521+
// Testing source AHB EGL image, target external ESSL3 texture
1522+
TEST_P(ImageTestES3, SourceAHBTargetExternalESSL3)
1523+
{
1524+
ANGLE_SKIP_TEST_IF(!IsAndroid());
1525+
SourceAHBTargetExternalESSL3_helper(kDefaultAttribs);
1526+
}
1527+
1528+
// Testing source AHB EGL image with colorspace, target external ESSL3 texture
1529+
TEST_P(ImageTestES3, SourceAHBTargetExternalESSL3_Colorspace)
1530+
{
1531+
ANGLE_SKIP_TEST_IF(!IsAndroid());
1532+
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1533+
ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1534+
SourceAHBTargetExternalESSL3_helper(kColorspaceAttribs);
1535+
}
1536+
1537+
void ImageTest::SourceAHBTargetExternalESSL3_helper(const EGLint *attribs)
1538+
{
1539+
EGLWindow *window = getEGLWindow();
1540+
ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
1541+
!hasExternalESSL3Ext());
1542+
ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1543+
1544+
GLubyte data[4] = {7, 51, 197, 231};
1545+
1546+
// Create the Image
1547+
AHardwareBuffer *source;
1548+
EGLImageKHR image;
1549+
createEGLImageAndroidHardwareBufferSource(1, 1, 1, GL_RGBA8, attribs, data, 4, &source, &image);
1550+
1551+
// Create a texture target to bind the egl image
1552+
GLuint target;
1553+
createEGLImageTargetTextureExternal(image, &target);
1554+
1555+
// Use texture target bound to egl image as source and render to framebuffer
1556+
// Verify that data in framebuffer matches that in the egl image
1557+
verifyResultsExternalESSL3(target, data);
1558+
1559+
// Clean up
1560+
eglDestroyImageKHR(window->getDisplay(), image);
1561+
destroyAndroidHardwareBuffer(source);
1562+
glDeleteTextures(1, &target);
1563+
}
1564+
12721565
TEST_P(ImageTest, Source2DTargetRenderbuffer)
12731566
{
12741567
Source2DTargetRenderbuffer_helper(kDefaultAttribs);

0 commit comments

Comments
 (0)