EGL: GLES: Implement GL_EXT_protected_textures

Implement EGL_EXT_protected_content Images
Add protected member to Images and Textures
Add error when creating objects if not supported or
does't match native buffer
When creating siblings pass protected state
Add extension caps
Add Validation
Add GetTexParameter and SetTextparameter
Add protected to Texture and state
Expand tests for images and textures

Test: angle_end2end_test --gtest_filter=EGLProtectedContentTest

Bug: angleproject:3965
Change-Id: I35a89b4e80bba6d9b6831c68e71630eef304dacb
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2802852
Commit-Queue: Mohan Maiya <m.maiya@samsung.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Jeff Vigil 2021-03-25 15:43:06 -07:00 коммит произвёл Angle LUCI CQ
Родитель d2b659f9a1
Коммит 6210a9b34a
55 изменённых файлов: 984 добавлений и 98 удалений

Просмотреть файл

@ -12,7 +12,7 @@
"scripts/gl_angle_ext.xml":
"08f74b35d908b7c02b45fdf45572c434",
"scripts/registry_xml.py":
"3fc0ede1891f7de9338993dea77df9e8",
"44a6f8c6713b39de5427da86b6c64595",
"scripts/wgl.xml":
"c36001431919e1c435f1215a85f7e1db",
"src/libEGL/egl_loader_autogen.cpp":

Просмотреть файл

@ -16,7 +16,7 @@
"scripts/gl_angle_ext.xml":
"08f74b35d908b7c02b45fdf45572c434",
"scripts/registry_xml.py":
"3fc0ede1891f7de9338993dea77df9e8",
"44a6f8c6713b39de5427da86b6c64595",
"scripts/wgl.xml":
"c36001431919e1c435f1215a85f7e1db",
"src/common/entry_points_enum_autogen.cpp":
@ -42,7 +42,7 @@
"src/libANGLE/Context_gles_3_2_autogen.h":
"48567dca16fd881dfe6d61fee0e3106f",
"src/libANGLE/Context_gles_ext_autogen.h":
"dbf7c9716e46e29b44db01f215f0808a",
"1e78e832b23a36d8b0eb290ebfd95812",
"src/libANGLE/capture/capture_gles_1_0_autogen.cpp":
"7ec7ef8f779b809a45d74b97502c419b",
"src/libANGLE/capture/capture_gles_1_0_autogen.h":
@ -66,7 +66,7 @@
"src/libANGLE/capture/capture_gles_ext_autogen.cpp":
"b027d574c21f369aee0fb0117f453935",
"src/libANGLE/capture/capture_gles_ext_autogen.h":
"46440404fc9219fbe709e564f26d57a6",
"42d26ead58cf52c8bbf2701589bc68aa",
"src/libANGLE/capture/frame_capture_replay_autogen.cpp":
"e0a3c284b986e2a712589b6f3523d79c",
"src/libANGLE/capture/frame_capture_utils_autogen.cpp":
@ -88,7 +88,7 @@
"src/libANGLE/validationES3_autogen.h":
"7435b9caddf8787b937c71a54dda96e1",
"src/libANGLE/validationESEXT_autogen.h":
"498a3fcf388dd8edbe38b25aaa1621cc",
"b2d36e26a63cd92fbb26d289f1aecb9b",
"src/libANGLE/validationGL1_autogen.h":
"439f8ea26dc37ee6608100f4c6f9205c",
"src/libANGLE/validationGL2_autogen.h":
@ -162,17 +162,17 @@
"src/libGLESv2/entry_points_gles_3_2_autogen.h":
"647f932a299cdb4726b60bbba059f0d2",
"src/libGLESv2/entry_points_gles_ext_autogen.cpp":
"dda68d8198adeb87c19f5fce8691a0b9",
"df737a111291710513eda6f38d391b26",
"src/libGLESv2/entry_points_gles_ext_autogen.h":
"95374bec6b53708d019455309ea887ec",
"5be077957c8cf2dbf10be897d56ef4ed",
"src/libGLESv2/libGLESv2_autogen.cpp":
"3805edff53f627f34ce6f55f064e473c",
"e6fd37cfcb725f9d3a25cc9c55a1ea40",
"src/libGLESv2/libGLESv2_autogen.def":
"b49ee14e4c440282d86e5ab4acbaaff5",
"7f8231e286656964204c1f303e91dfc9",
"src/libGLESv2/libGLESv2_no_capture_autogen.def":
"2303964798f342d2858dc44ba9f02a2e",
"e243621778233766d10df30029d4e2c7",
"src/libGLESv2/libGLESv2_with_capture_autogen.def":
"b74c9e193df59dc0f06ff45308f8fb51",
"cce23e17f23ef38ee99869b6bc3d8729",
"src/libOpenCL/libOpenCL_autogen.cpp":
"10849978c910dc1af5dd4f0c815d1581"
}

Просмотреть файл

@ -6,9 +6,9 @@
"scripts/gl_angle_ext.xml":
"08f74b35d908b7c02b45fdf45572c434",
"scripts/registry_xml.py":
"3fc0ede1891f7de9338993dea77df9e8",
"44a6f8c6713b39de5427da86b6c64595",
"src/libANGLE/capture/gl_enum_utils_autogen.cpp":
"335140f98374899f9e1303b23b4eddc1",
"9f432722dc11c315b6920d311d8df70e",
"src/libANGLE/capture/gl_enum_utils_autogen.h":
"fb0bb7f506f6082ea3b2c3fa384d2739"
}

Просмотреть файл

@ -12,7 +12,7 @@
"scripts/gl_angle_ext.xml":
"08f74b35d908b7c02b45fdf45572c434",
"scripts/registry_xml.py":
"3fc0ede1891f7de9338993dea77df9e8",
"44a6f8c6713b39de5427da86b6c64595",
"scripts/wgl.xml":
"c36001431919e1c435f1215a85f7e1db",
"src/libGL/proc_table_wgl_autogen.cpp":

Просмотреть файл

@ -90,6 +90,7 @@ gles_extensions = [
"GL_EXT_multisampled_render_to_texture2",
"GL_EXT_occlusion_query_boolean",
"GL_EXT_primitive_bounding_box",
"GL_EXT_protected_textures",
"GL_EXT_read_format_bgra",
"GL_EXT_robustness",
"GL_EXT_semaphore",

Просмотреть файл

@ -334,13 +334,15 @@ void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer,
int *width,
int *height,
int *depth,
int *pixelFormat)
int *pixelFormat,
uint64_t *usage)
{
*width = buffer->width;
*height = buffer->height;
*depth = static_cast<int>(buffer->layerCount);
*height = buffer->height;
*pixelFormat = buffer->format;
*usage = buffer->usage;
}
GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)

Просмотреть файл

@ -42,7 +42,8 @@ void GetANativeWindowBufferProperties(const ANativeWindowBuffer *buffer,
int *width,
int *height,
int *depth,
int *pixelFormat);
int *pixelFormat,
uint64_t *usage);
GLenum NativePixelFormatToGLInternalFormat(int pixelFormat);
int GLInternalFormatToNativePixelFormat(GLenum internalFormat);

Просмотреть файл

@ -1097,6 +1097,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_EXT_primitive_bounding_box"] = esOnlyExtension(&Extensions::primitiveBoundingBoxEXT);
map["GL_ANGLE_relaxed_vertex_attribute_type"] = esOnlyExtension(&Extensions::relaxedVertexAttributeTypeANGLE);
map["GL_ANGLE_yuv_internal_format"] = enableableExtension(&Extensions::yuvInternalFormatANGLE);
map["GL_EXT_protected_textures"] = enableableExtension(&Extensions::protectedTexturesEXT);
// GLES1 extensions
map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArrayOES);
map["GL_OES_texture_cube_map"] = enableableExtension(&Extensions::textureCubeMapOES);

Просмотреть файл

@ -741,6 +741,9 @@ struct Extensions
// GL_ANGLE_yuv_internal_format
bool yuvInternalFormatANGLE = false;
// GL_EXT_protected_textures
bool protectedTexturesEXT = false;
};
// Pointer to a boolean memeber of the Extensions struct

Просмотреть файл

@ -6,7 +6,6 @@
// Context.cpp: Implements the gl::Context class, managing all GL state and performing
// rendering operations. It is the GLES2 specific implementation of EGLContext.
#include "libANGLE/Context.h"
#include "libANGLE/Context.inl.h"
@ -3559,6 +3558,14 @@ Extensions Context::generateSupportedExtensions() const
ASSERT(supportedExtensions.textureCompressionASTCHDRKHR);
}
// GL_KHR_protected_textures
// If EGL_KHR_protected_content is not supported then GL_EXT_protected_texture
// can not be supported.
if (!mDisplay->getExtensions().protectedContentEXT)
{
supportedExtensions.protectedTexturesEXT = false;
}
// GL_ANGLE_get_tex_level_parameter is implemented in the frontend
supportedExtensions.getTexLevelParameterANGLE = true;

Просмотреть файл

@ -184,6 +184,7 @@
/* GL_EXT_multisampled_render_to_texture2 */ \
/* GL_EXT_occlusion_query_boolean */ \
/* GL_EXT_primitive_bounding_box */ \
/* GL_EXT_protected_textures */ \
/* GL_EXT_read_format_bgra */ \
/* GL_EXT_robustness */ \
/* GL_EXT_sRGB */ \

Просмотреть файл

@ -567,6 +567,7 @@ MSG kProgramNotSeparable = "Program object was not linked with its PROGRAM_SEPAR
MSG kProgramPipelineDoesNotExist = "Program pipeline does not exist.";
MSG kNotAllStagesOfSeparableProgramUsed = "A program object is active for at least one, but not all of the shader stages that were present when the program was linked.";
MSG kProgramPipelineLinkFailed = "Program pipeline link failed";
MSG kProtectedTexturesExtensionRequired = "GL_EXT_protected_textures not enabled.";
// clang-format on

Просмотреть файл

@ -212,6 +212,7 @@ class FramebufferAttachmentObject : public angle::Subject, public angle::Observe
GLenum binding,
const ImageIndex &imageIndex) const = 0;
virtual bool isYUV() const = 0;
virtual bool hasProtectedContent() const = 0;
virtual void onAttach(const Context *context, rx::Serial framebufferSerial) = 0;
virtual void onDetach(const Context *context, rx::Serial framebufferSerial) = 0;

Просмотреть файл

@ -135,6 +135,11 @@ bool ImageSibling::isYUV() const
return mTargetOf.get() && mTargetOf->isYUV();
}
bool ImageSibling::hasProtectedContent() const
{
return mTargetOf.get() && mTargetOf->hasProtectedContent();
}
void ImageSibling::notifySiblings(angle::SubjectMessage message)
{
if (mTargetOf.get())
@ -203,6 +208,11 @@ bool ExternalImageSibling::isYUV() const
return mImplementation->isYUV();
}
bool ExternalImageSibling::hasProtectedContent() const
{
return mImplementation->hasProtectedContent();
}
void ExternalImageSibling::onAttach(const gl::Context *context, rx::Serial framebufferSerial) {}
void ExternalImageSibling::onDetach(const gl::Context *context, rx::Serial framebufferSerial) {}
@ -249,7 +259,8 @@ ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap
samples(),
sourceType(target),
colorspace(
static_cast<EGLenum>(attribs.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_DEFAULT_EXT)))
static_cast<EGLenum>(attribs.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_DEFAULT_EXT))),
hasProtectedContent(static_cast<bool>(attribs.get(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE)))
{}
ImageState::~ImageState() {}
@ -414,6 +425,11 @@ size_t Image::getSamples() const
return mState.samples;
}
bool Image::hasProtectedContent() const
{
return mState.hasProtectedContent;
}
rx::ImageImpl *Image::getImplementation() const
{
return mImplementation;
@ -426,6 +442,8 @@ Error Image::initialize(const Display *display)
ExternalImageSibling *externalSibling = rx::GetAs<ExternalImageSibling>(mState.source);
ANGLE_TRY(externalSibling->initialize(display));
mState.hasProtectedContent = externalSibling->hasProtectedContent();
// Only external siblings can be YUV
mState.yuv = externalSibling->isYUV();
}

Просмотреть файл

@ -52,6 +52,7 @@ class ImageSibling : public gl::FramebufferAttachmentObject
GLenum binding,
const gl::ImageIndex &imageIndex) const override;
bool isYUV() const override;
bool hasProtectedContent() const override;
protected:
// Set the image target of this sibling
@ -99,6 +100,7 @@ class ExternalImageSibling : public ImageSibling
const gl::ImageIndex &imageIndex) const override;
bool isTextureable(const gl::Context *context) const;
bool isYUV() const override;
bool hasProtectedContent() const override;
void onAttach(const gl::Context *context, rx::Serial framebufferSerial) override;
void onDetach(const gl::Context *context, rx::Serial framebufferSerial) override;
@ -137,6 +139,7 @@ struct ImageState : private angle::NonCopyable
size_t samples;
EGLenum sourceType;
EGLenum colorspace;
bool hasProtectedContent;
};
class Image final : public RefCountObject, public LabeledObject
@ -162,6 +165,7 @@ class Image final : public RefCountObject, public LabeledObject
size_t getHeight() const;
bool isLayered() const;
size_t getSamples() const;
bool hasProtectedContent() const;
Error initialize(const Display *display);

Просмотреть файл

@ -18,7 +18,8 @@ MemoryObject::MemoryObject(rx::GLImplFactory *factory, MemoryObjectID id)
: RefCountObject(factory->generateSerial(), id),
mImplementation(factory->createMemoryObject()),
mImmutable(false),
mDedicatedMemory(false)
mDedicatedMemory(false),
mProtectedMemory(false)
{}
MemoryObject::~MemoryObject() {}
@ -35,6 +36,13 @@ angle::Result MemoryObject::setDedicatedMemory(const Context *context, bool dedi
return angle::Result::Continue;
}
angle::Result MemoryObject::setProtectedMemory(const Context *context, bool protectedMemory)
{
ANGLE_TRY(mImplementation->setProtectedMemory(context, protectedMemory));
mProtectedMemory = protectedMemory;
return angle::Result::Continue;
}
angle::Result MemoryObject::importFd(Context *context,
GLuint64 size,
HandleType handleType,

Просмотреть файл

@ -38,6 +38,8 @@ class MemoryObject final : public RefCountObject<MemoryObjectID>
angle::Result setDedicatedMemory(const Context *context, bool dedicatedMemory);
bool isDedicatedMemory() const { return mDedicatedMemory; }
angle::Result setProtectedMemory(const Context *context, bool protectedMemory);
bool isProtectedMemory() const { return mProtectedMemory; }
angle::Result importFd(Context *context, GLuint64 size, HandleType handleType, GLint fd);
angle::Result importZirconHandle(Context *context,
@ -50,6 +52,7 @@ class MemoryObject final : public RefCountObject<MemoryObjectID>
bool mImmutable;
bool mDedicatedMemory;
bool mProtectedMemory;
};
} // namespace gl

Просмотреть файл

@ -34,6 +34,7 @@ RenderbufferState::RenderbufferState()
mFormat(GL_RGBA4),
mSamples(0),
mMultisamplingMode(MultisamplingMode::Regular),
mHasProtectedContent(false),
mInitState(InitState::Initialized)
{}
@ -76,12 +77,18 @@ void RenderbufferState::update(GLsizei width,
MultisamplingMode multisamplingMode,
InitState initState)
{
mWidth = width;
mHeight = height;
mFormat = format;
mSamples = samples;
mMultisamplingMode = multisamplingMode;
mInitState = InitState::MayNeedInit;
mWidth = width;
mHeight = height;
mFormat = format;
mSamples = samples;
mMultisamplingMode = multisamplingMode;
mInitState = InitState::MayNeedInit;
mHasProtectedContent = false;
}
void RenderbufferState::setProtectedContent(bool hasProtectedContent)
{
mHasProtectedContent = hasProtectedContent;
}
// Renderbuffer implementation.
@ -164,6 +171,8 @@ angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl
mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
Format(image->getFormat()), 0, MultisamplingMode::Regular,
image->sourceInitState());
mState.setProtectedContent(image->hasProtectedContent());
onStateChange(angle::SubjectMessage::SubjectChanged);
return angle::Result::Continue;

Просмотреть файл

@ -44,6 +44,7 @@ class RenderbufferState final : angle::NonCopyable
GLsizei getSamples() const;
MultisamplingMode getMultisamplingMode() const;
InitState getInitState() const;
void setProtectedContent(bool hasProtectedContent);
private:
friend class Renderbuffer;
@ -60,6 +61,7 @@ class RenderbufferState final : angle::NonCopyable
Format mFormat;
GLsizei mSamples;
MultisamplingMode mMultisamplingMode;
bool mHasProtectedContent;
// For robust resource init.
InitState mInitState;

Просмотреть файл

@ -133,7 +133,7 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
EGLint getHorizontalResolution() const;
EGLint getVerticalResolution() const;
EGLenum getMultisampleResolve() const;
bool hasProtectedContent() const;
bool hasProtectedContent() const override;
gl::Texture *getBoundTexture() const { return mTexture; }

Просмотреть файл

@ -144,6 +144,7 @@ TextureState::TextureState(TextureType type)
mImmutableFormat(false),
mImmutableLevels(0),
mUsage(GL_NONE),
mHasProtectedContent(false),
mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) * (type == TextureType::CubeMap ? 6 : 1)),
mCropRect(0, 0, 0, 0),
mGenerateMipmapHint(GL_FALSE),
@ -1065,6 +1066,16 @@ GLenum Texture::getUsage() const
return mState.mUsage;
}
void Texture::setProtectedContent(Context *context, bool hasProtectedContent)
{
mState.mHasProtectedContent = hasProtectedContent;
}
bool Texture::hasProtectedContent() const
{
return mState.mHasProtectedContent;
}
const TextureState &Texture::getTextureState() const
{
return mState;
@ -1735,6 +1746,7 @@ angle::Result Texture::bindTexImageFromSurface(Context *context, egl::Surface *s
Extents size(surface->getWidth(), surface->getHeight(), 1);
ImageDesc desc(size, surface->getBindTexImageFormat(), InitState::Initialized);
mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0, desc);
mState.mHasProtectedContent = surface->hasProtectedContent();
signalDirtyStorage(InitState::Initialized);
return angle::Result::Continue;
}
@ -1748,6 +1760,7 @@ angle::Result Texture::releaseTexImageFromSurface(const Context *context)
// Erase the image info for level 0
ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
mState.mHasProtectedContent = false;
signalDirtyStorage(InitState::Initialized);
return angle::Result::Continue;
}
@ -1838,6 +1851,7 @@ angle::Result Texture::setEGLImageTarget(Context *context,
mState.clearImageDescs();
mState.setImageDesc(NonCubeTextureTypeToTarget(type), 0,
ImageDesc(size, imageTarget->getFormat(), initState));
mState.mHasProtectedContent = imageTarget->hasProtectedContent();
signalDirtyStorage(initState);
return angle::Result::Continue;

Просмотреть файл

@ -143,6 +143,7 @@ class TextureState final : private angle::NonCopyable
const SwizzleState &getSwizzleState() const { return mSwizzleState; }
const SamplerState &getSamplerState() const { return mSamplerState; }
GLenum getUsage() const { return mUsage; }
bool hasProtectedContent() const { return mHasProtectedContent; }
GLenum getDepthStencilTextureMode() const { return mDepthStencilTextureMode; }
bool isStencilMode() const { return mDepthStencilTextureMode == GL_STENCIL_INDEX; }
@ -224,6 +225,9 @@ class TextureState final : private angle::NonCopyable
// From GL_ANGLE_texture_usage
GLenum mUsage;
// GL_EXT_protected_textures
bool mHasProtectedContent;
std::vector<ImageDesc> mImageDescs;
// GLES1 emulation: Texture crop rectangle
@ -328,6 +332,9 @@ class Texture final : public RefCountObject<TextureID>,
void setUsage(const Context *context, GLenum usage);
GLenum getUsage() const;
void setProtectedContent(Context *context, bool hasProtectedContent);
bool hasProtectedContent() const override;
const TextureState &getState() const { return mState; }
void setBorderColor(const Context *context, const ColorGeneric &color);

Просмотреть файл

@ -1273,6 +1273,8 @@ angle::CallCapture CapturePrimitiveBoundingBoxEXT(const State &glState,
GLfloat maxZ,
GLfloat maxW);
// GL_EXT_protected_textures
// GL_EXT_read_format_bgra
// GL_EXT_robustness

Просмотреть файл

@ -535,6 +535,8 @@ const char *GLenumToString(GLenumGroup enumGroup, unsigned int value)
return "GL_CONTEXT_FLAG_DEBUG_BIT";
case 0x4:
return "GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT";
case 0x10:
return "GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT";
default:
return UnknownGLenumToString(value);
}
@ -1173,6 +1175,8 @@ const char *GLenumToString(GLenumGroup enumGroup, unsigned int value)
return "GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES";
case 0x8BE7:
return "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT";
case 0x8BFA:
return "GL_TEXTURE_PROTECTED_EXT";
case 0x8C10:
return "GL_TEXTURE_RED_TYPE";
case 0x8C11:

