CanvasState.h revision fca52b7583d1e5f5ff8ed06554875d2a30ef56fa
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
20984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include <SkMatrix.h>
21984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include <SkPath.h>
22984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include <SkRegion.h>
23984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
24984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include "Snapshot.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
74f59b8f0d7c9fe24253a1d9e85f59601d244ec978Dan Albertclass ANDROID_API CanvasState {
75984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonpublic:
76984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    CanvasState(CanvasStateClient& renderer);
77984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    ~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     */
83984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom,
84984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            const Vector3& lightCenter);
85984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
86984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setViewport(int width, int height);
87984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
88984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool hasRectToRectTransform() const {
89984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        return CC_LIKELY(currentTransform()->rectToRect());
90984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    }
91984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
92984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Save (layer)
93984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getSaveCount() const { return mSaveCount; }
94984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int save(int flags);
95984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restore();
96984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restoreToCount(int saveCount);
97984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
98984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Save/Restore without side-effects
99984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int saveSnapshot(int flags);
100984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void restoreSnapshot();
101984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
102984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Matrix
103984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void getMatrix(SkMatrix* outMatrix) const;
104984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void translate(float dx, float dy, float dz = 0.0f);
105984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void rotate(float degrees);
106984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void scale(float sx, float sy);
107984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void skew(float sx, float sy);
108984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
109984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setMatrix(const SkMatrix& matrix);
110984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setMatrix(const Matrix4& matrix); // internal only convenience method
111984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void concatMatrix(const SkMatrix& matrix);
112984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void concatMatrix(const Matrix4& matrix); // internal only convenience method
113984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
114984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    // Clip
115984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
116984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
117984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
118984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool quickRejectConservative(float left, float top, float right, float bottom) const;
119984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
120984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
121984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipPath(const SkPath* path, SkRegion::Op op);
122984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool clipRegion(const SkRegion* region, SkRegion::Op op);
123984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
124984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
125984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Sets a "clipping outline", which is independent from the regular clip.
126984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Currently only supports rectangles or rounded rectangles; passing in a
127984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * more complicated outline fails silently. Replaces any previous clipping
128984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * outline.
129984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
130984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
131984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setClippingRoundRect(LinearAllocator& allocator,
132984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            const Rect& rect, float radius, bool highPriority = true);
133fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    void setProjectionPathMask(LinearAllocator& allocator, const SkPath* path);
134984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
135984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /**
136984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * Returns true if drawing in the rectangle (left, top, right, bottom)
137984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * will be clipped out. Is conservative: might return false when subpixel-
138984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     * perfect tests would return true.
139984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson     */
140984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
141984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson            bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const;
142984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
143984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setDirtyClip(bool opaque) { mDirtyClip = opaque; }
144984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool getDirtyClip() const { return mDirtyClip; }
145984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
146984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
147984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setEmpty(bool value) { mSnapshot->empty = value; }
148984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    void setInvisible(bool value) { mSnapshot->invisible = value; }
149984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
150984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
151487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    inline const Rect& currentClipRect() const { return currentSnapshot()->getClipRect(); }
152984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline Region* currentRegion() const { return currentSnapshot()->region; }
153984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline int currentFlags() const { return currentSnapshot()->flags; }
154984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
155984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); }
156984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
157984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
158984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getWidth() { return mWidth; }
159984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int getHeight() { return mHeight; }
160984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
161984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline const Snapshot* currentSnapshot() const {
162e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik        return mSnapshot != nullptr ? mSnapshot.get() : mFirstSnapshot.get();
163984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    }
164984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline Snapshot* writableSnapshot() { return mSnapshot.get(); }
165984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    inline const Snapshot* firstSnapshot() const { return mFirstSnapshot.get(); }
166984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
167984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonprivate:
168984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// No default constructor - must supply a CanvasStateClient (mCanvas).
169984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    CanvasState();
170984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
171984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// indicates that the clip has been changed since the last time it was consumed
172984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    bool mDirtyClip;
173984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
174984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Dimensions of the drawing surface
175984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int mWidth, mHeight;
176984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
177984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Number of saved states
178984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    int mSaveCount;
179984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
180984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Base state
181984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    sp<Snapshot> mFirstSnapshot;
182984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
183984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Host providing callbacks
184984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    CanvasStateClient& mCanvas;
185984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
186984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    /// Current state
187984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    sp<Snapshot> mSnapshot;
188984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
189984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // class CanvasState
190984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
191984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // namespace uirenderer
192984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson}; // namespace android
193984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
194984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#endif // ANDROID_HWUI_CANVAS_STATE_H
195