Home | History | Annotate | Download | only in gpu
      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 #ifndef GrBuffer_DEFINED
      9 #define GrBuffer_DEFINED
     10 
     11 #include "GrGpuResource.h"
     12 
     13 class GrGpu;
     14 
     15 class GrBuffer : public GrGpuResource {
     16 public:
     17     /**
     18      * Creates a client-side buffer.
     19      */
     20     static SK_WARN_UNUSED_RESULT GrBuffer* CreateCPUBacked(GrGpu*, size_t sizeInBytes, GrBufferType,
     21                                                            const void* data = nullptr);
     22 
     23     /**
     24      * Computes a scratch key for a GPU-side buffer with a "dynamic" access pattern. (Buffers with
     25      * "static" and "stream" patterns are disqualified by nature from being cached and reused.)
     26      */
     27     static void ComputeScratchKeyForDynamicVBO(size_t size, GrBufferType, GrScratchKey*);
     28 
     29     GrAccessPattern accessPattern() const { return fAccessPattern; }
     30     size_t sizeInBytes() const { return fSizeInBytes; }
     31 
     32     /**
     33      * Returns true if the buffer is a wrapper around a CPU array. If true it
     34      * indicates that map will always succeed and will be free.
     35      */
     36     bool isCPUBacked() const { return SkToBool(fCPUData); }
     37     size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); }
     38 
     39     /**
     40      * Maps the buffer to be written by the CPU.
     41      *
     42      * The previous content of the buffer is invalidated. It is an error
     43      * to draw from the buffer while it is mapped. It may fail if the backend
     44      * doesn't support mapping the buffer. If the buffer is CPU backed then
     45      * it will always succeed and is a free operation. Once a buffer is mapped,
     46      * subsequent calls to map() are ignored.
     47      *
     48      * Note that buffer mapping does not go through GrContext and therefore is
     49      * not serialized with other operations.
     50      *
     51      * @return a pointer to the data or nullptr if the map fails.
     52      */
     53      void* map() {
     54          if (!fMapPtr) {
     55              this->onMap();
     56          }
     57          return fMapPtr;
     58      }
     59 
     60     /**
     61      * Unmaps the buffer.
     62      *
     63      * The pointer returned by the previous map call will no longer be valid.
     64      */
     65      void unmap() {
     66          SkASSERT(fMapPtr);
     67          this->onUnmap();
     68          fMapPtr = nullptr;
     69      }
     70 
     71     /**
     72      * Returns the same ptr that map() returned at time of map or nullptr if the
     73      * is not mapped.
     74      *
     75      * @return ptr to mapped buffer data or nullptr if buffer is not mapped.
     76      */
     77      void* mapPtr() const { return fMapPtr; }
     78 
     79     /**
     80      Queries whether the buffer has been mapped.
     81 
     82      @return true if the buffer is mapped, false otherwise.
     83      */
     84      bool isMapped() const { return SkToBool(fMapPtr); }
     85 
     86     /**
     87      * Updates the buffer data.
     88      *
     89      * The size of the buffer will be preserved. The src data will be
     90      * placed at the beginning of the buffer and any remaining contents will
     91      * be undefined. srcSizeInBytes must be <= to the buffer size.
     92      *
     93      * The buffer must not be mapped.
     94      *
     95      * Note that buffer updates do not go through GrContext and therefore are
     96      * not serialized with other operations.
     97      *
     98      * @return returns true if the update succeeds, false otherwise.
     99      */
    100     bool updateData(const void* src, size_t srcSizeInBytes) {
    101         SkASSERT(!this->isMapped());
    102         SkASSERT(srcSizeInBytes <= fSizeInBytes);
    103         return this->onUpdateData(src, srcSizeInBytes);
    104     }
    105 
    106     ~GrBuffer() override {
    107         sk_free(fCPUData);
    108     }
    109 
    110 protected:
    111     GrBuffer(GrGpu*, size_t sizeInBytes, GrBufferType, GrAccessPattern);
    112 
    113     void* fMapPtr;
    114 
    115 private:
    116     /**
    117      * Internal constructor to make a CPU-backed buffer.
    118      */
    119     GrBuffer(GrGpu*, size_t sizeInBytes, GrBufferType, void* cpuData);
    120 
    121     virtual void onMap() { SkASSERT(this->isCPUBacked()); fMapPtr = fCPUData; }
    122     virtual void onUnmap() { SkASSERT(this->isCPUBacked()); }
    123     virtual bool onUpdateData(const void* src, size_t srcSizeInBytes);
    124 
    125     size_t onGpuMemorySize() const override { return fSizeInBytes; } // TODO: zero for cpu backed?
    126     const char* getResourceType() const override { return "Buffer Object"; }
    127     void computeScratchKey(GrScratchKey* key) const override;
    128 
    129     size_t            fSizeInBytes;
    130     GrAccessPattern   fAccessPattern;
    131     void*             fCPUData;
    132     GrBufferType      fIntendedType;
    133 
    134     typedef GrGpuResource INHERITED;
    135 };
    136 
    137 #endif
    138