Branch :
//
// 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_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_PROTECTED_CONTENT_EXT, EGL_TRUE, EGL_NONE};
EGLint attribsUnProtected[] = {EGL_WIDTH, kWidth, EGL_HEIGHT, kHeight, 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;
}
void PbufferTest(bool isProtectedContext, bool isProtectedSurface);
void WindowTest(bool isProtectedContext, bool isProtectedSurface);
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)
{
if (isProtectedContext || isProtectedSurface)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
}
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
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_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)
{
if (isProtectedContext || isProtectedSurface)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
}
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
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.";
std::this_thread::sleep_for(1s);
// 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.";
std::this_thread::sleep_for(1s);
// 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.";
std::this_thread::sleep_for(1s);
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)
{
std::cout << "Operator should see RED, GREEN, BLUE on screen" << std::endl;
WindowTest(false, false);
}
// Protected context with Protected WindowSurface
TEST_P(EGLProtectedContentTest, ProtectedContextWithProtectedWindowSurface)
{
std::cout << "Operator should see RED, GREEN, BLUE on screen" << std::endl;
WindowTest(true, true);
}
ANGLE_INSTANTIATE_TEST(EGLProtectedContentTest,
WithNoFixture(ES2_VULKAN()),
WithNoFixture(ES3_VULKAN()));