1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef RENDER_SERVICE_CLIENT_CORE_PIPELINE_RS_PAINT_FILTER_CANVAS_H
17 #define RENDER_SERVICE_CLIENT_CORE_PIPELINE_RS_PAINT_FILTER_CANVAS_H
18 
19 #include <optional>
20 #include <stack>
21 #include <vector>
22 
23 #include "draw/canvas.h"
24 #include "draw/surface.h"
25 
26 #include "common/rs_color.h"
27 #include "common/rs_macros.h"
28 #include "screen_manager/screen_types.h"
29 #include "surface_type.h"
30 #include "utils/region.h"
31 
32 namespace OHOS {
33 namespace Rosen {
34 
35 class RSB_EXPORT RSPaintFilterCanvasBase : public Drawing::Canvas {
36 public:
37     RSPaintFilterCanvasBase(Drawing::Canvas* canvas);
38     ~RSPaintFilterCanvasBase() override = default;
39 
40     Drawing::Matrix GetTotalMatrix() const override;
41 
42     Drawing::Rect GetLocalClipBounds() const override;
43 
44     Drawing::RectI GetDeviceClipBounds() const override;
45 
46     Drawing::RectI GetRoundInDeviceClipBounds() const override;
47 
48     uint32_t GetSaveCount() const override;
49 
50 #ifdef RS_ENABLE_GPU
51     std::shared_ptr<Drawing::GPUContext> GetGPUContext() override;
52 #endif
53 
54     void DrawSdf(const Drawing::SDFShapeBase& shape) override;
55     void DrawPoint(const Drawing::Point& point) override;
56     void DrawPoints(Drawing::PointMode mode, size_t count, const Drawing::Point pts[]) override;
57     void DrawLine(const Drawing::Point& startPt, const Drawing::Point& endPt) override;
58     void DrawRect(const Drawing::Rect& rect) override;
59     void DrawRoundRect(const Drawing::RoundRect& roundRect) override;
60     void DrawNestedRoundRect(const Drawing::RoundRect& outer, const Drawing::RoundRect& inner) override;
61     void DrawArc(const Drawing::Rect& oval, Drawing::scalar startAngle, Drawing::scalar sweepAngle) override;
62     void DrawPie(const Drawing::Rect& oval, Drawing::scalar startAngle, Drawing::scalar sweepAngle) override;
63     void DrawOval(const Drawing::Rect& oval) override;
64     void DrawCircle(const Drawing::Point& centerPt, Drawing::scalar radius) override;
65     void DrawPath(const Drawing::Path& path) override;
66     void DrawBackground(const Drawing::Brush& brush) override;
67     void DrawShadow(const Drawing::Path& path, const Drawing::Point3& planeParams,
68         const Drawing::Point3& devLightPos, Drawing::scalar lightRadius,
69         Drawing::Color ambientColor, Drawing::Color spotColor, Drawing::ShadowFlags flag) override;
70     void DrawShadowStyle(const Drawing::Path& path, const Drawing::Point3& planeParams,
71         const Drawing::Point3& devLightPos, Drawing::scalar lightRadius,
72         Drawing::Color ambientColor, Drawing::Color spotColor, Drawing::ShadowFlags flag,
73         bool isLimitElevation) override;
74     void DrawColor(Drawing::ColorQuad color, Drawing::BlendMode mode = Drawing::BlendMode::SRC_OVER) override;
75     void DrawRegion(const Drawing::Region& region) override;
76     void DrawPatch(const Drawing::Point cubics[12], const Drawing::ColorQuad colors[4],
77         const Drawing::Point texCoords[4], Drawing::BlendMode mode) override;
78     void DrawVertices(const Drawing::Vertices& vertices, Drawing::BlendMode mode) override;
79 
80     void DrawImageNine(const Drawing::Image* image, const Drawing::RectI& center, const Drawing::Rect& dst,
81         Drawing::FilterMode filter, const Drawing::Brush* brush = nullptr) override;
82     void DrawImageLattice(const Drawing::Image* image, const Drawing::Lattice& lattice, const Drawing::Rect& dst,
83         Drawing::FilterMode filter) override;
84 
85     bool OpCalculateBefore(const Drawing::Matrix& matrix) override;
86     std::shared_ptr<Drawing::OpListHandle> OpCalculateAfter(const Drawing::Rect& bound) override;
87 
88     void DrawAtlas(const Drawing::Image* atlas, const Drawing::RSXform xform[], const Drawing::Rect tex[],
89         const Drawing::ColorQuad colors[], int count, Drawing::BlendMode mode,
90         const Drawing::SamplingOptions& sampling, const Drawing::Rect* cullRect) override;
91     void DrawBitmap(const Drawing::Bitmap& bitmap, const Drawing::scalar px, const Drawing::scalar py) override;
92     void DrawImage(const Drawing::Image& image,
93         const Drawing::scalar px, const Drawing::scalar py, const Drawing::SamplingOptions& sampling) override;
94     void DrawImageRect(const Drawing::Image& image, const Drawing::Rect& src, const Drawing::Rect& dst,
95         const Drawing::SamplingOptions& sampling, Drawing::SrcRectConstraint constraint) override;
96     void DrawImageRect(const Drawing::Image& image,
97         const Drawing::Rect& dst, const Drawing::SamplingOptions& sampling) override;
98     void DrawPicture(const Drawing::Picture& picture) override;
99     void DrawTextBlob(const Drawing::TextBlob* blob, const Drawing::scalar x, const Drawing::scalar y) override;
100 
101     void ClipRect(const Drawing::Rect& rect, Drawing::ClipOp op = Drawing::ClipOp::INTERSECT,
102         bool doAntiAlias = false) override;
103     void ClipIRect(const Drawing::RectI& rect, Drawing::ClipOp op = Drawing::ClipOp::INTERSECT) override;
104     void ClipRoundRect(const Drawing::RoundRect& roundRect, Drawing::ClipOp op = Drawing::ClipOp::INTERSECT,
105         bool doAntiAlias = false) override;
106     void ClipRoundRect(const Drawing::Rect& rect, std::vector<Drawing::Point>& pts, bool doAntiAlias = false) override;
107     void ClipPath(const Drawing::Path& path, Drawing::ClipOp op = Drawing::ClipOp::INTERSECT,
108         bool doAntiAlias = false) override;
109     void ClipRegion(const Drawing::Region& region, Drawing::ClipOp op = Drawing::ClipOp::INTERSECT) override;
110 
111     void SetMatrix(const Drawing::Matrix& matrix) override;
112     void ResetMatrix() override;
113     void ConcatMatrix(const Drawing::Matrix& matrix) override;
114     void Translate(Drawing::scalar dx, Drawing::scalar dy) override;
115     void Scale(Drawing::scalar sx, Drawing::scalar sy) override;
116     void Rotate(Drawing::scalar deg, Drawing::scalar sx, Drawing::scalar sy) override;
117     void Shear(Drawing::scalar sx, Drawing::scalar sy) override;
118 
119     void Flush() override;
120     void Clear(Drawing::ColorQuad color) override;
121     uint32_t Save() override;
122     void SaveLayer(const Drawing::SaveLayerOps& saveLayerOps) override;
123     void Restore() override;
124     void Discard() override;
125 
126     CoreCanvas& AttachPen(const Drawing::Pen& pen) override;
127     CoreCanvas& AttachBrush(const Drawing::Brush& brush) override;
128     CoreCanvas& AttachPaint(const Drawing::Paint& paint) override;
129     CoreCanvas& DetachPen() override;
130     CoreCanvas& DetachBrush() override;
131     CoreCanvas& DetachPaint() override;
132 
133     bool DrawBlurImage(const Drawing::Image& image, const Drawing::HpsBlurParameter& blurParams) override;
134     std::array<int, 2> CalcHpsBluredImageDimension(const Drawing::HpsBlurParameter& blurParams) override;
135 
136 protected:
137     virtual bool OnFilter() const = 0;
138     virtual bool OnFilterWithBrush(Drawing::Brush& brush) const = 0;
139     virtual Drawing::Brush* GetFilteredBrush() const = 0;
140     Drawing::Canvas* canvas_ = nullptr;
141 };
142 
143 // This class is used to filter the paint before drawing. currently, it is used to filter the alpha and foreground
144 // color.
145 class RSB_EXPORT RSPaintFilterCanvas : public RSPaintFilterCanvasBase {
146 public:
147     RSPaintFilterCanvas(Drawing::Canvas* canvas, float alpha = 1.0f);
148     RSPaintFilterCanvas(Drawing::Surface* surface, float alpha = 1.0f);
149     ~RSPaintFilterCanvas() override = default;;
150 
151     void CopyConfigurationToOffscreenCanvas(const RSPaintFilterCanvas& other);
152     void PushDirtyRegion(Drawing::Region& resultRegion);
153     void PopDirtyRegion();
154     bool IsDirtyRegionStackEmpty();
155     Drawing::Region& GetCurDirtyRegion();
156 
157     // alpha related
158     void MultiplyAlpha(float alpha);
159     void SetAlpha(float alpha);
160     float GetAlpha() const override;
161     int SaveAlpha();
162     void RestoreAlpha();
163     int GetAlphaSaveCount() const override;
164     void RestoreAlphaToCount(int count);
165 
166     // env related
167     void SetEnvForegroundColor(Color color);
168     Drawing::ColorQuad GetEnvForegroundColor() const override;
169     int SaveEnv();
170     void RestoreEnv();
171     int GetEnvSaveCount() const;
172     void RestoreEnvToCount(int count);
173 
174     // blendmode and blender related
175     void SaveLayer(const Drawing::SaveLayerOps& saveLayerOps) override;
176     void SetBlendMode(std::optional<int> blendMode);
177     void SetBlender(std::shared_ptr<Drawing::Blender>);
178     bool HasOffscreenLayer() const;
179 
180     // save/restore utils
181     struct SaveStatus {
182         int canvasSaveCount = -1;
183         int alphaSaveCount = -1;
184         int envSaveCount = -1;
185     };
186     enum SaveType : uint8_t {
187         kNone           = 0x0,
188         kCanvas         = 0x1,
189         kAlpha          = 0x2,
190         kEnv            = 0x4,
191         kCanvasAndAlpha = kCanvas | kAlpha,
192         kAll            = kCanvas | kAlpha | kEnv,
193     };
194 
195     SaveStatus SaveAllStatus(SaveType type = kAll);
196     SaveStatus GetSaveStatus() const;
197     void RestoreStatus(const SaveStatus& status);
198 
199     Drawing::Surface* GetSurface() const override;
200 
201     // high contrast
202     void SetHighContrast(bool enabled);
203     bool isHighContrastEnabled() const override;
204 
205     using CacheType = Drawing::CacheType;
206     // cache
207     void SetCacheType(CacheType type);
208     Drawing::CacheType GetCacheType() const override;
209 
210     // visible rect
211     void SetVisibleRect(Drawing::Rect visibleRect);
212     Drawing::Rect GetVisibleRect() const;
213 
214     static std::optional<Drawing::Rect> GetLocalClipBounds(const Drawing::Canvas& canvas,
215         const Drawing::RectI* clipBounds = nullptr);
216 
217     CoreCanvas& AttachPen(const Drawing::Pen& pen) override;
218     CoreCanvas& AttachBrush(const Drawing::Brush& brush) override;
219     CoreCanvas& AttachPaint(const Drawing::Paint& paint) override;
220 
221     void SetParallelThreadIdx(uint32_t idx);
222     uint32_t GetParallelThreadIdx() const;
223     void SetIsParallelCanvas(bool isParallel);
224     bool GetIsParallelCanvas() const;
225 
226     void SetDisableFilterCache(bool disable);
227     bool GetDisableFilterCache() const;
228 
229     void SetRecordDrawable(bool enable);
230     bool GetRecordDrawable() const;
231 
232     // effect cache data relate
233     struct CachedEffectData {
234         CachedEffectData() = default;
235         CachedEffectData(std::shared_ptr<Drawing::Image>&& image, const Drawing::RectI& rect);
236         ~CachedEffectData() = default;
237         std::shared_ptr<Drawing::Image> cachedImage_ = nullptr;
238         Drawing::RectI cachedRect_ = {};
239         Drawing::Matrix cachedMatrix_ = Drawing::Matrix();
240     };
241     void SetEffectData(const std::shared_ptr<CachedEffectData>& effectData);
242     const std::shared_ptr<CachedEffectData>& GetEffectData() const;
243     // behind window cache relate
244     void SetBehindWindowData(const std::shared_ptr<CachedEffectData>& behindWindowData);
245     const std::shared_ptr<CachedEffectData>& GetBehindWindowData() const;
246 
247     // for foregroundFilter to store offscreen canvas & surface
248     struct OffscreenData {
249         std::shared_ptr<Drawing::Surface> offscreenSurface_ = nullptr;
250         std::shared_ptr<RSPaintFilterCanvas> offscreenCanvas_ = nullptr;
251     };
252     // for foregroundFilter to store and restore offscreen canvas & surface
253     void ReplaceMainScreenData(std::shared_ptr<Drawing::Surface>& offscreenSurface,
254         std::shared_ptr<RSPaintFilterCanvas>& offscreenCanvas);
255     void SwapBackMainScreenData();
256     void SavePCanvasList();
257     void RestorePCanvasList();
258 
259     // canvas status relate
260     struct CanvasStatus {
261         float alpha_;
262         Drawing::Matrix matrix_;
263         std::shared_ptr<CachedEffectData> effectData_;
264     };
265     CanvasStatus GetCanvasStatus() const;
266     void SetCanvasStatus(const CanvasStatus& status);
267     Drawing::Canvas* GetRecordingCanvas() const override;
268     bool GetRecordingState() const override;
269     void SetRecordingState(bool flag) override;
270 
GetOffscreenDataList()271     const std::stack<OffscreenData>& GetOffscreenDataList() const
272     {
273         return offscreenDataList_;
274     }
275 
StoreCanvas()276     void StoreCanvas()
277     {
278         if (storeMainCanvas_ == nullptr) {
279             storeMainCanvas_ = canvas_;
280         }
281     }
282 
GetOriginalCanvas()283     Drawing::Canvas* GetOriginalCanvas()
284     {
285         return storeMainCanvas_;
286     }
287 
GetDrawingType()288     Drawing::DrawingType GetDrawingType() const override
289     {
290         return Drawing::DrawingType::PAINT_FILTER;
291     }
292     bool IsCapture() const;
293     void SetCapture(bool isCapture);
294     ScreenId GetScreenId() const;
295     void SetScreenId(ScreenId screenId);
296     GraphicColorGamut GetTargetColorGamut() const;
297     void SetTargetColorGamut(GraphicColorGamut colorGamut);
298     float GetBrightnessRatio() const;
299     void SetBrightnessRatio(float brightnessRatio);
300     void CopyHDRConfiguration(const RSPaintFilterCanvas& other);
301 
302 protected:
303     using Env = struct {
304         Color envForegroundColor_;
305         std::shared_ptr<CachedEffectData> effectData_;
306         std::shared_ptr<CachedEffectData> behindWindowData_;
307         std::shared_ptr<Drawing::Blender> blender_;
308         bool hasOffscreenLayer_;
309     };
310 
311     bool OnFilter() const override;
OnFilterWithBrush(Drawing::Brush & brush)312     inline bool OnFilterWithBrush(Drawing::Brush& brush) const override
313     {
314         float alpha = alphaStack_.top();
315         // foreground color and foreground color strategy identification
316         if (brush.GetColor().CastToColorQuad() == 0x00000001) {
317             brush.SetColor(envStack_.top().envForegroundColor_.AsArgbInt());
318         }
319 
320         // use alphaStack_.top() to multiply alpha
321         if (alpha < 1 && alpha > 0) {
322             brush.SetAlpha(brush.GetAlpha() * alpha);
323         }
324         return alpha > 0.f;
325     }
GetFilteredBrush()326     inline Drawing::Brush* GetFilteredBrush() const override
327     {
328         static Drawing::Brush brush;
329         float alpha = alphaStack_.top();
330         if (alpha >= 1) {
331             return nullptr;
332         }
333         brush.SetAlphaF(alpha);
334         return &brush;
335     }
336 
337 private:
338     Drawing::Surface* surface_ = nullptr;
339     std::stack<float> alphaStack_;
340     std::stack<Env> envStack_;
341 
342     // save every dirty region of the current surface for quick reject
343     std::stack<Drawing::Region> dirtyRegionStack_;
344 
345     // greater than 0 indicates canvas currently is drawing on a new layer created offscreen blendmode
346     // std::stack<bool> blendOffscreenStack_;
347 
348     // foregroundFilter related
349     std::vector<std::vector<Canvas*>> storedPCanvasList_; // store pCanvasList_
350     std::stack<OffscreenData> offscreenDataList_; // store offscreen canvas & surface
351     std::stack<Drawing::Surface*> storeMainScreenSurface_; // store surface_
352     std::stack<Drawing::Canvas*> storeMainScreenCanvas_; // store canvas_
353     Drawing::Canvas* storeMainCanvas_ = nullptr; // store main canvas
354 
355     std::atomic_bool isHighContrastEnabled_ { false };
356     CacheType cacheType_ { RSPaintFilterCanvas::CacheType::UNDEFINED };
357     Drawing::Rect visibleRect_ = Drawing::Rect();
358 
359     GraphicColorGamut targetColorGamut_ = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
360     float brightnessRatio_ = 1.0f; // Default 1.0f means no discount
361     ScreenId screenId_ = INVALID_SCREEN_ID;
362 
363     uint32_t threadIndex_ = UNI_RENDER_THREAD_INDEX; // default
364     bool isParallelCanvas_ = false;
365     bool disableFilterCache_ = false;
366     bool recordingState_ = false;
367     bool recordDrawable_ = false;
368     bool isCapture_ = false;
369 };
370 
371 // Helper class similar to SkAutoCanvasRestore, but also restores alpha and/or env
372 class RSB_EXPORT RSAutoCanvasRestore {
373 public:
374     /** Preserves canvas save count. Optionally call SkCanvas::save() and/or RSPaintFilterCanvas::SaveAlpha() and/or
375        RSPaintFilterCanvas::SaveEnv().
376         @param canvas     RSPaintFilterCanvas to guard
377         @param saveCanvas call SkCanvas::save()
378         @param saveAlpha  call RSPaintFilterCanvas::SaveAlpha()
379         @return           utility to restore RSPaintFilterCanvas state on destructor
380     */
381     RSAutoCanvasRestore(
382         RSPaintFilterCanvas* canvas, RSPaintFilterCanvas::SaveType type = RSPaintFilterCanvas::SaveType::kAll)
383         : canvas_(canvas), saveCount_(canvas ? canvas->SaveAllStatus(type) : RSPaintFilterCanvas::SaveStatus())
384     {}
385 
386     /** Allow RSAutoCanvasRestore to be used with std::unique_ptr and std::shared_ptr */
387     RSAutoCanvasRestore(const std::unique_ptr<RSPaintFilterCanvas>& canvas,
388         RSPaintFilterCanvas::SaveType type = RSPaintFilterCanvas::SaveType::kAll)
389         : RSAutoCanvasRestore(canvas.get(), type)
390     {}
391     RSAutoCanvasRestore(const std::shared_ptr<RSPaintFilterCanvas>& canvas,
392         RSPaintFilterCanvas::SaveType type = RSPaintFilterCanvas::SaveType::kAll)
393         : RSAutoCanvasRestore(canvas.get(), type)
394     {}
395 
396     RSAutoCanvasRestore(RSAutoCanvasRestore&&) = delete;
397     RSAutoCanvasRestore(const RSAutoCanvasRestore&) = delete;
398     RSAutoCanvasRestore& operator=(RSAutoCanvasRestore&&) = delete;
399     RSAutoCanvasRestore& operator=(const RSAutoCanvasRestore&) = delete;
400 
401     /** Restores RSPaintFilterCanvas to saved state. Destructor is called when container goes out of
402         scope.
403     */
~RSAutoCanvasRestore()404     ~RSAutoCanvasRestore()
405     {
406         if (canvas_) {
407             canvas_->RestoreStatus(saveCount_);
408         }
409     }
410 
411     /** Restores RSPaintFilterCanvas to saved state immediately. Subsequent calls and
412         ~RSAutoCanvasRestore() have no effect.
413     */
restore()414     void restore()
415     {
416         if (canvas_) {
417             canvas_->RestoreStatus(saveCount_);
418             canvas_ = nullptr;
419         }
420     }
421 
422 private:
423     RSPaintFilterCanvas* canvas_ = nullptr;
424     RSPaintFilterCanvas::SaveStatus saveCount_;
425 };
426 } // namespace Rosen
427 } // namespace OHOS
428 #endif // RENDER_SERVICE_CLIENT_CORE_PIPELINE_RS_PAINT_FILTER_CANVAS_H
429