180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGLIndexBuffer.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGpuGL.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GPUGL static_cast<GrGpuGL*>(getGpu())
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrGLIndexBuffer::GrGLIndexBuffer(GrGpuGL* gpu,
18d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                 bool isWrapped,
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 GrGLuint id,
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 size_t sizeInBytes,
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 bool dynamic)
22d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    : INHERITED(gpu, isWrapped, sizeInBytes, dynamic)
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fBufferID(id)
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fLockPtr(NULL) {
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLIndexBuffer::onRelease() {
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // make sure we've not been abandoned
30d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (fBufferID && !this->isWrapped()) {
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GPUGL->notifyIndexBufferDelete(this);
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GL_CALL(DeleteBuffers(1, &fBufferID));
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fBufferID = 0;
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    INHERITED::onRelease();
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLIndexBuffer::onAbandon() {
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fBufferID = 0;
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fLockPtr = NULL;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    INHERITED::onAbandon();
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLIndexBuffer::bind() const {
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, fBufferID));
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GPUGL->notifyIndexBufferBind(this);
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrGLuint GrGLIndexBuffer::bufferID() const {
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fBufferID;
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid* GrGLIndexBuffer::lock() {
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fBufferID);
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(!isLocked());
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->getGpu()->getCaps().bufferLockSupport()) {
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->bind();
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Let driver know it can discard the old data
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           this->sizeInBytes(),
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           NULL,
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           this->dynamic() ? GR_GL_DYNAMIC_DRAW :
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                             GR_GL_STATIC_DRAW));
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GR_GL_CALL_RET(GPUGL->glInterface(),
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       fLockPtr,
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       MapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 GR_GL_WRITE_ONLY));
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return fLockPtr;
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL;
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid* GrGLIndexBuffer::lockPtr() const {
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fLockPtr;
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLIndexBuffer::unlock() {
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fBufferID);
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(isLocked());
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(this->getGpu()->getCaps().bufferLockSupport());
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->bind();
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GL_CALL(UnmapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER));
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fLockPtr = NULL;
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrGLIndexBuffer::isLocked() const {
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this check causes a lot of noise in the gl log
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->isValid() && this->getGpu()->getCaps().fBufferLockSupport) {
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->bind();
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrGLint mapped;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GL_CALL(GetBufferParameteriv(GR_GL_ELEMENT_ARRAY_BUFFER,
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     GR_GL_BUFFER_MAPPED, &mapped));
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(!!mapped == !!fLockPtr);
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL != fLockPtr;
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrGLIndexBuffer::updateData(const void* src, size_t srcSizeInBytes) {
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(fBufferID);
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(!isLocked());
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (srcSizeInBytes > this->sizeInBytes()) {
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->bind();
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrGLenum usage = dynamic() ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW;
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_GL_USE_BUFFER_DATA_NULL_HINT
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->sizeInBytes() == srcSizeInBytes) {
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            srcSizeInBytes, src, usage));
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Before we call glBufferSubData we give the driver a hint using
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // glBufferData with NULL. This makes the old buffer contents
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // inaccessible to future draws. The GPU may still be processing
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // draws that reference the old contents. With this hint it can
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // assign a different allocation for the new contents to avoid
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // flushing the gpu past draws consuming the old contents.
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           this->sizeInBytes(), NULL, usage));
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GL_CALL(BufferSubData(GR_GL_ELEMENT_ARRAY_BUFFER,
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              0, srcSizeInBytes, src));
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Note that we're cheating on the size here. Currently no methods
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // allow a partial update that preserves contents of non-updated
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // portions of the buffer (lock() does a glBufferData(..size, NULL..))
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GL_CALL(BufferData(GR_GL_ELEMENT_ARRAY_BUFFER,
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       srcSizeInBytes, src, usage));
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
138