void GrResourceIOProcessor::TextureSampler::reset(GrResourceProvider* resourceProvider, sk_sp<GrTextureProxy> proxy, const GrSamplerParams& params, GrShaderFlags visibility) { // For now, end the deferral at this time. Once all the TextureSamplers are swapped over // to taking a GrSurfaceProxy just use the IORefs on the proxy GrTexture* texture = proxy->instantiate(resourceProvider); SkASSERT(texture); fTexture.set(SkRef(texture), kRead_GrIOType); fParams = params; fParams.setFilterMode(SkTMin(params.filterMode(), texture->texturePriv().highestFilterMode())); fVisibility = visibility; }
void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds, uint32_t mipLevels) const { SkASSERT(surface); // Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds. if (nullptr == bounds || !bounds->isEmpty()) { if (GrRenderTarget* target = surface->asRenderTarget()) { SkIRect flippedBounds; if (kBottomLeft_GrSurfaceOrigin == origin && bounds) { flippedBounds = {bounds->fLeft, surface->height() - bounds->fBottom, bounds->fRight, surface->height() - bounds->fTop}; bounds = &flippedBounds; } target->flagAsNeedingResolve(bounds); } GrTexture* texture = surface->asTexture(); if (texture && 1 == mipLevels) { texture->texturePriv().markMipMapsDirty(); } } }
std::unique_ptr<SkCrossContextImageData> SkCrossContextImageData::MakeFromEncoded( GrContext* context, sk_sp<SkData> encoded, SkColorSpace* dstColorSpace) { sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(std::move(encoded)); if (!codecImage) { return nullptr; } // Some backends or drivers don't support (safely) moving resources between contexts if (!context->caps()->crossContextTextureSupport()) { return std::unique_ptr<SkCrossContextImageData>( new SkCrossContextImageData(std::move(codecImage))); } sk_sp<SkImage> textureImage = codecImage->makeTextureImage(context, dstColorSpace); if (!textureImage) { // TODO: Force decode to raster here? Do mip-mapping, like getDeferredTextureImageData? return std::unique_ptr<SkCrossContextImageData>( new SkCrossContextImageData(std::move(codecImage))); } // Crack open the gpu image, extract the backend data, stick it in the SkCCID GrTexture* texture = as_IB(textureImage)->peekTexture(); SkASSERT(texture); GrBackendTextureDesc desc; desc.fFlags = kNone_GrBackendTextureFlag; desc.fOrigin = texture->origin(); desc.fWidth = texture->width(); desc.fHeight = texture->height(); desc.fConfig = texture->config(); desc.fSampleCnt = 0; context->contextPriv().prepareSurfaceForExternalIO(as_IB(textureImage)->peekProxy()); auto textureData = texture->texturePriv().detachBackendTexture(); SkASSERT(textureData); SkImageInfo info = as_IB(textureImage)->onImageInfo(); return std::unique_ptr<SkCrossContextImageData>(new SkCrossContextImageData( desc, std::move(textureData), info.alphaType(), info.refColorSpace())); }
// Returns true if this method handled the glyph, false if needs to be passed to fallback // bool GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, SkScalar sx, SkScalar sy, GrFontScaler* scaler) { if (NULL == fDrawTarget) { return true; } if (NULL == fStrike) { fStrike = fContext->getFontCache()->getStrike(scaler, true); } GrGlyph* glyph = fStrike->getGlyph(packed, scaler); if (NULL == glyph || glyph->fBounds.isEmpty()) { return true; } // fallback to color glyph support if (kA8_GrMaskFormat != glyph->fMaskFormat) { return false; } SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldInset); SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset); SkScalar scale = fTextRatio; dx *= scale; dy *= scale; sx += dx; sy += dy; width *= scale; height *= scale; SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); // check if we clipped out SkRect dstRect; const SkMatrix& ctm = fContext->getMatrix(); (void) ctm.mapRect(&dstRect, glyphRect); if (fClipRect.quickReject(SkScalarTruncToInt(dstRect.left()), SkScalarTruncToInt(dstRect.top()), SkScalarTruncToInt(dstRect.right()), SkScalarTruncToInt(dstRect.bottom()))) { // SkCLZ(3); // so we can set a break-point in the debugger return true; } if (NULL == glyph->fPlot) { if (!fStrike->glyphTooLargeForAtlas(glyph)) { if (fStrike->addGlyphToAtlas(glyph, scaler)) { goto HAS_ATLAS; } // try to clear out an unused plot before we flush if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) && fStrike->addGlyphToAtlas(glyph, scaler)) { goto HAS_ATLAS; } if (c_DumpFontCache) { #ifdef SK_DEVELOPER fContext->getFontCache()->dump(); #endif } // before we purge the cache, we must flush any accumulated draws this->flush(); fContext->flush(); // we should have an unused plot now if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) && fStrike->addGlyphToAtlas(glyph, scaler)) { goto HAS_ATLAS; } } if (NULL == glyph->fPath) { SkPath* path = SkNEW(SkPath); if (!scaler->getGlyphPath(glyph->glyphID(), path)) { // flag the glyph as being dead? delete path; return true; } glyph->fPath = path; } // flush any accumulated draws before drawing this glyph as a path. this->flush(); GrContext::AutoMatrix am; SkMatrix ctm; ctm.setScale(fTextRatio, fTextRatio); ctm.postTranslate(sx - dx, sy - dy); GrPaint tmpPaint(fPaint); am.setPreConcat(fContext, ctm, &tmpPaint); GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo); // remove this glyph from the vertices we need to allocate fTotalVertexCount -= kVerticesPerGlyph; return true; } HAS_ATLAS: SkASSERT(glyph->fPlot); GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); glyph->fPlot->setDrawToken(drawToken); GrTexture* texture = glyph->fPlot->texture(); SkASSERT(texture); if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fTotalVertexCount) { this->flush(); fCurrTexture = texture; fCurrTexture->ref(); } bool useColorVerts = !fUseLCDText; if (NULL == fVertices) { int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads(); fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices); fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, useColorVerts); } SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset); SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset); SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset); SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset); fVertexBounds.joinNonEmptyArg(glyphRect); size_t vertSize = get_vertex_stride(useColorVerts); SkPoint* positions = reinterpret_cast<SkPoint*>( reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex); positions->setRectFan(glyphRect.fLeft, glyphRect.fTop, glyphRect.fRight, glyphRect.fBottom, vertSize); // The texture coords are last in both the with and without color vertex layouts. SkPoint* textureCoords = reinterpret_cast<SkPoint*>( reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint)); textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)), SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)), SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + tw)), SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)), vertSize); if (useColorVerts) { // color comes after position. GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); for (int i = 0; i < 4; ++i) { *colors = fPaint.getColor(); colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize); } } fCurrVertex += 4; return true; }
void SkGrPixelRef::onNotifyPixelsChanged() { GrTexture* texture = this->getTexture(); if (texture) { texture->texturePriv().dirtyMipMaps(true); } }