void SkRasterPipelineBlitter::blitH(int x, int y, int w) { fDstPtr = fDst.writable_addr(0,y); fCurrentY = y; if (fCanMemsetInBlitH) { switch (fDst.shiftPerPixel()) { case 0: memset ((uint8_t *)fDstPtr + x, fMemsetColor, w); return; case 1: sk_memset16((uint16_t*)fDstPtr + x, fMemsetColor, w); return; case 2: sk_memset32((uint32_t*)fDstPtr + x, fMemsetColor, w); return; case 3: sk_memset64((uint64_t*)fDstPtr + x, fMemsetColor, w); return; default: break; } } auto& p = fBlitH; if (p.empty()) { p.extend(fShader); if (fBlend != SkBlendMode::kSrc) { this->append_load_d(&p); this->append_blend(&p); this->maybe_clamp(&p); } this->append_store(&p); } p.run(x,w); }
uint8_t* SourceSurfaceSkia::GetData() { #ifdef USE_SKIA_GPU if (mImage->isTextureBacked()) { sk_sp<SkImage> raster; if (sk_sp<SkData> data = MakeSkData(nullptr, mSize, mStride)) { SkImageInfo info = MakeSkiaImageInfo(mSize, mFormat); if (mImage->readPixels(info, data->writable_data(), mStride, 0, 0, SkImage::kDisallow_CachingHint)) { raster = SkImage::MakeRasterData(info, data, mStride); } } if (raster) { mImage = raster; } else { gfxCriticalError() << "Failed making Skia raster image for GPU surface"; } } #endif SkPixmap pixmap; if (!mImage->peekPixels(&pixmap)) { gfxCriticalError() << "Failed accessing pixels for Skia raster image"; } return reinterpret_cast<uint8_t*>(pixmap.writable_addr()); }
bool onGetROPixels(SkBitmap* dst) const override { const auto desc = SkBitmapCacheDesc::Make(this->uniqueID(), this->width(), this->height()); if (SkBitmapCache::Find(desc, dst)) { SkASSERT(dst->getGenerationID() == this->uniqueID()); SkASSERT(dst->isImmutable()); SkASSERT(dst->getPixels()); return true; } SkPixmap pmap; SkImageInfo info = SkImageInfo::MakeN32(this->width(), this->height(), this->alphaType(), fColorSpace); auto rec = SkBitmapCache::Alloc(desc, info, &pmap); if (!rec) { return false; } sk_sp<SkColorSpace> colorSpace; if (GrPixelConfigIsSRGB(fTextureProxy->config())) { colorSpace = SkColorSpace::MakeSRGB(); } sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeWrappedSurfaceContext( fTextureProxy, std::move(colorSpace)); if (!sContext) { return false; } if (!sContext->readPixels(info, pmap.writable_addr(), pmap.rowBytes(), 0, 0)) { return false; } SkBitmapCache::Add(std::move(rec), dst); fAddedRasterVersionToCache.store(true); return true; }
std::unique_ptr<SkEncoder> SkPngEncoder::Make(SkWStream* dst, const SkPixmap& src, const Options& options) { if (!SkPixmapIsValid(src)) { return nullptr; } std::unique_ptr<SkPngEncoderMgr> encoderMgr = SkPngEncoderMgr::Make(dst); if (!encoderMgr) { return nullptr; } if (!encoderMgr->setHeader(src.info(), options)) { return nullptr; } if (!encoderMgr->setColorSpace(src.info())) { return nullptr; } if (!encoderMgr->writeInfo(src.info())) { return nullptr; } encoderMgr->chooseProc(src.info()); return std::unique_ptr<SkPngEncoder>(new SkPngEncoder(std::move(encoderMgr), src)); }
/** * For the purposes of drawing bitmaps, if a matrix is "almost" translate * go ahead and treat it as if it were, so that subsequent code can go fast. */ static bool just_trans_clamp(const SkMatrix& matrix, const SkPixmap& pixmap) { SkASSERT(matrix_only_scale_translate(matrix)); if (matrix.getType() & SkMatrix::kScale_Mask) { SkRect dst; SkRect src = SkRect::Make(pixmap.bounds()); // Can't call mapRect(), since that will fix up inverted rectangles, // e.g. when scale is negative, and we don't want to return true for // those. matrix.mapPoints(SkTCast<SkPoint*>(&dst), SkTCast<const SkPoint*>(&src), 2); // Now round all 4 edges to device space, and then compare the device // width/height to the original. Note: we must map all 4 and subtract // rather than map the "width" and compare, since we care about the // phase (in pixel space) that any translate in the matrix might impart. SkIRect idst; dst.round(&idst); return idst.width() == pixmap.width() && idst.height() == pixmap.height(); } // if we got here, we're either kTranslate_Mask or identity return true; }
void SkLinearGradient:: LinearGradient4fContext::D32_BlitBW(BlitState* state, int x, int y, const SkPixmap& dst, int count) { // FIXME: ignoring coverage for now const LinearGradient4fContext* ctx = static_cast<const LinearGradient4fContext*>(state->fCtx); if (!dst.info().gammaCloseToSRGB()) { if (ctx->fColorsArePremul) { ctx->shadePremulSpan<DstType::L32, ApplyPremul::False>( x, y, dst.writable_addr32(x, y), count); } else { ctx->shadePremulSpan<DstType::L32, ApplyPremul::True>( x, y, dst.writable_addr32(x, y), count); } } else { if (ctx->fColorsArePremul) { ctx->shadePremulSpan<DstType::S32, ApplyPremul::False>( x, y, dst.writable_addr32(x, y), count); } else { ctx->shadePremulSpan<DstType::S32, ApplyPremul::True>( x, y, dst.writable_addr32(x, y), count); } } }
void SkLinearGradient:: LinearGradient4fContext::D32_BlitBW(BlitState* state, int x, int y, const SkPixmap& dst, int count) { // FIXME: ignoring coverage for now const LinearGradient4fContext* ctx = static_cast<const LinearGradient4fContext*>(state->fCtx); if (dst.info().isLinear()) { if (ctx->fColorsArePremul) { ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False>( x, y, dst.writable_addr32(x, y), count); } else { ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::True>( x, y, dst.writable_addr32(x, y), count); } } else { if (ctx->fColorsArePremul) { ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::False>( x, y, dst.writable_addr32(x, y), count); } else { ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::True>( x, y, dst.writable_addr32(x, y), count); } } }
bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) { SkPixmap srcPM; if (!src.peekPixels(&srcPM)) { return false; } SkBitmap tmpDst; SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType); if (!tmpDst.setInfo(dstInfo)) { return false; } if (!tmpDst.tryAllocPixels()) { return false; } SkPixmap dstPM; if (!tmpDst.peekPixels(&dstPM)) { return false; } if (!srcPM.readPixels(dstPM)) { return false; } dst->swap(tmpDst); return true; }
void SkRasterPipelineBlitter::blitH(int x, int y, int w) { fDstPtr = fDst.writable_addr(0,y); if (fCanMemsetInBlitH) { switch (fDst.shiftPerPixel()) { case 0: memset ((uint8_t *)fDstPtr + x, fMemsetColor, w); return; case 1: sk_memset16((uint16_t*)fDstPtr + x, fMemsetColor, w); return; case 2: sk_memset32((uint32_t*)fDstPtr + x, fMemsetColor, w); return; case 3: sk_memset64((uint64_t*)fDstPtr + x, fMemsetColor, w); return; default: break; } } if (!fBlitH) { SkRasterPipeline p(fAlloc); p.extend(fColorPipeline); if (fBlend == SkBlendMode::kSrcOver && fDst.info().colorType() == kRGBA_8888_SkColorType && !fDst.colorSpace() && fDst.info().alphaType() != kUnpremul_SkAlphaType && fDitherRate == 0.0f) { p.append(SkRasterPipeline::srcover_rgba_8888, &fDstPtr); } else { if (fBlend != SkBlendMode::kSrc) { this->append_load_d(&p); this->append_blend(&p); this->maybe_clamp(&p); } this->append_store(&p); } fBlitH = p.compile(); } this->maybe_shade(x,y,w); fBlitH(x,y,w); }
std::unique_ptr<SkEncoder> SkJpegEncoder::Make(SkWStream* dst, const SkPixmap& src, const Options& options) { if (!SkPixmapIsValid(src, options.fBlendBehavior)) { return nullptr; } std::unique_ptr<SkJpegEncoderMgr> encoderMgr = SkJpegEncoderMgr::Make(dst); if (setjmp(encoderMgr->jmpBuf())) { return nullptr; } if (!encoderMgr->setParams(src.info(), options)) { return nullptr; } jpeg_set_quality(encoderMgr->cinfo(), options.fQuality, TRUE); jpeg_start_compress(encoderMgr->cinfo(), TRUE); sk_sp<SkData> icc = icc_from_color_space(src.info()); if (icc) { // Create a contiguous block of memory with the icc signature followed by the profile. sk_sp<SkData> markerData = SkData::MakeUninitialized(kICCMarkerHeaderSize + icc->size()); uint8_t* ptr = (uint8_t*) markerData->writable_data(); memcpy(ptr, kICCSig, sizeof(kICCSig)); ptr += sizeof(kICCSig); *ptr++ = 1; // This is the first marker. *ptr++ = 1; // Out of one total markers. memcpy(ptr, icc->data(), icc->size()); jpeg_write_marker(encoderMgr->cinfo(), kICCMarker, markerData->bytes(), markerData->size()); } return std::unique_ptr<SkJpegEncoder>(new SkJpegEncoder(std::move(encoderMgr), src)); }
static void call_proc_X(SkMorphologyImageFilter::Proc procX, const SkPixmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds) { procX(src.addr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), radiusX, bounds.width(), bounds.height(), src.rowBytesAsPixels(), dst->rowBytesAsPixels()); }
static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { if (dst.colorType() != src.colorType()) { return false; } if (dst.info().profileType() != src.info().profileType()) { return false; } if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) { return false; } if (0xFF != paint.getAlpha()) { return false; } SkXfermode::Mode mode; if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { return false; } if (SkXfermode::kSrc_Mode == mode) { return true; } if (SkXfermode::kSrcOver_Mode == mode && src.isOpaque()) { return true; } return false; }
bool SkLinearBitmapPipeline::ClonePipelineForBlitting( SkEmbeddableLinearPipeline* pipelineStorage, const SkLinearBitmapPipeline& pipeline, SkMatrix::TypeMask matrixMask, SkShader::TileMode xTileMode, SkShader::TileMode yTileMode, SkFilterQuality filterQuality, const SkPixmap& srcPixmap, float finalAlpha, SkXfermode::Mode xferMode, const SkImageInfo& dstInfo) { if (xferMode == SkXfermode::kSrcOver_Mode && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) { xferMode = SkXfermode::kSrc_Mode; } if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return false; } if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return false; } if (finalAlpha != 1.0f) { return false; } if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType || dstInfo.colorType() != kRGBA_8888_SkColorType) { return false; } if (!srcPixmap.info().gammaCloseToSRGB() || !dstInfo.gammaCloseToSRGB()) { return false; } if (xferMode != SkXfermode::kSrc_Mode && xferMode != SkXfermode::kSrcOver_Mode) { return false; } pipelineStorage->init(pipeline, srcPixmap, xferMode, dstInfo); return true; }
void SkRasterPipelineBlitter::append_blend(SkRasterPipeline* p) const { if (fDst.info().alphaType() == kUnpremul_SkAlphaType) { p->append(SkRasterPipeline::premul_dst); } SkBlendMode_AppendStagesNoClamp(fBlend, p); if (fDst.info().alphaType() == kUnpremul_SkAlphaType) { p->append(SkRasterPipeline::unpremul); } }
SkSpecialImage_Raster(const SkIRect& subset, const SkPixmap& pixmap, RasterReleaseProc releaseProc, ReleaseContext context, const SkSurfaceProps* props) : INHERITED(subset, kNeedNewImageUniqueID_SpecialImage, props) { fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(), pixmap.ctable(), releaseProc, context); }
bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const { // Can't do anthing with empty src or dst if (this->width() <= 0 || this->height() <= 0 || dst.width() <= 0 || dst.height() <= 0) { return false; } // no scaling involved? if (dst.width() == this->width() && dst.height() == this->height()) { return this->readPixels(dst); } SkBitmap bitmap; if (!bitmap.installPixels(*this)) { return false; } bitmap.setIsVolatile(true); // so we don't try to cache it SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterDirect(dst.info(), dst.writable_addr(), dst.rowBytes())); if (!surface) { return false; } SkPaint paint; paint.setFilterQuality(quality); paint.setXfermodeMode(SkXfermode::kSrc_Mode); surface->getCanvas()->drawBitmapRect(bitmap, SkRect::MakeIWH(dst.width(), dst.height()), &paint); return true; }
void draw(SkCanvas* canvas) { std::vector<int32_t> pixels; pixels.resize(image->height() * image->width() * 4); SkPixmap pixmap(SkImageInfo::Make(image->width(), image->height(), kN32_SkColorType, image->alphaType()), (const void*) &pixels.front(), image->width() * 4); image->readPixels(pixmap, 0, 0); SkDebugf("pixels address: 0x%llx\n", pixmap.addr()); SkPixmap inset; if (pixmap.extractSubset(&inset, {128, 128, 512, 512})) { SkDebugf("inset address: 0x%llx\n", inset.addr()); } }
const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) { SkPixmap pm; if (this->peekPixels(&pm)) { if (info) { *info = pm.info(); } if (rowBytes) { *rowBytes = pm.rowBytes(); } return pm.addr(); } return nullptr; }
sk_sp<SkImage> SkImage::MakeTextureFromPixmap(GrContext* ctx, const SkPixmap& pixmap, SkBudgeted budgeted) { if (!ctx) { return nullptr; } sk_sp<GrTexture> texture(GrUploadPixmapToTexture(ctx, pixmap, budgeted)); if (!texture) { return nullptr; } return sk_make_sp<SkImage_Gpu>(texture->width(), texture->height(), kNeedNewImageUniqueID, pixmap.alphaType(), std::move(texture), sk_ref_sp(pixmap.info().colorSpace()), budgeted); }
size_t getSize() const override { #if SK_SUPPORT_GPU if (GrTexture* texture = as_IB(fImage.get())->peekTexture()) { return texture->gpuMemorySize(); } else #endif { SkPixmap pm; if (fImage->peekPixels(&pm)) { return pm.height() * pm.rowBytes(); } } return 0; }
void SkLinearGradient:: LinearGradient4fContext::D64_BlitBW(BlitState* state, int x, int y, const SkPixmap& dst, int count) { // FIXME: ignoring coverage for now const LinearGradient4fContext* ctx = static_cast<const LinearGradient4fContext*>(state->fCtx); if (ctx->fColorsArePremul) { ctx->shadePremulSpan<DstType::F16, ApplyPremul::False>( x, y, dst.writable_addr64(x, y), count); } else { ctx->shadePremulSpan<DstType::F16, ApplyPremul::True>( x, y, dst.writable_addr64(x, y), count); } }
void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p) const { switch (fDst.info().colorType()) { case kGray_8_SkColorType: p->append(SkRasterPipeline::load_g8_dst, &fDstPtr); break; case kAlpha_8_SkColorType: p->append(SkRasterPipeline::load_a8_dst, &fDstPtr); break; case kRGB_565_SkColorType: p->append(SkRasterPipeline::load_565_dst, &fDstPtr); break; case kARGB_4444_SkColorType: p->append(SkRasterPipeline::load_4444_dst, &fDstPtr); break; case kBGRA_8888_SkColorType: p->append(SkRasterPipeline::load_bgra_dst, &fDstPtr); break; case kRGBA_8888_SkColorType: p->append(SkRasterPipeline::load_8888_dst, &fDstPtr); break; case kRGBA_F16_SkColorType: p->append(SkRasterPipeline::load_f16_dst, &fDstPtr); break; default: break; } if (fDst.info().gammaCloseToSRGB()) { p->append_from_srgb_dst(fDst.info().alphaType()); } }
bool SkBitmapScaler::Resize(SkBitmap* resultPtr, const SkPixmap& source, ResizeMethod method, int destWidth, int destHeight, SkBitmap::Allocator* allocator) { if (nullptr == source.addr() || source.colorType() != kN32_SkColorType || source.width() < 1 || source.height() < 1) { return false; } if (destWidth < 1 || destHeight < 1) { return false; } SkConvolutionProcs convolveProcs= { 0, nullptr, nullptr, nullptr, nullptr }; PlatformConvolutionProcs(&convolveProcs); SkRect destSubset = SkRect::MakeIWH(destWidth, destHeight); SkResizeFilter filter(method, source.width(), source.height(), destWidth, destHeight, destSubset, convolveProcs); // Get a subset encompassing this touched area. We construct the // offsets and row strides such that it looks like a new bitmap, while // referring to the old data. const uint8_t* sourceSubset = reinterpret_cast<const uint8_t*>(source.addr()); // Convolve into the result. SkBitmap result; result.setInfo(SkImageInfo::MakeN32(SkScalarCeilToInt(destSubset.width()), SkScalarCeilToInt(destSubset.height()), source.alphaType())); result.allocPixels(allocator, nullptr); if (!result.readyToDraw()) { return false; } if (!BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()), !source.isOpaque(), filter.xFilter(), filter.yFilter(), static_cast<int>(result.rowBytes()), static_cast<unsigned char*>(result.getPixels()), convolveProcs, true)) { return false; } *resultPtr = result; resultPtr->lockPixels(); SkASSERT(resultPtr->getPixels()); return true; }
Sprite_sRGB(const SkPixmap& src, const SkPaint& paint) : INHERITED(src, paint) { uint32_t flags = SkXfermode::kDstIsSRGB_D32Flag; if (src.isOpaque()) { flags |= SkXfermode::kSrcIsOpaque_D32Flag; } fWriter = SkXfermode::GetD32Proc(fXfer, flags); }
void SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) { if (!fBlitAntiH) { SkRasterPipeline p(fAlloc); p.extend(fColorPipeline); if (fBlend == SkBlendMode::kSrcOver) { p.append(SkRasterPipeline::scale_1_float, &fCurrentCoverage); this->append_load_d(&p); this->append_blend(&p); } else { this->append_load_d(&p); this->append_blend(&p); p.append(SkRasterPipeline::lerp_1_float, &fCurrentCoverage); } this->maybe_clamp(&p); this->append_store(&p); fBlitAntiH = p.compile(); } fDstPtr = fDst.writable_addr(0,y); for (int16_t run = *runs; run > 0; run = *runs) { switch (*aa) { case 0x00: break; case 0xff: this->blitH(x,y,run); break; default: this->maybe_shade(x,y,run); fCurrentCoverage = *aa * (1/255.0f); fBlitAntiH(x,y,run); } x += run; runs += run; aa += run; } }
static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { if (dst.colorType() != src.colorType()) { return false; } if (!SkColorSpace::Equals(dst.colorSpace(), src.colorSpace())) { return false; } if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) { return false; } if (0xFF != paint.getAlpha()) { return false; } SkBlendMode mode = paint.getBlendMode(); return SkBlendMode::kSrc == mode || (SkBlendMode::kSrcOver == mode && src.isOpaque()); }
static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) { // the caller has already inspected the colorspace on src and dst SkASSERT(!SkColorSpaceXformSteps::Required(src.colorSpace(), dst.colorSpace())); if (dst.colorType() != src.colorType()) { return false; } if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) { return false; } if (0xFF != paint.getAlpha()) { return false; } SkBlendMode mode = paint.getBlendMode(); return SkBlendMode::kSrc == mode || (SkBlendMode::kSrcOver == mode && src.isOpaque()); }
void SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { if (mask.fFormat == SkMask::kBW_Format) { // TODO: native BW masks? return INHERITED::blitMask(mask, clip); } int x = clip.left(); for (int y = clip.top(); y < clip.bottom(); y++) { auto dst = fDst.writable_addr(0,y); SkRasterPipeline p; p.extend(fShader); p.extend(fColorFilter); this->append_load_d(&p, dst); p.extend(fXfermode); switch (mask.fFormat) { case SkMask::kA8_Format: p.append<lerp_a8, lerp_a8_1>(mask.getAddr8(x,y)-x); break; case SkMask::kLCD16_Format: p.append<lerp_lcd16, lerp_lcd16_1>(mask.getAddrLCD16(x,y)-x); break; default: break; } this->append_store(&p, dst); p.run(x, clip.width()); } }
Sprite_F16(const SkPixmap& src, const SkPaint& paint) : INHERITED(src, paint) { uint32_t flags = 0; if (src.isOpaque()) { flags |= SkXfermode::kSrcIsOpaque_F16Flag; } fWriter = SkXfermode::GetF16Proc(fXfer, flags); }
SkState_Shader_Blitter(const SkPixmap& device, const SkPaint& paint, const SkShader::Context::BlitState& bstate) : INHERITED(device, paint, bstate.fCtx) , fState(device.info(), paint, bstate.fCtx) , fBState(bstate) , fBlitBW(bstate.fBlitBW) , fBlitAA(bstate.fBlitAA) {}