areaScaleFragmentShader.glsl 6.8 KB

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