| Index: src/core/SkBlitter_PM4f.cpp
|
| diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bd8ae493dab9f2bca50d98eb07f3c02163a66d25
|
| --- /dev/null
|
| +++ b/src/core/SkBlitter_PM4f.cpp
|
| @@ -0,0 +1,159 @@
|
| +/*
|
| + * Copyright 2016 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#include "SkCoreBlitters.h"
|
| +#include "SkColorPriv.h"
|
| +#include "SkShader.h"
|
| +#include "SkUtils.h"
|
| +#include "SkXfermode.h"
|
| +#include "SkBlitMask.h"
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +SkARGB32_Shader4f_Blitter::SkARGB32_Shader4f_Blitter(const SkPixmap& device,
|
| + const SkPaint& paint, SkShader::Context* shaderContext)
|
| + : INHERITED(device, paint, shaderContext)
|
| +{
|
| + const uint32_t shaderFlags = shaderContext->getFlags();
|
| +
|
| + SkASSERT(shaderFlags & SkShader::kSupports4f_Flag);
|
| +
|
| + fBuffer = (SkPM4f*)sk_malloc_throw(device.width() * (sizeof(SkPM4f)));
|
| +
|
| + fState.fXfer = SkSafeRef(paint.getXfermode());
|
| + fState.fFlags = 0;
|
| + if (shaderFlags & SkShader::kOpaqueAlpha_Flag) {
|
| + fState.fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
|
| + }
|
| + if (device.info().isSRGB()) {
|
| + fState.fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag;
|
| + }
|
| + if (fState.fXfer) {
|
| + fProc1 = fState.fXfer->getPM4fProc1(fState.fFlags);
|
| + fProcN = fState.fXfer->getPM4fProcN(fState.fFlags);
|
| + } else {
|
| + fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fState.fFlags);
|
| + fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fState.fFlags);
|
| + }
|
| +
|
| + fConstInY = SkToBool(shaderFlags & SkShader::kConstInY32_Flag);
|
| +}
|
| +
|
| +SkARGB32_Shader4f_Blitter::~SkARGB32_Shader4f_Blitter() {
|
| + SkSafeUnref(fState.fXfer);
|
| + sk_free(fBuffer);
|
| +}
|
| +
|
| +void SkARGB32_Shader4f_Blitter::blitH(int x, int y, int width) {
|
| + SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
|
| +
|
| + uint32_t* device = fDevice.writable_addr32(x, y);
|
| + fShaderContext->shadeSpan4f(x, y, fBuffer, width);
|
| + fProcN(fState, device, fBuffer, width, nullptr);
|
| +}
|
| +
|
| +void SkARGB32_Shader4f_Blitter::blitRect(int x, int y, int width, int height) {
|
| + SkASSERT(x >= 0 && y >= 0 &&
|
| + x + width <= fDevice.width() && y + height <= fDevice.height());
|
| +
|
| + uint32_t* device = fDevice.writable_addr32(x, y);
|
| + size_t deviceRB = fDevice.rowBytes();
|
| +
|
| + if (fConstInY) {
|
| + fShaderContext->shadeSpan4f(x, y, fBuffer, width);
|
| + do {
|
| + fProcN(fState, device, fBuffer, width, nullptr);
|
| + y += 1;
|
| + device = (uint32_t*)((char*)device + deviceRB);
|
| + } while (--height > 0);
|
| + } else {
|
| + do {
|
| + fShaderContext->shadeSpan4f(x, y, fBuffer, width);
|
| + fProcN(fState, device, fBuffer, width, nullptr);
|
| + y += 1;
|
| + device = (uint32_t*)((char*)device + deviceRB);
|
| + } while (--height > 0);
|
| + }
|
| +}
|
| +
|
| +void SkARGB32_Shader4f_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
|
| + const int16_t runs[]) {
|
| + uint32_t* device = fDevice.writable_addr32(x, y);
|
| +
|
| + for (;;) {
|
| + int count = *runs;
|
| + if (count <= 0) {
|
| + break;
|
| + }
|
| + int aa = *antialias;
|
| + if (aa) {
|
| + fShaderContext->shadeSpan4f(x, y, fBuffer, count);
|
| + if (aa == 255) {
|
| + fProcN(fState, device, fBuffer, count, nullptr);
|
| + } else {
|
| + // count is almost always 1
|
| + for (int i = count - 1; i >= 0; --i) {
|
| + fProcN(fState, &device[i], &fBuffer[i], 1, antialias);
|
| + }
|
| + }
|
| + }
|
| + device += count;
|
| + runs += count;
|
| + antialias += count;
|
| + x += count;
|
| + }
|
| +}
|
| +
|
| +void SkARGB32_Shader4f_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
|
| + // we only handle kA8
|
| + if (SkMask::kA8_Format != mask.fFormat) {
|
| + this->INHERITED::blitMask(mask, clip);
|
| + return;
|
| + }
|
| +
|
| + SkASSERT(mask.fBounds.contains(clip));
|
| +
|
| + const int x = clip.fLeft;
|
| + const int width = clip.width();
|
| + int y = clip.fTop;
|
| + int height = clip.height();
|
| +
|
| + char* dstRow = (char*)fDevice.writable_addr32(x, y);
|
| + const size_t dstRB = fDevice.rowBytes();
|
| + const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
|
| + const size_t maskRB = mask.fRowBytes;
|
| +
|
| + do {
|
| + fShaderContext->shadeSpan4f(x, y, fBuffer, width);
|
| + fProcN(fState, reinterpret_cast<SkPMColor*>(dstRow), fBuffer, width, maskRow);
|
| + dstRow += dstRB;
|
| + maskRow += maskRB;
|
| + y += 1;
|
| + } while (--height > 0);
|
| +}
|
| +
|
| +void SkARGB32_Shader4f_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
|
| + SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
|
| +
|
| + uint32_t* device = fDevice.writable_addr32(x, y);
|
| + size_t deviceRB = fDevice.rowBytes();
|
| +
|
| + if (fConstInY) {
|
| + fShaderContext->shadeSpan4f(x, y, fBuffer, 1);
|
| + do {
|
| + fProcN(fState, device, fBuffer, 1, &alpha);
|
| + device = (uint32_t*)((char*)device + deviceRB);
|
| + } while (--height > 0);
|
| + } else {
|
| + do {
|
| + fShaderContext->shadeSpan4f(x, y, fBuffer, 1);
|
| + fProcN(fState, device, fBuffer, 1, &alpha);
|
| + y += 1;
|
| + device = (uint32_t*)((char*)device + deviceRB);
|
| + } while (--height > 0);
|
| + }
|
| +}
|
|
|