Commit b66a9097 by Geoff Lang Committed by Commit Bot

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/344734Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent a0d3aa41
...@@ -48,7 +48,7 @@ typedef unsigned int GLenum; ...@@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 145 #define ANGLE_SH_VERSION 146
typedef enum { typedef enum {
SH_GLES2_SPEC = 0x8B40, SH_GLES2_SPEC = 0x8B40,
...@@ -255,6 +255,7 @@ typedef struct ...@@ -255,6 +255,7 @@ typedef struct
// Set to 1 to enable the extension, else 0. // Set to 1 to enable the extension, else 0.
int OES_standard_derivatives; int OES_standard_derivatives;
int OES_EGL_image_external; int OES_EGL_image_external;
int OES_EGL_image_external_essl3;
int NV_EGL_stream_consumer_external; int NV_EGL_stream_consumer_external;
int ARB_texture_rectangle; int ARB_texture_rectangle;
int EXT_blend_func_extended; int EXT_blend_func_extended;
......
...@@ -480,6 +480,8 @@ void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType) ...@@ -480,6 +480,8 @@ void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
void TCompiler::setResourceString() void TCompiler::setResourceString()
{ {
std::ostringstream strstream; std::ostringstream strstream;
// clang-format off
strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
<< ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
<< ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
...@@ -490,6 +492,8 @@ void TCompiler::setResourceString() ...@@ -490,6 +492,8 @@ void TCompiler::setResourceString()
<< ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
<< ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
<< ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external << ":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 << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
<< ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
<< ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
...@@ -509,6 +513,7 @@ void TCompiler::setResourceString() ...@@ -509,6 +513,7 @@ void TCompiler::setResourceString()
<< ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
<< ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision; << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision;
// clang-format on
builtInResourcesString = strstream.str(); builtInResourcesString = strstream.str();
} }
......
...@@ -315,6 +315,17 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR ...@@ -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", gsamplerCube, float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, 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) if (type == GL_FRAGMENT_SHADER)
{ {
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1);
...@@ -324,6 +335,18 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR ...@@ -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, float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, 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); const TType *sampler2DShadow = TCache::getType(EbtSampler2DShadow);
...@@ -351,6 +374,13 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR ...@@ -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, int2, "textureSize", samplerCubeShadow, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, 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) if (type == GL_FRAGMENT_SHADER)
{ {
symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdx, genType, "dFdx", genType); symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdx, genType, "dFdx", genType);
...@@ -403,6 +433,14 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR ...@@ -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", gsampler3D, int3, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2DArray, 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", gsampler2D, int2, int1, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1, int3); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1, int3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3, int1, int2); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3, int1, int2);
...@@ -594,6 +632,8 @@ void InitExtensionBehavior(const ShBuiltInResources& resources, ...@@ -594,6 +632,8 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
extBehavior["GL_OES_standard_derivatives"] = EBhUndefined; extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
if (resources.OES_EGL_image_external) if (resources.OES_EGL_image_external)
extBehavior["GL_OES_EGL_image_external"] = EBhUndefined; 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) if (resources.NV_EGL_stream_consumer_external)
extBehavior["GL_NV_EGL_stream_consumer_external"] = EBhUndefined; extBehavior["GL_NV_EGL_stream_consumer_external"] = EBhUndefined;
if (resources.ARB_texture_rectangle) if (resources.ARB_texture_rectangle)
......
...@@ -148,6 +148,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) ...@@ -148,6 +148,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
// Extensions. // Extensions.
resources->OES_standard_derivatives = 0; resources->OES_standard_derivatives = 0;
resources->OES_EGL_image_external = 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->ARB_texture_rectangle = 0;
resources->EXT_blend_func_extended = 0; resources->EXT_blend_func_extended = 0;
resources->EXT_draw_buffers = 0; resources->EXT_draw_buffers = 0;
......
...@@ -201,6 +201,7 @@ int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunctio ...@@ -201,6 +201,7 @@ int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunctio
switch (textureFunction.sampler) switch (textureFunction.sampler)
{ {
case EbtSampler2D: case EbtSampler2D:
case EbtSamplerExternalOES:
hlslCoords = 2; hlslCoords = 2;
break; break;
case EbtSamplerCube: case EbtSamplerCube:
...@@ -275,6 +276,7 @@ void OutputTextureFunctionArgumentList(TInfoSinkBase &out, ...@@ -275,6 +276,7 @@ void OutputTextureFunctionArgumentList(TInfoSinkBase &out,
switch (textureFunction.sampler) switch (textureFunction.sampler)
{ {
case EbtSampler2D: case EbtSampler2D:
case EbtSamplerExternalOES:
out << "sampler2D s"; out << "sampler2D s";
break; break;
case EbtSamplerCube: case EbtSamplerCube:
...@@ -790,6 +792,7 @@ void OutputTextureSampleFunctionReturnStatement( ...@@ -790,6 +792,7 @@ void OutputTextureSampleFunctionReturnStatement(
switch (textureFunction.sampler) switch (textureFunction.sampler)
{ {
case EbtSampler2D: case EbtSampler2D:
case EbtSamplerExternalOES:
out << "tex2D"; out << "tex2D";
break; break;
case EbtSamplerCube: case EbtSamplerCube:
......
...@@ -50,8 +50,8 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &data) ...@@ -50,8 +50,8 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &data)
mResources.OES_standard_derivatives = extensions.standardDerivatives; mResources.OES_standard_derivatives = extensions.standardDerivatives;
mResources.EXT_draw_buffers = extensions.drawBuffers; mResources.EXT_draw_buffers = extensions.drawBuffers;
mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD; mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD;
// TODO: disabled until the extension is actually supported. mResources.OES_EGL_image_external = extensions.eglImageExternal;
mResources.OES_EGL_image_external = 0; mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3;
mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal; mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal;
// TODO: use shader precision caps to determine if high precision is supported? // TODO: use shader precision caps to determine if high precision is supported?
mResources.FragmentPrecisionHigh = 1; mResources.FragmentPrecisionHigh = 1;
......
...@@ -2089,6 +2089,7 @@ void Context::initCaps(GLuint clientVersion) ...@@ -2089,6 +2089,7 @@ void Context::initCaps(GLuint clientVersion)
{ {
// Disable ES3+ extensions // Disable ES3+ extensions
mExtensions.colorBufferFloat = false; mExtensions.colorBufferFloat = false;
mExtensions.eglImageExternalEssl3 = false;
} }
if (clientVersion > 2) if (clientVersion > 2)
......
...@@ -61,7 +61,7 @@ TextureState::TextureState(GLenum target) ...@@ -61,7 +61,7 @@ TextureState::TextureState(GLenum target)
swizzleGreen(GL_GREEN), swizzleGreen(GL_GREEN),
swizzleBlue(GL_BLUE), swizzleBlue(GL_BLUE),
swizzleAlpha(GL_ALPHA), swizzleAlpha(GL_ALPHA),
samplerState(), samplerState(SamplerState::CreateDefaultForTarget(target)),
baseLevel(0), baseLevel(0),
maxLevel(1000), maxLevel(1000),
immutableFormat(false), immutableFormat(false),
...@@ -755,7 +755,7 @@ void Texture::releaseTexImageInternal() ...@@ -755,7 +755,7 @@ void Texture::releaseTexImageInternal()
Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget) Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
{ {
ASSERT(target == mState.target); 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 // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal(); releaseTexImageInternal();
...@@ -847,6 +847,27 @@ bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, ...@@ -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: // 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 // 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_- // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
......
...@@ -53,6 +53,23 @@ SamplerState::SamplerState() ...@@ -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) static void MinMax(int a, int b, int *minimum, int *maximum)
{ {
if (a < b) if (a < b)
......
...@@ -194,6 +194,7 @@ struct DepthStencilState ...@@ -194,6 +194,7 @@ struct DepthStencilState
struct SamplerState struct SamplerState
{ {
SamplerState(); SamplerState();
static SamplerState CreateDefaultForTarget(GLenum target);
GLenum minFilter; GLenum minFilter;
GLenum magFilter; GLenum magFilter;
......
...@@ -3178,21 +3178,17 @@ void TextureD3D_2DArray::markAllImagesDirty() ...@@ -3178,21 +3178,17 @@ void TextureD3D_2DArray::markAllImagesDirty()
TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer) TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer)
: TextureD3D(state, renderer) : TextureD3D(state, renderer)
{ {
mImage = renderer->createImage();
} }
TextureD3D_External::~TextureD3D_External() TextureD3D_External::~TextureD3D_External()
{ {
SafeDelete(mImage);
SafeDelete(mTexStorage); SafeDelete(mTexStorage);
} }
ImageD3D *TextureD3D_External::getImage(const gl::ImageIndex &index) const ImageD3D *TextureD3D_External::getImage(const gl::ImageIndex &index) const
{ {
// External images only have one mipmap level UNREACHABLE();
ASSERT(index.type == GL_TEXTURE_EXTERNAL_OES); return nullptr;
ASSERT(index.mipIndex == 0);
return mImage;
} }
GLsizei TextureD3D_External::getLayerCount(int level) const GLsizei TextureD3D_External::getLayerCount(int level) const
...@@ -3200,29 +3196,6 @@ GLsizei TextureD3D_External::getLayerCount(int level) const ...@@ -3200,29 +3196,6 @@ GLsizei TextureD3D_External::getLayerCount(int level) const
return 1; 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, gl::Error TextureD3D_External::setImage(GLenum target,
size_t imageLevel, size_t imageLevel,
GLenum internalFormat, GLenum internalFormat,
...@@ -3308,15 +3281,11 @@ gl::Error TextureD3D_External::setImageExternal(GLenum target, ...@@ -3308,15 +3281,11 @@ gl::Error TextureD3D_External::setImageExternal(GLenum target,
{ {
ASSERT(target == GL_TEXTURE_EXTERNAL_OES); ASSERT(target == GL_TEXTURE_EXTERNAL_OES);
// If the strean is null, the external image is unbound and we release the storage SafeDelete(mTexStorage);
if (stream == nullptr)
{ // If the stream is null, the external image is unbound and we release the storage
SafeDelete(mTexStorage); if (stream != nullptr)
mTexStorage = nullptr;
}
else
{ {
SafeDelete(mTexStorage);
mTexStorage = mRenderer->createTextureStorageExternal(stream, desc); mTexStorage = mRenderer->createTextureStorageExternal(stream, desc);
} }
...@@ -3335,8 +3304,12 @@ void TextureD3D_External::releaseTexImage() ...@@ -3335,8 +3304,12 @@ void TextureD3D_External::releaseTexImage()
gl::Error TextureD3D_External::setEGLImageTarget(GLenum target, egl::Image *image) gl::Error TextureD3D_External::setEGLImageTarget(GLenum target, egl::Image *image)
{ {
UNREACHABLE(); EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
return gl::Error(GL_INVALID_OPERATION);
SafeDelete(mTexStorage);
mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d);
return gl::NoError();
} }
void TextureD3D_External::initMipmapsImages() void TextureD3D_External::initMipmapsImages()
...@@ -3350,19 +3323,9 @@ gl::Error TextureD3D_External::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -3350,19 +3323,9 @@ gl::Error TextureD3D_External::getRenderTarget(const gl::ImageIndex &index, Rend
return gl::Error(GL_INVALID_OPERATION); 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 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) gl::Error TextureD3D_External::initializeStorage(bool renderTarget)
...@@ -3393,20 +3356,6 @@ gl::Error TextureD3D_External::updateStorage() ...@@ -3393,20 +3356,6 @@ gl::Error TextureD3D_External::updateStorage()
return gl::Error(GL_NO_ERROR); 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 gl::ImageIndexIterator TextureD3D_External::imageIterator() const
{ {
return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount()); return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
......
...@@ -413,11 +413,6 @@ class TextureD3D_External : public TextureD3D ...@@ -413,11 +413,6 @@ class TextureD3D_External : public TextureD3D
ImageD3D *getImage(const gl::ImageIndex &index) const override; ImageD3D *getImage(const gl::ImageIndex &index) const override;
GLsizei getLayerCount(int level) 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, gl::Error setImage(GLenum target,
size_t level, size_t level,
GLenum internalFormat, GLenum internalFormat,
...@@ -492,18 +487,7 @@ class TextureD3D_External : public TextureD3D ...@@ -492,18 +487,7 @@ class TextureD3D_External : public TextureD3D
gl::Error updateStorage() override; gl::Error updateStorage() override;
void initMipmapsImages() override; void initMipmapsImages() override;
bool isValidLevel(int level) const;
bool isLevelComplete(int level) const;
bool isImageComplete(const gl::ImageIndex &index) const override; 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 ...@@ -1231,6 +1231,8 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
extensions->fboRenderMipmap = false; extensions->fboRenderMipmap = false;
extensions->debugMarker = true; extensions->debugMarker = true;
extensions->eglImage = true; extensions->eglImage = true;
extensions->eglImageExternal = true;
extensions->eglImageExternalEssl3 = true;
extensions->eglStreamConsumerExternal = true; extensions->eglStreamConsumerExternal = true;
extensions->unpackSubimage = true; extensions->unpackSubimage = true;
extensions->packSubimage = true; extensions->packSubimage = true;
......
...@@ -69,6 +69,8 @@ TextureImpl *Context9::createTexture(const gl::TextureState &state) ...@@ -69,6 +69,8 @@ TextureImpl *Context9::createTexture(const gl::TextureState &state)
return new TextureD3D_2D(state, mRenderer); return new TextureD3D_2D(state, mRenderer);
case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP:
return new TextureD3D_Cube(state, mRenderer); return new TextureD3D_Cube(state, mRenderer);
case GL_TEXTURE_EXTERNAL_OES:
return new TextureD3D_External(state, mRenderer);
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -1657,6 +1657,7 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D, ...@@ -1657,6 +1657,7 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
{ {
case GL_SAMPLER_2D: case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE: case GL_SAMPLER_CUBE:
case GL_SAMPLER_EXTERNAL_OES:
break; break;
case GL_BOOL: case GL_BOOL:
case GL_BOOL_VEC2: case GL_BOOL_VEC2:
......
...@@ -590,6 +590,7 @@ void GenerateCaps(IDirect3D9 *d3d9, ...@@ -590,6 +590,7 @@ void GenerateCaps(IDirect3D9 *d3d9,
extensions->colorBufferFloat = false; extensions->colorBufferFloat = false;
extensions->debugMarker = true; extensions->debugMarker = true;
extensions->eglImage = true; extensions->eglImage = true;
extensions->eglImageExternal = true;
extensions->unpackSubimage = true; extensions->unpackSubimage = true;
extensions->packSubimage = true; extensions->packSubimage = true;
extensions->vertexArrayObject = true; extensions->vertexArrayObject = true;
......
...@@ -857,13 +857,18 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pnam ...@@ -857,13 +857,18 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pnam
case GL_TEXTURE_COMPARE_FUNC: case GL_TEXTURE_COMPARE_FUNC:
case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD: case GL_TEXTURE_MAX_LOD:
// ES3 texture paramters are not supported on external textures as the extension is if (context->getClientVersion() < 3)
// written against ES2.
if (context->getClientVersion() < 3 || target == GL_TEXTURE_EXTERNAL_OES)
{ {
context->handleError(Error(GL_INVALID_ENUM)); context->handleError(Error(GL_INVALID_ENUM));
return false; 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; break;
default: break; default: break;
...@@ -1014,16 +1019,20 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pnam ...@@ -1014,16 +1019,20 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pnam
break; break;
case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL: if (param < 0)
if (target == GL_TEXTURE_EXTERNAL_OES) {
context->handleError(Error(GL_INVALID_VALUE));
return false;
}
if (target == GL_TEXTURE_EXTERNAL_OES && 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( context->handleError(
Error(GL_INVALID_OPERATION, Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
"Setting the base level or max level of external textures not supported"));
return false; return false;
} }
return true;
case GL_TEXTURE_MAX_LEVEL:
if (param < 0) if (param < 0)
{ {
context->handleError(Error(GL_INVALID_VALUE)); context->handleError(Error(GL_INVALID_VALUE));
...@@ -2398,6 +2407,20 @@ bool ValidateEGLImageTargetTexture2DOES(Context *context, ...@@ -2398,6 +2407,20 @@ bool ValidateEGLImageTargetTexture2DOES(Context *context,
switch (target) switch (target)
{ {
case GL_TEXTURE_2D: 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; break;
default: default:
......
...@@ -1997,7 +1997,8 @@ bool ValidateBindTexture(Context *context, GLenum target, GLuint texture) ...@@ -1997,7 +1997,8 @@ bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
} }
break; break;
case GL_TEXTURE_EXTERNAL_OES: case GL_TEXTURE_EXTERNAL_OES:
if (!context->getExtensions().eglStreamConsumerExternal) if (!context->getExtensions().eglImageExternal &&
!context->getExtensions().eglStreamConsumerExternal)
{ {
context->handleError( context->handleError(
Error(GL_INVALID_ENUM, "External texture extension not enabled")); Error(GL_INVALID_ENUM, "External texture extension not enabled"));
......
...@@ -2279,7 +2279,7 @@ void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) ...@@ -2279,7 +2279,7 @@ void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidTextureTarget(context, target)) if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
{ {
context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target")); context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
return; return;
...@@ -2434,7 +2434,7 @@ void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params) ...@@ -2434,7 +2434,7 @@ void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!ValidTextureTarget(context, target)) if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
{ {
context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target")); context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
return; return;
......
...@@ -358,37 +358,79 @@ TEST_P(EGLStreamTest, StreamProducerTextureNV12End2End) ...@@ -358,37 +358,79 @@ TEST_P(EGLStreamTest, StreamProducerTextureNV12End2End)
{ {
EGLWindow *window = getEGLWindow(); EGLWindow *window = getEGLWindow();
EGLDisplay display = window->getDisplay(); EGLDisplay display = window->getDisplay();
const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS); if (!eglDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture_nv12"))
if (strstr(extensionsString, "EGL_ANGLE_stream_producer_d3d_texture_nv12") == nullptr)
{ {
std::cout << "Stream producer d3d nv12 texture not supported" << std::endl; std::cout << "Stream producer d3d nv12 texture not supported" << std::endl;
return; return;
} }
// Shader setup bool useESSL3Shaders =
const std::string yuvVS = getClientVersion() >= 3 && extensionEnabled("GL_OES_EGL_image_external_essl3");
"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";
// yuv to rgb conversion shader using Microsoft's given conversion formulas // yuv to rgb conversion shader using Microsoft's given conversion formulas
const std::string yuvPS = std::string yuvVS, yuvPS;
"#extension GL_NV_EGL_stream_consumer_external : require\n" if (useESSL3Shaders)
"precision highp float; varying vec2 texcoord;\n" {
"uniform samplerExternalOES y; uniform samplerExternalOES uv\n;" yuvVS =
"void main(void)\n" "#version 300 es\n"
"{\n" "in highp vec4 position;\n"
" float c = texture2D(y, texcoord).r - (16.0 / 256.0);\n" "out vec2 texcoord;\n"
" float d = texture2D(uv, texcoord).r - 0.5;\n" "void main(void)\n"
" float e = texture2D(uv, texcoord).g - 0.5;\n" "{\n"
" float r = 1.164383 * c + 1.596027 * e;\n" " gl_Position = position;\n"
" float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n" " texcoord = (position.xy * 0.5) + 0.5;\n"
" float b = 1.164383 * c + 2.017232 * d;\n" " texcoord.y = 1.0 - texcoord.y;\n"
" gl_FragColor = vec4(r, g, b, 1.0);\n" "}\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); GLuint program = CompileProgram(yuvVS, yuvPS);
ASSERT_NE(0u, program); ASSERT_NE(0u, program);
GLuint yUniform = glGetUniformLocation(program, "y"); GLuint yUniform = glGetUniformLocation(program, "y");
......
...@@ -40,6 +40,18 @@ class ImageTest : public ANGLETest ...@@ -40,6 +40,18 @@ class ImageTest : public ANGLETest
" texcoord = (position.xy * 0.5) + 0.5;\n" " texcoord = (position.xy * 0.5) + 0.5;\n"
" texcoord.y = 1.0 - texcoord.y;\n" " texcoord.y = 1.0 - texcoord.y;\n"
"}\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 = const std::string textureFSSource =
"precision highp float;\n" "precision highp float;\n"
...@@ -50,6 +62,28 @@ class ImageTest : public ANGLETest ...@@ -50,6 +62,28 @@ class ImageTest : public ANGLETest
"{\n" "{\n"
" gl_FragColor = texture2D(tex, texcoord);\n" " gl_FragColor = texture2D(tex, texcoord);\n"
"}\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); mTextureProgram = CompileProgram(vsSource, textureFSSource);
if (mTextureProgram == 0) if (mTextureProgram == 0)
...@@ -59,6 +93,24 @@ class ImageTest : public ANGLETest ...@@ -59,6 +93,24 @@ class ImageTest : public ANGLETest
mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex"); 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 = eglCreateImageKHR =
reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR")); reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
eglDestroyImageKHR = eglDestroyImageKHR =
...@@ -69,9 +121,11 @@ class ImageTest : public ANGLETest ...@@ -69,9 +121,11 @@ class ImageTest : public ANGLETest
void TearDown() override void TearDown() override
{ {
ANGLETest::TearDown();
glDeleteProgram(mTextureProgram); glDeleteProgram(mTextureProgram);
glDeleteProgram(mTextureExternalProgram);
glDeleteProgram(mTextureExternalESSL3Program);
ANGLETest::TearDown();
} }
void createEGLImage2DTextureSource(size_t width, void createEGLImage2DTextureSource(size_t width,
...@@ -245,6 +299,23 @@ class ImageTest : public ANGLETest ...@@ -245,6 +299,23 @@ class ImageTest : public ANGLETest
*outTargetTexture = target; *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) void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint *outTargetRenderbuffer)
{ {
// Create a target texture from the image // Create a target texture from the image
...@@ -258,19 +329,41 @@ class ImageTest : public ANGLETest ...@@ -258,19 +329,41 @@ class ImageTest : public ANGLETest
*outTargetRenderbuffer = target; *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 // Draw a quad with the target texture
glUseProgram(mTextureProgram); glUseProgram(program);
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(textureTarget, texture);
glUniform1i(mTextureUniformLocation, 0); 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 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]); 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]) void verifyResultsRenderbuffer(GLuint renderbuffer, GLubyte data[4])
{ {
// Bind the renderbuffer to a framebuffer // Bind the renderbuffer to a framebuffer
...@@ -298,10 +391,20 @@ class ImageTest : public ANGLETest ...@@ -298,10 +391,20 @@ class ImageTest : public ANGLETest
GLuint mTextureProgram; GLuint mTextureProgram;
GLint mTextureUniformLocation; GLint mTextureUniformLocation;
GLuint mTextureExternalProgram = 0;
GLint mTextureExternalUniformLocation = -1;
GLuint mTextureExternalESSL3Program = 0;
GLint mTextureExternalESSL3UniformLocation = -1;
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
}; };
class ImageTestES3 : public ImageTest
{
};
// Check validation from the EGL_KHR_image_base extension // Check validation from the EGL_KHR_image_base extension
TEST_P(ImageTest, ValidationImageBase) TEST_P(ImageTest, ValidationImageBase)
{ {
...@@ -755,17 +858,114 @@ TEST_P(ImageTest, ValidationGLEGLImage) ...@@ -755,17 +858,114 @@ TEST_P(ImageTest, ValidationGLEGLImage)
// Check validation from the GL_OES_EGL_image_external extension // Check validation from the GL_OES_EGL_image_external extension
TEST_P(ImageTest, ValidationGLEGLImageExternal) TEST_P(ImageTest, ValidationGLEGLImageExternal)
{ {
// This extension is not implemented anywhere yet. This makes sure that it is tested once it is if (!extensionEnabled("GL_OES_EGL_image_external"))
// added. {
EXPECT_FALSE(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 // Check validation from the GL_OES_EGL_image_external_essl3 extension
TEST_P(ImageTest, ValidationGLEGLImageExternalESSL3) TEST_P(ImageTest, ValidationGLEGLImageExternalESSL3)
{ {
// This extension is not implemented anywhere yet. This makes sure that it is tested once it is if (!extensionEnabled("GL_OES_EGL_image_external_essl3"))
// added. {
EXPECT_FALSE(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) TEST_P(ImageTest, Source2DTarget2D)
...@@ -834,6 +1034,74 @@ TEST_P(ImageTest, Source2DTargetRenderbuffer) ...@@ -834,6 +1034,74 @@ TEST_P(ImageTest, Source2DTargetRenderbuffer)
glDeleteRenderbuffers(1, &target); 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) TEST_P(ImageTest, SourceCubeTarget2D)
{ {
EGLWindow *window = getEGLWindow(); EGLWindow *window = getEGLWindow();
...@@ -916,6 +1184,92 @@ TEST_P(ImageTest, SourceCubeTargetRenderbuffer) ...@@ -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) TEST_P(ImageTest, Source3DTargetTexture)
{ {
EGLWindow *window = getEGLWindow(); EGLWindow *window = getEGLWindow();
...@@ -1008,6 +1362,102 @@ TEST_P(ImageTest, Source3DTargetRenderbuffer) ...@@ -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) TEST_P(ImageTest, SourceRenderbufferTargetTexture)
{ {
EGLWindow *window = getEGLWindow(); EGLWindow *window = getEGLWindow();
...@@ -1041,6 +1491,76 @@ TEST_P(ImageTest, SourceRenderbufferTargetTexture) ...@@ -1041,6 +1491,76 @@ TEST_P(ImageTest, SourceRenderbufferTargetTexture)
glDeleteTextures(1, &target); 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) TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer)
{ {
EGLWindow *window = getEGLWindow(); EGLWindow *window = getEGLWindow();
...@@ -1449,4 +1969,5 @@ ANGLE_INSTANTIATE_TEST(ImageTest, ...@@ -1449,4 +1969,5 @@ ANGLE_INSTANTIATE_TEST(ImageTest,
ES3_OPENGL(), ES3_OPENGL(),
ES2_OPENGLES(), ES2_OPENGLES(),
ES3_OPENGLES()); ES3_OPENGLES());
ANGLE_INSTANTIATE_TEST(ImageTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment