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 | */ |
39 | static 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 | |
59 | static 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 | |
69 | static 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 */ |
83 | static 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 */ |
100 | static 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 */ |
118 | static 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 */ |
232 | static const Uint8 GLES2_Fragment_TextureYUVJPEG[] = \ |
233 | YUV_SHADER_PROLOGUE \ |
234 | JPEG_SHADER_CONSTANTS \ |
235 | YUV_SHADER_BODY \ |
236 | ; |
237 | static const Uint8 GLES2_Fragment_TextureYUVBT601[] = \ |
238 | YUV_SHADER_PROLOGUE \ |
239 | BT601_SHADER_CONSTANTS \ |
240 | YUV_SHADER_BODY \ |
241 | ; |
242 | static const Uint8 GLES2_Fragment_TextureYUVBT709[] = \ |
243 | YUV_SHADER_PROLOGUE \ |
244 | BT709_SHADER_CONSTANTS \ |
245 | YUV_SHADER_BODY \ |
246 | ; |
247 | |
248 | /* NV12 to ABGR conversion */ |
249 | static const Uint8 GLES2_Fragment_TextureNV12JPEG[] = \ |
250 | YUV_SHADER_PROLOGUE \ |
251 | JPEG_SHADER_CONSTANTS \ |
252 | NV12_SHADER_BODY \ |
253 | ; |
254 | static const Uint8 GLES2_Fragment_TextureNV12BT601[] = \ |
255 | YUV_SHADER_PROLOGUE \ |
256 | BT601_SHADER_CONSTANTS \ |
257 | NV12_SHADER_BODY \ |
258 | ; |
259 | static const Uint8 GLES2_Fragment_TextureNV12BT709[] = \ |
260 | YUV_SHADER_PROLOGUE \ |
261 | BT709_SHADER_CONSTANTS \ |
262 | NV12_SHADER_BODY \ |
263 | ; |
264 | |
265 | /* NV21 to ABGR conversion */ |
266 | static const Uint8 GLES2_Fragment_TextureNV21JPEG[] = \ |
267 | YUV_SHADER_PROLOGUE \ |
268 | JPEG_SHADER_CONSTANTS \ |
269 | NV21_SHADER_BODY \ |
270 | ; |
271 | static const Uint8 GLES2_Fragment_TextureNV21BT601[] = \ |
272 | YUV_SHADER_PROLOGUE \ |
273 | BT601_SHADER_CONSTANTS \ |
274 | NV21_SHADER_BODY \ |
275 | ; |
276 | static 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 */ |
283 | static 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 | |
302 | const 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 | |