зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
a0d3aa4116
Коммит
b66a9097a3
|
@ -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());
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче