inline void GrDistanceFieldTextContext::init(GrRenderTarget* rt, const GrClip& clip,
                                             const GrPaint& paint, const SkPaint& skPaint,
                                             const SkIRect& regionClipBounds) {
    GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds);

    fStrike = NULL;

    const SkMatrix& ctm = fViewMatrix;

    // getMaxScale doesn't support perspective, so neither do we at the moment
    SkASSERT(!ctm.hasPerspective());
    SkScalar maxScale = ctm.getMaxScale();
    SkScalar textSize = fSkPaint.getTextSize();
    SkScalar scaledTextSize = textSize;
    // if we have non-unity scale, we need to choose our base text size
    // based on the SkPaint's text size multiplied by the max scale factor
    // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
    if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
        scaledTextSize *= maxScale;
    }

    fVertices = NULL;
    fCurrVertex = 0;
    fAllocVertexCount = 0;
    fTotalVertexCount = 0;

    if (scaledTextSize <= kSmallDFFontLimit) {
        fTextRatio = textSize / kSmallDFFontSize;
        fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
#if DEBUG_TEXT_SIZE
        fSkPaint.setColor(SkColorSetARGB(0xFF, 0x00, 0x00, 0x7F));
        fPaint.setColor(GrColorPackRGBA(0x00, 0x00, 0x7F, 0xFF));
#endif
    } else if (scaledTextSize <= kMediumDFFontLimit) {
        fTextRatio = textSize / kMediumDFFontSize;
        fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
#if DEBUG_TEXT_SIZE
        fSkPaint.setColor(SkColorSetARGB(0xFF, 0x00, 0x3F, 0x00));
        fPaint.setColor(GrColorPackRGBA(0x00, 0x3F, 0x00, 0xFF));
#endif
    } else {
        fTextRatio = textSize / kLargeDFFontSize;
        fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
#if DEBUG_TEXT_SIZE
        fSkPaint.setColor(SkColorSetARGB(0xFF, 0x7F, 0x00, 0x00));
        fPaint.setColor(GrColorPackRGBA(0x7F, 0x00, 0x00, 0xFF));
#endif
    }

    fUseLCDText = fSkPaint.isLCDRenderText();

    fSkPaint.setLCDRenderText(false);
    fSkPaint.setAutohinted(false);
    fSkPaint.setHinting(SkPaint::kNormal_Hinting);
    fSkPaint.setSubpixelText(true);
}
static void test_clear(skiatest::Reporter* reporter, GrContext* context,
                       GrTexture* rectangleTexture) {
    if (rectangleTexture->asRenderTarget()) {
        sk_sp<GrDrawContext> dc(
                            context->drawContext(sk_ref_sp(rectangleTexture->asRenderTarget()),
                                                 nullptr));
        if (!dc) {
            ERRORF(reporter, "Could not get GrDrawContext for rectangle texture.");
            return;
        }

        // Clear the whole thing.
        GrColor color0 = GrColorPackRGBA(0xA, 0xB, 0xC, 0xD);
        dc->clear(nullptr, color0, false);

        int w = rectangleTexture->width();
        int h = rectangleTexture->height();
        int pixelCnt = w * h;
        SkAutoTMalloc<uint32_t> expectedPixels(pixelCnt);

        // The clear color is a GrColor, our readback is to kRGBA_8888, which may be different.
        uint32_t expectedColor0 = 0;
        uint8_t* expectedBytes0 = SkTCast<uint8_t*>(&expectedColor0);
        expectedBytes0[0] = GrColorUnpackR(color0);
        expectedBytes0[1] = GrColorUnpackG(color0);
        expectedBytes0[2] = GrColorUnpackB(color0);
        expectedBytes0[3] = GrColorUnpackA(color0);
        for (int i = 0; i < rectangleTexture->width() * rectangleTexture->height(); ++i) {
            expectedPixels.get()[i] = expectedColor0;
        }

        // Clear the the top to a different color.
        GrColor color1 = GrColorPackRGBA(0x1, 0x2, 0x3, 0x4);
        SkIRect rect = SkIRect::MakeWH(w, h/2);
        dc->clear(&rect, color1, false);

        uint32_t expectedColor1 = 0;
        uint8_t* expectedBytes1 = SkTCast<uint8_t*>(&expectedColor1);
        expectedBytes1[0] = GrColorUnpackR(color1);
        expectedBytes1[1] = GrColorUnpackG(color1);
        expectedBytes1[2] = GrColorUnpackB(color1);
        expectedBytes1[3] = GrColorUnpackA(color1);

        for (int y = 0; y < h/2; ++y) {
            for (int x = 0; x < w; ++x) {
                expectedPixels.get()[y * h + x] = expectedColor1;
            }
        }

        test_read_pixels(reporter, context, rectangleTexture, expectedPixels.get());
    }
}
void test_write_pixels(skiatest::Reporter* reporter,
                       GrSurfaceContext* dstContext, bool expectedToWork,
                       const char* testName) {
    int pixelCnt = dstContext->width() * dstContext->height();
    SkAutoTMalloc<uint32_t> pixels(pixelCnt);
    for (int y = 0; y < dstContext->width(); ++y) {
        for (int x = 0; x < dstContext->height(); ++x) {
            pixels.get()[y * dstContext->width() + x] =
                GrPremulColor(GrColorPackRGBA(x, y, x + y, 2*y));
        }
    }

    SkImageInfo ii = SkImageInfo::Make(dstContext->width(), dstContext->height(),
                                       kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    bool write = dstContext->writePixels(ii, pixels.get(), 0, 0, 0);
    if (!write) {
        if (expectedToWork) {
            ERRORF(reporter, "%s: Error writing to texture.", testName);
        }
        return;
    }

    if (write && !expectedToWork) {
        ERRORF(reporter, "%s: writePixels succeeded when it wasn't supposed to.", testName);
        return;
    }

    test_read_pixels(reporter, dstContext, pixels.get(), testName);
}
Example #4
0
bool does_full_buffer_contain_correct_color(GrColor* buffer,
                                            GrColor clearColor,
                                            GrPixelConfig config,
                                            int width,
                                            int height) {
    GrColor matchColor;
    if (kRGBA_8888_GrPixelConfig == config) {
        matchColor = clearColor;
    } else if (kBGRA_8888_GrPixelConfig) {
        // Hack to flip the R, B componets in the GrColor so that the comparrison will work below
        matchColor = GrColorPackRGBA(GrColorUnpackB(clearColor),
                                     GrColorUnpackG(clearColor),
                                     GrColorUnpackR(clearColor),
                                     GrColorUnpackA(clearColor));
    } else {
        // currently only supporting rgba_8888 and bgra_8888
        return false;
    }

    for (int j = 0; j < height; ++j) {
        for (int i = 0; i < width; ++i) {
            if (buffer[j * width + i] != matchColor) {
                return false;
            }
        }
    }
    return true;
}
void test_copy_to_surface(skiatest::Reporter* reporter, GrProxyProvider* proxyProvider,
                          GrSurfaceContext* dstContext, const char* testName) {

    int pixelCnt = dstContext->width() * dstContext->height();
    SkAutoTMalloc<uint32_t> pixels(pixelCnt);
    for (int y = 0; y < dstContext->width(); ++y) {
        for (int x = 0; x < dstContext->height(); ++x) {
            pixels.get()[y * dstContext->width() + x] =
                GrPremulColor(GrColorPackRGBA(y, x, x * y, 2*y));
        }
    }

    GrSurfaceDesc copySrcDesc;
    copySrcDesc.fWidth = dstContext->width();
    copySrcDesc.fHeight = dstContext->height();
    copySrcDesc.fConfig = kRGBA_8888_GrPixelConfig;

    for (auto flags : { kNone_GrSurfaceFlags, kRenderTarget_GrSurfaceFlag }) {
        copySrcDesc.fFlags = flags;
        copySrcDesc.fOrigin = (kNone_GrSurfaceFlags == flags) ? kTopLeft_GrSurfaceOrigin
                                                              : kBottomLeft_GrSurfaceOrigin;

        sk_sp<GrTextureProxy> src = proxyProvider->createTextureProxy(copySrcDesc, SkBudgeted::kYes,
                                                                      pixels.get(), 0);

        dstContext->copy(src.get());

        test_read_pixels(reporter, dstContext, pixels.get(), testName);
    }
}
Example #6
0
static void test_clear(skiatest::Reporter* reporter, GrSurfaceContext* rectContext) {
    if (GrRenderTargetContext* rtc = rectContext->asRenderTargetContext()) {
        // Clear the whole thing.
        GrColor color0 = GrColorPackRGBA(0xA, 0xB, 0xC, 0xD);
        rtc->clear(nullptr, color0, GrRenderTargetContext::CanClearFullscreen::kNo);

        int w = rtc->width();
        int h = rtc->height();
        int pixelCnt = w * h;
        SkAutoTMalloc<uint32_t> expectedPixels(pixelCnt);

        // The clear color is a GrColor, our readback is to kRGBA_8888, which may be different.
        uint32_t expectedColor0 = 0;
        uint8_t* expectedBytes0 = SkTCast<uint8_t*>(&expectedColor0);
        expectedBytes0[0] = GrColorUnpackR(color0);
        expectedBytes0[1] = GrColorUnpackG(color0);
        expectedBytes0[2] = GrColorUnpackB(color0);
        expectedBytes0[3] = GrColorUnpackA(color0);
        for (int i = 0; i < rtc->width() * rtc->height(); ++i) {
            expectedPixels.get()[i] = expectedColor0;
        }

        // Clear the the top to a different color.
        GrColor color1 = GrColorPackRGBA(0x1, 0x2, 0x3, 0x4);
        SkIRect rect = SkIRect::MakeWH(w, h/2);
        rtc->clear(&rect, color1, GrRenderTargetContext::CanClearFullscreen::kNo);

        uint32_t expectedColor1 = 0;
        uint8_t* expectedBytes1 = SkTCast<uint8_t*>(&expectedColor1);
        expectedBytes1[0] = GrColorUnpackR(color1);
        expectedBytes1[1] = GrColorUnpackG(color1);
        expectedBytes1[2] = GrColorUnpackB(color1);
        expectedBytes1[3] = GrColorUnpackA(color1);

        for (int y = 0; y < h/2; ++y) {
            for (int x = 0; x < w; ++x) {
                expectedPixels.get()[y * h + x] = expectedColor1;
            }
        }

        test_read_pixels(reporter, rtc, expectedPixels.get(), "RectangleTexture-clear");
    }
}
GrXferProcessor::OptFlags
PDLCDXferProcessor::onGetOptimizations(const GrPipelineOptimizations& optimizations,
                                       bool doesStencilWrite,
                                       GrColor* overrideColor,
                                       const GrCaps& caps) const {
        // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
        // value of the blend the constant. We should already have valid blend coeff's if we are at
        // a point where we have RGB coverage. We don't need any color stages since the known color
        // output is already baked into the blendConstant.
        *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha);
        return GrXferProcessor::kOverrideColor_OptFlag;
}
Example #8
0
const GrFragmentProcessor* ModeColorFilterEffect::TestCreate(GrProcessorTestData* d) {
    SkXfermode::Mode mode = SkXfermode::kDst_Mode;
    while (SkXfermode::kDst_Mode == mode) {
        mode = static_cast<SkXfermode::Mode>(d->fRandom->nextRangeU(0, SkXfermode::kLastCoeffMode));
    }

    // pick a random premul color
    uint8_t alpha = d->fRandom->nextULessThan(256);
    GrColor color = GrColorPackRGBA(d->fRandom->nextRangeU(0, alpha),
                                    d->fRandom->nextRangeU(0, alpha),
                                    d->fRandom->nextRangeU(0, alpha),
                                    alpha);
    return ModeColorFilterEffect::Create(color, mode);
}
Example #9
0
void basic_clear_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config) {
    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());
    gpu->discard(NULL);
    SkAutoTMalloc<GrColor> buffer(25);

    GrSurfaceDesc surfDesc;
    surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    surfDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
    surfDesc.fWidth = 5;
    surfDesc.fHeight = 5;
    surfDesc.fConfig = config;
    surfDesc.fSampleCnt = 0;
    GrTexture* tex = gpu->createTexture(surfDesc, false, nullptr, 0);
    SkASSERT(tex);
    SkASSERT(tex->asRenderTarget());
    SkIRect rect = SkIRect::MakeWH(5, 5);

    gpu->clear(rect, GrColor_TRANSPARENT_BLACK, tex->asRenderTarget());

    gpu->readPixels(tex, 0, 0, 5, 5, config, (void*)buffer.get(), 0);

    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(buffer.get(),
                                                                     GrColor_TRANSPARENT_BLACK,
                                                                     config,
                                                                     5,
                                                                     5));

    gpu->clear(rect, GrColor_WHITE, tex->asRenderTarget());

    gpu->readPixels(tex, 0, 0, 5, 5, config, (void*)buffer.get(), 0);

    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(buffer.get(),
                                                                     GrColor_WHITE,
                                                                     config,
                                                                     5,
                                                                     5));

    GrColor myColor = GrColorPackRGBA(0xFF, 0x7F, 0x40, 0x20);

    gpu->clear(rect, myColor, tex->asRenderTarget());

    gpu->readPixels(tex, 0, 0, 5, 5, config, (void*)buffer.get(), 0);

    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(buffer.get(),
                                                                     myColor,
                                                                     config,
                                                                     5,
                                                                     5));
}
bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath,
                                       const SkStrokeRec& stroke,
                                       GrDrawTarget* target,
                                       bool antiAlias) {

    // generate verts using Android algorithm
    android::uirenderer::VertexBuffer vertices;
    android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL,
                                                          &vertices);

    // set vertex layout depending on anti-alias
    GrVertexLayout layout = antiAlias ? GrDrawState::kCoverage_VertexLayoutBit : 0;

    // allocate our vert buffer
    int vertCount = vertices.getSize();
    GrDrawTarget::AutoReleaseGeometry geo(target, layout, vertCount, 0);
    if (!geo.succeeded()) {
        GrPrintf("Failed to get space for vertices!\n");
        return false;
    }

    // copy android verts to our vertex buffer
    if (antiAlias) {
        ColorVertex* outVert = reinterpret_cast<ColorVertex*>(geo.vertices());
        android::uirenderer::AlphaVertex* inVert =
            reinterpret_cast<android::uirenderer::AlphaVertex*>(vertices.getBuffer());

        for (int i = 0; i < vertCount; ++i) {
            // copy vertex position
            outVert->pos.set(inVert->position[0], inVert->position[1]);
            // copy alpha
            int coverage = static_cast<int>(inVert->alpha * 0xff);
            outVert->color = GrColorPackRGBA(coverage, coverage, coverage, coverage);
            ++outVert;
            ++inVert;
        }
    } else {
       size_t vsize = GrDrawState::VertexSize(layout);
       size_t copySize = vsize*vertCount;
       memcpy(geo.vertices(), vertices.getBuffer(), copySize);
    }

    // render it
    target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, vertCount);

    return true;
}
static void test_write_pixels(skiatest::Reporter* reporter, GrContext* context,
                              GrTexture* rectangleTexture) {
    int pixelCnt = rectangleTexture->width() * rectangleTexture->height();
    SkAutoTMalloc<uint32_t> pixels(pixelCnt);
    for (int y = 0; y < rectangleTexture->width(); ++y) {
        for (int x = 0; x < rectangleTexture->height(); ++x) {
            pixels.get()[y * rectangleTexture->width() + x] = GrColorPackRGBA(x, y, x + y, x * y);
        }
    }
    bool write = rectangleTexture->writePixels(0, 0, rectangleTexture->width(),
                                               rectangleTexture->height(), kRGBA_8888_GrPixelConfig,
                                               pixels.get());
    if (!write) {
        ERRORF(reporter, "Error writing to rectangle texture.");
    }
    test_read_pixels(reporter, context, rectangleTexture, pixels.get());
}
Example #12
0
GrFragmentProcessor* ModeColorFilterEffect::TestCreate(SkRandom* rand,
                                                       GrContext*,
                                                       const GrDrawTargetCaps&,
                                                       GrTexture*[]) {
    SkXfermode::Mode mode = SkXfermode::kDst_Mode;
    while (SkXfermode::kDst_Mode == mode) {
        mode = static_cast<SkXfermode::Mode>(rand->nextRangeU(0, SkXfermode::kLastCoeffMode));
    }

    // pick a random premul color
    uint8_t alpha = rand->nextULessThan(256);
    GrColor color = GrColorPackRGBA(rand->nextRangeU(0, alpha),
                                    rand->nextRangeU(0, alpha),
                                    rand->nextRangeU(0, alpha),
                                    alpha);
    return ModeColorFilterEffect::Create(color, mode);
}
Example #13
0
/**
 * Move the result of the software mask generation back to the gpu
 */
