Refactor tracking of bound vbufs and ibufs and vertex attrib arrays.

Review URL: https://codereview.appspot.com/7359045

git-svn-id: http://skia.googlecode.com/svn/trunk@7779 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2013-02-19 20:17:28 +00:00
parent a62a9ce9e6
commit 880b8fcf25
9 changed files with 342 additions and 236 deletions

View File

@ -48,10 +48,6 @@ void GrGLIndexBuffer::bind() const {
GPUGL->notifyIndexBufferBind(this);
}
GrGLuint GrGLIndexBuffer::bufferID() const {
return fBufferID;
}
void* GrGLIndexBuffer::lock() {
GrAssert(fBufferID);
GrAssert(!isLocked());

View File

@ -19,9 +19,18 @@ class GrGLIndexBuffer : public GrIndexBuffer {
public:
GrGLIndexBuffer(GrGpuGL* gpu,
bool isWrapped,
GrGLuint id,
size_t sizeInBytes,
bool dynamic);
virtual ~GrGLIndexBuffer() { this->release(); }
GrGLuint bufferID() const;
GrGLuint bufferID() const { return fBufferID; }
size_t baseOffset() const { return 0; }
void bind() const;
// overrides of GrIndexBuffer
virtual void* lock();
@ -31,24 +40,16 @@ public:
virtual bool updateData(const void* src, size_t srcSizeInBytes);
protected:
GrGLIndexBuffer(GrGpuGL* gpu,
bool isWrapped,
GrGLuint id,
size_t sizeInBytes,
bool dynamic);
// overrides of GrResource
virtual void onAbandon() SK_OVERRIDE;
virtual void onRelease() SK_OVERRIDE;
private:
void bind() const;
GrGLuint fBufferID;
void* fLockPtr;
friend class GrGpuGL;
typedef GrIndexBuffer INHERITED;
};

View File

@ -966,12 +966,12 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
// Bind the attrib locations to same values for all shaders
GL_CALL(BindAttribLocation(fProgramID,
PositionAttributeIdx(),
kPositionAttributeIndex,
builder.positionAttribute().c_str()));
GL_CALL(BindAttribLocation(fProgramID, TexCoordAttributeIdx(), TEX_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, kTexCoordAttributeIndex, TEX_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, kColorAttributeIndex, COL_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, kCoverageAttributeIndex, COV_ATTR_NAME));
GL_CALL(BindAttribLocation(fProgramID, kEdgeAttributeIndex, EDGE_ATTR_NAME));
GL_CALL(LinkProgram(fProgramID));
@ -1067,7 +1067,7 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(color, c);
GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
GL_CALL(VertexAttrib4fv(kColorAttributeIndex, c));
sharedState->fConstAttribColor = color;
}
break;
@ -1101,7 +1101,7 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(coverage, c);
GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(), c));
GL_CALL(VertexAttrib4fv(kCoverageAttributeIndex, c));
sharedState->fConstAttribCoverage = coverage;
}
break;

View File

@ -81,11 +81,13 @@ public:
/**
* Attribute indices. These should not overlap.
*/
static int PositionAttributeIdx() { return 0; }
static int ColorAttributeIdx() { return 1; }
static int CoverageAttributeIdx() { return 2; }
static int EdgeAttributeIdx() { return 3; }
static int TexCoordAttributeIdx() { return 4; }
enum {
kPositionAttributeIndex = 0,
kColorAttributeIndex = 1,
kCoverageAttributeIndex = 2,
kEdgeAttributeIndex = 3,
kTexCoordAttributeIndex = 4,
};
/**
* Some GL state that is relevant to programs is not stored per-program. In particular vertex

View File

@ -47,10 +47,6 @@ void GrGLVertexBuffer::bind() const {
GPUGL->notifyVertexBufferBind(this);
}
GrGLuint GrGLVertexBuffer::bufferID() const {
return fBufferID;
}
void* GrGLVertexBuffer::lock() {
GrAssert(fBufferID);
GrAssert(!isLocked());

View File

@ -18,34 +18,35 @@ class GrGpuGL;
class GrGLVertexBuffer : public GrVertexBuffer {
public:
GrGLVertexBuffer(GrGpuGL* gpu,
bool isWrapped,
GrGLuint id,
size_t sizeInBytes,
bool dynamic);
virtual ~GrGLVertexBuffer() { this->release(); }
GrGLuint bufferID() const { return fBufferID; }
size_t baseOffset() const { return 0; }
void bind() const;
// overrides of GrVertexBuffer
virtual void* lock();
virtual void* lockPtr() const;
virtual void unlock();
virtual bool isLocked() const;
virtual bool updateData(const void* src, size_t srcSizeInBytes);
GrGLuint bufferID() const;
protected:
GrGLVertexBuffer(GrGpuGL* gpu,
bool isWrapped,
GrGLuint id,
size_t sizeInBytes,
bool dynamic);
// overrides of GrResource
virtual void onAbandon() SK_OVERRIDE;
virtual void onRelease() SK_OVERRIDE;
private:
void bind() const;
GrGLuint fBufferID;
void* fLockPtr;
friend class GrGpuGL;
typedef GrVertexBuffer INHERITED;
};

View File

@ -178,6 +178,8 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContextInfo()));
fHWGeometryState.setMaxAttribArrays(this->glCaps().maxVertexAttributes());
fLastSuccessfulStencilFmtIdx = 0;
if (false) { // avoid bit rot, suppress warning
fbo_test(this->glInterface(), 0, 0);
@ -446,10 +448,7 @@ void GrGpuGL::onResetContext() {
fHWStencilSettings.invalidate();
fHWStencilTestEnabled = kUnknown_TriState;
fHWGeometryState.fIndexBuffer = NULL;
fHWGeometryState.fVertexBuffer = NULL;
fHWGeometryState.fArrayPtrsDirty = true;
fHWGeometryState.invalidate();
fHWBoundRenderTarget = NULL;
@ -474,28 +473,6 @@ void GrGpuGL::onResetContext() {
GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
}
fHWGeometryState.fVertexOffset = ~0U;
// Third party GL code may have left vertex attributes enabled. Some GL
// implementations (osmesa) may read vetex attributes that are not required
// by the current shader. Therefore, we have to ensure that only the
// attributes we require for the current draw are enabled or we may cause an
// invalid read.
// Disable all vertex layout bits so that next flush will assume all
// optional vertex attributes are disabled.
fHWGeometryState.fVertexLayout = 0;
// We always use the this attribute and assume it is always enabled.
int posAttrIdx = GrGLProgram::PositionAttributeIdx();
GL_CALL(EnableVertexAttribArray(posAttrIdx));
// Disable all other vertex attributes.
for (int va = 0; va < this->glCaps().maxVertexAttributes(); ++va) {
if (va != posAttrIdx) {
GL_CALL(DisableVertexAttribArray(va));
}
}
fHWProgramID = 0;
fSharedGLProgramState.invalidate();
}
@ -1253,26 +1230,26 @@ GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
GL_CALL(GenBuffers(1, &id));
if (id) {
GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
fHWGeometryState.fArrayPtrsDirty = true;
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
// make sure driver can allocate memory for this buffer
GL_ALLOC_CALL(this->glInterface(),
BufferData(GR_GL_ARRAY_BUFFER,
size,
NULL, // data ptr
dynamic ? GR_GL_DYNAMIC_DRAW :
GR_GL_STATIC_DRAW));
dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
GL_CALL(DeleteBuffers(1, &id));
// deleting bound buffer does implicit bind to 0
fHWGeometryState.fVertexBuffer = NULL;
fHWGeometryState.setVertexBufferID(0);
return NULL;
}
static const bool kIsWrapped = false;
GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer,
(this, kIsWrapped, id,
size, dynamic));
fHWGeometryState.fVertexBuffer = vertexBuffer;
GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer, (this,
false,
id,
size,
dynamic));
fHWGeometryState.setVertexBufferID(id);
return vertexBuffer;
}
return NULL;
@ -1294,13 +1271,13 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
GL_CALL(DeleteBuffers(1, &id));
// deleting bound buffer does implicit bind to 0
fHWGeometryState.fIndexBuffer = NULL;
fHWGeometryState.setIndexBufferID(0);
return NULL;
}
static const bool kIsWrapped = false;
GrIndexBuffer* indexBuffer = SkNEW_ARGS(GrGLIndexBuffer,
(this, kIsWrapped, id, size, dynamic));
fHWGeometryState.fIndexBuffer = indexBuffer;
fHWGeometryState.setIndexBufferID(id);
return indexBuffer;
}
return NULL;
@ -1660,16 +1637,14 @@ GrGLenum gPrimitiveType2GLMode[] = {
#endif
void GrGpuGL::onGpuDraw(const DrawInfo& info) {
int extraStartIndexOffset;
this->setupGeometry(info, &extraStartIndexOffset);
size_t indexOffsetInBytes;
this->setupGeometry(info, &indexOffsetInBytes);
GrAssert((size_t)info.primitiveType() < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
GrAssert(NULL != fHWGeometryState.fVertexBuffer);
if (info.isIndexed()) {
GrAssert(NULL != fHWGeometryState.fIndexBuffer);
GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * (info.startIndex() +
extraStartIndexOffset));
GrGLvoid* indices =
reinterpret_cast<GrGLvoid*>(indexOffsetInBytes + sizeof(uint16_t) * info.startIndex());
// info.startVertex() was accounted for by setupGeometry.
GL_CALL(DrawElements(gPrimitiveType2GLMode[info.primitiveType()],
info.indexCount(),
@ -2171,29 +2146,19 @@ void GrGpuGL::flushMiscFixedFunctionState() {
}
void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
if (fHWGeometryState.fVertexBuffer != buffer) {
fHWGeometryState.fArrayPtrsDirty = true;
fHWGeometryState.fVertexBuffer = buffer;
}
fHWGeometryState.setVertexBufferID(buffer->bufferID());
}
void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
if (fHWGeometryState.fVertexBuffer == buffer) {
// deleting bound buffer does implied bind to 0
fHWGeometryState.fVertexBuffer = NULL;
fHWGeometryState.fArrayPtrsDirty = true;
}
fHWGeometryState.notifyVertexBufferDelete(buffer);
}
void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
fHWGeometryState.fIndexBuffer = buffer;
fHWGeometryState.setIndexBufferID(buffer->bufferID());
}
void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
if (fHWGeometryState.fIndexBuffer == buffer) {
// deleting bound buffer does implied bind to 0
fHWGeometryState.fIndexBuffer = NULL;
}
fHWGeometryState.notifyIndexBufferDelete(buffer);
}
void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
@ -2338,52 +2303,48 @@ void GrGpuGL::setSpareTextureUnit() {
}
}
void GrGpuGL::setBuffers(bool indexed,
int* extraVertexOffset,
int* extraIndexOffset) {
GrGLVertexBuffer* GrGpuGL::setBuffers(bool indexed,
size_t* vertexOffsetInBytes,
size_t* indexOffsetInBytes) {
GrAssert(NULL != extraVertexOffset);
GrAssert(NULL != vertexOffsetInBytes);
const GeometryPoolState& geoPoolState = this->getGeomPoolState();
GrGLVertexBuffer* vbuf;
switch (this->getGeomSrc().fVertexSrc) {
case kBuffer_GeometrySrcType:
*extraVertexOffset = 0;
vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
break;
case kArray_GeometrySrcType:
case kReserved_GeometrySrcType:
this->finalizeReservedVertices();
*extraVertexOffset = geoPoolState.fPoolStartVertex;
vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
break;
default:
vbuf = NULL; // suppress warning
GrCrash("Unknown geometry src type!");
case kBuffer_GeometrySrcType:
*vertexOffsetInBytes = 0;
vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
break;
case kArray_GeometrySrcType:
case kReserved_GeometrySrcType:
this->finalizeReservedVertices();
*vertexOffsetInBytes = geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize;
vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
break;
default:
vbuf = NULL; // suppress warning
GrCrash("Unknown geometry src type!");
}
GrAssert(NULL != vbuf);
GrAssert(!vbuf->isLocked());
if (fHWGeometryState.fVertexBuffer != vbuf) {
GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
fHWGeometryState.fArrayPtrsDirty = true;
fHWGeometryState.fVertexBuffer = vbuf;
}
*vertexOffsetInBytes += vbuf->baseOffset();
if (indexed) {
GrAssert(NULL != extraIndexOffset);
GrAssert(NULL != indexOffsetInBytes);
GrGLIndexBuffer* ibuf;
switch (this->getGeomSrc().fIndexSrc) {
case kBuffer_GeometrySrcType:
*extraIndexOffset = 0;
*indexOffsetInBytes = 0;
ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
break;
case kArray_GeometrySrcType:
case kReserved_GeometrySrcType:
this->finalizeReservedIndices();
*extraIndexOffset = geoPoolState.fPoolStartIndex;
*indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort);
ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
break;
default:
@ -2393,9 +2354,53 @@ void GrGpuGL::setBuffers(bool indexed,
GrAssert(NULL != ibuf);
GrAssert(!ibuf->isLocked());
if (fHWGeometryState.fIndexBuffer != ibuf) {
GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
fHWGeometryState.fIndexBuffer = ibuf;
if (!fHWGeometryState.isIndexBufferIDBound(ibuf->bufferID())) {
ibuf->bind();
fHWGeometryState.setIndexBufferID(ibuf->bufferID());
}
}
return vbuf;
}
///////////////////////////////////////////////////////////////////////////////
void GrGpuGL::HWGeometryState::AttribArray::set(const GrGpuGL* gpu,
HWGeometryState* geoState,
int index,
GrGLVertexBuffer* buffer,
GrGLint size,
GrGLenum type,
GrGLboolean normalized,
GrGLsizei stride,
GrGLvoid* offset) {
if (!fEnableIsValid || !fEnabled) {
GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
fEnableIsValid = true;
fEnabled = true;
}
if (!fAttribPointerIsValid ||
fVertexBufferID != buffer->bufferID() ||
fSize != size ||
fNormalized != normalized ||
fStride != stride ||
offset != fOffset) {
GrGLuint bufferID = buffer->bufferID();
if (!geoState->isVertexBufferIDBound(bufferID)) {
buffer->bind();
geoState->setVertexBufferID(bufferID);
}
GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
size,
type,
normalized,
stride,
offset));
fAttribPointerIsValid = true;
fVertexBufferID = bufferID;
fSize = size;
fNormalized = normalized;
fStride = stride;
fOffset = offset;
}
}

View File

@ -57,6 +57,14 @@ public:
const GrGLCaps& glCaps() const { return fGLContextInfo.caps(); }
// Callbacks to update state tracking when related GL objects are bound or deleted
void notifyVertexBufferBind(const GrGLVertexBuffer* buffer);
void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer);
void notifyIndexBufferBind(const GrGLIndexBuffer* buffer);
void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer);
void notifyTextureDelete(GrGLTexture* texture);
void notifyRenderTargetDelete(GrRenderTarget* renderTarget);
private:
// GrGpu overrides
virtual void onResetContext() SK_OVERRIDE;
@ -112,14 +120,16 @@ private:
// binds texture unit in GL
void setTextureUnit(int unitIdx);
// Sets up vertex attribute pointers and strides. On return startIndexOffset specifies an
// offset into the index buffer to the first index to be read (in addition to
// info.startIndex()). It accounts for the fact that index buffer pool may have provided space
// in the middle of a larger index buffer.
void setupGeometry(const DrawInfo& info, int* startIndexOffset);
// binds appropriate vertex and index buffers, also returns any extra verts or indices to
// offset by based on how space was allocated in pool VB/IBs.
void setBuffers(bool indexed, int* extraVertexOffset, int* extraIndexOffset);
// Sets up vertex attribute pointers and strides. On return indexOffsetInBytes gives the offset
// an into the index buffer. It does not account for drawInfo.startIndex() but rather the start
// index is relative to the returned offset.
void setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes);
// binds appropriate vertex and index buffers. It also returns offsets for the vertex and index
// buffers. These offsets account for placement within a pool buffer or CPU-side addresses for
// use with buffer 0. They do not account for start values in the DrawInfo (which is not passed
// here). The vertex buffer that contains the vertex data is returned. It is not necessarily
// bound.
GrGLVertexBuffer* setBuffers(bool indexed, size_t* vertexOffsetInBytes, size_t* indexOffsetInBytes);
// Subclasses should call this to flush the blend state.
// The params should be the final coefficients to apply
@ -199,15 +209,6 @@ private:
// determines valid stencil formats
void initStencilFormats();
// notify callbacks to update state tracking when related
// objects are bound to GL or deleted outside of the class
void notifyVertexBufferBind(const GrGLVertexBuffer* buffer);
void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer);
void notifyIndexBufferBind(const GrGLIndexBuffer* buffer);
void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer);
void notifyTextureDelete(GrGLTexture* texture);
void notifyRenderTargetDelete(GrRenderTarget* renderTarget);
void setSpareTextureUnit();
// bound is region that may be modified and therefore has to be resolved.
@ -235,11 +236,6 @@ private:
void fillInConfigRenderableTable();
friend class GrGLVertexBuffer;
friend class GrGLIndexBuffer;
friend class GrGLTexture;
friend class GrGLRenderTarget;
GrGLContextInfo fGLContextInfo;
// GL program-related state
@ -272,12 +268,139 @@ private:
GrGLIRect fHWViewport;
struct {
size_t fVertexOffset;
GrVertexLayout fVertexLayout;
const GrVertexBuffer* fVertexBuffer;
const GrIndexBuffer* fIndexBuffer;
bool fArrayPtrsDirty;
/**
* Tracks bound vertex and index buffers and vertex attrib array state.
*/
class HWGeometryState {
public:
HWGeometryState() { fAttribArrayCount = 0; this->invalidate();}
void setMaxAttribArrays(int max) {
fAttribArrayCount = max;
fAttribArrays.reset(max);
for (int i = 0; i < fAttribArrayCount; ++i) {
fAttribArrays[i].invalidate();
}
}
void invalidate() {
fBoundVertexBufferIDIsValid = false;
fBoundIndexBufferIDIsValid = false;
for (int i = 0; i < fAttribArrayCount; ++i) {
fAttribArrays[i].invalidate();
}
}
void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
GrGLuint id = buffer->bufferID();
if (0 != id) {
if (this->isVertexBufferIDBound(id)) {
// deleting bound buffer does implied bind to 0
this->setVertexBufferID(0);
}
for (int i = 0; i < fAttribArrayCount; ++i) {
if (fAttribArrays[i].vertexBufferID() == id) {
fAttribArrays[i].invalidate();
}
}
}
}
void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
GrGLuint id = buffer->bufferID();
if (0 != id) {
if (this->isIndexBufferIDBound(id)) {
// deleting bound buffer does implied bind to 0
this->setIndexBufferID(0);
}
}
}
void setVertexBufferID(GrGLuint id) {
fBoundVertexBufferIDIsValid = true;
fBoundVertexBufferID = id;
}
void setIndexBufferID(GrGLuint id) {
fBoundIndexBufferIDIsValid = true;
fBoundIndexBufferID = id;
}
bool isVertexBufferIDBound(GrGLuint id) const {
return fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID;
}
bool isIndexBufferIDBound(GrGLuint id) const {
return fBoundIndexBufferIDIsValid && id == fBoundIndexBufferID;
}
void setAttribArray(const GrGpuGL* gpu,
int index,
GrGLVertexBuffer* vertexBuffer,
GrGLint size,
GrGLenum type,
GrGLboolean normalized,
GrGLsizei stride,
GrGLvoid* offset) {
GrAssert(index >= 0 && index < fAttribArrayCount);
AttribArray* attrib = fAttribArrays.get() + index;
attrib->set(gpu, this, index, vertexBuffer, size, type, normalized, stride, offset);
}
void disableUnusedAttribArrays(const GrGpuGL* gpu,
uint32_t usedAttribIndexMask) {
for (int i = 0; i < fAttribArrayCount; ++i) {
if (!(usedAttribIndexMask & (1 << i))) {
fAttribArrays[i].disable(gpu, i);
}
}
}
private:
GrGLuint fBoundVertexBufferID;
GrGLuint fBoundIndexBufferID;
bool fBoundVertexBufferIDIsValid;
bool fBoundIndexBufferIDIsValid;
struct AttribArray {
public:
void set(const GrGpuGL* gpu,
HWGeometryState* geoState,
int index,
GrGLVertexBuffer* vertexBuffer,
GrGLint size,
GrGLenum type,
GrGLboolean normalized,
GrGLsizei stride,
GrGLvoid* offset);
void disable(const GrGpuGL* gpu, int index) {
if (!fEnableIsValid || fEnabled) {
GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(index));
fEnableIsValid = true;
fEnabled = false;
}
}
void invalidate() {
fEnableIsValid = false;
fAttribPointerIsValid = false;
}
GrGLuint vertexBufferID() const { return fVertexBufferID; }
private:
bool fEnableIsValid;
bool fAttribPointerIsValid;
bool fEnabled;
GrGLuint fVertexBufferID;
GrGLint fSize;
GrGLenum fType;
GrGLboolean fNormalized;
GrGLsizei fStride;
GrGLvoid* fOffset;
};
SkAutoTArray<AttribArray> fAttribArrays;
int fAttribArrayCount;
} fHWGeometryState;
struct {

View File

@ -213,103 +213,85 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
return true;
}
void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) {
void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
int newColorOffset;
int newCoverageOffset;
int newTexCoordOffset;
int newEdgeOffset;
int colorOffset;
int coverageOffset;
int texCoordOffset;
int edgeOffset;
GrVertexLayout currLayout = this->getDrawState().getVertexLayout();
GrGLsizei newStride = GrDrawState::VertexSizeAndOffsets(currLayout,
&newTexCoordOffset,
&newColorOffset,
&newCoverageOffset,
&newEdgeOffset);
int oldColorOffset;
int oldCoverageOffset;
int oldTexCoordOffset;
int oldEdgeOffset;
GrGLsizei stride = GrDrawState::VertexSizeAndOffsets(currLayout,
&texCoordOffset,
&colorOffset,
&coverageOffset,
&edgeOffset);
GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
&oldTexCoordOffset,
&oldColorOffset,
&oldCoverageOffset,
&oldEdgeOffset);
size_t vertexOffset;
GrGLVertexBuffer* vb= this->setBuffers(info.isIndexed(), &vertexOffset, indexOffsetInBytes);
vertexOffset += stride * info.startVertex();
int extraVertexOffset;
this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset);
size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride;
// all the Pointers must be set if any of these are true
bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
vertexOffset != fHWGeometryState.fVertexOffset ||
newStride != oldStride;
if (allOffsetsChange) {
int idx = GrGLProgram::PositionAttributeIdx();
GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, (GrGLvoid*)vertexOffset));
fHWGeometryState.fVertexOffset = vertexOffset;
uint32_t usedAttribArraysMask = (1 << GrGLProgram::kPositionAttributeIndex);
fHWGeometryState.setAttribArray(this,
GrGLProgram::kPositionAttributeIndex,
vb,
2,
GR_GL_FLOAT,
false,
stride,
reinterpret_cast<GrGLvoid*>(vertexOffset));
if (texCoordOffset > 0) {
usedAttribArraysMask |= (1 << GrGLProgram::kTexCoordAttributeIndex);
GrGLvoid* texCoordPtr = reinterpret_cast<GrGLvoid*>(vertexOffset + texCoordOffset);
fHWGeometryState.setAttribArray(this,
GrGLProgram::kTexCoordAttributeIndex,
vb,
2,
GR_GL_FLOAT,
false,
stride,
texCoordPtr);
}
if (newTexCoordOffset > 0) {
GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffset);
int idx = GrGLProgram::TexCoordAttributeIdx();
if (oldTexCoordOffset <= 0) {
GL_CALL(EnableVertexAttribArray(idx));
GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset));
} else if (allOffsetsChange || newTexCoordOffset != oldTexCoordOffset) {
GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset));
}
} else if (oldTexCoordOffset > 0) {
GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx()));
if (colorOffset > 0) {
usedAttribArraysMask |= (1 << GrGLProgram::kColorAttributeIndex);
GrGLvoid* colorPtr = reinterpret_cast<GrGLvoid*>(vertexOffset + colorOffset);
fHWGeometryState.setAttribArray(this,
GrGLProgram::kColorAttributeIndex,
vb,
4,
GR_GL_UNSIGNED_BYTE,
true,
stride,
colorPtr);
}
if (newColorOffset > 0) {
fSharedGLProgramState.fConstAttribColor = GrColor_ILLEGAL;
GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
int idx = GrGLProgram::ColorAttributeIdx();
if (oldColorOffset <= 0) {
GL_CALL(EnableVertexAttribArray(idx));
GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset));
} else if (allOffsetsChange || newColorOffset != oldColorOffset) {
GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset));
}
} else if (oldColorOffset > 0) {
GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
if (coverageOffset > 0) {
usedAttribArraysMask |= (1 << GrGLProgram::kCoverageAttributeIndex);
GrGLvoid* coveragePtr = reinterpret_cast<GrGLvoid*>(vertexOffset + coverageOffset);
fHWGeometryState.setAttribArray(this,
GrGLProgram::kCoverageAttributeIndex,
vb,
4,
GR_GL_UNSIGNED_BYTE,
true,
stride,
coveragePtr);
}
if (newCoverageOffset > 0) {
fSharedGLProgramState.fConstAttribColor = GrColor_ILLEGAL;
GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset);
int idx = GrGLProgram::CoverageAttributeIdx();
if (oldCoverageOffset <= 0) {
GL_CALL(EnableVertexAttribArray(idx));
GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
true, newStride, coverageOffset));
} else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) {
GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
true, newStride, coverageOffset));
}
} else if (oldCoverageOffset > 0) {
GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx()));
if (edgeOffset > 0) {
usedAttribArraysMask |= (1 << GrGLProgram::kEdgeAttributeIndex);
GrGLvoid* edgePtr = reinterpret_cast<GrGLvoid*>(vertexOffset + edgeOffset);
fHWGeometryState.setAttribArray(this,
GrGLProgram::kEdgeAttributeIndex,
vb,
4,
GR_GL_FLOAT,
false,
stride,
edgePtr);
}
if (newEdgeOffset > 0) {
GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset);
int idx = GrGLProgram::EdgeAttributeIdx();
if (oldEdgeOffset <= 0) {
GL_CALL(EnableVertexAttribArray(idx));
GL_CALL(VertexAttribPointer(idx, 4, GR_GL_FLOAT, false, newStride, edgeOffset));
} else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) {
GL_CALL(VertexAttribPointer(idx, 4, GR_GL_FLOAT, false, newStride, edgeOffset));
}
} else if (oldEdgeOffset > 0) {
GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx()));
}
fHWGeometryState.fVertexLayout = currLayout;
fHWGeometryState.fArrayPtrsDirty = false;
fHWGeometryState.disableUnusedAttribArrays(this, usedAttribArraysMask);
}