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