Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30dfc68a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Convert skpCaptureEnabled compile time flag into a property"

parents 8f34e0b2 e9d0012b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ bool Properties::forceDrawFrame = false;

bool Properties::filterOutTestOverhead = false;
bool Properties::disableVsync = false;
bool Properties::skpCaptureEnabled = false;

static int property_get_int(const char* key, int defaultValue) {
    char buf[PROPERTY_VALUE_MAX] = {'\0',};
@@ -128,6 +129,9 @@ bool Properties::load() {

    filterOutTestOverhead = property_get_bool(PROPERTY_FILTER_TEST_OVERHEAD, false);

    skpCaptureEnabled = property_get_bool("ro.debuggable", false)
            && property_get_bool(PROPERTY_CAPTURE_SKP_ENABLED, false);

    return (prevDebugLayersUpdates != debugLayersUpdates)
            || (prevDebugOverdraw != debugOverdraw)
            || (prevDebugStencilClip != debugStencilClip);
+18 −0
Original line number Diff line number Diff line
@@ -165,6 +165,22 @@ enum DebugLevel {
 */
#define PROPERTY_RENDERER "debug.hwui.renderer"

/**
 * Allows to collect a recording of Skia drawing commands.
 */
#define PROPERTY_CAPTURE_SKP_ENABLED "debug.hwui.capture_skp_enabled"


/**
 * Defines how many frames in a sequence to capture.
 */
#define PROPERTY_CAPTURE_SKP_FRAMES  "debug.hwui.capture_skp_frames"

/**
 * File name and location, where a SKP recording will be saved.
 */
#define PROPERTY_CAPTURE_SKP_FILENAME "debug.hwui.skp_filename"

///////////////////////////////////////////////////////////////////////////////
// Misc
///////////////////////////////////////////////////////////////////////////////
@@ -254,6 +270,8 @@ public:
    // created after changing this.
    static bool disableVsync;

    static bool skpCaptureEnabled;

    // Used for testing only to change the render pipeline.
#ifdef HWUI_GLES_WRAP_ENABLED
    static void overrideRenderPipelineType(RenderPipelineType);
+4 −0
Original line number Diff line number Diff line
@@ -35,6 +35,10 @@ void LayerDrawable::onDraw(SkCanvas* canvas) {
}

bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer) {
    if (context == nullptr) {
        SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface"));
        return false;
    }
    // transform the matrix based on the layer
    SkMatrix layerTransform;
    layer->getTransform().copyTo(layerTransform);
+1 −1
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ void RenderNodeDrawable::onDraw(SkCanvas* canvas) {

void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
    RenderNode* renderNode = mRenderNode.get();
    if (SkiaPipeline::skpCaptureEnabled()) {
    if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
        SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight());
        canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr);
    }
+94 −30
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers,

            const Rect& layerDamage = layers.entries()[i].damage;

            SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();
            SkCanvas* layerCanvas = tryCapture(layerNode->getLayerSurface());

            int saveCount = layerCanvas->save();
            SkASSERT(saveCount == 1);
@@ -139,9 +139,11 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers,
            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 = layerCanvas->getGrContext();
            GrContext* currentContext = layerNode->getLayerSurface()->getCanvas()->getGrContext();
            if (cachedContext.get() != currentContext) {
                if (cachedContext.get()) {
                    cachedContext->flush();
@@ -227,53 +229,115 @@ void SkiaPipeline::renderVectorDrawableCache() {
    }
}

void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
        const std::vector<sp<RenderNode>>& nodes, bool opaque, bool wideColorGamut,
        const Rect &contentDrawBounds, sk_sp<SkSurface> surface) {
class SkiaPipeline::SavePictureProcessor : public TaskProcessor<bool> {
public:
    explicit SavePictureProcessor(TaskManager* taskManager) : TaskProcessor<bool>(taskManager) {}

    renderVectorDrawableCache();
    struct SavePictureTask : public Task<bool> {
        sk_sp<SkData> data;
        std::string filename;
    };

    // draw all layers up front
    renderLayersImpl(layers, opaque, wideColorGamut);
    void savePicture(const sk_sp<SkData>& data, const std::string& filename) {
        sp<SavePictureTask> task(new SavePictureTask());
        task->data = data;
        task->filename = filename;
        TaskProcessor<bool>::add(task);
    }

    // initialize the canvas for the current frame
    SkCanvas* canvas = surface->getCanvas();
    virtual void onProcess(const sp<Task<bool> >& task) override {
        SavePictureTask* t = static_cast<SavePictureTask*>(task.get());

    std::unique_ptr<SkPictureRecorder> recorder;
    bool recordingPicture = false;
    char prop[PROPERTY_VALUE_MAX];
    if (skpCaptureEnabled()) {
        property_get("debug.hwui.capture_frame_as_skp", prop, "0");
        recordingPicture = prop[0] != '0' && access(prop, F_OK) != 0;
        if (recordingPicture) {
            recorder.reset(new SkPictureRecorder());
            canvas = recorder->beginRecording(surface->width(), surface->height(),
                    nullptr, SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
        if (0 == access(t->filename.c_str(), F_OK)) {
            task->setResult(false);
            return;
        }

        SkFILEWStream stream(t->filename.c_str());
        if (stream.isValid()) {
            stream.write(t->data->data(), t->data->size());
            stream.flush();
            SkDebugf("SKP Captured Drawing Output (%d bytes) for frame. %s",
                    stream.bytesWritten(), t->filename.c_str());
        }

    renderFrameImpl(layers, clip, nodes, opaque, wideColorGamut, contentDrawBounds, canvas);
        task->setResult(true);
    }
};

    if (skpCaptureEnabled() && recordingPicture) {
        sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
SkCanvas* SkiaPipeline::tryCapture(SkSurface* surface) {
    if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
        bool recordingPicture = mCaptureSequence > 0;
        char prop[PROPERTY_VALUE_MAX] = {'\0'};
        if (!recordingPicture) {
            property_get(PROPERTY_CAPTURE_SKP_FILENAME, prop, "0");
            recordingPicture = prop[0] != '0'
                    && mCapturedFile != prop; //ensure we capture only once per filename
            if (recordingPicture) {
                mCapturedFile = prop;
                mCaptureSequence = property_get_int32(PROPERTY_CAPTURE_SKP_FRAMES, 1);
            }
        }
        if (recordingPicture) {
            mRecorder.reset(new SkPictureRecorder());
            return mRecorder->beginRecording(surface->width(), surface->height(), nullptr,
                    SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
        }
    }
    return surface->getCanvas();
}

void SkiaPipeline::endCapture(SkSurface* surface) {
    if (CC_UNLIKELY(mRecorder.get())) {
        sk_sp<SkPicture> picture = mRecorder->finishRecordingAsPicture();
        surface->getCanvas()->drawPicture(picture);
        if (picture->approximateOpCount() > 0) {
            SkFILEWStream stream(prop);
            if (stream.isValid()) {
            SkDynamicMemoryWStream stream;
            PngPixelSerializer serializer;
            picture->serialize(&stream, &serializer);
                stream.flush();
                SkDebugf("Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), prop);

            //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(stream.detachAsData(), mCapturedFile);
            } else {
                mSavePictureProcessor->savePicture(stream.detachAsData(),
                                        mCapturedFile + "_" + std::to_string(mCaptureSequence));
            }
        surface->getCanvas()->drawPicture(picture);
            mCaptureSequence--;
        }
        mRecorder.reset();
    }
}

void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
        const std::vector<sp<RenderNode>>& nodes, bool opaque, bool wideColorGamut,
        const Rect &contentDrawBounds, sk_sp<SkSurface> surface) {

    renderVectorDrawableCache();

    // draw all layers up front
    renderLayersImpl(layers, opaque, wideColorGamut);

    // initialize the canvas for the current frame, that might be a recording canvas if SKP
    // capture is enabled.
    std::unique_ptr<SkPictureRecorder> recorder;
    SkCanvas* canvas = tryCapture(surface.get());

    renderFrameImpl(layers, clip, nodes, opaque, wideColorGamut, contentDrawBounds, canvas);

    endCapture(surface.get());

    if (CC_UNLIKELY(Properties::debugOverdraw)) {
        renderOverdraw(layers, clip, nodes, contentDrawBounds, surface);
    }

    ATRACE_NAME("flush commands");
    canvas->flush();
    surface->getCanvas()->flush();
}

namespace {
Loading