SkBlitRow_opts_arm_neon.cpp revision 0060159457453ca45a47828648c8f29d5695983c
1a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/* 2a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * Copyright 2012 The Android Open Source Project 3a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * 4a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * Use of this source code is governed by a BSD-style license that can be 5a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * found in the LICENSE file. 6a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */ 7a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 8a111e492b84c312a6bd5d5d9ef100dca48f4941ddjsollen@google.com#include "SkBlitRow_opts_arm_neon.h" 9a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 10a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkBlitMask.h" 11a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkBlitRow.h" 12a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkColorPriv.h" 13a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkDither.h" 14a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkMathPriv.h" 15a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkUtils.h" 16a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 17a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkCachePreload_arm.h" 180060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org#include "SkColor_opts_neon.h" 19a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include <arm_neon.h> 20a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 210060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.orgvoid S32_D565_Opaque_neon(uint16_t* SK_RESTRICT dst, 220060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org const SkPMColor* SK_RESTRICT src, int count, 230060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org U8CPU alpha, int /*x*/, int /*y*/) { 240060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org SkASSERT(255 == alpha); 250060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org 260060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org while (count >= 8) { 270060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org uint8x8x4_t vsrc; 280060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org uint16x8_t vdst; 290060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org 300060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org // Load 310060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org vsrc = vld4_u8((uint8_t*)src); 320060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org 330060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org // Convert src to 565 340060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org vdst = vshll_n_u8(vsrc.val[NEON_R], 8); 350060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org vdst = vsriq_n_u16(vdst, vshll_n_u8(vsrc.val[NEON_G], 8), 5); 360060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org vdst = vsriq_n_u16(vdst, vshll_n_u8(vsrc.val[NEON_B], 8), 5+6); 370060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org 380060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org // Store 390060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org vst1q_u16(dst, vdst); 400060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org 410060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org // Prepare next iteration 420060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org dst += 8; 430060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org src += 8; 440060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org count -= 8; 450060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org }; 460060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org 470060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org // Leftovers 480060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org while (count > 0) { 490060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org SkPMColor c = *src++; 500060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org SkPMColorAssert(c); 510060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org *dst = SkPixel32ToPixel16_ToU16(c); 520060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org dst++; 530060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org count--; 540060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org }; 550060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org} 560060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org 57a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Opaque_neon(uint16_t* SK_RESTRICT dst, 58a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com const SkPMColor* SK_RESTRICT src, int count, 59a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com U8CPU alpha, int /*x*/, int /*y*/) { 60a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkASSERT(255 == alpha); 61a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 62a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count >= 8) { 63efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com uint16_t* SK_RESTRICT keep_dst = 0; 64fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 65a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com asm volatile ( 66a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "ands ip, %[count], #7 \n\t" 67a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmov.u8 d31, #1<<7 \n\t" 68a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.16 {q12}, [%[dst]] \n\t" 69a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld4.8 {d0-d3}, [%[src]] \n\t" 70a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // Thumb does not support the standard ARM conditional 71a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // instructions but instead requires the 'it' instruction 72a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // to signal conditional execution 73a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "it eq \n\t" 74a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "moveq ip, #8 \n\t" 75a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "mov %[keep_dst], %[dst] \n\t" 76fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 77a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "add %[src], %[src], ip, LSL#2 \n\t" 78a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "add %[dst], %[dst], ip, LSL#1 \n\t" 79a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "subs %[count], %[count], ip \n\t" 80a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "b 9f \n\t" 81a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // LOOP 82a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "2: \n\t" 83fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 84a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.16 {q12}, [%[dst]]! \n\t" 85a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld4.8 {d0-d3}, [%[src]]! \n\t" 86a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vst1.16 {q10}, [%[keep_dst]] \n\t" 87a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "sub %[keep_dst], %[dst], #8*2 \n\t" 88a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "subs %[count], %[count], #8 \n\t" 89a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "9: \n\t" 90a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "pld [%[dst],#32] \n\t" 91a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // expand 0565 q12 to 8888 {d4-d7} 92a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovn.u16 d4, q12 \n\t" 93a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q11, q12, #5 \n\t" 94a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q10, q12, #6+5 \n\t" 95a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovn.u16 d5, q11 \n\t" 96a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovn.u16 d6, q10 \n\t" 97a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshl.u8 d4, d4, #3 \n\t" 98a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshl.u8 d5, d5, #2 \n\t" 99a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshl.u8 d6, d6, #3 \n\t" 100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 101a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q14, d31 \n\t" 102a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q13, d31 \n\t" 103a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q12, d31 \n\t" 104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 105a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // duplicate in 4/2/1 & 8pix vsns 106a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmvn.8 d30, d3 \n\t" 107a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmlal.u8 q14, d30, d6 \n\t" 108a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmlal.u8 q13, d30, d5 \n\t" 109a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmlal.u8 q12, d30, d4 \n\t" 110a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q8, q14, #5 \n\t" 111a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q9, q13, #6 \n\t" 112a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddhn.u16 d6, q14, q8 \n\t" 113a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q8, q12, #5 \n\t" 114a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddhn.u16 d5, q13, q9 \n\t" 115a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vqadd.u8 d6, d6, d0 \n\t" // moved up 116a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddhn.u16 d4, q12, q8 \n\t" 117a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // intentionally don't calculate alpha 118a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // result in d4-d6 119fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 120a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vqadd.u8 d5, d5, d1 \n\t" 121a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vqadd.u8 d4, d4, d2 \n\t" 122fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 123a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // pack 8888 {d4-d6} to 0565 q10 124a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshll.u8 q10, d6, #8 \n\t" 125a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshll.u8 q3, d5, #8 \n\t" 126a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshll.u8 q2, d4, #8 \n\t" 127a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsri.u16 q10, q3, #5 \n\t" 128a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsri.u16 q10, q2, #11 \n\t" 129fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 130a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "bne 2b \n\t" 131fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 132a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "1: \n\t" 133a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vst1.16 {q10}, [%[keep_dst]] \n\t" 134a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : [count] "+r" (count) 135fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com : [dst] "r" (dst), [keep_dst] "r" (keep_dst), [src] "r" (src) 136a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : "ip", "cc", "memory", "d0","d1","d2","d3","d4","d5","d6","d7", 137a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29", 138a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "d30","d31" 139a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com ); 140a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 141fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com else 142a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com { // handle count < 8 143efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com uint16_t* SK_RESTRICT keep_dst = 0; 144fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 145a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com asm volatile ( 146a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmov.u8 d31, #1<<7 \n\t" 147a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "mov %[keep_dst], %[dst] \n\t" 148fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 149a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "tst %[count], #4 \n\t" 150a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "beq 14f \n\t" 151a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.16 {d25}, [%[dst]]! \n\t" 152a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.32 {q1}, [%[src]]! \n\t" 153fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 154a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "14: \n\t" 155a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "tst %[count], #2 \n\t" 156a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "beq 12f \n\t" 157a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.32 {d24[1]}, [%[dst]]! \n\t" 158a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.32 {d1}, [%[src]]! \n\t" 159fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 160a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "12: \n\t" 161a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "tst %[count], #1 \n\t" 162a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "beq 11f \n\t" 163a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.16 {d24[1]}, [%[dst]]! \n\t" 164a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.32 {d0[1]}, [%[src]]! \n\t" 165fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 166a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "11: \n\t" 167a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // unzips achieve the same as a vld4 operation 168a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vuzpq.u16 q0, q1 \n\t" 169a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vuzp.u8 d0, d1 \n\t" 170a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vuzp.u8 d2, d3 \n\t" 171a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // expand 0565 q12 to 8888 {d4-d7} 172a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovn.u16 d4, q12 \n\t" 173a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q11, q12, #5 \n\t" 174a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q10, q12, #6+5 \n\t" 175a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovn.u16 d5, q11 \n\t" 176a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovn.u16 d6, q10 \n\t" 177a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshl.u8 d4, d4, #3 \n\t" 178a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshl.u8 d5, d5, #2 \n\t" 179a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshl.u8 d6, d6, #3 \n\t" 180fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 181a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q14, d31 \n\t" 182a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q13, d31 \n\t" 183a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q12, d31 \n\t" 184fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 185a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // duplicate in 4/2/1 & 8pix vsns 186a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmvn.8 d30, d3 \n\t" 187a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmlal.u8 q14, d30, d6 \n\t" 188a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmlal.u8 q13, d30, d5 \n\t" 189a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmlal.u8 q12, d30, d4 \n\t" 190a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q8, q14, #5 \n\t" 191a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q9, q13, #6 \n\t" 192a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddhn.u16 d6, q14, q8 \n\t" 193a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q8, q12, #5 \n\t" 194a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddhn.u16 d5, q13, q9 \n\t" 195a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vqadd.u8 d6, d6, d0 \n\t" // moved up 196a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddhn.u16 d4, q12, q8 \n\t" 197a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // intentionally don't calculate alpha 198a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // result in d4-d6 199fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 200a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vqadd.u8 d5, d5, d1 \n\t" 201a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vqadd.u8 d4, d4, d2 \n\t" 202fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 203a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // pack 8888 {d4-d6} to 0565 q10 204a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshll.u8 q10, d6, #8 \n\t" 205a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshll.u8 q3, d5, #8 \n\t" 206a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshll.u8 q2, d4, #8 \n\t" 207a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsri.u16 q10, q3, #5 \n\t" 208a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsri.u16 q10, q2, #11 \n\t" 209fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 210a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // store 211a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "tst %[count], #4 \n\t" 212a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "beq 24f \n\t" 213a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vst1.16 {d21}, [%[keep_dst]]! \n\t" 214fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 215a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "24: \n\t" 216a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "tst %[count], #2 \n\t" 217a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "beq 22f \n\t" 218a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vst1.32 {d20[1]}, [%[keep_dst]]! \n\t" 219fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 220a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "22: \n\t" 221a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "tst %[count], #1 \n\t" 222a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "beq 21f \n\t" 223a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vst1.16 {d20[1]}, [%[keep_dst]]! \n\t" 224fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 225a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "21: \n\t" 226a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : [count] "+r" (count) 227a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : [dst] "r" (dst), [keep_dst] "r" (keep_dst), [src] "r" (src) 228a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : "ip", "cc", "memory", "d0","d1","d2","d3","d4","d5","d6","d7", 229a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29", 230a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "d30","d31" 231a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com ); 232a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 233a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 234a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 235a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Blend_neon(uint16_t* SK_RESTRICT dst, 236a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com const SkPMColor* SK_RESTRICT src, int count, 237a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com U8CPU alpha, int /*x*/, int /*y*/) { 238a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 239a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com U8CPU alpha_for_asm = alpha; 240a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 241a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com asm volatile ( 242a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com /* This code implements a Neon version of S32A_D565_Blend. The output differs from 243a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * the original in two respects: 244a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * 1. The results have a few mismatches compared to the original code. These mismatches 245a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * never exceed 1. It's possible to improve accuracy vs. a floating point 246a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * implementation by introducing rounding right shifts (vrshr) for the final stage. 247a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * Rounding is not present in the code below, because although results would be closer 248fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * to a floating point implementation, the number of mismatches compared to the 249a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * original code would be far greater. 250a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * 2. On certain inputs, the original code can overflow, causing colour channels to 251a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * mix. Although the Neon code can also overflow, it doesn't allow one colour channel 252a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * to affect another. 253a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */ 254fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 255a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1 256fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* reflects SkAlpha255To256()'s change from a+a>>7 to a+1 */ 257a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "add %[alpha], %[alpha], #1 \n\t" // adjust range of alpha 0-256 258a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else 259a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "add %[alpha], %[alpha], %[alpha], lsr #7 \n\t" // adjust range of alpha 0-256 260a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 261a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmov.u16 q3, #255 \n\t" // set up constant 262a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "movs r4, %[count], lsr #3 \n\t" // calc. count>>3 263a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmov.u16 d2[0], %[alpha] \n\t" // move alpha to Neon 264a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "beq 2f \n\t" // if count8 == 0, exit 265a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmov.u16 q15, #0x1f \n\t" // set up blue mask 266fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 267a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "1: \n\t" 268a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.u16 {d0, d1}, [%[dst]] \n\t" // load eight dst RGB565 pixels 269a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "subs r4, r4, #1 \n\t" // decrement loop counter 270a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld4.u8 {d24, d25, d26, d27}, [%[src]]! \n\t" // load eight src ABGR32 pixels 271a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // and deinterleave 272fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 273a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshl.u16 q9, q0, #5 \n\t" // shift green to top of lanes 274a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vand q10, q0, q15 \n\t" // extract blue 275a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q8, q0, #11 \n\t" // extract red 276a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q9, q9, #10 \n\t" // extract green 277a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // dstrgb = {q8, q9, q10} 278fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 279a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u8 d24, d24, #3 \n\t" // shift red to 565 range 280a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u8 d25, d25, #2 \n\t" // shift green to 565 range 281a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u8 d26, d26, #3 \n\t" // shift blue to 565 range 282fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 283a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q11, d24 \n\t" // widen red to 16 bits 284a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q12, d25 \n\t" // widen green to 16 bits 285a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q14, d27 \n\t" // widen alpha to 16 bits 286a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovl.u8 q13, d26 \n\t" // widen blue to 16 bits 287a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // srcrgba = {q11, q12, q13, q14} 288fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 289a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmul.u16 q2, q14, d2[0] \n\t" // sa * src_scale 290a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmul.u16 q11, q11, d2[0] \n\t" // red result = src_red * src_scale 291a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmul.u16 q12, q12, d2[0] \n\t" // grn result = src_grn * src_scale 292a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmul.u16 q13, q13, d2[0] \n\t" // blu result = src_blu * src_scale 293fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 294a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q2, q2, #8 \n\t" // sa * src_scale >> 8 295a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsub.u16 q2, q3, q2 \n\t" // 255 - (sa * src_scale >> 8) 296a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // dst_scale = q2 297fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 298a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmla.u16 q11, q8, q2 \n\t" // red result += dst_red * dst_scale 299a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmla.u16 q12, q9, q2 \n\t" // grn result += dst_grn * dst_scale 300a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmla.u16 q13, q10, q2 \n\t" // blu result += dst_blu * dst_scale 301a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 302a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1 303fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // trying for a better match with SkDiv255Round(a) 304fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // C alg is: a+=128; (a+a>>8)>>8 305fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // we'll use just a rounding shift [q2 is available for scratch] 306a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vrshr.u16 q11, q11, #8 \n\t" // shift down red 307a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vrshr.u16 q12, q12, #8 \n\t" // shift down green 308a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vrshr.u16 q13, q13, #8 \n\t" // shift down blue 309a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else 310fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // arm's original "truncating divide by 256" 311a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q11, q11, #8 \n\t" // shift down red 312a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q12, q12, #8 \n\t" // shift down green 313a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q13, q13, #8 \n\t" // shift down blue 314a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 315fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 316a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsli.u16 q13, q12, #5 \n\t" // insert green into blue 317a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsli.u16 q13, q11, #11 \n\t" // insert red into green/blue 318a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vst1.16 {d26, d27}, [%[dst]]! \n\t" // write pixel back to dst, update ptr 319fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 320a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "bne 1b \n\t" // if counter != 0, loop 321a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "2: \n\t" // exit 322fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 323a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count), [alpha] "+r" (alpha_for_asm) 324a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : 325a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : "cc", "memory", "r4", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31" 326a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com ); 327a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 328a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com count &= 7; 329a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count > 0) { 330a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com do { 331a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColor sc = *src++; 332a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (sc) { 333a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com uint16_t dc = *dst; 334a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha); 335a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale); 336a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale); 337a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale); 338a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db)); 339a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 340a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com dst += 1; 341a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } while (--count != 0); 342a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 343a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 344a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 345a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/* dither matrix for Neon, derived from gDitherMatrix_3Bit_16. 346a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * each dither value is spaced out into byte lanes, and repeated 347a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * to allow an 8-byte load from offsets 0, 1, 2 or 3 from the 348a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * start of each row. 349a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */ 350a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic const uint8_t gDitherMatrix_Neon[48] = { 351a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 0, 4, 1, 5, 0, 4, 1, 5, 0, 4, 1, 5, 352a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 6, 2, 7, 3, 6, 2, 7, 3, 6, 2, 7, 3, 353a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1, 5, 0, 4, 1, 5, 0, 4, 1, 5, 0, 4, 354a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 7, 3, 6, 2, 7, 3, 6, 2, 7, 3, 6, 2, 355fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 356a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}; 357a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 358a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_D565_Blend_Dither_neon(uint16_t *dst, const SkPMColor *src, 359a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int count, U8CPU alpha, int x, int y) 360a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{ 361a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com /* select row and offset for dither array */ 362a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)]; 363fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 364a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com /* rescale alpha to range 0 - 256 */ 365a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int scale = SkAlpha255To256(alpha); 366fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 367a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com asm volatile ( 368a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.8 {d31}, [%[dstart]] \n\t" // load dither values 369a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u8 d30, d31, #1 \n\t" // calc. green dither values 370a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vdup.16 d6, %[scale] \n\t" // duplicate scale into neon reg 371a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmov.i8 d29, #0x3f \n\t" // set up green mask 372a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmov.i8 d28, #0x1f \n\t" // set up blue mask 373a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "1: \n\t" 374a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld4.8 {d0, d1, d2, d3}, [%[src]]! \n\t" // load 8 pixels and split into argb 375a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u8 d22, d0, #5 \n\t" // calc. red >> 5 376a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u8 d23, d1, #6 \n\t" // calc. green >> 6 377a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u8 d24, d2, #5 \n\t" // calc. blue >> 5 378a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddl.u8 q8, d0, d31 \n\t" // add in dither to red and widen 379a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddl.u8 q9, d1, d30 \n\t" // add in dither to green and widen 380a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddl.u8 q10, d2, d31 \n\t" // add in dither to blue and widen 381a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsubw.u8 q8, q8, d22 \n\t" // sub shifted red from result 382a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsubw.u8 q9, q9, d23 \n\t" // sub shifted green from result 383a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsubw.u8 q10, q10, d24 \n\t" // sub shifted blue from result 384a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d22, q8, #3 \n\t" // shift right and narrow to 5 bits 385a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d23, q9, #2 \n\t" // shift right and narrow to 6 bits 386a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d24, q10, #3 \n\t" // shift right and narrow to 5 bits 387a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // load 8 pixels from dst, extract rgb 388a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.16 {d0, d1}, [%[dst]] \n\t" // load 8 pixels 389a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d17, q0, #5 \n\t" // shift green down to bottom 6 bits 390a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovn.i16 d18, q0 \n\t" // narrow to get blue as bytes 391a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshr.u16 q0, q0, #11 \n\t" // shift down to extract red 392a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vand d17, d17, d29 \n\t" // and green with green mask 393a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vand d18, d18, d28 \n\t" // and blue with blue mask 394a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmovn.i16 d16, q0 \n\t" // narrow to get red as bytes 395a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // src = {d22 (r), d23 (g), d24 (b)} 396a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // dst = {d16 (r), d17 (g), d18 (b)} 397a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // subtract dst from src and widen 398a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsubl.s8 q0, d22, d16 \n\t" // subtract red src from dst 399a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsubl.s8 q1, d23, d17 \n\t" // subtract green src from dst 400a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsubl.s8 q2, d24, d18 \n\t" // subtract blue src from dst 401a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // multiply diffs by scale and shift 402a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmul.i16 q0, q0, d6[0] \n\t" // multiply red by scale 403a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmul.i16 q1, q1, d6[0] \n\t" // multiply blue by scale 404a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmul.i16 q2, q2, d6[0] \n\t" // multiply green by scale 405a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "subs %[count], %[count], #8 \n\t" // decrement loop counter 406a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d0, q0, #8 \n\t" // shift down red by 8 and narrow 407a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d2, q1, #8 \n\t" // shift down green by 8 and narrow 408a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d4, q2, #8 \n\t" // shift down blue by 8 and narrow 409a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // add dst to result 410a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddl.s8 q0, d0, d16 \n\t" // add dst to red 411a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddl.s8 q1, d2, d17 \n\t" // add dst to green 412a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vaddl.s8 q2, d4, d18 \n\t" // add dst to blue 413a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // put result into 565 format 414a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsli.i16 q2, q1, #5 \n\t" // shift up green and insert into blue 415a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vsli.i16 q2, q0, #11 \n\t" // shift up red and insert into blue 416a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vst1.16 {d4, d5}, [%[dst]]! \n\t" // store result 417a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "bgt 1b \n\t" // loop if count > 0 418a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count) 419a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : [dstart] "r" (dstart), [scale] "r" (scale) 420a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d28", "d29", "d30", "d31" 421a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com ); 422fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 423a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com DITHER_565_SCAN(y); 424fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 425a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com while((count & 7) > 0) 426a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com { 427a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColor c = *src++; 428fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 429a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int dither = DITHER_VALUE(x); 430a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int sr = SkGetPackedR32(c); 431a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int sg = SkGetPackedG32(c); 432a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int sb = SkGetPackedB32(c); 433a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sr = SkDITHER_R32To565(sr, dither); 434a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sg = SkDITHER_G32To565(sg, dither); 435a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sb = SkDITHER_B32To565(sb, dither); 436fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 437a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com uint16_t d = *dst; 438a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale), 439a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkAlphaBlend(sg, SkGetPackedG16(d), scale), 440a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkAlphaBlend(sb, SkGetPackedB16(d), scale)); 441a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com DITHER_INC_X(x); 442a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com count--; 443a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 444a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 445a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 446a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_Opaque_BlitRow32_neon(SkPMColor* SK_RESTRICT dst, 447a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com const SkPMColor* SK_RESTRICT src, 448a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int count, U8CPU alpha) { 449a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 450a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkASSERT(255 == alpha); 451a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count > 0) { 452a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 453a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 454fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t alpha_mask; 455a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 456fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7}; 457fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com alpha_mask = vld1_u8(alpha_mask_setup); 458a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 459fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* do the NEON unrolled code */ 460fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define UNROLL 4 461fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com while (count >= UNROLL) { 462fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t src_raw, dst_raw, dst_final; 463fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t src_raw_2, dst_raw_2, dst_final_2; 464a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 4650a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org /* The two prefetches below may make the code slighlty 4660a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org * slower for small values of count but are worth having 4670a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org * in the general case. 4680a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org */ 4690a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org __builtin_prefetch(src+32); 4700a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org __builtin_prefetch(dst+32); 4710a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org 472fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* get the source */ 473fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com src_raw = vreinterpret_u8_u32(vld1_u32(src)); 474fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if UNROLL > 2 475fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com src_raw_2 = vreinterpret_u8_u32(vld1_u32(src+2)); 476a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 477a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 478fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* get and hold the dst too */ 479fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_raw = vreinterpret_u8_u32(vld1_u32(dst)); 480fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if UNROLL > 2 481fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_raw_2 = vreinterpret_u8_u32(vld1_u32(dst+2)); 482a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 483a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 484fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* 1st and 2nd bits of the unrolling */ 485fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { 486fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t dst_cooked; 487fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16x8_t dst_wide; 488fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t alpha_narrow; 489fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16x8_t alpha_wide; 490a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 491fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* get the alphas spread out properly */ 492fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com alpha_narrow = vtbl1_u8(src_raw, alpha_mask); 493fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow); 494a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 495fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* spread the dest */ 496fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_wide = vmovl_u8(dst_raw); 497a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 498fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* alpha mul the dest */ 499fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_wide = vmulq_u16 (dst_wide, alpha_wide); 500fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_cooked = vshrn_n_u16(dst_wide, 8); 501a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 502fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* sum -- ignoring any byte lane overflows */ 503fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_final = vadd_u8(src_raw, dst_cooked); 504fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 505a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 506fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if UNROLL > 2 507fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* the 3rd and 4th bits of our unrolling */ 508fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { 509fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t dst_cooked; 510fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16x8_t dst_wide; 511fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t alpha_narrow; 512fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16x8_t alpha_wide; 513a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 514fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com alpha_narrow = vtbl1_u8(src_raw_2, alpha_mask); 515fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow); 516a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 517fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* spread the dest */ 518fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_wide = vmovl_u8(dst_raw_2); 519a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 520fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* alpha mul the dest */ 521fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_wide = vmulq_u16 (dst_wide, alpha_wide); 522fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_cooked = vshrn_n_u16(dst_wide, 8); 523a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 524fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* sum -- ignoring any byte lane overflows */ 525fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_final_2 = vadd_u8(src_raw_2, dst_cooked); 526fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 527a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 528a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 529fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com vst1_u32(dst, vreinterpret_u32_u8(dst_final)); 530fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if UNROLL > 2 531fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com vst1_u32(dst+2, vreinterpret_u32_u8(dst_final_2)); 532a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 533a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 534fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com src += UNROLL; 535fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst += UNROLL; 536fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com count -= UNROLL; 537fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 538fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef UNROLL 539a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 540fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* do any residual iterations */ 541a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com while (--count >= 0) { 542a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *dst = SkPMSrcOver(*src, *dst); 543a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com src += 1; 544a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com dst += 1; 545a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 546a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 547a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 548a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 549c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comvoid S32A_Opaque_BlitRow32_neon_src_alpha(SkPMColor* SK_RESTRICT dst, 550c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com const SkPMColor* SK_RESTRICT src, 551c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com int count, U8CPU alpha) { 552c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com SkASSERT(255 == alpha); 553c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 554c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if (count <= 0) 555c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com return; 556c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 557c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* Use these to check if src is transparent or opaque */ 558c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com const unsigned int ALPHA_OPAQ = 0xFF000000; 559c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com const unsigned int ALPHA_TRANS = 0x00FFFFFF; 560c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 561c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#define UNROLL 4 562c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com const SkPMColor* SK_RESTRICT src_end = src + count - (UNROLL + 1); 563c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com const SkPMColor* SK_RESTRICT src_temp = src; 564c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 565c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* set up the NEON variables */ 566c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com uint8x8_t alpha_mask; 567c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7}; 568c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com alpha_mask = vld1_u8(alpha_mask_setup); 569c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 570c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com uint8x8_t src_raw, dst_raw, dst_final; 571c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com uint8x8_t src_raw_2, dst_raw_2, dst_final_2; 572c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com uint8x8_t dst_cooked; 573c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com uint16x8_t dst_wide; 574c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com uint8x8_t alpha_narrow; 575c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com uint16x8_t alpha_wide; 576c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 577c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* choose the first processing type */ 578c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if( src >= src_end) 579c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto TAIL; 580c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*src <= ALPHA_TRANS) 581c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto ALPHA_0; 582c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*src >= ALPHA_OPAQ) 583c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto ALPHA_255; 584c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* fall-thru */ 585c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 586c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_1_TO_254: 587c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com do { 588c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 589c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* get the source */ 590c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com src_raw = vreinterpret_u8_u32(vld1_u32(src)); 591c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com src_raw_2 = vreinterpret_u8_u32(vld1_u32(src+2)); 592c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 593c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* get and hold the dst too */ 594c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_raw = vreinterpret_u8_u32(vld1_u32(dst)); 595c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_raw_2 = vreinterpret_u8_u32(vld1_u32(dst+2)); 596c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 597c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 598c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* get the alphas spread out properly */ 599c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com alpha_narrow = vtbl1_u8(src_raw, alpha_mask); 600c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* reflect SkAlpha255To256() semantics a+1 vs a+a>>7 */ 601c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* we collapsed (255-a)+1 ... */ 602c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow); 603c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 604c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* spread the dest */ 605c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_wide = vmovl_u8(dst_raw); 606c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 607c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* alpha mul the dest */ 608c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_wide = vmulq_u16 (dst_wide, alpha_wide); 609c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_cooked = vshrn_n_u16(dst_wide, 8); 610c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 611c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* sum -- ignoring any byte lane overflows */ 612c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_final = vadd_u8(src_raw, dst_cooked); 613c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 614c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com alpha_narrow = vtbl1_u8(src_raw_2, alpha_mask); 615c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* reflect SkAlpha255To256() semantics a+1 vs a+a>>7 */ 616c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* we collapsed (255-a)+1 ... */ 617c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow); 618c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 619c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* spread the dest */ 620c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_wide = vmovl_u8(dst_raw_2); 621c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 622c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* alpha mul the dest */ 623c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_wide = vmulq_u16 (dst_wide, alpha_wide); 624c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_cooked = vshrn_n_u16(dst_wide, 8); 625c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 626c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* sum -- ignoring any byte lane overflows */ 627c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst_final_2 = vadd_u8(src_raw_2, dst_cooked); 628c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 629c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com vst1_u32(dst, vreinterpret_u32_u8(dst_final)); 630c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com vst1_u32(dst+2, vreinterpret_u32_u8(dst_final_2)); 631c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 632c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com src += UNROLL; 633c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst += UNROLL; 634c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 635c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* if 2 of the next pixels aren't between 1 and 254 636c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com it might make sense to go to the optimized loops */ 637c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if((src[0] <= ALPHA_TRANS && src[1] <= ALPHA_TRANS) || (src[0] >= ALPHA_OPAQ && src[1] >= ALPHA_OPAQ)) 638c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com break; 639c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 640c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } while(src < src_end); 641c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 642c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if (src >= src_end) 643c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto TAIL; 644c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 645c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(src[0] >= ALPHA_OPAQ && src[1] >= ALPHA_OPAQ) 646c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto ALPHA_255; 647c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 648c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /*fall-thru*/ 649c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 650c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_0: 651c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 652c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /*In this state, we know the current alpha is 0 and 653c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com we optimize for the next alpha also being zero. */ 654c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com src_temp = src; //so we don't have to increment dst every time 655c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com do { 656c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*(++src) > ALPHA_TRANS) 657c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com break; 658c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*(++src) > ALPHA_TRANS) 659c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com break; 660c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*(++src) > ALPHA_TRANS) 661c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com break; 662c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*(++src) > ALPHA_TRANS) 663c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com break; 664c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } while(src < src_end); 665c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 666c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst += (src - src_temp); 667c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 668c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* no longer alpha 0, so determine where to go next. */ 669c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if( src >= src_end) 670c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto TAIL; 671c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*src >= ALPHA_OPAQ) 672c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto ALPHA_255; 673c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com else 674c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto ALPHA_1_TO_254; 675c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 676c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_255: 677c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com while((src[0] & src[1] & src[2] & src[3]) >= ALPHA_OPAQ) { 678c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst[0]=src[0]; 679c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst[1]=src[1]; 680c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst[2]=src[2]; 681c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst[3]=src[3]; 682c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com src+=UNROLL; 683c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst+=UNROLL; 684c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(src >= src_end) 685c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto TAIL; 686c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } 687c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 688c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com //Handle remainder. 689c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*src >= ALPHA_OPAQ) { *dst++ = *src++; 690c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*src >= ALPHA_OPAQ) { *dst++ = *src++; 691c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*src >= ALPHA_OPAQ) { *dst++ = *src++; } 692c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } 693c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } 694c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 695c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if( src >= src_end) 696c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto TAIL; 697c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if(*src <= ALPHA_TRANS) 698c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto ALPHA_0; 699c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com else 700c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com goto ALPHA_1_TO_254; 701c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 702c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comTAIL: 703c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* do any residual iterations */ 704c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com src_end += UNROLL + 1; //goto the real end 705c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com while(src != src_end) { 706c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if( *src != 0 ) { 707c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com if( *src >= ALPHA_OPAQ ) { 708c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com *dst = *src; 709c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } 710c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com else { 711c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com *dst = SkPMSrcOver(*src, *dst); 712c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } 713c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } 714c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com src++; 715c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com dst++; 716c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com } 717c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com 718c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#undef UNROLL 719c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com return; 720c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com} 721a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 722a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/* Neon version of S32_Blend_BlitRow32() 723a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * portable version is in src/core/SkBlitRow_D32.cpp 724a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */ 725a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_Blend_BlitRow32_neon(SkPMColor* SK_RESTRICT dst, 726a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com const SkPMColor* SK_RESTRICT src, 727a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int count, U8CPU alpha) { 728a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkASSERT(alpha <= 255); 729a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count > 0) { 730a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com uint16_t src_scale = SkAlpha255To256(alpha); 731a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com uint16_t dst_scale = 256 - src_scale; 732a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 733fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* run them N at a time through the NEON unit */ 734fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* note that each 1 is 4 bytes, each treated exactly the same, 735fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * so we can work under that guise. We *do* know that the src&dst 736fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * will be 32-bit aligned quantities, so we can specify that on 737fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * the load/store ops and do a neon 'reinterpret' to get us to 738fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * byte-sized (pun intended) pieces that we widen/multiply/shift 739fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * we're limited at 128 bits in the wide ops, which is 8x16bits 740fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * or a pair of 32 bit src/dsts. 741fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com */ 742fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* we *could* manually unroll this loop so that we load 128 bits 743fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * (as a pair of 64s) from each of src and dst, processing them 744fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * in pieces. This might give us a little better management of 745fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * the memory latency, but my initial attempts here did not 746fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * produce an instruction stream that looked all that nice. 747fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com */ 748fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define UNROLL 2 749fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com while (count >= UNROLL) { 750fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t src_raw, dst_raw, dst_final; 751fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16x8_t src_wide, dst_wide; 752fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 753fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* get 64 bits of src, widen it, multiply by src_scale */ 754fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com src_raw = vreinterpret_u8_u32(vld1_u32(src)); 755fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com src_wide = vmovl_u8(src_raw); 756fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* gcc hoists vdupq_n_u16(), better than using vmulq_n_u16() */ 757fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com src_wide = vmulq_u16 (src_wide, vdupq_n_u16(src_scale)); 758fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 759fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* ditto with dst */ 760fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_raw = vreinterpret_u8_u32(vld1_u32(dst)); 761fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_wide = vmovl_u8(dst_raw); 762fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 763fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* combine add with dst multiply into mul-accumulate */ 764fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_wide = vmlaq_u16(src_wide, dst_wide, vdupq_n_u16(dst_scale)); 765fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 766fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_final = vshrn_n_u16(dst_wide, 8); 767fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com vst1_u32(dst, vreinterpret_u32_u8(dst_final)); 768fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 769fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com src += UNROLL; 770fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst += UNROLL; 771fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com count -= UNROLL; 772fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 773fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* RBE: well, i don't like how gcc manages src/dst across the above 774fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * loop it's constantly calculating src+bias, dst+bias and it only 775fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * adjusts the real ones when we leave the loop. Not sure why 776fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * it's "hoisting down" (hoisting implies above in my lexicon ;)) 777fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * the adjustments to src/dst/count, but it does... 778fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * (might be SSA-style internal logic... 779fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com */ 780fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 781fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if UNROLL == 2 782fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (count == 1) { 783a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale); 784fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 785a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else 786fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (count > 0) { 787a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com do { 788a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale); 789a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com src += 1; 790a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com dst += 1; 791a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } while (--count > 0); 792fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 793a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 794a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 795fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef UNROLL 796a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 797a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 798a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 7991fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.orgvoid S32A_Blend_BlitRow32_neon(SkPMColor* SK_RESTRICT dst, 8001fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org const SkPMColor* SK_RESTRICT src, 8011fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org int count, U8CPU alpha) { 8021fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8031fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org SkASSERT(255 >= alpha); 8041fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8051fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org if (count <= 0) { 8061fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org return; 8071fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org } 8081fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8091fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org unsigned alpha256 = SkAlpha255To256(alpha); 8101fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8111fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // First deal with odd counts 8121fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org if (count & 1) { 8131fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org uint8x8_t vsrc = vdup_n_u8(0), vdst = vdup_n_u8(0), vres; 8141fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org uint16x8_t vdst_wide, vsrc_wide; 8151fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org unsigned dst_scale; 8161fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8171fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Load 8181fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vsrc = vreinterpret_u8_u32(vld1_lane_u32(src, vreinterpret_u32_u8(vsrc), 0)); 8191fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst = vreinterpret_u8_u32(vld1_lane_u32(dst, vreinterpret_u32_u8(vdst), 0)); 8201fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8211fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Calc dst_scale 8221fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org dst_scale = vget_lane_u8(vsrc, 3); 8231fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org dst_scale *= alpha256; 8241fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org dst_scale >>= 8; 8251fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org dst_scale = 256 - dst_scale; 8261fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8271fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Process src 8281fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vsrc_wide = vmovl_u8(vsrc); 8291fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vsrc_wide = vmulq_n_u16(vsrc_wide, alpha256); 8301fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8311fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Process dst 8321fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst_wide = vmovl_u8(vdst); 8331fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst_wide = vmulq_n_u16(vdst_wide, dst_scale); 8341fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8351fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Combine 8361fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8); 8371fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8381fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vst1_lane_u32(dst, vreinterpret_u32_u8(vres), 0); 8391fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org dst++; 8401fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org src++; 8411fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org count--; 8421fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org } 8431fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8441fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org if (count) { 8451fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org uint8x8_t alpha_mask; 8461fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7}; 8471fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org alpha_mask = vld1_u8(alpha_mask_setup); 8481fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8491fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org do { 8501fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8511fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org uint8x8_t vsrc, vdst, vres, vsrc_alphas; 8521fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org uint16x8_t vdst_wide, vsrc_wide, vsrc_scale, vdst_scale; 8531fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8541fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org __builtin_prefetch(src+32); 8551fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org __builtin_prefetch(dst+32); 8561fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8571fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Load 8581fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vsrc = vreinterpret_u8_u32(vld1_u32(src)); 8591fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst = vreinterpret_u8_u32(vld1_u32(dst)); 8601fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8611fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Prepare src_scale 8621fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vsrc_scale = vdupq_n_u16(alpha256); 8631fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8641fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Calc dst_scale 8651fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vsrc_alphas = vtbl1_u8(vsrc, alpha_mask); 8661fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst_scale = vmovl_u8(vsrc_alphas); 8671fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst_scale *= vsrc_scale; 8681fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst_scale = vshrq_n_u16(vdst_scale, 8); 8691fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst_scale = vsubq_u16(vdupq_n_u16(256), vdst_scale); 8701fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8711fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Process src 8721fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vsrc_wide = vmovl_u8(vsrc); 8731fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vsrc_wide *= vsrc_scale; 8741fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8751fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Process dst 8761fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst_wide = vmovl_u8(vdst); 8771fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vdst_wide *= vdst_scale; 8781fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8791fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org // Combine 8801fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8); 8811fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8821fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org vst1_u32(dst, vreinterpret_u32_u8(vres)); 8831fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 8841fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org src += 2; 8851fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org dst += 2; 8861fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org count -= 2; 8871fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org } while(count); 8881fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org } 8891fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org} 8901fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org 891a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/////////////////////////////////////////////////////////////////////////////// 892a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 893fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef DEBUG_OPAQUE_DITHER 894a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 895fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if defined(DEBUG_OPAQUE_DITHER) 896a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic void showme8(char *str, void *p, int len) 897a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{ 898fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static char buf[256]; 899fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com char tbuf[32]; 900fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int i; 901fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com char *pc = (char*) p; 902fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sprintf(buf,"%8s:", str); 903fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com for(i=0;i<len;i++) { 904fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sprintf(tbuf, " %02x", pc[i]); 905fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com strcat(buf, tbuf); 906fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 907fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkDebugf("%s\n", buf); 908a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 909a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic void showme16(char *str, void *p, int len) 910a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{ 911fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static char buf[256]; 912fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com char tbuf[32]; 913fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int i; 914fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16_t *pc = (uint16_t*) p; 915fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sprintf(buf,"%8s:", str); 916fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com len = (len / sizeof(uint16_t)); /* passed as bytes */ 917fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com for(i=0;i<len;i++) { 918fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sprintf(tbuf, " %04x", pc[i]); 919fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com strcat(buf, tbuf); 920fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 921fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkDebugf("%s\n", buf); 922a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 923a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 924a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 925a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Opaque_Dither_neon (uint16_t * SK_RESTRICT dst, 926a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com const SkPMColor* SK_RESTRICT src, 927a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int count, U8CPU alpha, int x, int y) { 928a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkASSERT(255 == alpha); 929a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 930fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define UNROLL 8 931a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 932a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count >= UNROLL) { 933fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t dbase; 934fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 935fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if defined(DEBUG_OPAQUE_DITHER) 936fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16_t tmpbuf[UNROLL]; 937fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int td[UNROLL]; 938fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int tdv[UNROLL]; 939fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int ta[UNROLL]; 940fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int tap[UNROLL]; 941fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16_t in_dst[UNROLL]; 942fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int offset = 0; 943fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int noisy = 0; 944a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 945a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 946fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)]; 947fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dbase = vld1_u8(dstart); 948a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 949a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com do { 950fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t sr, sg, sb, sa, d; 951fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16x8_t dst8, scale8, alpha8; 952fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16x8_t dst_r, dst_g, dst_b; 953fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 954fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if defined(DEBUG_OPAQUE_DITHER) 955fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* calculate 8 elements worth into a temp buffer */ 956fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { 957fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int my_y = y; 958fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int my_x = x; 959fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkPMColor* my_src = (SkPMColor*)src; 960fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16_t* my_dst = dst; 961fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int i; 962a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 963a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com DITHER_565_SCAN(my_y); 964a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com for(i=0;i<UNROLL;i++) { 965a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColor c = *my_src++; 966a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColorAssert(c); 967a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (c) { 968a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned a = SkGetPackedA32(c); 969fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 970a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int d = SkAlphaMul(DITHER_VALUE(my_x), SkAlpha255To256(a)); 971fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com tdv[i] = DITHER_VALUE(my_x); 972fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com ta[i] = a; 973fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com tap[i] = SkAlpha255To256(a); 974fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com td[i] = d; 975fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 976a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned sr = SkGetPackedR32(c); 977a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned sg = SkGetPackedG32(c); 978a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned sb = SkGetPackedB32(c); 979a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sr = SkDITHER_R32_FOR_565(sr, d); 980a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sg = SkDITHER_G32_FOR_565(sg, d); 981a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sb = SkDITHER_B32_FOR_565(sb, d); 982fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 983a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2); 984a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com uint32_t dst_expanded = SkExpand_rgb_16(*my_dst); 985a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3); 986a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // now src and dst expanded are in g:11 r:10 x:1 b:10 987a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com tmpbuf[i] = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5); 988fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com td[i] = d; 989a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 990a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } else { 991fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com tmpbuf[i] = *my_dst; 992fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com ta[i] = tdv[i] = td[i] = 0xbeef; 993fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 994fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com in_dst[i] = *my_dst; 995a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com my_dst += 1; 996a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com DITHER_INC_X(my_x); 997a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 998fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 999a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 1000a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1001fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* source is in ABGR */ 1002fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { 1003fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com register uint8x8_t d0 asm("d0"); 1004fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com register uint8x8_t d1 asm("d1"); 1005fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com register uint8x8_t d2 asm("d2"); 1006fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com register uint8x8_t d3 asm("d3"); 1007a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1008fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com asm ("vld4.8 {d0-d3},[%4] /* r=%P0 g=%P1 b=%P2 a=%P3 */" 1009fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3) 1010fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com : "r" (src) 1011a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com ); 1012fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sr = d0; sg = d1; sb = d2; sa = d3; 1013fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1014a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1015fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* calculate 'd', which will be 0..7 */ 1016fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* dbase[] is 0..7; alpha is 0..256; 16 bits suffice */ 1017a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if defined(SK_BUILD_FOR_ANDROID) 1018fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* SkAlpha255To256() semantic a+1 vs a+a>>7 */ 1019fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com alpha8 = vaddw_u8(vmovl_u8(sa), vdup_n_u8(1)); 1020a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else 1021fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com alpha8 = vaddw_u8(vmovl_u8(sa), vshr_n_u8(sa, 7)); 1022a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 1023fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com alpha8 = vmulq_u16(alpha8, vmovl_u8(dbase)); 1024fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com d = vshrn_n_u16(alpha8, 8); /* narrowing too */ 1025fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1026fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* sr = sr - (sr>>5) + d */ 1027fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* watching for 8-bit overflow. d is 0..7; risky range of 1028fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * sr is >248; and then (sr>>5) is 7 so it offsets 'd'; 1029fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * safe as long as we do ((sr-sr>>5) + d) */ 1030fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sr = vsub_u8(sr, vshr_n_u8(sr, 5)); 1031fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sr = vadd_u8(sr, d); 1032fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1033fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* sb = sb - (sb>>5) + d */ 1034fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sb = vsub_u8(sb, vshr_n_u8(sb, 5)); 1035fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sb = vadd_u8(sb, d); 1036fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1037fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* sg = sg - (sg>>6) + d>>1; similar logic for overflows */ 1038fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sg = vsub_u8(sg, vshr_n_u8(sg, 6)); 1039fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sg = vadd_u8(sg, vshr_n_u8(d,1)); 1040fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1041fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* need to pick up 8 dst's -- at 16 bits each, 128 bits */ 1042fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst8 = vld1q_u16(dst); 1043fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_b = vandq_u16(dst8, vdupq_n_u16(0x001F)); 1044fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_g = vandq_u16(vshrq_n_u16(dst8,5), vdupq_n_u16(0x003F)); 1045fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_r = vshrq_n_u16(dst8,11); /* clearing hi bits */ 1046fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1047fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* blend */ 1048a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1 1049fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* SkAlpha255To256() semantic a+1 vs a+a>>7 */ 1050fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* originally 255-sa + 1 */ 1051fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com scale8 = vsubw_u8(vdupq_n_u16(256), sa); 1052a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else 1053fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com scale8 = vsubw_u8(vdupq_n_u16(255), sa); 1054fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com scale8 = vaddq_u16(scale8, vshrq_n_u16(scale8, 7)); 1055a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 1056a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1057a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1 1058fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* combine the addq and mul, save 3 insns */ 1059fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com scale8 = vshrq_n_u16(scale8, 3); 1060fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_b = vmlaq_u16(vshll_n_u8(sb,2), dst_b, scale8); 1061fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_g = vmlaq_u16(vshll_n_u8(sg,3), dst_g, scale8); 1062fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_r = vmlaq_u16(vshll_n_u8(sr,2), dst_r, scale8); 1063a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else 1064fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* known correct, but +3 insns over above */ 1065fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com scale8 = vshrq_n_u16(scale8, 3); 1066fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_b = vmulq_u16(dst_b, scale8); 1067fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_g = vmulq_u16(dst_g, scale8); 1068fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_r = vmulq_u16(dst_r, scale8); 1069fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1070fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* combine */ 1071fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* NB: vshll widens, need to preserve those bits */ 1072fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_b = vaddq_u16(dst_b, vshll_n_u8(sb,2)); 1073fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_g = vaddq_u16(dst_g, vshll_n_u8(sg,3)); 1074fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst_r = vaddq_u16(dst_r, vshll_n_u8(sr,2)); 1075a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 1076a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1077fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* repack to store */ 1078fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst8 = vandq_u16(vshrq_n_u16(dst_b, 5), vdupq_n_u16(0x001F)); 1079fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dst_g, 5), 5); 1080fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dst_r,5), 11); 1081fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1082fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com vst1q_u16(dst, dst8); 1083fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1084fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if defined(DEBUG_OPAQUE_DITHER) 1085fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* verify my 8 elements match the temp buffer */ 1086fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { 1087fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int i, bad=0; 1088fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com static int invocation; 1089fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1090fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com for (i=0;i<UNROLL;i++) 1091fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (tmpbuf[i] != dst[i]) bad=1; 1092fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (bad) { 1093fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkDebugf("BAD S32A_D565_Opaque_Dither_neon(); invocation %d offset %d\n", 1094fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com invocation, offset); 1095fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkDebugf(" alpha 0x%x\n", alpha); 1096fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com for (i=0;i<UNROLL;i++) 1097fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkDebugf("%2d: %s %04x w %04x id %04x s %08x d %04x %04x %04x %04x\n", 1098fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com i, ((tmpbuf[i] != dst[i])?"BAD":"got"), 1099fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst[i], tmpbuf[i], in_dst[i], src[i], td[i], tdv[i], tap[i], ta[i]); 1100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1101fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme16("alpha8", &alpha8, sizeof(alpha8)); 1102fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme16("scale8", &scale8, sizeof(scale8)); 1103fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme8("d", &d, sizeof(d)); 1104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme16("dst8", &dst8, sizeof(dst8)); 1105fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme16("dst_b", &dst_b, sizeof(dst_b)); 1106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme16("dst_g", &dst_g, sizeof(dst_g)); 1107fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme16("dst_r", &dst_r, sizeof(dst_r)); 1108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme8("sb", &sb, sizeof(sb)); 1109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme8("sg", &sg, sizeof(sg)); 1110fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com showme8("sr", &sr, sizeof(sr)); 1111fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* cop out */ 1113fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return; 1114fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1115fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com offset += UNROLL; 1116fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com invocation++; 1117fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1118a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 1119a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1120a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com dst += UNROLL; 1121fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com src += UNROLL; 1122fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com count -= UNROLL; 1123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* skip x += UNROLL, since it's unchanged mod-4 */ 1124a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } while (count >= UNROLL); 1125a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1126fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef UNROLL 1127a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1128a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com /* residuals */ 1129a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count > 0) { 1130a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com DITHER_565_SCAN(y); 1131a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com do { 1132a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColor c = *src++; 1133a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColorAssert(c); 1134a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (c) { 1135a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned a = SkGetPackedA32(c); 1136fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1137a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // dither and alpha are just temporary variables to work-around 1138a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // an ICE in debug. 1139a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned dither = DITHER_VALUE(x); 1140a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned alpha = SkAlpha255To256(a); 1141a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int d = SkAlphaMul(dither, alpha); 1142fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1143a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned sr = SkGetPackedR32(c); 1144a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned sg = SkGetPackedG32(c); 1145a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned sb = SkGetPackedB32(c); 1146a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sr = SkDITHER_R32_FOR_565(sr, d); 1147a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sg = SkDITHER_G32_FOR_565(sg, d); 1148a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sb = SkDITHER_B32_FOR_565(sb, d); 1149fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1150a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2); 1151a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com uint32_t dst_expanded = SkExpand_rgb_16(*dst); 1152a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3); 1153a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // now src and dst expanded are in g:11 r:10 x:1 b:10 1154a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5); 1155a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1156a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com dst += 1; 1157a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com DITHER_INC_X(x); 1158a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } while (--count != 0); 1159a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1160a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 1161a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1162a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/////////////////////////////////////////////////////////////////////////////// 1163a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1164fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef DEBUG_S32_OPAQUE_DITHER 1165a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1166a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_D565_Opaque_Dither_neon(uint16_t* SK_RESTRICT dst, 1167a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com const SkPMColor* SK_RESTRICT src, 1168a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com int count, U8CPU alpha, int x, int y) { 1169a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkASSERT(255 == alpha); 1170a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1171fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define UNROLL 8 1172a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count >= UNROLL) { 1173fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint8x8_t d; 1174fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)]; 1175fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com d = vld1_u8(dstart); 1176fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1177fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com while (count >= UNROLL) { 1178efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com uint8x8_t sr, sg, sb; 1179efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com uint16x8_t dr, dg, db; 1180fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16x8_t dst8; 1181fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1182fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { 1183fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com register uint8x8_t d0 asm("d0"); 1184fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com register uint8x8_t d1 asm("d1"); 1185fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com register uint8x8_t d2 asm("d2"); 1186fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com register uint8x8_t d3 asm("d3"); 1187fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1188688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org asm ( 1189688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org "vld4.8 {d0-d3},[%[src]]! /* r=%P0 g=%P1 b=%P2 a=%P3 */" 1190688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3), [src] "+&r" (src) 1191688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org : 1192688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org ); 1193688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org sg = d1; 1194688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) 1195688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org sr = d2; sb = d0; 1196688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) 1197688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org sr = d0; sb = d2; 1198688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#endif 1199fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1200fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* XXX: if we want to prefetch, hide it in the above asm() 1201fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * using the gcc __builtin_prefetch(), the prefetch will 1202fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * fall to the bottom of the loop -- it won't stick up 1203fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * at the top of the loop, just after the vld4. 1204fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com */ 1205fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1206688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // sr = sr - (sr>>5) + d 1207fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sr = vsub_u8(sr, vshr_n_u8(sr, 5)); 1208fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dr = vaddl_u8(sr, d); 1209fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1210688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // sb = sb - (sb>>5) + d 1211fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sb = vsub_u8(sb, vshr_n_u8(sb, 5)); 1212fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com db = vaddl_u8(sb, d); 1213fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1214688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // sg = sg - (sg>>6) + d>>1; similar logic for overflows 1215fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com sg = vsub_u8(sg, vshr_n_u8(sg, 6)); 1216688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org dg = vaddl_u8(sg, vshr_n_u8(d, 1)); 1217fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1218688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // pack high bits of each into 565 format (rgb, b is lsb) 1219fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst8 = vshrq_n_u16(db, 3); 1220fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dg, 2), 5); 1221688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dr, 3), 11); 1222fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1223688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // store it 1224fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com vst1q_u16(dst, dst8); 1225fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1226fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if defined(DEBUG_S32_OPAQUE_DITHER) 1227688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // always good to know if we generated good results 1228fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { 1229fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int i, myx = x, myy = y; 1230fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com DITHER_565_SCAN(myy); 1231fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com for (i=0;i<UNROLL;i++) { 1232688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // the '!' in the asm block above post-incremented src by the 8 pixels it reads. 1233688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org SkPMColor c = src[i-8]; 1234fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com unsigned dither = DITHER_VALUE(myx); 1235fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com uint16_t val = SkDitherRGB32To565(c, dither); 1236fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (val != dst[i]) { 1237fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkDebugf("RBE: src %08x dither %02x, want %04x got %04x dbas[i] %02x\n", 1238fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com c, dither, val, dst[i], dstart[i]); 1239fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1240fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com DITHER_INC_X(myx); 1241fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1242fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1243a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif 1244a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1245fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com dst += UNROLL; 1246688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // we don't need to increment src as the asm above has already done it 1247fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com count -= UNROLL; 1248688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org x += UNROLL; // probably superfluous 1249fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1250a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1251fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef UNROLL 1252a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1253688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org // residuals 1254a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count > 0) { 1255a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com DITHER_565_SCAN(y); 1256a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com do { 1257a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColor c = *src++; 1258a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColorAssert(c); 1259a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkASSERT(SkGetPackedA32(c) == 255); 1260a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1261a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned dither = DITHER_VALUE(x); 1262a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *dst++ = SkDitherRGB32To565(c, dither); 1263a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com DITHER_INC_X(x); 1264a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } while (--count != 0); 1265a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1266a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 1267a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1268a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid Color32_arm_neon(SkPMColor* dst, const SkPMColor* src, int count, 1269a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com SkPMColor color) { 1270a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count <= 0) { 1271a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com return; 1272a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1273a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1274a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (0 == color) { 1275a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (src != dst) { 1276a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com memcpy(dst, src, count * sizeof(SkPMColor)); 1277a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1278a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com return; 1279a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1280a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1281a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned colorA = SkGetPackedA32(color); 1282a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (255 == colorA) { 1283a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com sk_memset32(dst, color, count); 1284a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } else { 1285a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com unsigned scale = 256 - SkAlpha255To256(colorA); 1286a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1287a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com if (count >= 8) { 1288a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // at the end of this assembly, count will have been decremented 1289a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // to a negative value. That is, if count mod 8 = x, it will be 1290a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // -8 +x coming out. 1291a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com asm volatile ( 1292a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com PLD128(src, 0) 1293a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1294a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vdup.32 q0, %[color] \n\t" 1295a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1296a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com PLD128(src, 128) 1297a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1298a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // scale numerical interval [0-255], so load as 8 bits 1299a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vdup.8 d2, %[scale] \n\t" 1300a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1301a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com PLD128(src, 256) 1302a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1303a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "subs %[count], %[count], #8 \n\t" 1304a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1305a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com PLD128(src, 384) 1306a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1307a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "Loop_Color32: \n\t" 1308a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1309a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // load src color, 8 pixels, 4 64 bit registers 1310a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // (and increment src). 1311a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vld1.32 {d4-d7}, [%[src]]! \n\t" 1312a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1313a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com PLD128(src, 384) 1314a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1315a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // multiply long by scale, 64 bits at a time, 1316a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // destination into a 128 bit register. 1317a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmull.u8 q4, d4, d2 \n\t" 1318a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmull.u8 q5, d5, d2 \n\t" 1319a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmull.u8 q6, d6, d2 \n\t" 1320a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vmull.u8 q7, d7, d2 \n\t" 1321a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1322a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // shift the 128 bit registers, containing the 16 1323a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // bit scaled values back to 8 bits, narrowing the 1324a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // results to 64 bit registers. 1325a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d8, q4, #8 \n\t" 1326a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d9, q5, #8 \n\t" 1327a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d10, q6, #8 \n\t" 1328a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vshrn.i16 d11, q7, #8 \n\t" 1329a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1330a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // adding back the color, using 128 bit registers. 1331a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vadd.i8 q6, q4, q0 \n\t" 1332a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vadd.i8 q7, q5, q0 \n\t" 1333a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1334a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // store back the 8 calculated pixels (2 128 bit 1335a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // registers), and increment dst. 1336a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "vst1.32 {d12-d15}, [%[dst]]! \n\t" 1337a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1338a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "subs %[count], %[count], #8 \n\t" 1339a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "bge Loop_Color32 \n\t" 1340a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count) 1341a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : [color] "r" (color), [scale] "r" (scale) 1342a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com : "cc", "memory", 1343a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 1344a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15" 1345a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com ); 1346a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // At this point, if we went through the inline assembly, count is 1347a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // a negative value: 1348a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // if the value is -8, there is no pixel left to process. 1349a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // if the value is -7, there is one pixel left to process 1350a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // ... 1351a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // And'ing it with 7 will give us the number of pixels 1352a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // left to process. 1353a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com count = count & 0x7; 1354a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1355a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1356a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com while (count > 0) { 1357a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *dst = color + SkAlphaMulQ(*src, scale); 1358a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com src += 1; 1359a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com dst += 1; 1360a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com count--; 1361a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1362a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com } 1363a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com} 1364a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1365a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/////////////////////////////////////////////////////////////////////////////// 1366a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1367a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comconst SkBlitRow::Proc sk_blitrow_platform_565_procs_arm_neon[] = { 1368a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // no dither 13690060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org // NOTE: For the S32_D565_Blend function below, we don't have a special 13700060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org // version that assumes that each source pixel is opaque. But our 13710060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org // S32A is still faster than the default, so use it. 13720060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org S32_D565_Opaque_neon, 1373a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com S32A_D565_Blend_neon, // really S32_D565_Blend 1374a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com S32A_D565_Opaque_neon, 1375a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com S32A_D565_Blend_neon, 1376a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1377a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com // dither 1378a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com S32_D565_Opaque_Dither_neon, 1379a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com S32_D565_Blend_Dither_neon, 1380a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com S32A_D565_Opaque_Dither_neon, 1381a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com NULL, // S32A_D565_Blend_Dither 1382a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}; 1383a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com 1384a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comconst SkBlitRow::Proc32 sk_blitrow_platform_32_procs_arm_neon[] = { 1385a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com NULL, // S32_Opaque, 1386fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com S32_Blend_BlitRow32_neon, // S32_Blend, 1387c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com /* 1388c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com * We have two choices for S32A_Opaque procs. The one reads the src alpha 1389c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com * value and attempts to optimize accordingly. The optimization is 1390c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com * sensitive to the source content and is not a win in all cases. For 1391c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com * example, if there are a lot of transitions between the alpha states, 1392c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com * the performance will almost certainly be worse. However, for many 1393c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com * common cases the performance is equivalent or better than the standard 1394c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com * case where we do not inspect the src alpha. 1395c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com */ 1396c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#if SK_A32_SHIFT == 24 1397c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com // This proc assumes the alpha value occupies bits 24-32 of each SkPMColor 1398c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com S32A_Opaque_BlitRow32_neon_src_alpha, // S32A_Opaque, 1399c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#else 1400c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com S32A_Opaque_BlitRow32_neon, // S32A_Opaque, 1401c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#endif 14021fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org S32A_Blend_BlitRow32_neon // S32A_Blend 1403a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}; 1404