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:
bsalomon@google.com 2013-03-07 19:09:11 +00:00
Родитель 8890af397e
Коммит 6918d482d6
11 изменённых файлов: 474 добавлений и 260 удалений

Просмотреть файл

@ -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;