1 /*
2  * Copyright 2013 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 "GrGLBufferImpl.h"
9 #include "GrGLGpu.h"
10 
11 #define GL_CALL(GPU, X) GR_GL_CALL(GPU->glInterface(), X)
12 
13 #ifdef SK_DEBUG
14 #define VALIDATE() this->validate()
15 #else
16 #define VALIDATE() do {} while(false)
17 #endif
18 
GrGLBufferImpl(GrGLGpu * gpu,const Desc & desc,GrGLenum bufferType)19 GrGLBufferImpl::GrGLBufferImpl(GrGLGpu* gpu, const Desc& desc, GrGLenum bufferType)
20     : fDesc(desc)
21     , fBufferType(bufferType)
22     , fMapPtr(nullptr) {
23     if (0 == desc.fID) {
24         if (gpu->caps()->mustClearUploadedBufferData()) {
25             fCPUData = sk_calloc_throw(desc.fSizeInBytes);
26         } else {
27             fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW);
28         }
29         fGLSizeInBytes = 0;
30     } else {
31         fCPUData = nullptr;
32         // We assume that the GL buffer was created at the desc's size initially.
33         fGLSizeInBytes = fDesc.fSizeInBytes;
34     }
35     VALIDATE();
36 }
37 
release(GrGLGpu * gpu)38 void GrGLBufferImpl::release(GrGLGpu* gpu) {
39     VALIDATE();
40     // make sure we've not been abandoned or already released
41     if (fCPUData) {
42         sk_free(fCPUData);
43         fCPUData = nullptr;
44     } else if (fDesc.fID) {
45         gpu->releaseBuffer(fDesc.fID, fBufferType);
46         fDesc.fID = 0;
47         fGLSizeInBytes = 0;
48     }
49     fMapPtr = nullptr;
50     VALIDATE();
51 }
52 
abandon()53 void GrGLBufferImpl::abandon() {
54     fDesc.fID = 0;
55     fGLSizeInBytes = 0;
56     fMapPtr = nullptr;
57     sk_free(fCPUData);
58     fCPUData = nullptr;
59     VALIDATE();
60 }
61 
map(GrGLGpu * gpu)62 void* GrGLBufferImpl::map(GrGLGpu* gpu) {
63     VALIDATE();
64     SkASSERT(!this->isMapped());
65     if (0 == fDesc.fID) {
66         fMapPtr = fCPUData;
67     } else {
68         fMapPtr = gpu->mapBuffer(fDesc.fID, fBufferType, fDesc.fUsage, fGLSizeInBytes,
69                                  fDesc.fSizeInBytes);
70         fGLSizeInBytes = fDesc.fSizeInBytes;
71     }
72     VALIDATE();
73     return fMapPtr;
74 }
75 
unmap(GrGLGpu * gpu)76 void GrGLBufferImpl::unmap(GrGLGpu* gpu) {
77     VALIDATE();
78     SkASSERT(this->isMapped());
79     if (0 != fDesc.fID) {
80         gpu->unmapBuffer(fDesc.fID, fBufferType, fMapPtr);
81     }
82     fMapPtr = nullptr;
83 }
84 
isMapped() const85 bool GrGLBufferImpl::isMapped() const {
86     VALIDATE();
87     return SkToBool(fMapPtr);
88 }
89 
updateData(GrGLGpu * gpu,const void * src,size_t srcSizeInBytes)90 bool GrGLBufferImpl::updateData(GrGLGpu* gpu, const void* src, size_t srcSizeInBytes) {
91     SkASSERT(!this->isMapped());
92     SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType);
93     VALIDATE();
94     if (srcSizeInBytes > fDesc.fSizeInBytes) {
95         return false;
96     }
97     if (0 == fDesc.fID) {
98         memcpy(fCPUData, src, srcSizeInBytes);
99         return true;
100     }
101     gpu->bufferData(fDesc.fID, fBufferType, fDesc.fUsage, fDesc.fSizeInBytes, src,
102                     srcSizeInBytes);
103 #if GR_GL_USE_BUFFER_DATA_NULL_HINT
104     fGLSizeInBytes = fDesc.fSizeInBytes;
105 #else
106     fGLSizeInBytes = srcSizeInBytes;
107 #endif
108     VALIDATE();
109     return true;
110 }
111 
validate() const112 void GrGLBufferImpl::validate() const {
113     SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType ||
114              GR_GL_PIXEL_PACK_BUFFER == fBufferType || GR_GL_PIXEL_UNPACK_BUFFER == fBufferType ||
115              GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM == fBufferType ||
116              GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == fBufferType);
117     // The following assert isn't valid when the buffer has been abandoned:
118     // SkASSERT((0 == fDesc.fID) == (fCPUData));
119     SkASSERT(nullptr == fCPUData || 0 == fGLSizeInBytes);
120     SkASSERT(nullptr == fMapPtr || fCPUData || fGLSizeInBytes <= fDesc.fSizeInBytes);
121     SkASSERT(nullptr == fCPUData || nullptr == fMapPtr || fCPUData == fMapPtr);
122 }
123