xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrMeshBuffers.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2023 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrMeshBuffers.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMesh.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkMeshGanesh.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMeshPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDrawingManager.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpu.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuBuffer.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceCache.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrStagingBufferManager.h"
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
27*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
28*c8dee2aaSAndroid Build Coastguard Worker 
~GrMeshBuffer()29*c8dee2aaSAndroid Build Coastguard Worker template <typename Base, GrGpuBufferType Type> GrMeshBuffer<Base, Type>::~GrMeshBuffer() {
30*c8dee2aaSAndroid Build Coastguard Worker     GrResourceCache::ReturnResourceFromThread(std::move(fBuffer), fContextID);
31*c8dee2aaSAndroid Build Coastguard Worker }
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker template <typename Base, GrGpuBufferType Type>
Make(GrDirectContext * dc,const void * data,size_t size)34*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Base> GrMeshBuffer<Base, Type>::Make(GrDirectContext* dc, const void* data, size_t size) {
35*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(dc);
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrGpuBuffer> buffer = dc->priv().resourceProvider()->createBuffer(
38*c8dee2aaSAndroid Build Coastguard Worker             size,
39*c8dee2aaSAndroid Build Coastguard Worker             Type,
40*c8dee2aaSAndroid Build Coastguard Worker             kStatic_GrAccessPattern,
41*c8dee2aaSAndroid Build Coastguard Worker             data ? GrResourceProvider::ZeroInit::kNo : GrResourceProvider::ZeroInit::kYes);
42*c8dee2aaSAndroid Build Coastguard Worker     if (!buffer) {
43*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
44*c8dee2aaSAndroid Build Coastguard Worker     }
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker     if (data && !buffer->updateData(data, 0, size, /*preserve=*/false)) {
47*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
48*c8dee2aaSAndroid Build Coastguard Worker     }
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker     auto result = new GrMeshBuffer;
51*c8dee2aaSAndroid Build Coastguard Worker     result->fBuffer = std::move(buffer);
52*c8dee2aaSAndroid Build Coastguard Worker     result->fContextID = dc->directContextID();
53*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<Base>(result);
54*c8dee2aaSAndroid Build Coastguard Worker }
55*c8dee2aaSAndroid Build Coastguard Worker 
56*c8dee2aaSAndroid Build Coastguard Worker template <typename Base, GrGpuBufferType Type>
onUpdate(GrDirectContext * dc,const void * data,size_t offset,size_t size)57*c8dee2aaSAndroid Build Coastguard Worker bool GrMeshBuffer<Base, Type>::onUpdate(GrDirectContext* dc,
58*c8dee2aaSAndroid Build Coastguard Worker                                         const void* data,
59*c8dee2aaSAndroid Build Coastguard Worker                                         size_t offset,
60*c8dee2aaSAndroid Build Coastguard Worker                                         size_t size) {
61*c8dee2aaSAndroid Build Coastguard Worker     if (!dc || dc != fBuffer->getContext()) {
62*c8dee2aaSAndroid Build Coastguard Worker         return false;
63*c8dee2aaSAndroid Build Coastguard Worker     }
64*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!dc->abandoned());  // If dc is abandoned then fBuffer->getContext() should be null.
65*c8dee2aaSAndroid Build Coastguard Worker 
66*c8dee2aaSAndroid Build Coastguard Worker     if (!dc->priv().caps()->transferFromBufferToBufferSupport()) {
67*c8dee2aaSAndroid Build Coastguard Worker         auto ownedData = SkData::MakeWithCopy(data, size);
68*c8dee2aaSAndroid Build Coastguard Worker         dc->priv().drawingManager()->newBufferUpdateTask(
69*c8dee2aaSAndroid Build Coastguard Worker                 std::move(ownedData), fBuffer, offset);
70*c8dee2aaSAndroid Build Coastguard Worker         return true;
71*c8dee2aaSAndroid Build Coastguard Worker     }
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrGpuBuffer> tempBuffer;
74*c8dee2aaSAndroid Build Coastguard Worker     size_t tempOffset = 0;
75*c8dee2aaSAndroid Build Coastguard Worker     if (auto* sbm = dc->priv().getGpu()->stagingBufferManager()) {
76*c8dee2aaSAndroid Build Coastguard Worker         auto alignment = dc->priv().caps()->transferFromBufferToBufferAlignment();
77*c8dee2aaSAndroid Build Coastguard Worker         auto [sliceBuffer, sliceOffset, ptr] = sbm->allocateStagingBufferSlice(size, alignment);
78*c8dee2aaSAndroid Build Coastguard Worker         if (sliceBuffer) {
79*c8dee2aaSAndroid Build Coastguard Worker             std::memcpy(ptr, data, size);
80*c8dee2aaSAndroid Build Coastguard Worker             tempBuffer.reset(SkRef(sliceBuffer));
81*c8dee2aaSAndroid Build Coastguard Worker             tempOffset = sliceOffset;
82*c8dee2aaSAndroid Build Coastguard Worker         }
83*c8dee2aaSAndroid Build Coastguard Worker     }
84*c8dee2aaSAndroid Build Coastguard Worker 
85*c8dee2aaSAndroid Build Coastguard Worker     if (!tempBuffer) {
86*c8dee2aaSAndroid Build Coastguard Worker         tempBuffer = dc->priv().resourceProvider()->createBuffer(size,
87*c8dee2aaSAndroid Build Coastguard Worker                                                                  GrGpuBufferType::kXferCpuToGpu,
88*c8dee2aaSAndroid Build Coastguard Worker                                                                  kDynamic_GrAccessPattern,
89*c8dee2aaSAndroid Build Coastguard Worker                                                                  GrResourceProvider::ZeroInit::kNo);
90*c8dee2aaSAndroid Build Coastguard Worker         if (!tempBuffer) {
91*c8dee2aaSAndroid Build Coastguard Worker             return false;
92*c8dee2aaSAndroid Build Coastguard Worker         }
93*c8dee2aaSAndroid Build Coastguard Worker         if (!tempBuffer->updateData(data, 0, size, /*preserve=*/false)) {
94*c8dee2aaSAndroid Build Coastguard Worker             return false;
95*c8dee2aaSAndroid Build Coastguard Worker         }
96*c8dee2aaSAndroid Build Coastguard Worker     }
97*c8dee2aaSAndroid Build Coastguard Worker 
98*c8dee2aaSAndroid Build Coastguard Worker     dc->priv().drawingManager()->newBufferTransferTask(
99*c8dee2aaSAndroid Build Coastguard Worker             std::move(tempBuffer), tempOffset, fBuffer, offset, size);
100*c8dee2aaSAndroid Build Coastguard Worker 
101*c8dee2aaSAndroid Build Coastguard Worker     return true;
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker 
104*c8dee2aaSAndroid Build Coastguard Worker namespace SkMeshes {
MakeIndexBuffer(GrDirectContext * dc,const void * data,size_t size)105*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMesh::IndexBuffer> MakeIndexBuffer(GrDirectContext* dc, const void* data, size_t size) {
106*c8dee2aaSAndroid Build Coastguard Worker     if (!dc) {
107*c8dee2aaSAndroid Build Coastguard Worker         // Fallback to a CPU buffer.
108*c8dee2aaSAndroid Build Coastguard Worker         return MakeIndexBuffer(data, size);
109*c8dee2aaSAndroid Build Coastguard Worker     }
110*c8dee2aaSAndroid Build Coastguard Worker     return SkMeshPriv::GaneshIndexBuffer::Make(dc, data, size);
111*c8dee2aaSAndroid Build Coastguard Worker }
112*c8dee2aaSAndroid Build Coastguard Worker 
CopyIndexBuffer(GrDirectContext * dc,sk_sp<SkMesh::IndexBuffer> src)113*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMesh::IndexBuffer> CopyIndexBuffer(GrDirectContext* dc, sk_sp<SkMesh::IndexBuffer> src) {
114*c8dee2aaSAndroid Build Coastguard Worker     if (!src) {
115*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
116*c8dee2aaSAndroid Build Coastguard Worker     }
117*c8dee2aaSAndroid Build Coastguard Worker     auto* ib = static_cast<SkMeshPriv::IB*>(src.get());
118*c8dee2aaSAndroid Build Coastguard Worker     const void* data = ib->peek();
119*c8dee2aaSAndroid Build Coastguard Worker     if (!data) {
120*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
121*c8dee2aaSAndroid Build Coastguard Worker     }
122*c8dee2aaSAndroid Build Coastguard Worker     if (!dc) {
123*c8dee2aaSAndroid Build Coastguard Worker         return MakeIndexBuffer(data, ib->size());
124*c8dee2aaSAndroid Build Coastguard Worker     }
125*c8dee2aaSAndroid Build Coastguard Worker     return MakeIndexBuffer(dc, data, ib->size());
126*c8dee2aaSAndroid Build Coastguard Worker }
127*c8dee2aaSAndroid Build Coastguard Worker 
MakeVertexBuffer(GrDirectContext * dc,const void * data,size_t size)128*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMesh::VertexBuffer> MakeVertexBuffer(GrDirectContext* dc, const void* data, size_t size) {
129*c8dee2aaSAndroid Build Coastguard Worker     if (!dc) {
130*c8dee2aaSAndroid Build Coastguard Worker         return MakeVertexBuffer(data, size);
131*c8dee2aaSAndroid Build Coastguard Worker     }
132*c8dee2aaSAndroid Build Coastguard Worker     return SkMeshPriv::GaneshVertexBuffer::Make(dc, data, size);
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker 
CopyVertexBuffer(GrDirectContext * dc,sk_sp<SkMesh::VertexBuffer> src)135*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMesh::VertexBuffer> CopyVertexBuffer(GrDirectContext* dc, sk_sp<SkMesh::VertexBuffer> src) {
136*c8dee2aaSAndroid Build Coastguard Worker     if (!src) {
137*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
138*c8dee2aaSAndroid Build Coastguard Worker     }
139*c8dee2aaSAndroid Build Coastguard Worker     auto* vb = static_cast<SkMeshPriv::VB*>(src.get());
140*c8dee2aaSAndroid Build Coastguard Worker     const void* data = vb->peek();
141*c8dee2aaSAndroid Build Coastguard Worker     if (!data) {
142*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
143*c8dee2aaSAndroid Build Coastguard Worker     }
144*c8dee2aaSAndroid Build Coastguard Worker     if (!dc) {
145*c8dee2aaSAndroid Build Coastguard Worker         return MakeVertexBuffer(data, vb->size());
146*c8dee2aaSAndroid Build Coastguard Worker     }
147*c8dee2aaSAndroid Build Coastguard Worker     return MakeVertexBuffer(dc, data, vb->size());
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker }  // namespace SkMeshes
150