void GrSWMaskHelper::toTexture(GrTexture *texture, uint8_t alpha) {
    SkAutoLockPixels alp(fBM);

    // The destination texture is almost always larger than "fBM". Clear
    // it appropriately so we don't get mask artifacts outside of the path's
    // bounding box

    // "texture" needs to be installed as the render target for the clear
    // and the texture upload but cannot remain the render target upon
    // return. Callers typically use it as a texture and it would then
    // be both source and dest.
    GrDrawState::AutoRenderTargetRestore artr(fContext->getGpu()->drawState(),
            texture->asRenderTarget());

    fContext->getGpu()->clear(NULL, GrColorPackRGBA(alpha, alpha, alpha, alpha));

    texture->writePixels(0, 0, fBM.width(), fBM.height(),
                         kAlpha_8_GrPixelConfig,
                         fBM.getPixels(), fBM.rowBytes());
}
static void test_copy_surface_dst(skiatest::Reporter* reporter, GrContext* context,
                                  GrTexture* rectangleTexture) {
    int pixelCnt = rectangleTexture->width() * rectangleTexture->height();
    SkAutoTMalloc<uint32_t> pixels(pixelCnt);
    for (int y = 0; y < rectangleTexture->width(); ++y) {
        for (int x = 0; x < rectangleTexture->height(); ++x) {
            pixels.get()[y * rectangleTexture->width() + x] = GrColorPackRGBA(y, x, x * y, x *+ y);
        }
    }

    GrSurfaceDesc copySrcDesc;
    copySrcDesc.fConfig = kRGBA_8888_GrPixelConfig;
    copySrcDesc.fWidth = rectangleTexture->width();
    copySrcDesc.fHeight = rectangleTexture->height();
    copySrcDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    SkAutoTUnref<GrTexture> src(context->textureProvider()->createTexture(
            copySrcDesc, SkBudgeted::kYes, pixels.get(), 0));

    context->copySurface(rectangleTexture, src);
    test_read_pixels(reporter, context, rectangleTexture, pixels.get());
}
Example #15
0
bool SkPerlinNoiseShader::asFragmentProcessor(GrContext* context, const SkPaint& paint,
                                              const SkMatrix& viewM,
                                              const SkMatrix* externalLocalMatrix,
                                              GrColor* paintColor, GrFragmentProcessor** fp) const {
    SkASSERT(context);

    *paintColor = SkColor2GrColorJustAlpha(paint.getColor());

    SkMatrix localMatrix = this->getLocalMatrix();
    if (externalLocalMatrix) {
        localMatrix.preConcat(*externalLocalMatrix);
    }

    SkMatrix matrix = viewM;
    matrix.preConcat(localMatrix);

    if (0 == fNumOctaves) {
        if (kFractalNoise_Type == fType) {
            uint32_t alpha = paint.getAlpha() >> 1;
            uint32_t rgb = alpha >> 1;
            *paintColor = GrColorPackRGBA(rgb, rgb, rgb, alpha);
        } else {
const GrFragmentProcessor* GrConstColorProcessor::TestCreate(GrProcessorTestData* d) {
    GrColor color;
    int colorPicker = d->fRandom->nextULessThan(3);
    switch (colorPicker) {
        case 0: {
            uint32_t a = d->fRandom->nextULessThan(0x100);
            uint32_t r = d->fRandom->nextULessThan(a+1);
            uint32_t g = d->fRandom->nextULessThan(a+1);
            uint32_t b = d->fRandom->nextULessThan(a+1);
            color = GrColorPackRGBA(r, g, b, a);
            break;
        }
        case 1:
            color = 0;
            break;
        case 2:
            color = d->fRandom->nextULessThan(0x100);
            color = color | (color << 8) | (color << 16) | (color << 24);
            break;
    }
    InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt));
    return GrConstColorProcessor::Create(color, mode);
}
GrXferProcessor::OptFlags
PorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
                                          const GrProcOptInfo& coveragePOI,
                                          bool doesStencilWrite,
                                          GrColor* overrideColor,
                                          const GrDrawTargetCaps& caps) {
    GrXferProcessor::OptFlags optFlags;
    // Optimizations when doing RGB Coverage
    if (coveragePOI.isFourChannelOutput()) {
        // We want to force our primary output to be alpha * Coverage, where alpha is the alpha
        // value of the blend the constant. We should already have valid blend coeff's if we are at
        // a point where we have RGB coverage. We don't need any color stages since the known color
        // output is already baked into the blendConstant.
        uint8_t alpha = GrColorUnpackA(fBlendConstant);
        *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha);
        optFlags = GrXferProcessor::kOverrideColor_OptFlag;
    } else {
        optFlags = this->internalGetOptimizations(colorPOI,
                                                  coveragePOI,
                                                  doesStencilWrite);
    }
    this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite());
    return optFlags;
}
Example #18
0
void sub_clear_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config) {
    const int width = 10;
    const int height = 10;
    const int subWidth = width/2;
    const int subHeight = height/2;
    GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());
    gpu->discard(NULL);
    SkAutoTMalloc<GrColor> buffer(width * height);
    SkAutoTMalloc<GrColor> subBuffer(subWidth * subHeight);

    GrSurfaceDesc surfDesc;
    surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    surfDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
    surfDesc.fWidth = width;
    surfDesc.fHeight = height;
    surfDesc.fConfig = config;
    surfDesc.fSampleCnt = 0;
    GrTexture* tex = gpu->createTexture(surfDesc, false, nullptr, 0);
    SkASSERT(tex);
    SkASSERT(tex->asRenderTarget());

    SkIRect fullRect = SkIRect::MakeWH(10, 10);
    gpu->clear(fullRect, GrColor_TRANSPARENT_BLACK, tex->asRenderTarget());

    gpu->readPixels(tex, 0, 0, width, height, config, (void*)buffer.get(), 0);

    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(buffer.get(),
                                                                     GrColor_TRANSPARENT_BLACK,
                                                                     config,
                                                                     width,
                                                                     height));
    SkIRect rect;
    rect = SkIRect::MakeXYWH(0, 0, subWidth, subHeight);
    gpu->clear(rect, GrColor_WHITE, tex->asRenderTarget());
    rect = SkIRect::MakeXYWH(subWidth, 0, subWidth, subHeight);
    gpu->clear(rect, GrColor_WHITE, tex->asRenderTarget());
    rect = SkIRect::MakeXYWH(0, subHeight, subWidth, subHeight);
    gpu->clear(rect, GrColor_WHITE, tex->asRenderTarget());

    // Should fail since bottom right sub area has not been cleared to white
    gpu->readPixels(tex, 0, 0, width, height, config, (void*)buffer.get(), 0);
    REPORTER_ASSERT(reporter, !does_full_buffer_contain_correct_color(buffer.get(),
                                                                      GrColor_WHITE,
                                                                      config,
                                                                      width,
                                                                      height));

    rect = SkIRect::MakeXYWH(subWidth, subHeight, subWidth, subHeight);
    gpu->clear(rect, GrColor_WHITE, tex->asRenderTarget());

    gpu->readPixels(tex, 0, 0, width, height, config, (void*)buffer.get(), 0);
    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(buffer.get(),
                                                                     GrColor_WHITE,
                                                                     config,
                                                                     width,
                                                                     height));

    // Try different colors and that each sub area has correct color
    GrColor subColor1 = GrColorPackRGBA(0xFF, 0x00, 0x00, 0xFF);
    GrColor subColor2 = GrColorPackRGBA(0x00, 0xFF, 0x00, 0xFF);
    GrColor subColor3 = GrColorPackRGBA(0x00, 0x00, 0xFF, 0xFF);
    GrColor subColor4 = GrColorPackRGBA(0xFF, 0xFF, 0x00, 0xFF);

    rect = SkIRect::MakeXYWH(0, 0, subWidth, subHeight);
    gpu->clear(rect, subColor1, tex->asRenderTarget());
    rect = SkIRect::MakeXYWH(subWidth, 0, subWidth, subHeight);
    gpu->clear(rect, subColor2, tex->asRenderTarget());
    rect = SkIRect::MakeXYWH(0, subHeight, subWidth, subHeight);
    gpu->clear(rect, subColor3, tex->asRenderTarget());
    rect = SkIRect::MakeXYWH(subWidth, subHeight, subWidth, subHeight);
    gpu->clear(rect, subColor4, tex->asRenderTarget());

    gpu->readPixels(tex, 0, 0, subWidth, subHeight, config, (void*)subBuffer.get(), 0);
    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(subBuffer.get(),
                                                                     subColor1,
                                                                     config,
                                                                     subWidth,
                                                                     subHeight));
    gpu->readPixels(tex, subWidth, 0, subWidth, subHeight, config, (void*)subBuffer.get(), 0);
    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(subBuffer.get(),
                                                                     subColor2,
                                                                     config,
                                                                     subWidth,
                                                                     subHeight));
    gpu->readPixels(tex, 0, subHeight, subWidth, subHeight, config, (void*)subBuffer.get(), 0);
    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(subBuffer.get(),
                                                                     subColor3,
                                                                     config,
                                                                     subWidth,
                                                                     subHeight));
    gpu->readPixels(tex, subWidth, subHeight, subWidth, subHeight,
                    config, (void*)subBuffer.get(), 0);
    REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_color(subBuffer.get(),
                                                                     subColor4,
                                                                     config,
                                                                     subWidth,
                                                                     subHeight));
}
bool LightingShader::asFragmentProcessor(GrContext* context, const SkPaint& paint, 
                                         const SkMatrix& viewM, const SkMatrix* localMatrix, 
                                         GrColor* color, GrProcessorDataManager*,
                                         GrFragmentProcessor** fp) const {
    // we assume diffuse and normal maps have same width and height
    // TODO: support different sizes
    SkASSERT(fDiffuseMap.width() == fNormalMap.width() &&
             fDiffuseMap.height() == fNormalMap.height());
    SkMatrix matrix;
    matrix.setIDiv(fDiffuseMap.width(), fDiffuseMap.height());

    SkMatrix lmInverse;
    if (!this->getLocalMatrix().invert(&lmInverse)) {
        return false;
    }
    if (localMatrix) {
        SkMatrix inv;
        if (!localMatrix->invert(&inv)) {
            return false;
        }
        lmInverse.postConcat(inv);
    }
    matrix.preConcat(lmInverse);

    // Must set wrap and filter on the sampler before requesting a texture. In two places below
    // we check the matrix scale factors to determine how to interpret the filter quality setting.
    // This completely ignores the complexity of the drawVertices case where explicit local coords
    // are provided by the caller.
    GrTextureParams::FilterMode textureFilterMode = GrTextureParams::kBilerp_FilterMode;
    switch (paint.getFilterQuality()) {
    case kNone_SkFilterQuality:
        textureFilterMode = GrTextureParams::kNone_FilterMode;
        break;
    case kLow_SkFilterQuality:
        textureFilterMode = GrTextureParams::kBilerp_FilterMode;
        break;
    case kMedium_SkFilterQuality:{                          
        SkMatrix matrix;
        matrix.setConcat(viewM, this->getLocalMatrix());
        if (matrix.getMinScale() < SK_Scalar1) {
            textureFilterMode = GrTextureParams::kMipMap_FilterMode;
        } else {
            // Don't trigger MIP level generation unnecessarily.
            textureFilterMode = GrTextureParams::kBilerp_FilterMode;
        }
        break;
    }
    case kHigh_SkFilterQuality:
    default:
        SkErrorInternals::SetError(kInvalidPaint_SkError,
            "Sorry, I don't understand the filtering "
            "mode you asked for.  Falling back to "
            "MIPMaps.");
        textureFilterMode = GrTextureParams::kMipMap_FilterMode;
        break;

    }

    // TODO: support other tile modes
    GrTextureParams params(kClamp_TileMode, textureFilterMode);
    SkAutoTUnref<GrTexture> diffuseTexture(GrRefCachedBitmapTexture(context, fDiffuseMap, &params));
    if (!diffuseTexture) {
        SkErrorInternals::SetError(kInternalError_SkError,
            "Couldn't convert bitmap to texture.");
        return false;
    }

    SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, fNormalMap, &params));
    if (!normalTexture) {
        SkErrorInternals::SetError(kInternalError_SkError,
            "Couldn't convert bitmap to texture.");
        return false;
    }

    GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG(fLight.fColor),
                                         SkColorGetB(fLight.fColor), SkColorGetA(fLight.fColor));
    GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGetG(fAmbientColor),
                                           SkColorGetB(fAmbientColor), SkColorGetA(fAmbientColor));

    *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix,
                                  fLight.fDirection, lightColor, ambientColor));
    *color = GrColorPackA4(paint.getAlpha());
    return true;
}
Example #20
0
 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
     // The output is always black. The alpha value for the color passed in is arbitrary.
     inout->setToOther(kRGB_GrColorComponentFlags, GrColorPackRGBA(0, 0, 0, 0),
                       GrInvariantOutput::kWill_ReadInput);
 }
