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); }
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); } }
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; }
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); }
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()); }
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); }
/** * 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()); }
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; }
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, ¶ms)); if (!diffuseTexture) { SkErrorInternals::SetError(kInternalError_SkError, "Couldn't convert bitmap to texture."); return false; } SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, fNormalMap, ¶ms)); 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; }
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); }
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); }
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; }
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); } } } }
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); } }
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); } } } }
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))