Пример #1
0
// This tests that GrTextureStripAtlas flushes pending IO on the texture it acquires.
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrTextureStripAtlasFlush, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    GrSurfaceDesc desc;
    desc.fWidth = 32;
    desc.fHeight = 32;
    desc.fConfig = kRGBA_8888_GrPixelConfig;
    GrTexture* texture = context->textureProvider()->createTexture(desc, SkBudgeted::kYes,
                                                                   nullptr, 0);

    GrSurfaceDesc targetDesc = desc;
    targetDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    GrTexture* target = context->textureProvider()->createTexture(targetDesc, SkBudgeted::kYes,
                                                                  nullptr, 0);

    SkAutoTMalloc<uint32_t> pixels(desc.fWidth * desc.fHeight);
    memset(pixels.get(), 0xFF, sizeof(uint32_t) * desc.fWidth * desc.fHeight);
    texture->writePixels(0, 0, desc.fWidth, desc.fHeight, kRGBA_8888_GrPixelConfig, pixels.get());

    // Add a pending read to the texture, and then make it available for reuse.
    context->copySurface(target, texture);
    texture->unref();

    // Create an atlas with parameters that allow it to reuse the texture.
    GrTextureStripAtlas::Desc atlasDesc;
    atlasDesc.fContext = context;
    atlasDesc.fConfig = desc.fConfig;
    atlasDesc.fWidth = desc.fWidth;
    atlasDesc.fHeight = desc.fHeight;
    atlasDesc.fRowHeight = 1;
    GrTextureStripAtlas* atlas = GrTextureStripAtlas::GetAtlas(atlasDesc);

    // Write to the atlas' texture.
    SkImageInfo info = SkImageInfo::MakeN32(desc.fWidth, desc.fHeight, kPremul_SkAlphaType);
    size_t rowBytes = desc.fWidth * GrBytesPerPixel(desc.fConfig);
    SkBitmap bitmap;
    bitmap.allocPixels(info, rowBytes);
    memset(bitmap.getPixels(), 1, rowBytes * desc.fHeight);
    int row = atlas->lockRow(bitmap);
    if (!context->caps()->preferVRAMUseOverFlushes())
        REPORTER_ASSERT(reporter, texture == atlas->getTexture());

    // The atlas' use of its texture shouldn't change which pixels got copied to the target.
    SkAutoTMalloc<uint32_t> actualPixels(desc.fWidth * desc.fHeight);
    bool success = target->readPixels(0, 0, desc.fWidth, desc.fHeight, kRGBA_8888_GrPixelConfig,
                                      actualPixels.get());
    REPORTER_ASSERT(reporter, success);
    REPORTER_ASSERT(reporter,
                    !memcmp(pixels.get(), actualPixels.get(),
                            sizeof(uint32_t) * desc.fWidth * desc.fHeight));
    target->unref();
    atlas->unlockRow(row);
}
Пример #2
0
    virtual void onDraw(SkCanvas* canvas) {
        SkDevice* device = canvas->getDevice();
        GrRenderTarget* target = (GrRenderTarget*) device->accessRenderTarget();
        GrContext* ctx = GetGr();
        if (ctx && target) {
            SkPMColor gTextureData[(2 * S) * (2 * S)];
            static const int stride = 2 * S;
            static const SkPMColor gray  = SkPackARGB32(0x40, 0x40, 0x40, 0x40);
            static const SkPMColor white = SkPackARGB32(0xff, 0xff, 0xff, 0xff);
            static const SkPMColor red   = SkPackARGB32(0x80, 0x80, 0x00, 0x00);
            static const SkPMColor blue  = SkPackARGB32(0x80, 0x00, 0x00, 0x80);
            static const SkPMColor green = SkPackARGB32(0x80, 0x00, 0x80, 0x00);
            static const SkPMColor black = SkPackARGB32(0x00, 0x00, 0x00, 0x00);
            for (int i = 0; i < 2; ++i) {
                int offset = 0;
                // fill upper-left
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = gray;
                    }
                }
                // fill upper-right
                offset = S;
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = white;
                    }
                }
                // fill lower left
                offset = S * stride;
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = black;
                    }
                }
                // fill lower right
                offset = S * stride + S;
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = gray;
                    }
                }

                GrTextureDesc desc;
                desc.fAALevel   = kNone_GrAALevel;
                // use RT flag bit because in GL it makes the texture be bottom-up
                desc.fFlags     = i ? kRenderTarget_GrTextureFlagBit :
                                      kNone_GrTextureFlags;
                desc.fConfig    = kSkia8888_PM_GrPixelConfig;
                desc.fWidth     = 2 * S;
                desc.fHeight    = 2 * S;
                GrTexture* texture = 
                    ctx->createUncachedTexture(desc, gTextureData, 0);

                if (!texture) {
                    return;
                }
                GrAutoUnref au(texture);

                ctx->setClip(GrRect::MakeWH(2*S, 2*S));
                ctx->setRenderTarget(target);

                GrPaint paint;
                paint.reset();
                paint.fColor = 0xffffffff;
                paint.fSrcBlendCoeff = kOne_BlendCoeff;
                paint.fDstBlendCoeff = kISA_BlendCoeff;
                GrMatrix vm;
                if (i) {
                    vm.setRotate(90 * SK_Scalar1,
                                 S * SK_Scalar1,
                                 S * SK_Scalar1);
                } else {
                    vm.reset();
                }
                ctx->setMatrix(vm);
                GrMatrix tm;
                tm = vm;
                tm.postIDiv(2*S, 2*S);
                paint.textureSampler(0)->setMatrix(tm);
                paint.setTexture(0, texture);

                ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S));

                // now update the lower right of the texture in first pass
                // or upper right in second pass
                offset = 0;
                for (int y = 0; y < S; ++y) {
                    for (int x = 0; x < S; ++x) {
                        gTextureData[offset + y * stride + x] = 
                            ((x + y) % 2) ? (i ? green : red) : blue;
                    }
                }
                texture->writePixels(S, (i ? 0 : S), S, S,
                                     texture->config(), gTextureData,
                                     4 * stride);
                ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S));
            }
        }
    }