Просмотреть файл

@ -369,6 +369,9 @@ void QueryTexParameterBase(const Context *context,
*params = CastFromGLintStateValue<ParamType>(
pname, texture->getRequiredTextureImageUnits(context));
break;
case GL_TEXTURE_PROTECTED_EXT:
*params = CastFromGLintStateValue<ParamType>(pname, texture->hasProtectedContent());
break;
default:
UNREACHABLE();
break;
@ -479,6 +482,9 @@ void SetTexParameterBase(Context *context, Texture *texture, GLenum pname, const
texture->setInitState(ConvertToBool(params[0]) ? InitState::Initialized
: InitState::MayNeedInit);
break;
case GL_TEXTURE_PROTECTED_EXT:
texture->setProtectedContent(context, (params[0] == GL_TRUE));
break;
default:
UNREACHABLE();
break;
@ -2193,6 +2199,10 @@ angle::Result SetMemoryObjectParameteriv(const Context *context,
ANGLE_TRY(memoryObject->setDedicatedMemory(context, ConvertToBool(params[0])));
break;
case GL_PROTECTED_MEMORY_OBJECT_EXT:
ANGLE_TRY(memoryObject->setProtectedMemory(context, ConvertToBool(params[0])));
break;
default:
UNREACHABLE();
}
@ -2208,6 +2218,10 @@ void QueryMemoryObjectParameteriv(const MemoryObject *memoryObject, GLenum pname
*params = memoryObject->isDedicatedMemory();
break;
case GL_PROTECTED_MEMORY_OBJECT_EXT:
*params = memoryObject->isProtectedMemory();
break;
default:
UNREACHABLE();
}

Просмотреть файл

@ -40,6 +40,7 @@ class ExternalImageSiblingImpl : public FramebufferAttachmentObjectImpl
virtual bool isRenderable(const gl::Context *context) const = 0;
virtual bool isTexturable(const gl::Context *context) const = 0;
virtual bool isYUV() const = 0;
virtual bool hasProtectedContent() const = 0;
virtual gl::Extents getSize() const = 0;
virtual size_t getSamples() const = 0;
};

Просмотреть файл

@ -30,6 +30,7 @@ class MemoryObjectImpl : angle::NonCopyable
virtual void onDestroy(const gl::Context *context) = 0;
virtual angle::Result setDedicatedMemory(const gl::Context *context, bool dedicatedMemory) = 0;
virtual angle::Result setProtectedMemory(const gl::Context *context, bool protectedMemory) = 0;
virtual angle::Result importFd(gl::Context *context,
GLuint64 size,

Просмотреть файл

@ -81,6 +81,11 @@ bool ExternalImageSiblingImpl11::isYUV() const
return mYUV;
}
bool ExternalImageSiblingImpl11::hasProtectedContent() const
{
return mHasProtectedContent;
}
gl::Extents ExternalImageSiblingImpl11::getSize() const
{
return gl::Extents(mWidth, mHeight, 1);

Просмотреть файл

@ -30,6 +30,7 @@ class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl
bool isRenderable(const gl::Context *context) const override;
bool isTexturable(const gl::Context *context) const override;
bool isYUV() const override;
bool hasProtectedContent() const override;
gl::Extents getSize() const override;
size_t getSamples() const override;
@ -51,15 +52,16 @@ class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl
TextureHelper11 mTexture;
gl::Format mFormat = gl::Format::Invalid();
bool mIsRenderable = false;
bool mIsTexturable = false;
bool mIsTextureArray = false;
bool mYUV = false;
EGLint mWidth = 0;
EGLint mHeight = 0;
GLsizei mSamples = 0;
UINT mArraySlice = 0;
gl::Format mFormat = gl::Format::Invalid();
bool mIsRenderable = false;
bool mIsTexturable = false;
bool mIsTextureArray = false;
bool mYUV = false;
bool mHasProtectedContent = false;
EGLint mWidth = 0;
EGLint mHeight = 0;
GLsizei mSamples = 0;
UINT mArraySlice = 0;
std::unique_ptr<RenderTargetD3D> mRenderTarget;
};

Просмотреть файл

@ -40,6 +40,16 @@ angle::Result MemoryObjectGL::setDedicatedMemory(const gl::Context *context, boo
return angle::Result::Continue;
}
angle::Result MemoryObjectGL::setProtectedMemory(const gl::Context *context, bool protectedMemory)
{
const FunctionsGL *functions = GetFunctionsGL(context);
GLint params = gl::ConvertToGLBoolean(protectedMemory);
ANGLE_GL_TRY(context, functions->memoryObjectParameterivEXT(
mMemoryObject, GL_PROTECTED_MEMORY_OBJECT_EXT, &params));
return angle::Result::Continue;
}
angle::Result MemoryObjectGL::importFd(gl::Context *context,
GLuint64 size,
gl::HandleType handleType,

Просмотреть файл

@ -22,6 +22,7 @@ class MemoryObjectGL : public MemoryObjectImpl
void onDestroy(const gl::Context *context) override;
angle::Result setDedicatedMemory(const gl::Context *context, bool dedicatedMemory) override;
angle::Result setProtectedMemory(const gl::Context *context, bool protectedMemory) override;
angle::Result importFd(gl::Context *context,
GLuint64 size,

Просмотреть файл

@ -74,13 +74,14 @@ GLenum FourCCFormatToGLInternalFormat(int format, bool *isYUV)
namespace rx
{
DmaBufImageSiblingEGL::DmaBufImageSiblingEGL(const egl::AttributeMap &attribs)
: mAttribs(attribs), mFormat(GL_NONE), mYUV(false)
: mAttribs(attribs), mFormat(GL_NONE), mYUV(false), mHasProtectedContent(false)
{
ASSERT(mAttribs.contains(EGL_WIDTH));
mSize.width = mAttribs.getAsInt(EGL_WIDTH);
ASSERT(mAttribs.contains(EGL_HEIGHT));
mSize.height = mAttribs.getAsInt(EGL_HEIGHT);
mSize.depth = 1;
mSize.height = mAttribs.getAsInt(EGL_HEIGHT);
mSize.depth = 1;
mHasProtectedContent = mAttribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != 0;
int fourCCFormat = mAttribs.getAsInt(EGL_LINUX_DRM_FOURCC_EXT);
mFormat = gl::Format(FourCCFormatToGLInternalFormat(fourCCFormat, &mYUV));
@ -113,6 +114,11 @@ bool DmaBufImageSiblingEGL::isYUV() const
return mYUV;
}
bool DmaBufImageSiblingEGL::hasProtectedContent() const
{
return mHasProtectedContent;
}
gl::Extents DmaBufImageSiblingEGL::getSize() const
{
return mSize;
@ -132,6 +138,7 @@ void DmaBufImageSiblingEGL::getImageCreationAttributes(std::vector<EGLint> *outA
{
EGLenum kForwardedAttribs[] = {EGL_WIDTH,
EGL_HEIGHT,
EGL_PROTECTED_CONTENT_EXT,
EGL_LINUX_DRM_FOURCC_EXT,
EGL_DMA_BUF_PLANE0_FD_EXT,
EGL_DMA_BUF_PLANE0_OFFSET_EXT,

Просмотреть файл

@ -28,6 +28,7 @@ class DmaBufImageSiblingEGL : public ExternalImageSiblingEGL
bool isRenderable(const gl::Context *context) const override;
bool isTexturable(const gl::Context *context) const override;
bool isYUV() const override;
bool hasProtectedContent() const override;
gl::Extents getSize() const override;
size_t getSamples() const override;
@ -40,6 +41,7 @@ class DmaBufImageSiblingEGL : public ExternalImageSiblingEGL
gl::Extents mSize;
gl::Format mFormat;
bool mYUV;
bool mHasProtectedContent;
};
} // namespace rx

Просмотреть файл

@ -21,11 +21,13 @@ NativeBufferImageSiblingAndroid::~NativeBufferImageSiblingAndroid() {}
egl::Error NativeBufferImageSiblingAndroid::initialize(const egl::Display *display)
{
int pixelFormat = 0;
uint64_t usage = 0;
angle::android::GetANativeWindowBufferProperties(
angle::android::ClientBufferToANativeWindowBuffer(mBuffer), &mSize.width, &mSize.height,
&mSize.depth, &pixelFormat);
&mSize.depth, &pixelFormat, &usage);
mFormat = gl::Format(angle::android::NativePixelFormatToGLInternalFormat(pixelFormat));
mYUV = angle::android::NativePixelFormatIsYUV(pixelFormat);
mHasProtectedContent = (usage & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) != 0;
return egl::NoError();
}
@ -50,6 +52,11 @@ bool NativeBufferImageSiblingAndroid::isYUV() const
return mYUV;
}
bool NativeBufferImageSiblingAndroid::hasProtectedContent() const
{
return mHasProtectedContent;
}
gl::Extents NativeBufferImageSiblingAndroid::getSize() const
{
return mSize;

Просмотреть файл

@ -28,6 +28,7 @@ class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL
bool isRenderable(const gl::Context *context) const override;
bool isTexturable(const gl::Context *context) const override;
bool isYUV() const override;
bool hasProtectedContent() const override;
gl::Extents getSize() const override;
size_t getSamples() const override;
@ -39,6 +40,7 @@ class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL
gl::Extents mSize;
gl::Format mFormat;
bool mYUV;
bool mHasProtectedContent;
};
} // namespace rx

Просмотреть файл

@ -37,6 +37,7 @@ class TextureImageSiblingMtl : public ExternalImageSiblingImpl
size_t getSamples() const override;
bool isYUV() const override;
bool hasProtectedContent() const override;
const mtl::TextureRef &getTexture() const { return mNativeTexture; }
const mtl::Format &getFormatMtl() const { return mFormat; }

Просмотреть файл

@ -118,6 +118,11 @@ bool TextureImageSiblingMtl::isYUV() const
return false;
}
bool TextureImageSiblingMtl::hasProtectedContent() const
{
return false;
}
// ImageMtl implementation
ImageMtl::ImageMtl(const egl::ImageState &state, const gl::Context *context) : ImageImpl(state) {}

Просмотреть файл

@ -101,6 +101,12 @@ angle::Result MemoryObjectVk::setDedicatedMemory(const gl::Context *context, boo
return angle::Result::Continue;
}
angle::Result MemoryObjectVk::setProtectedMemory(const gl::Context *context, bool protectedMemory)
{
mProtectedMemory = protectedMemory;
return angle::Result::Continue;
}
angle::Result MemoryObjectVk::importFd(gl::Context *context,
GLuint64 size,
gl::HandleType handleType,
@ -204,11 +210,12 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
// ANGLE_external_objects_flags allows create flags to be specified by the application instead
// of getting defaulted to zero. Note that the GL enum values constituting the bits of
// |createFlags| are identical to their corresponding Vulkan value.
ANGLE_TRY(image->initExternal(contextVk, type, vkExtents, vkFormat, 1, imageUsageFlags,
createFlags, vk::ImageLayout::Undefined,
&externalMemoryImageCreateInfo, gl::LevelIndex(0),
static_cast<uint32_t>(levels), layerCount,
contextVk->isRobustResourceInitEnabled(), nullptr, false));
bool hasProtectedContent = mProtectedMemory;
ANGLE_TRY(image->initExternal(
contextVk, type, vkExtents, vkFormat, 1, imageUsageFlags, createFlags,
vk::ImageLayout::Undefined, &externalMemoryImageCreateInfo, gl::LevelIndex(0),
static_cast<uint32_t>(levels), layerCount, contextVk->isRobustResourceInitEnabled(),
nullptr, hasProtectedContent));
VkMemoryRequirements externalMemoryRequirements;
image->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);
@ -252,7 +259,7 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
ASSERT(offset == 0);
ASSERT(externalMemoryRequirements.size == mSize);
VkMemoryPropertyFlags flags = 0;
VkMemoryPropertyFlags flags = hasProtectedContent ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0;
ANGLE_TRY(image->initExternalMemory(contextVk, renderer->getMemoryProperties(),
externalMemoryRequirements, nullptr, importMemoryInfo,
renderer->getQueueFamilyIndex(), flags));

Просмотреть файл

@ -24,6 +24,7 @@ class MemoryObjectVk : public MemoryObjectImpl
void onDestroy(const gl::Context *context) override;
angle::Result setDedicatedMemory(const gl::Context *context, bool dedicatedMemory) override;
angle::Result setProtectedMemory(const gl::Context *context, bool protectedMemory) override;
angle::Result importFd(gl::Context *context,
GLuint64 size,
@ -52,6 +53,7 @@ class MemoryObjectVk : public MemoryObjectImpl
// Imported memory object was a dedicated allocation.
bool mDedicatedMemory = false;
bool mProtectedMemory = false;
GLuint64 mSize = 0;
gl::HandleType mHandleType = gl::HandleType::InvalidEnum;

Просмотреть файл

@ -1008,10 +1008,10 @@ angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();
ANGLE_TRY(
stagingImage->get().init2DStaging(contextVk, false, renderer->getMemoryProperties(),
gl::Extents(sourceBox.width, sourceBox.height, 1),
destFormat, kTransferStagingImageFlags, layerCount));
ANGLE_TRY(stagingImage->get().init2DStaging(
contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
gl::Extents(sourceBox.width, sourceBox.height, 1), destFormat,
kTransferStagingImageFlags, layerCount));
access.onImageTransferWrite(gl::LevelIndex(0), 1, 0, layerCount, VK_IMAGE_ASPECT_COLOR_BIT,
&stagingImage->get());
@ -1159,10 +1159,10 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
std::unique_ptr<vk::RefCounted<vk::ImageHelper>> stagingImage;
stagingImage = std::make_unique<vk::RefCounted<vk::ImageHelper>>();
ANGLE_TRY(
stagingImage->get().init2DStaging(contextVk, false, renderer->getMemoryProperties(),
gl::Extents(sourceBox.width, sourceBox.height, 1),
destFormat, kDrawStagingImageFlags, layerCount));
ANGLE_TRY(stagingImage->get().init2DStaging(
contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
gl::Extents(sourceBox.width, sourceBox.height, 1), destFormat, kDrawStagingImageFlags,
layerCount));
params.destOffset[0] = 0;
params.destOffset[1] = 0;
@ -1987,10 +1987,10 @@ angle::Result TextureVk::copyAndStageImageData(ContextVk *contextVk,
const uint32_t levelCount = srcImage->getLevelCount();
const uint32_t layerCount = srcImage->getLayerCount();
ANGLE_TRY(stagingImage->get().initStaging(contextVk, false, renderer->getMemoryProperties(),
srcImage->getType(), srcImage->getExtents(),
srcImage->getFormat(), srcImage->getSamples(),
kTransferStagingImageFlags, levelCount, layerCount));
ANGLE_TRY(stagingImage->get().initStaging(
contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
srcImage->getType(), srcImage->getExtents(), srcImage->getFormat(), srcImage->getSamples(),
kTransferStagingImageFlags, levelCount, layerCount));
// Copy the src image wholly into the staging image
const VkImageAspectFlags aspectFlags = srcImage->getAspectFlags();
@ -2196,8 +2196,8 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
// Create the implicit multisampled image.
ANGLE_TRY(multisampledImage->initImplicitMultisampledRenderToTexture(
contextVk, false, renderer->getMemoryProperties(), mState.getType(), samples, *mImage,
useRobustInit));
contextVk, mState.hasProtectedContent(), renderer->getMemoryProperties(),
mState.getType(), samples, *mImage, useRobustInit));
}
// Don't flush staged updates here. We'll handle that in FramebufferVk so it can defer clears.
@ -2793,17 +2793,28 @@ angle::Result TextureVk::initImage(ContextVk *contextVk,
gl_vk::GetExtentsAndLayerCount(mState.getType(), firstLevelExtents, &vkExtent, &layerCount);
GLint samples = mState.getBaseLevelDesc().samples ? mState.getBaseLevelDesc().samples : 1;
if (mState.hasProtectedContent())
{
mImageCreateFlags |= VK_IMAGE_CREATE_PROTECTED_BIT;
}
bool imageFormatListEnabled = false;
ANGLE_TRY(mImage->initExternal(
contextVk, mState.getType(), vkExtent, format, samples, mImageUsageFlags, mImageCreateFlags,
vk::ImageLayout::Undefined, nullptr, gl::LevelIndex(firstLevel), levelCount, layerCount,
contextVk->isRobustResourceInitEnabled(), &imageFormatListEnabled, false));
ANGLE_TRY(mImage->initExternal(contextVk, mState.getType(), vkExtent, format, samples,
mImageUsageFlags, mImageCreateFlags, vk::ImageLayout::Undefined,
nullptr, gl::LevelIndex(firstLevel), levelCount, layerCount,
contextVk->isRobustResourceInitEnabled(),
&imageFormatListEnabled, mState.hasProtectedContent()));
mRequiresMutableStorage = (mImageCreateFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0;
const VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
if (mState.hasProtectedContent())
{
flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
}
ANGLE_TRY(mImage->initMemory(contextVk, false, renderer->getMemoryProperties(), flags));
ANGLE_TRY(mImage->initMemory(contextVk, mState.hasProtectedContent(),
renderer->getMemoryProperties(), flags));
const uint32_t viewLevelCount =
mState.getImmutableFormat() ? getMipLevelCount(ImageMipLevels::EnabledLevels) : levelCount;

Просмотреть файл

@ -98,8 +98,8 @@ egl::Error DisplayVkAndroid::validateImageClientBuffer(const gl::Context *contex
switch (target)
{
case EGL_NATIVE_BUFFER_ANDROID:
return HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(mRenderer,
clientBuffer);
return HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(
mRenderer, clientBuffer, attribs);
default:
return DisplayVk::validateImageClientBuffer(context, target, clientBuffer, attribs);

Просмотреть файл

@ -87,8 +87,10 @@ HardwareBufferImageSiblingVkAndroid::HardwareBufferImageSiblingVkAndroid(EGLClie
HardwareBufferImageSiblingVkAndroid::~HardwareBufferImageSiblingVkAndroid() {}
// Static
egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(RendererVk *renderer,
EGLClientBuffer buffer)
egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(
RendererVk *renderer,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
{
struct ANativeWindowBuffer *windowBuffer =
angle::android::ClientBufferToANativeWindowBuffer(buffer);
@ -133,6 +135,23 @@ egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(RendererV
}
}
if (attribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) == EGL_TRUE)
{
int width = 0;
int height = 0;
int depth = 0;
int pixelFormat = 0;
uint64_t usage = 0;
angle::android::GetANativeWindowBufferProperties(windowBuffer, &width, &height, &depth,
&pixelFormat, &usage);
if ((usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) == 0)
{
return egl::EglBadAccess()
<< "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
"of EGLCleintBuffer.";
}
}
return egl::NoError();
}
@ -191,7 +210,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
int pixelFormat = 0;
angle::android::GetANativeWindowBufferProperties(windowBuffer, &mSize.width, &mSize.height,
&mSize.depth, &pixelFormat);
&mSize.depth, &pixelFormat, &mUsage);
GLenum internalFormat = angle::android::NativePixelFormatToGLInternalFormat(pixelFormat);
mFormat = gl::Format(internalFormat);
@ -259,12 +278,17 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
bool robustInitEnabled = false;
mImage->setTilingMode(imageTilingMode);
VkImageCreateFlags imageCreateFlags = vk::kVkImageCreateFlagsNone;
if (hasProtectedContent())
{
imageCreateFlags |= VK_IMAGE_CREATE_PROTECTED_BIT;
}
ANGLE_TRY(mImage->initExternal(
displayVk, gl::TextureType::_2D, vkExtents,
bufferFormatProperties.format == VK_FORMAT_UNDEFINED ? externalVkFormat : vkFormat, 1,
usage, vk::kVkImageCreateFlagsNone, vk::ImageLayout::ExternalPreInitialized,
usage, imageCreateFlags, vk::ImageLayout::ExternalPreInitialized,
&externalMemoryImageCreateInfo, gl::LevelIndex(0), 1, 1, robustInitEnabled, nullptr,
false));
hasProtectedContent()));
VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
@ -281,7 +305,8 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
externalMemoryRequirements.alignment = 0;
externalMemoryRequirements.memoryTypeBits = bufferProperties.memoryTypeBits;
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
(hasProtectedContent() ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0);
if (bufferFormatProperties.format == VK_FORMAT_UNDEFINED)
{
// Note from Vulkan spec: Since GL_OES_EGL_image_external does not require the same sampling
@ -360,6 +385,11 @@ bool HardwareBufferImageSiblingVkAndroid::isYUV() const
return mYUV;
}
bool HardwareBufferImageSiblingVkAndroid::hasProtectedContent() const
{
return ((mUsage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) != 0);
}
gl::Extents HardwareBufferImageSiblingVkAndroid::getSize() const
{
return mSize;

Просмотреть файл

@ -21,7 +21,9 @@ class HardwareBufferImageSiblingVkAndroid : public ExternalImageSiblingVk
HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer);
~HardwareBufferImageSiblingVkAndroid() override;
static egl::Error ValidateHardwareBuffer(RendererVk *renderer, EGLClientBuffer buffer);
static egl::Error ValidateHardwareBuffer(RendererVk *renderer,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs);
egl::Error initialize(const egl::Display *display) override;
void onDestroy(const egl::Display *display) override;
@ -31,6 +33,7 @@ class HardwareBufferImageSiblingVkAndroid : public ExternalImageSiblingVk
bool isRenderable(const gl::Context *context) const override;
bool isTexturable(const gl::Context *context) const override;
bool isYUV() const override;
bool hasProtectedContent() const override;
gl::Extents getSize() const override;
size_t getSamples() const override;
@ -49,6 +52,7 @@ class HardwareBufferImageSiblingVkAndroid : public ExternalImageSiblingVk
bool mRenderable;
bool mTextureable;
bool mYUV;
uint64_t mUsage;
size_t mSamples;
vk::ImageHelper *mImage;

Просмотреть файл

@ -1072,6 +1072,9 @@ void RendererVk::ensureCapsInitialized() const
// GL_ANGLE_yuv_internal_format
mNativeExtensions.yuvInternalFormatANGLE =
getFeatures().supportsYUVSamplerConversion.enabled && vk::CanSupportYuvInternalFormat(this);
// GL_EXT_protected_textures
mNativeExtensions.protectedTexturesEXT = mFeatures.supportsProtectedMemory.enabled;
}
namespace vk

Просмотреть файл

@ -3240,6 +3240,16 @@ bool ValidateCreateImage(const ValidationContext *val,
return false;
}
bool protectedContentAttrib =
(attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
if (protectedContentAttrib != texture->hasProtectedContent())
{
val->setError(EGL_BAD_PARAMETER,
"EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
"of target.");
return false;
}
ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
}
break;
@ -3301,6 +3311,16 @@ bool ValidateCreateImage(const ValidationContext *val,
"zero.");
return false;
}
bool protectedContentAttrib =
(attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
if (protectedContentAttrib != texture->hasProtectedContent())
{
val->setError(EGL_BAD_PARAMETER,
"EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
"of target.");
return false;
}
}
break;
@ -3355,6 +3375,16 @@ bool ValidateCreateImage(const ValidationContext *val,
return false;
}
bool protectedContentAttrib =
(attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
if (protectedContentAttrib != texture->hasProtectedContent())
{
val->setError(EGL_BAD_PARAMETER,
"EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
"of target.");
return false;
}
ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
}
break;
@ -3396,6 +3426,16 @@ bool ValidateCreateImage(const ValidationContext *val,
val->setError(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
return false;
}
bool protectedContentAttrib =
(attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
if (protectedContentAttrib != renderbuffer->hasProtectedContent())
{
val->setError(EGL_BAD_ACCESS,
"EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
"of target.");
return false;
}
}
break;

Просмотреть файл

@ -4583,6 +4583,13 @@ bool ValidateEGLImageTargetTexture2DOES(const Context *context,
return false;
}
if (imageObject->hasProtectedContent() != context->getState().hasProtectedContent())
{
context->validationError(GL_INVALID_OPERATION,
"Mismatch between Image and Context Protected Content state");
return false;
}
return true;
}
@ -4621,6 +4628,13 @@ bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
return false;
}
if (imageObject->hasProtectedContent() != context->getState().hasProtectedContent())
{
context->validationError(GL_INVALID_OPERATION,
"Mismatch between Image and Context Protected Content state");
return false;
}
return true;
}
@ -6549,6 +6563,14 @@ bool ValidateGetTexParameterBase(const Context *context,
}
break;
case GL_TEXTURE_PROTECTED_EXT:
if (!context->getExtensions().protectedTexturesEXT)
{
context->validationError(GL_INVALID_ENUM, kProtectedTexturesExtensionRequired);
return false;
}
break;
default:
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
@ -7251,7 +7273,20 @@ bool ValidateTexParameterBase(const Context *context,
kRobustResourceInitializationExtensionRequired);
return false;
}
break;
case GL_TEXTURE_PROTECTED_EXT:
if (!context->getExtensions().protectedTexturesEXT)
{
context->validationError(GL_INVALID_ENUM, kProtectedTexturesExtensionRequired);
return false;
}
if (ConvertToBool(params[0]) != context->getState().hasProtectedContent())
{
context->validationError(GL_INVALID_OPERATION,
"Protected Texture must match Protected Context");
return false;
}
break;
default:

Просмотреть файл

@ -72,6 +72,14 @@ bool IsValidMemoryObjectParamater(const Context *context, GLenum pname)
case GL_DEDICATED_MEMORY_OBJECT_EXT:
return true;
case GL_PROTECTED_MEMORY_OBJECT_EXT:
if (!context->getExtensions().protectedTexturesEXT)
{
context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
return false;
}
return true;
default:
return false;
}

Просмотреть файл

@ -1052,6 +1052,8 @@ bool ValidatePrimitiveBoundingBoxEXT(const Context *context,
GLfloat maxZ,
GLfloat maxW);
// GL_EXT_protected_textures
// GL_EXT_read_format_bgra
// GL_EXT_robustness

Просмотреть файл

@ -5483,6 +5483,8 @@ void GL_APIENTRY GL_PrimitiveBoundingBoxEXT(GLfloat minX,
}
}
// GL_EXT_protected_textures
// GL_EXT_read_format_bgra
// GL_EXT_robustness

Просмотреть файл

@ -893,6 +893,8 @@ ANGLE_EXPORT void GL_APIENTRY GL_PrimitiveBoundingBoxEXT(GLfloat minX,
GLfloat maxZ,
GLfloat maxW);
// GL_EXT_protected_textures
// GL_EXT_read_format_bgra
// GL_EXT_robustness

Просмотреть файл

@ -4227,6 +4227,8 @@ void GL_APIENTRY glPrimitiveBoundingBoxEXT(GLfloat minX,
return GL_PrimitiveBoundingBoxEXT(minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
}
// GL_EXT_protected_textures
// GL_EXT_read_format_bgra
// GL_EXT_robustness

Просмотреть файл

@ -716,6 +716,8 @@ EXPORTS
; GL_EXT_primitive_bounding_box
glPrimitiveBoundingBoxEXT
; GL_EXT_protected_textures
; GL_EXT_read_format_bgra
; GL_EXT_robustness

Просмотреть файл

@ -716,6 +716,8 @@ EXPORTS
; GL_EXT_primitive_bounding_box
glPrimitiveBoundingBoxEXT
; GL_EXT_protected_textures
; GL_EXT_read_format_bgra
; GL_EXT_robustness

Просмотреть файл

@ -716,6 +716,8 @@ EXPORTS
; GL_EXT_primitive_bounding_box
glPrimitiveBoundingBoxEXT
; GL_EXT_protected_textures
; GL_EXT_read_format_bgra
; GL_EXT_robustness

Просмотреть файл

@ -63,6 +63,8 @@ class EGLProtectedContentTest : public ANGLETest
clientVersion,
EGL_SURFACE_TYPE,
(EGL_PBUFFER_BIT | EGL_WINDOW_BIT),
EGL_BIND_TO_TEXTURE_RGBA,
EGL_TRUE,
EGL_NONE};
EGLint count = 0;
@ -88,10 +90,27 @@ class EGLProtectedContentTest : public ANGLETest
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};
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));
@ -116,8 +135,231 @@ class EGLProtectedContentTest : public ANGLETest
return result;
}
void PbufferTest(bool isProtectedContext, bool isProtectedSurface);
void WindowTest(bool isProtectedContext, bool isProtectedSurface);
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;
@ -125,15 +367,13 @@ class EGLProtectedContentTest : public ANGLETest
static const EGLint kHeight = 16;
};
void EGLProtectedContentTest::PbufferTest(bool isProtectedContext, bool isProtectedSurface)
void EGLProtectedContentTest::pbufferTest(bool isProtectedContext, bool isProtectedSurface)
{
if (isProtectedContext || isProtectedSurface)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
}
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));
@ -151,6 +391,7 @@ void EGLProtectedContentTest::PbufferTest(bool isProtectedContext, bool isProtec
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.";
@ -165,18 +406,16 @@ void EGLProtectedContentTest::PbufferTest(bool isProtectedContext, bool isProtec
// Unprotected context with Unprotected PbufferSurface
TEST_P(EGLProtectedContentTest, UnprotectedContextWithUnprotectedPbufferSurface)
{
PbufferTest(false, false);
pbufferTest(false, false);
}
void EGLProtectedContentTest::WindowTest(bool isProtectedContext, bool isProtectedSurface)
void EGLProtectedContentTest::windowTest(bool isProtectedContext, bool isProtectedSurface)
{
if (isProtectedContext || isProtectedSurface)
{
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_protected_content"));
}
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));
@ -199,7 +438,7 @@ void EGLProtectedContentTest::WindowTest(bool isProtectedContext, bool isProtect
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
std::this_thread::sleep_for(1s);
checkSwapBuffersResult("RED", isProtectedContext, isProtectedSurface);
// Green
glClearColor(0.0, 1.0, 0.0, 1.0);
@ -207,7 +446,7 @@ void EGLProtectedContentTest::WindowTest(bool isProtectedContext, bool isProtect
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
std::this_thread::sleep_for(1s);
checkSwapBuffersResult("GREEN", isProtectedContext, isProtectedSurface);
// Blue
glClearColor(0.0, 0.0, 1.0, 1.0);
@ -215,7 +454,7 @@ void EGLProtectedContentTest::WindowTest(bool isProtectedContext, bool isProtect
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, windowSurface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
std::this_thread::sleep_for(1s);
checkSwapBuffersResult("BLUE", isProtectedContext, isProtectedSurface);
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
@ -232,15 +471,361 @@ void EGLProtectedContentTest::WindowTest(bool isProtectedContext, bool isProtect
// Unprotected context with Unprotected WindowSurface
TEST_P(EGLProtectedContentTest, UnprotectedContextWithUnprotectedWindowSurface)
{
std::cout << "Operator should see RED, GREEN, BLUE on screen" << std::endl;
WindowTest(false, false);
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);
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,