Example #21
0
static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
    unsigned r = SkColorGetR(c);
    unsigned g = SkColorGetG(c);
    unsigned b = SkColorGetB(c);
    return GrColorPackRGBA(r, g, b, 0xff);
}
Example #22
0
bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
                                     uint32_t* solidColorKnownComponents) const {

    // TODO: Share this implementation with GrDrawState

    GrColor coverage = GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
    uint32_t coverageComps = kRGBA_GrColorComponentFlags;
    int count = fCoverageStages.count();
    for (int i = 0; i < count; ++i) {
        (*fCoverageStages[i].getEffect())->getConstantColorComponents(&coverage, &coverageComps);
    }
    if (kRGBA_GrColorComponentFlags != coverageComps || 0xffffffff != coverage) {
        return false;
    }

    GrColor color = fColor;
    uint32_t colorComps = kRGBA_GrColorComponentFlags;
    count = fColorStages.count();
    for (int i = 0; i < count; ++i) {
        (*fColorStages[i].getEffect())->getConstantColorComponents(&color, &colorComps);
    }

    SkASSERT((NULL == solidColor) == (NULL == solidColorKnownComponents));

    GrBlendCoeff srcCoeff = fSrcBlendCoeff;
    GrBlendCoeff dstCoeff = fDstBlendCoeff;
    GrSimplifyBlend(&srcCoeff, &dstCoeff, color, colorComps, 0, 0, 0);

    bool opaque = kZero_GrBlendCoeff == dstCoeff && !GrBlendCoeffRefsDst(srcCoeff);
    if (NULL != solidColor) {
        if (opaque) {
            switch (srcCoeff) {
            case kZero_GrBlendCoeff:
                *solidColor = 0;
                *solidColorKnownComponents = kRGBA_GrColorComponentFlags;
                break;

            case kOne_GrBlendCoeff:
                *solidColor = color;
                *solidColorKnownComponents = colorComps;
                break;

            // The src coeff should never refer to the src and if it refers to dst then opaque
            // should have been false.
            case kSC_GrBlendCoeff:
            case kISC_GrBlendCoeff:
            case kDC_GrBlendCoeff:
            case kIDC_GrBlendCoeff:
            case kSA_GrBlendCoeff:
            case kISA_GrBlendCoeff:
            case kDA_GrBlendCoeff:
            case kIDA_GrBlendCoeff:
            default:
                SkFAIL("srcCoeff should not refer to src or dst.");
                break;

            // TODO: update this once GrPaint actually has a const color.
            case kConstC_GrBlendCoeff:
            case kIConstC_GrBlendCoeff:
            case kConstA_GrBlendCoeff:
            case kIConstA_GrBlendCoeff:
                *solidColorKnownComponents = 0;
                break;
            }
        } else {
            solidColorKnownComponents = 0;
        }
    }
    return opaque;
}
Example #23
0
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadWriteAlpha, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    unsigned char alphaData[X_SIZE * Y_SIZE];

    static const int kClearValue = 0x2;

    bool match;
    static const size_t kRowBytes[] = {0, X_SIZE, X_SIZE + 1, 2 * X_SIZE - 1};
    {
        GrSurfaceDesc desc;
        desc.fFlags     = kNone_GrSurfaceFlags;
        desc.fConfig    = kAlpha_8_GrPixelConfig;    // it is a single channel texture
        desc.fWidth     = X_SIZE;
        desc.fHeight    = Y_SIZE;

        // We are initializing the texture with zeros here
        memset(alphaData, 0, X_SIZE * Y_SIZE);

        sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
                                                                 desc,
                                                                 SkBudgeted::kNo,
                                                                 alphaData, 0));
        if (!proxy) {
            ERRORF(reporter, "Could not create alpha texture.");
            return;
        }
        sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext(
                                                                  std::move(proxy), nullptr));

        const SkImageInfo ii = SkImageInfo::MakeA8(X_SIZE, Y_SIZE);
        sk_sp<SkSurface> surf(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii));

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

        for (auto rowBytes : kRowBytes) {

            // upload the texture (do per-rowbytes iteration because we may overwrite below).
            bool result = sContext->writePixels(ii, alphaData, 0, 0, 0);
            REPORTER_ASSERT_MESSAGE(reporter, result, "Initial A8 writePixels failed");

            size_t nonZeroRowBytes = rowBytes ? rowBytes : X_SIZE;
            std::unique_ptr<uint8_t[]> readback(new uint8_t[nonZeroRowBytes * Y_SIZE]);
            // clear readback to something non-zero so we can detect readback failures
            memset(readback.get(), kClearValue, nonZeroRowBytes * Y_SIZE);

            // read the texture back
            result = sContext->readPixels(ii, readback.get(), rowBytes, 0, 0);
            REPORTER_ASSERT_MESSAGE(reporter, result, "Initial A8 readPixels failed");

            // make sure the original & read back versions match
            SkString msg;
            msg.printf("rb:%d A8", SkToU32(rowBytes));
            validate_alpha_data(reporter, X_SIZE, Y_SIZE, readback.get(), nonZeroRowBytes,
                                alphaData, msg);

            // Now try writing to a single channel surface (if we could create one).
            if (surf) {
                SkCanvas* canvas = surf->getCanvas();

                SkPaint paint;

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

                paint.setColor(SK_ColorWHITE);

                canvas->drawRect(rect, paint);

                memset(readback.get(), kClearValue, nonZeroRowBytes * Y_SIZE);
                result = surf->readPixels(ii, readback.get(), nonZeroRowBytes, 0, 0);
                REPORTER_ASSERT_MESSAGE(reporter, result, "A8 readPixels after clear failed");

                match = true;
                for (int y = 0; y < Y_SIZE && match; ++y) {
                    for (int x = 0; x < X_SIZE && match; ++x) {
                        uint8_t rbValue = readback.get()[y * nonZeroRowBytes + x];
                        if (0xFF != rbValue) {
                            ERRORF(reporter,
                                   "Failed alpha readback after clear. Expected: 0xFF, Got: 0x%02x"
                                   " at (%d,%d), rb:%d", rbValue, x, y, SkToU32(rowBytes));
                            match = false;
                        }
                    }
                }
            }
        }
    }

    static const GrPixelConfig kRGBAConfigs[] {
        kRGBA_8888_GrPixelConfig,
        kBGRA_8888_GrPixelConfig,
        kSRGBA_8888_GrPixelConfig
    };

    for (int y = 0; y < Y_SIZE; ++y) {
        for (int x = 0; x < X_SIZE; ++x) {
            alphaData[y * X_SIZE + x] = y*X_SIZE+x;
        }
    }

    const SkImageInfo dstInfo = SkImageInfo::Make(X_SIZE, Y_SIZE,
                                                  kAlpha_8_SkColorType,
                                                  kPremul_SkAlphaType);

    // Attempt to read back just alpha from a RGBA/BGRA texture. Once with a texture-only src and
    // once with a render target.
    for (auto config : kRGBAConfigs) {
        for (int rt = 0; rt < 2; ++rt) {
            GrSurfaceDesc desc;
            desc.fFlags     = rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
            desc.fConfig    = config;
            desc.fWidth     = X_SIZE;
            desc.fHeight    = Y_SIZE;

            uint32_t rgbaData[X_SIZE * Y_SIZE];
            // Make the alpha channel of the rgba texture come from alphaData.
            for (int y = 0; y < Y_SIZE; ++y) {
                for (int x = 0; x < X_SIZE; ++x) {
                    rgbaData[y * X_SIZE + x] = GrColorPackRGBA(6, 7, 8, alphaData[y * X_SIZE + x]);
                }
            }
            sk_sp<GrTextureProxy> proxy =
                GrSurfaceProxy::MakeDeferred(context->resourceProvider(), desc, SkBudgeted::kNo,
                                             rgbaData, 0);
            if (!proxy) {
                // We always expect to be able to create a RGBA texture
                if (!rt  && kRGBA_8888_GrPixelConfig == desc.fConfig) {
                    ERRORF(reporter, "Failed to create RGBA texture.");
                }
                continue;
            }

            sk_sp<GrSurfaceContext> sContext = context->contextPriv().makeWrappedSurfaceContext(
                                                                       std::move(proxy), nullptr);

            for (auto rowBytes : kRowBytes) {
                size_t nonZeroRowBytes = rowBytes ? rowBytes : X_SIZE;

                std::unique_ptr<uint8_t[]> readback(new uint8_t[nonZeroRowBytes * Y_SIZE]);
                // Clear so we don't accidentally see values from previous iteration.
                memset(readback.get(), kClearValue, nonZeroRowBytes * Y_SIZE);

                // read the texture back
                bool result = sContext->readPixels(dstInfo, readback.get(), rowBytes, 0, 0);
                REPORTER_ASSERT_MESSAGE(reporter, result, "8888 readPixels failed");

                // make sure the original & read back versions match
                SkString msg;
                msg.printf("rt:%d, rb:%d 8888", rt, SkToU32(rowBytes));
                validate_alpha_data(reporter, X_SIZE, Y_SIZE, readback.get(), nonZeroRowBytes,
                                    alphaData, msg);
            }
        }
    }
}
Example #24
0
static void test_getConstantColorComponents(skiatest::Reporter* reporter, GrContext* grContext) {
    struct GetConstantComponentTestCase {
        // "Shape drawn with"
        uint32_t inputComponents; // "rgb of", "red of", "alpha of", ...
        GrColor inputColor;       // "[color]"

        SkColor filterColor;      // "with filter color [color]"
        SkXfermode::Mode filterMode; // "in mode [mode]"

        // "produces"
        uint32_t outputComponents; // "rgb of", "red of", "alpha of", ...
        GrColor outputColor;       // "[color]"
    };

    // Shorthands.
    enum {
        kR = kR_GrColorComponentFlag,
        kG = kG_GrColorComponentFlag,
        kB = kB_GrColorComponentFlag,
        kA = kA_GrColorComponentFlag,
        kRGB = kRGB_GrColorComponentFlags,
        kRGBA = kRGBA_GrColorComponentFlags
    };

    // Note: below, SkColors are non-premultiplied, where as GrColors are premultiplied.

    const SkColor c1 = SkColorSetARGB(200, 200, 200, 200);
    const SkColor c2 = SkColorSetARGB(60, 60, 60, 60);
    const GrColor gr_c1 = SkColor2GrColor(c1);
    const GrColor gr_c2 = SkColor2GrColor(c2);

    const GrColor gr_black = GrColorPackRGBA(0, 0, 0, 0);
    const GrColor gr_white = GrColorPackRGBA(255, 255, 255, 255);
    const GrColor gr_whiteTrans = GrColorPackRGBA(128, 128, 128, 128);

    GetConstantComponentTestCase filterTests[] = {
        // A color filtered with Clear produces black.
        { kRGBA, gr_white, SK_ColorBLACK, SkXfermode::kClear_Mode, kRGBA, gr_black },
        { kRGBA, gr_c1,    SK_ColorWHITE, SkXfermode::kClear_Mode, kRGBA, gr_black },
        { kR,    gr_white, c1,            SkXfermode::kClear_Mode, kRGBA, gr_black },

        // A color filtered with a color in mode Src, produces the filter color.
        { kRGBA, gr_c2, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 },
        { kA,    gr_c1, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 },

        // A color filtered with SrcOver produces a color.
        { kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGBA, GrColorPackRGBA(164, 164, 164, 192)},
        // An unknown color with known alpha filtered with SrcOver produces an unknown color with known alpha.
        { kA   , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kA   , GrColorPackRGBA(0, 0, 0, 192)},
        // A color with unknown alpha filtered with SrcOver produces a color with unknown alpha.
        { kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGB, GrColorPackRGBA(164, 164, 164, 0)},

        // A color filtered with DstOver produces a color.
        { kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kRGBA, GrColorPackRGBA(178, 178, 178, 192)},
        // An unknown color with known alpha filtered with DstOver produces an unknown color with known alpha.
        { kA   , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kA   , GrColorPackRGBA(0, 0, 0, 192)},
        // A color with unknown alpha filtered with DstOver produces an unknown color.
        { kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, 0    , gr_black},

        // An unknown color with known alpha and red component filtered with Multiply produces an unknown color with known red and alpha.
        { kR|kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kModulate_Mode, kR|kA, GrColorPackRGBA(50, 0, 0, 64) }
    };

    for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) {
        const GetConstantComponentTestCase& test = filterTests[i];
        SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(test.filterColor, test.filterMode));
        SkAutoTUnref<GrEffectRef> grEffect(cf->asNewEffect(grContext));
        GrColor color = test.inputColor;
        uint32_t components = test.inputComponents;
        grEffect->get()->getConstantColorComponents(&color, &components);

        REPORTER_ASSERT(reporter, filterColor(color, components) == test.outputColor);
        REPORTER_ASSERT(reporter, test.outputComponents == components);
    }
}
Example #25
0
bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
                                     uint32_t* solidColorKnownComponents) const {

    // TODO: Share this implementation with GrDrawState

    GrProcessor::InvariantOutput inout;
    inout.fColor = GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
    inout.fValidFlags = kRGBA_GrColorComponentFlags;
    inout.fIsSingleComponent = false;
    int count = fCoverageStages.count();
    for (int i = 0; i < count; ++i) {
        fCoverageStages[i].getProcessor()->computeInvariantOutput(&inout);
    }
    if (!inout.isSolidWhite()) {
        return false;
    }

    inout.fColor = fColor;
    inout.fValidFlags = kRGBA_GrColorComponentFlags;
    inout.fIsSingleComponent = false;
    count = fColorStages.count();
    for (int i = 0; i < count; ++i) {
        fColorStages[i].getProcessor()->computeInvariantOutput(&inout);
    }

    SkASSERT((NULL == solidColor) == (NULL == solidColorKnownComponents));

    GrBlendCoeff srcCoeff = fSrcBlendCoeff;
    GrBlendCoeff dstCoeff = fDstBlendCoeff;
    GrSimplifyBlend(&srcCoeff, &dstCoeff, inout.fColor, inout.fValidFlags,
                    0, 0, 0);

    bool opaque = kZero_GrBlendCoeff == dstCoeff && !GrBlendCoeffRefsDst(srcCoeff);
    if (solidColor) {
        if (opaque) {
            switch (srcCoeff) {
                case kZero_GrBlendCoeff:
                    *solidColor = 0;
                    *solidColorKnownComponents = kRGBA_GrColorComponentFlags;
                    break;

                case kOne_GrBlendCoeff:
                    *solidColor = inout.fColor;
                    *solidColorKnownComponents = inout.fValidFlags;
                    break;

                // The src coeff should never refer to the src and if it refers to dst then opaque
                // should have been false.
                case kSC_GrBlendCoeff:
                case kISC_GrBlendCoeff:
                case kDC_GrBlendCoeff:
                case kIDC_GrBlendCoeff:
                case kSA_GrBlendCoeff:
                case kISA_GrBlendCoeff:
                case kDA_GrBlendCoeff:
                case kIDA_GrBlendCoeff:
                default:
                    SkFAIL("srcCoeff should not refer to src or dst.");
                    break;

                // TODO: update this once GrPaint actually has a const color.
                case kConstC_GrBlendCoeff:
                case kIConstC_GrBlendCoeff:
                case kConstA_GrBlendCoeff:
                case kIConstA_GrBlendCoeff:
                    *solidColorKnownComponents = 0;
                    break;
            }
        } else {
            solidColorKnownComponents = 0;
        }
    }
    return opaque;
}
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadWriteAlpha, reporter, context) {
    unsigned char alphaData[X_SIZE * Y_SIZE];

    bool match;
    static const size_t kRowBytes[] = {0, X_SIZE, X_SIZE + 1, 2 * X_SIZE - 1};
    for (int rt = 0; rt < 2; ++rt) {
        GrSurfaceDesc desc;
        // let Skia know we will be using this texture as a render target
        desc.fFlags     = rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
        // 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
        memset(alphaData, 0, X_SIZE * Y_SIZE);
        SkAutoTUnref<GrTexture> texture(
            context->textureProvider()->createTexture(desc, SkBudgeted::kNo , alphaData, 0));
        if (!texture) {
            if (!rt) {
                ERRORF(reporter, "Could not create alpha texture.");
            }
            continue;
        }

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

        for (auto rowBytes : kRowBytes) {
            // upload the texture (do per-rowbytes iteration because we may overwrite below).
            texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
                                 alphaData, 0);

            size_t nonZeroRowBytes = rowBytes ? rowBytes : X_SIZE;
            SkAutoTDeleteArray<uint8_t> readback(new uint8_t[nonZeroRowBytes * Y_SIZE]);
            // clear readback to something non-zero so we can detect readback failures
            memset(readback.get(), 0x1, nonZeroRowBytes * Y_SIZE);

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

            // make sure the original & read back versions match
            SkString msg;
            msg.printf("rt:%d, rb:%d", rt, SkToU32(rowBytes));
            validate_alpha_data(reporter, X_SIZE, Y_SIZE, readback.get(), nonZeroRowBytes,
                                alphaData, msg);

            // Now try writing on the single channel texture (if we could create as a RT).
            if (texture->asRenderTarget()) {
                SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
                SkAutoTUnref<SkBaseDevice> device(SkGpuDevice::Create(
                                                      texture->asRenderTarget(), &props, SkGpuDevice::kUninit_InitContents));
                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);

                memset(readback.get(), 0x1, nonZeroRowBytes * Y_SIZE);
                texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, readback.get(),
                                    rowBytes);

                match = true;
                for (int y = 0; y < Y_SIZE && match; ++y) {
                    for (int x = 0; x < X_SIZE && match; ++x) {
                        uint8_t rbValue = readback.get()[y * nonZeroRowBytes + x];
                        if (0xFF != rbValue) {
                            ERRORF(reporter,
                                   "Failed alpha readback after clear. Expected: 0xFF, Got: 0x%02x"
                                   " at (%d,%d), rb:%d", rbValue, x, y, SkToU32(rowBytes));
                            match = false;
                        }
                    }
                }
            }
        }
    }

    static const GrPixelConfig kRGBAConfigs[] {
        kRGBA_8888_GrPixelConfig,
        kBGRA_8888_GrPixelConfig,
        kSRGBA_8888_GrPixelConfig
    };

    for (int y = 0; y < Y_SIZE; ++y) {
        for (int x = 0; x < X_SIZE; ++x) {
            alphaData[y * X_SIZE + x] = y*X_SIZE+x;
        }
    }

    // Attempt to read back just alpha from a RGBA/BGRA texture. Once with a texture-only src and
    // once with a render target.
    for (auto cfg : kRGBAConfigs) {
        for (int rt = 0; rt < 2; ++rt) {
            GrSurfaceDesc desc;
            desc.fFlags     = rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
            desc.fConfig    = cfg;
            desc.fWidth     = X_SIZE;
            desc.fHeight    = Y_SIZE;

            uint32_t rgbaData[X_SIZE * Y_SIZE];
            // Make the alpha channel of the rgba texture come from alphaData.
            for (int y = 0; y < Y_SIZE; ++y) {
                for (int x = 0; x < X_SIZE; ++x) {
                    rgbaData[y * X_SIZE + x] = GrColorPackRGBA(6, 7, 8, alphaData[y * X_SIZE + x]);
                }
            }
            SkAutoTUnref<GrTexture> texture(
                context->textureProvider()->createTexture(desc, SkBudgeted::kNo, rgbaData, 0));
            if (!texture) {
                // We always expect to be able to create a RGBA texture
                if (!rt  && kRGBA_8888_GrPixelConfig == desc.fConfig) {
                    ERRORF(reporter, "Failed to create RGBA texture.");
                }
                continue;
            }

            for (auto rowBytes : kRowBytes) {
                size_t nonZeroRowBytes = rowBytes ? rowBytes : X_SIZE;

                SkAutoTDeleteArray<uint8_t> readback(new uint8_t[nonZeroRowBytes * Y_SIZE]);
                // Clear so we don't accidentally see values from previous iteration.
                memset(readback.get(), 0x0, nonZeroRowBytes * Y_SIZE);

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

                // make sure the original & read back versions match
                SkString msg;
                msg.printf("rt:%d, rb:%d", rt, SkToU32(rowBytes));
                validate_alpha_data(reporter, X_SIZE, Y_SIZE, readback.get(), nonZeroRowBytes,
                                    alphaData, msg);
            }
        }
    }
}
Example #27
0
static void test_getConstantColorComponents(skiatest::Reporter* reporter, GrContext* grContext) {
    struct GetConstantComponentTestCase {
        // "Shape drawn with"
        uint32_t inputComponents; // "rgb of", "red of", "alpha of", ...
        GrColor inputColor;       // "[color]"

        SkColor filterColor;      // "with filter color [color]"
        SkXfermode::Mode filterMode; // "in mode [mode]"

        // "produces"
        uint32_t outputComponents; // "rgb of", "red of", "alpha of", ...
        GrColor outputColor;       // "[color]"
    };

    // Shorthands.
    enum {
        kR = kR_GrColorComponentFlag,
        kG = kG_GrColorComponentFlag,
        kB = kB_GrColorComponentFlag,
        kA = kA_GrColorComponentFlag,
        kRGB = kRGB_GrColorComponentFlags,
        kRGBA = kRGBA_GrColorComponentFlags
    };

    // Note: below, SkColors are non-premultiplied, where as GrColors are premultiplied.

    const SkColor c1 = SkColorSetARGB(200, 200, 200, 200);
    const SkColor c2 = SkColorSetARGB(60, 60, 60, 60);
    const GrColor gr_c1 = SkColor2GrColor(c1);
    const GrColor gr_c2 = SkColor2GrColor(c2);

    const GrColor gr_black = GrColorPackA4(0);
    const GrColor gr_white = GrColorPackA4(255);
    const GrColor gr_whiteTrans = GrColorPackA4(128);

    GetConstantComponentTestCase filterTests[] = {
        // A color filtered with Clear produces black.
        { kRGBA, gr_white, SK_ColorBLACK, SkXfermode::kClear_Mode, kRGBA, gr_black },
        { kRGBA, gr_c1,    SK_ColorWHITE, SkXfermode::kClear_Mode, kRGBA, gr_black },
        { kR,    gr_white, c1,            SkXfermode::kClear_Mode, kRGBA, gr_black },

        // A color filtered with a color in mode Src, produces the filter color.
        { kRGBA, gr_c2, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 },
        { kA,    gr_c1, c1, SkXfermode::kSrc_Mode, kRGBA, gr_c1 },

        // A color filtered with SrcOver produces a color.
        { kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGBA, GrColorPackRGBA(164, 164, 164, 192)},
        // An unknown color with known alpha filtered with SrcOver produces an unknown color with known alpha.
        { kA   , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kA   , GrColorPackRGBA(0, 0, 0, 192)},
        // A color with unknown alpha filtered with SrcOver produces a color with unknown alpha.
        { kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kSrcOver_Mode, kRGB, GrColorPackRGBA(164, 164, 164, 0)},

        // A color filtered with DstOver produces a color.
        { kRGBA, gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kRGBA, GrColorPackRGBA(178, 178, 178, 192)},
        // An unknown color with known alpha filtered with DstOver produces an unknown color with known alpha.
        { kA   , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, kA   , GrColorPackRGBA(0, 0, 0, 192)},
        // A color with unknown alpha filtered with DstOver produces an unknown color.
        { kRGB , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kDstOver_Mode, 0    , gr_black},

        // An unknown color with known alpha and red component filtered with Multiply produces an unknown color with known red and alpha.
        { kR|kA , gr_whiteTrans, SkColorSetARGB(128, 200, 200, 200), SkXfermode::kModulate_Mode, kR|kA, GrColorPackRGBA(50, 0, 0, 64) }
    };

    GrPaint paint;
    for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) {
        const GetConstantComponentTestCase& test = filterTests[i];
        SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(test.filterColor, test.filterMode));
        SkTDArray<const GrFragmentProcessor*> array;
        bool hasFrag = cf->asFragmentProcessors(grContext, paint.getProcessorDataManager(), &array);
        REPORTER_ASSERT(reporter, hasFrag);
        REPORTER_ASSERT(reporter, 1 == array.count());
        GrInvariantOutput inout(test.inputColor,
                                static_cast<GrColorComponentFlags>(test.inputComponents),
                                false);
        array[0]->computeInvariantOutput(&inout);

        REPORTER_ASSERT(reporter, filterColor(inout.color(), inout.validFlags()) == test.outputColor);
        REPORTER_ASSERT(reporter, test.outputComponents == inout.validFlags());
        array[0]->unref();
    }
}
bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath,
                                       const SkStrokeRec& stroke,
                                       GrDrawTarget* target,
                                       bool antiAlias) {

    // generate verts using Android algorithm
    android::uirenderer::VertexBuffer vertices;
    android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL,
                                                          &vertices);

    // set vertex attributes depending on anti-alias
    GrDrawState* drawState = target->drawState();
    if (antiAlias) {
        // position + coverage
        GrVertexAttrib attribs[] = {
            GrVertexAttrib(kVec2f_GrVertexAttribType, 0),
            GrVertexAttrib(kVec4ub_GrVertexAttribType, sizeof(GrPoint))
        };
        drawState->setVertexAttribs(attribs, SK_ARRAY_COUNT(attribs));
        drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
        drawState->setAttribIndex(GrDrawState::kCoverage_AttribIndex, 1);
        drawState->setAttribBindings(GrDrawState::kCoverage_AttribBindingsBit);
    } else {
        drawState->setDefaultVertexAttribs();
    }

    // allocate our vert buffer
    int vertCount = vertices.getSize();
    GrDrawTarget::AutoReleaseGeometry geo(target, vertCount, 0);
    if (!geo.succeeded()) {
        SkDebugf("Failed to get space for vertices!\n");
        return false;
    }

    // copy android verts to our vertex buffer
    if (antiAlias) {
        SkASSERT(sizeof(ColorVertex) == drawState->getVertexSize());
        ColorVertex* outVert = reinterpret_cast<ColorVertex*>(geo.vertices());
        android::uirenderer::AlphaVertex* inVert =
            reinterpret_cast<android::uirenderer::AlphaVertex*>(vertices.getBuffer());

        for (int i = 0; i < vertCount; ++i) {
            // copy vertex position
            outVert->pos.set(inVert->position[0], inVert->position[1]);
            // copy alpha
            int coverage = static_cast<int>(inVert->alpha * 0xff);
            outVert->color = GrColorPackRGBA(coverage, coverage, coverage, coverage);
            ++outVert;
            ++inVert;
        }
    } else {
       size_t vsize = drawState->getVertexSize();
       size_t copySize = vsize*vertCount;
       memcpy(geo.vertices(), vertices.getBuffer(), copySize);
    }

    // render it
    target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, vertCount);

    return true;
}
using ScissorState = GrPipeline::ScissorState;

