Re-re-land "Add GL_OES_vertex_array_object to D3D11 and GL renderers"
+ Include fixed validation logic for GL_UNPACK_SKIP_IMAGES and GL_UNPACK_ROW_LENGTH
+ Include fix for Clang build break
BUG=angleproject:1186
Change-Id: I403a066e29614f532db6931755265d2ee088d442
Reviewed-on: https://chromium-review.googlesource.com/308746
Tested-by: Austin Kinross <aukinros@microsoft.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index b57d30c..40511f0 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -141,6 +141,7 @@
eglImageExternalEssl3(false),
unpackSubimage(false),
packSubimage(false),
+ vertexArrayObject(false),
colorBufferFloat(false)
{
}
@@ -201,6 +202,7 @@
InsertExtensionString("GL_EXT_unpack_subimage", unpackSubimage, &extensionStrings);
InsertExtensionString("GL_NV_pack_subimage", packSubimage, &extensionStrings);
InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
+ InsertExtensionString("GL_OES_vertex_array_object", vertexArrayObject, &extensionStrings);
// clang-format on
return extensionStrings;
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index 1ed6783..8162dd0 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -239,6 +239,9 @@
// NV_pack_subimage
bool packSubimage;
+ // GL_OES_vertex_array_object
+ bool vertexArrayObject;
+
// ES3 Extension support
// GL_EXT_color_buffer_float
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index cef4037..5d7b22c 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -1107,26 +1107,6 @@
}
}
return true;
- case GL_PACK_ROW_LENGTH:
- case GL_PACK_SKIP_ROWS:
- case GL_PACK_SKIP_PIXELS:
- if ((mClientVersion < 3) && !mExtensions.packSubimage)
- {
- return false;
- }
- *type = GL_INT;
- *numParams = 1;
- return true;
- case GL_UNPACK_ROW_LENGTH:
- case GL_UNPACK_SKIP_ROWS:
- case GL_UNPACK_SKIP_PIXELS:
- if ((mClientVersion < 3) && !mExtensions.unpackSubimage)
- {
- return false;
- }
- *type = GL_INT;
- *numParams = 1;
- return true;
case GL_MAX_VIEWPORT_DIMS:
{
*type = GL_INT;
@@ -1199,6 +1179,39 @@
return true;
}
+ // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
+ switch (pname)
+ {
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ if ((mClientVersion < 3) && !mExtensions.packSubimage)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ if ((mClientVersion < 3) && !mExtensions.unpackSubimage)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_VERTEX_ARRAY_BINDING:
+ if ((mClientVersion < 3) && !mExtensions.vertexArrayObject)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
if (mClientVersion < 3)
{
return false;
@@ -1224,7 +1237,6 @@
case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
case GL_MAX_VARYING_COMPONENTS:
- case GL_VERTEX_ARRAY_BINDING:
case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
case GL_MIN_PROGRAM_TEXEL_OFFSET:
@@ -1237,14 +1249,8 @@
case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
- case GL_PACK_ROW_LENGTH:
- case GL_PACK_SKIP_ROWS:
- case GL_PACK_SKIP_PIXELS:
- case GL_UNPACK_ROW_LENGTH:
case GL_UNPACK_IMAGE_HEIGHT:
case GL_UNPACK_SKIP_IMAGES:
- case GL_UNPACK_SKIP_ROWS:
- case GL_UNPACK_SKIP_PIXELS:
{
*type = GL_INT;
*numParams = 1;
diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index 72462e9..76e541c 100644
--- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -1215,6 +1215,7 @@
extensions->eglImage = true;
extensions->unpackSubimage = true;
extensions->packSubimage = true;
+ extensions->vertexArrayObject = true;
// D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
// D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing.
diff --git a/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
index ed9c146..b931035 100644
--- a/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -576,6 +576,7 @@
extensions->eglImage = true;
extensions->unpackSubimage = true;
extensions->packSubimage = true;
+ extensions->vertexArrayObject = true;
// D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil
// state.
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp
index a47a7cd..3988a0c 100644
--- a/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -578,6 +578,9 @@
extensions->debugMarker =
functions->isAtLeastGL(gl::Version(4, 3)) || functions->hasGLExtension("GL_KHR_debug") ||
functions->isAtLeastGLES(gl::Version(3, 2)) || functions->hasGLESExtension("GL_KHR_debug");
+
+ // ANGLE emulates vertex array objects in its GL layer
+ extensions->vertexArrayObject = true;
}
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 8a59c06..fc90330 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -2173,4 +2173,41 @@
return true;
}
+
+bool ValidateBindVertexArrayBase(Context *context, GLuint array)
+{
+ VertexArray *vao = context->getVertexArray(array);
+
+ if (!vao)
+ {
+ // The default VAO should always exist
+ ASSERT(array != 0);
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeleteVertexArraysBase(Context *context, GLsizei n)
+{
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGenVertexArraysBase(Context *context, GLsizei n)
+{
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
}
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index afd1c0c..9439a7a 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -141,6 +141,10 @@
egl::Display *display,
GLenum target,
egl::Image *image);
+
+bool ValidateBindVertexArrayBase(Context *context, GLuint array);
+bool ValidateDeleteVertexArraysBase(Context *context, GLsizei n);
+bool ValidateGenVertexArraysBase(Context *context, GLsizei n);
}
#endif // LIBANGLE_VALIDATION_ES_H_
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index d9a69d1..dc05584 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -993,4 +993,48 @@
return true;
}
+
+bool ValidateBindVertexArrayOES(Context *context, GLuint array)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateBindVertexArrayBase(context, array);
+}
+
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateDeleteVertexArraysBase(context, n);
+}
+
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateGenVertexArraysBase(context, n);
+}
+
+bool ValidateIsVertexArrayOES(Context *context)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return true;
+}
}
diff --git a/src/libANGLE/validationES2.h b/src/libANGLE/validationES2.h
index 4a858d9..44166af 100644
--- a/src/libANGLE/validationES2.h
+++ b/src/libANGLE/validationES2.h
@@ -33,6 +33,11 @@
const GLenum *attachments);
bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs);
+
+bool ValidateBindVertexArrayOES(Context *context, GLuint array);
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n);
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n);
+bool ValidateIsVertexArrayOES(Context *context);
}
#endif // LIBANGLE_VALIDATION_ES2_H_
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index b13ee9c..245a4af 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -1299,4 +1299,48 @@
return true;
}
+
+bool ValidateBindVertexArray(Context *context, GLuint array)
+{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateBindVertexArrayBase(context, array);
+}
+
+bool ValidateDeleteVertexArrays(Context *context, GLsizei n)
+{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateDeleteVertexArraysBase(context, n);
+}
+
+bool ValidateGenVertexArrays(Context *context, GLsizei n)
+{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return ValidateGenVertexArraysBase(context, n);
+}
+
+bool ValidateIsVertexArray(Context *context)
+{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ return true;
+}
}
diff --git a/src/libANGLE/validationES3.h b/src/libANGLE/validationES3.h
index 60f321e..c1d7b74 100644
--- a/src/libANGLE/validationES3.h
+++ b/src/libANGLE/validationES3.h
@@ -54,6 +54,11 @@
GLint border,
GLsizei imageSize,
const GLvoid *data);
+
+bool ValidateBindVertexArray(Context *context, GLuint array);
+bool ValidateDeleteVertexArrays(Context *context, GLsizei n);
+bool ValidateGenVertexArrays(Context *context, GLsizei n);
+bool ValidateIsVertexArray(Context *context);
}
#endif // LIBANGLE_VALIDATION_ES3_H_
diff --git a/src/libGLESv2/entry_points_egl.cpp b/src/libGLESv2/entry_points_egl.cpp
index 1b2397c..0b72ff1 100644
--- a/src/libGLESv2/entry_points_egl.cpp
+++ b/src/libGLESv2/entry_points_egl.cpp
@@ -1341,6 +1341,12 @@
INSERT_PROC_ADDRESS(gl, EGLImageTargetTexture2DOES);
INSERT_PROC_ADDRESS(gl, EGLImageTargetRenderbufferStorageOES);
+ // GL_OES_vertex_array_object
+ INSERT_PROC_ADDRESS(gl, BindVertexArrayOES);
+ INSERT_PROC_ADDRESS(gl, DeleteVertexArraysOES);
+ INSERT_PROC_ADDRESS(gl, GenVertexArraysOES);
+ INSERT_PROC_ADDRESS(gl, IsVertexArrayOES);
+
// GLES3 core
INSERT_PROC_ADDRESS(gl, ReadBuffer);
INSERT_PROC_ADDRESS(gl, DrawRangeElements);
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
index bdd8b67..296f90d 100644
--- a/src/libGLESv2/entry_points_gles_2_0_ext.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -1202,4 +1202,86 @@
}
}
}
+
+void GL_APIENTRY BindVertexArrayOES(GLuint array)
+{
+ EVENT("(GLuint array = %u)", array);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateBindVertexArrayOES(context, array))
+ {
+ return;
+ }
+
+ context->bindVertexArray(array);
+ }
+}
+
+void GL_APIENTRY DeleteVertexArraysOES(GLsizei n, const GLuint *arrays)
+{
+ EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateDeleteVertexArraysOES(context, n))
+ {
+ return;
+ }
+
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ if (arrays[arrayIndex] != 0)
+ {
+ context->deleteVertexArray(arrays[arrayIndex]);
+ }
+ }
+ }
+}
+
+void GL_APIENTRY GenVertexArraysOES(GLsizei n, GLuint *arrays)
+{
+ EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateGenVertexArraysOES(context, n))
+ {
+ return;
+ }
+
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ arrays[arrayIndex] = context->createVertexArray();
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsVertexArrayOES(GLuint array)
+{
+ EVENT("(GLuint array = %u)", array);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateIsVertexArrayOES(context))
+ {
+ return GL_FALSE;
+ }
+
+ if (array == 0)
+ {
+ return GL_FALSE;
+ }
+
+ VertexArray *vao = context->getVertexArray(array);
+
+ return (vao != nullptr ? GL_TRUE : GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
}
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.h b/src/libGLESv2/entry_points_gles_2_0_ext.h
index 08d576b..486df6a 100644
--- a/src/libGLESv2/entry_points_gles_2_0_ext.h
+++ b/src/libGLESv2/entry_points_gles_2_0_ext.h
@@ -85,6 +85,12 @@
ANGLE_EXPORT void GL_APIENTRY EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
ANGLE_EXPORT void GL_APIENTRY EGLImageTargetRenderbufferStorageOES(GLenum target,
GLeglImageOES image);
+
+// GL_OES_vertex_array_object
+ANGLE_EXPORT void GL_APIENTRY BindVertexArrayOES(GLuint array);
+ANGLE_EXPORT void GL_APIENTRY DeleteVertexArraysOES(GLsizei n, const GLuint *arrays);
+ANGLE_EXPORT void GL_APIENTRY GenVertexArraysOES(GLsizei n, GLuint *arrays);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsVertexArrayOES(GLuint array);
}
#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_
diff --git a/src/libGLESv2/entry_points_gles_3_0.cpp b/src/libGLESv2/entry_points_gles_3_0.cpp
index b850109..2c19eb6 100644
--- a/src/libGLESv2/entry_points_gles_3_0.cpp
+++ b/src/libGLESv2/entry_points_gles_3_0.cpp
@@ -806,19 +806,8 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientVersion() < 3)
+ if (!ValidateBindVertexArray(context, array))
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- VertexArray *vao = context->getVertexArray(array);
-
- if (!vao)
- {
- // The default VAO should always exist
- ASSERT(array != 0);
- context->recordError(Error(GL_INVALID_OPERATION));
return;
}
@@ -833,15 +822,8 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientVersion() < 3)
+ if (!ValidateDeleteVertexArrays(context, n))
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
return;
}
@@ -862,15 +844,8 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientVersion() < 3)
+ if (!ValidateGenVertexArrays(context, n))
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
return;
}
@@ -888,9 +863,8 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientVersion() < 3)
+ if (!ValidateIsVertexArray(context))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return GL_FALSE;
}
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index 0d5dfd5..71eb25d 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1439,4 +1439,24 @@
{
return gl::EGLImageTargetRenderbufferStorageOES(target, image);
}
+
+void GL_APIENTRY glBindVertexArrayOES(GLuint array)
+{
+ return gl::BindVertexArrayOES(array);
+}
+
+void GL_APIENTRY glDeleteVertexArraysOES(GLsizei n, const GLuint *arrays)
+{
+ return gl::DeleteVertexArraysOES(n, arrays);
+}
+
+void GL_APIENTRY glGenVertexArraysOES(GLsizei n, GLuint *arrays)
+{
+ return gl::GenVertexArraysOES(n, arrays);
+}
+
+GLboolean GL_APIENTRY glIsVertexArrayOES(GLuint array)
+{
+ return gl::IsVertexArrayOES(array);
+}
}
diff --git a/src/libGLESv2/libGLESv2.def b/src/libGLESv2/libGLESv2.def
index e58826b..af41a67 100644
--- a/src/libGLESv2/libGLESv2.def
+++ b/src/libGLESv2/libGLESv2.def
@@ -183,6 +183,10 @@
glPopGroupMarkerEXT @296
glEGLImageTargetTexture2DOES @297
glEGLImageTargetRenderbufferStorageOES @298
+ glBindVertexArrayOES @299
+ glDeleteVertexArraysOES @300
+ glGenVertexArraysOES @301
+ glIsVertexArrayOES @302
; GLES 3.0 Functions
glReadBuffer @180