DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (d8847129d134)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
/*
 * Copyright 2009 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "SkBitmapScaler.h"
#include "SkBitmapProcState.h"
#include "SkColorPriv.h"
#include "SkPaint.h"
#include "SkTypes.h"
#include "SkUtils.h"
#include "SkUtilsArm.h"

#include "SkConvolver.h"

#if !defined(SK_CPU_ARM64) && SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
void SI8_D16_nofilter_DX_arm(
    const SkBitmapProcState& s,
    const uint32_t* SK_RESTRICT xy,
    int count,
    uint16_t* SK_RESTRICT colors) SK_ATTRIBUTE_OPTIMIZE_O1;

void SI8_D16_nofilter_DX_arm(const SkBitmapProcState& s,
                             const uint32_t* SK_RESTRICT xy,
                             int count, uint16_t* SK_RESTRICT colors) {
    SkASSERT(count > 0 && colors != NULL);
    SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask));
    SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);

    const uint16_t* SK_RESTRICT table = s.fBitmap->getColorTable()->lock16BitCache();
    const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels();

    // buffer is y32, x16, x16, x16, x16, x16
    // bump srcAddr to the proper row, since we're told Y never changes
    SkASSERT((unsigned)xy[0] < (unsigned)s.fBitmap->height());
    srcAddr = (const uint8_t*)((const char*)srcAddr +
                               xy[0] * s.fBitmap->rowBytes());

    uint8_t src;

    if (1 == s.fBitmap->width()) {
        src = srcAddr[0];
        uint16_t dstValue = table[src];
        sk_memset16(colors, dstValue, count);
    } else {
        int i;
        int count8 = count >> 3;
        const uint16_t* SK_RESTRICT xx = (const uint16_t*)(xy + 1);

        asm volatile (
            "cmp        %[count8], #0                  \n\t"  // compare loop counter with 0
            "beq        2f                             \n\t"  // if loop counter == 0, exit
            "1:                                        \n\t"
            "ldmia      %[xx]!, {r5, r7, r9, r11}      \n\t"  // load ptrs to pixels 0-7
            "subs       %[count8], %[count8], #1       \n\t"  // decrement loop counter
            "uxth       r4, r5                         \n\t"  // extract ptr 0
            "mov        r5, r5, lsr #16                \n\t"  // extract ptr 1
            "uxth       r6, r7                         \n\t"  // extract ptr 2
            "mov        r7, r7, lsr #16                \n\t"  // extract ptr 3
            "ldrb       r4, [%[srcAddr], r4]           \n\t"  // load pixel 0 from image
            "uxth       r8, r9                         \n\t"  // extract ptr 4
            "ldrb       r5, [%[srcAddr], r5]           \n\t"  // load pixel 1 from image
            "mov        r9, r9, lsr #16                \n\t"  // extract ptr 5
            "ldrb       r6, [%[srcAddr], r6]           \n\t"  // load pixel 2 from image
            "uxth       r10, r11                       \n\t"  // extract ptr 6
            "ldrb       r7, [%[srcAddr], r7]           \n\t"  // load pixel 3 from image
            "mov        r11, r11, lsr #16              \n\t"  // extract ptr 7
            "ldrb       r8, [%[srcAddr], r8]           \n\t"  // load pixel 4 from image
            "add        r4, r4, r4                     \n\t"  // double pixel 0 for RGB565 lookup
            "ldrb       r9, [%[srcAddr], r9]           \n\t"  // load pixel 5 from image
            "add        r5, r5, r5                     \n\t"  // double pixel 1 for RGB565 lookup
            "ldrb       r10, [%[srcAddr], r10]         \n\t"  // load pixel 6 from image
            "add        r6, r6, r6                     \n\t"  // double pixel 2 for RGB565 lookup
            "ldrb       r11, [%[srcAddr], r11]         \n\t"  // load pixel 7 from image
            "add        r7, r7, r7                     \n\t"  // double pixel 3 for RGB565 lookup
            "ldrh       r4, [%[table], r4]             \n\t"  // load pixel 0 RGB565 from colmap
            "add        r8, r8, r8                     \n\t"  // double pixel 4 for RGB565 lookup
            "ldrh       r5, [%[table], r5]             \n\t"  // load pixel 1 RGB565 from colmap
            "add        r9, r9, r9                     \n\t"  // double pixel 5 for RGB565 lookup
            "ldrh       r6, [%[table], r6]             \n\t"  // load pixel 2 RGB565 from colmap
            "add        r10, r10, r10                  \n\t"  // double pixel 6 for RGB565 lookup
            "ldrh       r7, [%[table], r7]             \n\t"  // load pixel 3 RGB565 from colmap
            "add        r11, r11, r11                  \n\t"  // double pixel 7 for RGB565 lookup
            "ldrh       r8, [%[table], r8]             \n\t"  // load pixel 4 RGB565 from colmap
            "ldrh       r9, [%[table], r9]             \n\t"  // load pixel 5 RGB565 from colmap
            "ldrh       r10, [%[table], r10]           \n\t"  // load pixel 6 RGB565 from colmap
            "ldrh       r11, [%[table], r11]           \n\t"  // load pixel 7 RGB565 from colmap
            "pkhbt      r5, r4, r5, lsl #16            \n\t"  // pack pixels 0 and 1
            "pkhbt      r6, r6, r7, lsl #16            \n\t"  // pack pixels 2 and 3
            "pkhbt      r8, r8, r9, lsl #16            \n\t"  // pack pixels 4 and 5
            "pkhbt      r10, r10, r11, lsl #16         \n\t"  // pack pixels 6 and 7
            "stmia      %[colors]!, {r5, r6, r8, r10}  \n\t"  // store last 8 pixels
            "bgt        1b                             \n\t"  // loop if counter > 0
            "2:                                        \n\t"
            : [xx] "+r" (xx), [count8] "+r" (count8), [colors] "+r" (colors)
            : [table] "r" (table), [srcAddr] "r" (srcAddr)
            : "memory", "cc", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
        );

        for (i = (count & 7); i > 0; --i) {
            src = srcAddr[*xx++]; *colors++ = table[src];
        }
    }

    s.fBitmap->getColorTable()->unlock16BitCache();
}

void SI8_opaque_D32_nofilter_DX_arm(
    const SkBitmapProcState& s,
    const uint32_t* SK_RESTRICT xy,
    int count,
    SkPMColor* SK_RESTRICT colors) SK_ATTRIBUTE_OPTIMIZE_O1;

void SI8_opaque_D32_nofilter_DX_arm(const SkBitmapProcState& s,
                                    const uint32_t* SK_RESTRICT xy,
                                    int count, SkPMColor* SK_RESTRICT colors) {
    SkASSERT(count > 0 && colors != NULL);
    SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask));
    SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);

    const SkPMColor* SK_RESTRICT table = s.fBitmap->getColorTable()->lockColors();
    const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels();

    // buffer is y32, x16, x16, x16, x16, x16
    // bump srcAddr to the proper row, since we're told Y never changes
    SkASSERT((unsigned)xy[0] < (unsigned)s.fBitmap->height());
    srcAddr = (const uint8_t*)((const char*)srcAddr + xy[0] * s.fBitmap->rowBytes());

    if (1 == s.fBitmap->width()) {
        uint8_t src = srcAddr[0];
        SkPMColor dstValue = table[src];
        sk_memset32(colors, dstValue, count);
    } else {
        const uint16_t* xx = (const uint16_t*)(xy + 1);

        asm volatile (
            "subs       %[count], %[count], #8        \n\t"   // decrement count by 8, set flags
            "blt        2f                            \n\t"   // if count < 0, branch to singles
            "1:                                       \n\t"   // eights loop
            "ldmia      %[xx]!, {r5, r7, r9, r11}     \n\t"   // load ptrs to pixels 0-7
            "uxth       r4, r5                        \n\t"   // extract ptr 0
            "mov        r5, r5, lsr #16               \n\t"   // extract ptr 1
            "uxth       r6, r7                        \n\t"   // extract ptr 2
            "mov        r7, r7, lsr #16               \n\t"   // extract ptr 3
            "ldrb       r4, [%[srcAddr], r4]          \n\t"   // load pixel 0 from image
            "uxth       r8, r9                        \n\t"   // extract ptr 4
            "ldrb       r5, [%[srcAddr], r5]          \n\t"   // load pixel 1 from image
            "mov        r9, r9, lsr #16               \n\t"   // extract ptr 5
            "ldrb       r6, [%[srcAddr], r6]          \n\t"   // load pixel 2 from image
            "uxth       r10, r11                      \n\t"   // extract ptr 6
            "ldrb       r7, [%[srcAddr], r7]          \n\t"   // load pixel 3 from image
            "mov        r11, r11, lsr #16             \n\t"   // extract ptr 7
            "ldrb       r8, [%[srcAddr], r8]          \n\t"   // load pixel 4 from image
            "ldrb       r9, [%[srcAddr], r9]          \n\t"   // load pixel 5 from image
            "ldrb       r10, [%[srcAddr], r10]        \n\t"   // load pixel 6 from image
            "ldrb       r11, [%[srcAddr], r11]        \n\t"   // load pixel 7 from image
            "ldr        r4, [%[table], r4, lsl #2]    \n\t"   // load pixel 0 SkPMColor from colmap
            "ldr        r5, [%[table], r5, lsl #2]    \n\t"   // load pixel 1 SkPMColor from colmap
            "ldr        r6, [%[table], r6, lsl #2]    \n\t"   // load pixel 2 SkPMColor from colmap
            "ldr        r7, [%[table], r7, lsl #2]    \n\t"   // load pixel 3 SkPMColor from colmap
            "ldr        r8, [%[table], r8, lsl #2]    \n\t"   // load pixel 4 SkPMColor from colmap
            "ldr        r9, [%[table], r9, lsl #2]    \n\t"   // load pixel 5 SkPMColor from colmap
            "ldr        r10, [%[table], r10, lsl #2]  \n\t"   // load pixel 6 SkPMColor from colmap
            "ldr        r11, [%[table], r11, lsl #2]  \n\t"   // load pixel 7 SkPMColor from colmap
            "subs       %[count], %[count], #8        \n\t"   // decrement loop counter
            "stmia      %[colors]!, {r4-r11}          \n\t"   // store 8 pixels
            "bge        1b                            \n\t"   // loop if counter >= 0
            "2:                                       \n\t"
            "adds       %[count], %[count], #8        \n\t"   // fix up counter, set flags
            "beq        4f                            \n\t"   // if count == 0, branch to exit
            "3:                                       \n\t"   // singles loop
            "ldrh       r4, [%[xx]], #2               \n\t"   // load pixel ptr
            "subs       %[count], %[count], #1        \n\t"   // decrement loop counter
            "ldrb       r5, [%[srcAddr], r4]          \n\t"   // load pixel from image
            "ldr        r6, [%[table], r5, lsl #2]    \n\t"   // load SkPMColor from colmap
            "str        r6, [%[colors]], #4           \n\t"   // store pixel, update ptr
            "bne        3b                            \n\t"   // loop if counter != 0
            "4:                                       \n\t"   // exit
            : [xx] "+r" (xx), [count] "+r" (count), [colors] "+r" (colors)
            : [table] "r" (table), [srcAddr] "r" (srcAddr)
            : "memory", "cc", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11"
        );
    }

    s.fBitmap->getColorTable()->unlockColors();
}
#endif // !defined(SK_CPU_ARM64) && SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)

///////////////////////////////////////////////////////////////////////////////

/*  If we replace a sampleproc, then we null-out the associated shaderproc,
    otherwise the shader won't even look at the matrix/sampler
 */
void SkBitmapProcState::platformProcs() {
#if !defined(SK_CPU_ARM64) && SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
    bool isOpaque = 256 == fAlphaScale;
    bool justDx = false;

    if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
        justDx = true;
    }

    switch (fBitmap->colorType()) {
        case kIndex_8_SkColorType:
            if (justDx && SkPaint::kNone_FilterLevel == fFilterLevel) {
#if 0   /* crashing on android device */
                fSampleProc16 = SI8_D16_nofilter_DX_arm;
                fShaderProc16 = NULL;
#endif
                if (isOpaque) {
                    // this one is only very slighty faster than the C version
                    fSampleProc32 = SI8_opaque_D32_nofilter_DX_arm;
                    fShaderProc32 = NULL;
                }
            }
            break;
        default:
            break;
    }
#endif
}

///////////////////////////////////////////////////////////////////////////////

extern void platformConvolutionProcs_arm_neon(SkConvolutionProcs* procs);

void platformConvolutionProcs_arm(SkConvolutionProcs* procs) {
}

void SkBitmapScaler::PlatformConvolutionProcs(SkConvolutionProcs* procs) {
    SK_ARM_NEON_WRAP(platformConvolutionProcs_arm)(procs);
}