Add texture rectangle extension.

This is needed to support binding IOSurfaces to textures on OSX. This
commit adds support in the API and tests, but didn't need to implement
compiler changes as it already supported ARB_texture_rectangle.

Implementation of CHROMIUM_opy_texture for rectangle texture and the
spec are left for follow-up commits.

Change-Id: I45c66be763a9d3f6f619640f9f95f39b05c70867
Reviewed-on: https://chromium-review.googlesource.com/559106
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Corentin Wallez 2017-07-04 18:27:01 -04:00 коммит произвёл Commit Bot
Родитель acd20b1ff9
Коммит 13c0dd4631
26 изменённых файлов: 796 добавлений и 80 удалений

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

@ -537,6 +537,14 @@ GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewSideBySideANGLE(GLenum
#endif
#endif /* GL_ANGLE_multiview */
#ifndef GL_ANGLE_texture_rectangle
#define GL_ANGLE_texture_rectangle 1
#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE 0x84F8
#define GL_TEXTURE_RECTANGLE_ANGLE 0x84F5
#define GL_TEXTURE_BINDING_RECTANGLE_ANGLE 0x84F6
#define GL_SAMPLER_2D_RECT_ANGLE 0x8B63
#endif /* GL_ANGLE_texture_rectangle */
// clang-format on
#endif // INCLUDE_GLES2_GL2EXT_ANGLE_H_

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

@ -16,9 +16,4 @@
#include "GLES3/gl31.h"
#include "GLES3/gl32.h"
// The following enum is used in ANGLE, but is from desktop GL
#ifndef GL_SAMPLER_2D_RECT_ARB
#define GL_SAMPLER_2D_RECT_ARB 0x8B63
#endif
#endif // ANGLEGL_H_

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

@ -124,6 +124,7 @@ GLenum VariableComponentType(GLenum type)
return GL_FLOAT;
case GL_INT:
case GL_SAMPLER_2D:
case GL_SAMPLER_2D_RECT_ANGLE:
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_ARRAY:
@ -251,7 +252,7 @@ int VariableRowCount(GLenum type)
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_ARRAY:
case GL_SAMPLER_EXTERNAL_OES:
case GL_SAMPLER_2D_RECT_ARB:
case GL_SAMPLER_2D_RECT_ANGLE:
case GL_SAMPLER_2D_MULTISAMPLE:
case GL_INT_SAMPLER_2D:
case GL_INT_SAMPLER_3D:
@ -321,7 +322,7 @@ int VariableColumnCount(GLenum type)
case GL_INT_SAMPLER_2D_ARRAY:
case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_EXTERNAL_OES:
case GL_SAMPLER_2D_RECT_ARB:
case GL_SAMPLER_2D_RECT_ANGLE:
case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
@ -385,6 +386,7 @@ bool IsSamplerType(GLenum type)
case GL_SAMPLER_2D_ARRAY:
case GL_SAMPLER_EXTERNAL_OES:
case GL_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_2D_RECT_ANGLE:
case GL_INT_SAMPLER_2D:
case GL_INT_SAMPLER_3D:
case GL_INT_SAMPLER_CUBE:
@ -471,6 +473,9 @@ GLenum SamplerTypeToTextureType(GLenum samplerType)
case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
return GL_TEXTURE_2D_MULTISAMPLE;
case GL_SAMPLER_2D_RECT_ANGLE:
return GL_TEXTURE_RECTANGLE_ANGLE;
default:
UNREACHABLE();
return 0;
@ -694,7 +699,7 @@ int VariableSortOrder(GLenum type)
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_EXTERNAL_OES:
case GL_SAMPLER_2D_RECT_ARB:
case GL_SAMPLER_2D_RECT_ANGLE:
case GL_SAMPLER_2D_ARRAY:
case GL_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_3D:

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

@ -332,7 +332,7 @@ GLenum GLVariableType(const TType &type)
case EbtSamplerExternal2DY2YEXT:
return GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
case EbtSampler2DRect:
return GL_SAMPLER_2D_RECT_ARB;
return GL_SAMPLER_2D_RECT_ANGLE;
case EbtSampler2DArray:
return GL_SAMPLER_2D_ARRAY;
case EbtSampler2DMS:

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

@ -229,7 +229,8 @@ Extensions::Extensions()
surfacelessContext(false),
clientArrays(false),
robustResourceInitialization(false),
programCacheControl(false)
programCacheControl(false),
textureRectangle(false)
{
}
@ -699,6 +700,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_ANGLE_client_arrays"] = esOnlyExtension(&Extensions::clientArrays);
map["GL_ANGLE_robust_resource_initialization"] = esOnlyExtension(&Extensions::robustResourceInitialization);
map["GL_ANGLE_program_cache_control"] = esOnlyExtension(&Extensions::programCacheControl);
map["GL_ANGLE_texture_rectangle"] = enableableExtension(&Extensions::textureRectangle);
// clang-format on
return map;
@ -746,6 +748,7 @@ Caps::Caps()
: maxElementIndex(0),
max3DTextureSize(0),
max2DTextureSize(0),
maxRectangleTextureSize(0),
maxArrayTextureLayers(0),
maxLODBias(0),
maxCubeMapTextureSize(0),

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

@ -370,6 +370,9 @@ struct Extensions
// GL_ANGLE_program_cache_control
bool programCacheControl;
// GL_ANGLE_texture_rectangle
bool textureRectangle;
};
struct ExtensionInfo
@ -432,6 +435,7 @@ struct Caps
GLuint64 maxElementIndex;
GLuint max3DTextureSize;
GLuint max2DTextureSize;
GLuint maxRectangleTextureSize;
GLuint maxArrayTextureLayers;
GLfloat maxLODBias;
GLuint maxCubeMapTextureSize;

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

