CanvasState.h revision d9ee550888011a64fa3f35e666360ec8278597d8
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     */
8364e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    void initializeSaveStack(int viewportWidth, int viewportHeight,
8464e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik            float clipLeft, float clipTop, float clipRight, float clipBottom,
85984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            const Vector3& lightCenter);
86984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
87984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool hasRectToRectTransform() const {
88984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        return CC_LIKELY(currentTransform()->rectToRect());
89984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    }
90984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
91984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Save (layer)
92984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getSaveCount() const { return mSaveCount; }
93984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int save(int flags);
94984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restore();
95984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restoreToCount(int saveCount);
96984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
97984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Save/Restore without side-effects
98984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int saveSnapshot(int flags);
99984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restoreSnapshot();
100984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
101984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Matrix
102984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void getMatrix(SkMatrix* outMatrix) const;
103984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void translate(float dx, float dy, float dz = 0.0f);
104984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void rotate(float degrees);
105984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void scale(float sx, float sy);
106984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void skew(float sx, float sy);
107984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
108984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setMatrix(const SkMatrix& matrix);
109984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setMatrix(const Matrix4& matrix); // internal only convenience method
110984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void concatMatrix(const SkMatrix& matrix);
111984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void concatMatrix(const Matrix4& matrix); // internal only convenience method
112984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
113984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Clip
114984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
115984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
116984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
117984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool quickRejectConservative(float left, float top, float right, float bottom) const;
118984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
119984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
120984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipPath(const SkPath* path, SkRegion::Op op);
121984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipRegion(const SkRegion* region, SkRegion::Op op);
122984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
123984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
124984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Sets a "clipping outline", which is independent from the regular clip.
125984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Currently only supports rectangles or rounded rectangles; passing in a
126984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * more complicated outline fails silently. Replaces any previous clipping
127984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * outline.
128984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
129984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
130984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setClippingRoundRect(LinearAllocator& allocator,
131984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            const Rect& rect, float radius, bool highPriority = true);
132fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path);
133984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
134984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
135984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Returns true if drawing in the rectangle (left, top, right, bottom)
136984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * will be clipped out. Is conservative: might return false when subpixel-
137984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * perfect tests would return true.
138984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
139984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
140984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
141984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
142984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setDirtyClip(bool opaque) { mDirtyClip = opaque; }
143984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool getDirtyClip() const { return mDirtyClip; }
144984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
145984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
146984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setEmpty(bool value) { mSnapshot->empty = value; }
147984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setInvisible(bool value) { mSnapshot->invisible = value; }
148984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
149984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
150487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    inline const Rect& currentClipRect() const { return currentSnapshot()->getClipRect(); }
151984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline Region* currentRegion() const { return currentSnapshot()->region; }
152984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline int currentFlags() const { return currentSnapshot()->flags; }
153984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
154984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); }
155984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
156984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
157a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    int getWidth() const { return mWidth; }
158a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    int getHeight() const { return mHeight; }
159a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); }
160984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
161d9ee550888011a64fa3f35e666360ec8278597d8John Reck    inline const Snapshot* currentSnapshot() const { return mSnapshot; }
162d9ee550888011a64fa3f35e666360ec8278597d8John Reck    inline Snapshot* writableSnapshot() { return mSnapshot; }
163d9ee550888011a64fa3f35e666360ec8278597d8John Reck    inline const Snapshot* firstSnapshot() const { return &mFirstSnapshot; }
164984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
165984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonprivate:
166d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* allocSnapshot(Snapshot* previous, int savecount);
167d9ee550888011a64fa3f35e666360ec8278597d8John Reck    void freeSnapshot(Snapshot* snapshot);
168d9ee550888011a64fa3f35e666360ec8278597d8John Reck    void freeAllSnapshots();
169d9ee550888011a64fa3f35e666360ec8278597d8John Reck
170984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// indicates that the clip has been changed since the last time it was consumed
171984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool mDirtyClip;
172984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
173984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Dimensions of the drawing surface
174984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int mWidth, mHeight;
175984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
176984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Number of saved states
177984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int mSaveCount;
178984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
179984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Base state
180d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot mFirstSnapshot;
181984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
182984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Host providing callbacks
183984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    CanvasStateClient& mCanvas;
184984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
185984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Current state
186d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* mSnapshot;
187d9ee550888011a64fa3f35e666360ec8278597d8John Reck
188d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // Pool of allocated snapshots to re-use
189d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // NOTE: The dtors have already been invoked!
190d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* mSnapshotPool = nullptr;
191d9ee550888011a64fa3f35e666360ec8278597d8John Reck    int mSnapshotPoolCount = 0;
192984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
193984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // class CanvasState
194984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
195984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // namespace uirenderer
196984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // namespace android
197984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
198984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#endif // ANDROID_HWUI_CANVAS_STATE_H
199