blob: 0b217788ec60bc29bddff10eb17eab2def45eb41 [file] [log] [blame]
Robert Phillipsa3457b82018-03-08 11:30:12 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/gpu/GrContext.h"
Robert Phillips576b6a12019-12-06 13:05:49 -05009#include "src/core/SkLRUCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/GrCaps.h"
11#include "src/gpu/GrContextPriv.h"
12#include "src/gpu/GrContextThreadSafeProxyPriv.h"
Robert Phillips576b6a12019-12-06 13:05:49 -050013#include "src/gpu/GrProgramDesc.h"
14#include "src/gpu/GrProgramInfo.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040015#include "src/gpu/GrSkSLFPFactoryCache.h"
Robert Phillips7f11fb52019-12-03 13:35:19 -050016#include "src/gpu/effects/GrSkSLFP.h"
Robert Phillipsa3457b82018-03-08 11:30:12 -050017
18/**
19 * The DDL Context is the one in effect during DDL Recording. It isn't backed by a GrGPU and
20 * cannot allocate any GPU resources.
21 */
Jim Van Verth861ac612019-11-27 09:41:43 -050022class GrDDLContext final : public GrContext {
Robert Phillipsa3457b82018-03-08 11:30:12 -050023public:
24 GrDDLContext(sk_sp<GrContextThreadSafeProxy> proxy)
Robert Phillipsc1541ae2019-02-04 12:05:37 -050025 : INHERITED(proxy->backend(), proxy->priv().options(), proxy->priv().contextID()) {
Robert Phillipsa3457b82018-03-08 11:30:12 -050026 fThreadSafeProxy = std::move(proxy);
27 }
28
Brian Salomon161c8ed2019-11-27 09:12:47 -050029 ~GrDDLContext() override {}
Robert Phillipsa3457b82018-03-08 11:30:12 -050030
Brian Salomon161c8ed2019-11-27 09:12:47 -050031 void abandonContext() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050032 SkASSERT(0); // abandoning in a DDL Recorder doesn't make a whole lot of sense
33 INHERITED::abandonContext();
34 }
35
Brian Salomon161c8ed2019-11-27 09:12:47 -050036 void releaseResourcesAndAbandonContext() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050037 SkASSERT(0); // abandoning in a DDL Recorder doesn't make a whole lot of sense
38 INHERITED::releaseResourcesAndAbandonContext();
39 }
40
Brian Salomon161c8ed2019-11-27 09:12:47 -050041 void freeGpuResources() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050042 SkASSERT(0); // freeing resources in a DDL Recorder doesn't make a whole lot of sense
43 INHERITED::freeGpuResources();
44 }
45
Robert Phillips933484f2019-11-26 09:38:55 -050046private:
Robert Phillipsa41c6852019-02-07 10:44:10 -050047 // TODO: Here we're pretending this isn't derived from GrContext. Switch this to be derived from
48 // GrRecordingContext!
Brian Salomon161c8ed2019-11-27 09:12:47 -050049 GrContext* asDirectContext() override { return nullptr; }
Robert Phillipsa41c6852019-02-07 10:44:10 -050050
Brian Salomon161c8ed2019-11-27 09:12:47 -050051 bool init(sk_sp<const GrCaps> caps, sk_sp<GrSkSLFPFactoryCache> FPFactoryCache) override {
Robert Phillipsbb606772019-02-04 17:50:57 -050052 SkASSERT(caps && FPFactoryCache);
Robert Phillipsa3457b82018-03-08 11:30:12 -050053 SkASSERT(fThreadSafeProxy); // should've been set in the ctor
54
Robert Phillipsbb606772019-02-04 17:50:57 -050055 if (!INHERITED::init(std::move(caps), std::move(FPFactoryCache))) {
Robert Phillipsa3457b82018-03-08 11:30:12 -050056 return false;
57 }
58
Greg Danielf41b2bd2019-08-22 16:19:24 -040059 // DDL contexts/drawing managers always sort the oplists and attempt to reduce opsTask
Robert Phillips6db27c22019-05-01 10:43:56 -040060 // splitting.
61 this->setupDrawingManager(true, true);
Robert Phillips56181ba2019-03-08 12:00:45 -050062
Robert Phillipsbb606772019-02-04 17:50:57 -050063 SkASSERT(this->caps());
64
Robert Phillipsa3457b82018-03-08 11:30:12 -050065 return true;
66 }
67
Brian Salomon161c8ed2019-11-27 09:12:47 -050068 GrAtlasManager* onGetAtlasManager() override {
Robert Phillipsa3457b82018-03-08 11:30:12 -050069 SkASSERT(0); // the DDL Recorders should never invoke this
70 return nullptr;
71 }
72
Robert Phillips576b6a12019-12-06 13:05:49 -050073 // Add to the set of unique program infos required by this DDL
74 void recordProgramInfo(const GrProgramInfo* programInfo) final {
75 const GrCaps* caps = this->caps();
76
77 if (this->backend() == GrBackendApi::kVulkan) {
78 // Currently, Vulkan requires a live renderTarget to compute the key
79 return;
80 }
81
82 if (programInfo->requestedFeatures() & GrProcessor::CustomFeatures::kSampleLocations) {
83 // Sample locations require a live renderTarget to compute the key
84 return;
85 }
86
87 GrProgramDesc desc = caps->makeDesc(nullptr, *programInfo);
88 if (desc.isValid()) {
89 return;
90 }
91
92 fProgramInfoMap.add(desc, programInfo);
93 }
94
95 void detachProgramInfos(SkTDArray<const GrProgramInfo*>* dst) final {
96 SkASSERT(dst->isEmpty());
97
98 fProgramInfoMap.toArray(dst);
99 }
100
101
102private:
103 class ProgramInfoMap : public ::SkNoncopyable {
104 typedef const GrProgramInfo* CacheValue;
105
106 public:
107 // All the programInfo data should be stored in the record-time arena so there is no
108 // need to ref them here or to delete them in the destructor.
109 ProgramInfoMap() : fMap(10) {}
110 ~ProgramInfoMap() {}
111
112 void add(const GrProgramDesc& desc, const GrProgramInfo* programInfo) {
113 SkASSERT(desc.isValid());
114
115 const CacheValue* preExisting = fMap.find(desc);
116 if (preExisting) {
117 return;
118 }
119
120 fMap.insert(desc, programInfo);
121 }
122
123 void toArray(SkTDArray<const GrProgramInfo*>* dst) {
124 fMap.foreach([dst](CacheValue* programInfo) {
125 dst->push_back(*programInfo);
126 });
127 }
128
129 private:
130 struct DescHash {
131 uint32_t operator()(const GrProgramDesc& desc) const {
132 return SkOpts::hash_fn(desc.asKey(), desc.keyLength(), 0);
133 }
134 };
135
136 SkLRUCache<GrProgramDesc, CacheValue, DescHash> fMap;
137 };
138
139 ProgramInfoMap fProgramInfoMap;
140
Robert Phillipsa3457b82018-03-08 11:30:12 -0500141 typedef GrContext INHERITED;
142};
143
Kevin Lubickb5502b22018-03-12 10:17:06 -0400144sk_sp<GrContext> GrContextPriv::MakeDDL(const sk_sp<GrContextThreadSafeProxy>& proxy) {
Robert Phillipsa3457b82018-03-08 11:30:12 -0500145 sk_sp<GrContext> context(new GrDDLContext(proxy));
146
Robert Phillipsbb606772019-02-04 17:50:57 -0500147 if (!context->init(proxy->priv().refCaps(), proxy->priv().fpFactoryCache())) {
Robert Phillipsa3457b82018-03-08 11:30:12 -0500148 return nullptr;
149 }
150 return context;
151}