@ -72,6 +72,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
mResources.OES_EGL_image_external = extensions.eglImageExternal;
mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3;
mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal;
mResources.ARB_texture_rectangle = extensions.textureRectangle;
// TODO: use shader precision caps to determine if high precision is supported?
mResources.FragmentPrecisionHigh = 1;
mResources.EXT_frag_depth = extensions.fragDepth;

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

@ -334,6 +334,13 @@ Context::Context(rx::EGLImplFactory *implFactory,
}
}
if (mExtensions.textureRectangle)
{
Texture *zeroTextureRectangle =
new Texture(mImplementation.get(), 0, GL_TEXTURE_RECTANGLE_ANGLE);
mZeroTextures[GL_TEXTURE_RECTANGLE_ANGLE].set(this, zeroTextureRectangle);
}
if (mExtensions.eglImageExternal || mExtensions.eglStreamConsumerExternal)
{
Texture *zeroTextureExternal =
@ -1422,6 +1429,9 @@ void Context::getIntegervImpl(GLenum pname, GLint *params)
case GL_MAX_TEXTURE_SIZE:
*params = mCaps.max2DTextureSize;
break;
case GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE:
*params = mCaps.maxRectangleTextureSize;
break;
case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
*params = mCaps.maxCubeMapTextureSize;
break;
@ -3028,6 +3038,10 @@ void Context::framebufferTexture2D(GLenum target,
{
index = ImageIndex::Make2D(level);
}
else if (textarget == GL_TEXTURE_RECTANGLE_ANGLE)
{
index = ImageIndex::MakeRectangle(level);
}
else if (textarget == GL_TEXTURE_2D_MULTISAMPLE)
{
ASSERT(level == 0);

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

@ -229,6 +229,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
*numParams = 1;
return true;
}
case GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE:
case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
{
if (!getExtensions().textureRectangle)
{
return false;
}
*type = GL_INT;
*numParams = 1;
return true;
}
case GL_MAX_DRAW_BUFFERS_EXT:
case GL_MAX_COLOR_ATTACHMENTS_EXT:
{

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

@ -38,6 +38,11 @@ ImageIndex ImageIndex::Make2D(GLint mipIndex)
return ImageIndex(GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL);
}
ImageIndex ImageIndex::MakeRectangle(GLint mipIndex)
{
return ImageIndex(GL_TEXTURE_RECTANGLE_ANGLE, mipIndex, ENTIRE_LEVEL);
}
ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex)
{
ASSERT(gl::IsCubeMapTextureTarget(target));
@ -112,6 +117,13 @@ ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
nullptr);
}
ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
{
return ImageIndexIterator(GL_TEXTURE_RECTANGLE_ANGLE, Range<GLint>(minMip, maxMip),
Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
nullptr);
}
ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
{
return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, Range<GLint>(minMip, maxMip), Range<GLint>(0, 6),

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

@ -31,6 +31,7 @@ struct ImageIndex
bool is3D() const;
static ImageIndex Make2D(GLint mipIndex);
static ImageIndex MakeRectangle(GLint mipIndex);
static ImageIndex MakeCube(GLenum target, GLint mipIndex);
static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
@ -55,6 +56,7 @@ class ImageIndexIterator
{
public:
static ImageIndexIterator Make2D(GLint minMip, GLint maxMip);
static ImageIndexIterator MakeRectangle(GLint minMip, GLint maxMip);
static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip);
static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);

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

@ -150,6 +150,10 @@ void State::initialize(const Context *context,
mShaderStorageBuffers.resize(caps.maxShaderStorageBufferBindings);
mImageUnits.resize(caps.maxImageUnits);
}
if (extensions.textureRectangle)
{
mSamplerTextures[GL_TEXTURE_RECTANGLE_ANGLE].resize(caps.maxCombinedTextureImageUnits);
}
if (extensions.eglImageExternal || extensions.eglStreamConsumerExternal)
{
mSamplerTextures[GL_TEXTURE_EXTERNAL_OES].resize(caps.maxCombinedTextureImageUnits);
@ -1917,6 +1921,11 @@ void State::getIntegerv(const Context *context, GLenum pname, GLint *params)
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D);
break;
case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
GL_TEXTURE_RECTANGLE_ANGLE);
break;
case GL_TEXTURE_BINDING_CUBE_MAP:
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params =

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

@ -1158,7 +1158,7 @@ Error Texture::bindTexImageFromSurface(const Context *context, egl::Surface *sur
mBoundSurface = surface;
// Set the image info to the size and format of the surface
ASSERT(mState.mTarget == GL_TEXTURE_2D);
ASSERT(mState.mTarget == GL_TEXTURE_2D || mState.mTarget == GL_TEXTURE_RECTANGLE_ANGLE);
Extents size(surface->getWidth(), surface->getHeight(), 1);
ImageDesc desc(size, Format(surface->getConfig()->renderTargetFormat));
mState.setImageDesc(mState.mTarget, 0, desc);
@ -1173,7 +1173,7 @@ Error Texture::releaseTexImageFromSurface(const Context *context)
ANGLE_TRY(mTexture->releaseTexImage(context));
// Erase the image info for level 0
ASSERT(mState.mTarget == GL_TEXTURE_2D);
ASSERT(mState.mTarget == GL_TEXTURE_2D || mState.mTarget == GL_TEXTURE_RECTANGLE_ANGLE);
mState.clearImageDesc(mState.mTarget, 0);
mDirtyChannel.signal();
return NoError();

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

@ -48,7 +48,8 @@ void BindFramebufferAttachment(const FunctionsGL *functions,
const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
if (texture->getTarget() == GL_TEXTURE_2D ||
texture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE)
texture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE ||
texture->getTarget() == GL_TEXTURE_RECTANGLE_ANGLE)
{
functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
texture->getTarget(), textureGL->getTextureID(),

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

@ -171,6 +171,7 @@ StateManagerGL::StateManagerGL(const FunctionsGL *functions,
ASSERT(extensions.maxViews >= 1u);
mTextures[GL_TEXTURE_2D].resize(rendererCaps.maxCombinedTextureImageUnits);
mTextures[GL_TEXTURE_RECTANGLE_ANGLE].resize(rendererCaps.maxCombinedTextureImageUnits);
mTextures[GL_TEXTURE_CUBE_MAP].resize(rendererCaps.maxCombinedTextureImageUnits);
mTextures[GL_TEXTURE_2D_ARRAY].resize(rendererCaps.maxCombinedTextureImageUnits);
mTextures[GL_TEXTURE_3D].resize(rendererCaps.maxCombinedTextureImageUnits);

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

@ -41,7 +41,8 @@ size_t GetLevelInfoIndex(GLenum target, size_t level)
bool UseTexImage2D(GLenum textureType)
{
return textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP;
return textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP ||
textureType == GL_TEXTURE_RECTANGLE_ANGLE;
}
bool UseTexImage3D(GLenum textureType)
@ -811,7 +812,7 @@ gl::Error TextureGL::setStorage(const gl::Context *context,
std::max(size.height >> level, 1),
1);
if (getTarget() == GL_TEXTURE_2D)
if (getTarget() == GL_TEXTURE_2D || getTarget() == GL_TEXTURE_RECTANGLE_ANGLE)
{
if (internalFormatInfo.compressed)
{
@ -989,7 +990,7 @@ gl::Error TextureGL::generateMipmap(const gl::Context *context)
gl::Error TextureGL::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
ASSERT(getTarget() == GL_TEXTURE_2D);
ASSERT(getTarget() == GL_TEXTURE_2D || getTarget() == GL_TEXTURE_RECTANGLE_ANGLE);
// Make sure this texture is bound
mStateManager->bindTexture(getTarget(), mTextureID);
@ -1001,7 +1002,7 @@ gl::Error TextureGL::bindTexImage(const gl::Context *context, egl::Surface *surf
gl::Error TextureGL::releaseTexImage(const gl::Context *context)
{
// Not all Surface implementations reset the size of mip 0 when releasing, do it manually
ASSERT(getTarget() == GL_TEXTURE_2D);
ASSERT(getTarget() == GL_TEXTURE_2D || getTarget() == GL_TEXTURE_RECTANGLE_ANGLE);
mStateManager->bindTexture(getTarget(), mTextureID);
if (UseTexImage2D(getTarget()))

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

@ -1002,6 +1002,14 @@ void GenerateCaps(const FunctionsGL *functions,
functions->hasGLESExtension("GL_ARB_invalidate_subdata");
extensions->translatedShaderSource = true;
if (functions->isAtLeastGL(gl::Version(3, 1)) ||
functions->hasGLExtension("GL_ARB_texture_rectangle"))
{
extensions->textureRectangle = true;
caps->maxRectangleTextureSize =
QuerySingleGLInt(functions, GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE);
}
}
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)

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

@ -35,6 +35,9 @@ size_t GetMaximumMipLevel(const gl::Context *context, GLenum target)
case GL_TEXTURE_2D:
maxDimension = caps.max2DTextureSize;
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
maxDimension = caps.maxRectangleTextureSize;
break;
case GL_TEXTURE_CUBE_MAP:
maxDimension = caps.maxCubeMapTextureSize;
break;

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

@ -257,7 +257,7 @@ bool ValidReadPixelsFormatType(ValidationContext *context,
}
template <typename ParamType>
bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
{
switch (ConvertToGLenum(params[0]))
{
@ -266,11 +266,11 @@ bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isEx
case GL_REPEAT:
case GL_MIRRORED_REPEAT:
if (isExternalTextureTarget)
if (restrictedWrapModes)
{
// OES_EGL_image_external specifies this error.
// OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
context->handleError(InvalidEnum()
<< "external textures only support CLAMP_TO_EDGE wrap mode");
<< "texture only support CLAMP_TO_EDGE wrap mode");
return false;
}
break;
@ -284,9 +284,7 @@ bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isEx
}
template <typename ParamType>
bool ValidateTextureMinFilterValue(Context *context,
ParamType *params,
bool isExternalTextureTarget)
bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
{
switch (ConvertToGLenum(params[0]))
{
@ -298,11 +296,11 @@ bool ValidateTextureMinFilterValue(Context *context,
case GL_LINEAR_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
if (isExternalTextureTarget)
if (restrictedMinFilter)
{
// OES_EGL_image_external specifies this error.
context->handleError(
InvalidEnum() << "external textures only support NEAREST and LINEAR filtering");
context->handleError(InvalidEnum()
<< "texture only support NEAREST and LINEAR filtering");
return false;
}
break;
@ -861,6 +859,9 @@ bool ValidTextureTarget(const ValidationContext *context, GLenum target)
case GL_TEXTURE_CUBE_MAP:
return true;
case GL_TEXTURE_RECTANGLE_ANGLE:
return context->getExtensions().textureRectangle;
case GL_TEXTURE_3D:
case GL_TEXTURE_2D_ARRAY:
return (context->getClientMajorVersion() >= 3);
@ -881,6 +882,9 @@ bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
case GL_TEXTURE_CUBE_MAP:
return true;
case GL_TEXTURE_RECTANGLE_ANGLE:
return context->getExtensions().textureRectangle;
default:
return false;
}
@ -924,6 +928,8 @@ bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum ta
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
return true;
case GL_TEXTURE_RECTANGLE_ANGLE:
return context->getExtensions().textureRectangle;
default:
return false;
}
@ -1023,6 +1029,8 @@ bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum tar
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_2D_MULTISAMPLE:
return true;
case GL_TEXTURE_RECTANGLE_ANGLE:
return context->getExtensions().textureRectangle;
default:
return false;
}
@ -1095,6 +1103,8 @@ bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
maxDimension = caps.maxCubeMapTextureSize;
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
return level == 0;
case GL_TEXTURE_3D:
maxDimension = caps.max3DTextureSize;
break;
@ -2494,6 +2504,14 @@ bool ValidateStateQuery(ValidationContext *context,
case GL_TEXTURE_BINDING_2D_ARRAY:
case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
break;
case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
if (!context->getExtensions().textureRectangle)
{
context->handleError(InvalidEnum()
<< "ANGLE_texture_rectangle extension not present");
return false;
}
break;
case GL_TEXTURE_BINDING_EXTERNAL_OES:
if (!context->getExtensions().eglStreamConsumerExternal &&
!context->getExtensions().eglImageExternal)
@ -2676,6 +2694,10 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
maxDimension = caps.maxCubeMapTextureSize;
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
maxDimension = caps.maxRectangleTextureSize;
break;
case GL_TEXTURE_2D_ARRAY:
maxDimension = caps.max2DTextureSize;
break;
@ -5688,16 +5710,24 @@ bool ValidateTexParameterBase(Context *context,
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
case GL_TEXTURE_WRAP_R:
if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
{
return false;
bool restrictedWrapModes =
target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
{
return false;
}
}
break;
case GL_TEXTURE_MIN_FILTER:
if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
{
return false;
bool restrictedMinFilter =
target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
{
return false;
}
}
break;
@ -5793,6 +5823,12 @@ bool ValidateTexParameterBase(Context *context,
<< "Base level must be 0 for multisampled textures.");
return false;
}
if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
{
context->handleError(InvalidOperation()
<< "Base level must be 0 for rectangle textures.");
return false;
}
break;
case GL_TEXTURE_MAX_LEVEL:

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

@ -314,8 +314,9 @@ bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, G
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
return textureType == GL_TEXTURE_CUBE_MAP;
// TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
// supported
case GL_TEXTURE_RECTANGLE_ANGLE:
return textureType == GL_TEXTURE_RECTANGLE_ANGLE &&
context->getExtensions().textureRectangle;
default:
return false;
@ -328,9 +329,8 @@ bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
{
case GL_TEXTURE_2D:
return true;
// TODO(geofflang): accept GL_TEXTURE_RECTANGLE_ARB if the texture_rectangle extension is
// supported
case GL_TEXTURE_RECTANGLE_ANGLE:
return context->getExtensions().textureRectangle;
// TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
// supported
@ -375,6 +375,15 @@ bool IsValidCopyTextureDestinationLevel(Context *context,
return false;
}
}
else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
{
ASSERT(level == 0);
if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
{
return false;
}
}
else if (IsCubeMapTextureTarget(target))
{
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
@ -1002,6 +1011,22 @@ bool ValidateES2TexImageParameters(Context *context,
return false;
}
}
else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
{
ASSERT(level == 0);
if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
{
context->handleError(InvalidValue());
return false;
}
if (isCompressed)
{
context->handleError(InvalidEnum()
<< "Rectangle texture cannot have a compressed format.");
return false;
}
}
else if (IsCubeMapTextureTarget(target))
{
if (!isSubImage && width != height)
@ -1480,7 +1505,8 @@ bool ValidateES2TexStorageParameters(Context *context,
GLsizei width,
GLsizei height)
{
if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
target != GL_TEXTURE_RECTANGLE_ANGLE)
{
context->handleError(InvalidEnum());
return false;
@ -1523,6 +1549,20 @@ bool ValidateES2TexStorageParameters(Context *context,
return false;
}
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
{
context->handleError(InvalidValue());
return false;
}
if (formatInfo.compressed)
{
context->handleError(InvalidEnum()
<< "Rectangle texture cannot have a compressed format.");
return false;
}
break;
case GL_TEXTURE_CUBE_MAP:
if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
@ -2601,6 +2641,12 @@ bool ValidateCompressedTexImage2D(Context *context,
return false;
}
if (target == GL_TEXTURE_RECTANGLE_ANGLE)
{
context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
return false;
}
return true;
}
@ -2796,6 +2842,15 @@ bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
case GL_TEXTURE_CUBE_MAP:
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
if (!context->getExtensions().textureRectangle)
{
context->handleError(InvalidEnum()
<< "Context does not support GL_ANGLE_texture_rectangle");
return false;
}
break;
case GL_TEXTURE_3D:
case GL_TEXTURE_2D_ARRAY:
if (context->getClientMajorVersion() < 3)
@ -5807,6 +5862,22 @@ bool ValidateFramebufferTexture2D(Context *context,
}
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
{
if (level != 0)
{
context->handleError(InvalidValue());
return false;
}
if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
{
context->handleError(InvalidOperation()
<< "Textarget must match the texture target type.");
return false;
}
}
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
@ -5954,7 +6025,8 @@ bool ValidateGenerateMipmap(Context *context, GLenum target)
(!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
!isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
{
ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
target == GL_TEXTURE_CUBE_MAP);
ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
return false;
}

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

@ -199,6 +199,22 @@ bool ValidateES3TexImageParametersBase(Context *context,
}
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
ASSERT(level == 0);
if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
{
context->handleError(InvalidValue());
return false;
}
if (isCompressed)
{
context->handleError(InvalidEnum()
<< "Rectangle texture cannot have a compressed format.");
return false;
}
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
@ -851,6 +867,17 @@ bool ValidateES3TexStorageParametersBase(Context *context,
}
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
{
if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
{
context->handleError(InvalidValue());
return false;
}
}
break;
case GL_TEXTURE_CUBE_MAP:
{
if (width != height)
@ -922,6 +949,12 @@ bool ValidateES3TexStorageParametersBase(Context *context,
return false;
}
if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
{
context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
return false;
}
return true;
}

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

@ -80,6 +80,7 @@
'<(angle_path)/src/tests/gl_tests/SwizzleTest.cpp',
'<(angle_path)/src/tests/gl_tests/SyncQueriesTest.cpp',
'<(angle_path)/src/tests/gl_tests/TextureMultisampleTest.cpp',
'<(angle_path)/src/tests/gl_tests/TextureRectangleTest.cpp',
'<(angle_path)/src/tests/gl_tests/TextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/TimerQueriesTest.cpp',
'<(angle_path)/src/tests/gl_tests/TransformFeedbackTest.cpp',

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

@ -49,6 +49,7 @@
'<(angle_path)/src/tests/angle_unittests_utils.h',
'<(angle_path)/src/tests/compiler_tests/API_test.cpp',
'<(angle_path)/src/tests/compiler_tests/AppendixALimitations_test.cpp',
'<(angle_path)/src/tests/compiler_tests/ARB_texture_rectangle_test.cpp',
'<(angle_path)/src/tests/compiler_tests/AtomicCounter_test.cpp',
'<(angle_path)/src/tests/compiler_tests/BufferVariables_test.cpp',
'<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp',

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

@ -0,0 +1,97 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ARB_texture_rectangle_test.cpp:
// Test for the ARB_texture_rectangle extension
//
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "tests/test_utils/ShaderCompileTreeTest.h"
using namespace sh;
class ARBTextureRectangleTestNoExt : public ShaderCompileTreeTest
{
protected:
::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
ShShaderSpec getShaderSpec() const override { return SH_GLES3_SPEC; }
};
class ARBTextureRectangleTest : public ARBTextureRectangleTestNoExt
{
protected:
void initResources(ShBuiltInResources *resources) override
{
resources->ARB_texture_rectangle = 1;
}
};
// Check that new types and builtins are disallowed if the extension isn't present in the translator
// resources
TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltinsWithoutTranslatorResourceExtension)
{
// The new builtins require Sampler2DRect so we can't test them independently.
const std::string &shaderString =
"precision mediump float;\n"
"uniform sampler2DRect tex;\n"
"void main() {\n"
"}\n";
ASSERT_TRUE(compile(shaderString));
}
// Check that new types and builtins are usable even with the #extension directive
// Issue #15 of ARB_texture_rectangle explains that the extension was specified before the
// #extension mechanism was in place so it doesn't require explicit enabling.
TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltinsWithoutExtensionDirective)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform sampler2DRect tex;\n"
"void main() {\n"
" vec4 color = texture2DRect(tex, vec2(1.0));"
" color = texture2DRectProj(tex, vec3(1.0));"
" color = texture2DRectProj(tex, vec4(1.0));"
"}\n";
ASSERT_TRUE(compile(shaderString));
}
// Test valid usage of the new types and builtins
TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltingsWithExtensionDirective)
{
const std::string &shaderString =
"#extension GL_ARB_texture_rectangle : require\n"
"precision mediump float;\n"
"uniform sampler2DRect tex;\n"
"void main() {\n"
" vec4 color = texture2DRect(tex, vec2(1.0));"
" color = texture2DRectProj(tex, vec3(1.0));"
" color = texture2DRectProj(tex, vec4(1.0));"
"}\n";
ASSERT_TRUE(compile(shaderString));
}
// Check that it is not possible to pass a sampler2DRect where sampler2D is expected, and vice versa
TEST_F(ARBTextureRectangleTest, Rect2DVs2DMismatch)
{
const std::string &shaderString1 =
"#extension GL_ARB_texture_rectangle : require\n"
"precision mediump float;\n"
"uniform sampler2DRect tex;\n"
"void main() {\n"
" vec4 color = texture2D(tex, vec2(1.0));"
"}\n";
ASSERT_FALSE(compile(shaderString1));
const std::string &shaderString2 =
"#extension GL_ARB_texture_rectangle : require\n"
"precision mediump float;\n"
"uniform sampler2D tex;\n"
"void main() {\n"
" vec4 color = texture2DRect(tex, vec2(1.0));"
"}\n";
ASSERT_FALSE(compile(shaderString2));
}

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

@ -10,48 +10,48 @@
#include "compiler/translator/VariablePacker.h"
static sh::GLenum types[] = {
GL_FLOAT_MAT4, // 0
GL_FLOAT_MAT2, // 1
GL_FLOAT_VEC4, // 2
GL_INT_VEC4, // 3
GL_BOOL_VEC4, // 4
GL_FLOAT_MAT3, // 5
GL_FLOAT_VEC3, // 6
GL_INT_VEC3, // 7
GL_BOOL_VEC3, // 8
GL_FLOAT_VEC2, // 9
GL_INT_VEC2, // 10
GL_BOOL_VEC2, // 11
GL_FLOAT, // 12
GL_INT, // 13
GL_BOOL, // 14
GL_SAMPLER_2D, // 15
GL_SAMPLER_CUBE, // 16
GL_SAMPLER_EXTERNAL_OES, // 17
GL_SAMPLER_2D_RECT_ARB, // 18
GL_UNSIGNED_INT, // 19
GL_UNSIGNED_INT_VEC2, // 20
GL_UNSIGNED_INT_VEC3, // 21
GL_UNSIGNED_INT_VEC4, // 22
GL_FLOAT_MAT2x3, // 23
GL_FLOAT_MAT2x4, // 24
GL_FLOAT_MAT3x2, // 25
GL_FLOAT_MAT3x4, // 26
GL_FLOAT_MAT4x2, // 27
GL_FLOAT_MAT4x3, // 28
GL_SAMPLER_3D, // 29
GL_SAMPLER_2D_ARRAY, // 30
GL_SAMPLER_2D_SHADOW, // 31
GL_SAMPLER_CUBE_SHADOW, // 32
GL_SAMPLER_2D_ARRAY_SHADOW, // 33
GL_INT_SAMPLER_2D, // 34
GL_INT_SAMPLER_CUBE, // 35
GL_INT_SAMPLER_3D, // 36
GL_INT_SAMPLER_2D_ARRAY, // 37
GL_UNSIGNED_INT_SAMPLER_2D, // 38
GL_UNSIGNED_INT_SAMPLER_CUBE, // 39
GL_UNSIGNED_INT_SAMPLER_3D, // 40
GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, // 41
GL_FLOAT_MAT4, // 0
GL_FLOAT_MAT2, // 1
GL_FLOAT_VEC4, // 2
GL_INT_VEC4, // 3
GL_BOOL_VEC4, // 4
GL_FLOAT_MAT3, // 5
GL_FLOAT_VEC3, // 6
GL_INT_VEC3, // 7
GL_BOOL_VEC3, // 8
GL_FLOAT_VEC2, // 9
GL_INT_VEC2, // 10
GL_BOOL_VEC2, // 11
GL_FLOAT, // 12
GL_INT, // 13
GL_BOOL, // 14
GL_SAMPLER_2D, // 15
GL_SAMPLER_CUBE, // 16
GL_SAMPLER_EXTERNAL_OES, // 17
GL_SAMPLER_2D_RECT_ANGLE, // 18
GL_UNSIGNED_INT, // 19
GL_UNSIGNED_INT_VEC2, // 20
GL_UNSIGNED_INT_VEC3, // 21
GL_UNSIGNED_INT_VEC4, // 22
GL_FLOAT_MAT2x3, // 23
GL_FLOAT_MAT2x4, // 24
GL_FLOAT_MAT3x2, // 25
GL_FLOAT_MAT3x4, // 26
GL_FLOAT_MAT4x2, // 27
GL_FLOAT_MAT4x3, // 28
GL_SAMPLER_3D, // 29
GL_SAMPLER_2D_ARRAY, // 30
GL_SAMPLER_2D_SHADOW, // 31
GL_SAMPLER_CUBE_SHADOW, // 32
GL_SAMPLER_2D_ARRAY_SHADOW, // 33
GL_INT_SAMPLER_2D, // 34
GL_INT_SAMPLER_CUBE, // 35
GL_INT_SAMPLER_3D, // 36
GL_INT_SAMPLER_2D_ARRAY, // 37
GL_UNSIGNED_INT_SAMPLER_2D, // 38
GL_UNSIGNED_INT_SAMPLER_CUBE, // 39
GL_UNSIGNED_INT_SAMPLER_3D, // 40
GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, // 41
};
static sh::GLenum nonSqMatTypes[] = {

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

@ -0,0 +1,398 @@
//
// Copyright 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureRectangleTest: Tests of GL_ANGLE_texture_rectangle
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle;
namespace
{
class TextureRectangleTest : public ANGLETest
{
protected:
TextureRectangleTest()
{
setWindowWidth(64);
setWindowHeight(64);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
bool checkExtensionSupported() const
{
if (!extensionEnabled("GL_ANGLE_texture_rectangle"))
{
std::cout << "Test skipped because GL_ANGLE_texture_rectangle is not available."
<< std::endl;
return false;
}
return true;
}
};
class TextureRectangleTestES3 : public TextureRectangleTest
{
};
class TextureRectangleTestES31 : public TextureRectangleTest
{
};
// Test using TexImage2D to define a rectangle texture
TEST_P(TextureRectangleTest, TexImage2D)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
// Defining level 0 is allowed
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
ASSERT_GL_NO_ERROR();
// Defining level other than 0 is not allowed
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 1, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
GLint maxSize = 0;
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE, &maxSize);
// Defining a texture of the max size is allowed
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, maxSize, maxSize, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
ASSERT_GL_NO_ERROR();
// Defining a texture of the max size is allowed
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, maxSize + 1, maxSize, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, maxSize, maxSize + 1, 0, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
}
// Test using CompressedTexImage2D cannot be used on a retangle texture
TEST_P(TextureRectangleTest, CompressedTexImage2DDisallowed)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
ANGLE_SKIP_TEST_IF(!extensionEnabled("GL_EXT_texture_compression_dxt1"));
const char data[128] = {0};
// Control case: 2D texture
{
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128,
data);
ASSERT_GL_NO_ERROR();
}
// Rectangle textures cannot be compressed
{
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
glCompressedTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16,
16, 0, 128, data);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
}
}
// Test using TexStorage2D to define a rectangle texture
TEST_P(TextureRectangleTest, TexStorage2D)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage"));
bool useES3 = getClientMajorVersion() >= 3;
auto TexStorage2D = [useES3](GLenum target, GLint levels, GLenum format, GLint width,
GLint height) {
if (useES3)
{
glTexStorage2D(target, levels, format, width, height);
}
else
{
glTexStorage2DEXT(target, levels, format, width, height);
}
};
// Defining one level is allowed
{
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
TexStorage2D(GL_TEXTURE_RECTANGLE_ANGLE, 1, GL_RGBA8UI, 16, 16);
ASSERT_GL_NO_ERROR();
}
// Having more than one level is not allowed
{
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
// Use 5 levels because the EXT_texture_storage extension requires a mip chain all the way
// to a 1x1 mip.
TexStorage2D(GL_TEXTURE_RECTANGLE_ANGLE, 5, GL_RGBA8UI, 16, 16);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
}
GLint maxSize = 0;
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE, &maxSize);
// Defining a texture of the max size is allowed
{
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
TexStorage2D(GL_TEXTURE_RECTANGLE_ANGLE, 1, GL_RGBA8UI, maxSize, maxSize);
ASSERT_GL_NO_ERROR();
}
// Defining a texture of the max size is allowed
{
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
TexStorage2D(GL_TEXTURE_RECTANGLE_ANGLE, 1, GL_RGBA8UI, maxSize + 1, maxSize);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
TexStorage2D(GL_TEXTURE_RECTANGLE_ANGLE, 1, GL_RGBA8UI, maxSize, maxSize + 1);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
}
// Compressed formats are disallowed
if (extensionEnabled("GL_EXT_texture_compression_dxt1"))
{
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
TexStorage2D(GL_TEXTURE_RECTANGLE_ANGLE, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
}
}
// Test validation of disallowed texture parameters
TEST_P(TextureRectangleTest, TexParameterRestriction)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
// Only wrap mode CLAMP_TO_EDGE is supported
// Wrap S
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
ASSERT_GL_NO_ERROR();
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_S, GL_REPEAT);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
// Wrap T
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
ASSERT_GL_NO_ERROR();
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_T, GL_REPEAT);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
// Min filter has to be nearest or linear
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
ASSERT_GL_NO_ERROR();
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
ASSERT_GL_ERROR(GL_INVALID_ENUM);
// Base level has to be 0
if (getClientMajorVersion() >= 3)
{
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_BASE_LEVEL, 0);
ASSERT_GL_NO_ERROR();
glTexParameteri(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_BASE_LEVEL, 1);
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
}
}
// Test validation of 'level' in GetTexParameter
TEST_P(TextureRectangleTestES31, GetTexLevelParameter)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
ASSERT_GL_NO_ERROR();
GLint param;
// Control case: level 0 is ok.
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_TEXTURE_INTERNAL_FORMAT, &param);
ASSERT_GL_NO_ERROR();
// Level 1 is not ok.
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ANGLE, 1, GL_TEXTURE_INTERNAL_FORMAT, &param);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
}
// Test validation of "level" in FramebufferTexture2D
TEST_P(TextureRectangleTest, FramebufferTexture2DLevel)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
ASSERT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Using level 0 of a rectangle texture is valid.
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ANGLE, tex,
0);
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
ASSERT_GL_NO_ERROR();
// Setting level != 0 is invalid
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ANGLE, tex,
1);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
}
// Test sampling from a rectangle texture
TEST_P(TextureRectangleTest, SamplingFromRectangle)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
&GLColor::green);
const std::string vs =
"attribute vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position.xy, 0.0, 1.0);\n"
"}\n";
const std::string fs =
"#extension GL_ARB_texture_rectangle : require\n"
"precision mediump float;\n"
"uniform sampler2DRect tex;\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
"}\n";
ANGLE_GL_PROGRAM(program, vs, fs);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
drawQuad(program, "position", 0.5f, 1.0f, false);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
ASSERT_GL_NO_ERROR();
}
// Test attaching a rectangle texture and rendering to it.
TEST_P(TextureRectangleTest, RenderToRectangle)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
&GLColor::black);
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ANGLE, tex,
0);
EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
ASSERT_GL_NO_ERROR();
// Clearing a texture is just as good as checking we can render to it, right?
glClearColor(0.0, 1.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
ASSERT_GL_NO_ERROR();
}
// Test glCopyTexImage with rectangle textures
TEST_P(TextureRectangleTestES3, CopyTexImage)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
// Error case: level != 0
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 1, GL_RGBA8, 0, 0, 1, 1, 0);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
// level = 0 works and defines the texture.
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA8, 0, 0, 1, 1, 0);
ASSERT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ANGLE, tex,
0);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
ASSERT_GL_NO_ERROR();
}
// Test glCopyTexSubImage with rectangle textures
TEST_P(TextureRectangleTestES3, CopyTexSubImage)
{
ANGLE_SKIP_TEST_IF(!checkExtensionSupported());
GLTexture tex;
glBindTexture(GL_TEXTURE_RECTANGLE_ANGLE, tex);
glTexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
&GLColor::black);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
// Error case: level != 0
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 1, 0, 0, 0, 0, 1, 1);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
// level = 0 works and defines the texture.
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, 0, 0, 0, 0, 1, 1);
ASSERT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ANGLE, tex,
0);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
ASSERT_GL_NO_ERROR();
}
ANGLE_INSTANTIATE_TEST(TextureRectangleTest, ES2_OPENGL(), ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(TextureRectangleTestES3, ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(TextureRectangleTestES31, ES31_OPENGL());
} // anonymous namespace