blob: d90b587bfc39bcfe6f1e537f35e2aa8247d498db [file] [log] [blame]
cdalton397536c2016-03-25 12:15:03 -07001/*
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
13class GrGpu;
14
15class GrBuffer : public GrGpuResource {
16public:
17 /**
csmartdalton485a1202016-07-13 10:16:32 -070018 * Creates a client-side buffer.
cdalton397536c2016-03-25 12:15:03 -070019 */
Brian Salomon12d22642019-01-29 14:38:50 -050020 static SK_WARN_UNUSED_RESULT sk_sp<GrBuffer> MakeCPUBacked(GrGpu*, size_t sizeInBytes,
Brian Salomonae64c192019-02-05 09:41:37 -050021 GrGpuBufferType,
Brian Salomon12d22642019-01-29 14:38:50 -050022 const void* data = nullptr);
csmartdalton485a1202016-07-13 10:16:32 -070023
24 /**
25 * Computes a scratch key for a GPU-side buffer with a "dynamic" access pattern. (Buffers with
26 * "static" and "stream" patterns are disqualified by nature from being cached and reused.)
27 */
Brian Salomonae64c192019-02-05 09:41:37 -050028 static void ComputeScratchKeyForDynamicVBO(size_t size, GrGpuBufferType, GrScratchKey*);
cdalton397536c2016-03-25 12:15:03 -070029
cdalton397536c2016-03-25 12:15:03 -070030 GrAccessPattern accessPattern() const { return fAccessPattern; }
csmartdalton485a1202016-07-13 10:16:32 -070031 size_t sizeInBytes() const { return fSizeInBytes; }
cdalton397536c2016-03-25 12:15:03 -070032
33 /**
34 * Returns true if the buffer is a wrapper around a CPU array. If true it
35 * indicates that map will always succeed and will be free.
36 */
csmartdalton485a1202016-07-13 10:16:32 -070037 bool isCPUBacked() const { return SkToBool(fCPUData); }
38 size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); }
cdalton397536c2016-03-25 12:15:03 -070039
40 /**
41 * Maps the buffer to be written by the CPU.
42 *
43 * The previous content of the buffer is invalidated. It is an error
44 * to draw from the buffer while it is mapped. It may fail if the backend
45 * doesn't support mapping the buffer. If the buffer is CPU backed then
46 * it will always succeed and is a free operation. Once a buffer is mapped,
47 * subsequent calls to map() are ignored.
48 *
49 * Note that buffer mapping does not go through GrContext and therefore is
50 * not serialized with other operations.
51 *
52 * @return a pointer to the data or nullptr if the map fails.
53 */
54 void* map() {
55 if (!fMapPtr) {
56 this->onMap();
57 }
58 return fMapPtr;
59 }
60
61 /**
62 * Unmaps the buffer.
63 *
64 * The pointer returned by the previous map call will no longer be valid.
65 */
66 void unmap() {
67 SkASSERT(fMapPtr);
68 this->onUnmap();
69 fMapPtr = nullptr;
70 }
71
72 /**
cdalton397536c2016-03-25 12:15:03 -070073 Queries whether the buffer has been mapped.
74
75 @return true if the buffer is mapped, false otherwise.
76 */
77 bool isMapped() const { return SkToBool(fMapPtr); }
78
79 /**
80 * Updates the buffer data.
81 *
82 * The size of the buffer will be preserved. The src data will be
83 * placed at the beginning of the buffer and any remaining contents will
84 * be undefined. srcSizeInBytes must be <= to the buffer size.
85 *
86 * The buffer must not be mapped.
87 *
88 * Note that buffer updates do not go through GrContext and therefore are
89 * not serialized with other operations.
90 *
91 * @return returns true if the update succeeds, false otherwise.
92 */
93 bool updateData(const void* src, size_t srcSizeInBytes) {
94 SkASSERT(!this->isMapped());
csmartdalton485a1202016-07-13 10:16:32 -070095 SkASSERT(srcSizeInBytes <= fSizeInBytes);
cdalton397536c2016-03-25 12:15:03 -070096 return this->onUpdateData(src, srcSizeInBytes);
97 }
98
csmartdalton485a1202016-07-13 10:16:32 -070099 ~GrBuffer() override {
100 sk_free(fCPUData);
kkinnunen2e6055b2016-04-22 01:48:29 -0700101 }
102
csmartdalton485a1202016-07-13 10:16:32 -0700103protected:
Brian Salomonae64c192019-02-05 09:41:37 -0500104 GrBuffer(GrGpu*, size_t sizeInBytes, GrGpuBufferType, GrAccessPattern);
Brian Salomon95548f62019-02-05 16:07:56 -0500105 GrGpuBufferType intendedType() const { return fIntendedType; }
cdalton397536c2016-03-25 12:15:03 -0700106
107 void* fMapPtr;
108
109private:
csmartdalton485a1202016-07-13 10:16:32 -0700110 /**
111 * Internal constructor to make a CPU-backed buffer.
112 */
Brian Salomonae64c192019-02-05 09:41:37 -0500113 GrBuffer(GrGpu*, size_t sizeInBytes, GrGpuBufferType, void* cpuData);
cdalton397536c2016-03-25 12:15:03 -0700114
csmartdalton485a1202016-07-13 10:16:32 -0700115 virtual void onMap() { SkASSERT(this->isCPUBacked()); fMapPtr = fCPUData; }
116 virtual void onUnmap() { SkASSERT(this->isCPUBacked()); }
117 virtual bool onUpdateData(const void* src, size_t srcSizeInBytes);
cdalton397536c2016-03-25 12:15:03 -0700118
csmartdalton485a1202016-07-13 10:16:32 -0700119 size_t onGpuMemorySize() const override { return fSizeInBytes; } // TODO: zero for cpu backed?
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400120 const char* getResourceType() const override { return "Buffer Object"; }
csmartdalton485a1202016-07-13 10:16:32 -0700121 void computeScratchKey(GrScratchKey* key) const override;
122
123 size_t fSizeInBytes;
cdalton397536c2016-03-25 12:15:03 -0700124 GrAccessPattern fAccessPattern;
csmartdalton485a1202016-07-13 10:16:32 -0700125 void* fCPUData;
Brian Salomonae64c192019-02-05 09:41:37 -0500126 GrGpuBufferType fIntendedType;
csmartdalton485a1202016-07-13 10:16:32 -0700127
cdalton397536c2016-03-25 12:15:03 -0700128 typedef GrGpuResource INHERITED;
129};
130
131#endif