LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/gl - GrGLBuffer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 121 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13