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