| 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); | 
| +    } | 
| +} | 
|  |