1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
758af9a64701540c7f8083bc22a42d0bae3a5583creed@google.com
8c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkBlitRow.h"
958af9a64701540c7f8083bc22a42d0bae3a5583creed@google.com#include "SkBlitMask.h"
10c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkColorPriv.h"
112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson#include "SkOpts.h"
12c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkUtils.h"
13c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
1457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#define UNROLL
1557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com
16c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.comstatic void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
17c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                                 const SkPMColor* SK_RESTRICT src,
18c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                                 int count, U8CPU alpha) {
19c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkASSERT(255 == alpha);
202880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    memcpy(dst, src, count * 4);
21c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com}
22c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
23c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.comstatic void S32_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
24c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                                const SkPMColor* SK_RESTRICT src,
25c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                                int count, U8CPU alpha) {
26c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkASSERT(alpha <= 255);
27c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    if (count > 0) {
28c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        unsigned src_scale = SkAlpha255To256(alpha);
29c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        unsigned dst_scale = 256 - src_scale;
3057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com
3157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#ifdef UNROLL
3257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        if (count & 1) {
3357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
3457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
3557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            count -= 1;
3657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        }
3757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com
3857f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        const SkPMColor* SK_RESTRICT srcEnd = src + count;
3957f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        while (src != srcEnd) {
4057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
4157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
4257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
4357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
4457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        }
4557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#else
46c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        do {
47c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
48c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            src += 1;
49c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            dst += 1;
50c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        } while (--count > 0);
5157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#endif
52c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    }
53c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com}
54c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
55c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.comstatic void S32A_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
56c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                                  const SkPMColor* SK_RESTRICT src,
57c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                                  int count, U8CPU alpha) {
58c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkASSERT(255 == alpha);
59c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    if (count > 0) {
6057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#ifdef UNROLL
6157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        if (count & 1) {
6257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkPMSrcOver(*(src++), *dst);
6357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
6457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            count -= 1;
6557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        }
6657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com
6757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        const SkPMColor* SK_RESTRICT srcEnd = src + count;
6857f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        while (src != srcEnd) {
6957f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkPMSrcOver(*(src++), *dst);
7057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
7157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkPMSrcOver(*(src++), *dst);
7257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
7357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        }
7457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#else
75c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        do {
76c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            *dst = SkPMSrcOver(*src, *dst);
77c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            src += 1;
78c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            dst += 1;
79c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        } while (--count > 0);
8057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#endif
81c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    }
82c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com}
83c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
84c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.comstatic void S32A_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
85c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                                 const SkPMColor* SK_RESTRICT src,
86c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                                 int count, U8CPU alpha) {
87c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkASSERT(alpha <= 255);
88c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    if (count > 0) {
8957f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#ifdef UNROLL
9057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        if (count & 1) {
9157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkBlendARGB32(*(src++), *dst, alpha);
9257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
9357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            count -= 1;
9457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        }
9557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com
9657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        const SkPMColor* SK_RESTRICT srcEnd = src + count;
9757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        while (src != srcEnd) {
9857f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkBlendARGB32(*(src++), *dst, alpha);
9957f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
10057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            *dst = SkBlendARGB32(*(src++), *dst, alpha);
10157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            dst += 1;
10257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        }
10357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#else
104c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        do {
105c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            *dst = SkBlendARGB32(*src, *dst, alpha);
106c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            src += 1;
107c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            dst += 1;
108c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        } while (--count > 0);
10957f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com#endif
110c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    }
111c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com}
112c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
113c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com///////////////////////////////////////////////////////////////////////////////
114c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
115c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.comstatic const SkBlitRow::Proc32 gDefault_Procs32[] = {
116c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    S32_Opaque_BlitRow32,
117c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    S32_Blend_BlitRow32,
118c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    S32A_Opaque_BlitRow32,
119c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    S32A_Blend_BlitRow32
120c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com};
121c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
122c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.comSkBlitRow::Proc32 SkBlitRow::Factory32(unsigned flags) {
123c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkASSERT(flags < SK_ARRAY_COUNT(gDefault_Procs32));
124c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    // just so we don't crash
125c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    flags &= kFlags32_Mask;
126981d4798007b91e2e19c13b171583927a56df63breed@google.com
1279272761b22746d2d22439c26f5555028f8e824dasenorblanco@chromium.org    SkBlitRow::Proc32 proc = PlatformProcs32(flags);
1282880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    if (nullptr == proc) {
129c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        proc = gDefault_Procs32[flags];
130c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    }
131c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkASSERT(proc);
132c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    return proc;
133c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com}
134c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
13595cc012ccaea20f372893ae277ea0a8a6339d094mtkleinvoid SkBlitRow::Color32(SkPMColor dst[], const SkPMColor src[], int count, SkPMColor color) {
136afe2ffb8ba5e7362a2ee6f4e1540c9ab22df2c1emtklein    switch (SkGetPackedA32(color)) {
137afe2ffb8ba5e7362a2ee6f4e1540c9ab22df2c1emtklein        case   0: memmove(dst, src, count * sizeof(SkPMColor)); return;
138afe2ffb8ba5e7362a2ee6f4e1540c9ab22df2c1emtklein        case 255: sk_memset32(dst, color, count);               return;
139afe2ffb8ba5e7362a2ee6f4e1540c9ab22df2c1emtklein    }
1402880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    return SkOpts::blit_row_color32(dst, src, count, color);
141c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com}
142