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:
parent
a62a9ce9e6
commit
880b8fcf25
@ -48,10 +48,6 @@ void GrGLIndexBuffer::bind() const {
|
||||
GPUGL->notifyIndexBufferBind(this);
|
||||
}
|
||||
|
||||
GrGLuint GrGLIndexBuffer::bufferID() const {
|
||||
return fBufferID;
|
||||
}
|
||||
|
||||
void* GrGLIndexBuffer::lock() {
|
||||
GrAssert(fBufferID);
|
||||
GrAssert(!isLocked());
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -47,10 +47,6 @@ void GrGLVertexBuffer::bind() const {
|
||||
GPUGL->notifyVertexBufferBind(this);
|
||||
}
|
||||
|
||||
GrGLuint GrGLVertexBuffer::bufferID() const {
|
||||
return fBufferID;
|
||||
}
|
||||
|
||||
void* GrGLVertexBuffer::lock() {
|
||||
GrAssert(fBufferID);
|
||||
GrAssert(!isLocked());
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user