15bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org/* 25bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org * Copyright 2012 The Android Open Source Project 35bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org * 45bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 55bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org * found in the LICENSE file. 65bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org */ 75bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 85bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org#include "SkMorphologyImageFilter.h" 944b93a06ef9f00cceaede2ffc0fed971fa018e38djsollen@google.com#include "SkBitmap.h" 105bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org#include "SkColorPriv.h" 119ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkFlattenableBuffers.h" 129ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkRect.h" 133515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com#if SK_SUPPORT_GPU 1451f8f47eb816bf6f153971f1fe242aec4a078714senorblanco@chromium.org#include "GrContext.h" 1551f8f47eb816bf6f153971f1fe242aec4a078714senorblanco@chromium.org#include "GrTexture.h" 168780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com#include "GrTBackendEffectFactory.h" 17aab3f0a5176fa13f1f0452386651dc5c8676ba68bsalomon@google.com#include "gl/GrGLEffect.h" 18bc7f7b134d013466fc237434468d758c7d025e99bsalomon@google.com#include "gl/GrGLEffectMatrix.h" 19bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org#include "effects/Gr1DKernelEffect.h" 20868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org#include "SkImageFilterUtils.h" 213515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com#endif 225bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 235bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.orgSkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer) 245bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org : INHERITED(buffer) { 250617a3cc12d399f60e4283cec051c47847c07c11tomhudson@google.com fRadius.fWidth = buffer.readInt(); 260617a3cc12d399f60e4283cec051c47847c07c11tomhudson@google.com fRadius.fHeight = buffer.readInt(); 275bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 285bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 29d1e690d99102d222364d2efa3eb7c881ff017446senorblanco@chromium.orgSkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input) 30d1e690d99102d222364d2efa3eb7c881ff017446senorblanco@chromium.org : INHERITED(input), fRadius(SkISize::Make(radiusX, radiusY)) { 315bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 325bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 335bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 34cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.comvoid SkMorphologyImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 355bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org this->INHERITED::flatten(buffer); 360617a3cc12d399f60e4283cec051c47847c07c11tomhudson@google.com buffer.writeInt(fRadius.fWidth); 370617a3cc12d399f60e4283cec051c47847c07c11tomhudson@google.com buffer.writeInt(fRadius.fHeight); 385bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 395bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 405bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.orgstatic void erode(const SkPMColor* src, SkPMColor* dst, 415bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int radius, int width, int height, 425bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int srcStrideX, int srcStrideY, 435bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int dstStrideX, int dstStrideY) 445bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org{ 45b2b48fed0305cc371b799519110051e2d4ce17c7senorblanco@chromium.org radius = SkMin32(radius, width - 1); 46b2b48fed0305cc371b799519110051e2d4ce17c7senorblanco@chromium.org const SkPMColor* upperSrc = src + radius * srcStrideX; 475bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org for (int x = 0; x < width; ++x) { 485bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org const SkPMColor* lp = src; 495bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org const SkPMColor* up = upperSrc; 505bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org SkPMColor* dptr = dst; 515bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org for (int y = 0; y < height; ++y) { 525bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int minB = 255, minG = 255, minR = 255, minA = 255; 535bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { 545bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int b = SkGetPackedB32(*p); 555bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int g = SkGetPackedG32(*p); 565bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int r = SkGetPackedR32(*p); 575bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int a = SkGetPackedA32(*p); 585bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (b < minB) minB = b; 595bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (g < minG) minG = g; 605bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (r < minR) minR = r; 615bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (a < minA) minA = a; 625bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 635bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org *dptr = SkPackARGB32(minA, minR, minG, minB); 645bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dptr += dstStrideY; 655bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org lp += srcStrideY; 665bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org up += srcStrideY; 675bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 685bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (x >= radius) src += srcStrideX; 695bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (x + radius < width - 1) upperSrc += srcStrideX; 705bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dst += dstStrideX; 715bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 725bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 735bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 745bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.orgstatic void erodeX(const SkBitmap& src, SkBitmap* dst, int radiusX) 755bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org{ 765bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org erode(src.getAddr32(0, 0), dst->getAddr32(0, 0), 775bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org radiusX, src.width(), src.height(), 785bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1, src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels()); 795bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 805bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 815bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.orgstatic void erodeY(const SkBitmap& src, SkBitmap* dst, int radiusY) 825bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org{ 835bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org erode(src.getAddr32(0, 0), dst->getAddr32(0, 0), 845bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org radiusY, src.height(), src.width(), 855bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels(), 1); 865bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 875bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 885bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.orgstatic void dilate(const SkPMColor* src, SkPMColor* dst, 895bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int radius, int width, int height, 905bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int srcStrideX, int srcStrideY, 915bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int dstStrideX, int dstStrideY) 925bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org{ 93b2b48fed0305cc371b799519110051e2d4ce17c7senorblanco@chromium.org radius = SkMin32(radius, width - 1); 94b2b48fed0305cc371b799519110051e2d4ce17c7senorblanco@chromium.org const SkPMColor* upperSrc = src + radius * srcStrideX; 955bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org for (int x = 0; x < width; ++x) { 965bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org const SkPMColor* lp = src; 975bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org const SkPMColor* up = upperSrc; 985bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org SkPMColor* dptr = dst; 995bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org for (int y = 0; y < height; ++y) { 1005bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int maxB = 0, maxG = 0, maxR = 0, maxA = 0; 1015bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org for (const SkPMColor* p = lp; p <= up; p += srcStrideX) { 1025bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int b = SkGetPackedB32(*p); 1035bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int g = SkGetPackedG32(*p); 1045bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int r = SkGetPackedR32(*p); 1055bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int a = SkGetPackedA32(*p); 1065bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (b > maxB) maxB = b; 1075bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (g > maxG) maxG = g; 1085bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (r > maxR) maxR = r; 1095bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (a > maxA) maxA = a; 1105bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1115bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org *dptr = SkPackARGB32(maxA, maxR, maxG, maxB); 1125bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dptr += dstStrideY; 1135bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org lp += srcStrideY; 1145bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org up += srcStrideY; 1155bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1165bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (x >= radius) src += srcStrideX; 1175bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (x + radius < width - 1) upperSrc += srcStrideX; 1185bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dst += dstStrideX; 1195bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1205bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 1215bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1225bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.orgstatic void dilateX(const SkBitmap& src, SkBitmap* dst, int radiusX) 1235bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org{ 1245bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dilate(src.getAddr32(0, 0), dst->getAddr32(0, 0), 1255bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org radiusX, src.width(), src.height(), 1265bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1, src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels()); 1275bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 1285bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1295bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.orgstatic void dilateY(const SkBitmap& src, SkBitmap* dst, int radiusY) 1305bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org{ 1315bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dilate(src.getAddr32(0, 0), dst->getAddr32(0, 0), 1325bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org radiusY, src.height(), src.width(), 1335bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels(), 1); 1345bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 1355bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 136d1e690d99102d222364d2efa3eb7c881ff017446senorblanco@chromium.orgbool SkErodeImageFilter::onFilterImage(Proxy* proxy, 137d1e690d99102d222364d2efa3eb7c881ff017446senorblanco@chromium.org const SkBitmap& source, const SkMatrix& ctm, 138d1e690d99102d222364d2efa3eb7c881ff017446senorblanco@chromium.org SkBitmap* dst, SkIPoint* offset) { 1393367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org SkBitmap src = source; 1403367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) { 1413367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org return false; 1423367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org } 1433367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org 1445bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (src.config() != SkBitmap::kARGB_8888_Config) { 1455bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return false; 1465bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1475bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1485bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org SkAutoLockPixels alp(src); 1495bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (!src.getPixels()) { 1505bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return false; 1515bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1525bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1535bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dst->setConfig(src.config(), src.width(), src.height()); 1545bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dst->allocPixels(); 1555bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1565bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int width = radius().width(); 1575bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int height = radius().height(); 1585bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1595bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (width < 0 || height < 0) { 1605bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return false; 1615bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1625bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1635bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (width == 0 && height == 0) { 1645bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org src.copyTo(dst, dst->config()); 1655bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return true; 1665bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1675bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1685bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org SkBitmap temp; 1695bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org temp.setConfig(dst->config(), dst->width(), dst->height()); 1705bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (!temp.allocPixels()) { 1715bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return false; 1725bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1735bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1745bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (width > 0 && height > 0) { 1755bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org erodeX(src, &temp, width); 1765bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org erodeY(temp, dst, height); 1775bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } else if (width > 0) { 1785bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org erodeX(src, dst, width); 1795bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } else if (height > 0) { 1805bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org erodeY(src, dst, height); 1815bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1825bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return true; 1835bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 1845bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 185d1e690d99102d222364d2efa3eb7c881ff017446senorblanco@chromium.orgbool SkDilateImageFilter::onFilterImage(Proxy* proxy, 186d1e690d99102d222364d2efa3eb7c881ff017446senorblanco@chromium.org const SkBitmap& source, const SkMatrix& ctm, 187d1e690d99102d222364d2efa3eb7c881ff017446senorblanco@chromium.org SkBitmap* dst, SkIPoint* offset) { 1883367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org SkBitmap src = source; 1893367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) { 1903367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org return false; 1913367b085856c70225f016ed90fd15ed393aeaed2senorblanco@chromium.org } 1925bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (src.config() != SkBitmap::kARGB_8888_Config) { 1935bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return false; 1945bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 1955bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 1965bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org SkAutoLockPixels alp(src); 1975bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (!src.getPixels()) { 1985bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return false; 1995bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 2005bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 2015bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dst->setConfig(src.config(), src.width(), src.height()); 2025bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dst->allocPixels(); 2035bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 2045bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int width = radius().width(); 2055bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org int height = radius().height(); 2065bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 2075bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (width < 0 || height < 0) { 2085bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return false; 2095bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 2105bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 2115bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (width == 0 && height == 0) { 2125bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org src.copyTo(dst, dst->config()); 2135bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return true; 2145bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 2155bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 2165bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org SkBitmap temp; 2175bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org temp.setConfig(dst->config(), dst->width(), dst->height()); 2185bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (!temp.allocPixels()) { 2195bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return false; 2205bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 2215bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 2225bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org if (width > 0 && height > 0) { 2235bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dilateX(src, &temp, width); 2245bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dilateY(temp, dst, height); 2255bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } else if (width > 0) { 2265bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dilateX(src, dst, width); 2275bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } else if (height > 0) { 2285bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org dilateY(src, dst, height); 2295bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org } 2305bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org return true; 2315bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 2325bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 2333515569a78b58fbb57f20ec909fffde8f945c19cbsalomon@google.com#if SK_SUPPORT_GPU 234bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 235bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org/////////////////////////////////////////////////////////////////////////////// 236bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 237bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgclass GrGLMorphologyEffect; 238bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 239bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org/** 240bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org * Morphology effects. Depending upon the type of morphology, either the 241bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org * component-wise min (Erode_Type) or max (Dilate_Type) of all pixels in the 242bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org * kernel is selected as the new color. The new color is modulated by the input 243bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org * color. 244bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org */ 245bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgclass GrMorphologyEffect : public Gr1DKernelEffect { 246bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 247bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgpublic: 248bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 249bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org enum MorphologyType { 250bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org kErode_MorphologyType, 251bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org kDilate_MorphologyType, 252bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org }; 253bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 25438b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com static GrEffectRef* Create(GrTexture* tex, Direction dir, int radius, MorphologyType type) { 255ba8399f132a172950b49dec019e910ff681928f6bsalomon@google.com AutoEffectUnref effect(SkNEW_ARGS(GrMorphologyEffect, (tex, dir, radius, type))); 25686e2faff92b4e897e1e38e8728f098a5d9d22034bsalomon@google.com return CreateEffectRef(effect); 25738b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com } 25838b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com 259bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org virtual ~GrMorphologyEffect(); 260bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 261bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org MorphologyType type() const { return fType; } 262bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 263bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org static const char* Name() { return "Morphology"; } 264bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 265ca5e87e973b87209b5ffa298b8bc6ce0c512a204bsalomon@google.com typedef GrGLMorphologyEffect GLEffect; 266bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 2671f64de790a624dc250d3da0789b3ada6251facb7bsalomon@google.com virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 268c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 269bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 270bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgprotected: 271bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 272bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org MorphologyType fType; 273bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 274bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgprivate: 2756a2cef0e27af0600fe1afcc0fcda2f3011371be9bsalomon@google.com virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 276c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com 27738b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com GrMorphologyEffect(GrTexture*, Direction, int radius, MorphologyType); 27838b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com 2797e0b48a766909be86a2923d909b85c111de4d237bsalomon@google.com GR_DECLARE_EFFECT_TEST; 280bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 281bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org typedef Gr1DKernelEffect INHERITED; 282bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org}; 283bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 284bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org/////////////////////////////////////////////////////////////////////////////// 285bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 286868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.orgclass GrGLMorphologyEffect : public GrGLEffect { 287bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgpublic: 2888bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com GrGLMorphologyEffect (const GrBackendEffectFactory&, const GrDrawEffect&); 289bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 2908780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com virtual void emitCode(GrGLShaderBuilder*, 2918bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrDrawEffect&, 2928780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com EffectKey, 2938780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const char* outputColor, 2948780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const char* inputColor, 2958780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const TextureSamplerArray&) SK_OVERRIDE; 296bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 2978bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 298bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 2998bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 300bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 301bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgprivate: 302bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org int width() const { return GrMorphologyEffect::WidthFromRadius(fRadius); } 303bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 304bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org int fRadius; 305bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrMorphologyEffect::MorphologyType fType; 306bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrGLUniformManager::UniformHandle fImageIncrementUni; 307bc7f7b134d013466fc237434468d758c7d025e99bsalomon@google.com GrGLEffectMatrix fEffectMatrix; 308bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 3098780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com typedef GrGLEffect INHERITED; 310bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org}; 311bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 3121f64de790a624dc250d3da0789b3ada6251facb7bsalomon@google.comGrGLMorphologyEffect::GrGLMorphologyEffect(const GrBackendEffectFactory& factory, 3138bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrDrawEffect& drawEffect) 31416d2ef4cfb3ded1a3424a372b37c641845095ff3bsalomon@google.com : INHERITED(factory) 3158bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com , fImageIncrementUni(GrGLUniformManager::kInvalidUniformHandle) 3168bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com , fEffectMatrix(drawEffect.castEffect<GrMorphologyEffect>().coordsType()) { 3178bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrMorphologyEffect& m = drawEffect.castEffect<GrMorphologyEffect>(); 318bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org fRadius = m.radius(); 319bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org fType = m.type(); 320bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 321bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 3228780f037626b5196962a39ab76afd51f094a7765bsalomon@google.comvoid GrGLMorphologyEffect::emitCode(GrGLShaderBuilder* builder, 3238bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrDrawEffect&, 324bc7f7b134d013466fc237434468d758c7d025e99bsalomon@google.com EffectKey key, 3258780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const char* outputColor, 3268780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const char* inputColor, 3278780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com const TextureSamplerArray& samplers) { 328bc7f7b134d013466fc237434468d758c7d025e99bsalomon@google.com const char* coords; 3298bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords); 330bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, 331bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org kVec2f_GrSLType, "ImageIncrement"); 332bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 333bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org const char* func; 334bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org switch (fType) { 335bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org case GrMorphologyEffect::kErode_MorphologyType: 336093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", outputColor); 337bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org func = "min"; 338bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org break; 339bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org case GrMorphologyEffect::kDilate_MorphologyType: 340093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); 341bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org func = "max"; 342bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org break; 343bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org default: 344bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrCrash("Unexpected type"); 345bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org func = ""; // suppress warning 346bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org break; 347bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org } 348bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org const char* imgInc = builder->getUniformCStr(fImageIncrementUni); 349bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 350093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords, fRadius, imgInc); 351093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", this->width()); 352093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppendf("\t\t\t%s = %s(%s, ", outputColor, func, outputColor); 353093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, samplers[0], "coord"); 354093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppend(");\n"); 355093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppendf("\t\t\tcoord += %s;\n", imgInc); 356093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppend("\t\t}\n"); 357093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com SkString modulate; 358093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); 359093bc9ad71adeb7a2a6a2aa3d123e846f2f6f8f4bsalomon@google.com builder->fsCodeAppend(modulate.c_str()); 360bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 361bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 3628bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.comGrGLEffect::EffectKey GrGLMorphologyEffect::GenKey(const GrDrawEffect& drawEffect, 3638bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrGLCaps&) { 3648bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrMorphologyEffect& m = drawEffect.castEffect<GrMorphologyEffect>(); 3659ae086cba571945957b4ea066bf0699862e5ece3bsalomon@google.com EffectKey key = static_cast<EffectKey>(m.radius()); 366bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org key |= (m.type() << 8); 367bc7f7b134d013466fc237434468d758c7d025e99bsalomon@google.com key <<= GrGLEffectMatrix::kKeyBits; 368bc7f7b134d013466fc237434468d758c7d025e99bsalomon@google.com EffectKey matrixKey = GrGLEffectMatrix::GenKey(m.getMatrix(), 3698bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com drawEffect, 3708bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com m.coordsType(), 371bc7f7b134d013466fc237434468d758c7d025e99bsalomon@google.com m.texture(0)); 372bc7f7b134d013466fc237434468d758c7d025e99bsalomon@google.com return key | matrixKey; 373bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 374bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 3758bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.comvoid GrGLMorphologyEffect::setData(const GrGLUniformManager& uman, 3768bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const GrDrawEffect& drawEffect) { 3778bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com const Gr1DKernelEffect& kern = drawEffect.castEffect<Gr1DKernelEffect>(); 3788780f037626b5196962a39ab76afd51f094a7765bsalomon@google.com GrTexture& texture = *kern.texture(0); 379bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org // the code we generated was for a specific kernel radius 380bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrAssert(kern.radius() == fRadius); 381bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org float imageIncrement[2] = { 0 }; 382bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org switch (kern.direction()) { 383bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org case Gr1DKernelEffect::kX_Direction: 384bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org imageIncrement[0] = 1.0f / texture.width(); 385bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org break; 386bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org case Gr1DKernelEffect::kY_Direction: 387bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org imageIncrement[1] = 1.0f / texture.height(); 388bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org break; 389bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org default: 390bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrCrash("Unknown filter direction."); 391bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org } 392bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement); 3938bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com fEffectMatrix.setData(uman, kern.getMatrix(), drawEffect, kern.texture(0)); 394bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 395bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 396bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org/////////////////////////////////////////////////////////////////////////////// 397bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 398bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgGrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, 399bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org Direction direction, 400bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org int radius, 401bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org MorphologyType type) 402bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org : Gr1DKernelEffect(texture, direction, radius) 403bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org , fType(type) { 404bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 405bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 406bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgGrMorphologyEffect::~GrMorphologyEffect() { 407bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 408bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 4091f64de790a624dc250d3da0789b3ada6251facb7bsalomon@google.comconst GrBackendEffectFactory& GrMorphologyEffect::getFactory() const { 4101f64de790a624dc250d3da0789b3ada6251facb7bsalomon@google.com return GrTBackendEffectFactory<GrMorphologyEffect>::getInstance(); 411bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 412bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 4136a2cef0e27af0600fe1afcc0fcda2f3011371be9bsalomon@google.combool GrMorphologyEffect::onIsEqual(const GrEffect& sBase) const { 414ba8399f132a172950b49dec019e910ff681928f6bsalomon@google.com const GrMorphologyEffect& s = CastEffect<GrMorphologyEffect>(sBase); 415c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com return (this->texture(0) == s.texture(0) && 416bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org this->radius() == s.radius() && 417bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org this->direction() == s.direction() && 418bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org this->type() == s.type()); 419bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 420bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 421c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.comvoid GrMorphologyEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { 422c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com // This is valid because the color components of the result of the kernel all come 423c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com // exactly from existing values in the source texture. 424c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com this->updateConstantColorComponentsForModulation(color, validFlags); 425c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com} 426c230a788e0c4339ca1638b79c493055d75ceefc5bsalomon@google.com 427bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org/////////////////////////////////////////////////////////////////////////////// 428bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 4297e0b48a766909be86a2923d909b85c111de4d237bsalomon@google.comGR_DEFINE_EFFECT_TEST(GrMorphologyEffect); 430bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 431f95aaa03702b16aea2251b6f812f7afeae4b8bbebsalomon@google.comGrEffectRef* GrMorphologyEffect::TestCreate(SkMWCRandom* random, 43285f3b52a22c623fc8846d920660fc0b0a4b7afa7sugoi@google.com GrContext*, 433516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com const GrDrawTargetCaps&, 43438b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com GrTexture* textures[]) { 43598b366d6fbbc21f44dfb41fd7fd27ce0a603c12cbsalomon@google.com int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : 43698b366d6fbbc21f44dfb41fd7fd27ce0a603c12cbsalomon@google.com GrEffectUnitTest::kAlphaTextureIdx; 437bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org Direction dir = random->nextBool() ? kX_Direction : kY_Direction; 438bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org static const int kMaxRadius = 10; 439bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org int radius = random->nextRangeU(1, kMaxRadius); 440bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org MorphologyType type = random->nextBool() ? GrMorphologyEffect::kErode_MorphologyType : 441bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrMorphologyEffect::kDilate_MorphologyType; 442bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 44338b58f31a3070ea9254d55894a59528270ac67ddbsalomon@google.com return GrMorphologyEffect::Create(textures[texIdx], dir, radius, type); 444bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 445bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 446bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgnamespace { 447bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 448bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgvoid apply_morphology_pass(GrContext* context, 449bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrTexture* texture, 450868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org const SkIRect& rect, 451bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org int radius, 452bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrMorphologyEffect::MorphologyType morphType, 453bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org Gr1DKernelEffect::Direction direction) { 454bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrPaint paint; 4554de2cfb9a63682aa6624f781a7454956ef6619a7commit-bot@chromium.org paint.addColorEffect(GrMorphologyEffect::Create(texture, 4564de2cfb9a63682aa6624f781a7454956ef6619a7commit-bot@chromium.org direction, 4574de2cfb9a63682aa6624f781a7454956ef6619a7commit-bot@chromium.org radius, 4584de2cfb9a63682aa6624f781a7454956ef6619a7commit-bot@chromium.org morphType))->unref(); 459868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org context->drawRect(paint, SkRect::MakeFromIRect(rect)); 460bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 461bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 462bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.orgGrTexture* apply_morphology(GrTexture* srcTexture, 463868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org const SkIRect& rect, 464bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrMorphologyEffect::MorphologyType morphType, 465bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org SkISize radius) { 466bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrContext* context = srcTexture->getContext(); 467bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org srcTexture->ref(); 4684a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com 4694a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com GrContext::AutoMatrix am; 4704a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com am.setIdentity(context); 4714a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com 472a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org GrContext::AutoClip acs(context, SkRect::MakeWH(SkIntToScalar(srcTexture->width()), 473bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org SkIntToScalar(srcTexture->height()))); 4744a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com 475bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrTextureDesc desc; 476bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 477868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org desc.fWidth = rect.width(); 478868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org desc.fHeight = rect.height(); 479868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org desc.fConfig = kSkia8888_GrPixelConfig; 4804a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com 481bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org if (radius.fWidth > 0) { 482bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrAutoScratchTexture ast(context, desc); 483bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget()); 484bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org apply_morphology_pass(context, srcTexture, rect, radius.fWidth, 485bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org morphType, Gr1DKernelEffect::kX_Direction); 486868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org SkIRect clearRect = SkIRect::MakeXYWH(rect.fLeft, rect.fBottom, 487868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org rect.width(), radius.fHeight); 488bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org context->clear(&clearRect, 0x0); 489bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org srcTexture->unref(); 490bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org srcTexture = ast.detach(); 491bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org } 492bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org if (radius.fHeight > 0) { 493bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrAutoScratchTexture ast(context, desc); 494bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget()); 495bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org apply_morphology_pass(context, srcTexture, rect, radius.fHeight, 496bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org morphType, Gr1DKernelEffect::kY_Direction); 497bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org srcTexture->unref(); 498bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org srcTexture = ast.detach(); 499bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org } 500bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org return srcTexture; 501bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org} 502bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 503bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org}; 504bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org 5056bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.orgbool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, 5066bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.org SkBitmap* result, SkIPoint* offset) { 507868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org SkBitmap inputBM; 5086bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.org if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &inputBM, offset)) { 509868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org return false; 510868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org } 51187816f8e3e4e8633221d6e2c20c2ecdab3b6b6fccommit-bot@chromium.org GrTexture* input = inputBM.getTexture(); 512868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org SkIRect bounds; 513868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org src.getBounds(&bounds); 514868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org SkAutoTUnref<GrTexture> resultTex(apply_morphology(input, bounds, 515868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org GrMorphologyEffect::kDilate_MorphologyType, radius())); 516868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org return SkImageFilterUtils::WrapTexture(resultTex, src.width(), src.height(), result); 5175bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 5185bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 5196bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.orgbool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, 5206bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.org SkBitmap* result, SkIPoint* offset) { 521868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org SkBitmap inputBM; 5226bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.org if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &inputBM, offset)) { 523868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org return false; 524868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org } 52587816f8e3e4e8633221d6e2c20c2ecdab3b6b6fccommit-bot@chromium.org GrTexture* input = inputBM.getTexture(); 526868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org SkIRect bounds; 527868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org src.getBounds(&bounds); 528868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org SkAutoTUnref<GrTexture> resultTex(apply_morphology(input, bounds, 529868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org GrMorphologyEffect::kErode_MorphologyType, radius())); 530868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org return SkImageFilterUtils::WrapTexture(resultTex, src.width(), src.height(), result); 5315bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org} 5325bd4c4bdde0062e3c31d667bfcaf54bb0df5e6d6senorblanco@chromium.org 533bf5364aea54e626e8fd8523608f85081152633f8senorblanco@chromium.org#endif 534