11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrGLVertexBuffer.h"
121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrGpuGL.h"
131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define GPUGL static_cast<GrGpuGL*>(getGpu())
151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
181cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrGLVertexBuffer::GrGLVertexBuffer(GrGpuGL* gpu,
191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   GrGLuint id,
201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   size_t sizeInBytes,
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   bool dynamic)
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    : INHERITED(gpu, sizeInBytes, dynamic)
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fBufferID(id)
241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    , fLockPtr(NULL) {
251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid GrGLVertexBuffer::onRelease() {
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // make sure we've not been abandoned
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fBufferID) {
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GPUGL->notifyVertexBufferDelete(this);
311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GL_CALL(DeleteBuffers(1, &fBufferID));
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fBufferID = 0;
331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid GrGLVertexBuffer::onAbandon() {
371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fBufferID = 0;
381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fLockPtr = NULL;
391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid GrGLVertexBuffer::bind() const {
421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, fBufferID));
431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GPUGL->notifyVertexBufferBind(this);
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
461cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrGLuint GrGLVertexBuffer::bufferID() const {
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return fBufferID;
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid* GrGLVertexBuffer::lock() {
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(fBufferID);
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(!isLocked());
531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (this->getGpu()->getCaps().fBufferLockSupport) {
541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        this->bind();
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // Let driver know it can discard the old data
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, this->sizeInBytes(), NULL,
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           this->dynamic() ? GR_GL_DYNAMIC_DRAW :
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                             GR_GL_STATIC_DRAW));
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GR_GL_CALL_RET(GPUGL->glInterface(),
601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       fLockPtr,
611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                       MapBuffer(GR_GL_ARRAY_BUFFER, GR_GL_WRITE_ONLY));
621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return fLockPtr;
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return NULL;
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid* GrGLVertexBuffer::lockPtr() const {
681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return fLockPtr;
691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid GrGLVertexBuffer::unlock() {
721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(fBufferID);
741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(isLocked());
751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(this->getGpu()->getCaps().fBufferLockSupport);
761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->bind();
781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GL_CALL(UnmapBuffer(GR_GL_ARRAY_BUFFER));
791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fLockPtr = NULL;
801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool GrGLVertexBuffer::isLocked() const {
831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(!this->isValid() || fBufferID);
841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if GR_DEBUG
851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) {
861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrGLint mapped;
871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        this->bind();
881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GL_CALL(GetBufferParameteriv(GR_GL_ARRAY_BUFFER,
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                     GR_GL_BUFFER_MAPPED, &mapped));
901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrAssert(!!mapped == !!fLockPtr);
911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return NULL != fLockPtr;
941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool GrGLVertexBuffer::updateData(const void* src, size_t srcSizeInBytes) {
971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(fBufferID);
981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrAssert(!isLocked());
991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (srcSizeInBytes > this->sizeInBytes()) {
1001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->bind();
1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW;
1044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
1054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#if GR_GL_USE_BUFFER_DATA_NULL_HINT
1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (this->sizeInBytes() == srcSizeInBytes) {
1071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, srcSizeInBytes, src, usage));
1081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // Before we call glBufferSubData we give the driver a hint using
1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // glBufferData with NULL. This makes the old buffer contents
1114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // inaccessible to future draws. The GPU may still be processing
1124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // draws that reference the old contents. With this hint it can
1134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // assign a different allocation for the new contents to avoid
1144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // flushing the gpu past draws consuming the old contents.
1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GL_CALL(BufferData(GR_GL_ARRAY_BUFFER,
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           this->sizeInBytes(), NULL, usage));
1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GL_CALL(BufferSubData(GR_GL_ARRAY_BUFFER, 0, srcSizeInBytes, src));
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
1194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
1204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // Note that we're cheating on the size here. Currently no methods
1214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // allow a partial update that preserves contents of non-updated
1224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // portions of the buffer (lock() does a glBufferData(..size, NULL..))
1234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool doSubData = false;
1244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#if GR_GL_MAC_BUFFER_OBJECT_PERFOMANCE_WORKAROUND
1254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    static int N = 0;
1264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // 128 was chosen experimentally. At 256 a slight hitchiness was noticed
1274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // when dragging a Chromium window around with a canvas tab backgrounded.
1284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    doSubData = 0 == (N % 128);
1294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    ++N;
1304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
1314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (doSubData) {
1324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // The workaround is to do a glBufferData followed by glBufferSubData.
1334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // Chromium's command buffer may turn a glBufferSubData where the size
1344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // exactly matches the buffer size into a glBufferData. So we tack 1
1354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // extra byte onto the glBufferData.
1364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, srcSizeInBytes + 1,
1374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                           NULL, usage));
1384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(BufferSubData(GR_GL_ARRAY_BUFFER, 0, srcSizeInBytes, src));
1394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    } else {
1404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, srcSizeInBytes, src, usage));
1414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
146