Пример #3
0
static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
                                              bool cache,
                                              const GrTextureParams* params,
                                              const SkBitmap& origBitmap) {
    SkAutoLockPixels alp(origBitmap);

    if (!origBitmap.readyToDraw()) {
        return NULL;
    }

    SkBitmap tmpBitmap;

    const SkBitmap* bitmap = &origBitmap;

    GrTextureDesc desc;
    generate_bitmap_texture_desc(*bitmap, &desc);

    if (SkBitmap::kIndex8_Config == bitmap->config()) {
        // build_compressed_data doesn't do npot->pot expansion
        // and paletted textures can't be sub-updated
        if (ctx->supportsIndex8PixelConfig(params,
                                           bitmap->width(), bitmap->height())) {
            size_t imagesize = bitmap->width() * bitmap->height() +
                                kGrColorTableSize;
            SkAutoMalloc storage(imagesize);

            build_compressed_data(storage.get(), origBitmap);

            // our compressed data will be trimmed, so pass width() for its
            // "rowBytes", since they are the same now.

            if (cache) {
                GrCacheID cacheID;
                generate_bitmap_cache_id(origBitmap, &cacheID);
                return ctx->createTexture(params, desc, cacheID, storage.get(), bitmap->width());
            } else {
                GrTexture* result = ctx->lockAndRefScratchTexture(desc,
                                                            GrContext::kExact_ScratchTexMatch);
                result->writePixels(0, 0, bitmap->width(),
                                    bitmap->height(), desc.fConfig,
                                    storage.get());
                return result;
            }
        } else {
            origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config);
            // now bitmap points to our temp, which has been promoted to 32bits
            bitmap = &tmpBitmap;
            desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config());
        }
    }

    if (cache) {
        // This texture is likely to be used again so leave it in the cache
        GrCacheID cacheID;
        generate_bitmap_cache_id(origBitmap, &cacheID);
        return ctx->createTexture(params, desc, cacheID, bitmap->getPixels(), bitmap->rowBytes());
    } else {
        // This texture is unlikely to be used again (in its present form) so
        // just use a scratch texture. This will remove the texture from the
        // cache so no one else can find it. Additionally, once unlocked, the
        // scratch texture will go to the end of the list for purging so will
        // likely be available for this volatile bitmap the next time around.
        GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch);
        result->writePixels(0, 0,
                            bitmap->width(), bitmap->height(),
                            desc.fConfig,
                            bitmap->getPixels(),
                            bitmap->rowBytes());
        return result;
    }
}
Пример #4
0
DEF_GPUTEST(ReadWriteAlpha, reporter, factory) {
    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
        if (!GrContextFactory::IsRenderingGLContext(glType)) {
            continue;
        }
        GrContext* context = factory->get(glType);
        if (NULL == context) {
            continue;
        }

        unsigned char textureData[X_SIZE][Y_SIZE];

        memset(textureData, 0, X_SIZE * Y_SIZE);

        GrSurfaceDesc desc;

        // let Skia know we will be using this texture as a render target
        desc.fFlags     = kRenderTarget_GrSurfaceFlag;
        // it is a single channel texture
        desc.fConfig    = kAlpha_8_GrPixelConfig;
        desc.fWidth     = X_SIZE;
        desc.fHeight    = Y_SIZE;

        // We are initializing the texture with zeros here
        GrTexture* texture = context->createTexture(desc, false, textureData, 0);
        if (!texture) {
            return;
        }

        SkAutoTUnref<GrTexture> au(texture);

        // create a distinctive texture
        for (int y = 0; y < Y_SIZE; ++y) {
            for (int x = 0; x < X_SIZE; ++x) {
                textureData[x][y] = x*Y_SIZE+y;
            }
        }

        // upload the texture
        texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
                             textureData, 0);

        unsigned char readback[X_SIZE][Y_SIZE];

        // clear readback to something non-zero so we can detect readback failures
        memset(readback, 0x1, X_SIZE * Y_SIZE);

        // read the texture back
        texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
                            readback, 0);

        // make sure the original & read back versions match
        bool match = true;

        for (int y = 0; y < Y_SIZE; ++y) {
            for (int x = 0; x < X_SIZE; ++x) {
                if (textureData[x][y] != readback[x][y]) {
                    match = false;
                }
            }
        }

        REPORTER_ASSERT(reporter, match);

        // Now try writing on the single channel texture
        SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
        SkAutoTUnref<SkBaseDevice> device(SkGpuDevice::Create(texture->asRenderTarget(), &props));
        SkCanvas canvas(device);

        SkPaint paint;

        const SkRect rect = SkRect::MakeLTRB(-10, -10, X_SIZE + 10, Y_SIZE + 10);

        paint.setColor(SK_ColorWHITE);

        canvas.drawRect(rect, paint);

        texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
                            readback, 0);

        match = true;

        for (int y = 0; y < Y_SIZE; ++y) {
            for (int x = 0; x < X_SIZE; ++x) {
                if (0xFF != readback[x][y]) {
                    match = false;
                }
            }
        }

        REPORTER_ASSERT(reporter, match);
    }
}