зеркало из https://github.com/mozilla/moz-skia.git
Use vertex array objects on core profiles.
Review URL: https://codereview.chromium.org/12533007 git-svn-id: http://skia.googlecode.com/svn/trunk@8024 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
8890af397e
Коммит
6918d482d6
|
@ -175,6 +175,8 @@
|
|||
'<(skia_src_path)/gpu/gl/GrGLUniformManager.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLUniformManager.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLUniformHandle.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLVertexArray.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLVertexArray.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGLVertexBuffer.cpp',
|
||||
'<(skia_src_path)/gpu/gl/GrGLVertexBuffer.h',
|
||||
'<(skia_src_path)/gpu/gl/GrGpuGL.cpp',
|
||||
|
|
|
@ -57,12 +57,11 @@ void GrGLBufferImpl::abandon() {
|
|||
|
||||
void GrGLBufferImpl::bind(GrGpuGL* gpu) const {
|
||||
VALIDATE();
|
||||
GL_CALL(gpu, BindBuffer(fBufferType, fDesc.fID));
|
||||
if (GR_GL_ARRAY_BUFFER == fBufferType) {
|
||||
gpu->notifyVertexBufferBind(fDesc.fID);
|
||||
gpu->bindVertexBuffer(fDesc.fID);
|
||||
} else {
|
||||
GrAssert(GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType);
|
||||
gpu->notifyIndexBufferBind(fDesc.fID);
|
||||
gpu->bindIndexBufferAndDefaultVertexArray(fDesc.fID);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -308,7 +308,9 @@ const char* GrGLShaderBuilder::fragmentPosition() {
|
|||
#if 1
|
||||
if (fCtxInfo.caps().fragCoordConventionsSupport()) {
|
||||
if (!fSetupFragPosition) {
|
||||
fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n");
|
||||
if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
|
||||
fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n");
|
||||
}
|
||||
fFSInputs.push_back().set(kVec4f_GrSLType,
|
||||
GrGLShaderVar::kIn_TypeModifier,
|
||||
"gl_FragCoord",
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrGLVertexArray.h"
|
||||
#include "GrGpuGL.h"
|
||||
|
||||
#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
|
||||
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X);
|
||||
|
||||
void GrGLAttribArrayState::set(const GrGpuGL* gpu,
|
||||
int index,
|
||||
GrGLVertexBuffer* buffer,
|
||||
GrGLint size,
|
||||
GrGLenum type,
|
||||
GrGLboolean normalized,
|
||||
GrGLsizei stride,
|
||||
GrGLvoid* offset) {
|
||||
GrAssert(index >= 0 && index < fAttribArrayStates.count());
|
||||
AttribArrayState* array = &fAttribArrayStates[index];
|
||||
if (!array->fEnableIsValid || !array->fEnabled) {
|
||||
GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
|
||||
array->fEnableIsValid = true;
|
||||
array->fEnabled = true;
|
||||
}
|
||||
if (!array->fAttribPointerIsValid ||
|
||||
array->fVertexBufferID != buffer->bufferID() ||
|
||||
array->fSize != size ||
|
||||
array->fNormalized != normalized ||
|
||||
array->fStride != stride ||
|
||||
array->fOffset != offset) {
|
||||
|
||||
buffer->bind();
|
||||
GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
|
||||
size,
|
||||
type,
|
||||
normalized,
|
||||
stride,
|
||||
offset));
|
||||
array->fAttribPointerIsValid = true;
|
||||
array->fVertexBufferID = buffer->bufferID();
|
||||
array->fSize = size;
|
||||
array->fNormalized = normalized;
|
||||
array->fStride = stride;
|
||||
array->fOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLAttribArrayState::disableUnusedAttribArrays(const GrGpuGL* gpu, uint64_t usedMask) {
|
||||
int count = fAttribArrayStates.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (!(usedMask & 0x1)) {
|
||||
if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
|
||||
GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
|
||||
fAttribArrayStates[i].fEnableIsValid = true;
|
||||
fAttribArrayStates[i].fEnabled = false;
|
||||
}
|
||||
}
|
||||
// if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
|
||||
usedMask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLVertexArray::GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount)
|
||||
: GrResource(gpu, false)
|
||||
, fID(id)
|
||||
, fAttribArrays(attribCount)
|
||||
, fIndexBufferIDIsValid(false) {
|
||||
}
|
||||
|
||||
void GrGLVertexArray::onAbandon() {
|
||||
fID = 0;
|
||||
INHERITED::onAbandon();
|
||||
}
|
||||
|
||||
void GrGLVertexArray::onRelease() {
|
||||
if (0 != fID) {
|
||||
GL_CALL(DeleteVertexArrays(1, &fID));
|
||||
GPUGL->notifyVertexArrayDelete(fID);
|
||||
fID = 0;
|
||||
}
|
||||
INHERITED::onRelease();
|
||||
}
|
||||
|
||||
GrGLAttribArrayState* GrGLVertexArray::bind() {
|
||||
if (0 == fID) {
|
||||
return NULL;
|
||||
}
|
||||
GPUGL->bindVertexArray(fID);
|
||||
return &fAttribArrays;
|
||||
}
|
||||
|
||||
GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(const GrGLIndexBuffer* buffer) {
|
||||
GrGLAttribArrayState* state = this->bind();
|
||||
if (NULL != state && NULL != buffer) {
|
||||
GrGLuint bufferID = buffer->bufferID();
|
||||
if (!fIndexBufferIDIsValid || bufferID != fIndexBufferID) {
|
||||
GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, bufferID));
|
||||
fIndexBufferIDIsValid = true;
|
||||
fIndexBufferID = bufferID;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void GrGLVertexArray::notifyIndexBufferDelete(GrGLuint bufferID) {
|
||||
if (fIndexBufferIDIsValid && bufferID == fIndexBufferID) {
|
||||
fIndexBufferID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLVertexArray::invalidateCachedState() {
|
||||
int count = fAttribArrays.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
fAttribArrays.invalidate();
|
||||
}
|
||||
fIndexBufferIDIsValid = false;
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrGLVertexArray_DEFINED
|
||||
#define GrGLVertexArray_DEFINED
|
||||
|
||||
#include "GrResource.h"
|
||||
#include "gl/GrGLFunctions.h"
|
||||
|
||||
#include "SkTArray.h"
|
||||
|
||||
class GrGLVertexBuffer;
|
||||
class GrGLIndexBuffer;
|
||||
class GrGpuGL;
|
||||
|
||||
/**
|
||||
* This sets and tracks the vertex attribute array state. It is used internally by GrGLVertexArray
|
||||
* (below) but is separate because it is also used to track the state of vertex array object 0.
|
||||
*/
|
||||
class GrGLAttribArrayState {
|
||||
public:
|
||||
explicit GrGLAttribArrayState(int arrayCount = 0) { this->resize(arrayCount); }
|
||||
|
||||
void resize(int newCount) {
|
||||
fAttribArrayStates.resize_back(newCount);
|
||||
for (int i = 0; i < newCount; ++i) {
|
||||
fAttribArrayStates[i].invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function enables and sets vertex attrib state for the specified attrib index. It is
|
||||
* assumed that the GrGLAttribArrayState is tracking the state of the currently bound vertex
|
||||
* array object.
|
||||
*/
|
||||
void set(const GrGpuGL*,
|
||||
int index,
|
||||
GrGLVertexBuffer*,
|
||||
GrGLint size,
|
||||
GrGLenum type,
|
||||
GrGLboolean normalized,
|
||||
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 invalidate() {
|
||||
int count = fAttribArrayStates.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
fAttribArrayStates[i].invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void notifyVertexBufferDelete(GrGLuint id) {
|
||||
int count = fAttribArrayStates.count();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (id == fAttribArrayStates[i].fVertexBufferID) {
|
||||
fAttribArrayStates[i].invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of attrib arrays that this object is configured to track.
|
||||
*/
|
||||
int count() const { return fAttribArrayStates.count(); }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Tracks the state of glVertexAttribArray for an attribute index.
|
||||
*/
|
||||
struct AttribArrayState {
|
||||
void invalidate() {
|
||||
fEnableIsValid = false;
|
||||
fAttribPointerIsValid = false;
|
||||
}
|
||||
|
||||
bool fEnableIsValid;
|
||||
bool fAttribPointerIsValid;
|
||||
bool fEnabled;
|
||||
GrGLuint fVertexBufferID;
|
||||
GrGLint fSize;
|
||||
GrGLenum fType;
|
||||
GrGLboolean fNormalized;
|
||||
GrGLsizei fStride;
|
||||
GrGLvoid* fOffset;
|
||||
};
|
||||
|
||||
SkSTArray<16, AttribArrayState, true> fAttribArrayStates;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class represents an OpenGL vertex array object. It manages the lifetime of the vertex array
|
||||
* and is used to track the state of the vertex array to avoid redundant GL calls.
|
||||
*/
|
||||
class GrGLVertexArray : public GrResource {
|
||||
public:
|
||||
GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount);
|
||||
|
||||
/**
|
||||
* Binds this vertex array. If the ID has been deleted or abandoned then NULL is returned.
|
||||
* Otherwise, the GrGLAttribArrayState that is tracking this vertex array's attrib bindings is
|
||||
* returned.
|
||||
*/
|
||||
GrGLAttribArrayState* bind();
|
||||
|
||||
/**
|
||||
* This is a version of the above function that also binds an index buffer to the vertex
|
||||
* array object.
|
||||
*/
|
||||
GrGLAttribArrayState* bindWithIndexBuffer(const GrGLIndexBuffer* indexBuffer);
|
||||
|
||||
void notifyIndexBufferDelete(GrGLuint bufferID);
|
||||
|
||||
void notifyVertexBufferDelete(GrGLuint id) {
|
||||
fAttribArrays.notifyVertexBufferDelete(id);
|
||||
}
|
||||
|
||||
GrGLuint arrayID() const { return fID; }
|
||||
|
||||
void invalidateCachedState();
|
||||
|
||||
virtual size_t sizeInBytes() const SK_OVERRIDE { return 0; }
|
||||
|
||||
protected:
|
||||
virtual void onAbandon() SK_OVERRIDE;
|
||||
|
||||
virtual void onRelease() SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
GrGLuint fID;
|
||||
GrGLAttribArrayState fAttribArrays;
|
||||
GrGLuint fIndexBufferID;
|
||||
bool fIndexBufferIDIsValid;
|
||||
|
||||
typedef GrResource INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -180,8 +180,6 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
|
|||
|
||||
fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext()));
|
||||
|
||||
fHWGeometryState.setMaxAttribArrays(this->glCaps().maxVertexAttributes());
|
||||
|
||||
GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt);
|
||||
GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue);
|
||||
GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue);
|
||||
|
@ -423,6 +421,8 @@ void GrGpuGL::onResetContext() {
|
|||
GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP));
|
||||
}
|
||||
if (this->glCaps().imagingSupport()) {
|
||||
// This produces a GL error on the windows NVIDIA driver when using a core profile but
|
||||
// I think that is a driver bug since GL_ARB_imaging is in the extension string.
|
||||
GL_CALL(Disable(GR_GL_COLOR_TABLE));
|
||||
}
|
||||
GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
|
||||
|
@ -1246,8 +1246,7 @@ GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
|
|||
} else {
|
||||
GL_CALL(GenBuffers(1, &desc.fID));
|
||||
if (desc.fID) {
|
||||
GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, desc.fID));
|
||||
fHWGeometryState.setVertexBufferID(desc.fID);
|
||||
fHWGeometryState.setVertexBufferID(this, desc.fID);
|
||||
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
|
||||
// make sure driver can allocate memory for this buffer
|
||||
GL_ALLOC_CALL(this->glInterface(),
|
||||
|
@ -1257,8 +1256,7 @@ GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
|
|||
desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
|
||||
if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
|
||||
GL_CALL(DeleteBuffers(1, &desc.fID));
|
||||
// deleting bound buffer does implicit bind to 0
|
||||
fHWGeometryState.setVertexBufferID(0);
|
||||
this->notifyVertexBufferDelete(desc.fID);
|
||||
return NULL;
|
||||
}
|
||||
GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer, (this, desc));
|
||||
|
@ -1281,8 +1279,7 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
|
|||
} else {
|
||||
GL_CALL(GenBuffers(1, &desc.fID));
|
||||
if (desc.fID) {
|
||||
GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, desc.fID));
|
||||
fHWGeometryState.setIndexBufferID(desc.fID);
|
||||
fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, desc.fID);
|
||||
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
|
||||
// make sure driver can allocate memory for this buffer
|
||||
GL_ALLOC_CALL(this->glInterface(),
|
||||
|
@ -1292,8 +1289,7 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
|
|||
desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
|
||||
if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
|
||||
GL_CALL(DeleteBuffers(1, &desc.fID));
|
||||
// deleting bound buffer does implicit bind to 0
|
||||
fHWGeometryState.setIndexBufferID(0);
|
||||
this->notifyIndexBufferDelete(desc.fID);
|
||||
return NULL;
|
||||
}
|
||||
GrIndexBuffer* indexBuffer = SkNEW_ARGS(GrGLIndexBuffer, (this, desc));
|
||||
|
@ -2165,22 +2161,6 @@ void GrGpuGL::flushMiscFixedFunctionState() {
|
|||
}
|
||||
}
|
||||
|
||||
void GrGpuGL::notifyVertexBufferBind(GrGLuint id) {
|
||||
fHWGeometryState.setVertexBufferID(id);
|
||||
}
|
||||
|
||||
void GrGpuGL::notifyVertexBufferDelete(GrGLuint id) {
|
||||
fHWGeometryState.notifyVertexBufferDelete(id);
|
||||
}
|
||||
|
||||
void GrGpuGL::notifyIndexBufferBind(GrGLuint id) {
|
||||
fHWGeometryState.setIndexBufferID(id);
|
||||
}
|
||||
|
||||
void GrGpuGL::notifyIndexBufferDelete(GrGLuint id) {
|
||||
fHWGeometryState.notifyIndexBufferDelete(id);
|
||||
}
|
||||
|
||||
void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
|
||||
GrAssert(NULL != renderTarget);
|
||||
if (fHWBoundRenderTarget == renderTarget) {
|
||||
|
@ -2323,105 +2303,35 @@ void GrGpuGL::setSpareTextureUnit() {
|
|||
}
|
||||
}
|
||||
|
||||
GrGLVertexBuffer* GrGpuGL::setBuffers(bool indexed,
|
||||
size_t* vertexOffsetInBytes,
|
||||
size_t* indexOffsetInBytes) {
|
||||
|
||||
GrAssert(NULL != vertexOffsetInBytes);
|
||||
|
||||
const GeometryPoolState& geoPoolState = this->getGeomPoolState();
|
||||
|
||||
GrGLVertexBuffer* vbuf;
|
||||
switch (this->getGeomSrc().fVertexSrc) {
|
||||
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());
|
||||
*vertexOffsetInBytes += vbuf->baseOffset();
|
||||
|
||||
if (indexed) {
|
||||
GrAssert(NULL != indexOffsetInBytes);
|
||||
|
||||
GrGLIndexBuffer* ibuf;
|
||||
switch (this->getGeomSrc().fIndexSrc) {
|
||||
case kBuffer_GeometrySrcType:
|
||||
*indexOffsetInBytes = 0;
|
||||
ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
|
||||
break;
|
||||
case kArray_GeometrySrcType:
|
||||
case kReserved_GeometrySrcType:
|
||||
this->finalizeReservedIndices();
|
||||
*indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort);
|
||||
ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
|
||||
break;
|
||||
default:
|
||||
ibuf = NULL; // suppress warning
|
||||
GrCrash("Unknown geometry src type!");
|
||||
}
|
||||
|
||||
GrAssert(NULL != ibuf);
|
||||
GrAssert(!ibuf->isLocked());
|
||||
*indexOffsetInBytes += ibuf->baseOffset();
|
||||
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);
|
||||
GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw(
|
||||
GrGpuGL* gpu,
|
||||
const GrGLVertexBuffer* vbuffer,
|
||||
const GrGLIndexBuffer* ibuffer) {
|
||||
GrAssert(NULL != vbuffer);
|
||||
GrGLAttribArrayState* attribState = &fDefaultVertexArrayAttribState;
|
||||
// We use a vertex array if we're on a core profile and the verts are in a VBO.
|
||||
if (gpu->glCaps().isCoreProfile() && !vbuffer->isCPUBacked()) {
|
||||
if (NULL == fVBOVertexArray || !fVBOVertexArray->isValid()) {
|
||||
SkSafeUnref(fVBOVertexArray);
|
||||
GrGLuint arrayID;
|
||||
GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID));
|
||||
int attrCount = gpu->glCaps().maxVertexAttributes();
|
||||
fVBOVertexArray = SkNEW_ARGS(GrGLVertexArray, (gpu, arrayID, attrCount));
|
||||
}
|
||||
GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
|
||||
size,
|
||||
type,
|
||||
normalized,
|
||||
stride,
|
||||
offset));
|
||||
fAttribPointerIsValid = true;
|
||||
fVertexBufferID = bufferID;
|
||||
fSize = size;
|
||||
fNormalized = normalized;
|
||||
fStride = stride;
|
||||
fOffset = offset;
|
||||
attribState = fVBOVertexArray->bindWithIndexBuffer(ibuffer);
|
||||
} else {
|
||||
if (NULL != ibuffer) {
|
||||
this->setIndexBufferIDOnDefaultVertexArray(gpu, ibuffer->bufferID());
|
||||
} else {
|
||||
this->setVertexArrayID(gpu, 0);
|
||||
}
|
||||
int attrCount = gpu->glCaps().maxVertexAttributes();
|
||||
if (fDefaultVertexArrayAttribState.count() != attrCount) {
|
||||
fDefaultVertexArrayAttribState.resize(attrCount);
|
||||
}
|
||||
attribState = &fDefaultVertexArrayAttribState;
|
||||
}
|
||||
return attribState;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "GrGLProgram.h"
|
||||
#include "GrGLStencilBuffer.h"
|
||||
#include "GrGLTexture.h"
|
||||
#include "GrGLVertexArray.h"
|
||||
#include "GrGLVertexBuffer.h"
|
||||
#include "../GrTHashCache.h"
|
||||
|
||||
|
@ -54,11 +55,29 @@ public:
|
|||
|
||||
const GrGLCaps& glCaps() const { return fGLContext.info().caps(); }
|
||||
|
||||
// Callbacks to update state tracking when related GL objects are bound or deleted
|
||||
void notifyVertexBufferBind(GrGLuint id);
|
||||
void notifyVertexBufferDelete(GrGLuint id);
|
||||
void notifyIndexBufferBind(GrGLuint id);
|
||||
void notifyIndexBufferDelete(GrGLuint id);
|
||||
// These functions should be used to bind GL objects. They track the GL state and skip redundant
|
||||
// bindings. Making the equivalent glBind calls directly will confuse the state tracking.
|
||||
void bindVertexArray(GrGLuint id) {
|
||||
fHWGeometryState.setVertexArrayID(this, id);
|
||||
}
|
||||
void bindIndexBufferAndDefaultVertexArray(GrGLuint id) {
|
||||
fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id);
|
||||
}
|
||||
void bindVertexBuffer(GrGLuint id) {
|
||||
fHWGeometryState.setVertexBufferID(this, id);
|
||||
}
|
||||
|
||||
// These callbacks update state tracking when GL objects are deleted. They are called from
|
||||
// GrGLResource onRelease functions.
|
||||
void notifyVertexArrayDelete(GrGLuint id) {
|
||||
fHWGeometryState.notifyVertexArrayDelete(id);
|
||||
}
|
||||
void notifyVertexBufferDelete(GrGLuint id) {
|
||||
fHWGeometryState.notifyVertexBufferDelete(id);
|
||||
}
|
||||
void notifyIndexBufferDelete(GrGLuint id) {
|
||||
fHWGeometryState.notifyIndexBufferDelete(id);
|
||||
}
|
||||
void notifyTextureDelete(GrGLTexture* texture);
|
||||
void notifyRenderTargetDelete(GrRenderTarget* renderTarget);
|
||||
|
||||
|
@ -121,12 +140,6 @@ private:
|
|||
// 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
|
||||
|
@ -268,134 +281,104 @@ private:
|
|||
*/
|
||||
class HWGeometryState {
|
||||
public:
|
||||
HWGeometryState() { fAttribArrayCount = 0; this->invalidate();}
|
||||
HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); }
|
||||
|
||||
~HWGeometryState() { SkSafeUnref(fVBOVertexArray); }
|
||||
|
||||
void setMaxAttribArrays(int max) {
|
||||
fAttribArrayCount = max;
|
||||
fAttribArrays.reset(max);
|
||||
for (int i = 0; i < fAttribArrayCount; ++i) {
|
||||
fAttribArrays[i].invalidate();
|
||||
void invalidate() {
|
||||
fBoundVertexArrayIDIsValid = false;
|
||||
fBoundVertexBufferIDIsValid = false;
|
||||
fDefaultVertexArrayBoundIndexBufferID = false;
|
||||
fDefaultVertexArrayBoundIndexBufferIDIsValid = false;
|
||||
fDefaultVertexArrayAttribState.invalidate();
|
||||
}
|
||||
|
||||
void notifyVertexArrayDelete(GrGLuint id) {
|
||||
if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) {
|
||||
// Does implicit bind to 0
|
||||
fBoundVertexArrayID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
fBoundVertexBufferIDIsValid = false;
|
||||
fBoundIndexBufferIDIsValid = false;
|
||||
for (int i = 0; i < fAttribArrayCount; ++i) {
|
||||
fAttribArrays[i].invalidate();
|
||||
void setVertexArrayID(GrGpuGL* gpu, GrGLuint arrayID) {
|
||||
if (!gpu->glCaps().vertexArrayObjectSupport()) {
|
||||
GrAssert(0 == arrayID);
|
||||
return;
|
||||
}
|
||||
if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) {
|
||||
GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID));
|
||||
fBoundVertexArrayIDIsValid = true;
|
||||
fBoundVertexArrayID = arrayID;
|
||||
}
|
||||
}
|
||||
|
||||
void notifyVertexBufferDelete(GrGLuint id) {
|
||||
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].isVertexBufferIDBound(id)) {
|
||||
fAttribArrays[i].invalidate();
|
||||
}
|
||||
}
|
||||
if (fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID) {
|
||||
fBoundVertexBufferID = 0;
|
||||
}
|
||||
if (NULL != fVBOVertexArray) {
|
||||
fVBOVertexArray->notifyVertexBufferDelete(id);
|
||||
}
|
||||
fDefaultVertexArrayAttribState.notifyVertexBufferDelete(id);
|
||||
}
|
||||
|
||||
void notifyIndexBufferDelete(GrGLuint id) {
|
||||
if (0 != id) {
|
||||
if (this->isIndexBufferIDBound(id)) {
|
||||
// deleting bound buffer does implied bind to 0
|
||||
this->setIndexBufferID(0);
|
||||
}
|
||||
if (fDefaultVertexArrayBoundIndexBufferIDIsValid &&
|
||||
id == fDefaultVertexArrayBoundIndexBufferID) {
|
||||
fDefaultVertexArrayBoundIndexBufferID = 0;
|
||||
}
|
||||
if (NULL != fVBOVertexArray) {
|
||||
fVBOVertexArray->notifyIndexBufferDelete(id);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
void setVertexBufferID(GrGpuGL* gpu, GrGLuint id) {
|
||||
if (!fBoundVertexBufferIDIsValid || id != fBoundVertexBufferID) {
|
||||
GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ARRAY_BUFFER, id));
|
||||
fBoundVertexBufferIDIsValid = true;
|
||||
fBoundVertexBufferID = id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the default vertex array and binds the index buffer. This is used when binding
|
||||
* an index buffer in order to update it.
|
||||
*/
|
||||
void setIndexBufferIDOnDefaultVertexArray(GrGpuGL* gpu, GrGLuint id) {
|
||||
this->setVertexArrayID(gpu, 0);
|
||||
if (!fDefaultVertexArrayBoundIndexBufferIDIsValid ||
|
||||
id != fDefaultVertexArrayBoundIndexBufferID) {
|
||||
GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id));
|
||||
fDefaultVertexArrayBoundIndexBufferIDIsValid = true;
|
||||
fDefaultVertexArrayBoundIndexBufferID = id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the vertex array object that should be used to render from the vertex buffer.
|
||||
* The vertex array is bound and its attrib array state object is returned. The vertex
|
||||
* buffer is bound. The index buffer (if non-NULL) is bound to the vertex array. The
|
||||
* returned GrGLAttribArrayState should be used to set vertex attribute arrays.
|
||||
*/
|
||||
GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGpuGL* gpu,
|
||||
const GrGLVertexBuffer* vbuffer,
|
||||
const GrGLIndexBuffer* ibuffer);
|
||||
|
||||
private:
|
||||
GrGLuint fBoundVertexArrayID;
|
||||
GrGLuint fBoundVertexBufferID;
|
||||
GrGLuint fBoundIndexBufferID;
|
||||
bool fBoundVertexArrayIDIsValid;
|
||||
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);
|
||||
GrGLuint fDefaultVertexArrayBoundIndexBufferID;
|
||||
bool fDefaultVertexArrayBoundIndexBufferIDIsValid;
|
||||
// We return a non-const pointer to this from bindArrayAndBuffersToDraw when vertex array 0
|
||||
// is bound. However, this class is internal to GrGpuGL and this object never leaks out of
|
||||
// GrGpuGL.
|
||||
GrGLAttribArrayState fDefaultVertexArrayAttribState;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool isVertexBufferIDBound(GrGLuint id) const {
|
||||
return fAttribPointerIsValid && id == 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;
|
||||
// This is used when we're using a core profile and the vertices are in a VBO.
|
||||
GrGLVertexArray* fVBOVertexArray;
|
||||
} fHWGeometryState;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -217,9 +217,56 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
|
|||
|
||||
GrGLsizei stride = this->getDrawState().getVertexSize();
|
||||
|
||||
size_t vertexOffset;
|
||||
GrGLVertexBuffer* vb= this->setBuffers(info.isIndexed(), &vertexOffset, indexOffsetInBytes);
|
||||
vertexOffset += stride * info.startVertex();
|
||||
size_t vertexOffsetInBytes = stride * info.startVertex();
|
||||
|
||||
const GeometryPoolState& geoPoolState = this->getGeomPoolState();
|
||||
|
||||
GrGLVertexBuffer* vbuf;
|
||||
switch (this->getGeomSrc().fVertexSrc) {
|
||||
case kBuffer_GeometrySrcType:
|
||||
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());
|
||||
vertexOffsetInBytes += vbuf->baseOffset();
|
||||
|
||||
GrGLIndexBuffer* ibuf = NULL;
|
||||
if (info.isIndexed()) {
|
||||
GrAssert(NULL != indexOffsetInBytes);
|
||||
|
||||
switch (this->getGeomSrc().fIndexSrc) {
|
||||
case kBuffer_GeometrySrcType:
|
||||
*indexOffsetInBytes = 0;
|
||||
ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
|
||||
break;
|
||||
case kArray_GeometrySrcType:
|
||||
case kReserved_GeometrySrcType:
|
||||
this->finalizeReservedIndices();
|
||||
*indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort);
|
||||
ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
|
||||
break;
|
||||
default:
|
||||
ibuf = NULL; // suppress warning
|
||||
GrCrash("Unknown geometry src type!");
|
||||
}
|
||||
|
||||
GrAssert(NULL != ibuf);
|
||||
GrAssert(!ibuf->isLocked());
|
||||
*indexOffsetInBytes += ibuf->baseOffset();
|
||||
}
|
||||
GrGLAttribArrayState* attribState =
|
||||
fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
|
||||
|
||||
uint32_t usedAttribArraysMask = 0;
|
||||
const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
|
||||
|
@ -229,16 +276,16 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
|
|||
|
||||
usedAttribArraysMask |= (1 << vertexAttribIndex);
|
||||
GrVertexAttribType attribType = vertexAttrib->fType;
|
||||
fHWGeometryState.setAttribArray(this,
|
||||
vertexAttribIndex,
|
||||
vb,
|
||||
GrGLProgram::kAttribLayouts[attribType].fCount,
|
||||
GrGLProgram::kAttribLayouts[attribType].fType,
|
||||
GrGLProgram::kAttribLayouts[attribType].fNormalized,
|
||||
stride,
|
||||
reinterpret_cast<GrGLvoid*>(
|
||||
vertexOffset + vertexAttrib->fOffset));
|
||||
}
|
||||
attribState->set(this,
|
||||
vertexAttribIndex,
|
||||
vbuf,
|
||||
GrGLProgram::kAttribLayouts[attribType].fCount,
|
||||
GrGLProgram::kAttribLayouts[attribType].fType,
|
||||
GrGLProgram::kAttribLayouts[attribType].fNormalized,
|
||||
stride,
|
||||
reinterpret_cast<GrGLvoid*>(
|
||||
vertexOffsetInBytes + vertexAttrib->fOffset));
|
||||
}
|
||||
|
||||
fHWGeometryState.disableUnusedAttribArrays(this, usedAttribArraysMask);
|
||||
attribState->disableUnusedAttribArrays(this, usedAttribArraysMask);
|
||||
}
|
||||
|
|
|
@ -559,7 +559,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteVertexArrays(GrGLsizei n, const GrGLui
|
|||
|
||||
GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindVertexArray(GrGLuint id) {
|
||||
GrVertexArrayObj* array = GR_FIND(id, GrVertexArrayObj, GrDebugGL::kVertexArray_ObjTypes);
|
||||
GrAlwaysAssert(array);
|
||||
GrAlwaysAssert((0 == id) || NULL != array);
|
||||
GrDebugGL::getInstance()->setVertexArray(array);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "gl/SkNativeGLContext.h"
|
||||
#include "AvailabilityMacros.h"
|
||||
|
||||
SkNativeGLContext::AutoContextRestore::AutoContextRestore() {
|
||||
fOldCGLContext = CGLGetCurrentContext();
|
||||
|
@ -35,7 +36,7 @@ const GrGLInterface* SkNativeGLContext::createGLContext() {
|
|||
SkASSERT(NULL == fContext);
|
||||
|
||||
CGLPixelFormatAttribute attributes[] = {
|
||||
#if 0
|
||||
#if MAC_OS_X_VERSION_10_7
|
||||
kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
|
||||
#endif
|
||||
(CGLPixelFormatAttribute)0
|
||||
|
|
|
@ -86,7 +86,7 @@ const GrGLInterface* SkNativeGLContext::createGLContext() {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false))) {
|
||||
if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, true))) {
|
||||
SkDebugf("Could not create rendering context.\n");
|
||||
this->destroyGLContext();
|
||||
return NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче