xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrDDLContext.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2018 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 "include/core/SkRefCnt.h"
9 #include "include/gpu/ganesh/GrContextThreadSafeProxy.h"
10 #include "include/gpu/ganesh/GrRecordingContext.h"
11 #include "include/gpu/ganesh/GrTypes.h"
12 #include "include/private/base/SkAssert.h"
13 #include "include/private/base/SkNoncopyable.h"
14 #include "include/private/base/SkTArray.h"
15 #include "src/core/SkChecksum.h"
16 #include "src/core/SkLRUCache.h"
17 #include "src/gpu/ganesh/GrCaps.h"
18 #include "src/gpu/ganesh/GrProgramDesc.h"
19 #include "src/gpu/ganesh/GrRecordingContextPriv.h"
20 
21 #include <cstdint>
22 #include <memory>
23 #include <utility>
24 
25 class GrProgramInfo;
26 
27 using namespace skia_private;
28 
29 /**
30  * The DDL Context is the one in effect during DDL Recording. It isn't backed by a GrGPU and
31  * cannot allocate any GPU resources.
32  */
33 class GrDDLContext final : public GrRecordingContext {
34 public:
GrDDLContext(sk_sp<GrContextThreadSafeProxy> proxy)35     GrDDLContext(sk_sp<GrContextThreadSafeProxy> proxy)
36         : INHERITED(std::move(proxy), true) {
37     }
38 
~GrDDLContext()39     ~GrDDLContext() override {}
40 
abandonContext()41     void abandonContext() override {
42         SkASSERT(0); // abandoning in a DDL Recorder doesn't make a whole lot of sense
43         INHERITED::abandonContext();
44     }
45 
46 private:
47     // Add to the set of unique program infos required by this DDL
recordProgramInfo(const GrProgramInfo * programInfo)48     void recordProgramInfo(const GrProgramInfo* programInfo) final {
49         if (!programInfo) {
50             return;
51         }
52 
53         const GrCaps* caps = this->caps();
54 
55         if (this->backend() == GrBackendApi::kMetal || this->backend() == GrBackendApi::kDirect3D) {
56             // Currently Metal and Direct3D require a live renderTarget to compute the key
57             return;
58         }
59 
60         GrProgramDesc desc = caps->makeDesc(nullptr, *programInfo);
61         if (!desc.isValid()) {
62             return;
63         }
64 
65         fProgramInfoMap.add(desc, programInfo);
66     }
67 
detachProgramData(TArray<ProgramData> * dst)68     void detachProgramData(TArray<ProgramData>* dst) final {
69         SkASSERT(dst->empty());
70 
71         fProgramInfoMap.toArray(dst);
72     }
73 
74 
75 private:
76     class ProgramInfoMap : public ::SkNoncopyable {
77         typedef const GrProgramDesc  CacheKey;
78         typedef const GrProgramInfo* CacheValue;
79 
80     public:
81         // All the programInfo data should be stored in the record-time arena so there is no
82         // need to ref them here or to delete them in the destructor.
ProgramInfoMap()83         ProgramInfoMap() : fMap(10) {}
~ProgramInfoMap()84         ~ProgramInfoMap() {}
85 
86         // TODO: this is doing a lot of reallocating of the ProgramDesc! Once the program descs
87         // are allocated in the record-time area there won't be a problem.
add(CacheKey & desc,const GrProgramInfo * programInfo)88         void add(CacheKey& desc, const GrProgramInfo* programInfo) {
89             SkASSERT(desc.isValid());
90 
91             const CacheValue* preExisting = fMap.find(desc);
92             if (preExisting) {
93                 return;
94             }
95 
96             fMap.insert(desc, programInfo);
97         }
98 
toArray(TArray<ProgramData> * dst)99         void toArray(TArray<ProgramData>* dst) {
100             fMap.foreach([dst](CacheKey* programDesc, CacheValue* programInfo) {
101                              // TODO: remove this allocation once the program descs are stored
102                              // in the record-time arena.
103                              dst->emplace_back(std::make_unique<const GrProgramDesc>(*programDesc),
104                                                *programInfo);
105                          });
106         }
107 
108     private:
109         struct DescHash {
operator ()GrDDLContext::ProgramInfoMap::DescHash110             uint32_t operator()(CacheKey& desc) const {
111                 return SkChecksum::Hash32(desc.asKey(), desc.keyLength());
112             }
113         };
114 
115         SkLRUCache<CacheKey, CacheValue, DescHash> fMap;
116     };
117 
118     ProgramInfoMap fProgramInfoMap;
119 
120     using INHERITED = GrRecordingContext;
121 };
122 
MakeDDL(sk_sp<GrContextThreadSafeProxy> proxy)123 sk_sp<GrRecordingContext> GrRecordingContextPriv::MakeDDL(sk_sp<GrContextThreadSafeProxy> proxy) {
124     sk_sp<GrRecordingContext> context(new GrDDLContext(std::move(proxy)));
125 
126     if (!context->init()) {
127         return nullptr;
128     }
129     return context;
130 }
131