// TODO just use class params // TODO trying to figure out why lcd is so whack GrGeometryProcessor* GrAtlasTextBatch::setupDfProcessor(const SkMatrix& viewMatrix, SkColor filteredColor, GrColor color, GrTexture* texture) const { GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode); bool isLCD = this->isLCD(); // set up any flags uint32_t flags = viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; flags |= viewMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0; // see if we need to create a new effect if (isLCD) { flags |= kUseLCD_DistanceFieldEffectFlag; flags |= fUseBGR ? kBGR_DistanceFieldEffectFlag : 0; GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); float redCorrection = (*fDistanceAdjustTable)[GrColorUnpackR(colorNoPreMul) >> kDistanceAdjustLumShift]; float greenCorrection = (*fDistanceAdjustTable)[GrColorUnpackG(colorNoPreMul) >> kDistanceAdjustLumShift]; float blueCorrection = (*fDistanceAdjustTable)[GrColorUnpackB(colorNoPreMul) >> kDistanceAdjustLumShift]; GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(redCorrection, greenCorrection, blueCorrection); return GrDistanceFieldLCDTextGeoProc::Create(color, viewMatrix, texture, params, widthAdjust, flags, this->usesLocalCoords()); } else {
void GrBitmapTextContext::flushGlyphs() { if (NULL == fDrawTarget) { return; } GrDrawState* drawState = fDrawTarget->drawState(); GrDrawState::AutoRestoreEffects are(drawState); drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); if (fCurrVertex > 0) { // setup our sampler state for our text texture/atlas SkASSERT(SkIsAlign4(fCurrVertex)); SkASSERT(fCurrTexture); GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); // This effect could be stored with one of the cache objects (atlas?) drawState->addCoverageEffect( GrCustomCoordsTextureEffect::Create(fCurrTexture, params), kGlyphCoordsAttributeIndex)->unref(); if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) { drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(0xffffffff); } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || fPaint.numColorStages()) { GrPrintf("LCD Text will not draw correctly.\n"); } // We don't use the GrPaint's color in this case because it's been premultiplied by // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by // the mask texture color. The end result is that we get // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor int a = SkColorGetA(fSkPaint.getColor()); // paintAlpha drawState->setColor(SkColorSetARGB(a, a, a, a)); // paintColor drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor())); drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); } else { // set back to normal in case we took LCD path previously. drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(fPaint.getColor()); } int nGlyphs = fCurrVertex / 4; fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, nGlyphs, 4, 6, &fVertexBounds); fDrawTarget->resetVertexSource(); fVertices = NULL; fMaxVertices = 0; fCurrVertex = 0; fVertexBounds.setLargestInverted(); SkSafeSetNull(fCurrTexture); } }
void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) { GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode); GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode); uint32_t textureUniqueID = fCurrTexture->getUniqueID(); const SkMatrix& ctm = fContext->getMatrix(); // set up any flags uint32_t flags = 0; flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0; flags |= fUseLCDText && ctm.rectStaysRect() ? kRectToRect_DistanceFieldEffectFlag : 0; bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.pixelGeometry()); flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0; // see if we need to create a new effect if (textureUniqueID != fEffectTextureUniqueID || filteredColor != fEffectColor || flags != fEffectFlags) { if (fUseLCDText) { GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Create(fCurrTexture, params, fGammaTexture, gammaParams, colorNoPreMul, flags)); } else { #ifdef SK_GAMMA_APPLY_TO_A8 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.gamma(), filteredColor); fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(fCurrTexture, params, fGammaTexture, gammaParams, lum/255.f, flags)); #else fCachedGeometryProcessor.reset(GrDistanceFieldNoGammaTextureEffect::Create(fCurrTexture, params, flags)); #endif } fEffectTextureUniqueID = textureUniqueID; fEffectColor = filteredColor; fEffectFlags = flags; } }
void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) { GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode); GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode); uint32_t textureUniqueID = fCurrTexture->getUniqueID(); const SkMatrix& ctm = fViewMatrix; // set up any flags uint32_t flags = 0; flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0; flags |= fUseLCDText && ctm.rectStaysRect() ? kRectToRect_DistanceFieldEffectFlag : 0; bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.pixelGeometry()); flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0; // see if we need to create a new effect if (textureUniqueID != fEffectTextureUniqueID || filteredColor != fEffectColor || flags != fEffectFlags || !fCachedGeometryProcessor->viewMatrix().cheapEqualTo(fViewMatrix)) { GrColor color = fPaint.getColor(); if (fUseLCDText) { GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); float redCorrection = fDistanceAdjustTable[GrColorUnpackR(colorNoPreMul) >> kDistanceAdjustLumShift]; float greenCorrection = fDistanceAdjustTable[GrColorUnpackG(colorNoPreMul) >> kDistanceAdjustLumShift]; float blueCorrection = fDistanceAdjustTable[GrColorUnpackB(colorNoPreMul) >> kDistanceAdjustLumShift]; GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust = GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(redCorrection, greenCorrection, blueCorrection); fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextGeoProc::Create(color, fViewMatrix, fCurrTexture, params, widthAdjust, flags)); } else {
void GrDistanceFieldTextContext::flush() { if (NULL == fDrawTarget) { return; } if (fCurrVertex > 0) { GrDrawState drawState; drawState.setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget()); bool useColorVerts = !fUseLCDText; set_vertex_attributes(&drawState, useColorVerts); // setup our sampler state for our text texture/atlas SkASSERT(SkIsAlign4(fCurrVertex)); // get our current color SkColor filteredColor; SkColorFilter* colorFilter = fSkPaint.getColorFilter(); if (colorFilter) { filteredColor = colorFilter->filterColor(fSkPaint.getColor()); } else { filteredColor = fSkPaint.getColor(); } this->setupCoverageEffect(filteredColor); // Effects could be stored with one of the cache objects (atlas?) drawState.setGeometryProcessor(fCachedGeometryProcessor.get()); // Set draw state if (fUseLCDText) { GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || fPaint.numColorStages()) { SkDebugf("LCD Text will not draw correctly.\n"); } SkASSERT(!drawState.hasColorVertexAttribute()); // We don't use the GrPaint's color in this case because it's been premultiplied by // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by // the mask texture color. The end result is that we get // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor int a = SkColorGetA(fSkPaint.getColor()); // paintAlpha drawState.setColor(SkColorSetARGB(a, a, a, a)); // paintColor drawState.setBlendConstant(colorNoPreMul); drawState.setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); } else { if (0xFF == GrColorUnpackA(fPaint.getColor())) { drawState.setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true); } // set back to normal in case we took LCD path previously. drawState.setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); // We're using per-vertex color. SkASSERT(drawState.hasColorVertexAttribute()); } int nGlyphs = fCurrVertex / kVerticesPerGlyph; fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->drawIndexedInstances(&drawState, kTriangles_GrPrimitiveType, nGlyphs, kVerticesPerGlyph, kIndicesPerGlyph, &fVertexBounds); fDrawTarget->resetVertexSource(); fVertices = NULL; fTotalVertexCount -= fCurrVertex; fCurrVertex = 0; SkSafeSetNull(fCurrTexture); fVertexBounds.setLargestInverted(); } }
void GrBitmapTextContext::flushGlyphs() { if (NULL == fDrawTarget) { return; } GrDrawState* drawState = fDrawTarget->drawState(); GrDrawState::AutoRestoreEffects are(drawState); drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); if (fCurrVertex > 0) { // setup our sampler state for our text texture/atlas SkASSERT(SkIsAlign4(fCurrVertex)); SkASSERT(fCurrTexture); GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); uint32_t textureUniqueID = fCurrTexture->getUniqueID(); if (textureUniqueID != fEffectTextureUniqueID) { fCachedEffect.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture, params)); fEffectTextureUniqueID = textureUniqueID; } // This effect could be stored with one of the cache objects (atlas?) int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex : kGlyphCoordsNoColorAttributeIndex; drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx); SkASSERT(NULL != fStrike); switch (fStrike->getMaskFormat()) { // Color bitmap text case kARGB_GrMaskFormat: SkASSERT(!drawState->hasColorVertexAttribute()); drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); drawState->setColor(0xffffffff); break; // LCD text case kA888_GrMaskFormat: case kA565_GrMaskFormat: { if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || fPaint.numColorStages()) { GrPrintf("LCD Text will not draw correctly.\n"); } SkASSERT(!drawState->hasColorVertexAttribute()); // We don't use the GrPaint's color in this case because it's been premultiplied by // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by // the mask texture color. The end result is that we get // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor int a = SkColorGetA(fSkPaint.getColor()); // paintAlpha drawState->setColor(SkColorSetARGB(a, a, a, a)); // paintColor drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor())); drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); break; } // Grayscale/BW text case kA8_GrMaskFormat: // set back to normal in case we took LCD path previously. drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); // We're using per-vertex color. SkASSERT(drawState->hasColorVertexAttribute()); break; default: SkFAIL("Unexepected mask format."); } int nGlyphs = fCurrVertex / 4; fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, nGlyphs, 4, 6, &fVertexBounds); fDrawTarget->resetVertexSource(); fVertices = NULL; fMaxVertices = 0; fCurrVertex = 0; fVertexBounds.setLargestInverted(); SkSafeSetNull(fCurrTexture); } }