1/*
2   Hyllian's xBR-vertex code and texel mapping
3
4   Copyright (C) 2011/2016 Hyllian - sergiogdb@gmail.com
5
6   Permission is hereby granted, free of charge, to any person obtaining a copy
7   of this software and associated documentation files (the "Software"), to deal
8   in the Software without restriction, including without limitation the rights
9   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10   copies of the Software, and to permit persons to whom the Software is
11   furnished to do so, subject to the following conditions:
12
13   The above copyright notice and this permission notice shall be included in
14   all copies or substantial portions of the Software.
15
16   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22   THE SOFTWARE.
23
24*/
25
26// This shader also uses code and/or concepts from xBRZ as it appears
27// in the Desmume source code. The license for which is as follows:
28
29// ****************************************************************************
30// * This file is part of the HqMAME project. It is distributed under         *
31// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0          *
32// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved          *
33// *                                                                          *
34// * Additionally and as a special exception, the author gives permission     *
35// * to link the code of this program with the MAME library (or with modified *
36// * versions of MAME that use the same license as MAME), and distribute      *
37// * linked combinations including the two. You must obey the GNU General     *
38// * Public License in all respects for all of the code used other than MAME. *
39// * If you modify this file, you may extend this exception to your version   *
40// * of the file, but you are not obligated to do so. If you do not wish to   *
41// * do so, delete this exception statement from your version.                *
42// ****************************************************************************
43
44#define BLEND_NONE 0
45#define BLEND_NORMAL 1
46#define BLEND_DOMINANT 2
47#define LUMINANCE_WEIGHT 1.0
48#define EQUAL_COLOR_TOLERANCE 30.0/255.0
49#define STEEP_DIRECTION_THRESHOLD 2.2
50#define DOMINANT_DIRECTION_THRESHOLD 3.6
51
52#if defined(VERTEX)
53
54#if __VERSION__ >= 130
55#define COMPAT_VARYING out
56#define COMPAT_ATTRIBUTE in
57#define COMPAT_TEXTURE texture
58#else
59#define COMPAT_VARYING varying
60#define COMPAT_ATTRIBUTE attribute
61#define COMPAT_TEXTURE texture2D
62#endif
63
64#ifdef GL_ES
65#define COMPAT_PRECISION mediump
66#else
67#define COMPAT_PRECISION
68#endif
69
70COMPAT_ATTRIBUTE vec4 VertexCoord;
71COMPAT_ATTRIBUTE vec4 COLOR;
72COMPAT_ATTRIBUTE vec4 TexCoord;
73COMPAT_VARYING vec4 COL0;
74COMPAT_VARYING vec4 TEX0;
75COMPAT_VARYING vec4 t1;
76COMPAT_VARYING vec4 t2;
77COMPAT_VARYING vec4 t3;
78COMPAT_VARYING vec4 t4;
79COMPAT_VARYING vec4 t5;
80COMPAT_VARYING vec4 t6;
81COMPAT_VARYING vec4 t7;
82
83uniform mat4 MVPMatrix;
84uniform COMPAT_PRECISION int FrameDirection;
85uniform COMPAT_PRECISION int FrameCount;
86uniform COMPAT_PRECISION vec2 OutputSize;
87uniform COMPAT_PRECISION vec2 TextureSize;
88uniform COMPAT_PRECISION vec2 InputSize;
89
90// vertex compatibility #defines
91#define vTexCoord TEX0.xy
92#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
93#define outsize vec4(OutputSize, 1.0 / OutputSize)
94
95void main()
96{
97    gl_Position = MVPMatrix * VertexCoord;
98    COL0 = COLOR;
99    TEX0.xy = TexCoord.xy;
100	vec2 ps = vec2(SourceSize.z, SourceSize.w);
101	float dx = ps.x;
102	float dy = ps.y;
103
104	 //  A1 B1 C1
105	// A0 A  B  C C4
106	// D0 D  E  F F4
107	// G0 G  H  I I4
108	 //  G5 H5 I5
109
110	t1 = vTexCoord.xxxy + vec4( -dx, 0.0, dx,-2.0*dy); // A1 B1 C1
111	t2 = vTexCoord.xxxy + vec4( -dx, 0.0, dx, -dy);    //  A  B  C
112	t3 = vTexCoord.xxxy + vec4( -dx, 0.0, dx, 0.0);    //  D  E  F
113	t4 = vTexCoord.xxxy + vec4( -dx, 0.0, dx, dy);     //  G  H  I
114	t5 = vTexCoord.xxxy + vec4( -dx, 0.0, dx, 2.0*dy); // G5 H5 I5
115	t6 = vTexCoord.xyyy + vec4(-2.0*dx,-dy, 0.0, dy);  // A0 D0 G0
116	t7 = vTexCoord.xyyy + vec4( 2.0*dx,-dy, 0.0, dy);  // C4 F4 I4
117}
118
119#elif defined(FRAGMENT)
120
121#if __VERSION__ >= 130
122#define COMPAT_VARYING in
123#define COMPAT_TEXTURE texture
124out vec4 FragColor;
125#else
126#define COMPAT_VARYING varying
127#define FragColor gl_FragColor
128#define COMPAT_TEXTURE texture2D
129#endif
130
131#ifdef GL_ES
132#ifdef GL_FRAGMENT_PRECISION_HIGH
133precision highp float;
134#else
135precision mediump float;
136#endif
137#define COMPAT_PRECISION mediump
138#else
139#define COMPAT_PRECISION
140#endif
141
142uniform COMPAT_PRECISION int FrameDirection;
143uniform COMPAT_PRECISION int FrameCount;
144uniform COMPAT_PRECISION vec2 OutputSize;
145uniform COMPAT_PRECISION vec2 TextureSize;
146uniform COMPAT_PRECISION vec2 InputSize;
147uniform sampler2D Texture;
148COMPAT_VARYING vec4 TEX0;
149COMPAT_VARYING vec4 t1;
150COMPAT_VARYING vec4 t2;
151COMPAT_VARYING vec4 t3;
152COMPAT_VARYING vec4 t4;
153COMPAT_VARYING vec4 t5;
154COMPAT_VARYING vec4 t6;
155COMPAT_VARYING vec4 t7;
156
157// fragment compatibility #defines
158#define Source Texture
159#define vTexCoord TEX0.xy
160
161#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
162#define outsize vec4(OutputSize, 1.0 / OutputSize)
163
164	const float  one_sixth = 1.0 / 6.0;
165	const float  two_sixth = 2.0 / 6.0;
166	const float four_sixth = 4.0 / 6.0;
167	const float five_sixth = 5.0 / 6.0;
168
169	float reduce(const vec3 color)
170	{
171		return dot(color, vec3(65536.0, 256.0, 1.0));
172	}
173
174	float DistYCbCr(const vec3 pixA, const vec3 pixB)
175	{
176		const vec3 w = vec3(0.2627, 0.6780, 0.0593);
177		const float scaleB = 0.5 / (1.0 - w.b);
178		const float scaleR = 0.5 / (1.0 - w.r);
179		vec3 diff = pixA - pixB;
180		float Y = dot(diff, w);
181		float Cb = scaleB * (diff.b - Y);
182		float Cr = scaleR * (diff.r - Y);
183
184		return sqrt( ((LUMINANCE_WEIGHT * Y) * (LUMINANCE_WEIGHT * Y)) + (Cb * Cb) + (Cr * Cr) );
185	}
186
187	bool IsPixEqual(const vec3 pixA, const vec3 pixB)
188	{
189		return (DistYCbCr(pixA, pixB) < EQUAL_COLOR_TOLERANCE);
190	}
191
192	bool IsBlendingNeeded(const ivec4 blend)
193	{
194		return any(notEqual(blend, ivec4(BLEND_NONE)));
195	}
196
197	//---------------------------------------
198	// Input Pixel Mapping:    --|21|22|23|--
199	//                         19|06|07|08|09
200	//                         18|05|00|01|10
201	//                         17|04|03|02|11
202	//                         --|15|14|13|--
203	//
204	// Output Pixel Mapping: 20|21|22|23|24|25
205	//                       19|06|07|08|09|26
206	//                       18|05|00|01|10|27
207	//                       17|04|03|02|11|28
208	//                       16|15|14|13|12|29
209	//                       35|34|33|32|31|30
210
211void main()
212{
213vec2 f = fract(vTexCoord.xy * SourceSize.xy);
214
215	//---------------------------------------
216	// Input Pixel Mapping:  20|21|22|23|24
217	//                       19|06|07|08|09
218	//                       18|05|00|01|10
219	//                       17|04|03|02|11
220	//                       16|15|14|13|12
221
222	vec3 src[25];
223
224	src[21] = COMPAT_TEXTURE(Source, t1.xw).rgb;
225	src[22] = COMPAT_TEXTURE(Source, t1.yw).rgb;
226	src[23] = COMPAT_TEXTURE(Source, t1.zw).rgb;
227	src[ 6] = COMPAT_TEXTURE(Source, t2.xw).rgb;
228	src[ 7] = COMPAT_TEXTURE(Source, t2.yw).rgb;
229	src[ 8] = COMPAT_TEXTURE(Source, t2.zw).rgb;
230	src[ 5] = COMPAT_TEXTURE(Source, t3.xw).rgb;
231	src[ 0] = COMPAT_TEXTURE(Source, t3.yw).rgb;
232	src[ 1] = COMPAT_TEXTURE(Source, t3.zw).rgb;
233	src[ 4] = COMPAT_TEXTURE(Source, t4.xw).rgb;
234	src[ 3] = COMPAT_TEXTURE(Source, t4.yw).rgb;
235	src[ 2] = COMPAT_TEXTURE(Source, t4.zw).rgb;
236	src[15] = COMPAT_TEXTURE(Source, t5.xw).rgb;
237	src[14] = COMPAT_TEXTURE(Source, t5.yw).rgb;
238	src[13] = COMPAT_TEXTURE(Source, t5.zw).rgb;
239	src[19] = COMPAT_TEXTURE(Source, t6.xy).rgb;
240	src[18] = COMPAT_TEXTURE(Source, t6.xz).rgb;
241	src[17] = COMPAT_TEXTURE(Source, t6.xw).rgb;
242	src[ 9] = COMPAT_TEXTURE(Source, t7.xy).rgb;
243	src[10] = COMPAT_TEXTURE(Source, t7.xz).rgb;
244	src[11] = COMPAT_TEXTURE(Source, t7.xw).rgb;
245
246		float v[9];
247		v[0] = reduce(src[0]);
248		v[1] = reduce(src[1]);
249		v[2] = reduce(src[2]);
250		v[3] = reduce(src[3]);
251		v[4] = reduce(src[4]);
252		v[5] = reduce(src[5]);
253		v[6] = reduce(src[6]);
254		v[7] = reduce(src[7]);
255		v[8] = reduce(src[8]);
256
257		ivec4 blendResult = ivec4(BLEND_NONE);
258
259		// Preprocess corners
260		// Pixel Tap Mapping: --|--|--|--|--
261		//                    --|--|07|08|--
262		//                    --|05|00|01|10
263		//                    --|04|03|02|11
264		//                    --|--|14|13|--
265		// Corner (1, 1)
266		if ( ((v[0] == v[1] && v[3] == v[2]) || (v[0] == v[3] && v[1] == v[2])) == false)
267		{
268			float dist_03_01 = DistYCbCr(src[ 4], src[ 0]) + DistYCbCr(src[ 0], src[ 8]) + DistYCbCr(src[14], src[ 2]) + DistYCbCr(src[ 2], src[10]) + (4.0 * DistYCbCr(src[ 3], src[ 1]));
269			float dist_00_02 = DistYCbCr(src[ 5], src[ 3]) + DistYCbCr(src[ 3], src[13]) + DistYCbCr(src[ 7], src[ 1]) + DistYCbCr(src[ 1], src[11]) + (4.0 * DistYCbCr(src[ 0], src[ 2]));
270			bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_03_01) < dist_00_02;
271			blendResult[2] = ((dist_03_01 < dist_00_02) && (v[0] != v[1]) && (v[0] != v[3])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
272		}
273
274		// Pixel Tap Mapping: --|--|--|--|--
275		//                    --|06|07|--|--
276		//                    18|05|00|01|--
277		//                    17|04|03|02|--
278		//                    --|15|14|--|--
279		// Corner (0, 1)
280		if ( ((v[5] == v[0] && v[4] == v[3]) || (v[5] == v[4] && v[0] == v[3])) == false)
281		{
282			float dist_04_00 = DistYCbCr(src[17], src[ 5]) + DistYCbCr(src[ 5], src[ 7]) + DistYCbCr(src[15], src[ 3]) + DistYCbCr(src[ 3], src[ 1]) + (4.0 * DistYCbCr(src[ 4], src[ 0]));
283			float dist_05_03 = DistYCbCr(src[18], src[ 4]) + DistYCbCr(src[ 4], src[14]) + DistYCbCr(src[ 6], src[ 0]) + DistYCbCr(src[ 0], src[ 2]) + (4.0 * DistYCbCr(src[ 5], src[ 3]));
284			bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_05_03) < dist_04_00;
285			blendResult[3] = ((dist_04_00 > dist_05_03) && (v[0] != v[5]) && (v[0] != v[3])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
286		}
287
288		// Pixel Tap Mapping: --|--|22|23|--
289		//                    --|06|07|08|09
290		//                    --|05|00|01|10
291		//                    --|--|03|02|--
292		//                    --|--|--|--|--
293		// Corner (1, 0)
294		if ( ((v[7] == v[8] && v[0] == v[1]) || (v[7] == v[0] && v[8] == v[1])) == false)
295		{
296			float dist_00_08 = DistYCbCr(src[ 5], src[ 7]) + DistYCbCr(src[ 7], src[23]) + DistYCbCr(src[ 3], src[ 1]) + DistYCbCr(src[ 1], src[ 9]) + (4.0 * DistYCbCr(src[ 0], src[ 8]));
297			float dist_07_01 = DistYCbCr(src[ 6], src[ 0]) + DistYCbCr(src[ 0], src[ 2]) + DistYCbCr(src[22], src[ 8]) + DistYCbCr(src[ 8], src[10]) + (4.0 * DistYCbCr(src[ 7], src[ 1]));
298			bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_07_01) < dist_00_08;
299			blendResult[1] = ((dist_00_08 > dist_07_01) && (v[0] != v[7]) && (v[0] != v[1])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
300		}
301
302		// Pixel Tap Mapping: --|21|22|--|--
303		//                    19|06|07|08|--
304		//                    18|05|00|01|--
305		//                    --|04|03|--|--
306		//                    --|--|--|--|--
307		// Corner (0, 0)
308		if ( ((v[6] == v[7] && v[5] == v[0]) || (v[6] == v[5] && v[7] == v[0])) == false)
309		{
310			float dist_05_07 = DistYCbCr(src[18], src[ 6]) + DistYCbCr(src[ 6], src[22]) + DistYCbCr(src[ 4], src[ 0]) + DistYCbCr(src[ 0], src[ 8]) + (4.0 * DistYCbCr(src[ 5], src[ 7]));
311			float dist_06_00 = DistYCbCr(src[19], src[ 5]) + DistYCbCr(src[ 5], src[ 3]) + DistYCbCr(src[21], src[ 7]) + DistYCbCr(src[ 7], src[ 1]) + (4.0 * DistYCbCr(src[ 6], src[ 0]));
312			bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_05_07) < dist_06_00;
313			blendResult[0] = ((dist_05_07 < dist_06_00) && (v[0] != v[5]) && (v[0] != v[7])) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
314		}
315
316		vec3 dst[36];
317		dst[ 0] = src[0];
318		dst[ 1] = src[0];
319		dst[ 2] = src[0];
320		dst[ 3] = src[0];
321		dst[ 4] = src[0];
322		dst[ 5] = src[0];
323		dst[ 6] = src[0];
324		dst[ 7] = src[0];
325		dst[ 8] = src[0];
326		dst[ 9] = src[0];
327		dst[10] = src[0];
328		dst[11] = src[0];
329		dst[12] = src[0];
330		dst[13] = src[0];
331		dst[14] = src[0];
332		dst[15] = src[0];
333		dst[16] = src[0];
334		dst[17] = src[0];
335		dst[18] = src[0];
336		dst[19] = src[0];
337		dst[20] = src[0];
338		dst[21] = src[0];
339		dst[22] = src[0];
340		dst[23] = src[0];
341		dst[24] = src[0];
342		dst[25] = src[0];
343		dst[26] = src[0];
344		dst[27] = src[0];
345		dst[28] = src[0];
346		dst[29] = src[0];
347		dst[30] = src[0];
348		dst[31] = src[0];
349		dst[32] = src[0];
350		dst[33] = src[0];
351		dst[34] = src[0];
352		dst[35] = src[0];
353
354		// Scale pixel
355		if (IsBlendingNeeded(blendResult) == true)
356		{
357			float dist_01_04 = DistYCbCr(src[1], src[4]);
358			float dist_03_08 = DistYCbCr(src[3], src[8]);
359			bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[4]) && (v[5] != v[4]);
360			bool haveSteepLine   = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[8]) && (v[7] != v[8]);
361			bool needBlend = (blendResult[2] != BLEND_NONE);
362			bool doLineBlend = (  blendResult[2] >= BLEND_DOMINANT ||
363							   ((blendResult[1] != BLEND_NONE && !IsPixEqual(src[0], src[4])) ||
364								 (blendResult[3] != BLEND_NONE && !IsPixEqual(src[0], src[8])) ||
365								 (IsPixEqual(src[4], src[3]) && IsPixEqual(src[3], src[2]) && IsPixEqual(src[2], src[1]) && IsPixEqual(src[1], src[8]) && IsPixEqual(src[0], src[2]) == false) ) == false );
366
367			vec3 blendPix = ( DistYCbCr(src[0], src[1]) <= DistYCbCr(src[0], src[3]) ) ? src[1] : src[3];
368			dst[10] = mix(dst[10], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.250 : 0.000);
369			dst[11] = mix(dst[11], blendPix, (needBlend && doLineBlend) ? ((haveSteepLine) ? 0.750 : ((haveShallowLine) ? 0.250 : 0.000)) : 0.000);
370			dst[12] = mix(dst[12], blendPix, (needBlend && doLineBlend) ? ((!haveShallowLine && !haveSteepLine) ? 0.500 : 1.000) : 0.000);
371			dst[13] = mix(dst[13], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? 0.750 : ((haveSteepLine) ? 0.250 : 0.000)) : 0.000);
372			dst[14] = mix(dst[14], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.250 : 0.000);
373			dst[25] = mix(dst[25], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.250 : 0.000);
374			dst[26] = mix(dst[26], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.750 : 0.000);
375			dst[27] = mix(dst[27], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 1.000 : 0.000);
376			dst[28] = mix(dst[28], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.000 : ((haveShallowLine) ? 0.750 : 0.500)) : 0.05652034508) : 0.000);
377			dst[29] = mix(dst[29], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.4236372243) : 0.000);
378			dst[30] = mix(dst[30], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.9711013910) : 0.000);
379			dst[31] = mix(dst[31], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.4236372243) : 0.000);
380			dst[32] = mix(dst[32], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.000 : ((haveSteepLine) ? 0.750 : 0.500)) : 0.05652034508) : 0.000);
381			dst[33] = mix(dst[33], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 1.000 : 0.000);
382			dst[34] = mix(dst[34], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.750 : 0.000);
383			dst[35] = mix(dst[35], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.250 : 0.000);
384
385			dist_01_04 = DistYCbCr(src[7], src[2]);
386			dist_03_08 = DistYCbCr(src[1], src[6]);
387			haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[2]) && (v[3] != v[2]);
388			haveSteepLine   = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[6]) && (v[5] != v[6]);
389			needBlend = (blendResult[1] != BLEND_NONE);
390			doLineBlend = (  blendResult[1] >= BLEND_DOMINANT ||
391						  !((blendResult[0] != BLEND_NONE && !IsPixEqual(src[0], src[2])) ||
392							(blendResult[2] != BLEND_NONE && !IsPixEqual(src[0], src[6])) ||
393							(IsPixEqual(src[2], src[1]) && IsPixEqual(src[1], src[8]) && IsPixEqual(src[8], src[7]) && IsPixEqual(src[7], src[6]) && !IsPixEqual(src[0], src[8])) ) );
394
395			dist_01_04 = DistYCbCr(src[7], src[2]);
396			dist_03_08 = DistYCbCr(src[1], src[6]);
397			haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[2]) && (v[3] != v[2]);
398			haveSteepLine   = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[6]) && (v[5] != v[6]);
399			needBlend = (blendResult[1] != BLEND_NONE);
400			doLineBlend = (  blendResult[1] >= BLEND_DOMINANT ||
401						  !((blendResult[0] != BLEND_NONE && !IsPixEqual(src[0], src[2])) ||
402							(blendResult[2] != BLEND_NONE && !IsPixEqual(src[0], src[6])) ||
403							(IsPixEqual(src[2], src[1]) && IsPixEqual(src[1], src[8]) && IsPixEqual(src[8], src[7]) && IsPixEqual(src[7], src[6]) && !IsPixEqual(src[0], src[8])) ) );
404
405			blendPix = ( DistYCbCr(src[0], src[7]) <= DistYCbCr(src[0], src[1]) ) ? src[7] : src[1];
406			dst[ 7] = mix(dst[ 7], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.250 : 0.000);
407			dst[ 8] = mix(dst[ 8], blendPix, (needBlend && doLineBlend) ? ((haveSteepLine) ? 0.750 : ((haveShallowLine) ? 0.250 : 0.000)) : 0.000);
408			dst[ 9] = mix(dst[ 9], blendPix, (needBlend && doLineBlend) ? ((!haveShallowLine && !haveSteepLine) ? 0.500 : 1.000) : 0.000);
409			dst[10] = mix(dst[10], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? 0.750 : ((haveSteepLine) ? 0.250 : 0.000)) : 0.000);
410			dst[11] = mix(dst[11], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.250 : 0.000);
411			dst[20] = mix(dst[20], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.250 : 0.000);
412			dst[21] = mix(dst[21], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.750 : 0.000);
413			dst[22] = mix(dst[22], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 1.000 : 0.000);
414			dst[23] = mix(dst[23], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.000 : ((haveShallowLine) ? 0.750 : 0.500)) : 0.05652034508) : 0.000);
415			dst[24] = mix(dst[24], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.4236372243) : 0.000);
416			dst[25] = mix(dst[25], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.9711013910) : 0.000);
417			dst[26] = mix(dst[26], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.4236372243) : 0.000);
418			dst[27] = mix(dst[27], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.000 : ((haveSteepLine) ? 0.750 : 0.500)) : 0.05652034508) : 0.000);
419			dst[28] = mix(dst[28], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 1.000 : 0.000);
420			dst[29] = mix(dst[29], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.750 : 0.000);
421			dst[30] = mix(dst[30], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.250 : 0.000);
422
423			dist_01_04 = DistYCbCr(src[5], src[8]);
424			dist_03_08 = DistYCbCr(src[7], src[4]);
425			haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[8]) && (v[1] != v[8]);
426			haveSteepLine   = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[4]) && (v[3] != v[4]);
427			needBlend = (blendResult[0] != BLEND_NONE);
428			doLineBlend = (  blendResult[0] >= BLEND_DOMINANT ||
429						  !((blendResult[3] != BLEND_NONE && !IsPixEqual(src[0], src[8])) ||
430							(blendResult[1] != BLEND_NONE && !IsPixEqual(src[0], src[4])) ||
431							(IsPixEqual(src[8], src[7]) && IsPixEqual(src[7], src[6]) && IsPixEqual(src[6], src[5]) && IsPixEqual(src[5], src[4]) && !IsPixEqual(src[0], src[6])) ) );
432
433			blendPix = ( DistYCbCr(src[0], src[5]) <= DistYCbCr(src[0], src[7]) ) ? src[5] : src[7];
434			dst[ 4] = mix(dst[ 4], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.250 : 0.000);
435			dst[ 5] = mix(dst[ 5], blendPix, (needBlend && doLineBlend) ? ((haveSteepLine) ? 0.750 : ((haveShallowLine) ? 0.250 : 0.000)) : 0.000);
436			dst[ 6] = mix(dst[ 6], blendPix, (needBlend && doLineBlend) ? ((!haveShallowLine && !haveSteepLine) ? 0.500 : 1.000) : 0.000);
437			dst[ 7] = mix(dst[ 7], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? 0.750 : ((haveSteepLine) ? 0.250 : 0.000)) : 0.000);
438			dst[ 8] = mix(dst[ 8], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.250 : 0.000);
439			dst[35] = mix(dst[35], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.250 : 0.000);
440			dst[16] = mix(dst[16], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.750 : 0.000);
441			dst[17] = mix(dst[17], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 1.000 : 0.000);
442			dst[18] = mix(dst[18], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.000 : ((haveShallowLine) ? 0.750 : 0.500)) : 0.05652034508) : 0.000);
443			dst[19] = mix(dst[19], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.4236372243) : 0.000);
444			dst[20] = mix(dst[20], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.9711013910) : 0.000);
445			dst[21] = mix(dst[21], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.4236372243) : 0.000);
446			dst[22] = mix(dst[22], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.000 : ((haveSteepLine) ? 0.750 : 0.500)) : 0.05652034508) : 0.000);
447			dst[23] = mix(dst[23], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 1.000 : 0.000);
448			dst[24] = mix(dst[24], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.750 : 0.000);
449			dst[25] = mix(dst[25], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.250 : 0.000);
450
451
452			dist_01_04 = DistYCbCr(src[3], src[6]);
453			dist_03_08 = DistYCbCr(src[5], src[2]);
454			haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_01_04 <= dist_03_08) && (v[0] != v[6]) && (v[7] != v[6]);
455			haveSteepLine   = (STEEP_DIRECTION_THRESHOLD * dist_03_08 <= dist_01_04) && (v[0] != v[2]) && (v[1] != v[2]);
456			needBlend = (blendResult[3] != BLEND_NONE);
457			doLineBlend = (  blendResult[3] >= BLEND_DOMINANT ||
458						  !((blendResult[2] != BLEND_NONE && !IsPixEqual(src[0], src[6])) ||
459							(blendResult[0] != BLEND_NONE && !IsPixEqual(src[0], src[2])) ||
460							(IsPixEqual(src[6], src[5]) && IsPixEqual(src[5], src[4]) && IsPixEqual(src[4], src[3]) && IsPixEqual(src[3], src[2]) && !IsPixEqual(src[0], src[4])) ) );
461
462			blendPix = ( DistYCbCr(src[0], src[3]) <= DistYCbCr(src[0], src[5]) ) ? src[3] : src[5];
463			dst[13] = mix(dst[13], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.250 : 0.000);
464			dst[14] = mix(dst[14], blendPix, (needBlend && doLineBlend) ? ((haveSteepLine) ? 0.750 : ((haveShallowLine) ? 0.250 : 0.000)) : 0.000);
465			dst[15] = mix(dst[15], blendPix, (needBlend && doLineBlend) ? ((!haveShallowLine && !haveSteepLine) ? 0.500 : 1.000) : 0.000);
466			dst[ 4] = mix(dst[ 4], blendPix, (needBlend && doLineBlend) ? ((haveShallowLine) ? 0.750 : ((haveSteepLine) ? 0.250 : 0.000)) : 0.000);
467			dst[ 5] = mix(dst[ 5], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.250 : 0.000);
468			dst[30] = mix(dst[30], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.250 : 0.000);
469			dst[31] = mix(dst[31], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 0.750 : 0.000);
470			dst[32] = mix(dst[32], blendPix, (needBlend && doLineBlend && haveSteepLine) ? 1.000 : 0.000);
471			dst[33] = mix(dst[33], blendPix, (needBlend) ? ((doLineBlend) ? ((haveSteepLine) ? 1.000 : ((haveShallowLine) ? 0.750 : 0.500)) : 0.05652034508) : 0.000);
472			dst[34] = mix(dst[34], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.4236372243) : 0.000);
473			dst[35] = mix(dst[35], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.9711013910) : 0.000);
474			dst[16] = mix(dst[16], blendPix, (needBlend) ? ((doLineBlend) ? 1.000 : 0.4236372243) : 0.000);
475			dst[17] = mix(dst[17], blendPix, (needBlend) ? ((doLineBlend) ? ((haveShallowLine) ? 1.000 : ((haveSteepLine) ? 0.750 : 0.500)) : 0.05652034508) : 0.000);
476			dst[18] = mix(dst[18], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 1.000 : 0.000);
477			dst[19] = mix(dst[19], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.750 : 0.000);
478			dst[20] = mix(dst[20], blendPix, (needBlend && doLineBlend && haveShallowLine) ? 0.250 : 0.000);
479
480		}
481
482			vec3 res = mix( mix( mix( mix( mix( mix(dst[20], dst[21], step(one_sixth, f.x) ), dst[22], step(two_sixth, f.x) ), mix( mix(dst[23], dst[24], step(four_sixth, f.x) ), dst[25], step(five_sixth, f.x) ), step(0.50, f.x) ),
483		                                  mix( mix( mix(dst[19], dst[ 6], step(one_sixth, f.x) ), dst[ 7], step(two_sixth, f.x) ), mix( mix(dst[ 8], dst[ 9], step(four_sixth, f.x) ), dst[26], step(five_sixth, f.x) ), step(0.50, f.x) ), step(one_sixth, f.y) ),
484		                                  mix( mix( mix(dst[18], dst[ 5], step(one_sixth, f.x) ), dst[ 0], step(two_sixth, f.x) ), mix( mix(dst[ 1], dst[10], step(four_sixth, f.x) ), dst[27], step(five_sixth, f.x) ), step(0.50, f.x) ), step(two_sixth, f.y) ),
485		                        mix( mix( mix( mix( mix(dst[17], dst[ 4], step(one_sixth, f.x) ), dst[ 3], step(two_sixth, f.x) ), mix( mix(dst[ 2], dst[11], step(four_sixth, f.x) ), dst[28], step(five_sixth, f.x) ), step(0.50, f.x) ),
486		                                  mix( mix( mix(dst[16], dst[15], step(one_sixth, f.x) ), dst[14], step(two_sixth, f.x) ), mix( mix(dst[13], dst[12], step(four_sixth, f.x) ), dst[29], step(five_sixth, f.x) ), step(0.50, f.x) ), step(four_sixth, f.y) ),
487		                                  mix( mix( mix(dst[35], dst[34], step(one_sixth, f.x) ), dst[33], step(two_sixth, f.x) ), mix( mix(dst[32], dst[31], step(four_sixth, f.x) ), dst[30], step(five_sixth, f.x) ), step(0.50, f.x) ), step(five_sixth, f.y) ),
488		                     step(0.50, f.y) );
489
490   FragColor = vec4(res, 1.0);
491}
492#endif
493