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
133 lines
4.4 KiB
C++
133 lines
4.4 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "Properties.h"
|
|
#include "utils/Macros.h"
|
|
|
|
#include <utils/Timers.h>
|
|
#include "SkSize.h"
|
|
|
|
#include <string>
|
|
|
|
namespace android {
|
|
namespace uirenderer {
|
|
|
|
namespace renderthread {
|
|
class CanvasContext;
|
|
}
|
|
|
|
class DamageAccumulator;
|
|
class LayerUpdateQueue;
|
|
class RenderNode;
|
|
class RenderState;
|
|
|
|
class ErrorHandler {
|
|
public:
|
|
virtual void onError(const std::string& message) = 0;
|
|
|
|
protected:
|
|
virtual ~ErrorHandler() = default;
|
|
};
|
|
|
|
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.
|
|
virtual void onMaybeRemovedFromTree(RenderNode* node) = 0;
|
|
|
|
protected:
|
|
virtual ~TreeObserver() = default;
|
|
};
|
|
|
|
// This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN
|
|
class TreeInfo {
|
|
PREVENT_COPY_AND_ASSIGN(TreeInfo);
|
|
|
|
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,
|
|
};
|
|
|
|
TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContext);
|
|
|
|
TraversalMode mode;
|
|
// TODO: Remove this? Currently this is used to signal to stop preparing
|
|
// textures if we run out of cache space.
|
|
bool prepareTextures;
|
|
renderthread::CanvasContext& canvasContext;
|
|
// 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
|
|
bool runAnimations = true;
|
|
|
|
// Must not be null during actual usage
|
|
DamageAccumulator* damageAccumulator = nullptr;
|
|
int64_t damageGenerationId = 0;
|
|
|
|
LayerUpdateQueue* layerUpdateQueue = nullptr;
|
|
ErrorHandler* errorHandler = nullptr;
|
|
|
|
bool updateWindowPositions = false;
|
|
|
|
int disableForceDark;
|
|
|
|
const SkISize screenSize;
|
|
|
|
struct Out {
|
|
bool hasFunctors = false;
|
|
// This is only updated if evaluateAnimations is true
|
|
bool hasAnimations = false;
|
|
// 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
|
|
bool requiresUiRedraw = false;
|
|
// 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()
|
|
bool canDrawThisFrame = true;
|
|
// 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;
|
|
} out;
|
|
|
|
// This flag helps to disable projection for receiver nodes that do not have any backward
|
|
// projected children.
|
|
bool hasBackwardProjectedNodes = false;
|
|
// TODO: Damage calculations
|
|
};
|
|
|
|
} /* namespace uirenderer */
|
|
} /* namespace android */
|