1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLBuffer.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkTraceMemoryDump.h" 11cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourcePriv.h" 13cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLCaps.h" 14cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLGpu.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X) 17cb93a386Sopenharmony_ci#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), RET, X) 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#define GL_ALLOC_CALL(call) \ 20cb93a386Sopenharmony_ci [&] { \ 21cb93a386Sopenharmony_ci if (this->glGpu()->glCaps().skipErrorChecks()) { \ 22cb93a386Sopenharmony_ci GR_GL_CALL(this->glGpu()->glInterface(), call); \ 23cb93a386Sopenharmony_ci return static_cast<GrGLenum>(GR_GL_NO_ERROR); \ 24cb93a386Sopenharmony_ci } else { \ 25cb93a386Sopenharmony_ci this->glGpu()->clearErrorsAndCheckForOOM(); \ 26cb93a386Sopenharmony_ci GR_GL_CALL_NOERRCHECK(this->glGpu()->glInterface(), call); \ 27cb93a386Sopenharmony_ci return this->glGpu()->getErrorAndCheckForOOM(); \ 28cb93a386Sopenharmony_ci } \ 29cb93a386Sopenharmony_ci }() 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci#ifdef SK_DEBUG 32cb93a386Sopenharmony_ci#define VALIDATE() this->validate() 33cb93a386Sopenharmony_ci#else 34cb93a386Sopenharmony_ci#define VALIDATE() do {} while(false) 35cb93a386Sopenharmony_ci#endif 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_cisk_sp<GrGLBuffer> GrGLBuffer::Make(GrGLGpu* gpu, size_t size, GrGpuBufferType intendedType, 38cb93a386Sopenharmony_ci GrAccessPattern accessPattern, const void* data) { 39cb93a386Sopenharmony_ci if (gpu->glCaps().transferBufferType() == GrGLCaps::TransferBufferType::kNone && 40cb93a386Sopenharmony_ci (GrGpuBufferType::kXferCpuToGpu == intendedType || 41cb93a386Sopenharmony_ci GrGpuBufferType::kXferGpuToCpu == intendedType)) { 42cb93a386Sopenharmony_ci return nullptr; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci sk_sp<GrGLBuffer> buffer(new GrGLBuffer(gpu, size, intendedType, accessPattern, data)); 46cb93a386Sopenharmony_ci if (0 == buffer->bufferID()) { 47cb93a386Sopenharmony_ci return nullptr; 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci return buffer; 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci// GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a client's vertex buffer 53cb93a386Sopenharmony_ci// objects are implemented as client-side-arrays on tile-deferred architectures. 54cb93a386Sopenharmony_ci#define DYNAMIC_DRAW_PARAM GR_GL_STREAM_DRAW 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ciinline static GrGLenum gr_to_gl_access_pattern(GrGpuBufferType bufferType, 57cb93a386Sopenharmony_ci GrAccessPattern accessPattern, 58cb93a386Sopenharmony_ci const GrGLCaps& caps) { 59cb93a386Sopenharmony_ci auto drawUsage = [](GrAccessPattern pattern) { 60cb93a386Sopenharmony_ci switch (pattern) { 61cb93a386Sopenharmony_ci case kDynamic_GrAccessPattern: 62cb93a386Sopenharmony_ci // TODO: Do we really want to use STREAM_DRAW here on non-Chromium? 63cb93a386Sopenharmony_ci return DYNAMIC_DRAW_PARAM; 64cb93a386Sopenharmony_ci case kStatic_GrAccessPattern: 65cb93a386Sopenharmony_ci return GR_GL_STATIC_DRAW; 66cb93a386Sopenharmony_ci case kStream_GrAccessPattern: 67cb93a386Sopenharmony_ci return GR_GL_STREAM_DRAW; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci SkUNREACHABLE; 70cb93a386Sopenharmony_ci }; 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci auto readUsage = [](GrAccessPattern pattern) { 73cb93a386Sopenharmony_ci switch (pattern) { 74cb93a386Sopenharmony_ci case kDynamic_GrAccessPattern: 75cb93a386Sopenharmony_ci return GR_GL_DYNAMIC_READ; 76cb93a386Sopenharmony_ci case kStatic_GrAccessPattern: 77cb93a386Sopenharmony_ci return GR_GL_STATIC_READ; 78cb93a386Sopenharmony_ci case kStream_GrAccessPattern: 79cb93a386Sopenharmony_ci return GR_GL_STREAM_READ; 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci SkUNREACHABLE; 82cb93a386Sopenharmony_ci }; 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci auto usageType = [&drawUsage, &readUsage, &caps](GrGpuBufferType type, 85cb93a386Sopenharmony_ci GrAccessPattern pattern) { 86cb93a386Sopenharmony_ci // GL_NV_pixel_buffer_object adds transfer buffers but not the related <usage> values. 87cb93a386Sopenharmony_ci if (caps.transferBufferType() == GrGLCaps::TransferBufferType::kNV_PBO) { 88cb93a386Sopenharmony_ci return drawUsage(pattern); 89cb93a386Sopenharmony_ci } 90cb93a386Sopenharmony_ci switch (type) { 91cb93a386Sopenharmony_ci case GrGpuBufferType::kVertex: 92cb93a386Sopenharmony_ci case GrGpuBufferType::kIndex: 93cb93a386Sopenharmony_ci case GrGpuBufferType::kDrawIndirect: 94cb93a386Sopenharmony_ci case GrGpuBufferType::kXferCpuToGpu: 95cb93a386Sopenharmony_ci case GrGpuBufferType::kUniform: 96cb93a386Sopenharmony_ci return drawUsage(pattern); 97cb93a386Sopenharmony_ci case GrGpuBufferType::kXferGpuToCpu: 98cb93a386Sopenharmony_ci return readUsage(pattern); 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci SkUNREACHABLE; 101cb93a386Sopenharmony_ci }; 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci return usageType(bufferType, accessPattern); 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ciGrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrGpuBufferType intendedType, 107cb93a386Sopenharmony_ci GrAccessPattern accessPattern, const void* data) 108cb93a386Sopenharmony_ci : INHERITED(gpu, size, intendedType, accessPattern) 109cb93a386Sopenharmony_ci , fIntendedType(intendedType) 110cb93a386Sopenharmony_ci , fBufferID(0) 111cb93a386Sopenharmony_ci , fUsage(gr_to_gl_access_pattern(intendedType, accessPattern, gpu->glCaps())) 112cb93a386Sopenharmony_ci , fGLSizeInBytes(0) 113cb93a386Sopenharmony_ci , fHasAttachedToTexture(false) { 114cb93a386Sopenharmony_ci GL_CALL(GenBuffers(1, &fBufferID)); 115cb93a386Sopenharmony_ci if (fBufferID) { 116cb93a386Sopenharmony_ci GrGLenum target = gpu->bindBuffer(fIntendedType, this); 117cb93a386Sopenharmony_ci GrGLenum error = GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)size, data, fUsage)); 118cb93a386Sopenharmony_ci if (error != GR_GL_NO_ERROR) { 119cb93a386Sopenharmony_ci GL_CALL(DeleteBuffers(1, &fBufferID)); 120cb93a386Sopenharmony_ci fBufferID = 0; 121cb93a386Sopenharmony_ci } else { 122cb93a386Sopenharmony_ci fGLSizeInBytes = size; 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci VALIDATE(); 126cb93a386Sopenharmony_ci this->registerWithCache(SkBudgeted::kYes); 127cb93a386Sopenharmony_ci if (!fBufferID) { 128cb93a386Sopenharmony_ci this->resourcePriv().removeScratchKey(); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci} 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ciinline GrGLGpu* GrGLBuffer::glGpu() const { 133cb93a386Sopenharmony_ci SkASSERT(!this->wasDestroyed()); 134cb93a386Sopenharmony_ci return static_cast<GrGLGpu*>(this->getGpu()); 135cb93a386Sopenharmony_ci} 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ciinline const GrGLCaps& GrGLBuffer::glCaps() const { 138cb93a386Sopenharmony_ci return this->glGpu()->glCaps(); 139cb93a386Sopenharmony_ci} 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_civoid GrGLBuffer::onRelease() { 142cb93a386Sopenharmony_ci TRACE_EVENT0("skia.gpu", TRACE_FUNC); 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci if (!this->wasDestroyed()) { 145cb93a386Sopenharmony_ci VALIDATE(); 146cb93a386Sopenharmony_ci // make sure we've not been abandoned or already released 147cb93a386Sopenharmony_ci if (fBufferID) { 148cb93a386Sopenharmony_ci GL_CALL(DeleteBuffers(1, &fBufferID)); 149cb93a386Sopenharmony_ci fBufferID = 0; 150cb93a386Sopenharmony_ci fGLSizeInBytes = 0; 151cb93a386Sopenharmony_ci } 152cb93a386Sopenharmony_ci fMapPtr = nullptr; 153cb93a386Sopenharmony_ci VALIDATE(); 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci INHERITED::onRelease(); 157cb93a386Sopenharmony_ci} 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_civoid GrGLBuffer::onAbandon() { 160cb93a386Sopenharmony_ci fBufferID = 0; 161cb93a386Sopenharmony_ci fGLSizeInBytes = 0; 162cb93a386Sopenharmony_ci fMapPtr = nullptr; 163cb93a386Sopenharmony_ci VALIDATE(); 164cb93a386Sopenharmony_ci INHERITED::onAbandon(); 165cb93a386Sopenharmony_ci} 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_civoid GrGLBuffer::onMap() { 168cb93a386Sopenharmony_ci SkASSERT(fBufferID); 169cb93a386Sopenharmony_ci SkASSERT(!this->wasDestroyed()); 170cb93a386Sopenharmony_ci VALIDATE(); 171cb93a386Sopenharmony_ci SkASSERT(!this->isMapped()); 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci // TODO: Make this a function parameter. 174cb93a386Sopenharmony_ci bool readOnly = (GrGpuBufferType::kXferGpuToCpu == fIntendedType); 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci // Handling dirty context is done in the bindBuffer call 177cb93a386Sopenharmony_ci switch (this->glCaps().mapBufferType()) { 178cb93a386Sopenharmony_ci case GrGLCaps::kNone_MapBufferType: 179cb93a386Sopenharmony_ci return; 180cb93a386Sopenharmony_ci case GrGLCaps::kMapBuffer_MapBufferType: { 181cb93a386Sopenharmony_ci GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this); 182cb93a386Sopenharmony_ci if (!readOnly) { 183cb93a386Sopenharmony_ci // Let driver know it can discard the old data 184cb93a386Sopenharmony_ci if (this->glCaps().useBufferDataNullHint() || fGLSizeInBytes != this->size()) { 185cb93a386Sopenharmony_ci GrGLenum error = 186cb93a386Sopenharmony_ci GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage)); 187cb93a386Sopenharmony_ci if (error != GR_GL_NO_ERROR) { 188cb93a386Sopenharmony_ci return; 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci GL_CALL_RET(fMapPtr, MapBuffer(target, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); 193cb93a386Sopenharmony_ci break; 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci case GrGLCaps::kMapBufferRange_MapBufferType: { 196cb93a386Sopenharmony_ci GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this); 197cb93a386Sopenharmony_ci // Make sure the GL buffer size agrees with fDesc before mapping. 198cb93a386Sopenharmony_ci if (fGLSizeInBytes != this->size()) { 199cb93a386Sopenharmony_ci GrGLenum error = GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage)); 200cb93a386Sopenharmony_ci if (error != GR_GL_NO_ERROR) { 201cb93a386Sopenharmony_ci return; 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci } 204cb93a386Sopenharmony_ci GrGLbitfield access; 205cb93a386Sopenharmony_ci if (readOnly) { 206cb93a386Sopenharmony_ci access = GR_GL_MAP_READ_BIT; 207cb93a386Sopenharmony_ci } else { 208cb93a386Sopenharmony_ci access = GR_GL_MAP_WRITE_BIT; 209cb93a386Sopenharmony_ci if (GrGpuBufferType::kXferCpuToGpu != fIntendedType) { 210cb93a386Sopenharmony_ci // TODO: Make this a function parameter. 211cb93a386Sopenharmony_ci access |= GR_GL_MAP_INVALIDATE_BUFFER_BIT; 212cb93a386Sopenharmony_ci } 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci GL_CALL_RET(fMapPtr, MapBufferRange(target, 0, this->size(), access)); 215cb93a386Sopenharmony_ci break; 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci case GrGLCaps::kChromium_MapBufferType: { 218cb93a386Sopenharmony_ci GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this); 219cb93a386Sopenharmony_ci // Make sure the GL buffer size agrees with fDesc before mapping. 220cb93a386Sopenharmony_ci if (fGLSizeInBytes != this->size()) { 221cb93a386Sopenharmony_ci GrGLenum error = GL_ALLOC_CALL(BufferData(target, this->size(), nullptr, fUsage)); 222cb93a386Sopenharmony_ci if (error != GR_GL_NO_ERROR) { 223cb93a386Sopenharmony_ci return; 224cb93a386Sopenharmony_ci } 225cb93a386Sopenharmony_ci } 226cb93a386Sopenharmony_ci GL_CALL_RET(fMapPtr, MapBufferSubData(target, 0, this->size(), 227cb93a386Sopenharmony_ci readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); 228cb93a386Sopenharmony_ci break; 229cb93a386Sopenharmony_ci } 230cb93a386Sopenharmony_ci } 231cb93a386Sopenharmony_ci fGLSizeInBytes = this->size(); 232cb93a386Sopenharmony_ci VALIDATE(); 233cb93a386Sopenharmony_ci} 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_civoid GrGLBuffer::onUnmap() { 236cb93a386Sopenharmony_ci SkASSERT(fBufferID); 237cb93a386Sopenharmony_ci VALIDATE(); 238cb93a386Sopenharmony_ci SkASSERT(this->isMapped()); 239cb93a386Sopenharmony_ci if (0 == fBufferID) { 240cb93a386Sopenharmony_ci fMapPtr = nullptr; 241cb93a386Sopenharmony_ci return; 242cb93a386Sopenharmony_ci } 243cb93a386Sopenharmony_ci // bind buffer handles the dirty context 244cb93a386Sopenharmony_ci switch (this->glCaps().mapBufferType()) { 245cb93a386Sopenharmony_ci case GrGLCaps::kNone_MapBufferType: 246cb93a386Sopenharmony_ci SkDEBUGFAIL("Shouldn't get here."); 247cb93a386Sopenharmony_ci return; 248cb93a386Sopenharmony_ci case GrGLCaps::kMapBuffer_MapBufferType: // fall through 249cb93a386Sopenharmony_ci case GrGLCaps::kMapBufferRange_MapBufferType: { 250cb93a386Sopenharmony_ci GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this); 251cb93a386Sopenharmony_ci GL_CALL(UnmapBuffer(target)); 252cb93a386Sopenharmony_ci break; 253cb93a386Sopenharmony_ci } 254cb93a386Sopenharmony_ci case GrGLCaps::kChromium_MapBufferType: 255cb93a386Sopenharmony_ci this->glGpu()->bindBuffer(fIntendedType, this); // TODO: Is this needed? 256cb93a386Sopenharmony_ci GL_CALL(UnmapBufferSubData(fMapPtr)); 257cb93a386Sopenharmony_ci break; 258cb93a386Sopenharmony_ci } 259cb93a386Sopenharmony_ci fMapPtr = nullptr; 260cb93a386Sopenharmony_ci} 261cb93a386Sopenharmony_ci 262cb93a386Sopenharmony_cibool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { 263cb93a386Sopenharmony_ci SkASSERT(fBufferID); 264cb93a386Sopenharmony_ci if (this->wasDestroyed()) { 265cb93a386Sopenharmony_ci return false; 266cb93a386Sopenharmony_ci } 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ci SkASSERT(!this->isMapped()); 269cb93a386Sopenharmony_ci VALIDATE(); 270cb93a386Sopenharmony_ci if (srcSizeInBytes > this->size()) { 271cb93a386Sopenharmony_ci return false; 272cb93a386Sopenharmony_ci } 273cb93a386Sopenharmony_ci SkASSERT(srcSizeInBytes <= this->size()); 274cb93a386Sopenharmony_ci // bindbuffer handles dirty context 275cb93a386Sopenharmony_ci GrGLenum target = this->glGpu()->bindBuffer(fIntendedType, this); 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci if (this->glCaps().useBufferDataNullHint()) { 278cb93a386Sopenharmony_ci if (this->size() == srcSizeInBytes) { 279cb93a386Sopenharmony_ci GrGLenum error = 280cb93a386Sopenharmony_ci GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)srcSizeInBytes, src, fUsage)); 281cb93a386Sopenharmony_ci if (error != GR_GL_NO_ERROR) { 282cb93a386Sopenharmony_ci return false; 283cb93a386Sopenharmony_ci } 284cb93a386Sopenharmony_ci } else { 285cb93a386Sopenharmony_ci // Before we call glBufferSubData we give the driver a hint using 286cb93a386Sopenharmony_ci // glBufferData with nullptr. This makes the old buffer contents 287cb93a386Sopenharmony_ci // inaccessible to future draws. The GPU may still be processing 288cb93a386Sopenharmony_ci // draws that reference the old contents. With this hint it can 289cb93a386Sopenharmony_ci // assign a different allocation for the new contents to avoid 290cb93a386Sopenharmony_ci // flushing the gpu past draws consuming the old contents. 291cb93a386Sopenharmony_ci // TODO I think we actually want to try calling bufferData here 292cb93a386Sopenharmony_ci GrGLenum error = 293cb93a386Sopenharmony_ci GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)this->size(), nullptr, fUsage)); 294cb93a386Sopenharmony_ci if (error != GR_GL_NO_ERROR) { 295cb93a386Sopenharmony_ci return false; 296cb93a386Sopenharmony_ci } 297cb93a386Sopenharmony_ci GL_CALL(BufferSubData(target, 0, (GrGLsizeiptr) srcSizeInBytes, src)); 298cb93a386Sopenharmony_ci } 299cb93a386Sopenharmony_ci fGLSizeInBytes = this->size(); 300cb93a386Sopenharmony_ci } else { 301cb93a386Sopenharmony_ci // Note that we're cheating on the size here. Currently no methods 302cb93a386Sopenharmony_ci // allow a partial update that preserves contents of non-updated 303cb93a386Sopenharmony_ci // portions of the buffer (map() does a glBufferData(..size, nullptr..)) 304cb93a386Sopenharmony_ci GrGLenum error = 305cb93a386Sopenharmony_ci GL_ALLOC_CALL(BufferData(target, (GrGLsizeiptr)srcSizeInBytes, src, fUsage)); 306cb93a386Sopenharmony_ci if (error != GR_GL_NO_ERROR) { 307cb93a386Sopenharmony_ci return false; 308cb93a386Sopenharmony_ci } 309cb93a386Sopenharmony_ci fGLSizeInBytes = srcSizeInBytes; 310cb93a386Sopenharmony_ci } 311cb93a386Sopenharmony_ci VALIDATE(); 312cb93a386Sopenharmony_ci return true; 313cb93a386Sopenharmony_ci} 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_civoid GrGLBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, 316cb93a386Sopenharmony_ci const SkString& dumpName) const { 317cb93a386Sopenharmony_ci SkString buffer_id; 318cb93a386Sopenharmony_ci buffer_id.appendU32(this->bufferID()); 319cb93a386Sopenharmony_ci traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", 320cb93a386Sopenharmony_ci buffer_id.c_str()); 321cb93a386Sopenharmony_ci} 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ci#ifdef SK_DEBUG 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_civoid GrGLBuffer::validate() const { 326cb93a386Sopenharmony_ci SkASSERT(0 != fBufferID || 0 == fGLSizeInBytes); 327cb93a386Sopenharmony_ci SkASSERT(nullptr == fMapPtr || fGLSizeInBytes <= this->size()); 328cb93a386Sopenharmony_ci} 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_ci#endif 331