static constexpr int kScreenSize = 6;
static constexpr int kNumMeshes = 4;
static constexpr int kScreenSplitX = kScreenSize/2;
static constexpr int kScreenSplitY = kScreenSize/2;

static const GrPipeline::DynamicState kDynamicStates[kNumMeshes] = {
    {SkIRect::MakeLTRB(0,              0,              kScreenSplitX,  kScreenSplitY)},
    {SkIRect::MakeLTRB(0,              kScreenSplitY,  kScreenSplitX,  kScreenSize)},
    {SkIRect::MakeLTRB(kScreenSplitX,  0,              kScreenSize,    kScreenSplitY)},
    {SkIRect::MakeLTRB(kScreenSplitX,  kScreenSplitY,  kScreenSize,    kScreenSize)},
};

static const GrColor kMeshColors[kNumMeshes] {
    GrColorPackRGBA(255, 0, 0, 255),
    GrColorPackRGBA(0, 255, 0, 255),
    GrColorPackRGBA(0, 0, 255, 255),
    GrColorPackRGBA(0, 0, 0, 255)
};

struct Vertex {
    float     fX;
    float     fY;
    GrColor   fColor;
};

class GrPipelineDynamicStateTestProcessor : public GrGeometryProcessor {
public:
    GrPipelineDynamicStateTestProcessor()
        : fVertex(this->addVertexAttrib("vertex", kVec2f_GrVertexAttribType))