182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com/* 282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com * Copyright 2012 The Android Open Source Project 382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com * 482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com * found in the LICENSE file. 682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com */ 782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "SkBitmap.h" 982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "SkMagnifierImageFilter.h" 1082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "SkColorPriv.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 13c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h" 1482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 1603245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#if SK_SUPPORT_GPU 1782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "effects/GrSingleTextureEffect.h" 18b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h" 1930ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h" 2082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "gl/GrGLSL.h" 2182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com#include "gl/GrGLTexture.h" 22b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 2382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comclass GrGLMagnifierEffect; 2582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comclass GrMagnifierEffect : public GrSingleTextureEffect { 2782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.compublic: 29b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrFragmentProcessor* Create(GrTexture* texture, 30b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float xOffset, 31b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float yOffset, 32b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float xInvZoom, 33b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float yInvZoom, 34b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float xInvInset, 35b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt float yInvInset) { 3655fad7af61c21d502acb9891d631e8aa29e3628cbsalomon return SkNEW_ARGS(GrMagnifierEffect, (texture, 3755fad7af61c21d502acb9891d631e8aa29e3628cbsalomon xOffset, 3855fad7af61c21d502acb9891d631e8aa29e3628cbsalomon yOffset, 3955fad7af61c21d502acb9891d631e8aa29e3628cbsalomon xInvZoom, 4055fad7af61c21d502acb9891d631e8aa29e3628cbsalomon yInvZoom, 4155fad7af61c21d502acb9891d631e8aa29e3628cbsalomon xInvInset, 4255fad7af61c21d502acb9891d631e8aa29e3628cbsalomon yInvInset)); 430ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com } 4482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 4582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com virtual ~GrMagnifierEffect() {}; 4682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 4782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com static const char* Name() { return "Magnifier"; } 4882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 49b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE; 5068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 5182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 5282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float x_offset() const { return fXOffset; } 5382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float y_offset() const { return fYOffset; } 54f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float x_inv_zoom() const { return fXInvZoom; } 55f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float y_inv_zoom() const { return fYInvZoom; } 56f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float x_inv_inset() const { return fXInvInset; } 57f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float y_inv_inset() const { return fYInvInset; } 5882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 59b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLMagnifierEffect GLProcessor; 6082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 6182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comprivate: 620ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com GrMagnifierEffect(GrTexture* texture, 630ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com float xOffset, 640ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com float yOffset, 65f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float xInvZoom, 66f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float yInvZoom, 67f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float xInvInset, 68f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float yInvInset) 696267f81f3d60ce144ab2b09ea369420984d5c9d9bsalomon : GrSingleTextureEffect(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) 700ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com , fXOffset(xOffset) 710ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com , fYOffset(yOffset) 72f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org , fXInvZoom(xInvZoom) 73f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org , fYInvZoom(yInvZoom) 74f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org , fXInvInset(xInvInset) 75f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org , fYInvInset(yInvInset) {} 760ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 77b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE; 7868b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com 79b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 8082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 8182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fXOffset; 8282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float fYOffset; 83f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fXInvZoom; 84f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fYInvZoom; 85f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fXInvInset; 86f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org float fYInvInset; 8782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 8882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com typedef GrSingleTextureEffect INHERITED; 8982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com}; 9082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 9182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com// For brevity 927510b224e52b9518a8ddf7418db0e9c258f79539kkinnunentypedef GrGLProgramDataManager::UniformHandle UniformHandle; 9382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 94b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLMagnifierEffect : public GrGLFragmentProcessor { 9582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.compublic: 96b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrGLMagnifierEffect(const GrBackendProcessorFactory&, const GrProcessor&); 9782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 9830ba436f04e61d4505fb854d5fc56079636e0788joshualitt virtual void emitCode(GrGLProgramBuilder*, 99b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 100b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey&, 10147d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com const char* outputColor, 10247d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com const char* inputColor, 10377af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray&, 10447d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com const TextureSamplerArray&) SK_OVERRIDE; 10582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 106b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE; 10782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 10882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.comprivate: 10917fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com UniformHandle fOffsetVar; 110f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org UniformHandle fInvZoomVar; 111f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org UniformHandle fInvInsetVar; 11217fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com 113b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLFragmentProcessor INHERITED; 11482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com}; 11582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 116b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLMagnifierEffect::GrGLMagnifierEffect(const GrBackendProcessorFactory& factory, 117b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor&) 11877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com : INHERITED(factory) { 11982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 12082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 12130ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLMagnifierEffect::emitCode(GrGLProgramBuilder* builder, 122b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor&, 123b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey& key, 12447d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com const char* outputColor, 12547d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com const char* inputColor, 12677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com const TransformedCoordsArray& coords, 12747d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com const TextureSamplerArray& samplers) { 12847d7a8885b02478fa41069f14bba7ffbe5475d87bsalomon@google.com fOffsetVar = builder->addUniform( 12930ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLProgramBuilder::kFragment_Visibility | 13030ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLProgramBuilder::kVertex_Visibility, 131f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org kVec2f_GrSLType, "Offset"); 132f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org fInvZoomVar = builder->addUniform( 13330ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLProgramBuilder::kFragment_Visibility | 13430ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLProgramBuilder::kVertex_Visibility, 135f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org kVec2f_GrSLType, "InvZoom"); 136f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org fInvInsetVar = builder->addUniform( 13730ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLProgramBuilder::kFragment_Visibility | 13830ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLProgramBuilder::kVertex_Visibility, 139f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org kVec2f_GrSLType, "InvInset"); 14082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 14130ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 14230ba436f04e61d4505fb854d5fc56079636e0788joshualitt SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); 14330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); 14430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n", 145f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com builder->getUniformCStr(fOffsetVar), 14677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com coords2D.c_str(), 147f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org builder->getUniformCStr(fInvZoomVar)); 148f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com 14930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\tvec2 delta = min(coord, vec2(1.0, 1.0) - coord);\n"); 150f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com 15130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(fInvInsetVar)); 152f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com 15330ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\tfloat weight = 0.0;\n"); 15430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); 15530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); 15630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n"); 15730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); 15830ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); 15930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\t} else {\n"); 16030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\t\tvec2 delta_squared = delta * delta;\n"); 16130ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n"); 16230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\t}\n"); 163f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com 16430ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n"); 16530ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend("\t\tvec4 output_color = "); 16630ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->appendTextureLookup(samplers[0], "mix_coord"); 16730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(";\n"); 168f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com 16930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\t%s = output_color;", outputColor); 170f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com SkString modulate; 171f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); 17230ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppend(modulate.c_str()); 17382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 17482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 1757510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLMagnifierEffect::setData(const GrGLProgramDataManager& pdman, 176b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor& effect) { 17749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrMagnifierEffect& zoom = effect.cast<GrMagnifierEffect>(); 1787510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fOffsetVar, zoom.x_offset(), zoom.y_offset()); 1797510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fInvZoomVar, zoom.x_inv_zoom(), zoom.y_inv_zoom()); 1807510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen pdman.set2f(fInvInsetVar, zoom.x_inv_inset(), zoom.y_inv_inset()); 18182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 18282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 18382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com///////////////////////////////////////////////////////////////////// 18482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 185b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrMagnifierEffect); 18682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 187b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrMagnifierEffect::TestCreate(SkRandom* random, 188b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext* context, 189b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 190b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture** textures) { 1911aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org GrTexture* texture = textures[0]; 19282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxWidth = 200; 19382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxHeight = 200; 19482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com const int kMaxInset = 20; 1955d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com uint32_t width = random->nextULessThan(kMaxWidth); 1965d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com uint32_t height = random->nextULessThan(kMaxHeight); 1975d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com uint32_t x = random->nextULessThan(kMaxWidth - width); 1985d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com uint32_t y = random->nextULessThan(kMaxHeight - height); 1991aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org uint32_t inset = random->nextULessThan(kMaxInset); 2001aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org 201b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrFragmentProcessor* effect = GrMagnifierEffect::Create( 2021aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org texture, 2031aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org (float) width / texture->width(), 2041aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org (float) height / texture->height(), 2051aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org texture->width() / (float) x, 2061aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org texture->height() / (float) y, 2071aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org (float) inset / texture->width(), 2081aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org (float) inset / texture->height()); 20949f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(effect); 210021fc736f89fddac4f26b3f32f50263ff8fe3279bsalomon@google.com return effect; 21182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 21282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 21382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 21482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 215b0a8a377f832c59cee939ad721e1f87d378b7142joshualittconst GrBackendFragmentProcessorFactory& GrMagnifierEffect::getFactory() const { 216b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return GrTBackendFragmentProcessorFactory<GrMagnifierEffect>::getInstance(); 21782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 21882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 219b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrMagnifierEffect::onIsEqual(const GrProcessor& sBase) const { 22049586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt const GrMagnifierEffect& s = sBase.cast<GrMagnifierEffect>(); 22168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com return (this->texture(0) == s.texture(0) && 22268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com this->fXOffset == s.fXOffset && 22382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->fYOffset == s.fYOffset && 224f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fXInvZoom == s.fXInvZoom && 225f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fYInvZoom == s.fYInvZoom && 226f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fXInvInset == s.fXInvInset && 227f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org this->fYInvInset == s.fYInvInset); 22882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 22982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 23068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.comvoid GrMagnifierEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { 23168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com this->updateConstantColorComponentsForModulation(color, validFlags); 23268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com} 23368b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com 23403245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#endif 23503245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com 23682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 2379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkMagnifierImageFilter::Create(const SkRect& srcRect, SkScalar inset, 2399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkImageFilter* input) { 2409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!SkScalarIsFinite(inset) || !SkIsValidRect(srcRect)) { 2429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 2439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 2449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed // Negative numbers in src rect are not supported 2459fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (srcRect.fLeft < 0 || srcRect.fTop < 0) { 2469fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return NULL; 2479fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 2489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return SkNEW_ARGS(SkMagnifierImageFilter, (srcRect, inset, input)); 2499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 2509fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 2529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 2538b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkMagnifierImageFilter::SkMagnifierImageFilter(SkReadBuffer& buffer) 254ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org : INHERITED(1, buffer) { 25582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float x = buffer.readScalar(); 25682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float y = buffer.readScalar(); 25782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float width = buffer.readScalar(); 25882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com float height = buffer.readScalar(); 25982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com fSrcRect = SkRect::MakeXYWH(x, y, width, height); 26082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com fInset = buffer.readScalar(); 261c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org 262cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org buffer.validate(SkScalarIsFinite(fInset) && SkIsValidRect(fSrcRect) && 263cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org // Negative numbers in src rect are not supported 264cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org (fSrcRect.fLeft >= 0) && (fSrcRect.fTop >= 0)); 26582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 2669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif 26782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2689ea3d57fde28a5fe4487a111dc3dd49418235e5esenorblancoSkMagnifierImageFilter::SkMagnifierImageFilter(const SkRect& srcRect, SkScalar inset, 2699ea3d57fde28a5fe4487a111dc3dd49418235e5esenorblanco SkImageFilter* input) 2709ea3d57fde28a5fe4487a111dc3dd49418235e5esenorblanco : INHERITED(1, &input), fSrcRect(srcRect), fInset(inset) { 27182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0); 27282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 27382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 27403245700d6f1c5db903a2b9ea34e6cc0ce34a185bsalomon@google.com#if SK_SUPPORT_GPU 275b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkMagnifierImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, GrTexture* texture, 276b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const SkMatrix&, const SkIRect&) const { 277b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (fp) { 278f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org SkScalar yOffset = (texture->origin() == kTopLeft_GrSurfaceOrigin) ? fSrcRect.y() : 279f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org (texture->height() - (fSrcRect.y() + fSrcRect.height())); 280f642f8cf90c8fd4111094026a1a9e9fdc92be9c3commit-bot@chromium.org SkScalar invInset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; 281b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt *fp = GrMagnifierEffect::Create(texture, 282b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fSrcRect.x() / texture->width(), 283b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt yOffset / texture->height(), 284b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fSrcRect.width() / texture->width(), 285b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fSrcRect.height() / texture->height(), 286b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt texture->width() * invInset, 287b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt texture->height() * invInset); 28882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 28982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return true; 29082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 291d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif 29282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 2939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkMagnifierImageFilter::CreateProc(SkReadBuffer& buffer) { 2949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 2959fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkRect src; 2969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&src); 2979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return Create(src, buffer.readScalar(), common.getInput(0)); 2989fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 2999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 3008b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkMagnifierImageFilter::flatten(SkWriteBuffer& buffer) const { 30182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com this->INHERITED::flatten(buffer); 3029fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.writeRect(fSrcRect); 30382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com buffer.writeScalar(fInset); 30482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 30582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 30682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.combool SkMagnifierImageFilter::onFilterImage(Proxy*, const SkBitmap& src, 3074cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org const Context&, SkBitmap* dst, 308ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org SkIPoint* offset) const { 30928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org SkASSERT(src.colorType() == kN32_SkColorType); 31082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(fSrcRect.width() < src.width()); 31182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(fSrcRect.height() < src.height()); 31282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 31328fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org if ((src.colorType() != kN32_SkColorType) || 314cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org (fSrcRect.width() >= src.width()) || 315cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org (fSrcRect.height() >= src.height())) { 31682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return false; 31782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 31882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 31982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkAutoLockPixels alp(src); 32082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkASSERT(src.getPixels()); 32182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) { 32282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return false; 32382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 32482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 325848250415eddc54075f7eb8795e8db79e749c6abreed if (!dst->tryAllocPixels(src.info())) { 326cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org return false; 327cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org } 328cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org 3295d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_inset = fInset > 0 ? SkScalarInvert(fInset) : SK_Scalar1; 33082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 3315d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_x_zoom = fSrcRect.width() / src.width(); 3325d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar inv_y_zoom = fSrcRect.height() / src.height(); 33382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 33482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkColor* sptr = src.getAddr32(0, 0); 33582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com SkColor* dptr = dst->getAddr32(0, 0); 33682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com int width = src.width(), height = src.height(); 33782aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com for (int y = 0; y < height; ++y) { 33882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com for (int x = 0; x < width; ++x) { 3395d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar x_dist = SkMin32(x, width - x - 1) * inv_inset; 3405d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar y_dist = SkMin32(y, height - y - 1) * inv_inset; 3415d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar weight = 0; 3425d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com 3435d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com static const SkScalar kScalar2 = SkScalar(2); 34482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 34582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com // To create a smooth curve at the corners, we need to work on 34682aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com // a square twice the size of the inset. 3475d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com if (x_dist < kScalar2 && y_dist < kScalar2) { 3485d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com x_dist = kScalar2 - x_dist; 3495d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com y_dist = kScalar2 - y_dist; 3505d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com 3515d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar dist = SkScalarSqrt(SkScalarSquare(x_dist) + 3525d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalarSquare(y_dist)); 3535d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com dist = SkMaxScalar(kScalar2 - dist, 0); 3545d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com weight = SkMinScalar(SkScalarSquare(dist), SK_Scalar1); 35582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } else { 3565d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar sqDist = SkMinScalar(SkScalarSquare(x_dist), 3575d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalarSquare(y_dist)); 3585d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com weight = SkMinScalar(sqDist, SK_Scalar1); 35982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 36082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 3615d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar x_interp = SkScalarMul(weight, (fSrcRect.x() + x * inv_x_zoom)) + 3625d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com (SK_Scalar1 - weight) * x; 3635d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com SkScalar y_interp = SkScalarMul(weight, (fSrcRect.y() + y * inv_y_zoom)) + 3645d8d18651a64f62dbb8881794e23f53bf22c9a23robertphillips@google.com (SK_Scalar1 - weight) * y; 36582aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 366cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org int x_val = SkPin32(SkScalarFloorToInt(x_interp), 0, width - 1); 367cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org int y_val = SkPin32(SkScalarFloorToInt(y_interp), 0, height - 1); 36882aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com 36982aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com *dptr = sptr[y_val * width + x_val]; 37082aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com dptr++; 37182aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 37282aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com } 37382aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com return true; 37482aa7482cbf55ce6d42c692550cadee5e23146e4bsalomon@google.com} 375