diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/hwui/VectorDrawable.cpp | 13 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/GLFunctorDrawable.cpp | 8 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaPipeline.cpp | 66 | ||||
| -rw-r--r-- | libs/hwui/pipeline/skia/SkiaPipeline.h | 7 | ||||
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 4 | ||||
| -rw-r--r-- | libs/hwui/renderthread/IRenderPipeline.h | 10 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 38 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 2 |
8 files changed, 100 insertions, 48 deletions
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index dd62bbbdc84f..72656922b03e 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -551,6 +551,19 @@ void Tree::draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& inPaint) SkPaint paint = inPaint; paint.setAlpha(mProperties.getRootAlpha() * 255); + if (canvas->getGrContext() == nullptr) { + // Recording to picture, don't use the SkSurface which won't work off of renderthread. + Bitmap& bitmap = getBitmapUpdateIfDirty(); + SkBitmap skiaBitmap; + bitmap.getSkBitmap(&skiaBitmap); + + int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth()); + int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight()); + canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight), bounds, + &paint, SkCanvas::kFast_SrcRectConstraint); + return; + } + SkRect src; sk_sp<SkSurface> vdSurface = mCache.getSurface(&src); if (vdSurface) { diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp index 240efb41285c..60c805741058 100644 --- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp @@ -74,7 +74,13 @@ static bool GetFboDetails(SkCanvas* canvas, GLuint* outFboID, SkISize* outFboSiz void GLFunctorDrawable::onDraw(SkCanvas* canvas) { if (canvas->getGrContext() == nullptr) { - SkDEBUGF(("Attempting to draw GLFunctor into an unsupported surface")); + // We're dumping a picture, render a light-blue rectangle instead + // TODO: Draw the WebView text on top? Seemingly complicated as SkPaint doesn't + // seem to have a default typeface that works. We only ever use drawGlyphs, which + // requires going through minikin & hwui's canvas which we don't have here. + SkPaint paint; + paint.setColor(0xFF81D4FA); + canvas->drawRect(mBounds, paint); return; } diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index df8224372ea7..47c90948bbbe 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -111,7 +111,7 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) const Rect& layerDamage = layers.entries()[i].damage; - SkCanvas* layerCanvas = tryCapture(layerNode->getLayerSurface()); + SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas(); int saveCount = layerCanvas->save(); SkASSERT(saveCount == 1); @@ -139,8 +139,6 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) layerCanvas->restoreToCount(saveCount); mLightCenter = savedLightCenter; - endCapture(layerNode->getLayerSurface()); - // cache the current context so that we can defer flushing it until // either all the layers have been rendered or the context changes GrContext* currentContext = layerNode->getLayerSurface()->getCanvas()->getGrContext(); @@ -244,6 +242,7 @@ public: } virtual void onProcess(const sp<Task<bool>>& task) override { + ATRACE_NAME("SavePictureTask"); SavePictureTask* t = static_cast<SavePictureTask*>(task.get()); if (0 == access(t->filename.c_str(), F_OK)) { @@ -265,46 +264,56 @@ public: SkCanvas* SkiaPipeline::tryCapture(SkSurface* surface) { if (CC_UNLIKELY(Properties::skpCaptureEnabled)) { - bool recordingPicture = mCaptureSequence > 0; char prop[PROPERTY_VALUE_MAX] = {'\0'}; - if (!recordingPicture) { + if (mCaptureSequence <= 0) { property_get(PROPERTY_CAPTURE_SKP_FILENAME, prop, "0"); - recordingPicture = prop[0] != '0' && - mCapturedFile != prop; // ensure we capture only once per filename - if (recordingPicture) { + if (prop[0] != '0' && mCapturedFile != prop) { mCapturedFile = prop; mCaptureSequence = property_get_int32(PROPERTY_CAPTURE_SKP_FRAMES, 1); } } - if (recordingPicture) { + if (mCaptureSequence > 0 || mPictureCapturedCallback) { mRecorder.reset(new SkPictureRecorder()); - return mRecorder->beginRecording(surface->width(), surface->height(), nullptr, - SkPictureRecorder::kPlaybackDrawPicture_RecordFlag); + SkCanvas* pictureCanvas = mRecorder->beginRecording(surface->width(), surface->height(), nullptr, + SkPictureRecorder::kPlaybackDrawPicture_RecordFlag); + mNwayCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height()); + mNwayCanvas->addCanvas(surface->getCanvas()); + mNwayCanvas->addCanvas(pictureCanvas); + return mNwayCanvas.get(); } } return surface->getCanvas(); } void SkiaPipeline::endCapture(SkSurface* surface) { + mNwayCanvas.reset(); if (CC_UNLIKELY(mRecorder.get())) { + ATRACE_CALL(); sk_sp<SkPicture> picture = mRecorder->finishRecordingAsPicture(); - surface->getCanvas()->drawPicture(picture); if (picture->approximateOpCount() > 0) { - auto data = picture->serialize(); - - // offload saving to file in a different thread - if (!mSavePictureProcessor.get()) { - TaskManager* taskManager = getTaskManager(); - mSavePictureProcessor = new SavePictureProcessor( - taskManager->canRunTasks() ? taskManager : nullptr); + if (mCaptureSequence > 0) { + ATRACE_BEGIN("picture->serialize"); + auto data = picture->serialize(); + ATRACE_END(); + + // offload saving to file in a different thread + if (!mSavePictureProcessor.get()) { + TaskManager* taskManager = getTaskManager(); + mSavePictureProcessor = new SavePictureProcessor( + taskManager->canRunTasks() ? taskManager : nullptr); + } + if (1 == mCaptureSequence) { + mSavePictureProcessor->savePicture(data, mCapturedFile); + } else { + mSavePictureProcessor->savePicture( + data, + mCapturedFile + "_" + std::to_string(mCaptureSequence)); + } + mCaptureSequence--; } - if (1 == mCaptureSequence) { - mSavePictureProcessor->savePicture(data, mCapturedFile); - } else { - mSavePictureProcessor->savePicture( - data, mCapturedFile + "_" + std::to_string(mCaptureSequence)); + if (mPictureCapturedCallback) { + std::invoke(mPictureCapturedCallback, std::move(picture)); } - mCaptureSequence--; } mRecorder.reset(); } @@ -314,6 +323,11 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect& contentDrawBounds, sk_sp<SkSurface> surface, const SkMatrix& preTransform) { + bool previousSkpEnabled = Properties::skpCaptureEnabled; + if (mPictureCapturedCallback) { + Properties::skpCaptureEnabled = true; + } + renderVectorDrawableCache(); // draw all layers up front @@ -334,6 +348,8 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli ATRACE_NAME("flush commands"); surface->getCanvas()->flush(); + + Properties::skpCaptureEnabled = previousSkpEnabled; } namespace { diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h index cf6f5b284d8c..e9957df95f10 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaPipeline.h @@ -105,6 +105,11 @@ public: mLightCenter = lightGeometry.center; } + void setPictureCapturedCallback( + const std::function<void(sk_sp<SkPicture>&&)>& callback) override { + mPictureCapturedCallback = callback; + } + protected: void dumpResourceCacheUsage() const; void setSurfaceColorProperties(renderthread::ColorMode colorMode); @@ -163,6 +168,8 @@ private: * parallel tryCapture calls (not really needed). */ std::unique_ptr<SkPictureRecorder> mRecorder; + std::unique_ptr<SkNWayCanvas> mNwayCanvas; + std::function<void(sk_sp<SkPicture>&&)> mPictureCapturedCallback; static float mLightRadius; static uint8_t mAmbientShadowAlpha; diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 9e7abf447cd6..db97763acd8b 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -184,6 +184,10 @@ public: mFrameCompleteCallbacks.push_back(std::move(func)); } + void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback) { + mRenderPipeline->setPictureCapturedCallback(callback); + } + void setForceDark(bool enable) { mUseForceDark = enable; } diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h index d4dd62941440..2cfc8df38297 100644 --- a/libs/hwui/renderthread/IRenderPipeline.h +++ b/libs/hwui/renderthread/IRenderPipeline.h @@ -59,15 +59,15 @@ public: virtual MakeCurrentResult makeCurrent() = 0; virtual Frame getFrame() = 0; virtual bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty, - const LightGeometry& lightGeometry, - LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds, - bool opaque, const LightInfo& lightInfo, + const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue, + const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo, const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler) = 0; virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty, FrameInfo* currentFrameInfo, bool* requireSwap) = 0; virtual DeferredLayerUpdater* createTextureLayer() = 0; - virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior, ColorMode colorMode) = 0; + virtual bool setSurface(ANativeWindow* window, SwapBehavior swapBehavior, + ColorMode colorMode) = 0; virtual void onStop() = 0; virtual bool isSurfaceReady() = 0; virtual bool isContextReady() = 0; @@ -85,6 +85,8 @@ public: virtual SkColorType getSurfaceColorType() const = 0; virtual sk_sp<SkColorSpace> getSurfaceColorSpace() = 0; virtual GrSurfaceOrigin getSurfaceOrigin() = 0; + virtual void setPictureCapturedCallback( + const std::function<void(sk_sp<SkPicture>&&)>& callback) = 0; virtual ~IRenderPipeline() {} }; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index aa6af23d8ed3..720c60362a55 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -21,6 +21,7 @@ #include "Properties.h" #include "Readback.h" #include "Rect.h" +#include "WebViewFunctorManager.h" #include "pipeline/skia/SkiaOpenGLPipeline.h" #include "pipeline/skia/VectorDrawableAtlas.h" #include "renderstate/RenderState.h" @@ -30,7 +31,6 @@ #include "renderthread/RenderThread.h" #include "utils/Macros.h" #include "utils/TimeUtils.h" -#include "WebViewFunctorManager.h" #include <ui/GraphicBuffer.h> @@ -147,9 +147,7 @@ void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { void RenderProxy::destroyFunctor(int functor) { ATRACE_CALL(); RenderThread& thread = RenderThread::getInstance(); - thread.queue().post([=]() { - WebViewFunctorManager::instance().destroyFunctor(functor); - }); + thread.queue().post([=]() { WebViewFunctorManager::instance().destroyFunctor(functor); }); } DeferredLayerUpdater* RenderProxy::createTextureLayer() { @@ -164,9 +162,9 @@ void RenderProxy::buildLayer(RenderNode* node) { bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { auto& thread = RenderThread::getInstance(); - return thread.queue().runSync( - [&]() -> bool { return thread.readback().copyLayerInto(layer, &bitmap) - == CopyResult::Success; }); + return thread.queue().runSync([&]() -> bool { + return thread.readback().copyLayerInto(layer, &bitmap) == CopyResult::Success; + }); } void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) { @@ -204,9 +202,8 @@ void RenderProxy::fence() { } int RenderProxy::maxTextureSize() { - static int maxTextureSize = RenderThread::getInstance().queue().runSync([]() { - return DeviceInfo::get()->maxTextureSize(); - }); + static int maxTextureSize = RenderThread::getInstance().queue().runSync( + []() { return DeviceInfo::get()->maxTextureSize(); }); return maxTextureSize; } @@ -244,8 +241,10 @@ uint32_t RenderProxy::frameTimePercentile(int percentile) { } void RenderProxy::dumpGraphicsMemory(int fd) { - auto& thread = RenderThread::getInstance(); - thread.queue().runSync([&]() { thread.dumpGraphicsMemory(fd); }); + if (RenderThread::hasInstance()) { + auto& thread = RenderThread::getInstance(); + thread.queue().runSync([&]() { thread.dumpGraphicsMemory(fd); }); + } } void RenderProxy::setProcessStatsBuffer(int fd) { @@ -281,6 +280,12 @@ void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) mDrawFrameTask.setContentDrawBounds(left, top, right, bottom); } +void RenderProxy::setPictureCapturedCallback( + const std::function<void(sk_sp<SkPicture>&&)>& callback) { + mRenderThread.queue().post( + [ this, cb = callback ]() { mContext->setPictureCapturedCallback(cb); }); +} + void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) { mDrawFrameTask.setFrameCallback(std::move(callback)); } @@ -302,9 +307,7 @@ void RenderProxy::removeFrameMetricsObserver(FrameMetricsObserver* observerPtr) } void RenderProxy::setForceDark(bool enable) { - mRenderThread.queue().post([this, enable]() { - mContext->setForceDark(enable); - }); + mRenderThread.queue().post([this, enable]() { mContext->setForceDark(enable); }); } int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom, @@ -348,9 +351,8 @@ int RenderProxy::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) { // TODO: fix everything that hits this. We should never be triggering a readback ourselves. return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap); } else { - return thread.queue().runSync([&]() -> int { - return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap); - }); + return thread.queue().runSync( + [&]() -> int { return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap); }); } } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 9dc918121be6..6e1bfd74528a 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -114,6 +114,8 @@ public: ANDROID_API void removeRenderNode(RenderNode* node); ANDROID_API void drawRenderNode(RenderNode* node); ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom); + ANDROID_API void setPictureCapturedCallback( + const std::function<void(sk_sp<SkPicture>&&)>& callback); ANDROID_API void setFrameCallback(std::function<void(int64_t)>&& callback); ANDROID_API void setFrameCompleteCallback(std::function<void(int64_t)>&& callback); |