1 /*
2 * Copyright 2021 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 "experimental/graphite/src/DrawContext.h"
9
10 #include "include/private/SkColorData.h"
11
12 #include "experimental/graphite/src/CommandBuffer.h"
13 #include "experimental/graphite/src/DrawList.h"
14 #include "experimental/graphite/src/DrawPass.h"
15 #include "experimental/graphite/src/RenderPassTask.h"
16 #include "experimental/graphite/src/TextureProxy.h"
17 #include "experimental/graphite/src/geom/BoundsManager.h"
18 #include "experimental/graphite/src/geom/Shape.h"
19
20 namespace skgpu {
21
Make(sk_sp<TextureProxy> target,sk_sp<SkColorSpace> colorSpace,SkColorType colorType,SkAlphaType alphaType)22 sk_sp<DrawContext> DrawContext::Make(sk_sp<TextureProxy> target,
23 sk_sp<SkColorSpace> colorSpace,
24 SkColorType colorType,
25 SkAlphaType alphaType) {
26 if (!target) {
27 return nullptr;
28 }
29
30 // TODO: validate that the color type and alpha type are compatible with the target's info
31 SkImageInfo imageInfo = SkImageInfo::Make(target->dimensions(),
32 colorType,
33 alphaType,
34 std::move(colorSpace));
35 return sk_sp<DrawContext>(new DrawContext(std::move(target), imageInfo));
36 }
37
DrawContext(sk_sp<TextureProxy> target,const SkImageInfo & ii)38 DrawContext::DrawContext(sk_sp<TextureProxy> target, const SkImageInfo& ii)
39 : fTarget(std::move(target))
40 , fImageInfo(ii)
41 , fPendingDraws(std::make_unique<DrawList>()) {
42 // TBD - Will probably want DrawLists (and its internal commands) to come from an arena
43 // that the DC manages.
44 }
45
~DrawContext()46 DrawContext::~DrawContext() {
47 // If the DC is destroyed and there are pending commands, they won't be drawn.
48 fPendingDraws.reset();
49 fDrawPasses.clear();
50 }
51
stencilAndFillPath(const Transform & localToDevice,const Shape & shape,const Clip & clip,DrawOrder order,const PaintParams * paint)52 void DrawContext::stencilAndFillPath(const Transform& localToDevice,
53 const Shape& shape,
54 const Clip& clip,
55 DrawOrder order,
56 const PaintParams* paint) {
57 SkASSERT(SkIRect::MakeSize(fTarget->dimensions()).contains(clip.scissor()));
58 fPendingDraws->stencilAndFillPath(localToDevice, shape, clip, order,paint);
59 }
60
fillConvexPath(const Transform & localToDevice,const Shape & shape,const Clip & clip,DrawOrder order,const PaintParams * paint)61 void DrawContext::fillConvexPath(const Transform& localToDevice,
62 const Shape& shape,
63 const Clip& clip,
64 DrawOrder order,
65 const PaintParams* paint) {
66 SkASSERT(SkIRect::MakeSize(fTarget->dimensions()).contains(clip.scissor()));
67 fPendingDraws->fillConvexPath(localToDevice, shape, clip, order, paint);
68 }
69
strokePath(const Transform & localToDevice,const Shape & shape,const StrokeParams & stroke,const Clip & clip,DrawOrder order,const PaintParams * paint)70 void DrawContext::strokePath(const Transform& localToDevice,
71 const Shape& shape,
72 const StrokeParams& stroke,
73 const Clip& clip,
74 DrawOrder order,
75 const PaintParams* paint) {
76 SkASSERT(SkIRect::MakeSize(fTarget->dimensions()).contains(clip.scissor()));
77 fPendingDraws->strokePath(localToDevice, shape, stroke, clip, order, paint);
78 }
79
clear(const SkColor4f & clearColor)80 void DrawContext::clear(const SkColor4f& clearColor) {
81 fPendingLoadOp = LoadOp::kClear;
82 SkPMColor4f pmColor = clearColor.premul();
83 fPendingClearColor = pmColor.array();
84
85 // a fullscreen clear will overwrite anything that came before, so start a new DrawList
86 // and clear any drawpasses that haven't been snapped yet
87 fPendingDraws = std::make_unique<DrawList>();
88 fDrawPasses.clear();
89 }
90
snapDrawPass(Recorder * recorder,const BoundsManager * occlusionCuller)91 void DrawContext::snapDrawPass(Recorder* recorder, const BoundsManager* occlusionCuller) {
92 if (fPendingDraws->drawCount() == 0) {
93 return;
94 }
95
96 auto pass = DrawPass::Make(recorder, std::move(fPendingDraws), fTarget,
97 std::make_pair(fPendingLoadOp, fPendingStoreOp), fPendingClearColor,
98 occlusionCuller);
99 fDrawPasses.push_back(std::move(pass));
100 fPendingDraws = std::make_unique<DrawList>();
101 fPendingLoadOp = LoadOp::kLoad;
102 fPendingStoreOp = StoreOp::kStore;
103 }
104
snapRenderPassTask(Recorder * recorder,const BoundsManager * occlusionCuller)105 sk_sp<Task> DrawContext::snapRenderPassTask(Recorder* recorder,
106 const BoundsManager* occlusionCuller) {
107 this->snapDrawPass(recorder, occlusionCuller);
108 if (fDrawPasses.empty()) {
109 return nullptr;
110 }
111
112 // TODO: At this point we would determine all the targets used by the drawPasses,
113 // build up the union of them and store them in the RenderPassDesc. However, for
114 // the moment we should have only one drawPass.
115 SkASSERT(fDrawPasses.size() == 1);
116 RenderPassDesc desc;
117 desc.fColorAttachment.fTextureProxy = sk_ref_sp(fDrawPasses[0]->target());
118 std::tie(desc.fColorAttachment.fLoadOp, desc.fColorAttachment.fStoreOp) = fDrawPasses[0]->ops();
119 desc.fClearColor = fDrawPasses[0]->clearColor();
120
121 return RenderPassTask::Make(std::move(fDrawPasses), desc);
122 }
123
124 } // namespace skgpu
125