1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "../../SDL_internal.h"
22
23#if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED
24
25#include "SDL_video.h"
26#include "SDL_opengles2.h"
27#include "SDL_shaders_gles2.h"
28#include "SDL_stdinc.h"
29
30/*************************************************************************************************
31 * Vertex/fragment shader source *
32 *************************************************************************************************/
33/* Notes on a_angle:
34 * It is a vector containing sin and cos for rotation matrix
35 * To get correct rotation for most cases when a_angle is disabled cos
36 value is decremented by 1.0 to get proper output with 0.0 which is
37 default value
38*/
39static const Uint8 GLES2_Vertex_Default[] = " \
40 uniform mat4 u_projection; \
41 attribute vec2 a_position; \
42 attribute vec2 a_texCoord; \
43 attribute vec2 a_angle; \
44 attribute vec2 a_center; \
45 varying vec2 v_texCoord; \
46 \
47 void main() \
48 { \
49 float s = a_angle[0]; \
50 float c = a_angle[1] + 1.0; \
51 mat2 rotationMatrix = mat2(c, -s, s, c); \
52 vec2 position = rotationMatrix * (a_position - a_center) + a_center; \
53 v_texCoord = a_texCoord; \
54 gl_Position = u_projection * vec4(position, 0.0, 1.0);\
55 gl_PointSize = 1.0; \
56 } \
57";
58
59static const Uint8 GLES2_Fragment_Solid[] = " \
60 precision mediump float; \
61 uniform vec4 u_color; \
62 \
63 void main() \
64 { \
65 gl_FragColor = u_color; \
66 } \
67";
68
69static const Uint8 GLES2_Fragment_TextureABGR[] = " \
70 precision mediump float; \
71 uniform sampler2D u_texture; \
72 uniform vec4 u_color; \
73 varying vec2 v_texCoord; \
74 \
75 void main() \
76 { \
77 gl_FragColor = texture2D(u_texture, v_texCoord); \
78 gl_FragColor *= u_color; \
79 } \
80";
81
82/* ARGB to ABGR conversion */
83static const Uint8 GLES2_Fragment_TextureARGB[] = " \
84 precision mediump float; \
85 uniform sampler2D u_texture; \
86 uniform vec4 u_color; \
87 varying vec2 v_texCoord; \
88 \
89 void main() \
90 { \
91 vec4 abgr = texture2D(u_texture, v_texCoord); \
92 gl_FragColor = abgr; \
93 gl_FragColor.r = abgr.b; \
94 gl_FragColor.b = abgr.r; \
95 gl_FragColor *= u_color; \
96 } \
97";
98
99/* RGB to ABGR conversion */
100static const Uint8 GLES2_Fragment_TextureRGB[] = " \
101 precision mediump float; \
102 uniform sampler2D u_texture; \
103 uniform vec4 u_color; \
104 varying vec2 v_texCoord; \
105 \
106 void main() \
107 { \
108 vec4 abgr = texture2D(u_texture, v_texCoord); \
109 gl_FragColor = abgr; \
110 gl_FragColor.r = abgr.b; \
111 gl_FragColor.b = abgr.r; \
112 gl_FragColor.a = 1.0; \
113 gl_FragColor *= u_color; \
114 } \
115";
116
117/* BGR to ABGR conversion */
118static const Uint8 GLES2_Fragment_TextureBGR[] = " \
119 precision mediump float; \
120 uniform sampler2D u_texture; \
121 uniform vec4 u_color; \
122 varying vec2 v_texCoord; \
123 \
124 void main() \
125 { \
126 vec4 abgr = texture2D(u_texture, v_texCoord); \
127 gl_FragColor = abgr; \
128 gl_FragColor.a = 1.0; \
129 gl_FragColor *= u_color; \
130 } \
131";
132
133#define JPEG_SHADER_CONSTANTS \
134"// YUV offset \n" \
135"const vec3 offset = vec3(0, -0.501960814, -0.501960814);\n" \
136"\n" \
137"// RGB coefficients \n" \
138"const mat3 matrix = mat3( 1, 1, 1,\n" \
139" 0, -0.3441, 1.772,\n" \
140" 1.402, -0.7141, 0);\n" \
141
142#define BT601_SHADER_CONSTANTS \
143"// YUV offset \n" \
144"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n" \
145"\n" \
146"// RGB coefficients \n" \
147"const mat3 matrix = mat3( 1.1644, 1.1644, 1.1644,\n" \
148" 0, -0.3918, 2.0172,\n" \
149" 1.596, -0.813, 0);\n" \
150
151#define BT709_SHADER_CONSTANTS \
152"// YUV offset \n" \
153"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n" \
154"\n" \
155"// RGB coefficients \n" \
156"const mat3 matrix = mat3( 1.1644, 1.1644, 1.1644,\n" \
157" 0, -0.2132, 2.1124,\n" \
158" 1.7927, -0.5329, 0);\n" \
159
160
161#define YUV_SHADER_PROLOGUE \
162"precision mediump float;\n" \
163"uniform sampler2D u_texture;\n" \
164"uniform sampler2D u_texture_u;\n" \
165"uniform sampler2D u_texture_v;\n" \
166"uniform vec4 u_color;\n" \
167"varying vec2 v_texCoord;\n" \
168"\n" \
169
170#define YUV_SHADER_BODY \
171"\n" \
172"void main()\n" \
173"{\n" \
174" mediump vec3 yuv;\n" \
175" lowp vec3 rgb;\n" \
176"\n" \
177" // Get the YUV values \n" \
178" yuv.x = texture2D(u_texture, v_texCoord).r;\n" \
179" yuv.y = texture2D(u_texture_u, v_texCoord).r;\n" \
180" yuv.z = texture2D(u_texture_v, v_texCoord).r;\n" \
181"\n" \
182" // Do the color transform \n" \
183" yuv += offset;\n" \
184" rgb = matrix * yuv;\n" \
185"\n" \
186" // That was easy. :) \n" \
187" gl_FragColor = vec4(rgb, 1);\n" \
188" gl_FragColor *= u_color;\n" \
189"}" \
190
191#define NV12_SHADER_BODY \
192"\n" \
193"void main()\n" \
194"{\n" \
195" mediump vec3 yuv;\n" \
196" lowp vec3 rgb;\n" \
197"\n" \
198" // Get the YUV values \n" \
199" yuv.x = texture2D(u_texture, v_texCoord).r;\n" \
200" yuv.yz = texture2D(u_texture_u, v_texCoord).ra;\n" \
201"\n" \
202" // Do the color transform \n" \
203" yuv += offset;\n" \
204" rgb = matrix * yuv;\n" \
205"\n" \
206" // That was easy. :) \n" \
207" gl_FragColor = vec4(rgb, 1);\n" \
208" gl_FragColor *= u_color;\n" \
209"}" \
210
211#define NV21_SHADER_BODY \
212"\n" \
213"void main()\n" \
214"{\n" \
215" mediump vec3 yuv;\n" \
216" lowp vec3 rgb;\n" \
217"\n" \
218" // Get the YUV values \n" \
219" yuv.x = texture2D(u_texture, v_texCoord).r;\n" \
220" yuv.yz = texture2D(u_texture_u, v_texCoord).ar;\n" \
221"\n" \
222" // Do the color transform \n" \
223" yuv += offset;\n" \
224" rgb = matrix * yuv;\n" \
225"\n" \
226" // That was easy. :) \n" \
227" gl_FragColor = vec4(rgb, 1);\n" \
228" gl_FragColor *= u_color;\n" \
229"}" \
230
231/* YUV to ABGR conversion */
232static const Uint8 GLES2_Fragment_TextureYUVJPEG[] = \
233 YUV_SHADER_PROLOGUE \
234 JPEG_SHADER_CONSTANTS \
235 YUV_SHADER_BODY \
236;
237static const Uint8 GLES2_Fragment_TextureYUVBT601[] = \
238 YUV_SHADER_PROLOGUE \
239 BT601_SHADER_CONSTANTS \
240 YUV_SHADER_BODY \
241;
242static const Uint8 GLES2_Fragment_TextureYUVBT709[] = \
243 YUV_SHADER_PROLOGUE \
244 BT709_SHADER_CONSTANTS \
245 YUV_SHADER_BODY \
246;
247
248/* NV12 to ABGR conversion */
249static const Uint8 GLES2_Fragment_TextureNV12JPEG[] = \
250 YUV_SHADER_PROLOGUE \
251 JPEG_SHADER_CONSTANTS \
252 NV12_SHADER_BODY \
253;
254static const Uint8 GLES2_Fragment_TextureNV12BT601[] = \
255 YUV_SHADER_PROLOGUE \
256 BT601_SHADER_CONSTANTS \
257 NV12_SHADER_BODY \
258;
259static const Uint8 GLES2_Fragment_TextureNV12BT709[] = \
260 YUV_SHADER_PROLOGUE \
261 BT709_SHADER_CONSTANTS \
262 NV12_SHADER_BODY \
263;
264
265/* NV21 to ABGR conversion */
266static const Uint8 GLES2_Fragment_TextureNV21JPEG[] = \
267 YUV_SHADER_PROLOGUE \
268 JPEG_SHADER_CONSTANTS \
269 NV21_SHADER_BODY \
270;
271static const Uint8 GLES2_Fragment_TextureNV21BT601[] = \
272 YUV_SHADER_PROLOGUE \
273 BT601_SHADER_CONSTANTS \
274 NV21_SHADER_BODY \
275;
276static const Uint8 GLES2_Fragment_TextureNV21BT709[] = \
277 YUV_SHADER_PROLOGUE \
278 BT709_SHADER_CONSTANTS \
279 NV21_SHADER_BODY \
280;
281
282/* Custom Android video format texture */
283static const Uint8 GLES2_Fragment_TextureExternalOES[] = " \
284 #extension GL_OES_EGL_image_external : require\n\
285 precision mediump float; \
286 uniform samplerExternalOES u_texture; \
287 uniform vec4 u_color; \
288 varying vec2 v_texCoord; \
289 \
290 void main() \
291 { \
292 gl_FragColor = texture2D(u_texture, v_texCoord); \
293 gl_FragColor *= u_color; \
294 } \
295";
296
297
298/*************************************************************************************************
299 * Shader selector *
300 *************************************************************************************************/
301
302const Uint8 *GLES2_GetShader(GLES2_ShaderType type)
303{
304 switch (type) {
305 case GLES2_SHADER_VERTEX_DEFAULT:
306 return GLES2_Vertex_Default;
307 case GLES2_SHADER_FRAGMENT_SOLID:
308 return GLES2_Fragment_Solid;
309 case GLES2_SHADER_FRAGMENT_TEXTURE_ABGR:
310 return GLES2_Fragment_TextureABGR;
311 case GLES2_SHADER_FRAGMENT_TEXTURE_ARGB:
312 return GLES2_Fragment_TextureARGB;
313 case GLES2_SHADER_FRAGMENT_TEXTURE_RGB:
314 return GLES2_Fragment_TextureRGB;
315 case GLES2_SHADER_FRAGMENT_TEXTURE_BGR:
316 return GLES2_Fragment_TextureBGR;
317 case GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG:
318 return GLES2_Fragment_TextureYUVJPEG;
319 case GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601:
320 return GLES2_Fragment_TextureYUVBT601;
321 case GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709:
322 return GLES2_Fragment_TextureYUVBT709;
323 case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG:
324 return GLES2_Fragment_TextureNV12JPEG;
325 case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601:
326 return GLES2_Fragment_TextureNV12BT601;
327 case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709:
328 return GLES2_Fragment_TextureNV12BT709;
329 case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG:
330 return GLES2_Fragment_TextureNV21JPEG;
331 case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601:
332 return GLES2_Fragment_TextureNV21BT601;
333 case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709:
334 return GLES2_Fragment_TextureNV21BT709;
335 case GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES:
336 return GLES2_Fragment_TextureExternalOES;
337 default:
338 return NULL;
339 }
340}
341
342#endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
343
344/* vi: set ts=4 sw=4 expandtab: */
345