Commit feb8c686 by Geoff Lang Committed by Commit Bot

Add extensions to disable client arrays.

Chrome doesn't allow any client data in its command buffer. Add an ANGLE extension to request a context that disallows client data. BUG=602737 Change-Id: If9d5144daea3c629a73562396000df59a671aad3 Reviewed-on: https://chromium-review.googlesource.com/441986 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 4336489f
Name
ANGLE_client_arrays
Name Strings
GL_ANGLE_client_arrays
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, February 13, 2016
Number
OpenGL ES Extension #??
Dependencies
Requires OpenGL ES 2.0
Written against the OpenGL ES 2.0 specification.
Overview
This extension allows the OpenGL context to indicate if it supports drawing
with client-side vertex or index data. Client-side can be very inefficient
and unsafe, it is convenient for some users to completely disable its usage.
New Procedures and Functions
None
New Tokens
Accepted by the <cap> parameter to IsEnabled and the <pname> parameter to
GetBooleanv, GetIntegerv, GetFloatv, and GetInteger64v:
CLIENT_ARRAYS_ANGLE 0x93AA
Additions to the OpenGL ES Specification
Add after paragraph 3 of section 2.8 "Vertex Arrays":
If VertexAttribPointer is called while zero is bound to the ARRAY_BUFFER
buffer object binding point, the pointer argument is not NULL, and
CLIENT_ARRAYS_ANGLE is TRUE, an INVALID_OPERATION error is generated.
Add to the end of section 2.9.1 "Vertex Arrays in Buffer Objects":
Rendering commands that draw more than 0 primitives using enabled vertex
attributes with no buffer bound when CLIENT_ARRAYS_ANGLE is TRUE generate
an INVALID_OPERATION error.
Add to the end of section 2.9.2 "Array Indices in Buffer Objects":
Rendering commands that draw more than 0 primitives using index data when
no buffer is bound to the ELEMENT_ARRAY_BUFFER binding point when
CLIENT_ARRAYS_ANGLE is TRUE generate an INVALID_OPERATION error.
New State
Modify Table 6.22, Miscellaneous
Add:
Initial
Get Value Type Get Command Value Description
-------------------- ---- ----------- ------- ---------------------
CLIENT_ARRAYS_ANGLE B IsEnabled TRUE Client arrays enabled
Conformance Tests
TBD
Issues
None
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
1 Feb 13, 2016 geofflang Initial version
Name
ANGLE_create_context_client_arrays
Name Strings
EGL_ANGLE_create_context_client_arrays
Contributors
Geoff Lang
Contacts
Geoff Lang (geofflang 'at' google.com)
Status
Draft
Version
Version 1, February 13, 2016
Number
EGL Extension #??
Dependencies
Requires EGL 1.4.
Written against the EGL 1.4 specification.
An OpenGL ES implementation supporting GL_ANGLE_client_arrays or equivalent
functionality is required.
Overview
This extension allows the creation of an OpenGL or OpenGL ES context that
allows or disallows drawing with client-side vertex or index data.
New Types
None
New Procedures and Functions
None
New Tokens
Accepted as an attribute name in the <*attrib_list> argument to
eglCreateContext:
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
Additions to the EGL 1.4 Specification
Add the following to section 3.7.1 "Creating Rendering Contexts":
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE indicates whether the context
should be created with the GL_CLIENT_ARRAYS_ANGLE state initialized to
GL_TRUE or GL_FALSE. The default value of
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE is EGL_FALSE.
Errors
None
New State
None
Conformance Tests
TBD
Issues
None
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
1 Feb 13, 2016 geofflang Initial version
...@@ -660,6 +660,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, E ...@@ -660,6 +660,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, E
#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD #define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */ #endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
#ifndef EGL_ANGLE_create_context_client_arrays
#define EGL_ANGLE_create_context_client_arrays 1
#define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
#endif /* EGL_ANGLE_create_context_client_arrays */
#ifndef EGL_ARM_implicit_external_sync #ifndef EGL_ARM_implicit_external_sync
#define EGL_ARM_implicit_external_sync 1 #define EGL_ARM_implicit_external_sync 1
#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A #define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
......
...@@ -867,6 +867,11 @@ GL_APICALL GLboolean GL_APIENTRY glRequestExtensionANGLE (const GLchar *name); ...@@ -867,6 +867,11 @@ GL_APICALL GLboolean GL_APIENTRY glRequestExtensionANGLE (const GLchar *name);
#endif #endif
#endif /* GL_ANGLE_webgl_compatibility */ #endif /* GL_ANGLE_webgl_compatibility */
#ifndef GL_ANGLE_client_arrays
#define GL_ANGLE_client_arrays 1
#define GL_CLIENT_ARRAYS_ANGLE 0x93AA
#endif /* GL_ANGLE_client_arrays */
#ifndef GL_CHROMIUM_framebuffer_mixed_samples #ifndef GL_CHROMIUM_framebuffer_mixed_samples
#define GL_CHROMIUM_frambuffer_mixed_samples 1 #define GL_CHROMIUM_frambuffer_mixed_samples 1
#define GL_COVERAGE_MODULATION_CHROMIUM 0x9332 #define GL_COVERAGE_MODULATION_CHROMIUM 0x9332
......
...@@ -213,7 +213,8 @@ Extensions::Extensions() ...@@ -213,7 +213,8 @@ Extensions::Extensions()
framebufferMixedSamples(false), framebufferMixedSamples(false),
textureNorm16(false), textureNorm16(false),
pathRendering(false), pathRendering(false),
surfacelessContext(false) surfacelessContext(false),
clientArrays(false)
{ {
} }
...@@ -646,6 +647,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -646,6 +647,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16); map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering); map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContext); map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContext);
map["GL_ANGLE_client_arrays"] = esOnlyExtension(&Extensions::clientArrays);
// clang-format on // clang-format on
return map; return map;
...@@ -1034,7 +1036,8 @@ DisplayExtensions::DisplayExtensions() ...@@ -1034,7 +1036,8 @@ DisplayExtensions::DisplayExtensions()
swapBuffersWithDamage(false), swapBuffersWithDamage(false),
pixelFormatFloat(false), pixelFormatFloat(false),
surfacelessContext(false), surfacelessContext(false),
displayTextureShareGroup(false) displayTextureShareGroup(false),
createContextClientArrays(false)
{ {
} }
...@@ -1074,7 +1077,8 @@ std::vector<std::string> DisplayExtensions::getStrings() const ...@@ -1074,7 +1077,8 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_EXT_swap_buffers_with_damage", swapBuffersWithDamage, &extensionStrings); InsertExtensionString("EGL_EXT_swap_buffers_with_damage", swapBuffersWithDamage, &extensionStrings);
InsertExtensionString("EGL_EXT_pixel_format_float", pixelFormatFloat, &extensionStrings); InsertExtensionString("EGL_EXT_pixel_format_float", pixelFormatFloat, &extensionStrings);
InsertExtensionString("EGL_KHR_surfaceless_context", surfacelessContext, &extensionStrings); InsertExtensionString("EGL_KHR_surfaceless_context", surfacelessContext, &extensionStrings);
InsertExtensionString("EGL_ANGLE_display_texture_share_group", displayTextureShareGroup, &extensionStrings); InsertExtensionString("EGL_ANGLE_display_texture_share_group", displayTextureShareGroup, &extensionStrings);
InsertExtensionString("EGL_ANGLE_create_context_client_arrays", createContextClientArrays, &extensionStrings);
// TODO(jmadill): Enable this when complete. // 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 // clang-format on
......
...@@ -351,6 +351,9 @@ struct Extensions ...@@ -351,6 +351,9 @@ struct Extensions
// GL_OES_surfaceless_context // GL_OES_surfaceless_context
bool surfacelessContext; bool surfacelessContext;
// GL_ANGLE_client_arrays
bool clientArrays;
}; };
struct ExtensionInfo struct ExtensionInfo
...@@ -649,6 +652,9 @@ struct DisplayExtensions ...@@ -649,6 +652,9 @@ struct DisplayExtensions
// EGL_ANGLE_display_texture_share_group // EGL_ANGLE_display_texture_share_group
bool displayTextureShareGroup; bool displayTextureShareGroup;
// EGL_ANGLE_create_context_client_arrays
bool createContextClientArrays;
}; };
struct DeviceExtensions struct DeviceExtensions
......
...@@ -198,6 +198,11 @@ bool GetBindGeneratesResource(const egl::AttributeMap &attribs) ...@@ -198,6 +198,11 @@ bool GetBindGeneratesResource(const egl::AttributeMap &attribs)
return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE); return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE);
} }
bool GetClientArraysEnabled(const egl::AttributeMap &attribs)
{
return (attribs.get(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE) == EGL_TRUE);
}
std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label) std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
{ {
std::string labelName; std::string labelName;
...@@ -271,7 +276,7 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -271,7 +276,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
initWorkarounds(); initWorkarounds();
mGLState.initialize(mCaps, mExtensions, getClientVersion(), GetDebug(attribs), mGLState.initialize(mCaps, mExtensions, getClientVersion(), GetDebug(attribs),
GetBindGeneratesResource(attribs)); GetBindGeneratesResource(attribs), GetClientArraysEnabled(attribs));
mFenceNVHandleAllocator.setBaseHandle(0); mFenceNVHandleAllocator.setBaseHandle(0);
...@@ -2429,6 +2434,7 @@ void Context::initCaps(bool webGLContext, const egl::DisplayExtensions &displayE ...@@ -2429,6 +2434,7 @@ void Context::initCaps(bool webGLContext, const egl::DisplayExtensions &displayE
mExtensions.bindUniformLocation = true; mExtensions.bindUniformLocation = true;
mExtensions.vertexArrayObject = true; mExtensions.vertexArrayObject = true;
mExtensions.bindGeneratesResource = true; mExtensions.bindGeneratesResource = true;
mExtensions.clientArrays = true;
mExtensions.requestExtension = true; mExtensions.requestExtension = true;
// Enable the no error extension if the context was created with the flag. // Enable the no error extension if the context was created with the flag.
......
...@@ -406,6 +406,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign ...@@ -406,6 +406,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
} }
} }
if (getExtensions().clientArrays)
{
switch (pname)
{
case GL_CLIENT_ARRAYS_ANGLE:
*type = GL_BOOL;
*numParams = 1;
return true;
}
}
if (getExtensions().sRGBWriteControl) if (getExtensions().sRGBWriteControl)
{ {
switch (pname) switch (pname)
......
...@@ -917,6 +917,7 @@ void Display::initDisplayExtensions() ...@@ -917,6 +917,7 @@ void Display::initDisplayExtensions()
mDisplayExtensions.createContextNoError = true; mDisplayExtensions.createContextNoError = true;
mDisplayExtensions.createContextWebGLCompatibility = true; mDisplayExtensions.createContextWebGLCompatibility = true;
mDisplayExtensions.createContextBindGeneratesResource = true; mDisplayExtensions.createContextBindGeneratesResource = true;
mDisplayExtensions.createContextClientArrays = true;
mDisplayExtensions.pixelFormatFloat = true; mDisplayExtensions.pixelFormatFloat = true;
// Force EGL_KHR_get_all_proc_addresses on. // Force EGL_KHR_get_all_proc_addresses on.
......
...@@ -51,6 +51,7 @@ State::State() ...@@ -51,6 +51,7 @@ State::State()
mGenerateMipmapHint(GL_NONE), mGenerateMipmapHint(GL_NONE),
mFragmentShaderDerivativeHint(GL_NONE), mFragmentShaderDerivativeHint(GL_NONE),
mBindGeneratesResource(true), mBindGeneratesResource(true),
mClientArraysEnabled(true),
mNearZ(0), mNearZ(0),
mFarZ(0), mFarZ(0),
mReadFramebuffer(nullptr), mReadFramebuffer(nullptr),
...@@ -73,7 +74,8 @@ void State::initialize(const Caps &caps, ...@@ -73,7 +74,8 @@ void State::initialize(const Caps &caps,
const Extensions &extensions, const Extensions &extensions,
const Version &clientVersion, const Version &clientVersion,
bool debug, bool debug,
bool bindGeneratesResource) bool bindGeneratesResource,
bool clientArraysEnabled)
{ {
mMaxDrawBuffers = caps.maxDrawBuffers; mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
...@@ -140,6 +142,7 @@ void State::initialize(const Caps &caps, ...@@ -140,6 +142,7 @@ void State::initialize(const Caps &caps,
mFragmentShaderDerivativeHint = GL_DONT_CARE; mFragmentShaderDerivativeHint = GL_DONT_CARE;
mBindGeneratesResource = bindGeneratesResource; mBindGeneratesResource = bindGeneratesResource;
mClientArraysEnabled = clientArraysEnabled;
mLineWidth = 1.0f; mLineWidth = 1.0f;
...@@ -682,6 +685,8 @@ bool State::getEnableFeature(GLenum feature) const ...@@ -682,6 +685,8 @@ bool State::getEnableFeature(GLenum feature) const
return mDebug.isOutputEnabled(); return mDebug.isOutputEnabled();
case GL_BIND_GENERATES_RESOURCE_CHROMIUM: case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return isBindGeneratesResourceEnabled(); return isBindGeneratesResourceEnabled();
case GL_CLIENT_ARRAYS_ANGLE:
return areClientArraysEnabled();
case GL_FRAMEBUFFER_SRGB_EXT: case GL_FRAMEBUFFER_SRGB_EXT:
return getFramebufferSRGB(); return getFramebufferSRGB();
default: UNREACHABLE(); return false; default: UNREACHABLE(); return false;
...@@ -719,6 +724,11 @@ bool State::isBindGeneratesResourceEnabled() const ...@@ -719,6 +724,11 @@ bool State::isBindGeneratesResourceEnabled() const
return mBindGeneratesResource; return mBindGeneratesResource;
} }
bool State::areClientArraysEnabled() const
{
return mClientArraysEnabled;
}
void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
{ {
mViewport.x = x; mViewport.x = x;
...@@ -1545,6 +1555,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params) ...@@ -1545,6 +1555,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
case GL_BIND_GENERATES_RESOURCE_CHROMIUM: case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
*params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE; *params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
break; break;
case GL_CLIENT_ARRAYS_ANGLE:
*params = areClientArraysEnabled() ? GL_TRUE : GL_FALSE;
break;
case GL_FRAMEBUFFER_SRGB_EXT: case GL_FRAMEBUFFER_SRGB_EXT:
*params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE; *params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
break; break;
......
...@@ -44,7 +44,8 @@ class State : angle::NonCopyable ...@@ -44,7 +44,8 @@ class State : angle::NonCopyable
const Extensions &extensions, const Extensions &extensions,
const Version &clientVersion, const Version &clientVersion,
bool debug, bool debug,
bool bindGeneratesResource); bool bindGeneratesResource,
bool clientArraysEnabled);
void reset(const Context *context); void reset(const Context *context);
// State chunk getters // State chunk getters
...@@ -152,6 +153,9 @@ class State : angle::NonCopyable ...@@ -152,6 +153,9 @@ class State : angle::NonCopyable
// GL_CHROMIUM_bind_generates_resource // GL_CHROMIUM_bind_generates_resource
bool isBindGeneratesResourceEnabled() const; bool isBindGeneratesResourceEnabled() const;
// GL_ANGLE_client_arrays
bool areClientArraysEnabled() const;
// Viewport state setter/getter // Viewport state setter/getter
void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
const Rectangle &getViewport() const; const Rectangle &getViewport() const;
...@@ -433,6 +437,7 @@ class State : angle::NonCopyable ...@@ -433,6 +437,7 @@ class State : angle::NonCopyable
GLenum mFragmentShaderDerivativeHint; GLenum mFragmentShaderDerivativeHint;
bool mBindGeneratesResource; bool mBindGeneratesResource;
bool mClientArraysEnabled;
Rectangle mViewport; Rectangle mViewport;
float mNearZ; float mNearZ;
......
...@@ -449,6 +449,21 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context ...@@ -449,6 +449,21 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
} }
break; break;
case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
if (!display->getExtensions().createContextClientArrays)
{
return Error(EGL_BAD_ATTRIBUTE,
"Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
"EGL_ANGLE_create_context_client_arrays.");
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
return Error(EGL_BAD_ATTRIBUTE,
"EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must be EGL_TRUE or "
"EGL_FALSE.");
}
break;
default: default:
return Error(EGL_BAD_ATTRIBUTE, "Unknown attribute."); return Error(EGL_BAD_ATTRIBUTE, "Unknown attribute.");
} }
......
...@@ -59,7 +59,7 @@ bool ValidateDrawAttribs(ValidationContext *context, ...@@ -59,7 +59,7 @@ bool ValidateDrawAttribs(ValidationContext *context,
gl::Buffer *buffer = attrib.buffer.get(); gl::Buffer *buffer = attrib.buffer.get();
if (!buffer) if (!buffer)
{ {
if (webglCompatibility) if (webglCompatibility || !state.areClientArraysEnabled())
{ {
// [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
// If a vertex attribute is enabled as an array via enableVertexAttribArray but // If a vertex attribute is enabled as an array via enableVertexAttribArray but
...@@ -205,6 +205,9 @@ bool ValidCap(const Context *context, GLenum cap, bool queryOnly) ...@@ -205,6 +205,9 @@ bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
case GL_BIND_GENERATES_RESOURCE_CHROMIUM: case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return queryOnly && context->getExtensions().bindGeneratesResource; return queryOnly && context->getExtensions().bindGeneratesResource;
case GL_CLIENT_ARRAYS_ANGLE:
return queryOnly && context->getExtensions().clientArrays;
case GL_FRAMEBUFFER_SRGB_EXT: case GL_FRAMEBUFFER_SRGB_EXT:
return context->getExtensions().sRGBWriteControl; return context->getExtensions().sRGBWriteControl;
...@@ -3484,6 +3487,11 @@ bool ValidateDrawElements(ValidationContext *context, ...@@ -3484,6 +3487,11 @@ bool ValidateDrawElements(ValidationContext *context,
"indices must be a multiple of the element type size.")); "indices must be a multiple of the element type size."));
return false; return false;
} }
}
if (context->getExtensions().webglCompatibility ||
!context->getGLState().areClientArraysEnabled())
{
if (!elementArrayBuffer && count > 0) if (!elementArrayBuffer && count > 0)
{ {
// [WebGL 1.0] Section 6.2 No Client Side Arrays // [WebGL 1.0] Section 6.2 No Client Side Arrays
......
...@@ -3957,8 +3957,9 @@ bool ValidateVertexAttribPointer(ValidationContext *context, ...@@ -3957,8 +3957,9 @@ bool ValidateVertexAttribPointer(ValidationContext *context,
// An INVALID_OPERATION error is generated when a non-zero vertex array object // An INVALID_OPERATION error is generated when a non-zero vertex array object
// is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
// and the pointer argument is not NULL. // and the pointer argument is not NULL.
if (context->getGLState().getVertexArray()->id() != 0 && bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
context->getGLState().getArrayBufferId() == 0 && ptr != NULL) context->getGLState().getVertexArray()->id() == 0;
if (!nullBufferAllowed && context->getGLState().getArrayBufferId() == 0 && ptr != NULL)
{ {
context->handleError( context->handleError(
Error(GL_INVALID_OPERATION, Error(GL_INVALID_OPERATION,
......
...@@ -78,7 +78,7 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError) ...@@ -78,7 +78,7 @@ TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError)
caps.maxElementIndex = 100; caps.maxElementIndex = 100;
caps.maxDrawBuffers = 1; caps.maxDrawBuffers = 1;
caps.maxColorAttachments = 1; caps.maxColorAttachments = 1;
state.initialize(caps, extensions, Version(3, 0), false, true); state.initialize(caps, extensions, Version(3, 0), false, true, true);
NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>(); NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl)); EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
'<(angle_path)/src/tests/gl_tests/BufferDataTest.cpp', '<(angle_path)/src/tests/gl_tests/BufferDataTest.cpp',
'<(angle_path)/src/tests/gl_tests/BuiltinVariableTest.cpp', '<(angle_path)/src/tests/gl_tests/BuiltinVariableTest.cpp',
'<(angle_path)/src/tests/gl_tests/ClearTest.cpp', '<(angle_path)/src/tests/gl_tests/ClearTest.cpp',
'<(angle_path)/src/tests/gl_tests/ClientArraysTest.cpp',
'<(angle_path)/src/tests/gl_tests/ColorMaskTest.cpp', '<(angle_path)/src/tests/gl_tests/ColorMaskTest.cpp',
'<(angle_path)/src/tests/gl_tests/ComputeShaderTest.cpp', '<(angle_path)/src/tests/gl_tests/ComputeShaderTest.cpp',
'<(angle_path)/src/tests/gl_tests/CopyCompressedTextureTest.cpp', '<(angle_path)/src/tests/gl_tests/CopyCompressedTextureTest.cpp',
......
//
// 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.
//
// ClientArraysTest.cpp : Tests of the GL_ANGLE_client_arrays extension.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
namespace angle
{
class ClientArraysTest : public ANGLETest
{
protected:
ClientArraysTest()
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setClientArraysEnabled(false);
}
};
// Context creation would fail if EGL_ANGLE_create_context_client_arrays was not available so
// the GL extension should always be present
TEST_P(ClientArraysTest, ExtensionStringExposed)
{
EXPECT_TRUE(extensionEnabled("GL_ANGLE_client_arrays"));
}
// Verify that GL_CLIENT_ARRAYS_ANGLE can be queried but not changed
TEST_P(ClientArraysTest, QueryValidation)
{
GLint intValue = 2;
glGetIntegerv(GL_CLIENT_ARRAYS_ANGLE, &intValue);
EXPECT_GL_NO_ERROR();
EXPECT_GL_FALSE(intValue);
float floatValue = 2.0f;
glGetFloatv(GL_CLIENT_ARRAYS_ANGLE, &floatValue);
EXPECT_GL_NO_ERROR();
EXPECT_EQ(0.0f, floatValue);
GLboolean boolValue = GL_TRUE;
glGetBooleanv(GL_CLIENT_ARRAYS_ANGLE, &boolValue);
EXPECT_GL_NO_ERROR();
EXPECT_GL_FALSE(GL_FALSE);
EXPECT_GL_FALSE(glIsEnabled(GL_CLIENT_ARRAYS_ANGLE));
EXPECT_GL_NO_ERROR();
glEnable(GL_CLIENT_ARRAYS_ANGLE);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
glDisable(GL_CLIENT_ARRAYS_ANGLE);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
// Test that client-side array buffers are forbidden when client arrays are disabled
TEST_P(ClientArraysTest, ForbidsClientSideArrayBuffer)
{
const auto &vertices = GetQuadVertices();
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4, vertices.data());
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
}
// Test that client-side element array buffers are forbidden when client arrays are disabled
TEST_P(ClientArraysTest, ForbidsClientSideElementBuffer)
{
ASSERT_GL_FALSE(glIsEnabled(GL_CLIENT_ARRAYS_ANGLE));
const std::string &vert =
"attribute vec3 a_pos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(a_pos, 1.0);\n"
"}\n";
const std::string &frag =
"precision highp float;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
ANGLE_GL_PROGRAM(program, vert, frag);
GLint posLocation = glGetAttribLocation(program.get(), "a_pos");
ASSERT_NE(-1, posLocation);
glUseProgram(program.get());
const auto &vertices = GetQuadVertices();
GLBuffer vertexBuffer;
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
GL_STATIC_DRAW);
glVertexAttribPointer(posLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(posLocation);
const GLubyte indices[] = {0, 1, 2, 3, 4, 5};
ASSERT_GL_NO_ERROR();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(ClientArraysTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_D3D11_FL9_3(),
ES2_OPENGL(),
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
} // namespace
...@@ -701,6 +701,11 @@ void ANGLETest::setVulkanLayersEnabled(bool enabled) ...@@ -701,6 +701,11 @@ void ANGLETest::setVulkanLayersEnabled(bool enabled)
mEGLWindow->setVulkanLayersEnabled(enabled); mEGLWindow->setVulkanLayersEnabled(enabled);
} }
void ANGLETest::setClientArraysEnabled(bool enabled)
{
mEGLWindow->setClientArraysEnabled(enabled);
}
int ANGLETest::getClientMajorVersion() const int ANGLETest::getClientMajorVersion() const
{ {
return mEGLWindow->getClientMajorVersion(); return mEGLWindow->getClientMajorVersion();
......
...@@ -237,6 +237,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters> ...@@ -237,6 +237,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
void setWebGLCompatibilityEnabled(bool webglCompatibility); void setWebGLCompatibilityEnabled(bool webglCompatibility);
void setBindGeneratesResource(bool bindGeneratesResource); void setBindGeneratesResource(bool bindGeneratesResource);
void setVulkanLayersEnabled(bool enabled); void setVulkanLayersEnabled(bool enabled);
void setClientArraysEnabled(bool enabled);
int getClientMajorVersion() const; int getClientMajorVersion() const;
int getClientMinorVersion() const; int getClientMinorVersion() const;
......
...@@ -113,6 +113,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion, ...@@ -113,6 +113,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion,
mNoError(false), mNoError(false),
mWebGLCompatibility(false), mWebGLCompatibility(false),
mBindGeneratesResource(true), mBindGeneratesResource(true),
mClientArraysEnabled(true),
mSwapInterval(-1) mSwapInterval(-1)
{ {
} }
...@@ -234,6 +235,15 @@ bool EGLWindow::initializeGL(OSWindow *osWindow) ...@@ -234,6 +235,15 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
return false; return false;
} }
bool hasClientArraysExtension =
strstr(displayExtensions, "EGL_ANGLE_create_context_client_arrays") != nullptr;
if (!mClientArraysEnabled && !hasClientArraysExtension)
{
// Non-default state requested without the extension present
destroyGL();
return false;
}
eglBindAPI(EGL_OPENGL_ES_API); eglBindAPI(EGL_OPENGL_ES_API);
if (eglGetError() != EGL_SUCCESS) if (eglGetError() != EGL_SUCCESS)
{ {
...@@ -327,6 +337,12 @@ bool EGLWindow::initializeGL(OSWindow *osWindow) ...@@ -327,6 +337,12 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM); contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
contextAttributes.push_back(mBindGeneratesResource ? EGL_TRUE : EGL_FALSE); contextAttributes.push_back(mBindGeneratesResource ? EGL_TRUE : EGL_FALSE);
} }
if (hasClientArraysExtension)
{
contextAttributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
contextAttributes.push_back(mClientArraysEnabled ? EGL_TRUE : EGL_FALSE);
}
} }
contextAttributes.push_back(EGL_NONE); contextAttributes.push_back(EGL_NONE);
......
...@@ -79,6 +79,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable ...@@ -79,6 +79,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
mBindGeneratesResource = bindGeneratesResource; mBindGeneratesResource = bindGeneratesResource;
} }
void setVulkanLayersEnabled(bool enabled) { mVulkanLayersEnabled = enabled; } void setVulkanLayersEnabled(bool enabled) { mVulkanLayersEnabled = enabled; }
void setClientArraysEnabled(bool enabled) { mClientArraysEnabled = enabled; }
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; } void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config); static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
...@@ -127,6 +128,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable ...@@ -127,6 +128,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
bool mNoError; bool mNoError;
bool mWebGLCompatibility; bool mWebGLCompatibility;
bool mBindGeneratesResource; bool mBindGeneratesResource;
bool mClientArraysEnabled;
EGLint mSwapInterval; EGLint mSwapInterval;
Optional<bool> mVulkanLayersEnabled; Optional<bool> mVulkanLayersEnabled;
}; };
......
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