Add support for OES_EGL_image_external and OES_EGL_image_external_essl3.

BUG=angleproject:1372

Change-Id: I8489e7fd0ab409b0775041ad5e9fbf0aab53886d
Reviewed-on: https://chromium-review.googlesource.com/344734
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Geoff Lang 2016-05-16 15:59:14 -04:00 коммит произвёл Commit Bot
Родитель a0d3aa4116
Коммит b66a9097a3
21 изменённых файлов: 752 добавлений и 135 удалений

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

@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 145
#define ANGLE_SH_VERSION 146
typedef enum {
SH_GLES2_SPEC = 0x8B40,
@ -255,6 +255,7 @@ typedef struct
// Set to 1 to enable the extension, else 0.
int OES_standard_derivatives;
int OES_EGL_image_external;
int OES_EGL_image_external_essl3;
int NV_EGL_stream_consumer_external;
int ARB_texture_rectangle;
int EXT_blend_func_extended;

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

@ -480,6 +480,8 @@ void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
void TCompiler::setResourceString()
{
std::ostringstream strstream;
// clang-format off
strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
<< ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
<< ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
@ -490,6 +492,8 @@ void TCompiler::setResourceString()
<< ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
<< ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
<< ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
<< ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
<< ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
<< ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
<< ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
<< ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
@ -509,6 +513,7 @@ void TCompiler::setResourceString()
<< ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers
<< ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision;
// clang-format on
builtInResourcesString = strstream.str();
}

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

@ -315,6 +315,17 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1);
if (resources.OES_EGL_image_external_essl3)
{
const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
float3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
float4);
}
if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1);
@ -324,6 +335,18 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1);
if (resources.OES_EGL_image_external_essl3)
{
const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2,
float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
float4, float1);
}
}
const TType *sampler2DShadow = TCache::getType(EbtSampler2DShadow);
@ -351,6 +374,13 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1);
if (resources.OES_EGL_image_external_essl3)
{
const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerExternalOES, int1);
}
if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdx, genType, "dFdx", genType);
@ -403,6 +433,14 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler3D, int3, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2DArray, int3, int1);
if (resources.OES_EGL_image_external_essl3)
{
const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texelFetch", samplerExternalOES, int2,
int1);
}
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2D, int2, int1, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1, int3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3, int1, int2);
@ -594,6 +632,8 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
if (resources.OES_EGL_image_external)
extBehavior["GL_OES_EGL_image_external"] = EBhUndefined;
if (resources.OES_EGL_image_external_essl3)
extBehavior["GL_OES_EGL_image_external_essl3"] = EBhUndefined;
if (resources.NV_EGL_stream_consumer_external)
extBehavior["GL_NV_EGL_stream_consumer_external"] = EBhUndefined;
if (resources.ARB_texture_rectangle)

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

@ -148,6 +148,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
// Extensions.
resources->OES_standard_derivatives = 0;
resources->OES_EGL_image_external = 0;
resources->OES_EGL_image_external_essl3 = 0;
resources->NV_EGL_stream_consumer_external = 0;
resources->ARB_texture_rectangle = 0;
resources->EXT_blend_func_extended = 0;
resources->EXT_draw_buffers = 0;

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

@ -201,6 +201,7 @@ int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunctio
switch (textureFunction.sampler)
{
case EbtSampler2D:
case EbtSamplerExternalOES:
hlslCoords = 2;
break;
case EbtSamplerCube:
@ -275,6 +276,7 @@ void OutputTextureFunctionArgumentList(TInfoSinkBase &out,
switch (textureFunction.sampler)
{
case EbtSampler2D:
case EbtSamplerExternalOES:
out << "sampler2D s";
break;
case EbtSamplerCube:
@ -790,6 +792,7 @@ void OutputTextureSampleFunctionReturnStatement(
switch (textureFunction.sampler)
{
case EbtSampler2D:
case EbtSamplerExternalOES:
out << "tex2D";
break;
case EbtSamplerCube:

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

@ -50,8 +50,8 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &data)
mResources.OES_standard_derivatives = extensions.standardDerivatives;
mResources.EXT_draw_buffers = extensions.drawBuffers;
mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD;
// TODO: disabled until the extension is actually supported.
mResources.OES_EGL_image_external = 0;
mResources.OES_EGL_image_external = extensions.eglImageExternal;
mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3;
mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal;
// TODO: use shader precision caps to determine if high precision is supported?
mResources.FragmentPrecisionHigh = 1;

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

@ -2089,6 +2089,7 @@ void Context::initCaps(GLuint clientVersion)
{
// Disable ES3+ extensions
mExtensions.colorBufferFloat = false;
mExtensions.eglImageExternalEssl3 = false;
}
if (clientVersion > 2)

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

@ -61,7 +61,7 @@ TextureState::TextureState(GLenum target)
swizzleGreen(GL_GREEN),
swizzleBlue(GL_BLUE),
swizzleAlpha(GL_ALPHA),
samplerState(),
samplerState(SamplerState::CreateDefaultForTarget(target)),
baseLevel(0),
maxLevel(1000),
immutableFormat(false),
@ -755,7 +755,7 @@ void Texture::releaseTexImageInternal()
Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
{
ASSERT(target == mState.target);
ASSERT(target == GL_TEXTURE_2D);
ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES);
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
@ -847,6 +847,27 @@ bool Texture::computeSamplerCompleteness(const SamplerState &samplerState,
}
}
// From GL_OES_EGL_image_external_essl3: If state is present in a sampler object bound to a
// texture unit that would have been rejected by a call to TexParameter* for the texture bound
// to that unit, the behavior of the implementation is as if the texture were incomplete. For
// example, if TEXTURE_WRAP_S or TEXTURE_WRAP_T is set to anything but CLAMP_TO_EDGE on the
// sampler object bound to a texture unit and the texture bound to that unit is an external
// texture, the texture will be considered incomplete.
// Sampler object state which does not affect sampling for the type of texture bound to a
// texture unit, such as TEXTURE_WRAP_R for an external texture, does not affect completeness.
if (mState.target == GL_TEXTURE_EXTERNAL_OES)
{
if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE)
{
return false;
}
if (samplerState.minFilter != GL_LINEAR && samplerState.minFilter != GL_NEAREST)
{
return false;
}
}
// OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
// The internalformat specified for the texture arrays is a sized internal depth or
// depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-

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

@ -53,6 +53,23 @@ SamplerState::SamplerState()
{
}
// static
SamplerState SamplerState::CreateDefaultForTarget(GLenum target)
{
SamplerState state;
// According to OES_EGL_image_external: For external textures, the default min filter is
// GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE.
if (target == GL_TEXTURE_EXTERNAL_OES)
{
state.minFilter = GL_LINEAR;
state.wrapS = GL_CLAMP_TO_EDGE;
state.wrapT = GL_CLAMP_TO_EDGE;
}
return state;
}
static void MinMax(int a, int b, int *minimum, int *maximum)
{
if (a < b)

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

@ -194,6 +194,7 @@ struct DepthStencilState
struct SamplerState
{
SamplerState();
static SamplerState CreateDefaultForTarget(GLenum target);
GLenum minFilter;
GLenum magFilter;

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

@ -3178,21 +3178,17 @@ void TextureD3D_2DArray::markAllImagesDirty()
TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer)
: TextureD3D(state, renderer)
{
mImage = renderer->createImage();
}
TextureD3D_External::~TextureD3D_External()
{
SafeDelete(mImage);
SafeDelete(mTexStorage);
}
ImageD3D *TextureD3D_External::getImage(const gl::ImageIndex &index) const
{
// External images only have one mipmap level
ASSERT(index.type == GL_TEXTURE_EXTERNAL_OES);
ASSERT(index.mipIndex == 0);
return mImage;
UNREACHABLE();
return nullptr;
}
GLsizei TextureD3D_External::getLayerCount(int level) const
@ -3200,29 +3196,6 @@ GLsizei TextureD3D_External::getLayerCount(int level) const
return 1;
}
GLsizei TextureD3D_External::getWidth(GLint level) const
{
ASSERT(level == 0);
return mImage->getWidth();
}
GLsizei TextureD3D_External::getHeight(GLint level) const
{
ASSERT(level == 0);
return mImage->getHeight();
}
GLenum TextureD3D_External::getInternalFormat(GLint level) const
{
ASSERT(level == 0);
return mImage->getInternalFormat();
}
bool TextureD3D_External::isDepth(GLint level) const
{
return false;
}
gl::Error TextureD3D_External::setImage(GLenum target,
size_t imageLevel,
GLenum internalFormat,
@ -3308,15 +3281,11 @@ gl::Error TextureD3D_External::setImageExternal(GLenum target,
{
ASSERT(target == GL_TEXTURE_EXTERNAL_OES);
// If the strean is null, the external image is unbound and we release the storage
if (stream == nullptr)
SafeDelete(mTexStorage);
// If the stream is null, the external image is unbound and we release the storage
if (stream != nullptr)
{
SafeDelete(mTexStorage);
mTexStorage = nullptr;
}
else
{
SafeDelete(mTexStorage);
mTexStorage = mRenderer->createTextureStorageExternal(stream, desc);
}
@ -3335,8 +3304,12 @@ void TextureD3D_External::releaseTexImage()
gl::Error TextureD3D_External::setEGLImageTarget(GLenum target, egl::Image *image)
{
UNREACHABLE();
return gl::Error(GL_INVALID_OPERATION);
EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
SafeDelete(mTexStorage);
mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d);
return gl::NoError();
}
void TextureD3D_External::initMipmapsImages()
@ -3350,19 +3323,9 @@ gl::Error TextureD3D_External::getRenderTarget(const gl::ImageIndex &index, Rend
return gl::Error(GL_INVALID_OPERATION);
}
bool TextureD3D_External::isValidLevel(int level) const
{
return (level == 0);
}
bool TextureD3D_External::isLevelComplete(int level) const
{
return (level == 0) ? (mTexStorage != nullptr) : false;
}
bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const
{
return isLevelComplete(index.mipIndex);
return (index.mipIndex == 0) ? (mTexStorage != nullptr) : false;
}
gl::Error TextureD3D_External::initializeStorage(bool renderTarget)
@ -3393,20 +3356,6 @@ gl::Error TextureD3D_External::updateStorage()
return gl::Error(GL_NO_ERROR);
}
gl::Error TextureD3D_External::updateStorageLevel(int level)
{
UNREACHABLE();
return gl::Error(GL_NO_ERROR);
}
void TextureD3D_External::redefineImage(size_t level,
GLenum internalformat,
const gl::Extents &size,
bool forceRelease)
{
UNREACHABLE();
}
gl::ImageIndexIterator TextureD3D_External::imageIterator() const
{
return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());

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

@ -413,11 +413,6 @@ class TextureD3D_External : public TextureD3D
ImageD3D *getImage(const gl::ImageIndex &index) const override;
GLsizei getLayerCount(int level) const override;
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isDepth(GLint level) const;
gl::Error setImage(GLenum target,
size_t level,
GLenum internalFormat,
@ -492,18 +487,7 @@ class TextureD3D_External : public TextureD3D
gl::Error updateStorage() override;
void initMipmapsImages() override;
bool isValidLevel(int level) const;
bool isLevelComplete(int level) const;
bool isImageComplete(const gl::ImageIndex &index) const override;
gl::Error updateStorageLevel(int level);
void redefineImage(size_t level,
GLenum internalformat,
const gl::Extents &size,
bool forceRelease);
ImageD3D *mImage;
};
}

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

@ -1231,6 +1231,8 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
extensions->fboRenderMipmap = false;
extensions->debugMarker = true;
extensions->eglImage = true;
extensions->eglImageExternal = true;
extensions->eglImageExternalEssl3 = true;
extensions->eglStreamConsumerExternal = true;
extensions->unpackSubimage = true;
extensions->packSubimage = true;

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

@ -69,6 +69,8 @@ TextureImpl *Context9::createTexture(const gl::TextureState &state)
return new TextureD3D_2D(state, mRenderer);
case GL_TEXTURE_CUBE_MAP:
return new TextureD3D_Cube(state, mRenderer);
case GL_TEXTURE_EXTERNAL_OES:
return new TextureD3D_External(state, mRenderer);
default:
UNREACHABLE();
}

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

@ -1657,6 +1657,7 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
{
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_EXTERNAL_OES:
break;
case GL_BOOL:
case GL_BOOL_VEC2:

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

@ -590,6 +590,7 @@ void GenerateCaps(IDirect3D9 *d3d9,
extensions->colorBufferFloat = false;
extensions->debugMarker = true;
extensions->eglImage = true;
extensions->eglImageExternal = true;
extensions->unpackSubimage = true;
extensions->packSubimage = true;
extensions->vertexArrayObject = true;

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

@ -857,13 +857,18 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pnam
case GL_TEXTURE_COMPARE_FUNC:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
// ES3 texture paramters are not supported on external textures as the extension is
// written against ES2.
if (context->getClientVersion() < 3 || target == GL_TEXTURE_EXTERNAL_OES)
if (context->getClientVersion() < 3)
{
context->handleError(Error(GL_INVALID_ENUM));
return false;
}
if (target == GL_TEXTURE_EXTERNAL_OES && !context->getExtensions().eglImageExternalEssl3)
{
context->handleError(Error(GL_INVALID_ENUM,
"ES3 texture parameters are not available without "
"GL_OES_EGL_image_external_essl3."));
return false;
}
break;
default: break;
@ -1014,16 +1019,20 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pnam
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
if (target == GL_TEXTURE_EXTERNAL_OES)
if (param < 0)
{
// This is not specified, but in line with the spirit of OES_EGL_image_external spec,
// which generally forbids setting mipmap related parameters on external textures.
context->handleError(
Error(GL_INVALID_OPERATION,
"Setting the base level or max level of external textures not supported"));
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
if (target == GL_TEXTURE_EXTERNAL_OES && param != 0)
{
context->handleError(
Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
return false;
}
return true;
case GL_TEXTURE_MAX_LEVEL:
if (param < 0)
{
context->handleError(Error(GL_INVALID_VALUE));
@ -2398,6 +2407,20 @@ bool ValidateEGLImageTargetTexture2DOES(Context *context,
switch (target)
{
case GL_TEXTURE_2D:
if (!context->getExtensions().eglImage)
{
context->handleError(Error(
GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
}
break;
case GL_TEXTURE_EXTERNAL_OES:
if (!context->getExtensions().eglImageExternal)
{
context->handleError(Error(
GL_INVALID_ENUM,
"GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
}
break;
default:

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

@ -1997,7 +1997,8 @@ bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
}
break;
case GL_TEXTURE_EXTERNAL_OES:
if (!context->getExtensions().eglStreamConsumerExternal)
if (!context->getExtensions().eglImageExternal &&
!context->getExtensions().eglStreamConsumerExternal)
{
context->handleError(
Error(GL_INVALID_ENUM, "External texture extension not enabled"));

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

@ -2279,7 +2279,7 @@ void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
Context *context = GetValidGlobalContext();
if (context)
{
if (!ValidTextureTarget(context, target))
if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
return;
@ -2434,7 +2434,7 @@ void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
Context *context = GetValidGlobalContext();
if (context)
{
if (!ValidTextureTarget(context, target))
if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
return;

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

@ -358,37 +358,79 @@ TEST_P(EGLStreamTest, StreamProducerTextureNV12End2End)
{
EGLWindow *window = getEGLWindow();
EGLDisplay display = window->getDisplay();
const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
if (strstr(extensionsString, "EGL_ANGLE_stream_producer_d3d_texture_nv12") == nullptr)
if (!eglDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture_nv12"))
{
std::cout << "Stream producer d3d nv12 texture not supported" << std::endl;
return;
}
// Shader setup
const std::string yuvVS =
"attribute highp vec4 position; varying vec2 texcoord; void main(void)\n"
"{\n"
" gl_Position = position;\n"
" texcoord = (position.xy * 0.5) + 0.5;\n"
" texcoord.y = 1.0 - texcoord.y;\n"
"}\n";
bool useESSL3Shaders =
getClientVersion() >= 3 && extensionEnabled("GL_OES_EGL_image_external_essl3");
// yuv to rgb conversion shader using Microsoft's given conversion formulas
const std::string yuvPS =
"#extension GL_NV_EGL_stream_consumer_external : require\n"
"precision highp float; varying vec2 texcoord;\n"
"uniform samplerExternalOES y; uniform samplerExternalOES uv\n;"
"void main(void)\n"
"{\n"
" float c = texture2D(y, texcoord).r - (16.0 / 256.0);\n"
" float d = texture2D(uv, texcoord).r - 0.5;\n"
" float e = texture2D(uv, texcoord).g - 0.5;\n"
" float r = 1.164383 * c + 1.596027 * e;\n"
" float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"
" float b = 1.164383 * c + 2.017232 * d;\n"
" gl_FragColor = vec4(r, g, b, 1.0);\n"
"}\n";
std::string yuvVS, yuvPS;
if (useESSL3Shaders)
{
yuvVS =
"#version 300 es\n"
"in highp vec4 position;\n"
"out vec2 texcoord;\n"
"void main(void)\n"
"{\n"
" gl_Position = position;\n"
" texcoord = (position.xy * 0.5) + 0.5;\n"
" texcoord.y = 1.0 - texcoord.y;\n"
"}\n";
yuvPS =
"#version 300 es\n"
"#extension GL_OES_EGL_image_external_essl3 : require\n"
"#extension GL_NV_EGL_stream_consumer_external : require\n"
"precision highp float;\n"
"in vec2 texcoord;\n"
"out vec4 color;\n"
"uniform samplerExternalOES y;\n"
"uniform samplerExternalOES uv\n;"
"void main(void)\n"
"{\n"
" float c = texture(y, texcoord).r - (16.0 / 256.0);\n"
" float d = texture(uv, texcoord).r - 0.5;\n"
" float e = texture(uv, texcoord).g - 0.5;\n"
" float r = 1.164383 * c + 1.596027 * e;\n"
" float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"
" float b = 1.164383 * c + 2.017232 * d;\n"
" color = vec4(r, g, b, 1.0);\n"
"}\n";
}
else
{
yuvVS =
"attribute highp vec4 position;\n"
"varying vec2 texcoord;\n"
"void main(void)\n"
"{\n"
" gl_Position = position;\n"
" texcoord = (position.xy * 0.5) + 0.5;\n"
" texcoord.y = 1.0 - texcoord.y;\n"
"}\n";
yuvPS =
"#extension GL_NV_EGL_stream_consumer_external : require\n"
"precision highp float;\n"
"varying vec2 texcoord;\n"
"uniform samplerExternalOES y;\n"
"uniform samplerExternalOES uv\n;"
"void main(void)\n"
"{\n"
" float c = texture2D(y, texcoord).r - (16.0 / 256.0);\n"
" float d = texture2D(uv, texcoord).r - 0.5;\n"
" float e = texture2D(uv, texcoord).g - 0.5;\n"
" float r = 1.164383 * c + 1.596027 * e;\n"
" float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"
" float b = 1.164383 * c + 2.017232 * d;\n"
" gl_FragColor = vec4(r, g, b, 1.0);\n"
"}\n";
}
GLuint program = CompileProgram(yuvVS, yuvPS);
ASSERT_NE(0u, program);
GLuint yUniform = glGetUniformLocation(program, "y");

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

@ -40,6 +40,18 @@ class ImageTest : public ANGLETest
" texcoord = (position.xy * 0.5) + 0.5;\n"
" texcoord.y = 1.0 - texcoord.y;\n"
"}\n";
const std::string vsESSL3Source =
"#version 300 es\n"
"precision highp float;\n"
"in vec4 position;\n"
"out vec2 texcoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
" texcoord = (position.xy * 0.5) + 0.5;\n"
" texcoord.y = 1.0 - texcoord.y;\n"
"}\n";
const std::string textureFSSource =
"precision highp float;\n"
@ -50,6 +62,28 @@ class ImageTest : public ANGLETest
"{\n"
" gl_FragColor = texture2D(tex, texcoord);\n"
"}\n";
const std::string textureExternalFSSource =
"#extension GL_OES_EGL_image_external : require\n"
"precision highp float;\n"
"uniform samplerExternalOES tex;\n"
"varying vec2 texcoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(tex, texcoord);\n"
"}\n";
const std::string textureExternalESSL3FSSource =
"#version 300 es\n"
"#extension GL_OES_EGL_image_external_essl3 : require\n"
"precision highp float;\n"
"uniform samplerExternalOES tex;\n"
"in vec2 texcoord;\n"
"out vec4 color;"
"\n"
"void main()\n"
"{\n"
" color = texture(tex, texcoord);\n"
"}\n";
mTextureProgram = CompileProgram(vsSource, textureFSSource);
if (mTextureProgram == 0)
@ -59,6 +93,24 @@ class ImageTest : public ANGLETest
mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
if (extensionEnabled("GL_OES_EGL_image_external"))
{
mTextureExternalProgram = CompileProgram(vsSource, textureExternalFSSource);
ASSERT_NE(0u, mTextureExternalProgram) << "shader compilation failed.";
mTextureExternalUniformLocation = glGetUniformLocation(mTextureExternalProgram, "tex");
}
if (extensionEnabled("GL_OES_EGL_image_external_essl3"))
{
mTextureExternalESSL3Program =
CompileProgram(vsESSL3Source, textureExternalESSL3FSSource);
ASSERT_NE(0u, mTextureExternalESSL3Program) << "shader compilation failed.";
mTextureExternalESSL3UniformLocation =
glGetUniformLocation(mTextureExternalESSL3Program, "tex");
}
eglCreateImageKHR =
reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
eglDestroyImageKHR =
@ -69,9 +121,11 @@ class ImageTest : public ANGLETest
void TearDown() override
{
ANGLETest::TearDown();
glDeleteProgram(mTextureProgram);
glDeleteProgram(mTextureExternalProgram);
glDeleteProgram(mTextureExternalESSL3Program);
ANGLETest::TearDown();
}
void createEGLImage2DTextureSource(size_t width,
@ -245,6 +299,23 @@ class ImageTest : public ANGLETest
*outTargetTexture = target;
}
void createEGLImageTargetTextureExternal(EGLImageKHR image, GLuint *outTargetTexture)
{
// Create a target texture from the image
GLuint target;
glGenTextures(1, &target);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
// Disable mipmapping
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
*outTargetTexture = target;
}
void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint *outTargetRenderbuffer)
{
// Create a target texture from the image
@ -258,19 +329,41 @@ class ImageTest : public ANGLETest
*outTargetRenderbuffer = target;
}
void verifyResults2D(GLuint texture, GLubyte data[4])
void verifyResultsTexture(GLuint texture,
GLubyte data[4],
GLenum textureTarget,
GLuint program,
GLuint textureUniform)
{
// Draw a quad with the target texture
glUseProgram(mTextureProgram);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(mTextureUniformLocation, 0);
glUseProgram(program);
glBindTexture(textureTarget, texture);
glUniform1i(textureUniform, 0);
drawQuad(mTextureProgram, "position", 0.5f);
drawQuad(program, "position", 0.5f);
// Expect that the rendered quad has the same color as the source texture
EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
}
void verifyResults2D(GLuint texture, GLubyte data[4])
{
verifyResultsTexture(texture, data, GL_TEXTURE_2D, mTextureProgram,
mTextureUniformLocation);
}
void verifyResultsExternal(GLuint texture, GLubyte data[4])
{
verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalProgram,
mTextureExternalUniformLocation);
}
void verifyResultsExternalESSL3(GLuint texture, GLubyte data[4])
{
verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalESSL3Program,
mTextureExternalESSL3UniformLocation);
}
void verifyResultsRenderbuffer(GLuint renderbuffer, GLubyte data[4])
{
// Bind the renderbuffer to a framebuffer
@ -298,10 +391,20 @@ class ImageTest : public ANGLETest
GLuint mTextureProgram;
GLint mTextureUniformLocation;
GLuint mTextureExternalProgram = 0;
GLint mTextureExternalUniformLocation = -1;
GLuint mTextureExternalESSL3Program = 0;
GLint mTextureExternalESSL3UniformLocation = -1;
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
};
class ImageTestES3 : public ImageTest
{
};
// Check validation from the EGL_KHR_image_base extension
TEST_P(ImageTest, ValidationImageBase)
{
@ -755,17 +858,114 @@ TEST_P(ImageTest, ValidationGLEGLImage)
// Check validation from the GL_OES_EGL_image_external extension
TEST_P(ImageTest, ValidationGLEGLImageExternal)
{
// This extension is not implemented anywhere yet. This makes sure that it is tested once it is
// added.
EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image_external"));
if (!extensionEnabled("GL_OES_EGL_image_external"))
{
std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
<< std::endl;
return;
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
// In the initial state of a TEXTURE_EXTERNAL_OES texture object, the value assigned to
// TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER is LINEAR, and the s and t wrap modes are both set
// to CLAMP_TO_EDGE
auto getTexParam = [](GLenum target, GLenum pname)
{
GLint value = 0;
glGetTexParameteriv(target, pname, &value);
EXPECT_GL_NO_ERROR();
return value;
};
EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER));
EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER));
EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S));
EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T));
// "When <target> is TEXTURE_EXTERNAL_OES only NEAREST and LINEAR are accepted as
// TEXTURE_MIN_FILTER, only CLAMP_TO_EDGE is accepted as TEXTURE_WRAP_S and TEXTURE_WRAP_T, and
// only FALSE is accepted as GENERATE_MIPMAP. Attempting to set other values for
// TEXTURE_MIN_FILTER, TEXTURE_WRAP_S, TEXTURE_WRAP_T, or GENERATE_MIPMAP will result in an
// INVALID_ENUM error.
GLenum validMinFilters[]{
GL_NEAREST, GL_LINEAR,
};
for (auto minFilter : validMinFilters)
{
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
EXPECT_GL_NO_ERROR();
}
GLenum invalidMinFilters[]{
GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_NEAREST,
};
for (auto minFilter : invalidMinFilters)
{
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
GLenum validWrapModes[]{
GL_CLAMP_TO_EDGE,
};
for (auto minFilter : validWrapModes)
{
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, minFilter);
EXPECT_GL_NO_ERROR();
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, minFilter);
EXPECT_GL_NO_ERROR();
}
GLenum invalidWrapModes[]{
GL_REPEAT, GL_MIRRORED_REPEAT,
};
for (auto minFilter : invalidWrapModes)
{
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, minFilter);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, minFilter);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
// When <target> is set to TEXTURE_EXTERNAL_OES, GenerateMipmap always fails and generates an
// INVALID_ENUM error.
glGenerateMipmap(GL_TEXTURE_EXTERNAL_OES);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glDeleteTextures(1, &texture);
}
// Check validation from the GL_OES_EGL_image_external_essl3 extension
TEST_P(ImageTest, ValidationGLEGLImageExternalESSL3)
{
// This extension is not implemented anywhere yet. This makes sure that it is tested once it is
// added.
EXPECT_FALSE(extensionEnabled("GL_OES_EGL_image_external_essl3"));
if (!extensionEnabled("GL_OES_EGL_image_external_essl3"))
{
std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
<< std::endl;
return;
}
// Make sure this extension is not exposed without ES3.
ASSERT_GE(getClientVersion(), 3);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
// It is an INVALID_OPERATION error to set the TEXTURE_BASE_LEVEL to a value other than zero.
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 1);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 10);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 0);
EXPECT_GL_NO_ERROR();
glDeleteTextures(1, &texture);
}
TEST_P(ImageTest, Source2DTarget2D)
@ -834,6 +1034,74 @@ TEST_P(ImageTest, Source2DTargetRenderbuffer)
glDeleteRenderbuffers(1, &target);
}
TEST_P(ImageTest, Source2DTargetExternal)
{
EGLWindow *window = getEGLWindow();
if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
{
std::cout
<< "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
"EGL_KHR_gl_texture_2D_image is not available."
<< std::endl;
return;
}
GLubyte data[4] = {255, 0, 255, 255};
// Create the Image
GLuint source;
EGLImageKHR image;
createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target renderbuffer has the same color as the source texture
verifyResultsExternal(target, data);
// Clean up
glDeleteTextures(1, &source);
eglDestroyImageKHR(window->getDisplay(), image);
glDeleteRenderbuffers(1, &target);
}
TEST_P(ImageTestES3, Source2DTargetExternalESSL3)
{
EGLWindow *window = getEGLWindow();
if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
{
std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
"EGL_KHR_image_base or "
"EGL_KHR_gl_texture_2D_image is not available."
<< std::endl;
return;
}
GLubyte data[4] = {255, 0, 255, 255};
// Create the Image
GLuint source;
EGLImageKHR image;
createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target renderbuffer has the same color as the source texture
verifyResultsExternalESSL3(target, data);
// Clean up
glDeleteTextures(1, &source);
eglDestroyImageKHR(window->getDisplay(), image);
glDeleteRenderbuffers(1, &target);
}
TEST_P(ImageTest, SourceCubeTarget2D)
{
EGLWindow *window = getEGLWindow();
@ -916,6 +1184,92 @@ TEST_P(ImageTest, SourceCubeTargetRenderbuffer)
}
}
// Test cubemap -> external texture EGL images.
TEST_P(ImageTest, SourceCubeTargetExternal)
{
EGLWindow *window = getEGLWindow();
if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
{
std::cout
<< "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
"EGL_KHR_gl_texture_cubemap_image is not available."
<< std::endl;
return;
}
GLubyte data[24] = {
255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
};
for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
{
// Create the Image
GLuint source;
EGLImageKHR image;
createEGLImageCubemapTextureSource(
1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target texture has the same color as the source texture
verifyResultsExternal(target, &data[faceIdx * 4]);
// Clean up
glDeleteTextures(1, &source);
eglDestroyImageKHR(window->getDisplay(), image);
glDeleteRenderbuffers(1, &target);
}
}
// Test cubemap -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3)
{
EGLWindow *window = getEGLWindow();
if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
{
std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
"EGL_KHR_image_base or "
"EGL_KHR_gl_texture_cubemap_image is not available."
<< std::endl;
return;
}
GLubyte data[24] = {
255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
};
for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
{
// Create the Image
GLuint source;
EGLImageKHR image;
createEGLImageCubemapTextureSource(
1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target texture has the same color as the source texture
verifyResultsExternalESSL3(target, &data[faceIdx * 4]);
// Clean up
glDeleteTextures(1, &source);
eglDestroyImageKHR(window->getDisplay(), image);
glDeleteRenderbuffers(1, &target);
}
}
TEST_P(ImageTest, Source3DTargetTexture)
{
EGLWindow *window = getEGLWindow();
@ -1008,6 +1362,102 @@ TEST_P(ImageTest, Source3DTargetRenderbuffer)
}
}
// Test 3D -> external texture EGL images.
TEST_P(ImageTest, Source3DTargetExternal)
{
EGLWindow *window = getEGLWindow();
if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
{
std::cout
<< "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
"EGL_KHR_gl_texture_3D_image is not available."
<< std::endl;
return;
}
if (getClientVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
{
std::cout << "Test skipped because 3D textures are not available." << std::endl;
return;
}
const size_t depth = 2;
GLubyte data[4 * depth] = {
255, 0, 255, 255, 255, 255, 0, 255,
};
for (size_t layer = 0; layer < depth; layer++)
{
// Create the Image
GLuint source;
EGLImageKHR image;
createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
&image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target renderbuffer has the same color as the source texture
verifyResultsExternal(target, &data[layer * 4]);
// Clean up
glDeleteTextures(1, &source);
eglDestroyImageKHR(window->getDisplay(), image);
glDeleteTextures(1, &target);
}
}
// Test 3D -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3, Source3DTargetExternalESSL3)
{
EGLWindow *window = getEGLWindow();
if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
{
std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
"EGL_KHR_image_base or "
"EGL_KHR_gl_texture_3D_image is not available."
<< std::endl;
return;
}
if (getClientVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
{
std::cout << "Test skipped because 3D textures are not available." << std::endl;
return;
}
const size_t depth = 2;
GLubyte data[4 * depth] = {
255, 0, 255, 255, 255, 255, 0, 255,
};
for (size_t layer = 0; layer < depth; layer++)
{
// Create the Image
GLuint source;
EGLImageKHR image;
createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
&image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target renderbuffer has the same color as the source texture
verifyResultsExternalESSL3(target, &data[layer * 4]);
// Clean up
glDeleteTextures(1, &source);
eglDestroyImageKHR(window->getDisplay(), image);
glDeleteTextures(1, &target);
}
}
TEST_P(ImageTest, SourceRenderbufferTargetTexture)
{
EGLWindow *window = getEGLWindow();
@ -1041,6 +1491,76 @@ TEST_P(ImageTest, SourceRenderbufferTargetTexture)
glDeleteTextures(1, &target);
}
// Test renderbuffer -> external texture EGL images.
TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal)
{
EGLWindow *window = getEGLWindow();
if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
{
std::cout
<< "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
"EGL_KHR_gl_renderbuffer_image is not available."
<< std::endl;
return;
}
GLubyte data[4] = {255, 0, 255, 255};
// Create the Image
GLuint source;
EGLImageKHR image;
createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target texture has the same color as the source texture
verifyResultsExternal(target, data);
// Clean up
glDeleteRenderbuffers(1, &source);
eglDestroyImageKHR(window->getDisplay(), image);
glDeleteTextures(1, &target);
}
// Test renderbuffer -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3)
{
EGLWindow *window = getEGLWindow();
if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
!eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
{
std::cout
<< "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
"EGL_KHR_gl_renderbuffer_image is not available."
<< std::endl;
return;
}
GLubyte data[4] = {255, 0, 255, 255};
// Create the Image
GLuint source;
EGLImageKHR image;
createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
// Create the target
GLuint target;
createEGLImageTargetTextureExternal(image, &target);
// Expect that the target texture has the same color as the source texture
verifyResultsExternalESSL3(target, data);
// Clean up
glDeleteRenderbuffers(1, &source);
eglDestroyImageKHR(window->getDisplay(), image);
glDeleteTextures(1, &target);
}
TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer)
{
EGLWindow *window = getEGLWindow();
@ -1449,4 +1969,5 @@ ANGLE_INSTANTIATE_TEST(ImageTest,
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(ImageTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
}