Commit f41a7151 by Geoff Lang Committed by Commit Bot

Add an extension to disable resource generation on bind.

BUG=angleproject:1518 Change-Id: I662f7b07da5c97831496f2617b0adadf9858bdc9 Reviewed-on: https://chromium-review.googlesource.com/386799Reviewed-by: 's avatarAntoine Labour <piman@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 44ebf6b4
Name
CHROMIUM_bind_generates_resource
Name Strings
GL_CHROMIUM_bind_generates_resource
Contributors
Geoff Lang
Contact
Geoff Lang (geofflang 'at' google.com)
Notice
Copyright (c) 2016 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Status
Draft
Version
Version 1, September 19, 2016
Number
OpenGL ES Extension #??
Dependencies
Requires OpenGL ES 2.0
Written against the OpenGL ES 2.0 specification.
Overview
This extension allows the user to control the behaviour when binding an
object that has not been generated. This functionality is useful to
notify the user of potential use-after-free errors or support other APIs
such as WebGL on top of an OpenGL ES context.
New Procedures and Functions
None
New Tokens
Accepted by the <cap> parameter to IsEnabled and the <pname> parameter to
GetBooleanv, GetIntegerv, GetFloatv, and GetInteger64v:
BIND_GENERATES_RESOURCE_CHROMIUM 0x9244
Additions to the OpenGL ES Specification
Add to the end of Section 2.9 "Buffer Objects":
If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindBuffer fails and an
INVALID_OPERATION error is generated if buffer is not zero or a name
returned from a previous call to GenBuffers, or if such a name has since
been deleted with DeleteBuffers.
Add to the end of Section 3.7.13 "Texture Objects":
If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindTexture fails and an
INVALID_OPERATION error is generated if texture is not zero or a name
returned from a previous call to GenTextures, or if such a name has since
been deleted with DeleteTextures.
Add to the end of Section 4.4.1 "Binding and Managing Framebuffer Objects":
If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindFramebuffer fails and an
INVALID_OPERATION error is generated if framebuffer is not zero or a name
returned from a previous call to GenFramebuffers, or if such a name has
since been deleted with DeleteFramebuffers.
Add to the end of Section 4.4.3 "Renderbuffer Objects":
If BIND_GENERATES_RESOURCE_CHROMIUM is false, BindRenderbuffer fails and an
INVALID_OPERATION error is generated if renderbuffer is not zero or a name
returned from a previous call to GenRenderbuffers, or if such a name has
since been deleted with DeleteRenderbuffers.
New State
Modify Table 6.22, Miscellaneous
Add:
Initial
Get Value Type Get Command Value Description
----------------------- ---- ----------- ------- --------------
BIND_GENERATES_RESOURCE_CHROMIUM B IsEnabled TRUE Bind generates
new resources
Conformance Tests
TBD
Issues
(1) Should the BIND_GENERATES_RESOURCE_CHROMIUM state be enabled at context
creation time or dynamically through the Enable and Disable functions?
RESOLOVED: BIND_GENERATES_RESOURCE_CHROMIUM is initialized by a context
creation attribute and cannot be modified. One of the major use cases of
this extension is to back WebGL contexts and the end user should not be
allowed to modify this state.
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
1 Sept 19, 2016 geofflang Initial version
Name
CHROMIUM_create_context_bind_generates_resource
Name Strings
EGL_CHROMIUM_create_context_bind_generates_resource
Contributors
Geoff Lang
Contacts
Geoff Lang (geofflang 'at' google.com)
Status
Draft
Version
Version 1, September 21, 2016
Number
EGL Extension #??
Dependencies
Requires EGL 1.4.
Written against the EGL 1.4 specification.
This spec interacts with GL_CHROMIUM_bind_generates_resource (or
equivalent) extension.
Overview
This extension allows the creation of an OpenGL or OpenGL ES context that
allows or disallows implicit creation of OpenGL resources on bind.
New Types
None
New Procedures and Functions
None
New Tokens
Accepted as an attribute name in the <*attrib_list> argument to
eglCreateContext:
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
Additions to the EGL 1.4 Specification
Add the following to section 3.7.1 "Creating Rendering Contexts":
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM indicates whether the context
should be created with the GL_BIND_GENERATES_RESOURCE_CHROMIUM state
initialized to GL_TRUE or GL_FALSE. The default value of
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM is EGL_TRUE.
Errors
None
New State
None
Conformance Tests
TBD
Issues
None
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
1 Sept 21, 2016 geofflang Initial version
......@@ -572,6 +572,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, E
#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
#endif /* EGL_ANGLE_create_context_webgl_compatibility */
#ifndef EGL_CHROMIUM_create_context_bind_generates_resource
#define EGL_CHROMIUM_create_context_bind_generates_resource 1
#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
#ifndef EGL_ARM_pixmap_multisample_discard
#define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286
......
......@@ -838,6 +838,11 @@ GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components);
#endif
#endif /* GL_CHROMIUM_framebuffer_mixed_samples */
#ifndef GL_CHROMIUM_bind_generates_resource
#define GL_CHROMIUM_bind_generates_resource 1
#define GL_BIND_GENERATES_RESOURCE_CHROMIUM 0x9244
#endif /* GL_CHROMIUM_bind_generates_resource */
// needed by NV_path_rendering (and thus CHROMIUM_path_rendering)
// but CHROMIUM_path_rendering only needs MatrixLoadfEXT, MatrixLoadIdentityEXT
#ifndef GL_EXT_direct_state_access
......
......@@ -167,6 +167,7 @@ Extensions::Extensions()
syncQuery(false),
copyTexture(false),
webglCompatibility(false),
bindGeneratesResource(false),
colorBufferFloat(false),
multisampleCompatibility(false),
framebufferMixedSamples(false),
......@@ -579,6 +580,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_CHROMIUM_sync_query"] = esOnlyExtension(&Extensions::syncQuery);
map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
......@@ -777,7 +779,8 @@ DisplayExtensions::DisplayExtensions()
streamConsumerGLTexture(false),
streamConsumerGLTextureYUV(false),
streamProducerD3DTextureNV12(false),
createContextWebGLCompatibility(false)
createContextWebGLCompatibility(false),
createContextBindGeneratesResource(false)
{
}
......@@ -786,34 +789,35 @@ std::vector<std::string> DisplayExtensions::getStrings() const
std::vector<std::string> extensionStrings;
// clang-format off
// | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings);
InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &extensionStrings);
InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility,&extensionStrings);
// | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings);
InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &extensionStrings);
InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility, &extensionStrings);
InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
// TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on
return extensionStrings;
......
......@@ -296,6 +296,9 @@ struct Extensions
// GL_ANGLE_webgl_compatibility
bool webglCompatibility;
// GL_CHROMIUM_bind_generates_resource
bool bindGeneratesResource;
// ES3 Extension support
// GL_EXT_color_buffer_float
......@@ -592,6 +595,9 @@ struct DisplayExtensions
// EGL_ANGLE_create_context_webgl_compatibility
bool createContextWebGLCompatibility;
// EGL_CHROMIUM_create_context_bind_generates_resource
bool createContextBindGeneratesResource;
};
struct DeviceExtensions
......
......@@ -184,6 +184,11 @@ bool GetWebGLContext(const egl::AttributeMap &attribs)
return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE);
}
bool GetBindGeneratesResource(const egl::AttributeMap &attribs)
{
return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE);
}
std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
{
std::string labelName;
......@@ -251,7 +256,8 @@ Context::Context(rx::EGLImplFactory *implFactory,
initCaps(GetWebGLContext(attribs));
mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs));
mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs),
GetBindGeneratesResource(attribs));
mFenceNVHandleAllocator.setBaseHandle(0);
......@@ -2080,13 +2086,36 @@ Framebuffer *Context::checkFramebufferAllocation(GLuint framebuffer)
return framebufferIt->second;
}
bool Context::isTextureGenerated(GLuint texture) const
{
return mResourceManager->isTextureGenerated(texture);
}
bool Context::isBufferGenerated(GLuint buffer) const
{
return mResourceManager->isBufferGenerated(buffer);
}
bool Context::isRenderbufferGenerated(GLuint renderbuffer) const
{
return mResourceManager->isRenderbufferGenerated(renderbuffer);
}
bool Context::isFramebufferGenerated(GLuint framebuffer) const
{
ASSERT(mFramebufferMap.find(0) != mFramebufferMap.end());
return mFramebufferMap.find(framebuffer) != mFramebufferMap.end();
}
bool Context::isVertexArrayGenerated(GLuint vertexArray)
{
ASSERT(mVertexArrayMap.find(0) != mVertexArrayMap.end());
return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
}
bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
{
ASSERT(mTransformFeedbackMap.find(0) != mTransformFeedbackMap.end());
return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
}
......@@ -2376,6 +2405,7 @@ void Context::initCaps(bool webGLContext)
// Some extensions are always available because they are implemented in the GL layer.
mExtensions.bindUniformLocation = true;
mExtensions.vertexArrayObject = true;
mExtensions.bindGeneratesResource = true;
// Enable the no error extension if the context was created with the flag.
mExtensions.noError = mSkipValidation;
......
......@@ -191,6 +191,10 @@ class Context final : public ValidationContext
bool isSampler(GLuint samplerName) const;
bool isTextureGenerated(GLuint texture) const;
bool isBufferGenerated(GLuint buffer) const;
bool isRenderbufferGenerated(GLuint renderbuffer) const;
bool isFramebufferGenerated(GLuint framebuffer) const;
bool isVertexArrayGenerated(GLuint vertexArray);
bool isTransformFeedbackGenerated(GLuint vertexArray);
......
......@@ -327,6 +327,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
}
}
if (getExtensions().bindGeneratesResource)
{
switch (pname)
{
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
*type = GL_BOOL;
*numParams = 1;
return true;
}
}
// Check for ES3.0+ parameter names which are also exposed as ES2 extensions
switch (pname)
{
......
......@@ -919,6 +919,7 @@ void Display::initDisplayExtensions()
mDisplayExtensions.createContext = true;
mDisplayExtensions.createContextNoError = true;
mDisplayExtensions.createContextWebGLCompatibility = true;
mDisplayExtensions.createContextBindGeneratesResource = true;
// Force EGL_KHR_get_all_proc_addresses on.
mDisplayExtensions.getAllProcAddresses = true;
......
......@@ -544,4 +544,19 @@ bool ResourceManager::isSampler(GLuint sampler)
return mSamplerMap.find(sampler) != mSamplerMap.end();
}
bool ResourceManager::isTextureGenerated(GLuint texture) const
{
return texture == 0 || mTextureMap.find(texture) != mTextureMap.end();
}
bool ResourceManager::isBufferGenerated(GLuint buffer) const
{
return buffer == 0 || mBufferMap.find(buffer) != mBufferMap.end();
}
bool ResourceManager::isRenderbufferGenerated(GLuint renderbuffer) const
{
return renderbuffer == 0 || mRenderbufferMap.find(renderbuffer) != mRenderbufferMap.end();
}
} // namespace gl
......@@ -85,6 +85,11 @@ class ResourceManager : angle::NonCopyable
bool isSampler(GLuint sampler);
// GL_CHROMIUM_bind_generates_resource
bool isTextureGenerated(GLuint texture) const;
bool isBufferGenerated(GLuint buffer) const;
bool isRenderbufferGenerated(GLuint renderbuffer) const;
private:
void createTextureInternal(GLuint handle);
......
......@@ -50,6 +50,7 @@ State::State()
mLineWidth(0),
mGenerateMipmapHint(GL_NONE),
mFragmentShaderDerivativeHint(GL_NONE),
mBindGeneratesResource(true),
mNearZ(0),
mFarZ(0),
mReadFramebuffer(nullptr),
......@@ -71,7 +72,8 @@ State::~State()
void State::initialize(const Caps &caps,
const Extensions &extensions,
GLuint clientVersion,
bool debug)
bool debug,
bool bindGeneratesResource)
{
mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
......@@ -137,6 +139,8 @@ void State::initialize(const Caps &caps,
mGenerateMipmapHint = GL_DONT_CARE;
mFragmentShaderDerivativeHint = GL_DONT_CARE;
mBindGeneratesResource = bindGeneratesResource;
mLineWidth = 1.0f;
mViewport.x = 0;
......@@ -658,6 +662,8 @@ bool State::getEnableFeature(GLenum feature) const
return mDebug.isOutputSynchronous();
case GL_DEBUG_OUTPUT:
return mDebug.isOutputEnabled();
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return isBindGeneratesResourceEnabled();
default: UNREACHABLE(); return false;
}
}
......@@ -688,6 +694,11 @@ void State::setFragmentShaderDerivativeHint(GLenum hint)
// Ignore for now. It is valid for implementations to ignore hint.
}
bool State::isBindGeneratesResourceEnabled() const
{
return mBindGeneratesResource;
}
void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
{
mViewport.x = x;
......@@ -1486,6 +1497,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
case GL_SAMPLE_ALPHA_TO_ONE_EXT:
*params = mSampleAlphaToOne;
break;
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
*params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
break;
default:
UNREACHABLE();
break;
......
......@@ -42,7 +42,8 @@ class State : angle::NonCopyable
void initialize(const Caps &caps,
const Extensions &extensions,
GLuint clientVersion,
bool debug);
bool debug,
bool bindGeneratesResource);
void reset();
// State chunk getters
......@@ -147,6 +148,9 @@ class State : angle::NonCopyable
void setGenerateMipmapHint(GLenum hint);
void setFragmentShaderDerivativeHint(GLenum hint);
// GL_CHROMIUM_bind_generates_resource
bool isBindGeneratesResourceEnabled() const;
// Viewport state setter/getter
void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
const Rectangle &getViewport() const;
......@@ -418,6 +422,8 @@ class State : angle::NonCopyable
GLenum mGenerateMipmapHint;
GLenum mFragmentShaderDerivativeHint;
bool mBindGeneratesResource;
Rectangle mViewport;
float mNearZ;
float mFarZ;
......
......@@ -342,6 +342,21 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
}
break;
case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
if (!display->getExtensions().createContextBindGeneratesResource)
{
return Error(EGL_BAD_ATTRIBUTE,
"Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
"EGL_CHROMIUM_create_context_bind_generates_resource.");
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
return Error(EGL_BAD_ATTRIBUTE,
"EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM must be EGL_TRUE or "
"EGL_FALSE.");
}
break;
default:
return Error(EGL_BAD_ATTRIBUTE);
}
......
......@@ -131,41 +131,44 @@ bool ValidReadPixelsFormatType(ValidationContext *context,
}
}
} // anonymous namespace
bool ValidCap(const Context *context, GLenum cap)
bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
{
switch (cap)
{
// EXT_multisample_compatibility
case GL_MULTISAMPLE_EXT:
case GL_SAMPLE_ALPHA_TO_ONE_EXT:
return context->getExtensions().multisampleCompatibility;
case GL_CULL_FACE:
case GL_POLYGON_OFFSET_FILL:
case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_COVERAGE:
case GL_SCISSOR_TEST:
case GL_STENCIL_TEST:
case GL_DEPTH_TEST:
case GL_BLEND:
case GL_DITHER:
return true;
// EXT_multisample_compatibility
case GL_MULTISAMPLE_EXT:
case GL_SAMPLE_ALPHA_TO_ONE_EXT:
return context->getExtensions().multisampleCompatibility;
case GL_CULL_FACE:
case GL_POLYGON_OFFSET_FILL:
case GL_SAMPLE_ALPHA_TO_COVERAGE:
case GL_SAMPLE_COVERAGE:
case GL_SCISSOR_TEST:
case GL_STENCIL_TEST:
case GL_DEPTH_TEST:
case GL_BLEND:
case GL_DITHER:
return true;
case GL_PRIMITIVE_RESTART_FIXED_INDEX:
case GL_RASTERIZER_DISCARD:
return (context->getClientMajorVersion() >= 3);
case GL_PRIMITIVE_RESTART_FIXED_INDEX:
case GL_RASTERIZER_DISCARD:
return (context->getClientMajorVersion() >= 3);
case GL_DEBUG_OUTPUT_SYNCHRONOUS:
case GL_DEBUG_OUTPUT:
return context->getExtensions().debug;
case GL_DEBUG_OUTPUT_SYNCHRONOUS:
case GL_DEBUG_OUTPUT:
return context->getExtensions().debug;
default:
return false;
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return queryOnly && context->getExtensions().bindGeneratesResource;
default:
return false;
}
}
} // anonymous namespace
bool ValidTextureTarget(const ValidationContext *context, GLenum target)
{
switch (target)
......@@ -3133,4 +3136,50 @@ bool ValidateGenOrDelete(Context *context, GLint n)
return true;
}
bool ValidateEnable(Context *context, GLenum cap)
{
if (!ValidCap(context, cap, false))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
return false;
}
if (context->getLimitations().noSampleAlphaToCoverageSupport &&
cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
{
const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
// We also output an error message to the debugger window if tracing is active, so that
// developers can see the error message.
ERR("%s", errorMessage);
return false;
}
return true;
}
bool ValidateDisable(Context *context, GLenum cap)
{
if (!ValidCap(context, cap, false))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
return false;
}
return true;
}
bool ValidateIsEnabled(Context *context, GLenum cap)
{
if (!ValidCap(context, cap, true))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
return false;
}
return true;
}
} // namespace gl
......@@ -29,7 +29,6 @@ class Program;
class Shader;
class ValidationContext;
bool ValidCap(const Context *context, GLenum cap);
bool ValidTextureTarget(const ValidationContext *context, GLenum target);
bool ValidTexture2DTarget(const ValidationContext *context, GLenum target);
bool ValidTexture3DTarget(const ValidationContext *context, GLenum target);
......@@ -270,6 +269,10 @@ bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *textures);
bool ValidateGenOrDelete(Context *context, GLint n);
bool ValidateEnable(Context *context, GLenum cap);
bool ValidateDisable(Context *context, GLenum cap);
bool ValidateIsEnabled(Context *context, GLenum cap);
// Error messages shared here for use in testing.
extern const char *g_ExceedsMaxElementErrorMessage;
} // namespace gl
......
......@@ -2187,6 +2187,13 @@ bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
return false;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isTextureGenerated(texture))
{
context->handleError(Error(GL_INVALID_OPERATION, "Texture was not generated"));
return false;
}
switch (target)
{
case GL_TEXTURE_2D:
......
......@@ -87,7 +87,7 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError)
caps.maxElementIndex = 100;
caps.maxDrawBuffers = 1;
caps.maxColorAttachments = 1;
state.initialize(caps, extensions, 3, false);
state.initialize(caps, extensions, 3, false, true);
NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
......
......@@ -123,6 +123,13 @@ void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target)
{
case GL_ARRAY_BUFFER:
......@@ -170,6 +177,13 @@ void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isFramebufferGenerated(framebuffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Framebuffer was not generated"));
return;
}
if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
{
context->bindReadFramebuffer(framebuffer);
......@@ -195,6 +209,13 @@ void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isRenderbufferGenerated(renderbuffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Renderbuffer was not generated"));
return;
}
context->bindRenderbuffer(renderbuffer);
}
}
......@@ -917,9 +938,8 @@ void GL_APIENTRY Disable(GLenum cap)
Context *context = GetValidGlobalContext();
if (context)
{
if (!ValidCap(context, cap))
if (!context->skipValidation() && !ValidateDisable(context, cap))
{
context->handleError(Error(GL_INVALID_ENUM));
return;
}
......@@ -995,26 +1015,11 @@ void GL_APIENTRY Enable(GLenum cap)
Context *context = GetValidGlobalContext();
if (context)
{
if (!ValidCap(context, cap))
if (!context->skipValidation() && !ValidateEnable(context, cap))
{
context->handleError(Error(GL_INVALID_ENUM));
return;
}
if (context->getLimitations().noSampleAlphaToCoverageSupport)
{
if (cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
{
const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
// We also output an error message to the debugger window if tracing is active, so that developers can see the error message.
ERR("%s", errorMessage);
return;
}
}
context->enable(cap);
}
}
......@@ -2677,9 +2682,8 @@ GLboolean GL_APIENTRY IsEnabled(GLenum cap)
Context *context = GetValidGlobalContext();
if (context)
{
if (!ValidCap(context, cap))
if (!context->skipValidation() && !ValidateIsEnabled(context, cap))
{
context->handleError(Error(GL_INVALID_ENUM));
return GL_FALSE;
}
......
......@@ -759,6 +759,13 @@ void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER:
......@@ -841,6 +848,13 @@ void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
return;
}
if (!context->getGLState().isBindGeneratesResourceEnabled() &&
!context->isBufferGenerated(buffer))
{
context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
return;
}
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER:
......
......@@ -15,6 +15,7 @@
{
'angle_end2end_tests_sources':
[
'<(angle_path)/src/tests/gl_tests/BindGeneratesResourceTest.cpp',
'<(angle_path)/src/tests/gl_tests/BindUniformLocationTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlendMinMaxTest.cpp',
'<(angle_path)/src/tests/gl_tests/BlitFramebufferANGLETest.cpp',
......
//
// Copyright 2015 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.
//
// BindGeneratesResourceTest.cpp : Tests of the GL_CHROMIUM_bind_generates_resource extension.
#include "test_utils/ANGLETest.h"
namespace angle
{
class BindGeneratesResourceTest : public ANGLETest
{
protected:
BindGeneratesResourceTest() { setBindGeneratesResource(false); }
};
// Context creation would fail if EGL_CHROMIUM_create_context_bind_generates_resource was not
// available so the GL extension should always be present
TEST_P(BindGeneratesResourceTest, ExtensionStringExposed)
{
EXPECT_TRUE(extensionEnabled("GL_CHROMIUM_bind_generates_resource"));
}
// Verify that GL_BIND_GENERATES_RESOURCE_CHROMIUM can be queried but not changed
TEST_P(BindGeneratesResourceTest, QueryValidation)
{
GLint intValue = 2;
glGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &intValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(intValue, GL_FALSE);
float floatValue = 2.0f;
glGetFloatv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &floatValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(floatValue, 0.0f);
GLboolean boolValue = GL_TRUE;
glGetBooleanv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, &boolValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(boolValue, GL_FALSE);
boolValue = glIsEnabled(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(boolValue, GL_FALSE);
glEnable(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glDisable(GL_BIND_GENERATES_RESOURCE_CHROMIUM);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
// Test that buffers cannot be generated on bind
TEST_P(BindGeneratesResourceTest, Buffers)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
EXPECT_GL_NO_ERROR();
if (getClientMajorVersion() >= 3)
{
glBindBufferBase(GL_UNIFORM_BUFFER, 0, 3);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
EXPECT_GL_NO_ERROR();
glBindBufferRange(GL_UNIFORM_BUFFER, 0, 4, 1, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, 0, 1, 2);
EXPECT_GL_NO_ERROR();
}
}
// Test that textures cannot be generated on bind
TEST_P(BindGeneratesResourceTest, Textures)
{
glBindTexture(GL_TEXTURE_2D, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindTexture(GL_TEXTURE_2D, 0);
EXPECT_GL_NO_ERROR();
}
// Test that framebuffers cannot be generated on bind
TEST_P(BindGeneratesResourceTest, Framebuffers)
{
glBindFramebuffer(GL_FRAMEBUFFER, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
EXPECT_GL_NO_ERROR();
}
// Test that renderbuffer cannot be generated on bind
TEST_P(BindGeneratesResourceTest, Renderbuffers)
{
glBindRenderbuffer(GL_RENDERBUFFER, 2);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
EXPECT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(BindGeneratesResourceTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_D3D11_FL9_3(),
ES2_OPENGL(),
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
} // namespace
......@@ -609,6 +609,11 @@ void ANGLETest::setWebGLCompatibilityEnabled(bool webglCompatibility)
mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility);
}
void ANGLETest::setBindGeneratesResource(bool bindGeneratesResource)
{
mEGLWindow->setBindGeneratesResource(bindGeneratesResource);
}
int ANGLETest::getClientMajorVersion() const
{
return mEGLWindow->getClientMajorVersion();
......
......@@ -185,6 +185,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
void setDebugEnabled(bool enabled);
void setNoErrorEnabled(bool enabled);
void setWebGLCompatibilityEnabled(bool webglCompatibility);
void setBindGeneratesResource(bool bindGeneratesResource);
int getClientMajorVersion() const;
int getClientMinorVersion() const;
......
......@@ -111,6 +111,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion,
mDebug(false),
mNoError(false),
mWebGLCompatibility(false),
mBindGeneratesResource(true),
mSwapInterval(-1)
{
}
......@@ -216,6 +217,14 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
return false;
}
bool hasBindGeneratesResource =
strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
if (!mBindGeneratesResource && !hasBindGeneratesResource)
{
destroyGL();
return false;
}
eglBindAPI(EGL_OPENGL_ES_API);
if (eglGetError() != EGL_SUCCESS)
{
......@@ -290,6 +299,12 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
contextAttributes.push_back(mWebGLCompatibility ? EGL_TRUE : EGL_FALSE);
}
if (hasBindGeneratesResource)
{
contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
contextAttributes.push_back(mBindGeneratesResource ? EGL_TRUE : EGL_FALSE);
}
}
contextAttributes.push_back(EGL_NONE);
......
......@@ -72,6 +72,10 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
{
mWebGLCompatibility = webglCompatibility;
}
void setBindGeneratesResource(bool bindGeneratesResource)
{
mBindGeneratesResource = bindGeneratesResource;
}
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
......@@ -118,6 +122,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
bool mDebug;
bool mNoError;
bool mWebGLCompatibility;
bool mBindGeneratesResource;
EGLint mSwapInterval;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment