| Index: src/gpu/gl/GrGLGpu.cpp
|
| diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
|
| index c8c12a388d3fcf1aa730188e8210e4e0d55027f3..e563325d7fe7394d5f42f51b1d2ee9f9f45586b5 100644
|
| --- a/src/gpu/gl/GrGLGpu.cpp
|
| +++ b/src/gpu/gl/GrGLGpu.cpp
|
| @@ -188,12 +188,45 @@ static bool gPrintStartupSpew;
|
|
|
| GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
|
| : GrGpu(context)
|
| - , fGLContext(ctx) {
|
| + , fGLContext(ctx)
|
| + , fProgramCache(new ProgramCache(this))
|
| + , fHWProgramID(0)
|
| + , fTempSrcFBOID(0)
|
| + , fTempDstFBOID(0)
|
| + , fStencilClearFBOID(0)
|
| + , fHWPLSEnabled(false)
|
| + , fPLSHasBeenUsed(false)
|
| + , fHWMinSampleShading(0.0) {
|
| + for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
|
| + fCopyPrograms[i].fProgram = 0;
|
| + }
|
| + fWireRectProgram.fProgram = 0;
|
| + fPLSSetupProgram.fProgram = 0;
|
| +
|
| SkASSERT(ctx);
|
| fCaps.reset(SkRef(ctx->caps()));
|
|
|
| fHWBoundTextureUniqueIDs.reset(this->glCaps().glslCaps()->maxCombinedSamplers());
|
|
|
| + fHWBufferState[kVertex_GrBufferType].fGLTarget = GR_GL_ARRAY_BUFFER;
|
| + fHWBufferState[kIndex_GrBufferType].fGLTarget = GR_GL_ELEMENT_ARRAY_BUFFER;
|
| + fHWBufferState[kTexel_GrBufferType].fGLTarget = GR_GL_TEXTURE_BUFFER;
|
| + fHWBufferState[kDrawIndirect_GrBufferType].fGLTarget = GR_GL_DRAW_INDIRECT_BUFFER;
|
| + if (GrGLCaps::kChromium_TransferBufferType == this->glCaps().transferBufferType()) {
|
| + fHWBufferState[kXferCpuToGpu_GrBufferType].fGLTarget =
|
| + GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM;
|
| + fHWBufferState[kXferGpuToCpu_GrBufferType].fGLTarget =
|
| + GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM;
|
| + } else {
|
| + fHWBufferState[kXferCpuToGpu_GrBufferType].fGLTarget = GR_GL_PIXEL_UNPACK_BUFFER;
|
| + fHWBufferState[kXferGpuToCpu_GrBufferType].fGLTarget = GR_GL_PIXEL_PACK_BUFFER;
|
| + }
|
| + GR_STATIC_ASSERT(6 == SK_ARRAY_COUNT(fHWBufferState));
|
| +
|
| + if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
|
| + fPathRendering.reset(new GrGLPathRendering(this));
|
| + }
|
| +
|
| GrGLClearErr(this->glInterface());
|
| if (gPrintStartupSpew) {
|
| const GrGLubyte* vendor;
|
| @@ -212,35 +245,15 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
|
| SkDebugf("\n");
|
| SkDebugf("%s", this->glCaps().dump().c_str());
|
| }
|
| -
|
| - fProgramCache = new ProgramCache(this);
|
| -
|
| - fHWProgramID = 0;
|
| - fTempSrcFBOID = 0;
|
| - fTempDstFBOID = 0;
|
| - fStencilClearFBOID = 0;
|
| -
|
| - if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
|
| - fPathRendering.reset(new GrGLPathRendering(this));
|
| - }
|
| - this->createCopyPrograms();
|
| - fWireRectProgram.fProgram = 0;
|
| - fWireRectArrayBuffer = 0;
|
| - if (this->glCaps().shaderCaps()->plsPathRenderingSupport()) {
|
| - this->createPLSSetupProgram();
|
| - }
|
| - else {
|
| - memset(&fPLSSetupProgram, 0, sizeof(fPLSSetupProgram));
|
| - }
|
| - fHWPLSEnabled = false;
|
| - fPLSHasBeenUsed = false;
|
| - fHWMinSampleShading = 0.0;
|
| }
|
|
|
| GrGLGpu::~GrGLGpu() {
|
| - // Delete the path rendering explicitly, since it will need working gpu object to release the
|
| - // resources the object itself holds.
|
| + // Ensure any GrGpuResource objects get deleted first, since they may require a working GrGLGpu
|
| + // to release the resources held by the objects themselves.
|
| fPathRendering.reset();
|
| + fCopyProgramArrayBuffer.reset();
|
| + fWireRectArrayBuffer.reset();
|
| + fPLSSetupProgram.fArrayBuffer.reset();
|
|
|
| if (0 != fHWProgramID) {
|
| // detach the current program so there is no confusion on OpenGL's part
|
| @@ -264,22 +277,10 @@ GrGLGpu::~GrGLGpu() {
|
| }
|
| }
|
|
|
| - if (0 != fCopyProgramArrayBuffer) {
|
| - GL_CALL(DeleteBuffers(1, &fCopyProgramArrayBuffer));
|
| - }
|
| -
|
| if (0 != fWireRectProgram.fProgram) {
|
| GL_CALL(DeleteProgram(fWireRectProgram.fProgram));
|
| }
|
|
|
| - if (0 != fWireRectArrayBuffer) {
|
| - GL_CALL(DeleteBuffers(1, &fWireRectArrayBuffer));
|
| - }
|
| -
|
| - if (0 != fPLSSetupProgram.fArrayBuffer) {
|
| - GL_CALL(DeleteBuffers(1, &fPLSSetupProgram.fArrayBuffer));
|
| - }
|
| -
|
| if (0 != fPLSSetupProgram.fProgram) {
|
| GL_CALL(DeleteProgram(fPLSSetupProgram.fProgram));
|
| }
|
| @@ -287,7 +288,28 @@ GrGLGpu::~GrGLGpu() {
|
| delete fProgramCache;
|
| }
|
|
|
| -void GrGLGpu::createPLSSetupProgram() {
|
| +bool GrGLGpu::createPLSSetupProgram() {
|
| + if (!fPLSSetupProgram.fArrayBuffer) {
|
| + static const GrGLfloat vdata[] = {
|
| + 0, 0,
|
| + 0, 1,
|
| + 1, 0,
|
| + 1, 1
|
| + };
|
| + fPLSSetupProgram.fArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata),
|
| + kVertex_GrBufferType,
|
| + kStatic_GrAccessPattern, vdata));
|
| + if (!fPLSSetupProgram.fArrayBuffer) {
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + SkASSERT(!fPLSSetupProgram.fProgram);
|
| + GL_CALL_RET(fPLSSetupProgram.fProgram, CreateProgram());
|
| + if (!fPLSSetupProgram.fProgram) {
|
| + return false;
|
| + }
|
| +
|
| const GrGLSLCaps* glslCaps = this->glCaps().glslCaps();
|
| const char* version = glslCaps->versionDeclString();
|
|
|
| @@ -347,7 +369,7 @@ void GrGLGpu::createPLSSetupProgram() {
|
| " pls.windings = ivec4(0, 0, 0, 0);\n"
|
| "}"
|
| );
|
| - GL_CALL_RET(fPLSSetupProgram.fProgram, CreateProgram());
|
| +
|
| const char* str;
|
| GrGLint length;
|
|
|
| @@ -371,19 +393,7 @@ void GrGLGpu::createPLSSetupProgram() {
|
| GL_CALL(DeleteShader(vshader));
|
| GL_CALL(DeleteShader(fshader));
|
|
|
| - GL_CALL(GenBuffers(1, &fPLSSetupProgram.fArrayBuffer));
|
| - fHWGeometryState.setVertexBufferID(this, fPLSSetupProgram.fArrayBuffer);
|
| - static const GrGLfloat vdata[] = {
|
| - 0, 0,
|
| - 0, 1,
|
| - 1, 0,
|
| - 1, 1
|
| - };
|
| - GL_ALLOC_CALL(this->glInterface(),
|
| - BufferData(GR_GL_ARRAY_BUFFER,
|
| - (GrGLsizeiptr) sizeof(vdata),
|
| - vdata, // data ptr
|
| - GR_GL_STATIC_DRAW));
|
| + return true;
|
| }
|
|
|
| void GrGLGpu::disconnect(DisconnectType type) {
|
| @@ -401,9 +411,6 @@ void GrGLGpu::disconnect(DisconnectType type) {
|
| if (fStencilClearFBOID) {
|
| GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
|
| }
|
| - if (fCopyProgramArrayBuffer) {
|
| - GL_CALL(DeleteBuffers(1, &fCopyProgramArrayBuffer));
|
| - }
|
| for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
|
| if (fCopyPrograms[i].fProgram) {
|
| GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram));
|
| @@ -412,16 +419,9 @@ void GrGLGpu::disconnect(DisconnectType type) {
|
| if (fWireRectProgram.fProgram) {
|
| GL_CALL(DeleteProgram(fWireRectProgram.fProgram));
|
| }
|
| - if (fWireRectArrayBuffer) {
|
| - GL_CALL(DeleteBuffers(1, &fWireRectArrayBuffer));
|
| - }
|
| -
|
| if (fPLSSetupProgram.fProgram) {
|
| GL_CALL(DeleteProgram(fPLSSetupProgram.fProgram));
|
| }
|
| - if (fPLSSetupProgram.fArrayBuffer) {
|
| - GL_CALL(DeleteBuffers(1, &fPLSSetupProgram.fArrayBuffer));
|
| - }
|
| } else {
|
| if (fProgramCache) {
|
| fProgramCache->abandon();
|
| @@ -435,14 +435,14 @@ void GrGLGpu::disconnect(DisconnectType type) {
|
| fTempSrcFBOID = 0;
|
| fTempDstFBOID = 0;
|
| fStencilClearFBOID = 0;
|
| - fCopyProgramArrayBuffer = 0;
|
| + fCopyProgramArrayBuffer.reset();
|
| for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
|
| fCopyPrograms[i].fProgram = 0;
|
| }
|
| fWireRectProgram.fProgram = 0;
|
| - fWireRectArrayBuffer = 0;
|
| + fWireRectArrayBuffer.reset();
|
| fPLSSetupProgram.fProgram = 0;
|
| - fPLSSetupProgram.fArrayBuffer = 0;
|
| + fPLSSetupProgram.fArrayBuffer.reset();
|
| if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
|
| this->glPathRendering()->disconnect(type);
|
| }
|
| @@ -456,8 +456,10 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
|
| GL_CALL(Disable(GR_GL_DEPTH_TEST));
|
| GL_CALL(DepthMask(GR_GL_FALSE));
|
|
|
| - fHWBoundTextureBufferIDIsValid = false;
|
| - fHWBoundDrawIndirectBufferIDIsValid = false;
|
| + fHWBufferState[kTexel_GrBufferType].invalidate();
|
| + fHWBufferState[kDrawIndirect_GrBufferType].invalidate();
|
| + fHWBufferState[kXferCpuToGpu_GrBufferType].invalidate();
|
| + fHWBufferState[kXferGpuToCpu_GrBufferType].invalidate();
|
|
|
| fHWDrawFace = GrPipelineBuilder::kInvalid_DrawFace;
|
|
|
| @@ -538,7 +540,9 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
|
|
|
| // Vertex
|
| if (resetBits & kVertex_GrGLBackendState) {
|
| - fHWGeometryState.invalidate();
|
| + fHWVertexArrayState.invalidate();
|
| + fHWBufferState[kVertex_GrBufferType].invalidate();
|
| + fHWBufferState[kIndex_GrBufferType].invalidate();
|
| }
|
|
|
| if (resetBits & kRenderTarget_GrGLBackendState) {
|
| @@ -900,11 +904,10 @@ bool GrGLGpu::onTransferPixels(GrSurface* surface,
|
| this->setScratchTextureUnit();
|
| GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
|
|
|
| - SkASSERT(kXferCpuToGpu_GrBufferType == transferBuffer->type());
|
| SkASSERT(!transferBuffer->isMapped());
|
| SkASSERT(!transferBuffer->isCPUBacked());
|
| const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(transferBuffer);
|
| - this->bindBuffer(glBuffer->bufferID(), glBuffer->target());
|
| + this->bindBuffer(kXferCpuToGpu_GrBufferType, glBuffer);
|
|
|
| bool success = false;
|
| GrMipLevel mipLevel;
|
| @@ -1974,8 +1977,9 @@ GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen
|
| // objects are implemented as client-side-arrays on tile-deferred architectures.
|
| #define DYNAMIC_USAGE_PARAM GR_GL_STREAM_DRAW
|
|
|
| -GrBuffer* GrGLGpu::onCreateBuffer(GrBufferType type, size_t size, GrAccessPattern accessPattern) {
|
| - return GrGLBuffer::Create(this, type, size, accessPattern);
|
| +GrBuffer* GrGLGpu::onCreateBuffer(size_t size, GrBufferType intendedType,
|
| + GrAccessPattern accessPattern) {
|
| + return GrGLBuffer::Create(this, size, intendedType, accessPattern);
|
| }
|
|
|
| void GrGLGpu::flushScissor(const GrScissorState& scissorState,
|
| @@ -2079,22 +2083,21 @@ void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
|
|
|
| SkASSERT(vbuf);
|
| SkASSERT(!vbuf->isMapped());
|
| - SkASSERT(kVertex_GrBufferType == vbuf->type());
|
|
|
| - const GrGLBuffer* ibuf = nullptr;
|
| + GrGLAttribArrayState* attribState;
|
| if (mesh.isIndexed()) {
|
| SkASSERT(indexOffsetInBytes);
|
|
|
| *indexOffsetInBytes = 0;
|
| - ibuf = static_cast<const GrGLBuffer*>(mesh.indexBuffer());
|
| + const GrGLBuffer* ibuf = static_cast<const GrGLBuffer*>(mesh.indexBuffer());
|
|
|
| SkASSERT(ibuf);
|
| SkASSERT(!ibuf->isMapped());
|
| - SkASSERT(kIndex_GrBufferType == ibuf->type());
|
| *indexOffsetInBytes += ibuf->baseOffset();
|
| + attribState = fHWVertexArrayState.bindInternalVertexArray(this, ibuf);
|
| + } else {
|
| + attribState = fHWVertexArrayState.bindInternalVertexArray(this);
|
| }
|
| - GrGLAttribArrayState* attribState =
|
| - fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
|
|
|
| int vaCount = primProc.numAttribs();
|
| if (vaCount > 0) {
|
| @@ -2114,7 +2117,7 @@ void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
|
| GrVertexAttribType attribType = attrib.fType;
|
| attribState->set(this,
|
| attribIndex,
|
| - vbuf->bufferID(),
|
| + vbuf,
|
| attribType,
|
| stride,
|
| reinterpret_cast<GrGLvoid*>(vertexOffsetInBytes + offset));
|
| @@ -2124,57 +2127,26 @@ void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc,
|
| }
|
| }
|
|
|
| -void GrGLGpu::bindBuffer(GrGLuint id, GrGLenum type) {
|
| +GrGLenum GrGLGpu::bindBuffer(GrBufferType type, const GrGLBuffer* buffer) {
|
| this->handleDirtyContext();
|
| - switch (type) {
|
| - case GR_GL_ARRAY_BUFFER:
|
| - this->bindVertexBuffer(id);
|
| - break;
|
| - case GR_GL_ELEMENT_ARRAY_BUFFER:
|
| - this->bindIndexBufferAndDefaultVertexArray(id);
|
| - break;
|
| - case GR_GL_TEXTURE_BUFFER:
|
| - if (!fHWBoundTextureBufferIDIsValid || id != fHWBoundTextureBufferID) {
|
| - GR_GL_CALL(this->glInterface(), BindBuffer(type, id));
|
| - fHWBoundTextureBufferID = id;
|
| - fHWBoundTextureBufferIDIsValid = true;
|
| - }
|
| - break;
|
| - case GR_GL_DRAW_INDIRECT_BUFFER:
|
| - if (!fHWBoundDrawIndirectBufferIDIsValid || id != fHWBoundDrawIndirectBufferID) {
|
| - GR_GL_CALL(this->glInterface(), BindBuffer(type, id));
|
| - fHWBoundDrawIndirectBufferID = id;
|
| - fHWBoundDrawIndirectBufferIDIsValid = true;
|
| - }
|
| - break;
|
| - default:
|
| - SkDebugf("WARNING: buffer target 0x%x is not tracked by GrGLGpu.\n", type);
|
| - GR_GL_CALL(this->glInterface(), BindBuffer(type, id));
|
| - break;
|
| +
|
| + // Index buffer state is tied to the vertex array.
|
| + if (kIndex_GrBufferType == type) {
|
| + this->bindVertexArray(0);
|
| }
|
| -}
|
|
|
| -void GrGLGpu::releaseBuffer(GrGLuint id, GrGLenum type) {
|
| - this->handleDirtyContext();
|
| - GL_CALL(DeleteBuffers(1, &id));
|
| - switch (type) {
|
| - case GR_GL_ARRAY_BUFFER:
|
| - this->notifyVertexBufferDelete(id);
|
| - break;
|
| - case GR_GL_ELEMENT_ARRAY_BUFFER:
|
| - this->notifyIndexBufferDelete(id);
|
| - break;
|
| - case GR_GL_TEXTURE_BUFFER:
|
| - if (fHWBoundTextureBufferIDIsValid && id == fHWBoundTextureBufferID) {
|
| - fHWBoundTextureBufferID = 0;
|
| - }
|
| - break;
|
| - case GR_GL_DRAW_INDIRECT_BUFFER:
|
| - if (fHWBoundDrawIndirectBufferIDIsValid && id == fHWBoundDrawIndirectBufferID) {
|
| - fHWBoundDrawIndirectBufferID = 0;
|
| - }
|
| - break;
|
| + SkASSERT(type >= 0 && type <= kLast_GrBufferType);
|
| + auto& bufferState = fHWBufferState[type];
|
| +
|
| + if (buffer->getUniqueID() != bufferState.fBoundBufferUniqueID) {
|
| + if (!buffer->isCPUBacked() || !bufferState.fBufferZeroKnownBound) {
|
| + GL_CALL(BindBuffer(bufferState.fGLTarget, buffer->bufferID()));
|
| + bufferState.fBufferZeroKnownBound = buffer->isCPUBacked();
|
| + }
|
| + bufferState.fBoundBufferUniqueID = buffer->getUniqueID();
|
| }
|
| +
|
| + return bufferState.fGLTarget;
|
| }
|
|
|
| void GrGLGpu::disableScissor() {
|
| @@ -2672,10 +2644,7 @@ void GrGLGpu::finishDrawTarget() {
|
| SkASSERT(!fHWPLSEnabled);
|
| SkASSERT(fMSAAEnabled != kYes_TriState);
|
| GL_CALL(Enable(GR_GL_SHADER_PIXEL_LOCAL_STORAGE));
|
| - this->stampRectUsingProgram(fPLSSetupProgram.fProgram,
|
| - SkRect::MakeXYWH(-100.0f, -100.0f, 0.01f, 0.01f),
|
| - fPLSSetupProgram.fPosXformUniform,
|
| - fPLSSetupProgram.fArrayBuffer);
|
| + this->stampPLSSetupRect(SkRect::MakeXYWH(-100.0f, -100.0f, 0.01f, 0.01f));
|
| GL_CALL(Disable(GR_GL_SHADER_PIXEL_LOCAL_STORAGE));
|
| }
|
| }
|
| @@ -2843,18 +2812,26 @@ void GrGLGpu::onDraw(const GrPipeline& pipeline,
|
| #endif
|
| }
|
|
|
| -void GrGLGpu::stampRectUsingProgram(GrGLuint program, const SkRect& bounds, GrGLint posXformUniform,
|
| - GrGLuint arrayBuffer) {
|
| - GL_CALL(UseProgram(program));
|
| - this->fHWGeometryState.setVertexArrayID(this, 0);
|
| +void GrGLGpu::stampPLSSetupRect(const SkRect& bounds) {
|
| + SkASSERT(this->glCaps().glslCaps()->plsPathRenderingSupport())
|
|
|
| - GrGLAttribArrayState* attribs =
|
| - this->fHWGeometryState.bindArrayAndBufferToDraw(this, arrayBuffer);
|
| - attribs->set(this, 0, arrayBuffer, kVec2f_GrVertexAttribType, 2 * sizeof(GrGLfloat), 0);
|
| + if (!fPLSSetupProgram.fProgram) {
|
| + if (!this->createPLSSetupProgram()) {
|
| + SkDebugf("Failed to create PLS setup program.\n");
|
| + return;
|
| + }
|
| + }
|
| +
|
| + GL_CALL(UseProgram(fPLSSetupProgram.fProgram));
|
| + this->fHWVertexArrayState.setVertexArrayID(this, 0);
|
| +
|
| + GrGLAttribArrayState* attribs = this->fHWVertexArrayState.bindInternalVertexArray(this);
|
| + attribs->set(this, 0, fPLSSetupProgram.fArrayBuffer, kVec2f_GrVertexAttribType,
|
| + 2 * sizeof(GrGLfloat), 0);
|
| attribs->disableUnusedArrays(this, 0x1);
|
|
|
| - GL_CALL(Uniform4f(posXformUniform, bounds.width(), bounds.height(), bounds.left(),
|
| - bounds.top()));
|
| + GL_CALL(Uniform4f(fPLSSetupProgram.fPosXformUniform, bounds.width(), bounds.height(),
|
| + bounds.left(), bounds.top()));
|
|
|
| GrXferProcessor::BlendInfo blendInfo;
|
| blendInfo.reset();
|
| @@ -2891,8 +2868,7 @@ void GrGLGpu::setupPixelLocalStorage(const GrPipeline& pipeline,
|
| SkRect deviceBounds = SkRect::MakeXYWH(dx0, dy0, dx1 - dx0, dy1 - dy0);
|
|
|
| GL_CALL(Enable(GR_GL_FETCH_PER_SAMPLE_ARM));
|
| - this->stampRectUsingProgram(fPLSSetupProgram.fProgram, deviceBounds,
|
| - fPLSSetupProgram.fPosXformUniform, fPLSSetupProgram.fArrayBuffer);
|
| + this->stampPLSSetupRect(deviceBounds);
|
| }
|
|
|
| void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) {
|
| @@ -3564,8 +3540,9 @@ bool GrGLGpu::onCopySurface(GrSurface* dst,
|
| // Don't prefer copying as a draw if the dst doesn't already have a FBO object.
|
| bool preferCopy = SkToBool(dst->asRenderTarget());
|
| if (preferCopy && src->asTexture()) {
|
| - this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
|
| - return true;
|
| + if (this->copySurfaceAsDraw(dst, src, srcRect, dstPoint)) {
|
| + return true;
|
| + }
|
| }
|
|
|
| if (can_copy_texsubimage(dst, src, this)) {
|
| @@ -3578,151 +3555,173 @@ bool GrGLGpu::onCopySurface(GrSurface* dst,
|
| }
|
|
|
| if (!preferCopy && src->asTexture()) {
|
| - this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
|
| - return true;
|
| + if (this->copySurfaceAsDraw(dst, src, srcRect, dstPoint)) {
|
| + return true;
|
| + }
|
| }
|
|
|
| return false;
|
| }
|
|
|
| -void GrGLGpu::createCopyPrograms() {
|
| - for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
|
| - fCopyPrograms[i].fProgram = 0;
|
| - }
|
| +bool GrGLGpu::createCopyProgram(int progIdx) {
|
| const GrGLSLCaps* glslCaps = this->glCaps().glslCaps();
|
| - const char* version = glslCaps->versionDeclString();
|
| static const GrSLType kSamplerTypes[3] = { kSampler2D_GrSLType, kSamplerExternal_GrSLType,
|
| kSampler2DRect_GrSLType };
|
| - SkASSERT(3 == SK_ARRAY_COUNT(fCopyPrograms));
|
| - for (int i = 0; i < 3; ++i) {
|
| - if (kSamplerExternal_GrSLType == kSamplerTypes[i] &&
|
| - !this->glCaps().glslCaps()->externalTextureSupport()) {
|
| - continue;
|
| - }
|
| - if (kSampler2DRect_GrSLType == kSamplerTypes[i] &&
|
| - !this->glCaps().rectangleTextureSupport()) {
|
| - continue;
|
| - }
|
| - GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
|
| - GrGLSLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
|
| - GrShaderVar::kUniform_TypeModifier);
|
| - GrGLSLShaderVar uPosXform("u_posXform", kVec4f_GrSLType,
|
| - GrShaderVar::kUniform_TypeModifier);
|
| - GrGLSLShaderVar uTexture("u_texture", kSamplerTypes[i],
|
| + if (kSamplerExternal_GrSLType == kSamplerTypes[progIdx] &&
|
| + !this->glCaps().glslCaps()->externalTextureSupport()) {
|
| + return false;
|
| + }
|
| + if (kSampler2DRect_GrSLType == kSamplerTypes[progIdx] &&
|
| + !this->glCaps().rectangleTextureSupport()) {
|
| + return false;
|
| + }
|
| +
|
| + if (!fCopyProgramArrayBuffer) {
|
| + static const GrGLfloat vdata[] = {
|
| + 0, 0,
|
| + 0, 1,
|
| + 1, 0,
|
| + 1, 1
|
| + };
|
| + fCopyProgramArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata), kVertex_GrBufferType,
|
| + kStatic_GrAccessPattern, vdata));
|
| + }
|
| + if (!fCopyProgramArrayBuffer) {
|
| + return false;
|
| + }
|
| +
|
| + SkASSERT(!fCopyPrograms[progIdx].fProgram);
|
| + GL_CALL_RET(fCopyPrograms[progIdx].fProgram, CreateProgram());
|
| + if (!fCopyPrograms[progIdx].fProgram) {
|
| + return false;
|
| + }
|
| +
|
| + const char* version = glslCaps->versionDeclString();
|
| + GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
|
| + GrGLSLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
|
| GrShaderVar::kUniform_TypeModifier);
|
| - GrGLSLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType,
|
| - GrShaderVar::kVaryingOut_TypeModifier);
|
| - GrGLSLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType,
|
| - GrShaderVar::kOut_TypeModifier);
|
| -
|
| - SkString vshaderTxt(version);
|
| - if (glslCaps->noperspectiveInterpolationSupport()) {
|
| - if (const char* extension = glslCaps->noperspectiveInterpolationExtensionString()) {
|
| - vshaderTxt.appendf("#extension %s : require\n", extension);
|
| - }
|
| - vTexCoord.addModifier("noperspective");
|
| - }
|
| + GrGLSLShaderVar uPosXform("u_posXform", kVec4f_GrSLType,
|
| + GrShaderVar::kUniform_TypeModifier);
|
| + GrGLSLShaderVar uTexture("u_texture", kSamplerTypes[progIdx],
|
| + GrShaderVar::kUniform_TypeModifier);
|
| + GrGLSLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType,
|
| + GrShaderVar::kVaryingOut_TypeModifier);
|
| + GrGLSLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType,
|
| + GrShaderVar::kOut_TypeModifier);
|
|
|
| - aVertex.appendDecl(glslCaps, &vshaderTxt);
|
| - vshaderTxt.append(";");
|
| - uTexCoordXform.appendDecl(glslCaps, &vshaderTxt);
|
| - vshaderTxt.append(";");
|
| - uPosXform.appendDecl(glslCaps, &vshaderTxt);
|
| - vshaderTxt.append(";");
|
| - vTexCoord.appendDecl(glslCaps, &vshaderTxt);
|
| - vshaderTxt.append(";");
|
| -
|
| - vshaderTxt.append(
|
| - "// Copy Program VS\n"
|
| - "void main() {"
|
| - " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
|
| - " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
|
| - " gl_Position.zw = vec2(0, 1);"
|
| - "}"
|
| - );
|
| -
|
| - SkString fshaderTxt(version);
|
| - if (glslCaps->noperspectiveInterpolationSupport()) {
|
| - if (const char* extension = glslCaps->noperspectiveInterpolationExtensionString()) {
|
| - fshaderTxt.appendf("#extension %s : require\n", extension);
|
| - }
|
| + SkString vshaderTxt(version);
|
| + if (glslCaps->noperspectiveInterpolationSupport()) {
|
| + if (const char* extension = glslCaps->noperspectiveInterpolationExtensionString()) {
|
| + vshaderTxt.appendf("#extension %s : require\n", extension);
|
| }
|
| - if (kSamplerTypes[i] == kSamplerExternal_GrSLType) {
|
| - fshaderTxt.appendf("#extension %s : require\n",
|
| - glslCaps->externalTextureExtensionString());
|
| + vTexCoord.addModifier("noperspective");
|
| + }
|
| +
|
| + aVertex.appendDecl(glslCaps, &vshaderTxt);
|
| + vshaderTxt.append(";");
|
| + uTexCoordXform.appendDecl(glslCaps, &vshaderTxt);
|
| + vshaderTxt.append(";");
|
| + uPosXform.appendDecl(glslCaps, &vshaderTxt);
|
| + vshaderTxt.append(";");
|
| + vTexCoord.appendDecl(glslCaps, &vshaderTxt);
|
| + vshaderTxt.append(";");
|
| +
|
| + vshaderTxt.append(
|
| + "// Copy Program VS\n"
|
| + "void main() {"
|
| + " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
|
| + " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
|
| + " gl_Position.zw = vec2(0, 1);"
|
| + "}"
|
| + );
|
| +
|
| + SkString fshaderTxt(version);
|
| + if (glslCaps->noperspectiveInterpolationSupport()) {
|
| + if (const char* extension = glslCaps->noperspectiveInterpolationExtensionString()) {
|
| + fshaderTxt.appendf("#extension %s : require\n", extension);
|
| }
|
| - GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *glslCaps,
|
| - &fshaderTxt);
|
| - vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
|
| - vTexCoord.appendDecl(glslCaps, &fshaderTxt);
|
| - fshaderTxt.append(";");
|
| - uTexture.appendDecl(glslCaps, &fshaderTxt);
|
| + }
|
| + if (kSamplerTypes[progIdx] == kSamplerExternal_GrSLType) {
|
| + fshaderTxt.appendf("#extension %s : require\n",
|
| + glslCaps->externalTextureExtensionString());
|
| + }
|
| + GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *glslCaps,
|
| + &fshaderTxt);
|
| + vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
|
| + vTexCoord.appendDecl(glslCaps, &fshaderTxt);
|
| + fshaderTxt.append(";");
|
| + uTexture.appendDecl(glslCaps, &fshaderTxt);
|
| + fshaderTxt.append(";");
|
| + const char* fsOutName;
|
| + if (glslCaps->mustDeclareFragmentShaderOutput()) {
|
| + oFragColor.appendDecl(glslCaps, &fshaderTxt);
|
| fshaderTxt.append(";");
|
| - const char* fsOutName;
|
| - if (glslCaps->mustDeclareFragmentShaderOutput()) {
|
| - oFragColor.appendDecl(glslCaps, &fshaderTxt);
|
| - fshaderTxt.append(";");
|
| - fsOutName = oFragColor.c_str();
|
| - } else {
|
| - fsOutName = "gl_FragColor";
|
| - }
|
| - fshaderTxt.appendf(
|
| - "// Copy Program FS\n"
|
| - "void main() {"
|
| - " %s = %s(u_texture, v_texCoord);"
|
| - "}",
|
| - fsOutName,
|
| - GrGLSLTexture2DFunctionName(kVec2f_GrSLType, kSamplerTypes[i], this->glslGeneration())
|
| - );
|
| -
|
| - GL_CALL_RET(fCopyPrograms[i].fProgram, CreateProgram());
|
| - const char* str;
|
| - GrGLint length;
|
| -
|
| - str = vshaderTxt.c_str();
|
| - length = SkToInt(vshaderTxt.size());
|
| - GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[i].fProgram,
|
| - GR_GL_VERTEX_SHADER, &str, &length, 1,
|
| - &fStats);
|
| -
|
| - str = fshaderTxt.c_str();
|
| - length = SkToInt(fshaderTxt.size());
|
| - GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[i].fProgram,
|
| - GR_GL_FRAGMENT_SHADER, &str, &length, 1,
|
| - &fStats);
|
| -
|
| - GL_CALL(LinkProgram(fCopyPrograms[i].fProgram));
|
| -
|
| - GL_CALL_RET(fCopyPrograms[i].fTextureUniform,
|
| - GetUniformLocation(fCopyPrograms[i].fProgram, "u_texture"));
|
| - GL_CALL_RET(fCopyPrograms[i].fPosXformUniform,
|
| - GetUniformLocation(fCopyPrograms[i].fProgram, "u_posXform"));
|
| - GL_CALL_RET(fCopyPrograms[i].fTexCoordXformUniform,
|
| - GetUniformLocation(fCopyPrograms[i].fProgram, "u_texCoordXform"));
|
| -
|
| - GL_CALL(BindAttribLocation(fCopyPrograms[i].fProgram, 0, "a_vertex"));
|
| -
|
| - GL_CALL(DeleteShader(vshader));
|
| - GL_CALL(DeleteShader(fshader));
|
| - }
|
| - fCopyProgramArrayBuffer = 0;
|
| - GL_CALL(GenBuffers(1, &fCopyProgramArrayBuffer));
|
| - fHWGeometryState.setVertexBufferID(this, fCopyProgramArrayBuffer);
|
| - static const GrGLfloat vdata[] = {
|
| - 0, 0,
|
| - 0, 1,
|
| - 1, 0,
|
| - 1, 1
|
| - };
|
| - GL_ALLOC_CALL(this->glInterface(),
|
| - BufferData(GR_GL_ARRAY_BUFFER,
|
| - (GrGLsizeiptr) sizeof(vdata),
|
| - vdata, // data ptr
|
| - GR_GL_STATIC_DRAW));
|
| + fsOutName = oFragColor.c_str();
|
| + } else {
|
| + fsOutName = "gl_FragColor";
|
| + }
|
| + fshaderTxt.appendf(
|
| + "// Copy Program FS\n"
|
| + "void main() {"
|
| + " %s = %s(u_texture, v_texCoord);"
|
| + "}",
|
| + fsOutName,
|
| + GrGLSLTexture2DFunctionName(kVec2f_GrSLType, kSamplerTypes[progIdx], this->glslGeneration())
|
| + );
|
| +
|
| + const char* str;
|
| + GrGLint length;
|
| +
|
| + str = vshaderTxt.c_str();
|
| + length = SkToInt(vshaderTxt.size());
|
| + GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
|
| + GR_GL_VERTEX_SHADER, &str, &length, 1,
|
| + &fStats);
|
| +
|
| + str = fshaderTxt.c_str();
|
| + length = SkToInt(fshaderTxt.size());
|
| + GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
|
| + GR_GL_FRAGMENT_SHADER, &str, &length, 1,
|
| + &fStats);
|
| +
|
| + GL_CALL(LinkProgram(fCopyPrograms[progIdx].fProgram));
|
| +
|
| + GL_CALL_RET(fCopyPrograms[progIdx].fTextureUniform,
|
| + GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_texture"));
|
| + GL_CALL_RET(fCopyPrograms[progIdx].fPosXformUniform,
|
| + GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_posXform"));
|
| + GL_CALL_RET(fCopyPrograms[progIdx].fTexCoordXformUniform,
|
| + GetUniformLocation(fCopyPrograms[progIdx].fProgram, "u_texCoordXform"));
|
| +
|
| + GL_CALL(BindAttribLocation(fCopyPrograms[progIdx].fProgram, 0, "a_vertex"));
|
| +
|
| + GL_CALL(DeleteShader(vshader));
|
| + GL_CALL(DeleteShader(fshader));
|
| +
|
| + return true;
|
| }
|
|
|
| -void GrGLGpu::createWireRectProgram() {
|
| +bool GrGLGpu::createWireRectProgram() {
|
| + if (!fWireRectArrayBuffer) {
|
| + static const GrGLfloat vdata[] = {
|
| + 0, 0,
|
| + 0, 1,
|
| + 1, 1,
|
| + 1, 0
|
| + };
|
| + fWireRectArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata), kVertex_GrBufferType,
|
| + kStatic_GrAccessPattern, vdata));
|
| + if (!fWireRectArrayBuffer) {
|
| + return false;
|
| + }
|
| + }
|
| +
|
| SkASSERT(!fWireRectProgram.fProgram);
|
| + GL_CALL_RET(fWireRectProgram.fProgram, CreateProgram());
|
| + if (!fWireRectProgram.fProgram) {
|
| + return false;
|
| + }
|
| +
|
| GrGLSLShaderVar uColor("u_color", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
|
| GrGLSLShaderVar uRect("u_rect", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
|
| GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
|
| @@ -3770,7 +3769,6 @@ void GrGLGpu::createWireRectProgram() {
|
| uColor.c_str()
|
| );
|
|
|
| - GL_CALL_RET(fWireRectProgram.fProgram, CreateProgram());
|
| const char* str;
|
| GrGLint length;
|
|
|
| @@ -3796,19 +3794,8 @@ void GrGLGpu::createWireRectProgram() {
|
|
|
| GL_CALL(DeleteShader(vshader));
|
| GL_CALL(DeleteShader(fshader));
|
| - GL_CALL(GenBuffers(1, &fWireRectArrayBuffer));
|
| - fHWGeometryState.setVertexBufferID(this, fWireRectArrayBuffer);
|
| - static const GrGLfloat vdata[] = {
|
| - 0, 0,
|
| - 0, 1,
|
| - 1, 1,
|
| - 1, 0,
|
| - };
|
| - GL_ALLOC_CALL(this->glInterface(),
|
| - BufferData(GR_GL_ARRAY_BUFFER,
|
| - (GrGLsizeiptr) sizeof(vdata),
|
| - vdata, // data ptr
|
| - GR_GL_STATIC_DRAW));
|
| +
|
| + return true;
|
| }
|
|
|
| void GrGLGpu::drawDebugWireRect(GrRenderTarget* rt, const SkIRect& rect, GrColor color) {
|
| @@ -3817,7 +3804,10 @@ void GrGLGpu::drawDebugWireRect(GrRenderTarget* rt, const SkIRect& rect, GrColor
|
|
|
| this->handleDirtyContext();
|
| if (!fWireRectProgram.fProgram) {
|
| - this->createWireRectProgram();
|
| + if (!this->createWireRectProgram()) {
|
| + SkDebugf("Failed to create wire rect program.\n");
|
| + return;
|
| + }
|
| }
|
|
|
| int w = rt->width();
|
| @@ -3853,10 +3843,9 @@ void GrGLGpu::drawDebugWireRect(GrRenderTarget* rt, const SkIRect& rect, GrColor
|
| GL_CALL(UseProgram(fWireRectProgram.fProgram));
|
| fHWProgramID = fWireRectProgram.fProgram;
|
|
|
| - fHWGeometryState.setVertexArrayID(this, 0);
|
| + fHWVertexArrayState.setVertexArrayID(this, 0);
|
|
|
| - GrGLAttribArrayState* attribs =
|
| - fHWGeometryState.bindArrayAndBufferToDraw(this, fWireRectArrayBuffer);
|
| + GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
|
| attribs->set(this, 0, fWireRectArrayBuffer, kVec2f_GrVertexAttribType, 2 * sizeof(GrGLfloat),
|
| 0);
|
| attribs->disableUnusedArrays(this, 0x1);
|
| @@ -3879,14 +3868,23 @@ void GrGLGpu::drawDebugWireRect(GrRenderTarget* rt, const SkIRect& rect, GrColor
|
| }
|
|
|
|
|
| -void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
|
| +bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
|
| GrSurface* src,
|
| const SkIRect& srcRect,
|
| const SkIPoint& dstPoint) {
|
| + GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture());
|
| + int progIdx = TextureTargetToCopyProgramIdx(srcTex->target());
|
| +
|
| + if (!fCopyPrograms[progIdx].fProgram) {
|
| + if (!this->createCopyProgram(progIdx)) {
|
| + SkDebugf("Failed to create copy program.\n");
|
| + return false;
|
| + }
|
| + }
|
| +
|
| int w = srcRect.width();
|
| int h = srcRect.height();
|
|
|
| - GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture());
|
| GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
|
| this->bindTexture(0, params, true, srcTex);
|
|
|
| @@ -3897,15 +3895,12 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
|
|
|
| SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h);
|
|
|
| - int progIdx = TextureTargetToCopyProgramIdx(srcTex->target());
|
| -
|
| GL_CALL(UseProgram(fCopyPrograms[progIdx].fProgram));
|
| fHWProgramID = fCopyPrograms[progIdx].fProgram;
|
|
|
| - fHWGeometryState.setVertexArrayID(this, 0);
|
| + fHWVertexArrayState.setVertexArrayID(this, 0);
|
|
|
| - GrGLAttribArrayState* attribs =
|
| - fHWGeometryState.bindArrayAndBufferToDraw(this, fCopyProgramArrayBuffer);
|
| + GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
|
| attribs->set(this, 0, fCopyProgramArrayBuffer, kVec2f_GrVertexAttribType, 2 * sizeof(GrGLfloat),
|
| 0);
|
| attribs->disableUnusedArrays(this, 0x1);
|
| @@ -3961,6 +3956,7 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
|
| this->unbindTextureFBOForCopy(GR_GL_FRAMEBUFFER, dst);
|
| this->didWriteToSurface(dst, &dstRect);
|
|
|
| + return true;
|
| }
|
|
|
| void GrGLGpu::copySurfaceAsCopyTexSubImage(GrSurface* dst,
|
| @@ -4198,52 +4194,27 @@ void GrGLGpu::resetShaderCacheForTesting() const {
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| -GrGLAttribArrayState* GrGLGpu::HWGeometryState::bindArrayAndBuffersToDraw(
|
| - GrGLGpu* gpu,
|
| - const GrGLBuffer* vbuffer,
|
| - const GrGLBuffer* ibuffer) {
|
| - SkASSERT(vbuffer);
|
| - GrGLuint vbufferID = vbuffer->bufferID();
|
| - GrGLuint* ibufferIDPtr = nullptr;
|
| - GrGLuint ibufferID;
|
| - if (ibuffer) {
|
| - ibufferID = ibuffer->bufferID();
|
| - ibufferIDPtr = &ibufferID;
|
| - }
|
| - return this->internalBind(gpu, vbufferID, ibufferIDPtr);
|
| -}
|
| -
|
| -GrGLAttribArrayState* GrGLGpu::HWGeometryState::bindArrayAndBufferToDraw(GrGLGpu* gpu,
|
| - GrGLuint vbufferID) {
|
| - return this->internalBind(gpu, vbufferID, nullptr);
|
| -}
|
| -
|
| -GrGLAttribArrayState* GrGLGpu::HWGeometryState::bindArrayAndBuffersToDraw(GrGLGpu* gpu,
|
| - GrGLuint vbufferID,
|
| - GrGLuint ibufferID) {
|
| - return this->internalBind(gpu, vbufferID, &ibufferID);
|
| -}
|
|
|
| -GrGLAttribArrayState* GrGLGpu::HWGeometryState::internalBind(GrGLGpu* gpu,
|
| - GrGLuint vbufferID,
|
| - GrGLuint* ibufferID) {
|
| +GrGLAttribArrayState* GrGLGpu::HWVertexArrayState::bindInternalVertexArray(GrGLGpu* gpu,
|
| + const GrGLBuffer* ibuf) {
|
| GrGLAttribArrayState* attribState;
|
|
|
| - if (gpu->glCaps().isCoreProfile() && 0 != vbufferID) {
|
| - if (!fVBOVertexArray) {
|
| + if (gpu->glCaps().isCoreProfile()) {
|
| + if (!fCoreProfileVertexArray) {
|
| GrGLuint arrayID;
|
| GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID));
|
| int attrCount = gpu->glCaps().maxVertexAttributes();
|
| - fVBOVertexArray = new GrGLVertexArray(arrayID, attrCount);
|
| + fCoreProfileVertexArray = new GrGLVertexArray(arrayID, attrCount);
|
| }
|
| - if (ibufferID) {
|
| - attribState = fVBOVertexArray->bindWithIndexBuffer(gpu, *ibufferID);
|
| + if (ibuf) {
|
| + attribState = fCoreProfileVertexArray->bindWithIndexBuffer(gpu, ibuf);
|
| } else {
|
| - attribState = fVBOVertexArray->bind(gpu);
|
| + attribState = fCoreProfileVertexArray->bind(gpu);
|
| }
|
| } else {
|
| - if (ibufferID) {
|
| - this->setIndexBufferIDOnDefaultVertexArray(gpu, *ibufferID);
|
| + if (ibuf) {
|
| + // bindBuffer implicitly binds VAO 0 when binding an index buffer.
|
| + gpu->bindBuffer(kIndex_GrBufferType, ibuf);
|
| } else {
|
| this->setVertexArrayID(gpu, 0);
|
| }
|
|
|