Loading libs/hwui/VectorDrawable.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -491,6 +491,36 @@ Bitmap& Tree::getBitmapUpdateIfDirty() { return *mCache.bitmap; } void Tree::updateCache(sk_sp<SkSurface> surface) { if (surface.get()) { mCache.surface = surface; } if (surface.get() || mCache.dirty) { SkSurface* vdSurface = mCache.surface.get(); SkCanvas* canvas = vdSurface->getCanvas(); float scaleX = vdSurface->width() / mProperties.getViewportWidth(); float scaleY = vdSurface->height() / mProperties.getViewportHeight(); SkAutoCanvasRestore acr(canvas, true); canvas->clear(SK_ColorTRANSPARENT); canvas->scale(scaleX, scaleY); mRootNode->draw(canvas, false); mCache.dirty = false; canvas->flush(); } } void Tree::draw(SkCanvas* canvas) { /* * TODO address the following... * * 1) figure out how to set path's as volatile during animation * 2) if mRoot->getPaint() != null either promote to layer (during * animation) or cache in SkSurface (for static content) */ canvas->drawImageRect(mCache.surface->makeImageSnapshot().get(), mutateProperties()->getBounds(), getPaint()); } void Tree::updateBitmapCache(Bitmap& bitmap, bool useStagingData) { SkBitmap outCache; bitmap.getSkBitmap(&outCache); Loading libs/hwui/VectorDrawable.h +24 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <SkPathMeasure.h> #include <SkRect.h> #include <SkShader.h> #include <SkSurface.h> #include <cutils/compiler.h> #include <stddef.h> Loading Loading @@ -677,15 +678,37 @@ public: // This should only be called from animations on RT TreeProperties* mutateProperties() { return &mProperties; } // called from RT only const TreeProperties& properties() const { return mProperties; } // This should always be called from RT. void markDirty() { mCache.dirty = true; } bool isDirty() const { return mCache.dirty; } bool getPropertyChangeWillBeConsumed() const { return mWillBeConsumed; } void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; } // Returns true if VD cache surface is big enough. This should always be called from RT and it // works with Skia pipelines only. bool canReuseSurface() { SkSurface* surface = mCache.surface.get(); return surface && surface->width() >= mProperties.getScaledWidth() && surface->height() >= mProperties.getScaledHeight(); } // Draws VD cache into a canvas. This should always be called from RT and it works with Skia // pipelines only. void draw(SkCanvas* canvas); // Draws VD into a GPU backed surface. If canReuseSurface returns false, then "surface" must // contain a new surface. This should always be called from RT and it works with Skia pipelines // only. void updateCache(sk_sp<SkSurface> surface); private: struct Cache { sk_sp<Bitmap> bitmap; sk_sp<Bitmap> bitmap; //used by HWUI pipeline and software //TODO: use surface instead of bitmap when drawing in software canvas sk_sp<SkSurface> surface; //used only by Skia pipelines bool dirty = true; }; Loading libs/hwui/pipeline/skia/SkiaDisplayList.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "renderthread/CanvasContext.h" #include "VectorDrawable.h" #include "DumpOpsCanvas.h" #include "SkiaPipeline.h" #include <SkImagePriv.h> Loading Loading @@ -92,6 +93,8 @@ bool SkiaDisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& i // If any vector drawable in the display list needs update, damage the node. if (vectorDrawable->isDirty()) { isDirty = true; static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline()) ->getVectorDrawables()->push_back(vectorDrawable); } vectorDrawable->setPropertyChangeWillBeConsumed(true); } Loading libs/hwui/pipeline/skia/SkiaPipeline.cpp +30 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <SkPictureRecorder.h> #include <SkPixelSerializer.h> #include <SkStream.h> #include "VectorDrawable.h" #include <unistd.h> Loading @@ -40,7 +41,9 @@ uint8_t SkiaPipeline::mSpotShadowAlpha = 0; Vector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN}; SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) { } SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) { mVectorDrawables.reserve(30); } TaskManager* SkiaPipeline::getTaskManager() { return &mTaskManager; Loading Loading @@ -74,6 +77,7 @@ void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry const BakedOpRenderer::LightInfo& lightInfo) { updateLighting(lightGeometry, lightInfo); ATRACE_NAME("draw layers"); renderVectorDrawableCache(); renderLayersImpl(*layerUpdateQueue, opaque); layerUpdateQueue->clear(); } Loading Loading @@ -176,10 +180,35 @@ public: } }; void SkiaPipeline::renderVectorDrawableCache() { //render VectorDrawables into offscreen buffers for (auto vd : mVectorDrawables) { sk_sp<SkSurface> surface; if (!vd->canReuseSurface()) { #ifndef ANDROID_ENABLE_LINEAR_BLENDING sk_sp<SkColorSpace> colorSpace = nullptr; #else sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB(); #endif int scaledWidth = SkScalarCeilToInt(vd->properties().getScaledWidth()); int scaledHeight = SkScalarCeilToInt(vd->properties().getScaledHeight()); SkImageInfo info = SkImageInfo::MakeN32(scaledWidth, scaledHeight, kPremul_SkAlphaType, colorSpace); SkASSERT(mRenderThread.getGrContext() != nullptr); surface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes, info); } vd->updateCache(surface); } mVectorDrawables.clear(); } void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip, const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds, sk_sp<SkSurface> surface) { renderVectorDrawableCache(); // draw all layers up front renderLayersImpl(layers, opaque); Loading libs/hwui/pipeline/skia/SkiaPipeline.h +12 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ public: const std::vector< sp<RenderNode> >& nodes, bool opaque, const Rect &contentDrawBounds, sk_sp<SkSurface> surface); std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; } static void destroyLayer(RenderNode* node); static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap); Loading Loading @@ -119,8 +121,18 @@ private: const std::vector< sp<RenderNode> >& nodes, const Rect &contentDrawBounds, sk_sp<SkSurface>); /** * Render mVectorDrawables into offscreen buffers. */ void renderVectorDrawableCache(); TaskManager mTaskManager; std::vector<sk_sp<SkImage>> mPinnedImages; /** * populated by prepareTree with dirty VDs */ std::vector<VectorDrawableRoot*> mVectorDrawables; static float mLightRadius; static uint8_t mAmbientShadowAlpha; static uint8_t mSpotShadowAlpha; Loading Loading
libs/hwui/VectorDrawable.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -491,6 +491,36 @@ Bitmap& Tree::getBitmapUpdateIfDirty() { return *mCache.bitmap; } void Tree::updateCache(sk_sp<SkSurface> surface) { if (surface.get()) { mCache.surface = surface; } if (surface.get() || mCache.dirty) { SkSurface* vdSurface = mCache.surface.get(); SkCanvas* canvas = vdSurface->getCanvas(); float scaleX = vdSurface->width() / mProperties.getViewportWidth(); float scaleY = vdSurface->height() / mProperties.getViewportHeight(); SkAutoCanvasRestore acr(canvas, true); canvas->clear(SK_ColorTRANSPARENT); canvas->scale(scaleX, scaleY); mRootNode->draw(canvas, false); mCache.dirty = false; canvas->flush(); } } void Tree::draw(SkCanvas* canvas) { /* * TODO address the following... * * 1) figure out how to set path's as volatile during animation * 2) if mRoot->getPaint() != null either promote to layer (during * animation) or cache in SkSurface (for static content) */ canvas->drawImageRect(mCache.surface->makeImageSnapshot().get(), mutateProperties()->getBounds(), getPaint()); } void Tree::updateBitmapCache(Bitmap& bitmap, bool useStagingData) { SkBitmap outCache; bitmap.getSkBitmap(&outCache); Loading
libs/hwui/VectorDrawable.h +24 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <SkPathMeasure.h> #include <SkRect.h> #include <SkShader.h> #include <SkSurface.h> #include <cutils/compiler.h> #include <stddef.h> Loading Loading @@ -677,15 +678,37 @@ public: // This should only be called from animations on RT TreeProperties* mutateProperties() { return &mProperties; } // called from RT only const TreeProperties& properties() const { return mProperties; } // This should always be called from RT. void markDirty() { mCache.dirty = true; } bool isDirty() const { return mCache.dirty; } bool getPropertyChangeWillBeConsumed() const { return mWillBeConsumed; } void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; } // Returns true if VD cache surface is big enough. This should always be called from RT and it // works with Skia pipelines only. bool canReuseSurface() { SkSurface* surface = mCache.surface.get(); return surface && surface->width() >= mProperties.getScaledWidth() && surface->height() >= mProperties.getScaledHeight(); } // Draws VD cache into a canvas. This should always be called from RT and it works with Skia // pipelines only. void draw(SkCanvas* canvas); // Draws VD into a GPU backed surface. If canReuseSurface returns false, then "surface" must // contain a new surface. This should always be called from RT and it works with Skia pipelines // only. void updateCache(sk_sp<SkSurface> surface); private: struct Cache { sk_sp<Bitmap> bitmap; sk_sp<Bitmap> bitmap; //used by HWUI pipeline and software //TODO: use surface instead of bitmap when drawing in software canvas sk_sp<SkSurface> surface; //used only by Skia pipelines bool dirty = true; }; Loading
libs/hwui/pipeline/skia/SkiaDisplayList.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "renderthread/CanvasContext.h" #include "VectorDrawable.h" #include "DumpOpsCanvas.h" #include "SkiaPipeline.h" #include <SkImagePriv.h> Loading Loading @@ -92,6 +93,8 @@ bool SkiaDisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& i // If any vector drawable in the display list needs update, damage the node. if (vectorDrawable->isDirty()) { isDirty = true; static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline()) ->getVectorDrawables()->push_back(vectorDrawable); } vectorDrawable->setPropertyChangeWillBeConsumed(true); } Loading
libs/hwui/pipeline/skia/SkiaPipeline.cpp +30 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <SkPictureRecorder.h> #include <SkPixelSerializer.h> #include <SkStream.h> #include "VectorDrawable.h" #include <unistd.h> Loading @@ -40,7 +41,9 @@ uint8_t SkiaPipeline::mSpotShadowAlpha = 0; Vector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN}; SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) { } SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) { mVectorDrawables.reserve(30); } TaskManager* SkiaPipeline::getTaskManager() { return &mTaskManager; Loading Loading @@ -74,6 +77,7 @@ void SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry const BakedOpRenderer::LightInfo& lightInfo) { updateLighting(lightGeometry, lightInfo); ATRACE_NAME("draw layers"); renderVectorDrawableCache(); renderLayersImpl(*layerUpdateQueue, opaque); layerUpdateQueue->clear(); } Loading Loading @@ -176,10 +180,35 @@ public: } }; void SkiaPipeline::renderVectorDrawableCache() { //render VectorDrawables into offscreen buffers for (auto vd : mVectorDrawables) { sk_sp<SkSurface> surface; if (!vd->canReuseSurface()) { #ifndef ANDROID_ENABLE_LINEAR_BLENDING sk_sp<SkColorSpace> colorSpace = nullptr; #else sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB(); #endif int scaledWidth = SkScalarCeilToInt(vd->properties().getScaledWidth()); int scaledHeight = SkScalarCeilToInt(vd->properties().getScaledHeight()); SkImageInfo info = SkImageInfo::MakeN32(scaledWidth, scaledHeight, kPremul_SkAlphaType, colorSpace); SkASSERT(mRenderThread.getGrContext() != nullptr); surface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes, info); } vd->updateCache(surface); } mVectorDrawables.clear(); } void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip, const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds, sk_sp<SkSurface> surface) { renderVectorDrawableCache(); // draw all layers up front renderLayersImpl(layers, opaque); Loading
libs/hwui/pipeline/skia/SkiaPipeline.h +12 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ public: const std::vector< sp<RenderNode> >& nodes, bool opaque, const Rect &contentDrawBounds, sk_sp<SkSurface> surface); std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; } static void destroyLayer(RenderNode* node); static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap); Loading Loading @@ -119,8 +121,18 @@ private: const std::vector< sp<RenderNode> >& nodes, const Rect &contentDrawBounds, sk_sp<SkSurface>); /** * Render mVectorDrawables into offscreen buffers. */ void renderVectorDrawableCache(); TaskManager mTaskManager; std::vector<sk_sp<SkImage>> mPinnedImages; /** * populated by prepareTree with dirty VDs */ std::vector<VectorDrawableRoot*> mVectorDrawables; static float mLightRadius; static uint8_t mAmbientShadowAlpha; static uint8_t mSpotShadowAlpha; Loading