michael@0: michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: #include "SkUtils.h" michael@0: michael@0: #if DSTSIZE==32 michael@0: #define DSTTYPE SkPMColor michael@0: #elif DSTSIZE==16 michael@0: #define DSTTYPE uint16_t michael@0: #else michael@0: #error "need DSTSIZE to be 32 or 16" michael@0: #endif michael@0: michael@0: #if (DSTSIZE == 32) michael@0: #define BITMAPPROC_MEMSET(ptr, value, n) sk_memset32(ptr, value, n) michael@0: #elif (DSTSIZE == 16) michael@0: #define BITMAPPROC_MEMSET(ptr, value, n) sk_memset16(ptr, value, n) michael@0: #else michael@0: #error "unsupported DSTSIZE" michael@0: #endif michael@0: michael@0: michael@0: // declare functions externally to suppress warnings. michael@0: void MAKENAME(_nofilter_DXDY)(const SkBitmapProcState& s, michael@0: const uint32_t* SK_RESTRICT xy, michael@0: int count, DSTTYPE* SK_RESTRICT colors); michael@0: void MAKENAME(_nofilter_DX)(const SkBitmapProcState& s, michael@0: const uint32_t* SK_RESTRICT xy, michael@0: int count, DSTTYPE* SK_RESTRICT colors); michael@0: void MAKENAME(_filter_DX)(const SkBitmapProcState& s, michael@0: const uint32_t* SK_RESTRICT xy, michael@0: int count, DSTTYPE* SK_RESTRICT colors); michael@0: void MAKENAME(_filter_DXDY)(const SkBitmapProcState& s, michael@0: const uint32_t* SK_RESTRICT xy, michael@0: int count, DSTTYPE* SK_RESTRICT colors); michael@0: michael@0: void MAKENAME(_nofilter_DXDY)(const SkBitmapProcState& s, michael@0: const uint32_t* SK_RESTRICT xy, michael@0: int count, DSTTYPE* SK_RESTRICT colors) { michael@0: SkASSERT(count > 0 && colors != NULL); michael@0: SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); michael@0: SkDEBUGCODE(CHECKSTATE(s);) michael@0: michael@0: #ifdef PREAMBLE michael@0: PREAMBLE(s); michael@0: #endif michael@0: const char* SK_RESTRICT srcAddr = (const char*)s.fBitmap->getPixels(); michael@0: size_t rb = s.fBitmap->rowBytes(); michael@0: michael@0: uint32_t XY; michael@0: SRCTYPE src; michael@0: michael@0: for (int i = (count >> 1); i > 0; --i) { michael@0: XY = *xy++; michael@0: SkASSERT((XY >> 16) < (unsigned)s.fBitmap->height() && michael@0: (XY & 0xFFFF) < (unsigned)s.fBitmap->width()); michael@0: src = ((const SRCTYPE*)(srcAddr + (XY >> 16) * rb))[XY & 0xFFFF]; michael@0: *colors++ = RETURNDST(src); michael@0: michael@0: XY = *xy++; michael@0: SkASSERT((XY >> 16) < (unsigned)s.fBitmap->height() && michael@0: (XY & 0xFFFF) < (unsigned)s.fBitmap->width()); michael@0: src = ((const SRCTYPE*)(srcAddr + (XY >> 16) * rb))[XY & 0xFFFF]; michael@0: *colors++ = RETURNDST(src); michael@0: } michael@0: if (count & 1) { michael@0: XY = *xy++; michael@0: SkASSERT((XY >> 16) < (unsigned)s.fBitmap->height() && michael@0: (XY & 0xFFFF) < (unsigned)s.fBitmap->width()); michael@0: src = ((const SRCTYPE*)(srcAddr + (XY >> 16) * rb))[XY & 0xFFFF]; michael@0: *colors++ = RETURNDST(src); michael@0: } michael@0: michael@0: #ifdef POSTAMBLE michael@0: POSTAMBLE(s); michael@0: #endif michael@0: } michael@0: michael@0: void MAKENAME(_nofilter_DX)(const SkBitmapProcState& s, michael@0: const uint32_t* SK_RESTRICT xy, michael@0: int count, DSTTYPE* SK_RESTRICT colors) { michael@0: SkASSERT(count > 0 && colors != NULL); michael@0: SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); michael@0: SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); michael@0: SkDEBUGCODE(CHECKSTATE(s);) michael@0: michael@0: #ifdef PREAMBLE michael@0: PREAMBLE(s); michael@0: #endif michael@0: const SRCTYPE* SK_RESTRICT srcAddr = (const SRCTYPE*)s.fBitmap->getPixels(); michael@0: michael@0: // buffer is y32, x16, x16, x16, x16, x16 michael@0: // bump srcAddr to the proper row, since we're told Y never changes michael@0: SkASSERT((unsigned)xy[0] < (unsigned)s.fBitmap->height()); michael@0: srcAddr = (const SRCTYPE*)((const char*)srcAddr + michael@0: xy[0] * s.fBitmap->rowBytes()); michael@0: xy += 1; michael@0: michael@0: SRCTYPE src; michael@0: michael@0: if (1 == s.fBitmap->width()) { michael@0: src = srcAddr[0]; michael@0: DSTTYPE dstValue = RETURNDST(src); michael@0: BITMAPPROC_MEMSET(colors, dstValue, count); michael@0: } else { michael@0: int i; michael@0: for (i = (count >> 2); i > 0; --i) { michael@0: uint32_t xx0 = *xy++; michael@0: uint32_t xx1 = *xy++; michael@0: SRCTYPE x0 = srcAddr[UNPACK_PRIMARY_SHORT(xx0)]; michael@0: SRCTYPE x1 = srcAddr[UNPACK_SECONDARY_SHORT(xx0)]; michael@0: SRCTYPE x2 = srcAddr[UNPACK_PRIMARY_SHORT(xx1)]; michael@0: SRCTYPE x3 = srcAddr[UNPACK_SECONDARY_SHORT(xx1)]; michael@0: michael@0: *colors++ = RETURNDST(x0); michael@0: *colors++ = RETURNDST(x1); michael@0: *colors++ = RETURNDST(x2); michael@0: *colors++ = RETURNDST(x3); michael@0: } michael@0: const uint16_t* SK_RESTRICT xx = (const uint16_t*)(xy); michael@0: for (i = (count & 3); i > 0; --i) { michael@0: SkASSERT(*xx < (unsigned)s.fBitmap->width()); michael@0: src = srcAddr[*xx++]; *colors++ = RETURNDST(src); michael@0: } michael@0: } michael@0: michael@0: #ifdef POSTAMBLE michael@0: POSTAMBLE(s); michael@0: #endif michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: void MAKENAME(_filter_DX)(const SkBitmapProcState& s, michael@0: const uint32_t* SK_RESTRICT xy, michael@0: int count, DSTTYPE* SK_RESTRICT colors) { michael@0: SkASSERT(count > 0 && colors != NULL); michael@0: SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel); michael@0: SkDEBUGCODE(CHECKSTATE(s);) michael@0: michael@0: #ifdef PREAMBLE michael@0: PREAMBLE(s); michael@0: #endif michael@0: const char* SK_RESTRICT srcAddr = (const char*)s.fBitmap->getPixels(); michael@0: size_t rb = s.fBitmap->rowBytes(); michael@0: unsigned subY; michael@0: const SRCTYPE* SK_RESTRICT row0; michael@0: const SRCTYPE* SK_RESTRICT row1; michael@0: michael@0: // setup row ptrs and update proc_table michael@0: { michael@0: uint32_t XY = *xy++; michael@0: unsigned y0 = XY >> 14; michael@0: row0 = (const SRCTYPE*)(srcAddr + (y0 >> 4) * rb); michael@0: row1 = (const SRCTYPE*)(srcAddr + (XY & 0x3FFF) * rb); michael@0: subY = y0 & 0xF; michael@0: } michael@0: michael@0: do { michael@0: uint32_t XX = *xy++; // x0:14 | 4 | x1:14 michael@0: unsigned x0 = XX >> 14; michael@0: unsigned x1 = XX & 0x3FFF; michael@0: unsigned subX = x0 & 0xF; michael@0: x0 >>= 4; michael@0: michael@0: FILTER_PROC(subX, subY, michael@0: SRC_TO_FILTER(row0[x0]), michael@0: SRC_TO_FILTER(row0[x1]), michael@0: SRC_TO_FILTER(row1[x0]), michael@0: SRC_TO_FILTER(row1[x1]), michael@0: colors); michael@0: colors += 1; michael@0: michael@0: } while (--count != 0); michael@0: michael@0: #ifdef POSTAMBLE michael@0: POSTAMBLE(s); michael@0: #endif michael@0: } michael@0: void MAKENAME(_filter_DXDY)(const SkBitmapProcState& s, michael@0: const uint32_t* SK_RESTRICT xy, michael@0: int count, DSTTYPE* SK_RESTRICT colors) { michael@0: SkASSERT(count > 0 && colors != NULL); michael@0: SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel); michael@0: SkDEBUGCODE(CHECKSTATE(s);) michael@0: michael@0: #ifdef PREAMBLE michael@0: PREAMBLE(s); michael@0: #endif michael@0: const char* SK_RESTRICT srcAddr = (const char*)s.fBitmap->getPixels(); michael@0: size_t rb = s.fBitmap->rowBytes(); michael@0: michael@0: do { michael@0: uint32_t data = *xy++; michael@0: unsigned y0 = data >> 14; michael@0: unsigned y1 = data & 0x3FFF; michael@0: unsigned subY = y0 & 0xF; michael@0: y0 >>= 4; michael@0: michael@0: data = *xy++; michael@0: unsigned x0 = data >> 14; michael@0: unsigned x1 = data & 0x3FFF; michael@0: unsigned subX = x0 & 0xF; michael@0: x0 >>= 4; michael@0: michael@0: const SRCTYPE* SK_RESTRICT row0 = (const SRCTYPE*)(srcAddr + y0 * rb); michael@0: const SRCTYPE* SK_RESTRICT row1 = (const SRCTYPE*)(srcAddr + y1 * rb); michael@0: michael@0: FILTER_PROC(subX, subY, michael@0: SRC_TO_FILTER(row0[x0]), michael@0: SRC_TO_FILTER(row0[x1]), michael@0: SRC_TO_FILTER(row1[x0]), michael@0: SRC_TO_FILTER(row1[x1]), michael@0: colors); michael@0: colors += 1; michael@0: } while (--count != 0); michael@0: michael@0: #ifdef POSTAMBLE michael@0: POSTAMBLE(s); michael@0: #endif michael@0: } michael@0: michael@0: #undef MAKENAME michael@0: #undef DSTSIZE michael@0: #undef DSTTYPE michael@0: #undef SRCTYPE michael@0: #undef CHECKSTATE michael@0: #undef RETURNDST michael@0: #undef SRC_TO_FILTER michael@0: #undef FILTER_TO_DST michael@0: michael@0: #ifdef PREAMBLE michael@0: #undef PREAMBLE michael@0: #endif michael@0: #ifdef POSTAMBLE michael@0: #undef POSTAMBLE michael@0: #endif michael@0: michael@0: #undef FILTER_PROC_TYPE michael@0: #undef GET_FILTER_TABLE michael@0: #undef GET_FILTER_ROW michael@0: #undef GET_FILTER_ROW_PROC michael@0: #undef GET_FILTER_PROC michael@0: #undef BITMAPPROC_MEMSET