Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: src/gpu/gl/GrGLBuffer.cpp

Issue 1831133004: Revert of Consolidate GPU buffer implementations (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/gl/GrGLBuffer.h ('k') | src/gpu/gl/GrGLBufferImpl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 GrGLBuffer* GrGLBuffer::Create(GrGLGpu* gpu, GrBufferType type, size_t size,
32 GrAccessPattern accessPattern) {
33 static const int kIsVertexOrIndex = (1 << kVertex_GrBufferType) | (1 << kInd ex_GrBufferType);
34 bool cpuBacked = gpu->glCaps().useNonVBOVertexAndIndexDynamicData() &&
35 kDynamic_GrAccessPattern == accessPattern &&
36 ((kIsVertexOrIndex >> type) & 1);
37 SkAutoTUnref<GrGLBuffer> buffer(new GrGLBuffer(gpu, type, size, accessPatter n, cpuBacked));
38 if (!cpuBacked && 0 == buffer->fBufferID) {
39 return nullptr;
40 }
41 return buffer.release();
42 }
43
44 // GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a cli ent's vertex buffer
45 // objects are implemented as client-side-arrays on tile-deferred architectures.
46 #define DYNAMIC_DRAW_PARAM GR_GL_STREAM_DRAW
47
48 inline static void get_target_and_usage(GrBufferType type, GrAccessPattern acces sPattern,
49 const GrGLCaps& caps, GrGLenum* target, GrGLenum* usage) {
50 static const GrGLenum nonXferTargets[] = {
51 GR_GL_ARRAY_BUFFER,
52 GR_GL_ELEMENT_ARRAY_BUFFER
53 };
54 GR_STATIC_ASSERT(0 == kVertex_GrBufferType);
55 GR_STATIC_ASSERT(1 == kIndex_GrBufferType);
56
57 static const GrGLenum drawUsages[] = {
58 DYNAMIC_DRAW_PARAM, // TODO: Do we really want to use STREAM_DRAW here o n non-Chromium?
59 GR_GL_STATIC_DRAW,
60 GR_GL_STREAM_DRAW
61 };
62 static const GrGLenum readUsages[] = {
63 GR_GL_DYNAMIC_READ,
64 GR_GL_STATIC_READ,
65 GR_GL_STREAM_READ
66 };
67 GR_STATIC_ASSERT(0 == kDynamic_GrAccessPattern);
68 GR_STATIC_ASSERT(1 == kStatic_GrAccessPattern);
69 GR_STATIC_ASSERT(2 == kStream_GrAccessPattern);
70 GR_STATIC_ASSERT(SK_ARRAY_COUNT(drawUsages) == 1 + kLast_GrAccessPattern);
71 GR_STATIC_ASSERT(SK_ARRAY_COUNT(readUsages) == 1 + kLast_GrAccessPattern);
72
73 SkASSERT(accessPattern >= 0 && accessPattern <= kLast_GrAccessPattern);
74
75 switch (type) {
76 case kVertex_GrBufferType:
77 case kIndex_GrBufferType:
78 *target = nonXferTargets[type];
79 *usage = drawUsages[accessPattern];
80 break;
81 case kXferCpuToGpu_GrBufferType:
82 if (GrGLCaps::kChromium_TransferBufferType == caps.transferBufferTyp e()) {
83 *target = GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM;
84 } else {
85 SkASSERT(GrGLCaps::kPBO_TransferBufferType == caps.transferBuffe rType());
86 *target = GR_GL_PIXEL_UNPACK_BUFFER;
87 }
88 *usage = drawUsages[accessPattern];
89 break;
90 case kXferGpuToCpu_GrBufferType:
91 if (GrGLCaps::kChromium_TransferBufferType == caps.transferBufferTyp e()) {
92 *target = GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM;
93 } else {
94 SkASSERT(GrGLCaps::kPBO_TransferBufferType == caps.transferBuffe rType());
95 *target = GR_GL_PIXEL_PACK_BUFFER;
96 }
97 *usage = readUsages[accessPattern];
98 break;
99 default:
100 SkFAIL("Unexpected buffer type.");
101 break;
102 }
103 }
104
105 GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, GrBufferType type, size_t size, GrAccessPat tern accessPattern,
106 bool cpuBacked)
107 : INHERITED(gpu, type, size, accessPattern, cpuBacked),
108 fCPUData(nullptr),
109 fTarget(0),
110 fBufferID(0),
111 fSizeInBytes(size),
112 fUsage(0),
113 fGLSizeInBytes(0) {
114 if (cpuBacked) {
115 if (gpu->caps()->mustClearUploadedBufferData()) {
116 fCPUData = sk_calloc_throw(fSizeInBytes);
117 } else {
118 fCPUData = sk_malloc_flags(fSizeInBytes, SK_MALLOC_THROW);
119 }
120 } else {
121 GL_CALL(GenBuffers(1, &fBufferID));
122 fSizeInBytes = size;
123 get_target_and_usage(type, accessPattern, gpu->glCaps(), &fTarget, &fUsa ge);
124 if (fBufferID) {
125 gpu->bindBuffer(fBufferID, fTarget);
126 CLEAR_ERROR_BEFORE_ALLOC(gpu->glInterface());
127 // make sure driver can allocate memory for this buffer
128 GL_ALLOC_CALL(gpu->glInterface(), BufferData(fTarget,
129 (GrGLsizeiptr) fSizeInB ytes,
130 nullptr, // data ptr
131 fUsage));
132 if (CHECK_ALLOC_ERROR(gpu->glInterface()) != GR_GL_NO_ERROR) {
133 gpu->releaseBuffer(fBufferID, fTarget);
134 fBufferID = 0;
135 } else {
136 fGLSizeInBytes = fSizeInBytes;
137 }
138 }
139 }
140 VALIDATE();
141 this->registerWithCache();
142 }
143
144 inline GrGLGpu* GrGLBuffer::glGpu() const {
145 SkASSERT(!this->wasDestroyed());
146 return static_cast<GrGLGpu*>(this->getGpu());
147 }
148
149 inline const GrGLCaps& GrGLBuffer::glCaps() const {
150 return this->glGpu()->glCaps();
151 }
152
153 void GrGLBuffer::onRelease() {
154 if (!this->wasDestroyed()) {
155 VALIDATE();
156 // make sure we've not been abandoned or already released
157 if (fCPUData) {
158 SkASSERT(!fBufferID);
159 sk_free(fCPUData);
160 fCPUData = nullptr;
161 } else if (fBufferID) {
162 this->glGpu()->releaseBuffer(fBufferID, fTarget);
163 fBufferID = 0;
164 fGLSizeInBytes = 0;
165 }
166 fMapPtr = nullptr;
167 VALIDATE();
168 }
169
170 INHERITED::onRelease();
171 }
172
173 void GrGLBuffer::onAbandon() {
174 fBufferID = 0;
175 fGLSizeInBytes = 0;
176 fMapPtr = nullptr;
177 sk_free(fCPUData);
178 fCPUData = nullptr;
179 VALIDATE();
180 INHERITED::onAbandon();
181 }
182
183 void GrGLBuffer::onMap() {
184 if (this->wasDestroyed()) {
185 return;
186 }
187
188 VALIDATE();
189 SkASSERT(!this->isMapped());
190
191 if (0 == fBufferID) {
192 fMapPtr = fCPUData;
193 VALIDATE();
194 return;
195 }
196
197 bool readOnly = (kXferGpuToCpu_GrBufferType == this->type());
198
199 // Handling dirty context is done in the bindBuffer call
200 switch (this->glCaps().mapBufferType()) {
201 case GrGLCaps::kNone_MapBufferType:
202 break;
203 case GrGLCaps::kMapBuffer_MapBufferType:
204 this->glGpu()->bindBuffer(fBufferID, fTarget);
205 // Let driver know it can discard the old data
206 if (GR_GL_USE_BUFFER_DATA_NULL_HINT || fGLSizeInBytes != fSizeInByte s) {
207 GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage));
208 }
209 GL_CALL_RET(fMapPtr, MapBuffer(fTarget, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY));
210 break;
211 case GrGLCaps::kMapBufferRange_MapBufferType: {
212 this->glGpu()->bindBuffer(fBufferID, fTarget);
213 // Make sure the GL buffer size agrees with fDesc before mapping.
214 if (fGLSizeInBytes != fSizeInBytes) {
215 GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage));
216 }
217 GrGLbitfield writeAccess = GR_GL_MAP_WRITE_BIT;
218 // TODO: allow the client to specify invalidation in the transfer bu ffer case.
219 if (kXferCpuToGpu_GrBufferType != this->type()) {
220 writeAccess |= GR_GL_MAP_INVALIDATE_BUFFER_BIT;
221 }
222 GL_CALL_RET(fMapPtr, MapBufferRange(fTarget, 0, fSizeInBytes,
223 readOnly ? GR_GL_MAP_READ_BIT : writeAccess));
224 break;
225 }
226 case GrGLCaps::kChromium_MapBufferType:
227 this->glGpu()->bindBuffer(fBufferID, fTarget);
228 // Make sure the GL buffer size agrees with fDesc before mapping.
229 if (fGLSizeInBytes != fSizeInBytes) {
230 GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage));
231 }
232 GL_CALL_RET(fMapPtr, MapBufferSubData(fTarget, 0, fSizeInBytes,
233 readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY));
234 break;
235 }
236 fGLSizeInBytes = fSizeInBytes;
237 VALIDATE();
238 }
239
240 void GrGLBuffer::onUnmap() {
241 if (this->wasDestroyed()) {
242 return;
243 }
244
245 VALIDATE();
246 SkASSERT(this->isMapped());
247 if (0 == fBufferID) {
248 fMapPtr = nullptr;
249 return;
250 }
251 // bind buffer handles the dirty context
252 switch (this->glCaps().mapBufferType()) {
253 case GrGLCaps::kNone_MapBufferType:
254 SkDEBUGFAIL("Shouldn't get here.");
255 return;
256 case GrGLCaps::kMapBuffer_MapBufferType: // fall through
257 case GrGLCaps::kMapBufferRange_MapBufferType:
258 this->glGpu()->bindBuffer(fBufferID, fTarget);
259 GL_CALL(UnmapBuffer(fTarget));
260 break;
261 case GrGLCaps::kChromium_MapBufferType:
262 this->glGpu()->bindBuffer(fBufferID, fTarget);
263 GL_CALL(UnmapBufferSubData(fMapPtr));
264 break;
265 }
266 fMapPtr = nullptr;
267 }
268
269 bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
270 if (this->wasDestroyed()) {
271 return false;
272 }
273
274 SkASSERT(!this->isMapped());
275 SkASSERT(GR_GL_ARRAY_BUFFER == fTarget || GR_GL_ELEMENT_ARRAY_BUFFER == fTar get);
276 VALIDATE();
277 if (srcSizeInBytes > fSizeInBytes) {
278 return false;
279 }
280 if (0 == fBufferID) {
281 memcpy(fCPUData, src, srcSizeInBytes);
282 return true;
283 }
284 SkASSERT(srcSizeInBytes <= fSizeInBytes);
285 // bindbuffer handles dirty context
286 this->glGpu()->bindBuffer(fBufferID, fTarget);
287
288 #if GR_GL_USE_BUFFER_DATA_NULL_HINT
289 if (fSizeInBytes == srcSizeInBytes) {
290 GL_CALL(BufferData(fTarget, (GrGLsizeiptr) srcSizeInBytes, src, fUsage)) ;
291 } else {
292 // Before we call glBufferSubData we give the driver a hint using
293 // glBufferData with nullptr. This makes the old buffer contents
294 // inaccessible to future draws. The GPU may still be processing
295 // draws that reference the old contents. With this hint it can
296 // assign a different allocation for the new contents to avoid
297 // flushing the gpu past draws consuming the old contents.
298 // TODO I think we actually want to try calling bufferData here
299 GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage));
300 GL_CALL(BufferSubData(fTarget, 0, (GrGLsizeiptr) srcSizeInBytes, src));
301 }
302 fGLSizeInBytes = fSizeInBytes;
303 #else
304 // Note that we're cheating on the size here. Currently no methods
305 // allow a partial update that preserves contents of non-updated
306 // portions of the buffer (map() does a glBufferData(..size, nullptr..))
307 GL_CALL(BufferData(fTarget, srcSizeInBytes, src, fUsage));
308 fGLSizeInBytes = srcSizeInBytes;
309 #endif
310 VALIDATE();
311 return true;
312 }
313
314 void GrGLBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
315 const SkString& dumpName) const {
316 SkString buffer_id;
317 buffer_id.appendU32(this->bufferID());
318 traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer",
319 buffer_id.c_str());
320 }
321
322 #ifdef SK_DEBUG
323
324 void GrGLBuffer::validate() const {
325 SkASSERT(GR_GL_ARRAY_BUFFER == fTarget || GR_GL_ELEMENT_ARRAY_BUFFER == fTar get ||
326 GR_GL_PIXEL_PACK_BUFFER == fTarget || GR_GL_PIXEL_UNPACK_BUFFER == fTarget ||
327 GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM == fTarget ||
328 GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == fTarget);
329 // The following assert isn't valid when the buffer has been abandoned:
330 // SkASSERT((0 == fDesc.fID) == (fCPUData));
331 SkASSERT(0 != fBufferID || 0 == fGLSizeInBytes);
332 SkASSERT(nullptr == fMapPtr || fCPUData || fGLSizeInBytes <= fSizeInBytes);
333 SkASSERT(nullptr == fCPUData || nullptr == fMapPtr || fCPUData == fMapPtr);
334 }
335
336 #endif
OLDNEW
« no previous file with comments | « src/gpu/gl/GrGLBuffer.h ('k') | src/gpu/gl/GrGLBufferImpl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698