Improve handling of FF vertex array state
R=robertphillips@google.com, jvanverth@google.com
Author: bsalomon@google.com
Review URL: https://chromiumcodereview.appspot.com/23542013
git-svn-id: http://skia.googlecode.com/svn/trunk@11154 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index a843953..0dbd425 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -559,6 +559,7 @@
#define GR_GL_VERTEX_ARRAY 0x8074
#define GR_GL_NORMAL_ARRAY 0x8075
#define GR_GL_COLOR_ARRAY 0x8076
+#define GR_GL_SECONDARY_COLOR_ARRAY 0x845E
#define GR_GL_INDEX_ARRAY 0x8077
#define GR_GL_TEXTURE_COORD_ARRAY 0x8078
#define GR_GL_EDGE_FLAG_ARRAY 0x8079
diff --git a/src/gpu/gl/GrGLVertexArray.cpp b/src/gpu/gl/GrGLVertexArray.cpp
index bf3d3b5..605ec33 100644
--- a/src/gpu/gl/GrGLVertexArray.cpp
+++ b/src/gpu/gl/GrGLVertexArray.cpp
@@ -49,7 +49,39 @@
}
}
-void GrGLAttribArrayState::disableUnusedAttribArrays(const GrGpuGL* gpu, uint64_t usedMask) {
+void GrGLAttribArrayState::setFixedFunctionVertexArray(const GrGpuGL* gpu,
+ GrGLVertexBuffer* buffer,
+ GrGLint size,
+ GrGLenum type,
+ GrGLsizei stride,
+ GrGLvoid* offset) {
+ SkASSERT(gpu->glCaps().fixedFunctionSupport());
+ AttribArrayState* array = &fFixedFunctionVertexArray;
+ if (!array->fEnableIsValid || !array->fEnabled) {
+ GR_GL_CALL(gpu->glInterface(), EnableClientState(GR_GL_VERTEX_ARRAY));
+ array->fEnableIsValid = true;
+ array->fEnabled = true;
+ }
+ if (!array->fAttribPointerIsValid ||
+ array->fVertexBufferID != buffer->bufferID() ||
+ array->fSize != size ||
+ array->fStride != stride ||
+ array->fOffset != offset) {
+
+ buffer->bind();
+ GR_GL_CALL(gpu->glInterface(), VertexPointer(size,
+ type,
+ stride,
+ offset));
+ array->fAttribPointerIsValid = true;
+ array->fVertexBufferID = buffer->bufferID();
+ array->fSize = size;
+ array->fStride = stride;
+ array->fOffset = offset;
+ }
+}
+
+void GrGLAttribArrayState::disableUnusedArrays(const GrGpuGL* gpu, uint64_t usedMask, bool usingFFVertexArray) {
int count = fAttribArrayStates.count();
for (int i = 0; i < count; ++i) {
if (!(usedMask & 0x1)) {
@@ -58,10 +90,41 @@
fAttribArrayStates[i].fEnableIsValid = true;
fAttribArrayStates[i].fEnabled = false;
}
+ } else {
+ SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
}
// if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
usedMask >>= 1;
}
+
+ // Deal with fixed-function vertex arrays.
+ if (gpu->glCaps().fixedFunctionSupport()) {
+ if (!usingFFVertexArray) {
+ if (!fFixedFunctionVertexArray.fEnableIsValid || fFixedFunctionVertexArray.fEnabled) {
+ GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_VERTEX_ARRAY));
+ fFixedFunctionVertexArray.fEnableIsValid = true;
+ fFixedFunctionVertexArray.fEnabled = false;
+ }
+ } else {
+ SkASSERT(fFixedFunctionVertexArray.fEnableIsValid && fFixedFunctionVertexArray.fEnabled);
+ }
+ // When we use fixed function vertex processing we always use the vertex array and none of
+ // the other arrays.
+ if (!fUnusedFixedFunctionArraysDisabled) {
+ GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_NORMAL_ARRAY));
+ GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_COLOR_ARRAY));
+ GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_SECONDARY_COLOR_ARRAY));
+ GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_INDEX_ARRAY));
+ GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_EDGE_FLAG_ARRAY));
+ for (int i = 0; i < gpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
+ GR_GL_CALL(gpu->glInterface(), ClientActiveTexture(GR_GL_TEXTURE0 + i));
+ GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
+ }
+ fUnusedFixedFunctionArraysDisabled = true;
+ }
+ } else {
+ SkASSERT(!usingFFVertexArray);
+ }
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -115,9 +178,6 @@
}
void GrGLVertexArray::invalidateCachedState() {
- int count = fAttribArrays.count();
- for (int i = 0; i < count; ++i) {
- fAttribArrays.invalidate();
- }
+ fAttribArrays.invalidate();
fIndexBufferIDIsValid = false;
}
diff --git a/src/gpu/gl/GrGLVertexArray.h b/src/gpu/gl/GrGLVertexArray.h
index 7352caf..5cc7b5f 100644
--- a/src/gpu/gl/GrGLVertexArray.h
+++ b/src/gpu/gl/GrGLVertexArray.h
@@ -49,7 +49,12 @@
*/
class GrGLAttribArrayState {
public:
- explicit GrGLAttribArrayState(int arrayCount = 0) { this->resize(arrayCount); }
+ explicit GrGLAttribArrayState(int arrayCount = 0) {
+ this->resize(arrayCount);
+ // glVertexPointer doesn't have a normalization param.
+ fFixedFunctionVertexArray.fNormalized = false;
+ fUnusedFixedFunctionArraysDisabled = false;
+ }
void resize(int newCount) {
fAttribArrayStates.resize_back(newCount);
@@ -72,17 +77,26 @@
GrGLsizei stride,
GrGLvoid* offset);
+ void setFixedFunctionVertexArray(const GrGpuGL*,
+ GrGLVertexBuffer*,
+ GrGLint size,
+ GrGLenum type,
+ GrGLsizei stride,
+ GrGLvoid* offset);
+
/**
* This function disables vertex attribs not present in the mask. It is assumed that the
* GrGLAttribArrayState is tracking the state of the currently bound vertex array object.
*/
- void disableUnusedAttribArrays(const GrGpuGL*, uint64_t usedAttribArrayMask);
+ void disableUnusedArrays(const GrGpuGL*, uint64_t usedAttribArrayMask, bool usingFFVertexArray);
void invalidate() {
int count = fAttribArrayStates.count();
for (int i = 0; i < count; ++i) {
fAttribArrayStates[i].invalidate();
}
+ fFixedFunctionVertexArray.invalidate();
+ fUnusedFixedFunctionArraysDisabled = false;
}
void notifyVertexBufferDelete(GrGLuint id) {
@@ -93,6 +107,10 @@
fAttribArrayStates[i].invalidate();
}
}
+ if (fFixedFunctionVertexArray.fAttribPointerIsValid &&
+ id == fFixedFunctionVertexArray.fVertexBufferID) {
+ fFixedFunctionVertexArray.invalidate();
+ }
}
/**
@@ -122,6 +140,13 @@
};
SkSTArray<16, AttribArrayState, true> fAttribArrayStates;
+
+ // Tracks the array specified by glVertexPointer.
+ AttribArrayState fFixedFunctionVertexArray;
+
+ // Tracks whether we've disabled the other fixed function arrays that we don't
+ // use (e.g. glNormalPointer).
+ bool fUnusedFixedFunctionArraysDisabled;
};
/**
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index bc067e0..6f9a8ab 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -371,17 +371,7 @@
GL_CALL(MatrixMode(GR_GL_MODELVIEW));
GL_CALL(LoadIdentity());
- // When we use fixed function vertex processing we always use the vertex array
- // and none of the other arrays.
- GL_CALL(EnableClientState(GR_GL_VERTEX_ARRAY));
- GL_CALL(DisableClientState(GR_GL_NORMAL_ARRAY));
- GL_CALL(DisableClientState(GR_GL_COLOR_ARRAY));
- GL_CALL(DisableClientState(GR_GL_INDEX_ARRAY));
- GL_CALL(DisableClientState(GR_GL_EDGE_FLAG_ARRAY));
for (int i = 0; i < this->glCaps().maxFixedFunctionTextureCoords(); ++i) {
- GL_CALL(ClientActiveTexture(GR_GL_TEXTURE0 + i));
- GL_CALL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
-
GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + i));
GL_CALL(Disable(GR_GL_TEXTURE_GEN_S));
GL_CALL(Disable(GR_GL_TEXTURE_GEN_T));
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 669f21c..95ae726 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -303,6 +303,9 @@
fDefaultVertexArrayBoundIndexBufferID = false;
fDefaultVertexArrayBoundIndexBufferIDIsValid = false;
fDefaultVertexArrayAttribState.invalidate();
+ if (NULL != fVBOVertexArray) {
+ fVBOVertexArray->invalidateCachedState();
+ }
}
void notifyVertexArrayDelete(GrGLuint id) {
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index ce74303..159d6d8 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -371,5 +371,5 @@
vertexOffsetInBytes + vertexAttrib->fOffset));
}
- attribState->disableUnusedAttribArrays(this, usedAttribArraysMask);
+ attribState->disableUnusedArrays(this, usedAttribArraysMask, false);
}