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