Don't allocate VertexArray or TransformFeedback objects until binding.
Follow the spec more closely and only reserve IDs of vertex arrays and
transform feedback objects before binding. This saves memory and allows
the glIs* calls to succeed.
BUG=angleproject:1218
BUG=angleproject:1101
Change-Id: I0039680c39c66c1c5506f6a1a9121a71791b77e9
Reviewed-on: https://chromium-review.googlesource.com/316591
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index ae7f928..fb42b1f 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -144,8 +144,6 @@
// In the initial state, a default transform feedback object is bound and treated as
// a transform feedback object with a name of zero. That object is bound any time
// BindTransformFeedback is called with id of zero
- mTransformFeedbackZero.set(
- new TransformFeedback(mRenderer->createTransformFeedback(), 0, mCaps));
bindTransformFeedback(0);
}
@@ -189,10 +187,12 @@
SafeDelete(vertexArray.second);
}
- mTransformFeedbackZero.set(NULL);
for (auto transformFeedback : mTransformFeedbackMap)
{
- transformFeedback.second->release();
+ if (transformFeedback.second != nullptr)
+ {
+ transformFeedback.second->release();
+ }
}
for (auto &zeroTexture : mZeroTextures)
@@ -324,14 +324,9 @@
GLuint Context::createVertexArray()
{
- GLuint handle = mVertexArrayHandleAllocator.allocate();
-
- // Although the spec states VAO state is not initialized until the object is bound,
- // we create it immediately. The resulting behaviour is transparent to the application,
- // since it's not currently possible to access the state until the object is bound.
- VertexArray *vertexArray = new VertexArray(mRenderer, handle, MAX_VERTEX_ATTRIBS);
- mVertexArrayMap[handle] = vertexArray;
- return handle;
+ GLuint vertexArray = mVertexArrayHandleAllocator.allocate();
+ mVertexArrayMap[vertexArray] = nullptr;
+ return vertexArray;
}
GLuint Context::createSampler()
@@ -341,11 +336,9 @@
GLuint Context::createTransformFeedback()
{
- GLuint handle = mTransformFeedbackAllocator.allocate();
- TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle, mCaps);
- transformFeedback->addRef();
- mTransformFeedbackMap[handle] = transformFeedback;
- return handle;
+ GLuint transformFeedback = mTransformFeedbackAllocator.allocate();
+ mTransformFeedbackMap[transformFeedback] = nullptr;
+ return transformFeedback;
}
// Returns an unused framebuffer name
@@ -428,15 +421,18 @@
void Context::deleteVertexArray(GLuint vertexArray)
{
- auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
-
- if (vertexArrayObject != mVertexArrayMap.end())
+ auto iter = mVertexArrayMap.find(vertexArray);
+ if (iter != mVertexArrayMap.end())
{
- detachVertexArray(vertexArray);
+ VertexArray *vertexArrayObject = iter->second;
+ if (vertexArrayObject != nullptr)
+ {
+ detachVertexArray(vertexArray);
+ delete vertexArrayObject;
+ }
- mVertexArrayHandleAllocator.release(vertexArrayObject->first);
- delete vertexArrayObject->second;
- mVertexArrayMap.erase(vertexArrayObject);
+ mVertexArrayMap.erase(iter);
+ mVertexArrayHandleAllocator.release(vertexArray);
}
}
@@ -455,10 +451,15 @@
auto iter = mTransformFeedbackMap.find(transformFeedback);
if (iter != mTransformFeedbackMap.end())
{
- detachTransformFeedback(transformFeedback);
- mTransformFeedbackAllocator.release(transformFeedback);
- iter->second->release();
+ TransformFeedback *transformFeedbackObject = iter->second;
+ if (transformFeedbackObject != nullptr)
+ {
+ detachTransformFeedback(transformFeedback);
+ transformFeedbackObject->release();
+ }
+
mTransformFeedbackMap.erase(iter);
+ mTransformFeedbackAllocator.release(transformFeedback);
}
}
@@ -535,15 +536,7 @@
VertexArray *Context::getVertexArray(GLuint handle) const
{
auto vertexArray = mVertexArrayMap.find(handle);
-
- if (vertexArray == mVertexArrayMap.end())
- {
- return NULL;
- }
- else
- {
- return vertexArray->second;
- }
+ return (vertexArray != mVertexArrayMap.end()) ? vertexArray->second : nullptr;
}
Sampler *Context::getSampler(GLuint handle) const
@@ -553,15 +546,8 @@
TransformFeedback *Context::getTransformFeedback(GLuint handle) const
{
- if (handle == 0)
- {
- return mTransformFeedbackZero.get();
- }
- else
- {
- TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(handle);
- return (iter != mTransformFeedbackMap.end()) ? iter->second : NULL;
- }
+ auto iter = mTransformFeedbackMap.find(handle);
+ return (iter != mTransformFeedbackMap.end()) ? iter->second : nullptr;
}
bool Context::isSampler(GLuint samplerName) const
@@ -631,11 +617,7 @@
void Context::bindVertexArray(GLuint vertexArray)
{
- if (!getVertexArray(vertexArray))
- {
- VertexArray *vertexArrayObject = new VertexArray(mRenderer, vertexArray, MAX_VERTEX_ATTRIBS);
- mVertexArrayMap[vertexArray] = vertexArrayObject;
- }
+ checkVertexArrayAllocation(vertexArray);
mState.setVertexArrayBinding(getVertexArray(vertexArray));
}
@@ -711,6 +693,8 @@
void Context::bindTransformFeedback(GLuint transformFeedback)
{
+ checkTransformFeedbackAllocation(transformFeedback);
+
mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback));
}
@@ -1493,6 +1477,37 @@
}
}
+void Context::checkVertexArrayAllocation(GLuint vertexArray)
+{
+ if (!getVertexArray(vertexArray))
+ {
+ VertexArray *vertexArrayObject =
+ new VertexArray(mRenderer, vertexArray, MAX_VERTEX_ATTRIBS);
+ mVertexArrayMap[vertexArray] = vertexArrayObject;
+ }
+}
+
+void Context::checkTransformFeedbackAllocation(GLuint transformFeedback)
+{
+ if (!getTransformFeedback(transformFeedback))
+ {
+ TransformFeedback *transformFeedbackObject =
+ new TransformFeedback(mRenderer->createTransformFeedback(), transformFeedback, mCaps);
+ transformFeedbackObject->addRef();
+ mTransformFeedbackMap[transformFeedback] = transformFeedbackObject;
+ }
+}
+
+bool Context::isVertexArrayGenerated(GLuint vertexArray)
+{
+ return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
+}
+
+bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
+{
+ return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
+}
+
void Context::detachTexture(GLuint texture)
{
// Simple pass-through to State's detachTexture method, as textures do not require
@@ -1516,7 +1531,11 @@
// mark as freed among the vertex array objects
for (auto &vaoPair : mVertexArrayMap)
{
- vaoPair.second->detachBuffer(buffer);
+ VertexArray* vertexArray = vaoPair.second;
+ if (vertexArray != nullptr)
+ {
+ vertexArray->detachBuffer(buffer);
+ }
}
}