Пример #1
0
DEF_TEST(DontOptimizeSaveLayerDrawDrawRestore, reporter) {
    // This test is from crbug.com/344987.
    // The commands are:
    //   saveLayer with paint that modifies alpha
    //     drawBitmapRect
    //     drawBitmapRect
    //   restore
    // The bug was that this structure was modified so that:
    //  - The saveLayer and restore were eliminated
    //  - The alpha was only applied to the first drawBitmapRectToRect

    // This test draws blue and red squares inside a 50% transparent
    // layer.  Both colours should show up muted.
    // When the bug is present, the red square (the second bitmap)
    // shows upwith full opacity.

    SkBitmap blueBM;
    make_bm(&blueBM, 100, 100, SkColorSetARGB(255, 0, 0, 255), true);
    SkBitmap redBM;
    make_bm(&redBM, 100, 100, SkColorSetARGB(255, 255, 0, 0), true);
    SkPaint semiTransparent;
    semiTransparent.setAlpha(0x80);

    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording(100, 100);
    canvas->drawARGB(0, 0, 0, 0);

    canvas->saveLayer(0, &semiTransparent);
    canvas->drawBitmap(blueBM, 25, 25);
    canvas->drawBitmap(redBM, 50, 50);
    canvas->restore();

    sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());

    // Now replay the picture back on another canvas
    // and check a couple of its pixels.
    SkBitmap replayBM;
    make_bm(&replayBM, 100, 100, SK_ColorBLACK, false);
    SkCanvas replayCanvas(replayBM);
    picture->playback(&replayCanvas);
    replayCanvas.flush();

    // With the bug present, at (55, 55) we would get a fully opaque red
    // intead of a dark red.
    REPORTER_ASSERT(reporter, replayBM.getColor(30, 30) == 0xff000080);
    REPORTER_ASSERT(reporter, replayBM.getColor(55, 55) == 0xff800000);
}
Пример #2
0
static void test_gen_id(skiatest::Reporter* reporter) {

    SkPictureRecorder recorder;
    recorder.beginRecording(0, 0);
    sk_sp<SkPicture> empty(recorder.finishRecordingAsPicture());

    // Empty pictures should still have a valid ID
    REPORTER_ASSERT(reporter, empty->uniqueID() != SK_InvalidGenID);

    SkCanvas* canvas = recorder.beginRecording(1, 1);
    canvas->drawARGB(255, 255, 255, 255);
    sk_sp<SkPicture> hasData(recorder.finishRecordingAsPicture());
    // picture should have a non-zero id after recording
    REPORTER_ASSERT(reporter, hasData->uniqueID() != SK_InvalidGenID);

    // both pictures should have different ids
    REPORTER_ASSERT(reporter, hasData->uniqueID() != empty->uniqueID());
}
Пример #3
0
CanvasLayer::CanvasLayer(const CanvasLayer& layer)
    : LayerAndroid(layer)
    , m_canvas(0)
    , m_bitmap(0)
    , m_gpuCanvas(0)
{
    init();
    if (!layer.m_canvas) {
        // The canvas has already been destroyed - this shouldn't happen
        ALOGW("Creating a CanvasLayer for a destroyed canvas!");
        m_visibleContentRect = IntRect();
        m_offsetFromRenderer = IntSize();
        m_texture->setHwAccelerated(false);
        return;
    }
    // We are making a copy for the UI, sync the interesting bits
    m_visibleContentRect = layer.visibleContentRect();
    m_offsetFromRenderer = layer.offsetFromRenderer();
    bool previousState = m_texture->hasValidTexture();

    if(layer.m_canvas->isUsingGpuRendering())
        return;

    ImageBuffer* imageBuffer = layer.m_canvas->buffer();
    
    if (!previousState && layer.m_dirtyCanvas.isEmpty() && imageBuffer && !(imageBuffer->drawsUsingRecording())) {
        // We were previously in software and don't have anything new to draw,
        // so stay in software
        m_bitmap = layer.bitmap();
        SkSafeRef(m_bitmap);
    } else {

        if(imageBuffer && imageBuffer->drawsUsingRecording() && !layer.m_canvas->isUsingGpuRendering())
        {
            bool canUseGpuRendering = imageBuffer->canUseGpuRendering();

            if(canUseGpuRendering && layer.m_canvas->canUseGpuRendering())
            {
                layer.m_canvas->enableGpuRendering();
                CanvasLayer::setGpuCanvasStatus(layer.uniqueId(), true);
            }
        }

        // If recording is being used
        if(imageBuffer && imageBuffer->drawsUsingRecording())
        {
            GraphicsContext* gc = imageBuffer->context();
            //SkPicture* canvasRecording = gc->platformContext()->getRecordingPicture();

            SkPicture* canvasRecording = CanvasLayer::getRecordingPicture(this);
            SkBitmap* bitmap = CanvasLayer::getRecordingBitmap(this);
            SkCanvas* canvas = CanvasLayer::getRecordingCanvas(this);

            if(canvasRecording == NULL)
                return;

            if(bitmap == NULL || bitmap->width() != canvasRecording->width()
                    || bitmap->height() != canvasRecording->height())
            {
                SkBitmap* newBitmap = new SkBitmap();
                newBitmap->setConfig(SkBitmap::kARGB_8888_Config, canvasRecording->width(), canvasRecording->height());
                newBitmap->allocPixels();
                newBitmap->eraseColor(0);
                CanvasLayer::setRecordingBitmap(newBitmap, this);
                bitmap = newBitmap;
                if(canvas != NULL)
                    canvas->setBitmapDevice(*bitmap);
            }

            if(canvas == NULL)
            {
                canvas = new SkCanvas();
                canvas->setBitmapDevice(*bitmap);
                CanvasLayer::setRecordingCanvas(canvas, this);
            }

            canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
            canvasRecording->draw(canvas);

            if (!m_texture->uploadImageBitmap(bitmap)) {
                //SLOGD("+++++++++++++++++++++ Didn't upload bitmap .. fall back to software");
                // TODO:: Fix this
            }
        }
        else
        {
            if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) {
                // Blargh, no surface texture or ImageBuffer - fall back to software
                m_bitmap = layer.bitmap();
                SkSafeRef(m_bitmap);
                // Merge the canvas invals with the layer's invals to repaint the needed
                // tiles.
                SkRegion::Iterator iter(layer.m_dirtyCanvas);
                const IntPoint& offset = m_visibleContentRect.location();
                for (; !iter.done(); iter.next()) {
                    SkIRect diff = iter.rect();
                    diff.fLeft += offset.x();
                    diff.fRight += offset.x();
                    diff.fTop += offset.y();
                    diff.fBottom += offset.y();
                    m_dirtyRegion.op(diff, SkRegion::kUnion_Op);
                }
            }else{
                ImageBuffer* imageBuffer = layer.m_canvas->buffer();
                bool recordingCanvasEnabled = layer.m_canvas->isRecordingCanvasEnabled();

                if(recordingCanvasEnabled && imageBuffer && imageBuffer->isAnimating()){
                    SLOGD("[%s] Animation detected. Converting the HTML5 canvas buffer to a SkPicture.", __FUNCTION__);
                    imageBuffer->convertToRecording();
                }
            }//End of non-recording
        }
        if (previousState != m_texture->hasValidTexture()) {
            // Need to do a full inval of the canvas content as we are mode switching
            m_dirtyRegion.op(m_visibleContentRect.x(), m_visibleContentRect.y(),
                    m_visibleContentRect.maxX(), m_visibleContentRect.maxY(), SkRegion::kUnion_Op);
        }
    }
}