Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / vcl / opengl / shaders / areaScaleFragmentShader.glsl
blob5dab5ba0114d59c2e1fc0bff1fcc397754aa45b9
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  */
10 #version 130
12 uniform sampler2D sampler;
13 uniform int swidth;
14 uniform int sheight;
15 uniform float xscale;
16 uniform float yscale;
17 uniform float xoffset;
18 uniform float yoffset;
19 uniform float xfrompixelratio;
20 uniform float yfrompixelratio;
21 uniform float xtopixelratio;
22 uniform float ytopixelratio;
24 varying vec2 tex_coord;
26 // This mode makes the scaling work like maskedTextureFragmentShader.glsl
27 // (instead of like plain textureVertexShader.glsl).
28 #ifdef MASKED
29 varying vec2 mask_coord;
30 uniform sampler2D mask;
31 #endif
33 #ifdef USE_REDUCED_REGISTER_VARIANT
35 vec4 getTexel(int x, int y)
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;
45 void main(void)
47     // Convert to pixel coordinates again.
48     int dx = int(( tex_coord.s - xoffset ) * xtopixelratio );
49     int dy = int(( tex_coord.t - yoffset ) * ytopixelratio );
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));
55     float fsy1 = min(dy * yscale,   float(sheight - 1));
56     float fsy2 = min(fsy1 + yscale, float(sheight - 1));
58     // To whole pixel coordinates.
59     int xstart = int(floor(fsx1));
60     int xend   = int(floor(fsx2));
62     int ystart = int(floor(fsy1));
63     int yend   = int(floor(fsy2));
65     float xlength = fsx2 - fsx1;
66     float ylength = fsy2 - fsy1;
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;
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;
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);
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];
91         sumAll += sumX * yContribution[0];
92     }
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);
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];
106         sumAll += sumX * yContribution[1];
107     }
109     // Last Y pass
110     {
111         vec4 sumX = vec4(0.0, 0.0, 0.0, 0.0);
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];
120         sumAll += sumX * yContribution[2];
121     }
123     gl_FragColor = sumAll;
125 #else
126 void main(void)
128     // Convert to pixel coordinates again.
129     int dx = int(( tex_coord.s - xoffset ) * xtopixelratio );
130     int dy = int(( tex_coord.t - yoffset ) * ytopixelratio );
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 ];
141     // For finding the first and last source pixel.
142     int xpixel[ 16 + 2 ];
143     int ypixel[ 16 + 2 ];
145     int xpos = 0;
146     int ypos = 0;
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 );
158     // How much one full column contributes to the resulting pixel.
159     float width = min( xscale, swidth - fsx1 );
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     }
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 );
188     float height = min( yscale, sheight - fsy1 );
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     }
209     int xstart = xpixel[ 0 ];
210     int xend = xpixel[ xpos - 1 ];
211     int ystart = ypixel[ 0 ];
212     int yend = ypixel[ ypos - 1 ];
214     vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );
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     }
236     gl_FragColor = sum;
238 #endif
239 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */