1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2/* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 */ 9 10#version 130 11 12uniform sampler2D sampler; 13uniform int swidth; 14uniform int sheight; 15uniform float xscale; 16uniform float yscale; 17uniform float xoffset; 18uniform float yoffset; 19uniform float xfrompixelratio; 20uniform float yfrompixelratio; 21uniform float xtopixelratio; 22uniform float ytopixelratio; 23 24varying vec2 tex_coord; 25 26// This mode makes the scaling work like maskedTextureFragmentShader.glsl 27// (instead of like plain textureVertexShader.glsl). 28#ifdef MASKED 29varying vec2 mask_coord; 30uniform sampler2D mask; 31#endif 32 33#ifdef USE_REDUCED_REGISTER_VARIANT 34 35vec4 getTexel(int x, int y) 36{ 37 vec2 pos = vec2( x * xfrompixelratio + xoffset, y * yfrompixelratio + yoffset ); 38 vec4 texel = texture2D(sampler, pos); 39#ifdef MASKED 40 texel.a = 1.0 - texture2D(mask, pos - tex_coord.st + mask_coord.st).r; 41#endif 42 return texel; 43} 44 45void main(void) 46{ 47 // Convert to pixel coordinates again. 48 int dx = int(( tex_coord.s - xoffset ) * xtopixelratio ); 49 int dy = int(( tex_coord.t - yoffset ) * ytopixelratio ); 50 51 // Compute the range of source pixels which will make up this destination pixel. 52 float fsx1 = min(dx * xscale, float(swidth - 1)); 53 float fsx2 = min(fsx1 + xscale, float(swidth - 1)); 54 55 float fsy1 = min(dy * yscale, float(sheight - 1)); 56 float fsy2 = min(fsy1 + yscale, float(sheight - 1)); 57 58 // To whole pixel coordinates. 59 int xstart = int(floor(fsx1)); 60 int xend = int(floor(fsx2)); 61 62 int ystart = int(floor(fsy1)); 63 int yend = int(floor(fsy2)); 64 65 float xlength = fsx2 - fsx1; 66 float ylength = fsy2 - fsy1; 67 68 float xContribution[3]; 69 xContribution[0] = (1.0 - max(0.0, fsx1 - xstart)) / xlength; 70 xContribution[1] = 1.0 / xlength; 71 xContribution[2] = (1.0 - max(0.0, (xend + 1) - fsx2)) / xlength; 72 73 float yContribution[3]; 74 yContribution[0] = (1.0 - max(0.0, fsy1 - ystart)) / ylength; 75 yContribution[1] = 1.0 / ylength; 76 yContribution[2] = (1.0 - max(0.0, (yend + 1) - fsy2)) / ylength; 77 78 vec4 sumAll = vec4(0.0, 0.0, 0.0, 0.0); 79 vec4 texel; 80 // First Y pass 81 { 82 vec4 sumX = vec4(0.0, 0.0, 0.0, 0.0); 83 84 sumX += getTexel(xstart, ystart) * xContribution[0]; 85 for (int x = xstart + 1; x < xend; ++x) 86 { 87 sumX += getTexel(x, ystart) * xContribution[1]; 88 } 89 sumX += getTexel(xend, ystart) * xContribution[2]; 90 91 sumAll += sumX * yContribution[0]; 92 } 93 94 // Middle Y Passes 95 for (int y = ystart + 1; y < yend; ++y) 96 { 97 vec4 sumX = vec4(0.0, 0.0, 0.0, 0.0); 98 99 sumX += getTexel(xstart, y) * xContribution[0]; 100 for (int x = xstart + 1; x < xend; ++x) 101 { 102 sumX += getTexel(x, y) * xContribution[1]; 103 } 104 sumX += getTexel(xend, y) * xContribution[2]; 105 106 sumAll += sumX * yContribution[1]; 107 } 108 109 // Last Y pass 110 { 111 vec4 sumX = vec4(0.0, 0.0, 0.0, 0.0); 112 113 sumX += getTexel(xstart, yend) * xContribution[0]; 114 for (int x = xstart + 1; x < xend; ++x) 115 { 116 sumX += getTexel(x, yend) * xContribution[1]; 117 } 118 sumX += getTexel(xend, yend) * xContribution[2]; 119 120 sumAll += sumX * yContribution[2]; 121 } 122 123 gl_FragColor = sumAll; 124} 125#else 126void main(void) 127{ 128 // Convert to pixel coordinates again. 129 int dx = int(( tex_coord.s - xoffset ) * xtopixelratio ); 130 int dy = int(( tex_coord.t - yoffset ) * ytopixelratio ); 131 132 // How much each column/row will contribute to the resulting pixel. 133 // Note: These values are always the same for the same X (or Y), 134 // so they could be precalculated in C++ and passed to the shader, 135 // but GLSL has limits on the size of uniforms passed to it, 136 // so it'd need something like texture buffer objects from newer 137 // GLSL versions, and it seems the hassle is not really worth it. 138 float xratio[ 16 + 2 ]; 139 float yratio[ 16 + 2 ]; 140 141 // For finding the first and last source pixel. 142 int xpixel[ 16 + 2 ]; 143 int ypixel[ 16 + 2 ]; 144 145 int xpos = 0; 146 int ypos = 0; 147 148 // Compute the range of source pixels which will make up this destination pixel. 149 float fsx1 = dx * xscale; 150 float fsx2 = fsx1 + xscale; 151 // To whole pixel coordinates. 152 int sx1 = int( ceil( fsx1 ) ); 153 int sx2 = int( floor( fsx2 ) ); 154 // Range checking. 155 sx2 = min( sx2, swidth - 1 ); 156 sx1 = min( sx1, sx2 ); 157 158 // How much one full column contributes to the resulting pixel. 159 float width = min( xscale, swidth - fsx1 ); 160 161 if( sx1 - fsx1 > 0.001 ) 162 { // The first column contributes only partially. 163 xpixel[ xpos ] = sx1 - 1; 164 xratio[ xpos ] = ( sx1 - fsx1 ) / width; 165 ++xpos; 166 } 167 for( int sx = sx1; sx < sx2; ++sx ) 168 { // Columns that fully contribute to the resulting pixel. 169 xpixel[ xpos ] = sx; 170 xratio[ xpos ] = 1.0 / width; 171 ++xpos; 172 } 173 if( fsx2 - sx2 > 0.001 ) 174 { // The last column contributes only partially. 175 xpixel[ xpos ] = sx2; 176 xratio[ xpos ] = min( min( fsx2 - sx2, 1.0 ) / width, 1.0 ); 177 ++xpos; 178 } 179 180 // The same for Y. 181 float fsy1 = dy * yscale; 182 float fsy2 = fsy1 + yscale; 183 int sy1 = int( ceil( fsy1 ) ); 184 int sy2 = int( floor( fsy2 ) ); 185 sy2 = min( sy2, sheight - 1 ); 186 sy1 = min( sy1, sy2 ); 187 188 float height = min( yscale, sheight - fsy1 ); 189 190 if( sy1 - fsy1 > 0.001 ) 191 { 192 ypixel[ ypos ] = sy1 - 1; 193 yratio[ ypos ] = ( sy1 - fsy1 ) / height; 194 ++ypos; 195 } 196 for( int sy = sy1; sy < sy2; ++sy ) 197 { 198 ypixel[ ypos ] = sy; 199 yratio[ ypos ] = 1.0 / height; 200 ++ypos; 201 } 202 if( fsy2 - sy2 > 0.001 ) 203 { 204 ypixel[ ypos ] = sy2; 205 yratio[ ypos ] = min( min( fsy2 - sy2, 1.0 ) / height, 1.0 ); 206 ++ypos; 207 } 208 209 int xstart = xpixel[ 0 ]; 210 int xend = xpixel[ xpos - 1 ]; 211 int ystart = ypixel[ 0 ]; 212 int yend = ypixel[ ypos - 1 ]; 213 214 vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 ); 215 216 ypos = 0; 217 for( int y = ystart; y <= yend; ++y, ++ypos ) 218 { 219 vec4 tmp = vec4( 0.0, 0.0, 0.0, 0.0 ); 220 xpos = 0; 221 for( int x = xstart; x <= xend; ++x, ++xpos ) 222 { 223 vec2 pos = vec2( x * xfrompixelratio + xoffset, y * yfrompixelratio + yoffset ); 224#ifndef MASKED 225 tmp += texture2D( sampler, pos ) * xratio[ xpos ]; 226#else 227 vec4 texel; 228 texel = texture2D( sampler, pos ); 229 texel.a = 1.0 - texture2D( mask, pos - tex_coord.st + mask_coord.st ).r; 230 tmp += texel * xratio[ xpos ]; 231#endif 232 } 233 sum += tmp * yratio[ ypos ]; 234 } 235 236 gl_FragColor = sum; 237} 238#endif 239/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 240