| /* |
| * 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 <SkBitmap.h> |
| #include <SkRect.h> |
| #include <SkSize.h> |
| #include <cutils/compiler.h> |
| #include <utils/Functor.h> |
| #include <utils/Mutex.h> |
| |
| #include <functional> |
| #include <future> |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "ColorMode.h" |
| #include "DamageAccumulator.h" |
| #include "FrameInfo.h" |
| #include "FrameInfoVisualizer.h" |
| #include "FrameMetricsReporter.h" |
| #include "HintSessionWrapper.h" |
| #include "IContextFactory.h" |
| #include "IRenderPipeline.h" |
| #include "JankTracker.h" |
| #include "LayerUpdateQueue.h" |
| #include "Lighting.h" |
| #include "ReliableSurface.h" |
| #include "RenderNode.h" |
| #include "renderstate/RenderState.h" |
| #include "renderthread/RenderTask.h" |
| #include "renderthread/RenderThread.h" |
| #include "utils/ForceDark.h" |
| #include "utils/RingBuffer.h" |
| |
| namespace android { |
| namespace uirenderer { |
| |
| class AnimationContext; |
| class DeferredLayerUpdater; |
| class ErrorHandler; |
| class Layer; |
| class Rect; |
| class RenderState; |
| |
| namespace renderthread { |
| |
| class Frame; |
| |
| // This per-renderer class manages the bridge between the global EGL context |
| // and the render surface. |
| // TODO: Rename to Renderer or some other per-window, top-level manager |
| class CanvasContext : public IFrameCallback, public IGpuContextCallback { |
| public: |
| static CanvasContext* create(RenderThread& thread, bool translucent, RenderNode* rootRenderNode, |
| IContextFactory* contextFactory, pid_t uiThreadId, |
| pid_t renderThreadId); |
| virtual ~CanvasContext(); |
| |
| /** |
| * Update or create a layer specific for the provided RenderNode. The layer |
| * attached to the node will be specific to the RenderPipeline used by this |
| * context |
| * |
| * @return true if the layer has been created or updated |
| */ |
| bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& dmgAccumulator, |
| ErrorHandler* errorHandler) { |
| return mRenderPipeline->createOrUpdateLayer(node, dmgAccumulator, errorHandler); |
| } |
| |
| /** |
| * Pin any mutable images to the GPU cache. A pinned images is guaranteed to |
| * remain in the cache until it has been unpinned. We leverage this feature |
| * to avoid making a CPU copy of the pixels. |
| * |
| * @return true if all images have been successfully pinned to the GPU cache |
| * and false otherwise (e.g. cache limits have been exceeded). |
| */ |
| bool pinImages(std::vector<SkImage*>& mutableImages) { |
| if (!Properties::isDrawingEnabled()) { |
| return true; |
| } |
| return mRenderPipeline->pinImages(mutableImages); |
| } |
| bool pinImages(LsaVector<sk_sp<Bitmap>>& images) { |
| if (!Properties::isDrawingEnabled()) { |
| return true; |
| } |
| return mRenderPipeline->pinImages(images); |
| } |
| |
| /** |
| * Unpin any image that had be previously pinned to the GPU cache |
| */ |
| void unpinImages() { mRenderPipeline->unpinImages(); } |
| |
| static void invokeFunctor(const RenderThread& thread, Functor* functor); |
| |
| static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap); |
| |
| /* |
| * If Properties::isSkiaEnabled() is true then this will return the Skia |
| * grContext associated with the current RenderPipeline. |
| */ |
| GrDirectContext* getGrContext() const { return mRenderThread.getGrContext(); } |
| |
| ASurfaceControl* getSurfaceControl() const { return mSurfaceControl; } |
| int32_t getSurfaceControlGenerationId() const { return mSurfaceControlGenerationId; } |
| |
| // Won't take effect until next EGLSurface creation |
| void setSwapBehavior(SwapBehavior swapBehavior); |
| |
| void setHardwareBuffer(AHardwareBuffer* buffer); |
| void setSurface(ANativeWindow* window, bool enableTimeout = true); |
| void setSurfaceControl(ASurfaceControl* surfaceControl); |
| bool pauseSurface(); |
| void setStopped(bool stopped); |
| bool isStopped() { return mStopped || !hasOutputTarget(); } |
| bool hasOutputTarget() const { return mNativeSurface.get() || mHardwareBuffer; } |
| void allocateBuffers(); |
| |
| void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha); |
| void setLightGeometry(const Vector3& lightCenter, float lightRadius); |
| void setOpaque(bool opaque); |
| float setColorMode(ColorMode mode); |
| float targetSdrHdrRatio() const; |
| void setTargetSdrHdrRatio(float ratio); |
| bool makeCurrent(); |
| void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target); |
| // Returns the DequeueBufferDuration. |
| void draw(bool solelyTextureViewUpdates); |
| void destroy(); |
| |
| // IFrameCallback, Choreographer-driven frame callback entry point |
| virtual void doFrame() override; |
| void prepareAndDraw(RenderNode* node); |
| |
| void buildLayer(RenderNode* node); |
| void markLayerInUse(RenderNode* node); |
| |
| void destroyHardwareResources(); |
| void onContextDestroyed() override; |
| |
| DeferredLayerUpdater* createTextureLayer(); |
| |
| void stopDrawing(); |
| void notifyFramePending(); |
| |
| FrameInfoVisualizer& profiler() { return mProfiler; } |
| |
| void dumpFrames(int fd); |
| void resetFrameStats(); |
| |
| void setName(const std::string&& name); |
| |
| void addRenderNode(RenderNode* node, bool placeFront); |
| void removeRenderNode(RenderNode* node); |
| |
| void setContentDrawBounds(const Rect& bounds) { mContentDrawBounds = bounds; } |
| |
| void addFrameMetricsObserver(FrameMetricsObserver* observer); |
| void removeFrameMetricsObserver(FrameMetricsObserver* observer); |
| |
| // Used to queue up work that needs to be completed before this frame completes |
| void enqueueFrameWork(std::function<void()>&& func); |
| |
| uint64_t getFrameNumber(); |
| |
| void waitOnFences(); |
| |
| IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); } |
| |
| void addFrameCommitListener(std::function<void(bool)>&& func) { |
| mFrameCommitCallbacks.push_back(std::move(func)); |
| } |
| |
| void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback) { |
| mRenderPipeline->setPictureCapturedCallback(callback); |
| } |
| |
| void setForceDark(ForceDarkType type) { mForceDarkType = type; } |
| |
| ForceDarkType getForceDarkType() { return mForceDarkType; } |
| |
| SkISize getNextFrameSize() const; |
| |
| // Returns the matrix to use to nudge non-AA'd points/lines towards the fragment center |
| const SkM44& getPixelSnapMatrix() const; |
| |
| // Called when SurfaceStats are available. |
| static void onSurfaceStatsAvailable(void* context, int32_t surfaceControlId, |
| ASurfaceControlStats* stats); |
| |
| void setASurfaceTransactionCallback( |
| const std::function<bool(int64_t, int64_t, int64_t)>& callback) { |
| mASurfaceTransactionCallback = callback; |
| } |
| |
| void setHardwareBufferRenderParams(const HardwareBufferRenderParams& params) { |
| mBufferParams = params; |
| } |
| |
| bool mergeTransaction(ASurfaceTransaction* transaction, ASurfaceControl* control); |
| |
| void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback) { |
| mPrepareSurfaceControlForWebviewCallback = callback; |
| } |
| |
| void prepareSurfaceControlForWebview(); |
| |
| static CanvasContext* getActiveContext(); |
| |
| void sendLoadResetHint(); |
| |
| void sendLoadIncreaseHint(); |
| |
| void setSyncDelayDuration(nsecs_t duration); |
| |
| void startHintSession(); |
| |
| static bool shouldDither(); |
| |
| void visitAllRenderNodes(std::function<void(const RenderNode&)>) const; |
| |
| private: |
| CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode, |
| IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline, |
| pid_t uiThreadId, pid_t renderThreadId); |
| |
| friend class RegisterFrameCallbackTask; |
| // TODO: Replace with something better for layer & other GL object |
| // lifecycle tracking |
| friend class android::uirenderer::RenderState; |
| |
| void freePrefetchedLayers(); |
| |
| bool isSwapChainStuffed(); |
| bool surfaceRequiresRedraw(); |
| void setupPipelineSurface(); |
| |
| SkRect computeDirtyRect(const Frame& frame, SkRect* dirty); |
| void finishFrame(FrameInfo* frameInfo); |
| |
| /** |
| * Invoke 'reportFrameMetrics' on the last frame stored in 'mLast4FrameInfos'. |
| * Populate the 'presentTime' field before calling. |
| */ |
| void reportMetricsWithPresentTime(); |
| |
| struct FrameMetricsInfo { |
| FrameInfo* frameInfo; |
| int64_t frameNumber; |
| int32_t surfaceId; |
| }; |
| |
| FrameInfo* getFrameInfoFromLast4(uint64_t frameNumber, uint32_t surfaceControlId); |
| |
| Frame getFrame(); |
| |
| // The same type as Frame.mWidth and Frame.mHeight |
| int32_t mLastFrameWidth = 0; |
| int32_t mLastFrameHeight = 0; |
| |
| RenderThread& mRenderThread; |
| |
| AHardwareBuffer* mHardwareBuffer = nullptr; |
| HardwareBufferRenderParams mBufferParams; |
| std::unique_ptr<ReliableSurface> mNativeSurface; |
| // The SurfaceControl reference is passed from ViewRootImpl, can be set to |
| // NULL to remove the reference |
| ASurfaceControl* mSurfaceControl = nullptr; |
| // id to track surface control changes and WebViewFunctor uses it to determine |
| // whether reparenting is needed also used by FrameMetricsReporter to determine |
| // if a frame is from an "old" surface (i.e. one that existed before the |
| // observer was attched) and therefore shouldn't be reported. |
| // NOTE: It is important that this is an increasing counter. |
| int32_t mSurfaceControlGenerationId = 0; |
| // stopped indicates the CanvasContext will reject actual redraw operations, |
| // and defer repaint until it is un-stopped |
| bool mStopped = false; |
| // Incremented each time the CanvasContext is stopped. Used to ignore |
| // delayed messages that are triggered after stopping. |
| int mGenerationID; |
| // CanvasContext is dirty if it has received an update that it has not |
| // painted onto its surface. |
| bool mIsDirty = false; |
| SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default; |
| struct SwapHistory { |
| SkRect damage; |
| nsecs_t vsyncTime; |
| nsecs_t swapCompletedTime; |
| nsecs_t dequeueDuration; |
| nsecs_t queueDuration; |
| }; |
| |
| // Need at least 4 because we do quad buffer. Add a few more for good measure. |
| RingBuffer<SwapHistory, 7> mSwapHistory; |
| // Frame numbers start at 1, 0 means uninitialized |
| uint64_t mFrameNumber = 0; |
| int64_t mDamageId = 0; |
| |
| // last vsync for a dropped frame due to stuffed queue |
| nsecs_t mLastDropVsync = 0; |
| |
| bool mOpaque; |
| ForceDarkType mForceDarkType = ForceDarkType::NONE; |
| LightInfo mLightInfo; |
| LightGeometry mLightGeometry = {{0, 0, 0}, 0}; |
| |
| bool mHaveNewSurface = false; |
| DamageAccumulator mDamageAccumulator; |
| LayerUpdateQueue mLayerUpdateQueue; |
| std::unique_ptr<AnimationContext> mAnimationContext; |
| |
| std::vector<sp<RenderNode>> mRenderNodes; |
| |
| FrameInfo* mCurrentFrameInfo = nullptr; |
| |
| // List of data of frames that are awaiting GPU completion reporting. Used to compute frame |
| // metrics and determine whether or not to report the metrics. |
| RingBuffer<FrameMetricsInfo, 4> mLast4FrameMetricsInfos |
| GUARDED_BY(mLast4FrameMetricsInfosMutex); |
| std::mutex mLast4FrameMetricsInfosMutex; |
| |
| std::string mName; |
| JankTracker mJankTracker; |
| FrameInfoVisualizer mProfiler; |
| std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter |
| GUARDED_BY(mFrameMetricsReporterMutex); |
| std::mutex mFrameMetricsReporterMutex; |
| |
| std::set<RenderNode*> mPrefetchedLayers; |
| |
| // Stores the bounds of the main content. |
| Rect mContentDrawBounds; |
| |
| std::vector<std::future<void>> mFrameFences; |
| std::unique_ptr<IRenderPipeline> mRenderPipeline; |
| |
| std::vector<std::function<void(bool)>> mFrameCommitCallbacks; |
| |
| // If set to true, we expect that callbacks into onSurfaceStatsAvailable |
| bool mExpectSurfaceStats = false; |
| |
| std::function<bool(int64_t, int64_t, int64_t)> mASurfaceTransactionCallback; |
| std::function<void()> mPrepareSurfaceControlForWebviewCallback; |
| |
| std::shared_ptr<HintSessionWrapper> mHintSessionWrapper; |
| nsecs_t mLastDequeueBufferDuration = 0; |
| nsecs_t mSyncDelayDuration = 0; |
| nsecs_t mIdleDuration = 0; |
| |
| ColorMode mColorMode = ColorMode::Default; |
| float mTargetSdrHdrRatio = 1.f; |
| |
| struct SkippedFrameInfo { |
| int64_t vsyncId; |
| int64_t startTime; |
| }; |
| std::optional<SkippedFrameInfo> mSkippedFrameInfo; |
| }; |
| |
| } /* namespace renderthread */ |
| } /* namespace uirenderer */ |
| } /* namespace android */ |