2014-04-15 09:50:16 -07:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
2016-07-06 16:10:09 -07:00
|
|
|
|
|
|
|
#pragma once
|
2014-04-15 09:50:16 -07:00
|
|
|
|
2018-09-21 14:30:19 -07:00
|
|
|
#include "Properties.h"
|
2018-09-26 11:21:08 -07:00
|
|
|
#include "utils/Macros.h"
|
2014-06-18 14:21:29 -07:00
|
|
|
|
2014-04-15 09:50:16 -07:00
|
|
|
#include <utils/Timers.h>
|
Do not cache AVDs that are off screen
Bug: 128805564
Test: Manual + systrace; hwui_unit_tests; CtsUiRenderingTestCases
Only update a VectorDrawable's cache if it is onscreen. This fixes a
Twitter use case where the app has a ProgressBar that is exactly one
pixel offscreen. Prior to this CL, we repeatedly drew the ProgressBar's
AVD to a GPU surface, even though we clip it out later and never draw
that GPU surface. Now, we recognize that the AVD is outside of the
bounds of the screen, so we never draw to the GPU surface.
TreeInfo:
- store the size of the screen, retrieved from
CanvasContext::getNextFrameSize.
SkiaDisplayList:
- Store the matrix at the time of recording a VectorDrawable. Concat
that with the current matrix to determine whether the VD is on screen,
based on the TreeInfo. If it is offscreen, do not add it to the list
of AVDs that need to be updated ahead of rendering.
- In addition, if it is offscreen (or not dirty), do not call
setPropertyChangeWillBeConsumed(true). This prevents triggering
dispatchFrameCallbacks to update on the RenderThread when there is no
need to. This also mimics what would happen if the View/RenderNode had
been completely offscreen.
- Add a method to append an AVD to mVectorDrawables. Now that the vector
is of Pairs, this simplifies the call sites. Add a second helper to
just add an AVD without a matrix, for use in tests.
SkiaRecordingCanvas:
- get the current matrix and store it in the display list along with the
AVD.
CanvasContext:
- add getNextFrameSize, for reporting the size of the next frame without
dequeuing it
VectorDrawable.cpp:
- call quickReject to potentially short circuit drawing. This is for a
hypothetical use case (verified in a test app) where the containing
RenderNode is partially onscreen, but the AVD itself is not. Even
without the change to VectorDrawable.cpp, we skip uploading to the GPU
cache, the SkiaDisplayList still attempts to draw it. This change
keeps us from drawing it at all.
SkiaDisplayListTests.cpp:
- Now that I've hidden mVectorDrawables, call the new public APIs.
- prepareListAndChildren test
- for the clean VD, assert that getPropertyChangeWillBeConsumed
returns FALSE. This is due to the behavior change that we do not
set it unless the VD is dirty.
- set the bounds, so our onscreen check works.
- Add another test for prepareListAndChildren, which puts VDs offscreen.
Change-Id: Iae0a07adcf58e7884e0854720de644e7b2faf2bf
2019-04-03 15:09:25 -04:00
|
|
|
#include "SkSize.h"
|
2014-04-15 09:50:16 -07:00
|
|
|
|
2015-10-28 16:50:44 -07:00
|
|
|
#include <string>
|
2014-06-03 15:53:15 -07:00
|
|
|
|
2014-04-15 09:50:16 -07:00
|
|
|
namespace android {
|
|
|
|
namespace uirenderer {
|
|
|
|
|
2014-08-28 15:35:53 -07:00
|
|
|
namespace renderthread {
|
|
|
|
class CanvasContext;
|
|
|
|
}
|
|
|
|
|
2014-10-15 15:46:42 -04:00
|
|
|
class DamageAccumulator;
|
2015-10-28 16:50:44 -07:00
|
|
|
class LayerUpdateQueue;
|
2016-03-25 14:29:48 -07:00
|
|
|
class RenderNode;
|
2014-06-23 13:13:08 -07:00
|
|
|
class RenderState;
|
2014-04-15 09:50:16 -07:00
|
|
|
|
2014-06-18 14:21:29 -07:00
|
|
|
class ErrorHandler {
|
|
|
|
public:
|
|
|
|
virtual void onError(const std::string& message) = 0;
|
2017-11-03 10:12:19 -07:00
|
|
|
|
2018-09-26 11:21:08 -07:00
|
|
|
virtual ~ErrorHandler() = default;
|
2014-06-18 14:21:29 -07:00
|
|
|
};
|
|
|
|
|
2016-03-25 14:29:48 -07:00
|
|
|
class TreeObserver {
|
|
|
|
public:
|
|
|
|
// Called when a RenderNode's parent count hits 0.
|
|
|
|
// Due to the unordered nature of tree pushes, once prepareTree
|
|
|
|
// is finished it is possible that the node was "resurrected" and has
|
|
|
|
// a non-zero parent count.
|
2017-01-25 10:58:30 -08:00
|
|
|
virtual void onMaybeRemovedFromTree(RenderNode* node) = 0;
|
2017-11-03 10:12:19 -07:00
|
|
|
|
2016-03-25 14:29:48 -07:00
|
|
|
protected:
|
2018-09-26 11:21:08 -07:00
|
|
|
virtual ~TreeObserver() = default;
|
2016-03-25 14:29:48 -07:00
|
|
|
};
|
|
|
|
|
2014-06-03 15:53:15 -07:00
|
|
|
// This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN
|
|
|
|
class TreeInfo {
|
|
|
|
PREVENT_COPY_AND_ASSIGN(TreeInfo);
|
2017-11-03 10:12:19 -07:00
|
|
|
|
2014-06-03 15:53:15 -07:00
|
|
|
public:
|
|
|
|
enum TraversalMode {
|
|
|
|
// The full monty - sync, push, run animators, etc... Used by DrawFrameTask
|
|
|
|
// May only be used if both the UI thread and RT thread are blocked on the
|
|
|
|
// prepare
|
|
|
|
MODE_FULL,
|
|
|
|
// Run only what can be done safely on RT thread. Currently this only means
|
|
|
|
// animators, but potentially things like SurfaceTexture updates
|
|
|
|
// could be handled by this as well if there are no listeners
|
|
|
|
MODE_RT_ONLY,
|
|
|
|
};
|
|
|
|
|
2018-09-26 11:21:08 -07:00
|
|
|
TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContext);
|
2014-06-24 15:34:58 -07:00
|
|
|
|
2015-08-28 07:10:31 -07:00
|
|
|
TraversalMode mode;
|
2014-06-03 15:53:15 -07:00
|
|
|
// TODO: Remove this? Currently this is used to signal to stop preparing
|
|
|
|
// textures if we run out of cache space.
|
2014-04-15 09:50:16 -07:00
|
|
|
bool prepareTextures;
|
2015-10-28 15:55:40 -07:00
|
|
|
renderthread::CanvasContext& canvasContext;
|
2014-08-21 11:23:05 -07:00
|
|
|
// TODO: buildLayer uses this to suppress running any animations, but this
|
|
|
|
// should probably be refactored somehow. The reason this is done is
|
|
|
|
// because buildLayer is not setup for injecting the animationHook, as well
|
|
|
|
// as this being otherwise wasted work as all the animators will be
|
|
|
|
// re-evaluated when the frame is actually drawn
|
2015-10-28 15:55:40 -07:00
|
|
|
bool runAnimations = true;
|
2014-08-14 13:34:01 -07:00
|
|
|
|
|
|
|
// Must not be null during actual usage
|
2015-10-28 15:55:40 -07:00
|
|
|
DamageAccumulator* damageAccumulator = nullptr;
|
2019-03-07 17:01:08 -08:00
|
|
|
int64_t damageGenerationId = 0;
|
2015-10-28 16:50:44 -07:00
|
|
|
|
|
|
|
LayerUpdateQueue* layerUpdateQueue = nullptr;
|
2015-10-28 15:55:40 -07:00
|
|
|
ErrorHandler* errorHandler = nullptr;
|
2014-05-02 18:21:16 -07:00
|
|
|
|
2016-02-02 15:18:23 -08:00
|
|
|
bool updateWindowPositions = false;
|
|
|
|
|
2018-09-26 11:21:08 -07:00
|
|
|
int disableForceDark;
|
2018-09-21 14:30:19 -07:00
|
|
|
|
Do not cache AVDs that are off screen
Bug: 128805564
Test: Manual + systrace; hwui_unit_tests; CtsUiRenderingTestCases
Only update a VectorDrawable's cache if it is onscreen. This fixes a
Twitter use case where the app has a ProgressBar that is exactly one
pixel offscreen. Prior to this CL, we repeatedly drew the ProgressBar's
AVD to a GPU surface, even though we clip it out later and never draw
that GPU surface. Now, we recognize that the AVD is outside of the
bounds of the screen, so we never draw to the GPU surface.
TreeInfo:
- store the size of the screen, retrieved from
CanvasContext::getNextFrameSize.
SkiaDisplayList:
- Store the matrix at the time of recording a VectorDrawable. Concat
that with the current matrix to determine whether the VD is on screen,
based on the TreeInfo. If it is offscreen, do not add it to the list
of AVDs that need to be updated ahead of rendering.
- In addition, if it is offscreen (or not dirty), do not call
setPropertyChangeWillBeConsumed(true). This prevents triggering
dispatchFrameCallbacks to update on the RenderThread when there is no
need to. This also mimics what would happen if the View/RenderNode had
been completely offscreen.
- Add a method to append an AVD to mVectorDrawables. Now that the vector
is of Pairs, this simplifies the call sites. Add a second helper to
just add an AVD without a matrix, for use in tests.
SkiaRecordingCanvas:
- get the current matrix and store it in the display list along with the
AVD.
CanvasContext:
- add getNextFrameSize, for reporting the size of the next frame without
dequeuing it
VectorDrawable.cpp:
- call quickReject to potentially short circuit drawing. This is for a
hypothetical use case (verified in a test app) where the containing
RenderNode is partially onscreen, but the AVD itself is not. Even
without the change to VectorDrawable.cpp, we skip uploading to the GPU
cache, the SkiaDisplayList still attempts to draw it. This change
keeps us from drawing it at all.
SkiaDisplayListTests.cpp:
- Now that I've hidden mVectorDrawables, call the new public APIs.
- prepareListAndChildren test
- for the clean VD, assert that getPropertyChangeWillBeConsumed
returns FALSE. This is due to the behavior change that we do not
set it unless the VD is dirty.
- set the bounds, so our onscreen check works.
- Add another test for prepareListAndChildren, which puts VDs offscreen.
Change-Id: Iae0a07adcf58e7884e0854720de644e7b2faf2bf
2019-04-03 15:09:25 -04:00
|
|
|
const SkISize screenSize;
|
|
|
|
|
2014-05-02 18:21:16 -07:00
|
|
|
struct Out {
|
2015-10-28 15:55:40 -07:00
|
|
|
bool hasFunctors = false;
|
2014-05-02 18:21:16 -07:00
|
|
|
// This is only updated if evaluateAnimations is true
|
2015-10-28 15:55:40 -07:00
|
|
|
bool hasAnimations = false;
|
2014-05-02 18:21:16 -07:00
|
|
|
// This is set to true if there is an animation that RenderThread cannot
|
|
|
|
// animate itself, such as if hasFunctors is true
|
|
|
|
// This is only set if hasAnimations is true
|
2015-10-28 15:55:40 -07:00
|
|
|
bool requiresUiRedraw = false;
|
2014-05-22 15:43:54 -07:00
|
|
|
// This is set to true if draw() can be called this frame
|
|
|
|
// false means that we must delay until the next vsync pulse as frame
|
|
|
|
// production is outrunning consumption
|
|
|
|
// NOTE that if this is false CanvasContext will set either requiresUiRedraw
|
|
|
|
// *OR* will post itself for the next vsync automatically, use this
|
|
|
|
// only to avoid calling draw()
|
2015-10-28 15:55:40 -07:00
|
|
|
bool canDrawThisFrame = true;
|
AnimatedImageDrawable: Eliminate unnecessary calls to redraw
Bug: 78866720
Test: Manual + systrace; existing CTS
Previously, we set hasAnimations to true when the AnimatedImageDrawable,
so that we would get a call to redraw. But if the image does not need to
show its next frame yet, the redraw was unnecessary.
Instead, add a new field to TreeInfo::Out, representing the delay time
until the image will need to be redrawn - i.e. when the duration of the
current frame has passed. Each call to prepareTree will post at most one
message to redraw, in time for the earliest animated image to be
redrawn. Post the message for one rendered frame ahead of time, so that
when it is time to show the next frame, the image has already gotten the
message to update.
On a screen with a single animated image, this drops the number of calls
to dispatchFrameCallbacks to as infrequent as possible. It is called
only when we need to draw a new frame of the image. On a screen with
multiple animated images, the calls may be redundant, but they will not
be more frequent than they would be without this change.
Switch to nsecs_t and systemTime internally, matching the rest of HWUI.
Remove mDidDraw and related. Its purpose was to prevent advancing the
animation while the image is not being drawn. But it isn't really
necessary. If it's not drawn, onDraw is not called, which is where we
trigger decoding. And onDraw already has a defense against getting too
far ahead - if its timer indicates that it should skip a frame or show
it very briefly, it will back up its timer. More importantly, mDidDraw
caused a bug, when combined with less frequent redraws. If the display
list containing the drawable doesn't need to be redrawn for other
reasons, the drawable's timer never advanced, so its animation stopped.
Fix software drawing. Compute the milliseconds in the future to draw the
next frame, and add that to SystemClock.uptimeMillis() to compute the
time to pass to scheduleSelf.
Change-Id: I13aab49922fa300f73b327be25561d7120c09ec4
2018-05-14 14:59:30 -04:00
|
|
|
// Sentinel for animatedImageDelay meaning there is no need to post such
|
|
|
|
// a message.
|
|
|
|
static constexpr nsecs_t kNoAnimatedImageDelay = -1;
|
|
|
|
// This is used to post a message to redraw when it is time to draw the
|
|
|
|
// next frame of an AnimatedImageDrawable.
|
|
|
|
nsecs_t animatedImageDelay = kNoAnimatedImageDelay;
|
2014-05-02 18:21:16 -07:00
|
|
|
} out;
|
2014-04-15 09:50:16 -07:00
|
|
|
|
2016-11-08 14:18:31 -05:00
|
|
|
// This flag helps to disable projection for receiver nodes that do not have any backward
|
|
|
|
// projected children.
|
|
|
|
bool hasBackwardProjectedNodes = false;
|
2014-04-15 09:50:16 -07:00
|
|
|
// TODO: Damage calculations
|
|
|
|
};
|
|
|
|
|
|
|
|
} /* namespace uirenderer */
|
|
|
|
} /* namespace android */
|