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