blob: 9137461b8a788a66fcba8b13790f090186eadfc1 [file] [log] [blame]
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// EGLProtectedContentTest.cpp:
// EGL extension EGL_EXT_protected_content
//
#include <gtest/gtest.h>
#include <chrono>
#include <iostream>
#include <thread>
#include "test_utils/ANGLETest.h"
#include "util/EGLWindow.h"
#include "util/OSWindow.h"
using namespace std::chrono_literals;
using namespace angle;
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLProtectedContentTest);
class EGLProtectedContentTest : public ANGLETest
{
public:
EGLProtectedContentTest() : mDisplay(EGL_NO_DISPLAY) {}
void testSetUp() override
{
EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
mDisplay = eglGetPlatformDisplayEXT(
EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY);
EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));
mMajorVersion = GetParam().majorVersion;
}
void testTearDown() override
{
if (mDisplay != EGL_NO_DISPLAY)
{
eglTerminate(mDisplay);
eglReleaseThread();
mDisplay = EGL_NO_DISPLAY;
}
ASSERT_EGL_SUCCESS() << "Error during test TearDown";
}
bool chooseConfig(EGLConfig *config)
{
EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
EGLint attribs[] = {EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_RENDERABLE_TYPE,
clientVersion,
EGL_SURFACE_TYPE,
(EGL_PBUFFER_BIT | EGL_WINDOW_BIT),
EGL_BIND_TO_TEXTURE_RGBA,
EGL_TRUE,
EGL_NONE};
EGLint count = 0;
bool result = eglChooseConfig(mDisplay, attribs, config, 1, &count);
EXPECT_EGL_TRUE(result);
EXPECT_EGL_TRUE(count > 0);
return result;
}
bool createContext(EGLBoolean isProtected, EGLConfig config, EGLContext *context)
{
bool result = false;
EGLint attribsProtected[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion,
EGL_PROTECTED_CONTENT_EXT, EGL_TRUE, EGL_NONE};
EGLint attribsUnProtected[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE};
*context = eglCreateContext(mDisplay, config, nullptr,
(isProtected ? attribsProtected : attribsUnProtected));
result = (*context != EGL_NO_CONTEXT);
EXPECT_TRUE(result);
return result;
}
bool createPbufferSurface(EGLBoolean isProtected, EGLConfig config, EGLSurface *surface)
{
bool result = false;
EGLint attribsProtected[] = {EGL_WIDTH,
kWidth,
EGL_HEIGHT,
kHeight,
EGL_TEXTURE_FORMAT,
EGL_TEXTURE_RGBA,
EGL_TEXTURE_TARGET,
EGL_TEXTURE_2D,
EGL_PROTECTED_CONTENT_EXT,
EGL_TRUE,
EGL_NONE};
EGLint attribsUnProtected[] = {EGL_WIDTH,
kWidth,
EGL_HEIGHT,
kHeight,
EGL_TEXTURE_FORMAT,
EGL_TEXTURE_RGBA,
EGL_TEXTURE_TARGET,
EGL_TEXTURE_2D,
EGL_NONE};
*surface = eglCreatePbufferSurface(mDisplay, config,
(isProtected ? attribsProtected : attribsUnProtected));
result = (*surface != EGL_NO_SURFACE);
EXPECT_TRUE(result);
return result;
}
bool createWindowSurface(EGLBoolean isProtected,
EGLConfig config,
EGLNativeWindowType win,
EGLSurface *surface)
{
bool result = false;
EGLint attribsProtected[] = {EGL_PROTECTED_CONTENT_EXT, EGL_TRUE, EGL_NONE};
EGLint attribsUnProtected[] = {EGL_NONE};
*surface = eglCreateWindowSurface(mDisplay, config, win,
(isProtected ? attribsProtected : attribsUnProtected));
result = (*surface != EGL_NO_SURFACE);
EXPECT_TRUE(result);
return result;
}
bool createImage(EGLBoolean isProtected,
EGLContext context,
EGLenum target,
EGLClientBuffer buffer,
EGLImage *image)
{
bool result = false;
EGLAttrib attribsProtected[] = {EGL_PROTECTED_CONTENT_EXT, EGL_TRUE, EGL_NONE};
*image = eglCreateImage(mDisplay, context, target, buffer,
(isProtected ? attribsProtected : nullptr));
EXPECT_EGL_SUCCESS();
result = (*image != EGL_NO_SURFACE);
EXPECT_TRUE(result);
return result;
}
bool createTexture(EGLBoolean isProtected, GLuint *textureId)
{
bool result = false;
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
EXPECT_GL_NO_ERROR();
if (isProtected)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_PROTECTED_EXT, GL_TRUE);
// GL_INVALID_OPERATION expected when context is not protected too.
GLenum error = glGetError();
if (error == GL_INVALID_OPERATION)
{
return false;
}
}
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
EXPECT_GL_NO_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
result = (texture != 0);
EXPECT_TRUE(result);
*textureId = texture;
return result;
}
bool createTextureFromImage(EGLImage image, GLuint *textureId)
{
bool result = false;
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
EXPECT_GL_NO_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
result = (texture != 0);
EXPECT_TRUE(result);
*textureId = texture;
return result;
}
bool createTextureFromPbuffer(EGLSurface pBuffer, GLuint *textureId)
{
bool result = false;
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
EXPECT_GL_NO_ERROR();
EXPECT_TRUE(texture != 0);
result = eglBindTexImage(mDisplay, pBuffer, EGL_BACK_BUFFER);
glViewport(0, 0, kWidth, kHeight);
*textureId = texture;
return result;
}
bool fillTexture(GLuint textureId, GLColor color)
{
GLuint pixels[kWidth * kHeight];
for (uint32_t i = 0; i < (kWidth * kHeight); i++)
{
pixels[i] = *(GLuint *)(color.data());
}
glBindTexture(GL_TEXTURE_2D, textureId);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
(void *)pixels);
EXPECT_GL_NO_ERROR();
return true;
}
bool renderTexture(GLuint textureId)
{
const char *kVertexShader = R"(
precision highp float;
attribute vec4 position;
varying vec2 texcoord;
void main()
{
gl_Position = vec4(position.xy, 0.0, 1.0);
texcoord = (position.xy * 0.5) + 0.5;
}
)";
const char *kFragmentShader = R"(
precision highp float;
uniform sampler2D tex;
varying vec2 texcoord;
void main()
{
gl_FragColor = texture2D(tex, texcoord);
}
)";
GLuint program = CompileProgram(kVertexShader, kFragmentShader);
glUseProgram(program);
glBindTexture(GL_TEXTURE_2D, textureId);
glActiveTexture(GL_TEXTURE0);
GLint texture2DUniformLocation = glGetUniformLocation(program, "tex");
glUniform1i(texture2DUniformLocation, 0);
drawQuad(program, "position", 0.5f);
glDeleteProgram(program);
EXPECT_GL_NO_ERROR();
return true;
}
bool createRenderbuffer(GLuint *renderbuffer)
{
bool result = false;
*renderbuffer = 0;
glGenRenderbuffers(1, renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, *renderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, kWidth, kHeight);
EXPECT_GL_NO_ERROR();
result = (*renderbuffer != 0);
EXPECT_TRUE(result);
return result;
}
bool createRenderbufferFromImage(EGLImage image, GLuint *renderbuffer)
{
bool result = false;
*renderbuffer = 0;
glGenRenderbuffers(1, renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, *renderbuffer);
glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
EXPECT_GL_NO_ERROR();
result = (*renderbuffer != 0);
EXPECT_TRUE(result);
return result;
}
bool createAndroidClientBuffer(bool useProtected,
bool useRenderbuffer,
bool useTexture,
EGLClientBuffer *clientBuffer)
{
bool result = false;
EGLint nativeBufferUsage =
0 | (useProtected ? EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID : 0) |
(useRenderbuffer ? EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID : 0) |
(useTexture ? EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID : 0);
EGLint attribs[] = {EGL_WIDTH,
kWidth,
EGL_HEIGHT,
kHeight,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_NATIVE_BUFFER_USAGE_ANDROID,
nativeBufferUsage,
EGL_NONE};
*clientBuffer = eglCreateNativeClientBufferANDROID(attribs);
EXPECT_EGL_SUCCESS();
result = (*clientBuffer != nullptr);
EXPECT_TRUE(result);
return result;
}
void pbufferTest(bool isProtectedContext, bool isProtectedSurface);
void windowTest(bool isProtectedContext, bool isProtectedSurface);
void textureTest(bool isProtectedContext, bool isProtectedTexture);
void textureFromImageTest(bool isProtectedContext, bool isProtectedTexture);
void textureFromPbufferTest(bool isProtectedContext, bool isProtectedTexture);
void textureFromAndroidNativeBufferTest(bool isProtectedContext, bool isProtectedTexture);
void checkSwapBuffersResult(const std::string color,
bool isProtectedContext,
bool isProtectedSurface)
{
std::this_thread::sleep_for(1s);
if (isProtectedContext)
{
if (isProtectedSurface)
{
std::cout << "Operator should see color: " << color << std::endl;
}
else
{
std::cout << "Operator should see color: BLACK" << std::endl;
}
}
else
{
if (isProtectedSurface)
{
std::cout << "Operator should see color: BLACK" << std::endl;
}
else
{
std::cout << "Operator should see color: " << color << std::endl;
}
}
}
EGLDisplay mDisplay = EGL_NO_DISPLAY;
EGLint mMajorVersion = 0;
static const EGLint kWidth = 16;
static const EGLint kHeight = 16;
};
void EGLProtectedContentTest::pbufferTest(bool isProtectedContext, bool isProtectedSurface)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR);
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(isProtectedContext, config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface pBufferSurface = EGL_NO_SURFACE;
EXPECT_TRUE(createPbufferSurface(isProtectedSurface, config, &pBufferSurface));
ASSERT_EGL_SUCCESS() << "eglCreatePbufferSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, pBufferSurface, pBufferSurface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glFinish();
ASSERT_GL_NO_ERROR() << "glFinish failed";
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, pBufferSurface);
pBufferSurface = EGL_NO_SURFACE;
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Unprotected context with Unprotected PbufferSurface
TEST_P(EGLProtectedContentTest, UnprotectedContextWithUnprotectedPbufferSurface)
{
pbufferTest(false, false);
}
void EGLProtectedContentTest::windowTest(bool isProtectedContext, bool isProtectedSurface)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR);
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(isProtectedContext, config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("ProtectedContentTest", kWidth, kHeight);
EGLSurface windowSurface = EGL_NO_SURFACE;
EGLBoolean createWinSurfaceResult = createWindowSurface(
isProtectedSurface, config, osWindow->getNativeWindow(), &windowSurface);
EXPECT_TRUE(createWinSurfaceResult);
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
// Red
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
checkSwapBuffersResult("RED", isProtectedContext, isProtectedSurface);
// Green
glClearColor(0.0, 1.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
checkSwapBuffersResult("GREEN", isProtectedContext, isProtectedSurface);
// Blue
glClearColor(0.0, 0.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
checkSwapBuffersResult("BLUE", isProtectedContext, isProtectedSurface);
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, windowSurface);
windowSurface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Unprotected context with Unprotected WindowSurface
TEST_P(EGLProtectedContentTest, UnprotectedContextWithUnprotectedWindowSurface)
{
windowTest(false, false);
}
// Protected context with Protected WindowSurface
TEST_P(EGLProtectedContentTest, ProtectedContextWithProtectedWindowSurface)
{
windowTest(true, true);
}
void EGLProtectedContentTest::textureTest(bool isProtectedContext, bool isProtectedTexture)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
bool isProtectedSurface = isProtectedTexture;
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR);
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(isProtectedContext, config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("ProtectedContentTest", kWidth, kHeight);
EGLSurface windowSurface = EGL_NO_SURFACE;
EGLBoolean createWinSurfaceResult = createWindowSurface(
isProtectedSurface, config, osWindow->getNativeWindow(), &windowSurface);
EXPECT_TRUE(createWinSurfaceResult);
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
glViewport(0, 0, kWidth, kHeight);
EXPECT_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
if (IsGLExtensionEnabled("GL_EXT_protected_textures"))
{
GLuint texture = 0;
bool result = createTexture(isProtectedTexture, &texture);
if (isProtectedTexture && !isProtectedContext)
{
std::cout << "Can't create protected Texture for Unprotected Context" << std::endl;
ASSERT_FALSE(result);
}
else
{
ASSERT_TRUE(result);
EXPECT_TRUE(fillTexture(texture, GLColor::red));
EXPECT_TRUE(renderTexture(texture));
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
checkSwapBuffersResult("RED", isProtectedContext, isProtectedSurface);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &texture);
}
}
else
{
std::cout << "Skipping tests, GL_EXT_protected_textures not supported" << std::endl;
}
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, windowSurface);
windowSurface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Unprotected context with unprotected texture
TEST_P(EGLProtectedContentTest, UnprotectedContextWithUnprotectedTexture)
{
textureTest(false, false);
}
// Protected context with protected texture
TEST_P(EGLProtectedContentTest, ProtectedContextWithProtectedTexture)
{
textureTest(true, true);
}
void EGLProtectedContentTest::textureFromImageTest(bool isProtectedContext, bool isProtectedTexture)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
bool isProtectedSurface = isProtectedTexture;
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR);
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(isProtectedContext, config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("ProtectedContentTest", kWidth, kHeight);
EGLSurface windowSurface = EGL_NO_SURFACE;
EGLBoolean createWinSurfaceResult = createWindowSurface(
isProtectedSurface, config, osWindow->getNativeWindow(), &windowSurface);
EXPECT_TRUE(createWinSurfaceResult);
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
glViewport(0, 0, kWidth, kHeight);
if (IsGLExtensionEnabled("GL_OES_EGL_image") &&
IsGLExtensionEnabled("GL_EXT_protected_textures"))
{
GLuint srcTexture = 0;
if (isProtectedTexture && !isProtectedContext)
{
std::cout << "Can't create protected Texture for Unprotected Context, Skipping"
<< std::endl;
ASSERT_FALSE(createTexture(isProtectedTexture, &srcTexture));
}
else
{
ASSERT_TRUE(createTexture(isProtectedTexture, &srcTexture));
EXPECT_TRUE(fillTexture(srcTexture, GLColor::red));
EGLImage image = EGL_NO_IMAGE;
EXPECT_TRUE(createImage(isProtectedTexture, context, EGL_GL_TEXTURE_2D,
(void *)(static_cast<intptr_t>(srcTexture)), &image));
GLuint dstTexture = 0;
EXPECT_TRUE(createTextureFromImage(image, &dstTexture));
EXPECT_TRUE(renderTexture(dstTexture));
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
checkSwapBuffersResult("RED", isProtectedContext, isProtectedSurface);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &dstTexture);
glDeleteTextures(1, &srcTexture);
eglDestroyImage(mDisplay, image);
image = EGL_NO_IMAGE;
}
}
else
{
std::cout << "Skipping tests, GL_OES_EGL_image or GL_EXT_protected_textures not supported"
<< std::endl;
}
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, windowSurface);
windowSurface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Unprotected context with unprotected texture from EGL image
TEST_P(EGLProtectedContentTest, UnprotectedContextWithUnprotectedTextureFromImage)
{
textureFromImageTest(false, false);
}
// Protected context with protected texture from EGL image
TEST_P(EGLProtectedContentTest, ProtectedContextWithProtectedTextureFromImage)
{
textureFromImageTest(true, true);
}
void EGLProtectedContentTest::textureFromPbufferTest(bool isProtectedContext,
bool isProtectedTexture)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
bool isProtectedSurface = isProtectedTexture;
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR);
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(isProtectedContext, config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface pBufferSurface = EGL_NO_SURFACE;
EXPECT_TRUE(createPbufferSurface(isProtectedSurface, config, &pBufferSurface));
ASSERT_EGL_SUCCESS() << "eglCreatePbufferSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, pBufferSurface, pBufferSurface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
glViewport(0, 0, kWidth, kHeight);
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glFinish();
ASSERT_GL_NO_ERROR() << "glFinish failed";
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("ProtectedContentTest", kWidth, kHeight);
EGLSurface windowSurface = EGL_NO_SURFACE;
EGLBoolean createWinSurfaceResult = createWindowSurface(
isProtectedSurface, config, osWindow->getNativeWindow(), &windowSurface);
EXPECT_TRUE(createWinSurfaceResult);
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
glViewport(0, 0, kWidth, kHeight);
if (IsGLExtensionEnabled("GL_EXT_protected_textures"))
{
GLuint texture = 0;
EXPECT_TRUE(createTextureFromPbuffer(pBufferSurface, &texture));
EXPECT_TRUE(renderTexture(texture));
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
checkSwapBuffersResult("RED", isProtectedContext, isProtectedTexture);
eglReleaseTexImage(mDisplay, pBufferSurface, EGL_BACK_BUFFER);
glDeleteTextures(1, &texture);
}
else
{
std::cout << "Skipping tests, GL_EXT_protected_textures not supported" << std::endl;
}
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, windowSurface);
windowSurface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroySurface(mDisplay, pBufferSurface);
pBufferSurface = EGL_NO_SURFACE;
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Unprotected context with unprotected texture from BindTex of PBufferSurface
TEST_P(EGLProtectedContentTest, UnprotectedContextWithUnprotectedTextureFromPBuffer)
{
textureFromPbufferTest(false, false);
}
// Protected context with protected texture from BindTex of PBufferSurface
TEST_P(EGLProtectedContentTest, ProtectedContextWithProtectedTextureFromPbuffer)
{
textureFromPbufferTest(true, true);
}
void EGLProtectedContentTest::textureFromAndroidNativeBufferTest(bool isProtectedContext,
bool isProtectedTexture)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
ANGLE_SKIP_TEST_IF(
!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_get_native_client_buffer"));
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANDROID_image_native_buffer"));
bool isProtectedSurface = isProtectedTexture;
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
ANGLE_SKIP_TEST_IF(config == EGL_NO_CONFIG_KHR);
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(isProtectedContext, config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("ProtectedContentTest", kWidth, kHeight);
EGLSurface windowSurface = EGL_NO_SURFACE;
EGLBoolean createWinSurfaceResult = createWindowSurface(
isProtectedSurface, config, osWindow->getNativeWindow(), &windowSurface);
EXPECT_TRUE(createWinSurfaceResult);
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, windowSurface, windowSurface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
glViewport(0, 0, kWidth, kHeight);
if (IsGLExtensionEnabled("GL_EXT_protected_textures"))
{
EGLClientBuffer clientBuffer = nullptr;
EXPECT_TRUE(createAndroidClientBuffer(isProtectedTexture, false, true, &clientBuffer));
EGLImage image = EGL_NO_IMAGE;
EXPECT_TRUE(createImage(isProtectedTexture, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
clientBuffer, &image));
GLuint texture = 0;
if (isProtectedTexture && !isProtectedContext)
{
std::cout << "Can't create protected Texture for Unprotected Context, Skipping"
<< std::endl;
ASSERT_FALSE(createTextureFromImage(image, &texture));
}
else
{
EXPECT_TRUE(createTextureFromImage(image, &texture));
EXPECT_TRUE(fillTexture(texture, GLColor::red));
EXPECT_TRUE(renderTexture(texture));
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
checkSwapBuffersResult("RED", isProtectedContext, isProtectedTexture);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &texture);
eglDestroyImage(mDisplay, image);
image = EGL_NO_IMAGE;
}
}
else
{
std::cout << "Skipping tests, GL_EXT_protected_textures not supported" << std::endl;
}
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, windowSurface);
windowSurface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Unprotected context with unprotected texture from EGL image from Android native buffer
TEST_P(EGLProtectedContentTest, UnprotectedContextWithUnprotectedTextureFromAndroidNativeBuffer)
{
textureFromAndroidNativeBufferTest(false, false);
}
// Protected context with protected texture from EGL image from Android native buffer
TEST_P(EGLProtectedContentTest, ProtectedContextWithProtectedTextureFromAndroidNativeBuffer)
{
textureFromAndroidNativeBufferTest(true, true);
}
ANGLE_INSTANTIATE_TEST(EGLProtectedContentTest,
WithNoFixture(ES2_VULKAN()),
WithNoFixture(ES3_VULKAN()));