Loading libs/renderengine/skia/SkiaGLRenderEngine.cpp +13 −4 Original line number Diff line number Diff line Loading @@ -518,7 +518,7 @@ sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp<SkShader> sh } void SkiaGLRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) { if (mCapture->isCaptureRunning()) { if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record display settings when capture is running. std::stringstream displaySettings; PrintTo(display, &displaySettings); Loading Loading @@ -626,6 +626,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, // offscreen buffer and when to render to the native buffer. sk_sp<SkSurface> activeSurface(dstSurface); SkCanvas* canvas = dstCanvas; SkiaCapture::OffscreenState offscreenCaptureState; const LayerSettings* blurCompositionLayer = nullptr; if (mBlurFilter) { bool requiresCompositionLayer = false; Loading @@ -642,7 +643,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } if (requiresCompositionLayer) { activeSurface = dstSurface->makeSurface(dstSurface->imageInfo()); canvas = activeSurface->getCanvas(); canvas = mCapture->tryOffscreenCapture(activeSurface.get(), &offscreenCaptureState); blurCompositionLayer = layer; break; } Loading Loading @@ -692,7 +693,15 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, // blit the offscreen framebuffer into the destination AHB SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); if (CC_UNLIKELY(mCapture->isCaptureRunning())) { uint64_t id = mCapture->endOffscreenCapture(&offscreenCaptureState); dstCanvas->drawAnnotation(SkRect::Make(dstCanvas->imageInfo().dimensions()), String8::format("SurfaceID|%" PRId64, id).c_str(), nullptr); dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint); } else { activeSurface->draw(dstCanvas, 0, 0, SkSamplingOptions(), &paint); } // assign dstCanvas to canvas and ensure that the canvas state is up to date canvas = dstCanvas; Loading @@ -709,7 +718,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } canvas->save(); if (mCapture->isCaptureRunning()) { if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record the name of the layer if the capture is running. std::stringstream layerSettings; PrintTo(*layer, &layerSettings); Loading libs/renderengine/skia/debug/SkiaCapture.cpp +61 −7 Original line number Diff line number Diff line Loading @@ -41,11 +41,11 @@ SkiaCapture::~SkiaCapture() { mTimer.stop(); } SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) { SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); // If we are not running yet, set up. if (!mCaptureRunning) { if (CC_LIKELY(!mCaptureRunning)) { mTimerInterval = std::chrono::milliseconds( base::GetIntProperty(PROPERTY_DEBUG_RENDERENGINE_CAPTURE_SKIA_MS, 0)); // Set up the multi-frame capture. If we fail to set it up, then just return canvas. Loading @@ -56,7 +56,8 @@ SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) { // Start the new timer. When timer expires, write to file. mTimer.setTimeout( [this] { endCapture(); const std::scoped_lock lock(mMutex); LOG_ALWAYS_FATAL_IF(mCurrentPageCanvas != nullptr); writeToFile(); // To avoid going in circles, set the flag to 0. This way the capture can be // restarted just by setting the flag and without restarting the process. Loading @@ -65,29 +66,82 @@ SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) { mTimerInterval); } mMutex.lock(); // Create a canvas pointer, fill it. SkCanvas* pictureCanvas = mMultiPic->beginPage(surface->width(), surface->height()); mCurrentPageCanvas = mMultiPic->beginPage(surface->width(), surface->height()); // Setting up an nway canvas is common to any kind of capture. mNwayCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height()); mNwayCanvas->addCanvas(surface->getCanvas()); mNwayCanvas->addCanvas(pictureCanvas); mNwayCanvas->addCanvas(mCurrentPageCanvas); return mNwayCanvas.get(); } void SkiaCapture::endCapture() { void SkiaCapture::endCapture() NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); // Don't end anything if we are not running. if (!mCaptureRunning) { if (CC_LIKELY(!mCaptureRunning)) { return; } // Reset the canvas pointer. mCurrentPageCanvas = nullptr; mNwayCanvas.reset(); // End page. if (mMultiPic) { mMultiPic->endPage(); } mMutex.unlock(); } SkCanvas* SkiaCapture::tryOffscreenCapture(SkSurface* surface, OffscreenState* state) { ATRACE_CALL(); // Don't start anything if we are not running. if (CC_LIKELY(!mCaptureRunning)) { return surface->getCanvas(); } // Create a canvas pointer, fill it. state->offscreenRecorder = std::make_unique<SkPictureRecorder>(); SkCanvas* pictureCanvas = state->offscreenRecorder->beginRecording(surface->width(), surface->height()); // Setting up an nway canvas is common to any kind of capture. state->offscreenCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height()); state->offscreenCanvas->addCanvas(surface->getCanvas()); state->offscreenCanvas->addCanvas(pictureCanvas); return state->offscreenCanvas.get(); } uint64_t SkiaCapture::endOffscreenCapture(OffscreenState* state) { ATRACE_CALL(); // Don't end anything if we are not running. if (CC_LIKELY(!mCaptureRunning)) { return 0; } // compute the uniqueID for this capture static std::atomic<uint64_t> nextID{1}; const uint64_t uniqueID = nextID.fetch_add(1, std::memory_order_relaxed); // Reset the canvas pointer as we are no longer drawing into it state->offscreenCanvas.reset(); // Record the offscreen as a picture in the currently active page. SkRect bounds = SkRect::Make(state->offscreenRecorder->getRecordingCanvas()->imageInfo().dimensions()); mCurrentPageCanvas ->drawAnnotation(bounds, String8::format("OffscreenLayerDraw|%" PRId64, uniqueID).c_str(), nullptr); mCurrentPageCanvas->drawPicture(state->offscreenRecorder->finishRecordingAsPicture()); // Reset the offscreen picture recorder state->offscreenRecorder.reset(); return uniqueID; } void SkiaCapture::writeToFile() { Loading libs/renderengine/skia/debug/SkiaCapture.h +20 −0 Original line number Diff line number Diff line Loading @@ -18,8 +18,12 @@ #include <SkDocument.h> #include <SkNWayCanvas.h> #include <SkPictureRecorder.h> #include <SkSurface.h> #include <chrono> #include <mutex> #include "CaptureTimer.h" #include "tools/SkSharingProc.h" Loading Loading @@ -48,6 +52,16 @@ public: // Returns whether the capture is running. bool isCaptureRunning() { return mCaptureRunning; } // Offscreen state member variables are private to SkiaCapture, but the allocation // and lifetime is managed by the caller. This enables nested offscreen // captures to occur. struct OffscreenState { std::unique_ptr<SkPictureRecorder> offscreenRecorder; std::unique_ptr<SkNWayCanvas> offscreenCanvas; }; SkCanvas* tryOffscreenCapture(SkSurface* surface, OffscreenState* state); uint64_t endOffscreenCapture(OffscreenState* state); private: // Performs the first-frame work of a multi frame SKP capture. Returns true if successful. bool setupMultiFrameCapture(); Loading @@ -61,10 +75,16 @@ private: std::unique_ptr<SkSharingSerialContext> mSerialContext; std::unique_ptr<SkNWayCanvas> mNwayCanvas; SkCanvas* mCurrentPageCanvas; // Capturing and interval control. bool mCaptureRunning = false; CaptureTimer mTimer; Interval mTimerInterval = 0ms; // Mutex to ensure that a frame in progress when the timer fires is allowed to run to // completion before we write the file to disk. std::mutex mMutex; }; } // namespace skia Loading Loading
libs/renderengine/skia/SkiaGLRenderEngine.cpp +13 −4 Original line number Diff line number Diff line Loading @@ -518,7 +518,7 @@ sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp<SkShader> sh } void SkiaGLRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) { if (mCapture->isCaptureRunning()) { if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record display settings when capture is running. std::stringstream displaySettings; PrintTo(display, &displaySettings); Loading Loading @@ -626,6 +626,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, // offscreen buffer and when to render to the native buffer. sk_sp<SkSurface> activeSurface(dstSurface); SkCanvas* canvas = dstCanvas; SkiaCapture::OffscreenState offscreenCaptureState; const LayerSettings* blurCompositionLayer = nullptr; if (mBlurFilter) { bool requiresCompositionLayer = false; Loading @@ -642,7 +643,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } if (requiresCompositionLayer) { activeSurface = dstSurface->makeSurface(dstSurface->imageInfo()); canvas = activeSurface->getCanvas(); canvas = mCapture->tryOffscreenCapture(activeSurface.get(), &offscreenCaptureState); blurCompositionLayer = layer; break; } Loading Loading @@ -692,7 +693,15 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, // blit the offscreen framebuffer into the destination AHB SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); if (CC_UNLIKELY(mCapture->isCaptureRunning())) { uint64_t id = mCapture->endOffscreenCapture(&offscreenCaptureState); dstCanvas->drawAnnotation(SkRect::Make(dstCanvas->imageInfo().dimensions()), String8::format("SurfaceID|%" PRId64, id).c_str(), nullptr); dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint); } else { activeSurface->draw(dstCanvas, 0, 0, SkSamplingOptions(), &paint); } // assign dstCanvas to canvas and ensure that the canvas state is up to date canvas = dstCanvas; Loading @@ -709,7 +718,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } canvas->save(); if (mCapture->isCaptureRunning()) { if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record the name of the layer if the capture is running. std::stringstream layerSettings; PrintTo(*layer, &layerSettings); Loading
libs/renderengine/skia/debug/SkiaCapture.cpp +61 −7 Original line number Diff line number Diff line Loading @@ -41,11 +41,11 @@ SkiaCapture::~SkiaCapture() { mTimer.stop(); } SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) { SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); // If we are not running yet, set up. if (!mCaptureRunning) { if (CC_LIKELY(!mCaptureRunning)) { mTimerInterval = std::chrono::milliseconds( base::GetIntProperty(PROPERTY_DEBUG_RENDERENGINE_CAPTURE_SKIA_MS, 0)); // Set up the multi-frame capture. If we fail to set it up, then just return canvas. Loading @@ -56,7 +56,8 @@ SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) { // Start the new timer. When timer expires, write to file. mTimer.setTimeout( [this] { endCapture(); const std::scoped_lock lock(mMutex); LOG_ALWAYS_FATAL_IF(mCurrentPageCanvas != nullptr); writeToFile(); // To avoid going in circles, set the flag to 0. This way the capture can be // restarted just by setting the flag and without restarting the process. Loading @@ -65,29 +66,82 @@ SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) { mTimerInterval); } mMutex.lock(); // Create a canvas pointer, fill it. SkCanvas* pictureCanvas = mMultiPic->beginPage(surface->width(), surface->height()); mCurrentPageCanvas = mMultiPic->beginPage(surface->width(), surface->height()); // Setting up an nway canvas is common to any kind of capture. mNwayCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height()); mNwayCanvas->addCanvas(surface->getCanvas()); mNwayCanvas->addCanvas(pictureCanvas); mNwayCanvas->addCanvas(mCurrentPageCanvas); return mNwayCanvas.get(); } void SkiaCapture::endCapture() { void SkiaCapture::endCapture() NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); // Don't end anything if we are not running. if (!mCaptureRunning) { if (CC_LIKELY(!mCaptureRunning)) { return; } // Reset the canvas pointer. mCurrentPageCanvas = nullptr; mNwayCanvas.reset(); // End page. if (mMultiPic) { mMultiPic->endPage(); } mMutex.unlock(); } SkCanvas* SkiaCapture::tryOffscreenCapture(SkSurface* surface, OffscreenState* state) { ATRACE_CALL(); // Don't start anything if we are not running. if (CC_LIKELY(!mCaptureRunning)) { return surface->getCanvas(); } // Create a canvas pointer, fill it. state->offscreenRecorder = std::make_unique<SkPictureRecorder>(); SkCanvas* pictureCanvas = state->offscreenRecorder->beginRecording(surface->width(), surface->height()); // Setting up an nway canvas is common to any kind of capture. state->offscreenCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height()); state->offscreenCanvas->addCanvas(surface->getCanvas()); state->offscreenCanvas->addCanvas(pictureCanvas); return state->offscreenCanvas.get(); } uint64_t SkiaCapture::endOffscreenCapture(OffscreenState* state) { ATRACE_CALL(); // Don't end anything if we are not running. if (CC_LIKELY(!mCaptureRunning)) { return 0; } // compute the uniqueID for this capture static std::atomic<uint64_t> nextID{1}; const uint64_t uniqueID = nextID.fetch_add(1, std::memory_order_relaxed); // Reset the canvas pointer as we are no longer drawing into it state->offscreenCanvas.reset(); // Record the offscreen as a picture in the currently active page. SkRect bounds = SkRect::Make(state->offscreenRecorder->getRecordingCanvas()->imageInfo().dimensions()); mCurrentPageCanvas ->drawAnnotation(bounds, String8::format("OffscreenLayerDraw|%" PRId64, uniqueID).c_str(), nullptr); mCurrentPageCanvas->drawPicture(state->offscreenRecorder->finishRecordingAsPicture()); // Reset the offscreen picture recorder state->offscreenRecorder.reset(); return uniqueID; } void SkiaCapture::writeToFile() { Loading
libs/renderengine/skia/debug/SkiaCapture.h +20 −0 Original line number Diff line number Diff line Loading @@ -18,8 +18,12 @@ #include <SkDocument.h> #include <SkNWayCanvas.h> #include <SkPictureRecorder.h> #include <SkSurface.h> #include <chrono> #include <mutex> #include "CaptureTimer.h" #include "tools/SkSharingProc.h" Loading Loading @@ -48,6 +52,16 @@ public: // Returns whether the capture is running. bool isCaptureRunning() { return mCaptureRunning; } // Offscreen state member variables are private to SkiaCapture, but the allocation // and lifetime is managed by the caller. This enables nested offscreen // captures to occur. struct OffscreenState { std::unique_ptr<SkPictureRecorder> offscreenRecorder; std::unique_ptr<SkNWayCanvas> offscreenCanvas; }; SkCanvas* tryOffscreenCapture(SkSurface* surface, OffscreenState* state); uint64_t endOffscreenCapture(OffscreenState* state); private: // Performs the first-frame work of a multi frame SKP capture. Returns true if successful. bool setupMultiFrameCapture(); Loading @@ -61,10 +75,16 @@ private: std::unique_ptr<SkSharingSerialContext> mSerialContext; std::unique_ptr<SkNWayCanvas> mNwayCanvas; SkCanvas* mCurrentPageCanvas; // Capturing and interval control. bool mCaptureRunning = false; CaptureTimer mTimer; Interval mTimerInterval = 0ms; // Mutex to ensure that a frame in progress when the timer fires is allowed to run to // completion before we write the file to disk. std::mutex mMutex; }; } // namespace skia Loading