예제 #1
0
// This test case exercises the public API of the GrLayerCache class.
// In particular it checks its interaction with the resource cache (w.r.t.
// locking & unlocking textures).
// TODO: need to add checks on VRAM usage!
DEF_GPUTEST(GpuLayerCache, reporter, factory) {

    GrContext* context = factory->get(GrContextFactory::kNative_GLContextType);
    if (NULL == context) {
        return;
    }

    SkPicture picture;

    GrLayerCache cache(context);

    create_layers(reporter, &cache, picture);

    // Lock the layers making them all 512x512
    GrTextureDesc desc;
    desc.fWidth = 512;
    desc.fHeight = 512;
    desc.fConfig = kSkia8888_GrPixelConfig;

    for (int i = 0; i < kNumLayers; ++i) {
        GrCachedLayer* layer = cache.findLayer(&picture, i);
        REPORTER_ASSERT(reporter, NULL != layer);

        bool foundInCache = cache.lock(layer, desc);
        REPORTER_ASSERT(reporter, !foundInCache);
        foundInCache = cache.lock(layer, desc);
        REPORTER_ASSERT(reporter, foundInCache);

        REPORTER_ASSERT(reporter, NULL != layer->texture());
#if USE_ATLAS
        // The first 4 layers should be in the atlas (and thus have non-empty
        // rects)
        if (i < 4) {
            REPORTER_ASSERT(reporter, !layer->rect().isEmpty());
        } else {
#endif
            REPORTER_ASSERT(reporter, layer->rect().isEmpty());
#if USE_ATLAS
        }
#endif
    }

    // Unlock the textures
    for (int i = 0; i < kNumLayers; ++i) {
        GrCachedLayer* layer = cache.findLayer(&picture, i);
        REPORTER_ASSERT(reporter, NULL != layer);

        cache.unlock(layer);
    }

    for (int i = 0; i < kNumLayers; ++i) {
        GrCachedLayer* layer = cache.findLayer(&picture, i);
        REPORTER_ASSERT(reporter, NULL != layer);

#if USE_ATLAS
        // The first 4 layers should be in the atlas (and thus do not 
        // currently unlock). The final layer should be unlocked.
        if (i < 4) {
            REPORTER_ASSERT(reporter, NULL != layer->texture());
            REPORTER_ASSERT(reporter, !layer->rect().isEmpty());
        } else {
#endif
            REPORTER_ASSERT(reporter, NULL == layer->texture());
            REPORTER_ASSERT(reporter, layer->rect().isEmpty());
#if USE_ATLAS
        }
#endif
    }

    // Free them all SkGpuDevice-style. This will not free up the
    // atlas' texture but will eliminate all the layers.
    cache.purge(&picture);

    REPORTER_ASSERT(reporter, GetNumLayers::NumLayers(&cache) == 0);
    // TODO: add VRAM/resource cache check here
#if 0
    // Re-create the layers
    create_layers(reporter, &cache, picture);

    // Free them again GrContext-style. This should free up everything.
    cache.freeAll();

    REPORTER_ASSERT(reporter, GetNumLayers::NumLayers(&cache) == 0);
    // TODO: add VRAM/resource cache check here
#endif
}
예제 #2
0
void GrLayerHoister::DrawLayers(const SkTDArray<GrHoistedLayer>& atlased,
                                const SkTDArray<GrHoistedLayer>& nonAtlased,
                                const SkTDArray<GrHoistedLayer>& recycled,
                                GrReplacements* replacements) {
    // Render the atlased layers that require it
    if (atlased.count() > 0) {
        // All the atlased layers are rendered into the same GrTexture
        SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
                                        atlased[0].fLayer->texture()->asRenderTarget(), NULL));

        SkCanvas* atlasCanvas = surface->getCanvas();

        SkPaint paint;
        paint.setColor(SK_ColorTRANSPARENT);
        paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref();

        for (int i = 0; i < atlased.count(); ++i) {
            GrCachedLayer* layer = atlased[i].fLayer;
            const SkPicture* pict = atlased[i].fPicture;
            const SkIPoint offset = atlased[i].fOffset;

            atlasCanvas->save();

            // Add a rect clip to make sure the rendering doesn't
            // extend beyond the boundaries of the atlased sub-rect
            SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
                                            SkIntToScalar(layer->rect().fTop),
                                            SkIntToScalar(layer->rect().width()),
                                            SkIntToScalar(layer->rect().height()));
            atlasCanvas->clipRect(bound);

            // Since 'clear' doesn't respect the clip we need to draw a rect
            // TODO: ensure none of the atlased layers contain a clear call!
            atlasCanvas->drawRect(bound, paint);

            // info.fCTM maps the layer's top/left to the origin.
            // Since this layer is atlased, the top/left corner needs
            // to be offset to the correct location in the backing texture.
            SkMatrix initialCTM;
            initialCTM.setTranslate(SkIntToScalar(-offset.fX), 
                                    SkIntToScalar(-offset.fY));
            initialCTM.postTranslate(bound.fLeft, bound.fTop);
            
            atlasCanvas->translate(SkIntToScalar(-offset.fX), 
                                   SkIntToScalar(-offset.fY));
            atlasCanvas->translate(bound.fLeft, bound.fTop);
            atlasCanvas->concat(atlased[i].fCTM);

            SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound,
                                layer->start()+1, layer->stop(), initialCTM);

            atlasCanvas->restore();
        }

        atlasCanvas->flush();
    }

    // Render the non-atlased layers that require it
    for (int i = 0; i < nonAtlased.count(); ++i) {
        GrCachedLayer* layer = nonAtlased[i].fLayer;
        const SkPicture* pict = nonAtlased[i].fPicture;
        const SkIPoint offset = nonAtlased[i].fOffset;

        // Each non-atlased layer has its own GrTexture
        SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
                                        layer->texture()->asRenderTarget(), NULL));

        SkCanvas* layerCanvas = surface->getCanvas();

        // Add a rect clip to make sure the rendering doesn't
        // extend beyond the boundaries of the atlased sub-rect
        SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft),
                                        SkIntToScalar(layer->rect().fTop),
                                        SkIntToScalar(layer->rect().width()),
                                        SkIntToScalar(layer->rect().height()));

        layerCanvas->clipRect(bound); // TODO: still useful?

        layerCanvas->clear(SK_ColorTRANSPARENT);

        SkMatrix initialCTM;
        initialCTM.setTranslate(SkIntToScalar(-offset.fX), 
                                SkIntToScalar(-offset.fY));

        layerCanvas->translate(SkIntToScalar(-offset.fX), 
                               SkIntToScalar(-offset.fY));
        layerCanvas->concat(nonAtlased[i].fCTM);

        SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound,
                            layer->start()+1, layer->stop(), initialCTM);

        layerCanvas->flush();
    }

    convert_layers_to_replacements(atlased, replacements);
    convert_layers_to_replacements(nonAtlased, replacements);
    convert_layers_to_replacements(recycled, replacements);
}