1984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson/*
2984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Copyright (C) 2014 The Android Open Source Project
3984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson *
4984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Licensed under the Apache License, Version 2.0 (the "License");
5984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * you may not use this file except in compliance with the License.
6984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * You may obtain a copy of the License at
7984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson *
8984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson *      http://www.apache.org/licenses/LICENSE-2.0
9984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson *
10984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Unless required by applicable law or agreed to in writing, software
11984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * distributed under the License is distributed on an "AS IS" BASIS,
12984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * See the License for the specific language governing permissions and
14984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * limitations under the License.
15984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson */
16984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
17984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#ifndef ANDROID_HWUI_CANVAS_STATE_H
18984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#define ANDROID_HWUI_CANVAS_STATE_H
19984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
20d9ee550888011a64fa3f35e666360ec8278597d8John Reck#include "Snapshot.h"
21d9ee550888011a64fa3f35e666360ec8278597d8John Reck
22984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include <SkMatrix.h>
23984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include <SkPath.h>
24984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include <SkRegion.h>
25984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
26984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonnamespace android {
27984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonnamespace uirenderer {
28984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
29984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson/**
30984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Abstract base class for any class containing CanvasState.
31984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Defines three mandatory callbacks.
32984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson */
33984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonclass CanvasStateClient {
34984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonpublic:
35984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    CanvasStateClient() { }
36984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    virtual ~CanvasStateClient() { }
37984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
38984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
39984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Callback allowing embedder to take actions in the middle of a
40984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * setViewport() call.
41984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
42984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    virtual void onViewportInitialized() = 0;
43984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
44984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
45984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Callback allowing embedder to take actions in the middle of a
46984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * restore() call.  May be called several times sequentially.
47984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
48984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) = 0;
49984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
50984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
51984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Allows subclasses to control what value is stored in snapshot's
52984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * fbo field in * initializeSaveStack.
53984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
546b109c74982033d4a220cd10a0eab8b024b351c9Chris Craik    virtual GLuint getTargetFbo() const = 0;
55984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
56984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // class CanvasStateClient
57984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
58984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson/**
59984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Implements Canvas state methods on behalf of Renderers.
60984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson *
61984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Manages the Snapshot stack, implementing matrix, save/restore, and clipping methods in the
62984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Renderer interface. Drawing and recording classes that include a CanvasState will have
63984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * different use cases:
64984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson *
65db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik * Drawing code maintaining canvas state (i.e. OpenGLRenderer) can query attributes (such as
66db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik * transform) or hook into changes (e.g. save/restore) with minimal surface area for manipulating
67db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik * the stack itself.
68984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson *
69db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik * Recording code maintaining canvas state (i.e. DisplayListCanvas) can both record and pass
70db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik * through state operations to CanvasState, so that not only will querying operations work
71db663fe83f976107fd8fd9307d871b37d9e47370Chris Craik * (getClip/Matrix), but so that quickRejection can also be used.
72984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson */
73984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
7464e445bf74bee2098781d608cedfd723d8cc88d3Chris Craikclass CanvasState {
75984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonpublic:
76984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    CanvasState(CanvasStateClient& renderer);
77d9ee550888011a64fa3f35e666360ec8278597d8John Reck    ~CanvasState();
78984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
79984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
80984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Initializes the first snapshot, computing the projection matrix,
81984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * and stores the dimensions of the render target.
82984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
83e4db79de127cfe961195f52907af8451026eaa20Chris Craik    void initializeRecordingSaveStack(int viewportWidth, int viewportHeight);
84e4db79de127cfe961195f52907af8451026eaa20Chris Craik
85e4db79de127cfe961195f52907af8451026eaa20Chris Craik    /**
86e4db79de127cfe961195f52907af8451026eaa20Chris Craik     * Initializes the first snapshot, computing the projection matrix,
87e4db79de127cfe961195f52907af8451026eaa20Chris Craik     * and stores the dimensions of the render target.
88e4db79de127cfe961195f52907af8451026eaa20Chris Craik     */
8964e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    void initializeSaveStack(int viewportWidth, int viewportHeight,
9064e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik            float clipLeft, float clipTop, float clipRight, float clipBottom,
91984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            const Vector3& lightCenter);
92984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
93984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool hasRectToRectTransform() const {
94984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        return CC_LIKELY(currentTransform()->rectToRect());
95984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    }
96984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
97984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Save (layer)
98984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getSaveCount() const { return mSaveCount; }
99984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int save(int flags);
100984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restore();
101984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restoreToCount(int saveCount);
102984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
103984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Save/Restore without side-effects
104984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int saveSnapshot(int flags);
105984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restoreSnapshot();
106984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
107984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Matrix
108984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void getMatrix(SkMatrix* outMatrix) const;
109984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void translate(float dx, float dy, float dz = 0.0f);
110984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void rotate(float degrees);
111984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void scale(float sx, float sy);
112984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void skew(float sx, float sy);
113984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
114984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setMatrix(const SkMatrix& matrix);
115984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setMatrix(const Matrix4& matrix); // internal only convenience method
116984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void concatMatrix(const SkMatrix& matrix);
117984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void concatMatrix(const Matrix4& matrix); // internal only convenience method
118984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
119984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Clip
120984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
121984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
122984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
123984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool quickRejectConservative(float left, float top, float right, float bottom) const;
124984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
125984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
126984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipPath(const SkPath* path, SkRegion::Op op);
127984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipRegion(const SkRegion* region, SkRegion::Op op);
128984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
129984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
130984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Sets a "clipping outline", which is independent from the regular clip.
131984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Currently only supports rectangles or rounded rectangles; passing in a
132984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * more complicated outline fails silently. Replaces any previous clipping
133984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * outline.
134984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
135984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
136984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setClippingRoundRect(LinearAllocator& allocator,
137984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            const Rect& rect, float radius, bool highPriority = true);
138fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path);
139984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
140984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
141984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Returns true if drawing in the rectangle (left, top, right, bottom)
142984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * will be clipped out. Is conservative: might return false when subpixel-
143984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * perfect tests would return true.
144984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
145984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
146984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
147984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
148984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setDirtyClip(bool opaque) { mDirtyClip = opaque; }
149984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool getDirtyClip() const { return mDirtyClip; }
150984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
151984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
152984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setEmpty(bool value) { mSnapshot->empty = value; }
153984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setInvisible(bool value) { mSnapshot->invisible = value; }
154984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
155984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
1566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    inline const Rect& currentRenderTargetClip() const { return currentSnapshot()->getRenderTargetClip(); }
157984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline Region* currentRegion() const { return currentSnapshot()->region; }
158984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline int currentFlags() const { return currentSnapshot()->flags; }
159984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
160984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); }
161984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
162984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
163a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    int getWidth() const { return mWidth; }
164a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    int getHeight() const { return mHeight; }
165a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); }
166984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
167d9ee550888011a64fa3f35e666360ec8278597d8John Reck    inline const Snapshot* currentSnapshot() const { return mSnapshot; }
168d9ee550888011a64fa3f35e666360ec8278597d8John Reck    inline Snapshot* writableSnapshot() { return mSnapshot; }
169d9ee550888011a64fa3f35e666360ec8278597d8John Reck    inline const Snapshot* firstSnapshot() const { return &mFirstSnapshot; }
170984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
171984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonprivate:
172d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* allocSnapshot(Snapshot* previous, int savecount);
173d9ee550888011a64fa3f35e666360ec8278597d8John Reck    void freeSnapshot(Snapshot* snapshot);
174d9ee550888011a64fa3f35e666360ec8278597d8John Reck    void freeAllSnapshots();
175d9ee550888011a64fa3f35e666360ec8278597d8John Reck
176984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// indicates that the clip has been changed since the last time it was consumed
177e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // TODO: delete when switching to HWUI_NEW_OPS
178984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool mDirtyClip;
179984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
180984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Dimensions of the drawing surface
181984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int mWidth, mHeight;
182984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
183984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Number of saved states
184984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int mSaveCount;
185984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
186984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Base state
187d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot mFirstSnapshot;
188984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
189984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Host providing callbacks
190984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    CanvasStateClient& mCanvas;
191984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
192984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Current state
193d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* mSnapshot;
194d9ee550888011a64fa3f35e666360ec8278597d8John Reck
195d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // Pool of allocated snapshots to re-use
196d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // NOTE: The dtors have already been invoked!
197d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* mSnapshotPool = nullptr;
198d9ee550888011a64fa3f35e666360ec8278597d8John Reck    int mSnapshotPoolCount = 0;
199984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
200984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // class CanvasState
201984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
202984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // namespace uirenderer
203984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // namespace android
204984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
205984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#endif // ANDROID_HWUI_CANVAS_STATE_H
206