1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2010 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
9cb93a386Sopenharmony_ci#include "include/gpu/GrTypes.h"
10cb93a386Sopenharmony_ci#include "include/private/SkMacros.h"
11cb93a386Sopenharmony_ci#include "src/core/SkSafeMath.h"
12cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h"
13cb93a386Sopenharmony_ci#include "src/gpu/GrBufferAllocPool.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci#include <memory>
16cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
17cb93a386Sopenharmony_ci#include "src/gpu/GrCpuBuffer.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h"
20cb93a386Sopenharmony_ci#include "src/gpu/GrGpuBuffer.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h"
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_cisk_sp<GrBufferAllocPool::CpuBufferCache> GrBufferAllocPool::CpuBufferCache::Make(
24cb93a386Sopenharmony_ci        int maxBuffersToCache) {
25cb93a386Sopenharmony_ci    return sk_sp<CpuBufferCache>(new CpuBufferCache(maxBuffersToCache));
26cb93a386Sopenharmony_ci}
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ciGrBufferAllocPool::CpuBufferCache::CpuBufferCache(int maxBuffersToCache)
29cb93a386Sopenharmony_ci        : fMaxBuffersToCache(maxBuffersToCache) {
30cb93a386Sopenharmony_ci    if (fMaxBuffersToCache) {
31cb93a386Sopenharmony_ci        fBuffers = std::make_unique<Buffer[]>(fMaxBuffersToCache);
32cb93a386Sopenharmony_ci    }
33cb93a386Sopenharmony_ci}
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_cisk_sp<GrCpuBuffer> GrBufferAllocPool::CpuBufferCache::makeBuffer(size_t size,
36cb93a386Sopenharmony_ci                                                                 bool mustBeInitialized) {
37cb93a386Sopenharmony_ci    SkASSERT(size > 0);
38cb93a386Sopenharmony_ci    Buffer* result = nullptr;
39cb93a386Sopenharmony_ci    if (size == kDefaultBufferSize) {
40cb93a386Sopenharmony_ci        int i = 0;
41cb93a386Sopenharmony_ci        for (; i < fMaxBuffersToCache && fBuffers[i].fBuffer; ++i) {
42cb93a386Sopenharmony_ci            SkASSERT(fBuffers[i].fBuffer->size() == kDefaultBufferSize);
43cb93a386Sopenharmony_ci            if (fBuffers[i].fBuffer->unique()) {
44cb93a386Sopenharmony_ci                result = &fBuffers[i];
45cb93a386Sopenharmony_ci            }
46cb93a386Sopenharmony_ci        }
47cb93a386Sopenharmony_ci        if (!result && i < fMaxBuffersToCache) {
48cb93a386Sopenharmony_ci            fBuffers[i].fBuffer = GrCpuBuffer::Make(size);
49cb93a386Sopenharmony_ci            result = &fBuffers[i];
50cb93a386Sopenharmony_ci        }
51cb93a386Sopenharmony_ci    }
52cb93a386Sopenharmony_ci    Buffer tempResult;
53cb93a386Sopenharmony_ci    if (!result) {
54cb93a386Sopenharmony_ci        tempResult.fBuffer = GrCpuBuffer::Make(size);
55cb93a386Sopenharmony_ci        result = &tempResult;
56cb93a386Sopenharmony_ci    }
57cb93a386Sopenharmony_ci    if (mustBeInitialized && !result->fCleared) {
58cb93a386Sopenharmony_ci        result->fCleared = true;
59cb93a386Sopenharmony_ci        memset(result->fBuffer->data(), 0, result->fBuffer->size());
60cb93a386Sopenharmony_ci    }
61cb93a386Sopenharmony_ci    return result->fBuffer;
62cb93a386Sopenharmony_ci}
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_civoid GrBufferAllocPool::CpuBufferCache::releaseAll() {
65cb93a386Sopenharmony_ci    for (int i = 0; i < fMaxBuffersToCache && fBuffers[i].fBuffer; ++i) {
66cb93a386Sopenharmony_ci        fBuffers[i].fBuffer.reset();
67cb93a386Sopenharmony_ci        fBuffers[i].fCleared = false;
68cb93a386Sopenharmony_ci    }
69cb93a386Sopenharmony_ci}
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci#ifdef SK_DEBUG
74cb93a386Sopenharmony_ci    #define VALIDATE validate
75cb93a386Sopenharmony_ci#else
76cb93a386Sopenharmony_ci    static void VALIDATE(bool = false) {}
77cb93a386Sopenharmony_ci#endif
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci#define UNMAP_BUFFER(block)                                                          \
80cb93a386Sopenharmony_ci    do {                                                                             \
81cb93a386Sopenharmony_ci        TRACE_EVENT_INSTANT1("skia.gpu", "GrBufferAllocPool Unmapping Buffer",       \
82cb93a386Sopenharmony_ci                             TRACE_EVENT_SCOPE_THREAD, "percent_unwritten",          \
83cb93a386Sopenharmony_ci                             (float)((block).fBytesFree) / (block).fBuffer->size()); \
84cb93a386Sopenharmony_ci        SkASSERT(!block.fBuffer->isCpuBuffer());                                     \
85cb93a386Sopenharmony_ci        static_cast<GrGpuBuffer*>(block.fBuffer.get())->unmap();                     \
86cb93a386Sopenharmony_ci    } while (false)
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ciGrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, GrGpuBufferType bufferType,
89cb93a386Sopenharmony_ci                                     sk_sp<CpuBufferCache> cpuBufferCache)
90cb93a386Sopenharmony_ci        : fBlocks(8)
91cb93a386Sopenharmony_ci        , fCpuBufferCache(std::move(cpuBufferCache))
92cb93a386Sopenharmony_ci        , fGpu(gpu)
93cb93a386Sopenharmony_ci        , fBufferType(bufferType) {}
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_civoid GrBufferAllocPool::deleteBlocks() {
96cb93a386Sopenharmony_ci    if (fBlocks.count()) {
97cb93a386Sopenharmony_ci        GrBuffer* buffer = fBlocks.back().fBuffer.get();
98cb93a386Sopenharmony_ci        if (!buffer->isCpuBuffer() && static_cast<GrGpuBuffer*>(buffer)->isMapped()) {
99cb93a386Sopenharmony_ci            UNMAP_BUFFER(fBlocks.back());
100cb93a386Sopenharmony_ci        }
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci    while (!fBlocks.empty()) {
103cb93a386Sopenharmony_ci        this->destroyBlock();
104cb93a386Sopenharmony_ci    }
105cb93a386Sopenharmony_ci    SkASSERT(!fBufferPtr);
106cb93a386Sopenharmony_ci}
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ciGrBufferAllocPool::~GrBufferAllocPool() {
109cb93a386Sopenharmony_ci    VALIDATE();
110cb93a386Sopenharmony_ci    this->deleteBlocks();
111cb93a386Sopenharmony_ci}
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_civoid GrBufferAllocPool::reset() {
114cb93a386Sopenharmony_ci    VALIDATE();
115cb93a386Sopenharmony_ci    fBytesInUse = 0;
116cb93a386Sopenharmony_ci    this->deleteBlocks();
117cb93a386Sopenharmony_ci    this->resetCpuData(0);
118cb93a386Sopenharmony_ci    VALIDATE();
119cb93a386Sopenharmony_ci}
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_civoid GrBufferAllocPool::unmap() {
122cb93a386Sopenharmony_ci    VALIDATE();
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    if (fBufferPtr) {
125cb93a386Sopenharmony_ci        BufferBlock& block = fBlocks.back();
126cb93a386Sopenharmony_ci        GrBuffer* buffer = block.fBuffer.get();
127cb93a386Sopenharmony_ci        if (!buffer->isCpuBuffer()) {
128cb93a386Sopenharmony_ci            if (static_cast<GrGpuBuffer*>(buffer)->isMapped()) {
129cb93a386Sopenharmony_ci                UNMAP_BUFFER(block);
130cb93a386Sopenharmony_ci            } else {
131cb93a386Sopenharmony_ci                size_t flushSize = block.fBuffer->size() - block.fBytesFree;
132cb93a386Sopenharmony_ci                this->flushCpuData(fBlocks.back(), flushSize);
133cb93a386Sopenharmony_ci            }
134cb93a386Sopenharmony_ci        }
135cb93a386Sopenharmony_ci        fBufferPtr = nullptr;
136cb93a386Sopenharmony_ci    }
137cb93a386Sopenharmony_ci    VALIDATE();
138cb93a386Sopenharmony_ci}
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci#ifdef SK_DEBUG
141cb93a386Sopenharmony_civoid GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
142cb93a386Sopenharmony_ci    bool wasDestroyed = false;
143cb93a386Sopenharmony_ci    if (fBufferPtr) {
144cb93a386Sopenharmony_ci        SkASSERT(!fBlocks.empty());
145cb93a386Sopenharmony_ci        const GrBuffer* buffer = fBlocks.back().fBuffer.get();
146cb93a386Sopenharmony_ci        if (!buffer->isCpuBuffer() && !static_cast<const GrGpuBuffer*>(buffer)->isMapped()) {
147cb93a386Sopenharmony_ci            SkASSERT(fCpuStagingBuffer && fCpuStagingBuffer->data() == fBufferPtr);
148cb93a386Sopenharmony_ci        }
149cb93a386Sopenharmony_ci    } else if (!fBlocks.empty()) {
150cb93a386Sopenharmony_ci        const GrBuffer* buffer = fBlocks.back().fBuffer.get();
151cb93a386Sopenharmony_ci        SkASSERT(buffer->isCpuBuffer() || !static_cast<const GrGpuBuffer*>(buffer)->isMapped());
152cb93a386Sopenharmony_ci    }
153cb93a386Sopenharmony_ci    size_t bytesInUse = 0;
154cb93a386Sopenharmony_ci    for (int i = 0; i < fBlocks.count() - 1; ++i) {
155cb93a386Sopenharmony_ci        const GrBuffer* buffer = fBlocks[i].fBuffer.get();
156cb93a386Sopenharmony_ci        SkASSERT(buffer->isCpuBuffer() || !static_cast<const GrGpuBuffer*>(buffer)->isMapped());
157cb93a386Sopenharmony_ci    }
158cb93a386Sopenharmony_ci    for (int i = 0; !wasDestroyed && i < fBlocks.count(); ++i) {
159cb93a386Sopenharmony_ci        GrBuffer* buffer = fBlocks[i].fBuffer.get();
160cb93a386Sopenharmony_ci        if (!buffer->isCpuBuffer() && static_cast<GrGpuBuffer*>(buffer)->wasDestroyed()) {
161cb93a386Sopenharmony_ci            wasDestroyed = true;
162cb93a386Sopenharmony_ci        } else {
163cb93a386Sopenharmony_ci            size_t bytes = fBlocks[i].fBuffer->size() - fBlocks[i].fBytesFree;
164cb93a386Sopenharmony_ci            bytesInUse += bytes;
165cb93a386Sopenharmony_ci            SkASSERT(bytes || unusedBlockAllowed);
166cb93a386Sopenharmony_ci        }
167cb93a386Sopenharmony_ci    }
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci    if (!wasDestroyed) {
170cb93a386Sopenharmony_ci        SkASSERT(bytesInUse == fBytesInUse);
171cb93a386Sopenharmony_ci        if (unusedBlockAllowed) {
172cb93a386Sopenharmony_ci            SkASSERT((fBytesInUse && !fBlocks.empty()) ||
173cb93a386Sopenharmony_ci                     (!fBytesInUse && (fBlocks.count() < 2)));
174cb93a386Sopenharmony_ci        } else {
175cb93a386Sopenharmony_ci            SkASSERT((0 == fBytesInUse) == fBlocks.empty());
176cb93a386Sopenharmony_ci        }
177cb93a386Sopenharmony_ci    }
178cb93a386Sopenharmony_ci}
179cb93a386Sopenharmony_ci#endif
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_cistatic inline size_t align_up_pad(size_t x, size_t alignment) {
182cb93a386Sopenharmony_ci    return (alignment - x % alignment) % alignment;
183cb93a386Sopenharmony_ci}
184cb93a386Sopenharmony_ci
185cb93a386Sopenharmony_cistatic inline size_t align_down(size_t x, uint32_t alignment) {
186cb93a386Sopenharmony_ci    return (x / alignment) * alignment;
187cb93a386Sopenharmony_ci}
188cb93a386Sopenharmony_ci
189cb93a386Sopenharmony_civoid* GrBufferAllocPool::makeSpace(size_t size,
190cb93a386Sopenharmony_ci                                   size_t alignment,
191cb93a386Sopenharmony_ci                                   sk_sp<const GrBuffer>* buffer,
192cb93a386Sopenharmony_ci                                   size_t* offset) {
193cb93a386Sopenharmony_ci    VALIDATE();
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_ci    SkASSERT(buffer);
196cb93a386Sopenharmony_ci    SkASSERT(offset);
197cb93a386Sopenharmony_ci
198cb93a386Sopenharmony_ci    if (fBufferPtr) {
199cb93a386Sopenharmony_ci        BufferBlock& back = fBlocks.back();
200cb93a386Sopenharmony_ci        size_t usedBytes = back.fBuffer->size() - back.fBytesFree;
201cb93a386Sopenharmony_ci        size_t pad = align_up_pad(usedBytes, alignment);
202cb93a386Sopenharmony_ci        SkSafeMath safeMath;
203cb93a386Sopenharmony_ci        size_t alignedSize = safeMath.add(pad, size);
204cb93a386Sopenharmony_ci        if (!safeMath.ok()) {
205cb93a386Sopenharmony_ci            return nullptr;
206cb93a386Sopenharmony_ci        }
207cb93a386Sopenharmony_ci        if (alignedSize <= back.fBytesFree) {
208cb93a386Sopenharmony_ci            memset((void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes), 0, pad);
209cb93a386Sopenharmony_ci            usedBytes += pad;
210cb93a386Sopenharmony_ci            *offset = usedBytes;
211cb93a386Sopenharmony_ci            *buffer = back.fBuffer;
212cb93a386Sopenharmony_ci            back.fBytesFree -= alignedSize;
213cb93a386Sopenharmony_ci            fBytesInUse += alignedSize;
214cb93a386Sopenharmony_ci            VALIDATE();
215cb93a386Sopenharmony_ci            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
216cb93a386Sopenharmony_ci        }
217cb93a386Sopenharmony_ci    }
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_ci    // We could honor the space request using by a partial update of the current
220cb93a386Sopenharmony_ci    // VB (if there is room). But we don't currently use draw calls to GL that
221cb93a386Sopenharmony_ci    // allow the driver to know that previously issued draws won't read from
222cb93a386Sopenharmony_ci    // the part of the buffer we update. Also, the GL buffer implementation
223cb93a386Sopenharmony_ci    // may be cheating on the actual buffer size by shrinking the buffer on
224cb93a386Sopenharmony_ci    // updateData() if the amount of data passed is less than the full buffer
225cb93a386Sopenharmony_ci    // size.
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci    if (!this->createBlock(size)) {
228cb93a386Sopenharmony_ci        return nullptr;
229cb93a386Sopenharmony_ci    }
230cb93a386Sopenharmony_ci    SkASSERT(fBufferPtr);
231cb93a386Sopenharmony_ci
232cb93a386Sopenharmony_ci    *offset = 0;
233cb93a386Sopenharmony_ci    BufferBlock& back = fBlocks.back();
234cb93a386Sopenharmony_ci    *buffer = back.fBuffer;
235cb93a386Sopenharmony_ci    back.fBytesFree -= size;
236cb93a386Sopenharmony_ci    fBytesInUse += size;
237cb93a386Sopenharmony_ci    VALIDATE();
238cb93a386Sopenharmony_ci    return fBufferPtr;
239cb93a386Sopenharmony_ci}
240cb93a386Sopenharmony_ci
241cb93a386Sopenharmony_civoid* GrBufferAllocPool::makeSpaceAtLeast(size_t minSize,
242cb93a386Sopenharmony_ci                                          size_t fallbackSize,
243cb93a386Sopenharmony_ci                                          size_t alignment,
244cb93a386Sopenharmony_ci                                          sk_sp<const GrBuffer>* buffer,
245cb93a386Sopenharmony_ci                                          size_t* offset,
246cb93a386Sopenharmony_ci                                          size_t* actualSize) {
247cb93a386Sopenharmony_ci    VALIDATE();
248cb93a386Sopenharmony_ci
249cb93a386Sopenharmony_ci    SkASSERT(buffer);
250cb93a386Sopenharmony_ci    SkASSERT(offset);
251cb93a386Sopenharmony_ci    SkASSERT(actualSize);
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci    size_t usedBytes = (fBlocks.empty()) ? 0 : fBlocks.back().fBuffer->size() -
254cb93a386Sopenharmony_ci                                               fBlocks.back().fBytesFree;
255cb93a386Sopenharmony_ci    size_t pad = align_up_pad(usedBytes, alignment);
256cb93a386Sopenharmony_ci    if (fBlocks.empty() || (minSize + pad) > fBlocks.back().fBytesFree) {
257cb93a386Sopenharmony_ci        // We either don't have a block yet or the current block doesn't have enough free space.
258cb93a386Sopenharmony_ci        // Create a new one.
259cb93a386Sopenharmony_ci        if (!this->createBlock(fallbackSize)) {
260cb93a386Sopenharmony_ci            return nullptr;
261cb93a386Sopenharmony_ci        }
262cb93a386Sopenharmony_ci        usedBytes = 0;
263cb93a386Sopenharmony_ci        pad = 0;
264cb93a386Sopenharmony_ci    }
265cb93a386Sopenharmony_ci    SkASSERT(fBufferPtr);
266cb93a386Sopenharmony_ci
267cb93a386Sopenharmony_ci    // Consume padding first, to make subsequent alignment math easier
268cb93a386Sopenharmony_ci    memset(static_cast<char*>(fBufferPtr) + usedBytes, 0, pad);
269cb93a386Sopenharmony_ci    usedBytes += pad;
270cb93a386Sopenharmony_ci    fBlocks.back().fBytesFree -= pad;
271cb93a386Sopenharmony_ci    fBytesInUse += pad;
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ci    // Give caller all remaining space in this block (but aligned correctly)
274cb93a386Sopenharmony_ci    size_t size = align_down(fBlocks.back().fBytesFree, alignment);
275cb93a386Sopenharmony_ci    *offset = usedBytes;
276cb93a386Sopenharmony_ci    *buffer = fBlocks.back().fBuffer;
277cb93a386Sopenharmony_ci    *actualSize = size;
278cb93a386Sopenharmony_ci    fBlocks.back().fBytesFree -= size;
279cb93a386Sopenharmony_ci    fBytesInUse += size;
280cb93a386Sopenharmony_ci    VALIDATE();
281cb93a386Sopenharmony_ci    return static_cast<char*>(fBufferPtr) + usedBytes;
282cb93a386Sopenharmony_ci}
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_civoid GrBufferAllocPool::putBack(size_t bytes) {
285cb93a386Sopenharmony_ci    VALIDATE();
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ci    while (bytes) {
288cb93a386Sopenharmony_ci        // caller shouldn't try to put back more than they've taken
289cb93a386Sopenharmony_ci        SkASSERT(!fBlocks.empty());
290cb93a386Sopenharmony_ci        BufferBlock& block = fBlocks.back();
291cb93a386Sopenharmony_ci        size_t bytesUsed = block.fBuffer->size() - block.fBytesFree;
292cb93a386Sopenharmony_ci        if (bytes >= bytesUsed) {
293cb93a386Sopenharmony_ci            bytes -= bytesUsed;
294cb93a386Sopenharmony_ci            fBytesInUse -= bytesUsed;
295cb93a386Sopenharmony_ci            // if we locked a vb to satisfy the make space and we're releasing
296cb93a386Sopenharmony_ci            // beyond it, then unmap it.
297cb93a386Sopenharmony_ci            GrBuffer* buffer = block.fBuffer.get();
298cb93a386Sopenharmony_ci            if (!buffer->isCpuBuffer() && static_cast<GrGpuBuffer*>(buffer)->isMapped()) {
299cb93a386Sopenharmony_ci                UNMAP_BUFFER(block);
300cb93a386Sopenharmony_ci            }
301cb93a386Sopenharmony_ci            this->destroyBlock();
302cb93a386Sopenharmony_ci        } else {
303cb93a386Sopenharmony_ci            block.fBytesFree += bytes;
304cb93a386Sopenharmony_ci            fBytesInUse -= bytes;
305cb93a386Sopenharmony_ci            bytes = 0;
306cb93a386Sopenharmony_ci            break;
307cb93a386Sopenharmony_ci        }
308cb93a386Sopenharmony_ci    }
309cb93a386Sopenharmony_ci
310cb93a386Sopenharmony_ci    VALIDATE();
311cb93a386Sopenharmony_ci}
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_cibool GrBufferAllocPool::createBlock(size_t requestSize) {
314cb93a386Sopenharmony_ci    size_t size = std::max(requestSize, kDefaultBufferSize);
315cb93a386Sopenharmony_ci
316cb93a386Sopenharmony_ci    VALIDATE();
317cb93a386Sopenharmony_ci
318cb93a386Sopenharmony_ci    BufferBlock& block = fBlocks.push_back();
319cb93a386Sopenharmony_ci
320cb93a386Sopenharmony_ci    block.fBuffer = this->getBuffer(size);
321cb93a386Sopenharmony_ci    if (!block.fBuffer) {
322cb93a386Sopenharmony_ci        fBlocks.pop_back();
323cb93a386Sopenharmony_ci        return false;
324cb93a386Sopenharmony_ci    }
325cb93a386Sopenharmony_ci
326cb93a386Sopenharmony_ci    block.fBytesFree = block.fBuffer->size();
327cb93a386Sopenharmony_ci    if (fBufferPtr) {
328cb93a386Sopenharmony_ci        SkASSERT(fBlocks.count() > 1);
329cb93a386Sopenharmony_ci        BufferBlock& prev = fBlocks.fromBack(1);
330cb93a386Sopenharmony_ci        GrBuffer* buffer = prev.fBuffer.get();
331cb93a386Sopenharmony_ci        if (!buffer->isCpuBuffer()) {
332cb93a386Sopenharmony_ci            if (static_cast<GrGpuBuffer*>(buffer)->isMapped()) {
333cb93a386Sopenharmony_ci                UNMAP_BUFFER(prev);
334cb93a386Sopenharmony_ci            } else {
335cb93a386Sopenharmony_ci                this->flushCpuData(prev, prev.fBuffer->size() - prev.fBytesFree);
336cb93a386Sopenharmony_ci            }
337cb93a386Sopenharmony_ci        }
338cb93a386Sopenharmony_ci        fBufferPtr = nullptr;
339cb93a386Sopenharmony_ci    }
340cb93a386Sopenharmony_ci
341cb93a386Sopenharmony_ci    SkASSERT(!fBufferPtr);
342cb93a386Sopenharmony_ci
343cb93a386Sopenharmony_ci    // If the buffer is CPU-backed we "map" it because it is free to do so and saves a copy.
344cb93a386Sopenharmony_ci    // Otherwise when buffer mapping is supported we map if the buffer size is greater than the
345cb93a386Sopenharmony_ci    // threshold.
346cb93a386Sopenharmony_ci    if (block.fBuffer->isCpuBuffer()) {
347cb93a386Sopenharmony_ci        fBufferPtr = static_cast<GrCpuBuffer*>(block.fBuffer.get())->data();
348cb93a386Sopenharmony_ci        SkASSERT(fBufferPtr);
349cb93a386Sopenharmony_ci    } else {
350cb93a386Sopenharmony_ci        if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
351cb93a386Sopenharmony_ci            size > fGpu->caps()->bufferMapThreshold()) {
352cb93a386Sopenharmony_ci            fBufferPtr = static_cast<GrGpuBuffer*>(block.fBuffer.get())->map();
353cb93a386Sopenharmony_ci        }
354cb93a386Sopenharmony_ci    }
355cb93a386Sopenharmony_ci    if (!fBufferPtr) {
356cb93a386Sopenharmony_ci        this->resetCpuData(block.fBytesFree);
357cb93a386Sopenharmony_ci        fBufferPtr = fCpuStagingBuffer->data();
358cb93a386Sopenharmony_ci    }
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci    VALIDATE(true);
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ci    return true;
363cb93a386Sopenharmony_ci}
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_civoid GrBufferAllocPool::destroyBlock() {
366cb93a386Sopenharmony_ci    SkASSERT(!fBlocks.empty());
367cb93a386Sopenharmony_ci    SkASSERT(fBlocks.back().fBuffer->isCpuBuffer() ||
368cb93a386Sopenharmony_ci             !static_cast<GrGpuBuffer*>(fBlocks.back().fBuffer.get())->isMapped());
369cb93a386Sopenharmony_ci    fBlocks.pop_back();
370cb93a386Sopenharmony_ci    fBufferPtr = nullptr;
371cb93a386Sopenharmony_ci}
372cb93a386Sopenharmony_ci
373cb93a386Sopenharmony_civoid GrBufferAllocPool::resetCpuData(size_t newSize) {
374cb93a386Sopenharmony_ci    SkASSERT(newSize >= kDefaultBufferSize || !newSize);
375cb93a386Sopenharmony_ci    if (!newSize) {
376cb93a386Sopenharmony_ci        fCpuStagingBuffer.reset();
377cb93a386Sopenharmony_ci        return;
378cb93a386Sopenharmony_ci    }
379cb93a386Sopenharmony_ci    if (fCpuStagingBuffer && newSize <= fCpuStagingBuffer->size()) {
380cb93a386Sopenharmony_ci        return;
381cb93a386Sopenharmony_ci    }
382cb93a386Sopenharmony_ci    bool mustInitialize = fGpu->caps()->mustClearUploadedBufferData();
383cb93a386Sopenharmony_ci    fCpuStagingBuffer = fCpuBufferCache ? fCpuBufferCache->makeBuffer(newSize, mustInitialize)
384cb93a386Sopenharmony_ci                                        : GrCpuBuffer::Make(newSize);
385cb93a386Sopenharmony_ci}
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_civoid GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) {
388cb93a386Sopenharmony_ci    SkASSERT(block.fBuffer.get());
389cb93a386Sopenharmony_ci    SkASSERT(!block.fBuffer.get()->isCpuBuffer());
390cb93a386Sopenharmony_ci    GrGpuBuffer* buffer = static_cast<GrGpuBuffer*>(block.fBuffer.get());
391cb93a386Sopenharmony_ci    SkASSERT(!buffer->isMapped());
392cb93a386Sopenharmony_ci    SkASSERT(fCpuStagingBuffer && fCpuStagingBuffer->data() == fBufferPtr);
393cb93a386Sopenharmony_ci    SkASSERT(flushSize <= buffer->size());
394cb93a386Sopenharmony_ci    VALIDATE(true);
395cb93a386Sopenharmony_ci
396cb93a386Sopenharmony_ci    if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
397cb93a386Sopenharmony_ci        flushSize > fGpu->caps()->bufferMapThreshold()) {
398cb93a386Sopenharmony_ci        void* data = buffer->map();
399cb93a386Sopenharmony_ci        if (data) {
400cb93a386Sopenharmony_ci            memcpy(data, fBufferPtr, flushSize);
401cb93a386Sopenharmony_ci            UNMAP_BUFFER(block);
402cb93a386Sopenharmony_ci            return;
403cb93a386Sopenharmony_ci        }
404cb93a386Sopenharmony_ci    }
405cb93a386Sopenharmony_ci    buffer->updateData(fBufferPtr, flushSize);
406cb93a386Sopenharmony_ci    VALIDATE(true);
407cb93a386Sopenharmony_ci}
408cb93a386Sopenharmony_ci
409cb93a386Sopenharmony_cisk_sp<GrBuffer> GrBufferAllocPool::getBuffer(size_t size) {
410cb93a386Sopenharmony_ci    const GrCaps& caps = *fGpu->caps();
411cb93a386Sopenharmony_ci    auto resourceProvider = fGpu->getContext()->priv().resourceProvider();
412cb93a386Sopenharmony_ci    if (caps.preferClientSideDynamicBuffers() ||
413cb93a386Sopenharmony_ci        (fBufferType == GrGpuBufferType::kDrawIndirect && caps.useClientSideIndirectBuffers())) {
414cb93a386Sopenharmony_ci        // Create a CPU buffer.
415cb93a386Sopenharmony_ci        bool mustInitialize = caps.mustClearUploadedBufferData();
416cb93a386Sopenharmony_ci        return fCpuBufferCache ? fCpuBufferCache->makeBuffer(size, mustInitialize)
417cb93a386Sopenharmony_ci                               : GrCpuBuffer::Make(size);
418cb93a386Sopenharmony_ci    }
419cb93a386Sopenharmony_ci    return resourceProvider->createBuffer(size, fBufferType, kDynamic_GrAccessPattern);
420cb93a386Sopenharmony_ci}
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
423cb93a386Sopenharmony_ci
424cb93a386Sopenharmony_ciGrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu, sk_sp<CpuBufferCache> cpuBufferCache)
425cb93a386Sopenharmony_ci        : GrBufferAllocPool(gpu, GrGpuBufferType::kVertex, std::move(cpuBufferCache)) {}
426cb93a386Sopenharmony_ci
427cb93a386Sopenharmony_civoid* GrVertexBufferAllocPool::makeSpace(size_t vertexSize,
428cb93a386Sopenharmony_ci                                         int vertexCount,
429cb93a386Sopenharmony_ci                                         sk_sp<const GrBuffer>* buffer,
430cb93a386Sopenharmony_ci                                         int* startVertex) {
431cb93a386Sopenharmony_ci    SkASSERT(vertexCount >= 0);
432cb93a386Sopenharmony_ci    SkASSERT(buffer);
433cb93a386Sopenharmony_ci    SkASSERT(startVertex);
434cb93a386Sopenharmony_ci
435cb93a386Sopenharmony_ci    size_t offset SK_INIT_TO_AVOID_WARNING;
436cb93a386Sopenharmony_ci    void* ptr = INHERITED::makeSpace(SkSafeMath::Mul(vertexSize, vertexCount),
437cb93a386Sopenharmony_ci                                     vertexSize,
438cb93a386Sopenharmony_ci                                     buffer,
439cb93a386Sopenharmony_ci                                     &offset);
440cb93a386Sopenharmony_ci
441cb93a386Sopenharmony_ci    SkASSERT(0 == offset % vertexSize);
442cb93a386Sopenharmony_ci    *startVertex = static_cast<int>(offset / vertexSize);
443cb93a386Sopenharmony_ci    return ptr;
444cb93a386Sopenharmony_ci}
445cb93a386Sopenharmony_ci
446cb93a386Sopenharmony_civoid* GrVertexBufferAllocPool::makeSpaceAtLeast(size_t vertexSize, int minVertexCount,
447cb93a386Sopenharmony_ci                                                int fallbackVertexCount,
448cb93a386Sopenharmony_ci                                                sk_sp<const GrBuffer>* buffer, int* startVertex,
449cb93a386Sopenharmony_ci                                                int* actualVertexCount) {
450cb93a386Sopenharmony_ci    SkASSERT(minVertexCount >= 0);
451cb93a386Sopenharmony_ci    SkASSERT(fallbackVertexCount >= minVertexCount);
452cb93a386Sopenharmony_ci    SkASSERT(buffer);
453cb93a386Sopenharmony_ci    SkASSERT(startVertex);
454cb93a386Sopenharmony_ci    SkASSERT(actualVertexCount);
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_ci    size_t offset SK_INIT_TO_AVOID_WARNING;
457cb93a386Sopenharmony_ci    size_t actualSize SK_INIT_TO_AVOID_WARNING;
458cb93a386Sopenharmony_ci    void* ptr = INHERITED::makeSpaceAtLeast(SkSafeMath::Mul(vertexSize, minVertexCount),
459cb93a386Sopenharmony_ci                                            SkSafeMath::Mul(vertexSize, fallbackVertexCount),
460cb93a386Sopenharmony_ci                                            vertexSize,
461cb93a386Sopenharmony_ci                                            buffer,
462cb93a386Sopenharmony_ci                                            &offset,
463cb93a386Sopenharmony_ci                                            &actualSize);
464cb93a386Sopenharmony_ci
465cb93a386Sopenharmony_ci    SkASSERT(0 == offset % vertexSize);
466cb93a386Sopenharmony_ci    *startVertex = static_cast<int>(offset / vertexSize);
467cb93a386Sopenharmony_ci
468cb93a386Sopenharmony_ci    SkASSERT(0 == actualSize % vertexSize);
469cb93a386Sopenharmony_ci    SkASSERT(actualSize >= vertexSize * minVertexCount);
470cb93a386Sopenharmony_ci    *actualVertexCount = static_cast<int>(actualSize / vertexSize);
471cb93a386Sopenharmony_ci
472cb93a386Sopenharmony_ci    return ptr;
473cb93a386Sopenharmony_ci}
474cb93a386Sopenharmony_ci
475cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////
476cb93a386Sopenharmony_ci
477cb93a386Sopenharmony_ciGrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu, sk_sp<CpuBufferCache> cpuBufferCache)
478cb93a386Sopenharmony_ci        : GrBufferAllocPool(gpu, GrGpuBufferType::kIndex, std::move(cpuBufferCache)) {}
479cb93a386Sopenharmony_ci
480cb93a386Sopenharmony_civoid* GrIndexBufferAllocPool::makeSpace(int indexCount, sk_sp<const GrBuffer>* buffer,
481cb93a386Sopenharmony_ci                                        int* startIndex) {
482cb93a386Sopenharmony_ci    SkASSERT(indexCount >= 0);
483cb93a386Sopenharmony_ci    SkASSERT(buffer);
484cb93a386Sopenharmony_ci    SkASSERT(startIndex);
485cb93a386Sopenharmony_ci
486cb93a386Sopenharmony_ci    size_t offset SK_INIT_TO_AVOID_WARNING;
487cb93a386Sopenharmony_ci    void* ptr = INHERITED::makeSpace(SkSafeMath::Mul(indexCount, sizeof(uint16_t)),
488cb93a386Sopenharmony_ci                                     sizeof(uint16_t),
489cb93a386Sopenharmony_ci                                     buffer,
490cb93a386Sopenharmony_ci                                     &offset);
491cb93a386Sopenharmony_ci
492cb93a386Sopenharmony_ci    SkASSERT(0 == offset % sizeof(uint16_t));
493cb93a386Sopenharmony_ci    *startIndex = static_cast<int>(offset / sizeof(uint16_t));
494cb93a386Sopenharmony_ci    return ptr;
495cb93a386Sopenharmony_ci}
496cb93a386Sopenharmony_ci
497cb93a386Sopenharmony_civoid* GrIndexBufferAllocPool::makeSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
498cb93a386Sopenharmony_ci                                               sk_sp<const GrBuffer>* buffer, int* startIndex,
499cb93a386Sopenharmony_ci                                               int* actualIndexCount) {
500cb93a386Sopenharmony_ci    SkASSERT(minIndexCount >= 0);
501cb93a386Sopenharmony_ci    SkASSERT(fallbackIndexCount >= minIndexCount);
502cb93a386Sopenharmony_ci    SkASSERT(buffer);
503cb93a386Sopenharmony_ci    SkASSERT(startIndex);
504cb93a386Sopenharmony_ci    SkASSERT(actualIndexCount);
505cb93a386Sopenharmony_ci
506cb93a386Sopenharmony_ci    size_t offset SK_INIT_TO_AVOID_WARNING;
507cb93a386Sopenharmony_ci    size_t actualSize SK_INIT_TO_AVOID_WARNING;
508cb93a386Sopenharmony_ci    void* ptr = INHERITED::makeSpaceAtLeast(SkSafeMath::Mul(minIndexCount, sizeof(uint16_t)),
509cb93a386Sopenharmony_ci                                            SkSafeMath::Mul(fallbackIndexCount, sizeof(uint16_t)),
510cb93a386Sopenharmony_ci                                            sizeof(uint16_t),
511cb93a386Sopenharmony_ci                                            buffer,
512cb93a386Sopenharmony_ci                                            &offset,
513cb93a386Sopenharmony_ci                                            &actualSize);
514cb93a386Sopenharmony_ci
515cb93a386Sopenharmony_ci    SkASSERT(0 == offset % sizeof(uint16_t));
516cb93a386Sopenharmony_ci    *startIndex = static_cast<int>(offset / sizeof(uint16_t));
517cb93a386Sopenharmony_ci
518cb93a386Sopenharmony_ci    SkASSERT(0 == actualSize % sizeof(uint16_t));
519cb93a386Sopenharmony_ci    SkASSERT(actualSize >= minIndexCount * sizeof(uint16_t));
520cb93a386Sopenharmony_ci    *actualIndexCount = static_cast<int>(actualSize / sizeof(uint16_t));
521cb93a386Sopenharmony_ci    return ptr;
522cb93a386Sopenharmony_ci}
523