summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/render/opengl
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
committer3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
commit5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch)
tree8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/render/opengl
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/render/opengl')
-rw-r--r--contrib/SDL-3.2.8/src/render/opengl/SDL_glfuncs.h476
-rw-r--r--contrib/SDL-3.2.8/src/render/opengl/SDL_render_gl.c1844
-rw-r--r--contrib/SDL-3.2.8/src/render/opengl/SDL_shaders_gl.c545
-rw-r--r--contrib/SDL-3.2.8/src/render/opengl/SDL_shaders_gl.h52
4 files changed, 2917 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/render/opengl/SDL_glfuncs.h b/contrib/SDL-3.2.8/src/render/opengl/SDL_glfuncs.h
new file mode 100644
index 0000000..7e9f265
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/render/opengl/SDL_glfuncs.h
@@ -0,0 +1,476 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 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
22/* list of OpenGL functions sorted alphabetically
23 If you need to use a GL function from the SDL video subsystem,
24 change its entry from SDL_PROC_UNUSED to SDL_PROC and rebuild.
25*/
26#define SDL_PROC_UNUSED(ret, func, params)
27
28SDL_PROC_UNUSED(void, glAccum, (GLenum, GLfloat))
29SDL_PROC_UNUSED(void, glAlphaFunc, (GLenum, GLclampf))
30SDL_PROC_UNUSED(GLboolean, glAreTexturesResident,
31 (GLsizei, const GLuint *, GLboolean *))
32SDL_PROC_UNUSED(void, glArrayElement, (GLint))
33SDL_PROC(void, glBegin, (GLenum))
34SDL_PROC(void, glBindTexture, (GLenum, GLuint))
35SDL_PROC_UNUSED(void, glBitmap,
36 (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat,
37 const GLubyte *))
38SDL_PROC(void, glBlendEquation, (GLenum))
39SDL_PROC_UNUSED(void, glBlendFunc, (GLenum, GLenum))
40SDL_PROC(void, glBlendFuncSeparate, (GLenum, GLenum, GLenum, GLenum))
41SDL_PROC_UNUSED(void, glCallList, (GLuint))
42SDL_PROC_UNUSED(void, glCallLists, (GLsizei, GLenum, const GLvoid *))
43SDL_PROC(void, glClear, (GLbitfield))
44SDL_PROC_UNUSED(void, glClearAccum, (GLfloat, GLfloat, GLfloat, GLfloat))
45SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
46SDL_PROC_UNUSED(void, glClearDepth, (GLclampd))
47SDL_PROC_UNUSED(void, glClearIndex, (GLfloat))
48SDL_PROC_UNUSED(void, glClearStencil, (GLint))
49SDL_PROC_UNUSED(void, glClipPlane, (GLenum, const GLdouble *))
50SDL_PROC_UNUSED(void, glColor3b, (GLbyte, GLbyte, GLbyte))
51SDL_PROC_UNUSED(void, glColor3bv, (const GLbyte *))
52SDL_PROC_UNUSED(void, glColor3d, (GLdouble, GLdouble, GLdouble))
53SDL_PROC_UNUSED(void, glColor3dv, (const GLdouble *))
54SDL_PROC_UNUSED(void, glColor3f, (GLfloat, GLfloat, GLfloat))
55SDL_PROC(void, glColor3fv, (const GLfloat *))
56SDL_PROC_UNUSED(void, glColor3i, (GLint, GLint, GLint))
57SDL_PROC_UNUSED(void, glColor3iv, (const GLint *))
58SDL_PROC_UNUSED(void, glColor3s, (GLshort, GLshort, GLshort))
59SDL_PROC_UNUSED(void, glColor3sv, (const GLshort *))
60SDL_PROC_UNUSED(void, glColor3ub, (GLubyte, GLubyte, GLubyte))
61SDL_PROC_UNUSED(void, glColor3ubv, (const GLubyte *))
62SDL_PROC_UNUSED(void, glColor3ui, (GLuint, GLuint, GLuint))
63SDL_PROC_UNUSED(void, glColor3uiv, (const GLuint *))
64SDL_PROC_UNUSED(void, glColor3us, (GLushort, GLushort, GLushort))
65SDL_PROC_UNUSED(void, glColor3usv, (const GLushort *))
66SDL_PROC_UNUSED(void, glColor4b, (GLbyte, GLbyte, GLbyte, GLbyte))
67SDL_PROC_UNUSED(void, glColor4bv, (const GLbyte *))
68SDL_PROC_UNUSED(void, glColor4d, (GLdouble, GLdouble, GLdouble, GLdouble))
69SDL_PROC_UNUSED(void, glColor4dv, (const GLdouble *))
70SDL_PROC(void, glColor4f, (GLfloat, GLfloat, GLfloat, GLfloat))
71SDL_PROC_UNUSED(void, glColor4fv, (const GLfloat *))
72SDL_PROC_UNUSED(void, glColor4i, (GLint, GLint, GLint, GLint))
73SDL_PROC_UNUSED(void, glColor4iv, (const GLint *))
74SDL_PROC_UNUSED(void, glColor4s, (GLshort, GLshort, GLshort, GLshort))
75SDL_PROC_UNUSED(void, glColor4sv, (const GLshort *))
76SDL_PROC(void, glColor4ub,
77 (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha))
78SDL_PROC_UNUSED(void, glColor4ubv, (const GLubyte *v))
79SDL_PROC_UNUSED(void, glColor4ui,
80 (GLuint red, GLuint green, GLuint blue, GLuint alpha))
81SDL_PROC_UNUSED(void, glColor4uiv, (const GLuint *v))
82SDL_PROC_UNUSED(void, glColor4us,
83 (GLushort red, GLushort green, GLushort blue, GLushort alpha))
84SDL_PROC_UNUSED(void, glColor4usv, (const GLushort *v))
85SDL_PROC_UNUSED(void, glColorMask,
86 (GLboolean red, GLboolean green, GLboolean blue,
87 GLboolean alpha))
88SDL_PROC_UNUSED(void, glColorMaterial, (GLenum face, GLenum mode))
89SDL_PROC(void, glColorPointer,
90 (GLint size, GLenum type, GLsizei stride,
91 const GLvoid *pointer))
92SDL_PROC_UNUSED(void, glCopyPixels,
93 (GLint x, GLint y, GLsizei width, GLsizei height,
94 GLenum type))
95SDL_PROC_UNUSED(void, glCopyTexImage1D,
96 (GLenum target, GLint level, GLenum internalFormat, GLint x,
97 GLint y, GLsizei width, GLint border))
98SDL_PROC_UNUSED(void, glCopyTexImage2D,
99 (GLenum target, GLint level, GLenum internalFormat, GLint x,
100 GLint y, GLsizei width, GLsizei height, GLint border))
101SDL_PROC_UNUSED(void, glCopyTexSubImage1D,
102 (GLenum target, GLint level, GLint xoffset, GLint x, GLint y,
103 GLsizei width))
104SDL_PROC_UNUSED(void, glCopyTexSubImage2D,
105 (GLenum target, GLint level, GLint xoffset, GLint yoffset,
106 GLint x, GLint y, GLsizei width, GLsizei height))
107SDL_PROC_UNUSED(void, glCullFace, (GLenum mode))
108SDL_PROC_UNUSED(void, glDeleteLists, (GLuint list, GLsizei range))
109SDL_PROC(void, glDeleteTextures, (GLsizei n, const GLuint *textures))
110SDL_PROC(void, glDepthFunc, (GLenum func))
111SDL_PROC_UNUSED(void, glDepthMask, (GLboolean flag))
112SDL_PROC_UNUSED(void, glDepthRange, (GLclampd zNear, GLclampd zFar))
113SDL_PROC(void, glDisable, (GLenum cap))
114SDL_PROC(void, glDisableClientState, (GLenum array))
115SDL_PROC(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count))
116SDL_PROC_UNUSED(void, glDrawBuffer, (GLenum mode))
117SDL_PROC_UNUSED(void, glDrawElements,
118 (GLenum mode, GLsizei count, GLenum type,
119 const GLvoid *indices))
120SDL_PROC(void, glDrawPixels,
121 (GLsizei width, GLsizei height, GLenum format, GLenum type,
122 const GLvoid *pixels))
123SDL_PROC_UNUSED(void, glEdgeFlag, (GLboolean flag))
124SDL_PROC_UNUSED(void, glEdgeFlagPointer,
125 (GLsizei stride, const GLvoid *pointer))
126SDL_PROC_UNUSED(void, glEdgeFlagv, (const GLboolean *flag))
127SDL_PROC(void, glEnable, (GLenum cap))
128SDL_PROC(void, glEnableClientState, (GLenum array))
129SDL_PROC(void, glEnd, (void))
130SDL_PROC_UNUSED(void, glEndList, (void))
131SDL_PROC_UNUSED(void, glEvalCoord1d, (GLdouble u))
132SDL_PROC_UNUSED(void, glEvalCoord1dv, (const GLdouble *u))
133SDL_PROC_UNUSED(void, glEvalCoord1f, (GLfloat u))
134SDL_PROC_UNUSED(void, glEvalCoord1fv, (const GLfloat *u))
135SDL_PROC_UNUSED(void, glEvalCoord2d, (GLdouble u, GLdouble v))
136SDL_PROC_UNUSED(void, glEvalCoord2dv, (const GLdouble *u))
137SDL_PROC_UNUSED(void, glEvalCoord2f, (GLfloat u, GLfloat v))
138SDL_PROC_UNUSED(void, glEvalCoord2fv, (const GLfloat *u))
139SDL_PROC_UNUSED(void, glEvalMesh1, (GLenum mode, GLint i1, GLint i2))
140SDL_PROC_UNUSED(void, glEvalMesh2,
141 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2))
142SDL_PROC_UNUSED(void, glEvalPoint1, (GLint i))
143SDL_PROC_UNUSED(void, glEvalPoint2, (GLint i, GLint j))
144SDL_PROC_UNUSED(void, glFeedbackBuffer,
145 (GLsizei size, GLenum type, GLfloat *buffer))
146SDL_PROC_UNUSED(void, glFinish, (void))
147SDL_PROC_UNUSED(void, glFlush, (void))
148SDL_PROC_UNUSED(void, glFogf, (GLenum pname, GLfloat param))
149SDL_PROC_UNUSED(void, glFogfv, (GLenum pname, const GLfloat *params))
150SDL_PROC_UNUSED(void, glFogi, (GLenum pname, GLint param))
151SDL_PROC_UNUSED(void, glFogiv, (GLenum pname, const GLint *params))
152SDL_PROC_UNUSED(void, glFrontFace, (GLenum mode))
153SDL_PROC_UNUSED(void, glFrustum,
154 (GLdouble left, GLdouble right, GLdouble bottom,
155 GLdouble top, GLdouble zNear, GLdouble zFar))
156SDL_PROC_UNUSED(GLuint, glGenLists, (GLsizei range))
157SDL_PROC(void, glGenTextures, (GLsizei n, GLuint *textures))
158SDL_PROC_UNUSED(void, glGetBooleanv, (GLenum pname, GLboolean *params))
159SDL_PROC_UNUSED(void, glGetClipPlane, (GLenum plane, GLdouble *equation))
160SDL_PROC_UNUSED(void, glGetDoublev, (GLenum pname, GLdouble *params))
161SDL_PROC(GLenum, glGetError, (void))
162SDL_PROC(void, glGetFloatv, (GLenum pname, GLfloat *params))
163SDL_PROC(void, glGetIntegerv, (GLenum pname, GLint *params))
164SDL_PROC_UNUSED(void, glGetLightfv,
165 (GLenum light, GLenum pname, GLfloat *params))
166SDL_PROC_UNUSED(void, glGetLightiv,
167 (GLenum light, GLenum pname, GLint *params))
168SDL_PROC_UNUSED(void, glGetMapdv, (GLenum target, GLenum query, GLdouble *v))
169SDL_PROC_UNUSED(void, glGetMapfv, (GLenum target, GLenum query, GLfloat *v))
170SDL_PROC_UNUSED(void, glGetMapiv, (GLenum target, GLenum query, GLint *v))
171SDL_PROC_UNUSED(void, glGetMaterialfv,
172 (GLenum face, GLenum pname, GLfloat *params))
173SDL_PROC_UNUSED(void, glGetMaterialiv,
174 (GLenum face, GLenum pname, GLint *params))
175SDL_PROC_UNUSED(void, glGetPixelMapfv, (GLenum map, GLfloat *values))
176SDL_PROC_UNUSED(void, glGetPixelMapuiv, (GLenum map, GLuint *values))
177SDL_PROC_UNUSED(void, glGetPixelMapusv, (GLenum map, GLushort *values))
178SDL_PROC(void, glGetPointerv, (GLenum pname, GLvoid **params))
179SDL_PROC_UNUSED(void, glGetPolygonStipple, (GLubyte * mask))
180SDL_PROC(const GLubyte *, glGetString, (GLenum name))
181SDL_PROC_UNUSED(void, glGetTexEnvfv,
182 (GLenum target, GLenum pname, GLfloat *params))
183SDL_PROC_UNUSED(void, glGetTexEnviv,
184 (GLenum target, GLenum pname, GLint *params))
185SDL_PROC_UNUSED(void, glGetTexGendv,
186 (GLenum coord, GLenum pname, GLdouble *params))
187SDL_PROC_UNUSED(void, glGetTexGenfv,
188 (GLenum coord, GLenum pname, GLfloat *params))
189SDL_PROC_UNUSED(void, glGetTexGeniv,
190 (GLenum coord, GLenum pname, GLint *params))
191SDL_PROC_UNUSED(void, glGetTexImage,
192 (GLenum target, GLint level, GLenum format, GLenum type,
193 GLvoid *pixels))
194SDL_PROC_UNUSED(void, glGetTexLevelParameterfv,
195 (GLenum target, GLint level, GLenum pname, GLfloat *params))
196SDL_PROC_UNUSED(void, glGetTexLevelParameteriv,
197 (GLenum target, GLint level, GLenum pname, GLint *params))
198SDL_PROC_UNUSED(void, glGetTexParameterfv,
199 (GLenum target, GLenum pname, GLfloat *params))
200SDL_PROC_UNUSED(void, glGetTexParameteriv,
201 (GLenum target, GLenum pname, GLint *params))
202SDL_PROC_UNUSED(void, glHint, (GLenum target, GLenum mode))
203SDL_PROC_UNUSED(void, glIndexMask, (GLuint mask))
204SDL_PROC_UNUSED(void, glIndexPointer,
205 (GLenum type, GLsizei stride, const GLvoid *pointer))
206SDL_PROC_UNUSED(void, glIndexd, (GLdouble c))
207SDL_PROC_UNUSED(void, glIndexdv, (const GLdouble *c))
208SDL_PROC_UNUSED(void, glIndexf, (GLfloat c))
209SDL_PROC_UNUSED(void, glIndexfv, (const GLfloat *c))
210SDL_PROC_UNUSED(void, glIndexi, (GLint c))
211SDL_PROC_UNUSED(void, glIndexiv, (const GLint *c))
212SDL_PROC_UNUSED(void, glIndexs, (GLshort c))
213SDL_PROC_UNUSED(void, glIndexsv, (const GLshort *c))
214SDL_PROC_UNUSED(void, glIndexub, (GLubyte c))
215SDL_PROC_UNUSED(void, glIndexubv, (const GLubyte *c))
216SDL_PROC_UNUSED(void, glInitNames, (void))
217SDL_PROC_UNUSED(void, glInterleavedArrays,
218 (GLenum format, GLsizei stride, const GLvoid *pointer))
219SDL_PROC_UNUSED(GLboolean, glIsEnabled, (GLenum cap))
220SDL_PROC_UNUSED(GLboolean, glIsList, (GLuint list))
221SDL_PROC_UNUSED(GLboolean, glIsTexture, (GLuint texture))
222SDL_PROC_UNUSED(void, glLightModelf, (GLenum pname, GLfloat param))
223SDL_PROC_UNUSED(void, glLightModelfv, (GLenum pname, const GLfloat *params))
224SDL_PROC_UNUSED(void, glLightModeli, (GLenum pname, GLint param))
225SDL_PROC_UNUSED(void, glLightModeliv, (GLenum pname, const GLint *params))
226SDL_PROC_UNUSED(void, glLightf, (GLenum light, GLenum pname, GLfloat param))
227SDL_PROC_UNUSED(void, glLightfv,
228 (GLenum light, GLenum pname, const GLfloat *params))
229SDL_PROC_UNUSED(void, glLighti, (GLenum light, GLenum pname, GLint param))
230SDL_PROC_UNUSED(void, glLightiv,
231 (GLenum light, GLenum pname, const GLint *params))
232SDL_PROC_UNUSED(void, glLineStipple, (GLint factor, GLushort pattern))
233SDL_PROC(void, glLineWidth, (GLfloat width))
234SDL_PROC_UNUSED(void, glListBase, (GLuint base))
235SDL_PROC(void, glLoadIdentity, (void))
236SDL_PROC_UNUSED(void, glLoadMatrixd, (const GLdouble *m))
237SDL_PROC_UNUSED(void, glLoadMatrixf, (const GLfloat *m))
238SDL_PROC_UNUSED(void, glLoadName, (GLuint name))
239SDL_PROC_UNUSED(void, glLogicOp, (GLenum opcode))
240SDL_PROC_UNUSED(void, glMap1d,
241 (GLenum target, GLdouble u1, GLdouble u2, GLint stride,
242 GLint order, const GLdouble *points))
243SDL_PROC_UNUSED(void, glMap1f,
244 (GLenum target, GLfloat u1, GLfloat u2, GLint stride,
245 GLint order, const GLfloat *points))
246SDL_PROC_UNUSED(void, glMap2d,
247 (GLenum target, GLdouble u1, GLdouble u2, GLint ustride,
248 GLint uorder, GLdouble v1, GLdouble v2, GLint vstride,
249 GLint vorder, const GLdouble *points))
250SDL_PROC_UNUSED(void, glMap2f,
251 (GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
252 GLint uorder, GLfloat v1, GLfloat v2, GLint vstride,
253 GLint vorder, const GLfloat *points))
254SDL_PROC_UNUSED(void, glMapGrid1d, (GLint un, GLdouble u1, GLdouble u2))
255SDL_PROC_UNUSED(void, glMapGrid1f, (GLint un, GLfloat u1, GLfloat u2))
256SDL_PROC_UNUSED(void, glMapGrid2d,
257 (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1,
258 GLdouble v2))
259SDL_PROC_UNUSED(void, glMapGrid2f,
260 (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1,
261 GLfloat v2))
262SDL_PROC_UNUSED(void, glMaterialf, (GLenum face, GLenum pname, GLfloat param))
263SDL_PROC_UNUSED(void, glMaterialfv,
264 (GLenum face, GLenum pname, const GLfloat *params))
265SDL_PROC_UNUSED(void, glMateriali, (GLenum face, GLenum pname, GLint param))
266SDL_PROC_UNUSED(void, glMaterialiv,
267 (GLenum face, GLenum pname, const GLint *params))
268SDL_PROC(void, glMatrixMode, (GLenum mode))
269SDL_PROC_UNUSED(void, glMultMatrixd, (const GLdouble *m))
270SDL_PROC_UNUSED(void, glMultMatrixf, (const GLfloat *m))
271SDL_PROC_UNUSED(void, glNewList, (GLuint list, GLenum mode))
272SDL_PROC_UNUSED(void, glNormal3b, (GLbyte nx, GLbyte ny, GLbyte nz))
273SDL_PROC_UNUSED(void, glNormal3bv, (const GLbyte *v))
274SDL_PROC_UNUSED(void, glNormal3d, (GLdouble nx, GLdouble ny, GLdouble nz))
275SDL_PROC_UNUSED(void, glNormal3dv, (const GLdouble *v))
276SDL_PROC_UNUSED(void, glNormal3f, (GLfloat nx, GLfloat ny, GLfloat nz))
277SDL_PROC_UNUSED(void, glNormal3fv, (const GLfloat *v))
278SDL_PROC_UNUSED(void, glNormal3i, (GLint nx, GLint ny, GLint nz))
279SDL_PROC_UNUSED(void, glNormal3iv, (const GLint *v))
280SDL_PROC_UNUSED(void, glNormal3s, (GLshort nx, GLshort ny, GLshort nz))
281SDL_PROC_UNUSED(void, glNormal3sv, (const GLshort *v))
282SDL_PROC_UNUSED(void, glNormalPointer,
283 (GLenum type, GLsizei stride, const GLvoid *pointer))
284SDL_PROC(void, glOrtho,
285 (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top,
286 GLdouble zNear, GLdouble zFar))
287SDL_PROC_UNUSED(void, glPassThrough, (GLfloat token))
288SDL_PROC_UNUSED(void, glPixelMapfv,
289 (GLenum map, GLsizei mapsize, const GLfloat *values))
290SDL_PROC_UNUSED(void, glPixelMapuiv,
291 (GLenum map, GLsizei mapsize, const GLuint *values))
292SDL_PROC_UNUSED(void, glPixelMapusv,
293 (GLenum map, GLsizei mapsize, const GLushort *values))
294SDL_PROC_UNUSED(void, glPixelStoref, (GLenum pname, GLfloat param))
295SDL_PROC(void, glPixelStorei, (GLenum pname, GLint param))
296SDL_PROC_UNUSED(void, glPixelTransferf, (GLenum pname, GLfloat param))
297SDL_PROC_UNUSED(void, glPixelTransferi, (GLenum pname, GLint param))
298SDL_PROC_UNUSED(void, glPixelZoom, (GLfloat xfactor, GLfloat yfactor))
299SDL_PROC(void, glPointSize, (GLfloat size))
300SDL_PROC_UNUSED(void, glPolygonMode, (GLenum face, GLenum mode))
301SDL_PROC_UNUSED(void, glPolygonOffset, (GLfloat factor, GLfloat units))
302SDL_PROC_UNUSED(void, glPolygonStipple, (const GLubyte *mask))
303SDL_PROC_UNUSED(void, glPopAttrib, (void))
304SDL_PROC_UNUSED(void, glPopClientAttrib, (void))
305SDL_PROC_UNUSED(void, glPopMatrix, (void))
306SDL_PROC_UNUSED(void, glPopName, (void))
307SDL_PROC_UNUSED(void, glPrioritizeTextures,
308 (GLsizei n, const GLuint *textures,
309 const GLclampf *priorities))
310SDL_PROC_UNUSED(void, glPushAttrib, (GLbitfield mask))
311SDL_PROC_UNUSED(void, glPushClientAttrib, (GLbitfield mask))
312SDL_PROC_UNUSED(void, glPushMatrix, (void))
313SDL_PROC_UNUSED(void, glPushName, (GLuint name))
314SDL_PROC_UNUSED(void, glRasterPos2d, (GLdouble x, GLdouble y))
315SDL_PROC_UNUSED(void, glRasterPos2dv, (const GLdouble *v))
316SDL_PROC_UNUSED(void, glRasterPos2f, (GLfloat x, GLfloat y))
317SDL_PROC_UNUSED(void, glRasterPos2fv, (const GLfloat *v))
318SDL_PROC(void, glRasterPos2i, (GLint x, GLint y))
319SDL_PROC_UNUSED(void, glRasterPos2iv, (const GLint *v))
320SDL_PROC_UNUSED(void, glRasterPos2s, (GLshort x, GLshort y))
321SDL_PROC_UNUSED(void, glRasterPos2sv, (const GLshort *v))
322SDL_PROC_UNUSED(void, glRasterPos3d, (GLdouble x, GLdouble y, GLdouble z))
323SDL_PROC_UNUSED(void, glRasterPos3dv, (const GLdouble *v))
324SDL_PROC_UNUSED(void, glRasterPos3f, (GLfloat x, GLfloat y, GLfloat z))
325SDL_PROC_UNUSED(void, glRasterPos3fv, (const GLfloat *v))
326SDL_PROC_UNUSED(void, glRasterPos3i, (GLint x, GLint y, GLint z))
327SDL_PROC_UNUSED(void, glRasterPos3iv, (const GLint *v))
328SDL_PROC_UNUSED(void, glRasterPos3s, (GLshort x, GLshort y, GLshort z))
329SDL_PROC_UNUSED(void, glRasterPos3sv, (const GLshort *v))
330SDL_PROC_UNUSED(void, glRasterPos4d,
331 (GLdouble x, GLdouble y, GLdouble z, GLdouble w))
332SDL_PROC_UNUSED(void, glRasterPos4dv, (const GLdouble *v))
333SDL_PROC_UNUSED(void, glRasterPos4f,
334 (GLfloat x, GLfloat y, GLfloat z, GLfloat w))
335SDL_PROC_UNUSED(void, glRasterPos4fv, (const GLfloat *v))
336SDL_PROC_UNUSED(void, glRasterPos4i, (GLint x, GLint y, GLint z, GLint w))
337SDL_PROC_UNUSED(void, glRasterPos4iv, (const GLint *v))
338SDL_PROC_UNUSED(void, glRasterPos4s,
339 (GLshort x, GLshort y, GLshort z, GLshort w))
340SDL_PROC_UNUSED(void, glRasterPos4sv, (const GLshort *v))
341SDL_PROC(void, glReadBuffer, (GLenum mode))
342SDL_PROC(void, glReadPixels,
343 (GLint x, GLint y, GLsizei width, GLsizei height,
344 GLenum format, GLenum type, GLvoid *pixels))
345SDL_PROC_UNUSED(void, glRectd,
346 (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2))
347SDL_PROC_UNUSED(void, glRectdv, (const GLdouble *v1, const GLdouble *v2))
348SDL_PROC(void, glRectf,
349 (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2))
350SDL_PROC_UNUSED(void, glRectfv, (const GLfloat *v1, const GLfloat *v2))
351SDL_PROC_UNUSED(void, glRecti, (GLint x1, GLint y1, GLint x2, GLint y2))
352SDL_PROC_UNUSED(void, glRectiv, (const GLint *v1, const GLint *v2))
353SDL_PROC_UNUSED(void, glRects,
354 (GLshort x1, GLshort y1, GLshort x2, GLshort y2))
355SDL_PROC_UNUSED(void, glRectsv, (const GLshort *v1, const GLshort *v2))
356SDL_PROC_UNUSED(GLint, glRenderMode, (GLenum mode))
357SDL_PROC_UNUSED(void, glRotated,
358 (GLdouble angle, GLdouble x, GLdouble y, GLdouble z))
359SDL_PROC(void, glRotatef,
360 (GLfloat angle, GLfloat x, GLfloat y, GLfloat z))
361SDL_PROC_UNUSED(void, glScaled, (GLdouble x, GLdouble y, GLdouble z))
362SDL_PROC_UNUSED(void, glScalef, (GLfloat x, GLfloat y, GLfloat z))
363SDL_PROC(void, glScissor, (GLint x, GLint y, GLsizei width, GLsizei height))
364SDL_PROC_UNUSED(void, glSelectBuffer, (GLsizei size, GLuint *buffer))
365SDL_PROC(void, glShadeModel, (GLenum mode))
366SDL_PROC_UNUSED(void, glStencilFunc, (GLenum func, GLint ref, GLuint mask))
367SDL_PROC_UNUSED(void, glStencilMask, (GLuint mask))
368SDL_PROC_UNUSED(void, glStencilOp, (GLenum fail, GLenum zfail, GLenum zpass))
369SDL_PROC_UNUSED(void, glTexCoord1d, (GLdouble s))
370SDL_PROC_UNUSED(void, glTexCoord1dv, (const GLdouble *v))
371SDL_PROC_UNUSED(void, glTexCoord1f, (GLfloat s))
372SDL_PROC_UNUSED(void, glTexCoord1fv, (const GLfloat *v))
373SDL_PROC_UNUSED(void, glTexCoord1i, (GLint s))
374SDL_PROC_UNUSED(void, glTexCoord1iv, (const GLint *v))
375SDL_PROC_UNUSED(void, glTexCoord1s, (GLshort s))
376SDL_PROC_UNUSED(void, glTexCoord1sv, (const GLshort *v))
377SDL_PROC_UNUSED(void, glTexCoord2d, (GLdouble s, GLdouble t))
378SDL_PROC_UNUSED(void, glTexCoord2dv, (const GLdouble *v))
379SDL_PROC(void, glTexCoord2f, (GLfloat s, GLfloat t))
380SDL_PROC_UNUSED(void, glTexCoord2fv, (const GLfloat *v))
381SDL_PROC_UNUSED(void, glTexCoord2i, (GLint s, GLint t))
382SDL_PROC_UNUSED(void, glTexCoord2iv, (const GLint *v))
383SDL_PROC_UNUSED(void, glTexCoord2s, (GLshort s, GLshort t))
384SDL_PROC_UNUSED(void, glTexCoord2sv, (const GLshort *v))
385SDL_PROC_UNUSED(void, glTexCoord3d, (GLdouble s, GLdouble t, GLdouble r))
386SDL_PROC_UNUSED(void, glTexCoord3dv, (const GLdouble *v))
387SDL_PROC_UNUSED(void, glTexCoord3f, (GLfloat s, GLfloat t, GLfloat r))
388SDL_PROC_UNUSED(void, glTexCoord3fv, (const GLfloat *v))
389SDL_PROC_UNUSED(void, glTexCoord3i, (GLint s, GLint t, GLint r))
390SDL_PROC_UNUSED(void, glTexCoord3iv, (const GLint *v))
391SDL_PROC_UNUSED(void, glTexCoord3s, (GLshort s, GLshort t, GLshort r))
392SDL_PROC_UNUSED(void, glTexCoord3sv, (const GLshort *v))
393SDL_PROC_UNUSED(void, glTexCoord4d,
394 (GLdouble s, GLdouble t, GLdouble r, GLdouble q))
395SDL_PROC_UNUSED(void, glTexCoord4dv, (const GLdouble *v))
396SDL_PROC_UNUSED(void, glTexCoord4f,
397 (GLfloat s, GLfloat t, GLfloat r, GLfloat q))
398SDL_PROC_UNUSED(void, glTexCoord4fv, (const GLfloat *v))
399SDL_PROC_UNUSED(void, glTexCoord4i, (GLint s, GLint t, GLint r, GLint q))
400SDL_PROC_UNUSED(void, glTexCoord4iv, (const GLint *v))
401SDL_PROC_UNUSED(void, glTexCoord4s,
402 (GLshort s, GLshort t, GLshort r, GLshort q))
403SDL_PROC_UNUSED(void, glTexCoord4sv, (const GLshort *v))
404SDL_PROC(void, glTexCoordPointer,
405 (GLint size, GLenum type, GLsizei stride,
406 const GLvoid *pointer))
407SDL_PROC(void, glTexEnvf, (GLenum target, GLenum pname, GLfloat param))
408SDL_PROC_UNUSED(void, glTexEnvfv,
409 (GLenum target, GLenum pname, const GLfloat *params))
410SDL_PROC_UNUSED(void, glTexEnvi, (GLenum target, GLenum pname, GLint param))
411SDL_PROC_UNUSED(void, glTexEnviv,
412 (GLenum target, GLenum pname, const GLint *params))
413SDL_PROC_UNUSED(void, glTexGend, (GLenum coord, GLenum pname, GLdouble param))
414SDL_PROC_UNUSED(void, glTexGendv,
415 (GLenum coord, GLenum pname, const GLdouble *params))
416SDL_PROC_UNUSED(void, glTexGenf, (GLenum coord, GLenum pname, GLfloat param))
417SDL_PROC_UNUSED(void, glTexGenfv,
418 (GLenum coord, GLenum pname, const GLfloat *params))
419SDL_PROC_UNUSED(void, glTexGeni, (GLenum coord, GLenum pname, GLint param))
420SDL_PROC_UNUSED(void, glTexGeniv,
421 (GLenum coord, GLenum pname, const GLint *params))
422SDL_PROC_UNUSED(void, glTexImage1D,
423 (GLenum target, GLint level, GLint internalformat,
424 GLsizei width, GLint border, GLenum format, GLenum type,
425 const GLvoid *pixels))
426SDL_PROC(void, glTexImage2D,
427 (GLenum target, GLint level, GLint internalformat, GLsizei width,
428 GLsizei height, GLint border, GLenum format, GLenum type,
429 const GLvoid *pixels))
430SDL_PROC_UNUSED(void, glTexParameterf,
431 (GLenum target, GLenum pname, GLfloat param))
432SDL_PROC_UNUSED(void, glTexParameterfv,
433 (GLenum target, GLenum pname, const GLfloat *params))
434SDL_PROC(void, glTexParameteri, (GLenum target, GLenum pname, GLint param))
435SDL_PROC_UNUSED(void, glTexParameteriv,
436 (GLenum target, GLenum pname, const GLint *params))
437SDL_PROC_UNUSED(void, glTexSubImage1D,
438 (GLenum target, GLint level, GLint xoffset, GLsizei width,
439 GLenum format, GLenum type, const GLvoid *pixels))
440SDL_PROC(void, glTexSubImage2D,
441 (GLenum target, GLint level, GLint xoffset, GLint yoffset,
442 GLsizei width, GLsizei height, GLenum format, GLenum type,
443 const GLvoid *pixels))
444SDL_PROC_UNUSED(void, glTranslated, (GLdouble x, GLdouble y, GLdouble z))
445SDL_PROC_UNUSED(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z))
446SDL_PROC_UNUSED(void, glVertex2d, (GLdouble x, GLdouble y))
447SDL_PROC_UNUSED(void, glVertex2dv, (const GLdouble *v))
448SDL_PROC(void, glVertex2f, (GLfloat x, GLfloat y))
449SDL_PROC_UNUSED(void, glVertex2fv, (const GLfloat *v))
450SDL_PROC_UNUSED(void, glVertex2i, (GLint x, GLint y))
451SDL_PROC_UNUSED(void, glVertex2iv, (const GLint *v))
452SDL_PROC_UNUSED(void, glVertex2s, (GLshort x, GLshort y))
453SDL_PROC_UNUSED(void, glVertex2sv, (const GLshort *v))
454SDL_PROC_UNUSED(void, glVertex3d, (GLdouble x, GLdouble y, GLdouble z))
455SDL_PROC_UNUSED(void, glVertex3dv, (const GLdouble *v))
456SDL_PROC_UNUSED(void, glVertex3f, (GLfloat x, GLfloat y, GLfloat z))
457SDL_PROC(void, glVertex3fv, (const GLfloat *v))
458SDL_PROC_UNUSED(void, glVertex3i, (GLint x, GLint y, GLint z))
459SDL_PROC_UNUSED(void, glVertex3iv, (const GLint *v))
460SDL_PROC_UNUSED(void, glVertex3s, (GLshort x, GLshort y, GLshort z))
461SDL_PROC_UNUSED(void, glVertex3sv, (const GLshort *v))
462SDL_PROC_UNUSED(void, glVertex4d,
463 (GLdouble x, GLdouble y, GLdouble z, GLdouble w))
464SDL_PROC_UNUSED(void, glVertex4dv, (const GLdouble *v))
465SDL_PROC_UNUSED(void, glVertex4f,
466 (GLfloat x, GLfloat y, GLfloat z, GLfloat w))
467SDL_PROC_UNUSED(void, glVertex4fv, (const GLfloat *v))
468SDL_PROC_UNUSED(void, glVertex4i, (GLint x, GLint y, GLint z, GLint w))
469SDL_PROC_UNUSED(void, glVertex4iv, (const GLint *v))
470SDL_PROC_UNUSED(void, glVertex4s,
471 (GLshort x, GLshort y, GLshort z, GLshort w))
472SDL_PROC_UNUSED(void, glVertex4sv, (const GLshort *v))
473SDL_PROC(void, glVertexPointer,
474 (GLint size, GLenum type, GLsizei stride,
475 const GLvoid *pointer))
476SDL_PROC(void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height))
diff --git a/contrib/SDL-3.2.8/src/render/opengl/SDL_render_gl.c b/contrib/SDL-3.2.8/src/render/opengl/SDL_render_gl.c
new file mode 100644
index 0000000..d534438
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/render/opengl/SDL_render_gl.c
@@ -0,0 +1,1844 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 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#ifdef SDL_VIDEO_RENDER_OGL
24#include "../../video/SDL_sysvideo.h" // For SDL_RecreateWindow
25#include <SDL3/SDL_opengl.h>
26#include "../SDL_sysrender.h"
27#include "SDL_shaders_gl.h"
28#include "../../video/SDL_pixels_c.h"
29
30#ifdef SDL_PLATFORM_MACOS
31#include <OpenGL/OpenGL.h>
32#endif
33
34#ifdef SDL_VIDEO_VITA_PVR_OGL
35#include <GL/gl.h>
36#include <GL/glext.h>
37#endif
38
39/* To prevent unnecessary window recreation,
40 * these should match the defaults selected in SDL_GL_ResetAttributes
41 */
42
43#define RENDERER_CONTEXT_MAJOR 2
44#define RENDERER_CONTEXT_MINOR 1
45
46// OpenGL renderer implementation
47
48/* Details on optimizing the texture path on macOS:
49 http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html
50*/
51
52typedef struct GL_FBOList GL_FBOList;
53
54struct GL_FBOList
55{
56 Uint32 w, h;
57 GLuint FBO;
58 GL_FBOList *next;
59};
60
61typedef struct
62{
63 bool viewport_dirty;
64 SDL_Rect viewport;
65 SDL_Texture *texture;
66 SDL_Texture *target;
67 int drawablew;
68 int drawableh;
69 SDL_BlendMode blend;
70 GL_Shader shader;
71 const float *shader_params;
72 bool cliprect_enabled_dirty;
73 bool cliprect_enabled;
74 bool cliprect_dirty;
75 SDL_Rect cliprect;
76 bool texturing;
77 bool texturing_dirty;
78 bool vertex_array;
79 bool color_array;
80 bool texture_array;
81 bool color_dirty;
82 SDL_FColor color;
83 bool clear_color_dirty;
84 SDL_FColor clear_color;
85} GL_DrawStateCache;
86
87typedef struct
88{
89 SDL_GLContext context;
90
91 bool debug_enabled;
92 bool GL_ARB_debug_output_supported;
93 int errors;
94 char **error_messages;
95 GLDEBUGPROCARB next_error_callback;
96 GLvoid *next_error_userparam;
97
98 GLenum textype;
99
100 bool GL_ARB_texture_non_power_of_two_supported;
101 bool GL_ARB_texture_rectangle_supported;
102 bool GL_EXT_framebuffer_object_supported;
103 GL_FBOList *framebuffers;
104
105 // OpenGL functions
106#define SDL_PROC(ret, func, params) ret (APIENTRY *func) params;
107#include "SDL_glfuncs.h"
108#undef SDL_PROC
109
110 // Multitexture support
111 bool GL_ARB_multitexture_supported;
112 PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
113 GLint num_texture_units;
114
115 PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
116 PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
117 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
118 PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
119 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
120
121 // Shader support
122 GL_ShaderContext *shaders;
123
124 GL_DrawStateCache drawstate;
125} GL_RenderData;
126
127typedef struct
128{
129 GLuint texture;
130 bool texture_external;
131 GLfloat texw;
132 GLfloat texh;
133 GLenum format;
134 GLenum formattype;
135 GL_Shader shader;
136 const float *shader_params;
137 void *pixels;
138 int pitch;
139 SDL_Rect locked_rect;
140
141#ifdef SDL_HAVE_YUV
142 // YUV texture support
143 bool yuv;
144 bool nv12;
145 GLuint utexture;
146 bool utexture_external;
147 GLuint vtexture;
148 bool vtexture_external;
149#endif
150
151 GL_FBOList *fbo;
152} GL_TextureData;
153
154static const char *GL_TranslateError(GLenum error)
155{
156#define GL_ERROR_TRANSLATE(e) \
157 case e: \
158 return #e;
159 switch (error) {
160 GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
161 GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
162 GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
163 GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
164 GL_ERROR_TRANSLATE(GL_NO_ERROR)
165 GL_ERROR_TRANSLATE(GL_STACK_OVERFLOW)
166 GL_ERROR_TRANSLATE(GL_STACK_UNDERFLOW)
167 GL_ERROR_TRANSLATE(GL_TABLE_TOO_LARGE)
168 default:
169 return "UNKNOWN";
170 }
171#undef GL_ERROR_TRANSLATE
172}
173
174static void GL_ClearErrors(SDL_Renderer *renderer)
175{
176 GL_RenderData *data = (GL_RenderData *)renderer->internal;
177
178 if (!data->debug_enabled) {
179 return;
180 }
181 if (data->GL_ARB_debug_output_supported) {
182 if (data->errors) {
183 int i;
184 for (i = 0; i < data->errors; ++i) {
185 SDL_free(data->error_messages[i]);
186 }
187 SDL_free(data->error_messages);
188
189 data->errors = 0;
190 data->error_messages = NULL;
191 }
192 } else if (data->glGetError) {
193 while (data->glGetError() != GL_NO_ERROR) {
194 // continue;
195 }
196 }
197}
198
199static bool GL_CheckAllErrors(const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
200{
201 GL_RenderData *data = (GL_RenderData *)renderer->internal;
202 bool result = true;
203
204 if (!data->debug_enabled) {
205 return true;
206 }
207 if (data->GL_ARB_debug_output_supported) {
208 if (data->errors) {
209 int i;
210 for (i = 0; i < data->errors; ++i) {
211 SDL_SetError("%s: %s (%d): %s %s", prefix, file, line, function, data->error_messages[i]);
212 result = false;
213 }
214 GL_ClearErrors(renderer);
215 }
216 } else {
217 // check gl errors (can return multiple errors)
218 for (;;) {
219 GLenum error = data->glGetError();
220 if (error != GL_NO_ERROR) {
221 if (prefix == NULL || prefix[0] == '\0') {
222 prefix = "generic";
223 }
224 SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
225 result = false;
226 } else {
227 break;
228 }
229 }
230 }
231 return result;
232}
233
234#if 0
235#define GL_CheckError(prefix, renderer)
236#else
237#define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION)
238#endif
239
240static bool GL_LoadFunctions(GL_RenderData *data)
241{
242#ifdef __SDL_NOGETPROCADDR__
243#define SDL_PROC(ret, func, params) data->func = func;
244#else
245 bool result = true;
246#define SDL_PROC(ret, func, params) \
247 do { \
248 data->func = (ret (APIENTRY *) params)SDL_GL_GetProcAddress(#func); \
249 if (!data->func) { \
250 result = SDL_SetError("Couldn't load GL function %s: %s", #func, SDL_GetError()); \
251 } \
252 } while (0);
253#endif // __SDL_NOGETPROCADDR__
254
255#include "SDL_glfuncs.h"
256#undef SDL_PROC
257 return result;
258}
259
260static bool GL_ActivateRenderer(SDL_Renderer *renderer)
261{
262 GL_RenderData *data = (GL_RenderData *)renderer->internal;
263
264 if (SDL_GL_GetCurrentContext() != data->context) {
265 if (!SDL_GL_MakeCurrent(renderer->window, data->context)) {
266 return false;
267 }
268 }
269
270 GL_ClearErrors(renderer);
271
272 return true;
273}
274
275static void APIENTRY GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam)
276{
277 SDL_Renderer *renderer = (SDL_Renderer *)userParam;
278 GL_RenderData *data = (GL_RenderData *)renderer->internal;
279
280 if (type == GL_DEBUG_TYPE_ERROR_ARB) {
281 // Record this error
282 int errors = data->errors + 1;
283 char **error_messages = (char **)SDL_realloc(data->error_messages, errors * sizeof(*data->error_messages));
284 if (error_messages) {
285 data->errors = errors;
286 data->error_messages = error_messages;
287 data->error_messages[data->errors - 1] = SDL_strdup(message);
288 }
289 }
290
291 // If there's another error callback, pass it along, otherwise log it
292 if (data->next_error_callback) {
293 data->next_error_callback(source, type, id, severity, length, message, data->next_error_userparam);
294 } else {
295 if (type == GL_DEBUG_TYPE_ERROR_ARB) {
296 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", message);
297 } else {
298 SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "%s", message);
299 }
300 }
301}
302
303static GL_FBOList *GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
304{
305 GL_FBOList *result = data->framebuffers;
306
307 while (result && ((result->w != w) || (result->h != h))) {
308 result = result->next;
309 }
310
311 if (!result) {
312 result = (GL_FBOList *)SDL_malloc(sizeof(GL_FBOList));
313 if (result) {
314 result->w = w;
315 result->h = h;
316 data->glGenFramebuffersEXT(1, &result->FBO);
317 result->next = data->framebuffers;
318 data->framebuffers = result;
319 }
320 }
321 return result;
322}
323
324static void GL_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
325{
326 /* If the window x/y/w/h changed at all, assume the viewport has been
327 * changed behind our backs. x/y changes might seem weird but viewport
328 * resets have been observed on macOS at minimum!
329 */
330 if (event->type == SDL_EVENT_WINDOW_RESIZED ||
331 event->type == SDL_EVENT_WINDOW_MOVED) {
332 GL_RenderData *data = (GL_RenderData *)renderer->internal;
333 data->drawstate.viewport_dirty = true;
334 }
335}
336
337static GLenum GetBlendFunc(SDL_BlendFactor factor)
338{
339 switch (factor) {
340 case SDL_BLENDFACTOR_ZERO:
341 return GL_ZERO;
342 case SDL_BLENDFACTOR_ONE:
343 return GL_ONE;
344 case SDL_BLENDFACTOR_SRC_COLOR:
345 return GL_SRC_COLOR;
346 case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
347 return GL_ONE_MINUS_SRC_COLOR;
348 case SDL_BLENDFACTOR_SRC_ALPHA:
349 return GL_SRC_ALPHA;
350 case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
351 return GL_ONE_MINUS_SRC_ALPHA;
352 case SDL_BLENDFACTOR_DST_COLOR:
353 return GL_DST_COLOR;
354 case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
355 return GL_ONE_MINUS_DST_COLOR;
356 case SDL_BLENDFACTOR_DST_ALPHA:
357 return GL_DST_ALPHA;
358 case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
359 return GL_ONE_MINUS_DST_ALPHA;
360 default:
361 return GL_INVALID_ENUM;
362 }
363}
364
365static GLenum GetBlendEquation(SDL_BlendOperation operation)
366{
367 switch (operation) {
368 case SDL_BLENDOPERATION_ADD:
369 return GL_FUNC_ADD;
370 case SDL_BLENDOPERATION_SUBTRACT:
371 return GL_FUNC_SUBTRACT;
372 case SDL_BLENDOPERATION_REV_SUBTRACT:
373 return GL_FUNC_REVERSE_SUBTRACT;
374 case SDL_BLENDOPERATION_MINIMUM:
375 return GL_MIN;
376 case SDL_BLENDOPERATION_MAXIMUM:
377 return GL_MAX;
378 default:
379 return GL_INVALID_ENUM;
380 }
381}
382
383static bool GL_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
384{
385 SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
386 SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
387 SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
388 SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
389 SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
390 SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
391
392 if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
393 GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
394 GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
395 GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
396 GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
397 GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
398 return false;
399 }
400 if (colorOperation != alphaOperation) {
401 return false;
402 }
403 return true;
404}
405
406static bool convert_format(Uint32 pixel_format, GLint *internalFormat, GLenum *format, GLenum *type)
407{
408 switch (pixel_format) {
409 case SDL_PIXELFORMAT_ARGB8888:
410 case SDL_PIXELFORMAT_XRGB8888:
411 *internalFormat = GL_RGBA8;
412 *format = GL_BGRA;
413 *type = GL_UNSIGNED_BYTE; // previously GL_UNSIGNED_INT_8_8_8_8_REV, seeing if this is better in modern times.
414 break;
415 case SDL_PIXELFORMAT_ABGR8888:
416 case SDL_PIXELFORMAT_XBGR8888:
417 *internalFormat = GL_RGBA8;
418 *format = GL_RGBA;
419 *type = GL_UNSIGNED_BYTE; // previously GL_UNSIGNED_INT_8_8_8_8_REV, seeing if this is better in modern times.
420 break;
421 case SDL_PIXELFORMAT_YV12:
422 case SDL_PIXELFORMAT_IYUV:
423 case SDL_PIXELFORMAT_NV12:
424 case SDL_PIXELFORMAT_NV21:
425 *internalFormat = GL_LUMINANCE;
426 *format = GL_LUMINANCE;
427 *type = GL_UNSIGNED_BYTE;
428 break;
429#ifdef SDL_PLATFORM_MACOS
430 case SDL_PIXELFORMAT_UYVY:
431 *internalFormat = GL_RGB8;
432 *format = GL_YCBCR_422_APPLE;
433 *type = GL_UNSIGNED_SHORT_8_8_APPLE;
434 break;
435#endif
436 default:
437 return false;
438 }
439 return true;
440}
441
442static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
443{
444 GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
445 const GLenum textype = renderdata->textype;
446 GL_TextureData *data;
447 GLint internalFormat;
448 GLenum format, type;
449 int texture_w, texture_h;
450 GLenum scaleMode;
451
452 GL_ActivateRenderer(renderer);
453
454 renderdata->drawstate.texture = NULL; // we trash this state.
455 renderdata->drawstate.texturing_dirty = true; // we trash this state.
456
457 if (texture->access == SDL_TEXTUREACCESS_TARGET &&
458 !renderdata->GL_EXT_framebuffer_object_supported) {
459 return SDL_SetError("Render targets not supported by OpenGL");
460 }
461
462 if (!convert_format(texture->format, &internalFormat, &format, &type)) {
463 return SDL_SetError("Texture format %s not supported by OpenGL",
464 SDL_GetPixelFormatName(texture->format));
465 }
466
467 data = (GL_TextureData *)SDL_calloc(1, sizeof(*data));
468 if (!data) {
469 return false;
470 }
471
472 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
473 size_t size;
474 data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
475 size = (size_t)texture->h * data->pitch;
476 if (texture->format == SDL_PIXELFORMAT_YV12 ||
477 texture->format == SDL_PIXELFORMAT_IYUV) {
478 // Need to add size for the U and V planes
479 size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
480 }
481 if (texture->format == SDL_PIXELFORMAT_NV12 ||
482 texture->format == SDL_PIXELFORMAT_NV21) {
483 // Need to add size for the U/V plane
484 size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
485 }
486 data->pixels = SDL_calloc(1, size);
487 if (!data->pixels) {
488 SDL_free(data);
489 return false;
490 }
491 }
492
493 if (texture->access == SDL_TEXTUREACCESS_TARGET) {
494 data->fbo = GL_GetFBO(renderdata, texture->w, texture->h);
495 } else {
496 data->fbo = NULL;
497 }
498
499 data->texture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER, 0);
500 if (data->texture) {
501 data->texture_external = true;
502 } else {
503 GL_CheckError("", renderer);
504 renderdata->glGenTextures(1, &data->texture);
505 if (!GL_CheckError("glGenTextures()", renderer)) {
506 if (data->pixels) {
507 SDL_free(data->pixels);
508 }
509 SDL_free(data);
510 return false;
511 }
512 }
513 texture->internal = data;
514
515 if (renderdata->GL_ARB_texture_non_power_of_two_supported) {
516 texture_w = texture->w;
517 texture_h = texture->h;
518 data->texw = 1.0f;
519 data->texh = 1.0f;
520 } else if (renderdata->GL_ARB_texture_rectangle_supported) {
521 texture_w = texture->w;
522 texture_h = texture->h;
523 data->texw = (GLfloat)texture_w;
524 data->texh = (GLfloat)texture_h;
525 } else {
526 texture_w = SDL_powerof2(texture->w);
527 texture_h = SDL_powerof2(texture->h);
528 data->texw = (GLfloat)(texture->w) / texture_w;
529 data->texh = (GLfloat)texture->h / texture_h;
530 }
531 SDL_PropertiesID props = SDL_GetTextureProperties(texture);
532 SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_NUMBER, data->texture);
533 SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_TARGET_NUMBER, (Sint64) textype);
534 SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_OPENGL_TEX_W_FLOAT, data->texw);
535 SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_OPENGL_TEX_H_FLOAT, data->texh);
536
537 data->format = format;
538 data->formattype = type;
539 scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
540 renderdata->glEnable(textype);
541 renderdata->glBindTexture(textype, data->texture);
542 renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode);
543 renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, scaleMode);
544#ifdef SDL_PLATFORM_MACOS
545#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
546#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
547#endif
548#ifndef STORAGE_CACHED_APPLE
549#define STORAGE_CACHED_APPLE 0x85BE
550#endif
551#ifndef STORAGE_SHARED_APPLE
552#define STORAGE_SHARED_APPLE 0x85BF
553#endif
554 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
555 renderdata->glTexParameteri(textype, GL_TEXTURE_STORAGE_HINT_APPLE,
556 GL_STORAGE_SHARED_APPLE);
557 } else {
558 renderdata->glTexParameteri(textype, GL_TEXTURE_STORAGE_HINT_APPLE,
559 GL_STORAGE_CACHED_APPLE);
560 }
561 if (texture->access == SDL_TEXTUREACCESS_STREAMING && texture->format == SDL_PIXELFORMAT_ARGB8888 && (texture->w % 8) == 0) {
562 renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
563 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
564 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
565 (data->pitch / SDL_BYTESPERPIXEL(texture->format)));
566 renderdata->glTexImage2D(textype, 0, internalFormat, texture_w,
567 texture_h, 0, format, type, data->pixels);
568 renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
569 } else
570#endif
571 {
572 renderdata->glTexImage2D(textype, 0, internalFormat, texture_w,
573 texture_h, 0, format, type, NULL);
574 }
575 renderdata->glDisable(textype);
576 if (!GL_CheckError("glTexImage2D()", renderer)) {
577 return false;
578 }
579
580#ifdef SDL_HAVE_YUV
581 if (texture->format == SDL_PIXELFORMAT_YV12 ||
582 texture->format == SDL_PIXELFORMAT_IYUV) {
583 data->yuv = true;
584
585 data->utexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER, 0);
586 if (data->utexture) {
587 data->utexture_external = true;
588 } else {
589 renderdata->glGenTextures(1, &data->utexture);
590 }
591 data->vtexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER, 0);
592 if (data->vtexture) {
593 data->vtexture_external = true;
594 } else {
595 renderdata->glGenTextures(1, &data->vtexture);
596 }
597
598 renderdata->glBindTexture(textype, data->utexture);
599 renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
600 scaleMode);
601 renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
602 scaleMode);
603 renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
604 (texture_h + 1) / 2, 0, format, type, NULL);
605 SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture);
606
607 renderdata->glBindTexture(textype, data->vtexture);
608 renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
609 scaleMode);
610 renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
611 scaleMode);
612 renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
613 (texture_h + 1) / 2, 0, format, type, NULL);
614 SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
615 }
616
617 if (texture->format == SDL_PIXELFORMAT_NV12 ||
618 texture->format == SDL_PIXELFORMAT_NV21) {
619 data->nv12 = true;
620
621 data->utexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER, 0);
622 if (data->utexture) {
623 data->utexture_external = true;
624 } else {
625 renderdata->glGenTextures(1, &data->utexture);
626 }
627 renderdata->glBindTexture(textype, data->utexture);
628 renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
629 scaleMode);
630 renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
631 scaleMode);
632 renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2,
633 (texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
634 SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture);
635 }
636#endif
637
638 if (texture->format == SDL_PIXELFORMAT_ABGR8888 || texture->format == SDL_PIXELFORMAT_ARGB8888) {
639 data->shader = SHADER_RGBA;
640 } else {
641 data->shader = SHADER_RGB;
642 }
643
644#ifdef SDL_HAVE_YUV
645 if (data->yuv || data->nv12) {
646 if (data->yuv) {
647 data->shader = SHADER_YUV;
648 } else if (texture->format == SDL_PIXELFORMAT_NV12) {
649 if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", false)) {
650 data->shader = SHADER_NV12_RG;
651 } else {
652 data->shader = SHADER_NV12_RA;
653 }
654 } else {
655 if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", false)) {
656 data->shader = SHADER_NV21_RG;
657 } else {
658 data->shader = SHADER_NV21_RA;
659 }
660 }
661 data->shader_params = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8);
662 if (!data->shader_params) {
663 return SDL_SetError("Unsupported YUV colorspace");
664 }
665 }
666#endif // SDL_HAVE_YUV
667
668 return GL_CheckError("", renderer);
669}
670
671static bool GL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
672 const SDL_Rect *rect, const void *pixels, int pitch)
673{
674 GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
675 const GLenum textype = renderdata->textype;
676 GL_TextureData *data = (GL_TextureData *)texture->internal;
677 const int texturebpp = SDL_BYTESPERPIXEL(texture->format);
678
679 SDL_assert_release(texturebpp != 0); // otherwise, division by zero later.
680
681 GL_ActivateRenderer(renderer);
682
683 renderdata->drawstate.texture = NULL; // we trash this state.
684
685 renderdata->glBindTexture(textype, data->texture);
686 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
687 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / texturebpp));
688 renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w,
689 rect->h, data->format, data->formattype,
690 pixels);
691#ifdef SDL_HAVE_YUV
692 if (data->yuv) {
693 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
694
695 // Skip to the correct offset into the next texture
696 pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
697 if (texture->format == SDL_PIXELFORMAT_YV12) {
698 renderdata->glBindTexture(textype, data->vtexture);
699 } else {
700 renderdata->glBindTexture(textype, data->utexture);
701 }
702 renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
703 (rect->w + 1) / 2, (rect->h + 1) / 2,
704 data->format, data->formattype, pixels);
705
706 // Skip to the correct offset into the next texture
707 pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
708 if (texture->format == SDL_PIXELFORMAT_YV12) {
709 renderdata->glBindTexture(textype, data->utexture);
710 } else {
711 renderdata->glBindTexture(textype, data->vtexture);
712 }
713 renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
714 (rect->w + 1) / 2, (rect->h + 1) / 2,
715 data->format, data->formattype, pixels);
716 }
717
718 if (data->nv12) {
719 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
720
721 // Skip to the correct offset into the next texture
722 pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
723 renderdata->glBindTexture(textype, data->utexture);
724 renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
725 (rect->w + 1) / 2, (rect->h + 1) / 2,
726 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
727 }
728#endif
729 return GL_CheckError("glTexSubImage2D()", renderer);
730}
731
732#ifdef SDL_HAVE_YUV
733static bool GL_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
734 const SDL_Rect *rect,
735 const Uint8 *Yplane, int Ypitch,
736 const Uint8 *Uplane, int Upitch,
737 const Uint8 *Vplane, int Vpitch)
738{
739 GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
740 const GLenum textype = renderdata->textype;
741 GL_TextureData *data = (GL_TextureData *)texture->internal;
742
743 GL_ActivateRenderer(renderer);
744
745 renderdata->drawstate.texture = NULL; // we trash this state.
746
747 renderdata->glBindTexture(textype, data->texture);
748 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
749 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Ypitch);
750 renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w,
751 rect->h, data->format, data->formattype,
752 Yplane);
753
754 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch);
755 renderdata->glBindTexture(textype, data->utexture);
756 renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
757 (rect->w + 1) / 2, (rect->h + 1) / 2,
758 data->format, data->formattype, Uplane);
759
760 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch);
761 renderdata->glBindTexture(textype, data->vtexture);
762 renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
763 (rect->w + 1) / 2, (rect->h + 1) / 2,
764 data->format, data->formattype, Vplane);
765
766 return GL_CheckError("glTexSubImage2D()", renderer);
767}
768
769static bool GL_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
770 const SDL_Rect *rect,
771 const Uint8 *Yplane, int Ypitch,
772 const Uint8 *UVplane, int UVpitch)
773{
774 GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
775 const GLenum textype = renderdata->textype;
776 GL_TextureData *data = (GL_TextureData *)texture->internal;
777
778 GL_ActivateRenderer(renderer);
779
780 renderdata->drawstate.texture = NULL; // we trash this state.
781
782 renderdata->glBindTexture(textype, data->texture);
783 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
784 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Ypitch);
785 renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w,
786 rect->h, data->format, data->formattype,
787 Yplane);
788
789 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, UVpitch / 2);
790 renderdata->glBindTexture(textype, data->utexture);
791 renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
792 (rect->w + 1) / 2, (rect->h + 1) / 2,
793 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UVplane);
794
795 return GL_CheckError("glTexSubImage2D()", renderer);
796}
797#endif
798
799static bool GL_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
800 const SDL_Rect *rect, void **pixels, int *pitch)
801{
802 GL_TextureData *data = (GL_TextureData *)texture->internal;
803
804 data->locked_rect = *rect;
805 *pixels =
806 (void *)((Uint8 *)data->pixels + rect->y * data->pitch +
807 rect->x * SDL_BYTESPERPIXEL(texture->format));
808 *pitch = data->pitch;
809 return true;
810}
811
812static void GL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
813{
814 GL_TextureData *data = (GL_TextureData *)texture->internal;
815 const SDL_Rect *rect;
816 void *pixels;
817
818 rect = &data->locked_rect;
819 pixels =
820 (void *)((Uint8 *)data->pixels + rect->y * data->pitch +
821 rect->x * SDL_BYTESPERPIXEL(texture->format));
822 GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
823}
824
825static void GL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
826{
827 GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
828 const GLenum textype = renderdata->textype;
829 GL_TextureData *data = (GL_TextureData *)texture->internal;
830 GLenum glScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
831
832 renderdata->glBindTexture(textype, data->texture);
833 renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
834 renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
835
836#ifdef SDL_HAVE_YUV
837 if (texture->format == SDL_PIXELFORMAT_YV12 ||
838 texture->format == SDL_PIXELFORMAT_IYUV) {
839 renderdata->glBindTexture(textype, data->utexture);
840 renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
841 renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
842
843 renderdata->glBindTexture(textype, data->vtexture);
844 renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
845 renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
846 }
847
848 if (texture->format == SDL_PIXELFORMAT_NV12 ||
849 texture->format == SDL_PIXELFORMAT_NV21) {
850 renderdata->glBindTexture(textype, data->utexture);
851 renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
852 renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
853 }
854#endif
855}
856
857static bool GL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
858{
859 GL_RenderData *data = (GL_RenderData *)renderer->internal;
860 GL_TextureData *texturedata;
861 GLenum status;
862
863 GL_ActivateRenderer(renderer);
864
865 if (!data->GL_EXT_framebuffer_object_supported) {
866 return SDL_SetError("Render targets not supported by OpenGL");
867 }
868
869 data->drawstate.viewport_dirty = true;
870
871 if (!texture) {
872 data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
873 return true;
874 }
875
876 texturedata = (GL_TextureData *)texture->internal;
877 data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texturedata->fbo->FBO);
878 // TODO: check if texture pixel format allows this operation
879 data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, data->textype, texturedata->texture, 0);
880 // Check FBO status
881 status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
882 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
883 return SDL_SetError("glFramebufferTexture2DEXT() failed");
884 }
885 return true;
886}
887
888/* !!! FIXME: all these Queue* calls set up the vertex buffer the way the immediate mode
889 !!! FIXME: renderer wants it, but this might want to operate differently if we move to
890 !!! FIXME: VBOs at some point. */
891static bool GL_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
892{
893 return true; // nothing to do in this backend.
894}
895
896static bool GL_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
897{
898 GLfloat *verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(GLfloat), 0, &cmd->data.draw.first);
899 int i;
900
901 if (!verts) {
902 return false;
903 }
904
905 cmd->data.draw.count = count;
906 for (i = 0; i < count; i++) {
907 *(verts++) = 0.5f + points[i].x;
908 *(verts++) = 0.5f + points[i].y;
909 }
910
911 return true;
912}
913
914static bool GL_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
915{
916 int i;
917 GLfloat prevx, prevy;
918 const size_t vertlen = (sizeof(GLfloat) * 2) * count;
919 GLfloat *verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
920
921 if (!verts) {
922 return false;
923 }
924 cmd->data.draw.count = count;
925
926 // 0.5f offset to hit the center of the pixel.
927 prevx = 0.5f + points->x;
928 prevy = 0.5f + points->y;
929 *(verts++) = prevx;
930 *(verts++) = prevy;
931
932 /* bump the end of each line segment out a quarter of a pixel, to provoke
933 the diamond-exit rule. Without this, you won't just drop the last
934 pixel of the last line segment, but you might also drop pixels at the
935 edge of any given line segment along the way too. */
936 for (i = 1; i < count; i++) {
937 const GLfloat xstart = prevx;
938 const GLfloat ystart = prevy;
939 const GLfloat xend = points[i].x + 0.5f; // 0.5f to hit pixel center.
940 const GLfloat yend = points[i].y + 0.5f;
941 // bump a little in the direction we are moving in.
942 const GLfloat deltax = xend - xstart;
943 const GLfloat deltay = yend - ystart;
944 const GLfloat angle = SDL_atan2f(deltay, deltax);
945 prevx = xend + (SDL_cosf(angle) * 0.25f);
946 prevy = yend + (SDL_sinf(angle) * 0.25f);
947 *(verts++) = prevx;
948 *(verts++) = prevy;
949 }
950
951 return true;
952}
953
954static bool GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
955 const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride,
956 int num_vertices, const void *indices, int num_indices, int size_indices,
957 float scale_x, float scale_y)
958{
959 GL_TextureData *texturedata = NULL;
960 int i;
961 int count = indices ? num_indices : num_vertices;
962 GLfloat *verts;
963 size_t sz = 2 * sizeof(GLfloat) + 4 * sizeof(GLfloat) + (texture ? 2 : 0) * sizeof(GLfloat);
964 const float color_scale = cmd->data.draw.color_scale;
965
966 verts = (GLfloat *)SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first);
967 if (!verts) {
968 return false;
969 }
970
971 if (texture) {
972 texturedata = (GL_TextureData *)texture->internal;
973 }
974
975 cmd->data.draw.count = count;
976 size_indices = indices ? size_indices : 0;
977
978 for (i = 0; i < count; i++) {
979 int j;
980 float *xy_;
981 SDL_FColor *col_;
982 if (size_indices == 4) {
983 j = ((const Uint32 *)indices)[i];
984 } else if (size_indices == 2) {
985 j = ((const Uint16 *)indices)[i];
986 } else if (size_indices == 1) {
987 j = ((const Uint8 *)indices)[i];
988 } else {
989 j = i;
990 }
991
992 xy_ = (float *)((char *)xy + j * xy_stride);
993
994 *(verts++) = xy_[0] * scale_x;
995 *(verts++) = xy_[1] * scale_y;
996
997 col_ = (SDL_FColor *)((char *)color + j * color_stride);
998 *(verts++) = col_->r * color_scale;
999 *(verts++) = col_->g * color_scale;
1000 *(verts++) = col_->b * color_scale;
1001 *(verts++) = col_->a;
1002
1003 if (texture) {
1004 float *uv_ = (float *)((char *)uv + j * uv_stride);
1005 *(verts++) = uv_[0] * texturedata->texw;
1006 *(verts++) = uv_[1] * texturedata->texh;
1007 }
1008 }
1009 return true;
1010}
1011
1012static bool SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader shader, const float *shader_params)
1013{
1014 const SDL_BlendMode blend = cmd->data.draw.blend;
1015 bool vertex_array;
1016 bool color_array;
1017 bool texture_array;
1018
1019 if (data->drawstate.viewport_dirty) {
1020 const bool istarget = data->drawstate.target != NULL;
1021 const SDL_Rect *viewport = &data->drawstate.viewport;
1022 data->glMatrixMode(GL_PROJECTION);
1023 data->glLoadIdentity();
1024 data->glViewport(viewport->x,
1025 istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
1026 viewport->w, viewport->h);
1027 if (viewport->w && viewport->h) {
1028 data->glOrtho((GLdouble)0, (GLdouble)viewport->w,
1029 (GLdouble)(istarget ? 0 : viewport->h),
1030 (GLdouble)(istarget ? viewport->h : 0),
1031 0.0, 1.0);
1032 }
1033 data->glMatrixMode(GL_MODELVIEW);
1034 data->drawstate.viewport_dirty = false;
1035 }
1036
1037 if (data->drawstate.cliprect_enabled_dirty) {
1038 if (!data->drawstate.cliprect_enabled) {
1039 data->glDisable(GL_SCISSOR_TEST);
1040 } else {
1041 data->glEnable(GL_SCISSOR_TEST);
1042 }
1043 data->drawstate.cliprect_enabled_dirty = false;
1044 }
1045
1046 if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
1047 const SDL_Rect *viewport = &data->drawstate.viewport;
1048 const SDL_Rect *rect = &data->drawstate.cliprect;
1049 data->glScissor(viewport->x + rect->x,
1050 data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
1051 rect->w, rect->h);
1052 data->drawstate.cliprect_dirty = false;
1053 }
1054
1055 if (blend != data->drawstate.blend) {
1056 if (blend == SDL_BLENDMODE_NONE) {
1057 data->glDisable(GL_BLEND);
1058 } else {
1059 data->glEnable(GL_BLEND);
1060 data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
1061 GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
1062 GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
1063 GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
1064 data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
1065 }
1066 data->drawstate.blend = blend;
1067 }
1068
1069 if (data->shaders &&
1070 (shader != data->drawstate.shader || shader_params != data->drawstate.shader_params)) {
1071 GL_SelectShader(data->shaders, shader, shader_params);
1072 data->drawstate.shader = shader;
1073 data->drawstate.shader_params = shader_params;
1074 }
1075
1076 if (data->drawstate.texturing_dirty || ((cmd->data.draw.texture != NULL) != data->drawstate.texturing)) {
1077 if (!cmd->data.draw.texture) {
1078 data->glDisable(data->textype);
1079 data->drawstate.texturing = false;
1080 } else {
1081 data->glEnable(data->textype);
1082 data->drawstate.texturing = true;
1083 }
1084 data->drawstate.texturing_dirty = false;
1085 }
1086
1087 vertex_array = cmd->command == SDL_RENDERCMD_DRAW_POINTS || cmd->command == SDL_RENDERCMD_DRAW_LINES || cmd->command == SDL_RENDERCMD_GEOMETRY;
1088 color_array = cmd->command == SDL_RENDERCMD_GEOMETRY;
1089 texture_array = cmd->data.draw.texture != NULL;
1090
1091 if (vertex_array != data->drawstate.vertex_array) {
1092 if (vertex_array) {
1093 data->glEnableClientState(GL_VERTEX_ARRAY);
1094 } else {
1095 data->glDisableClientState(GL_VERTEX_ARRAY);
1096 }
1097 data->drawstate.vertex_array = vertex_array;
1098 }
1099
1100 if (color_array != data->drawstate.color_array) {
1101 if (color_array) {
1102 data->glEnableClientState(GL_COLOR_ARRAY);
1103 } else {
1104 data->glDisableClientState(GL_COLOR_ARRAY);
1105 }
1106 data->drawstate.color_array = color_array;
1107 }
1108
1109 /* This is a little awkward but should avoid texcoord arrays getting into
1110 a bad state if the application is manually binding textures */
1111 if (texture_array != data->drawstate.texture_array) {
1112 if (texture_array) {
1113 data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1114 } else {
1115 data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1116 }
1117 data->drawstate.texture_array = texture_array;
1118 }
1119
1120 return true;
1121}
1122
1123static bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
1124{
1125 switch (addressMode) {
1126 case SDL_TEXTURE_ADDRESS_CLAMP:
1127 data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1128 data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1129 break;
1130 case SDL_TEXTURE_ADDRESS_WRAP:
1131 data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_REPEAT);
1132 data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_REPEAT);
1133 break;
1134 default:
1135 return SDL_SetError("Unknown texture address mode: %d", addressMode);
1136 }
1137 return true;
1138}
1139
1140static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
1141{
1142 SDL_Texture *texture = cmd->data.draw.texture;
1143 const GL_TextureData *texturedata = (GL_TextureData *)texture->internal;
1144
1145 SetDrawState(data, cmd, texturedata->shader, texturedata->shader_params);
1146
1147 if (texture != data->drawstate.texture) {
1148 const GLenum textype = data->textype;
1149#ifdef SDL_HAVE_YUV
1150 if (texturedata->yuv) {
1151 if (data->GL_ARB_multitexture_supported) {
1152 data->glActiveTextureARB(GL_TEXTURE2_ARB);
1153 }
1154 data->glBindTexture(textype, texturedata->vtexture);
1155
1156 if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
1157 return false;
1158 }
1159
1160 if (data->GL_ARB_multitexture_supported) {
1161 data->glActiveTextureARB(GL_TEXTURE1_ARB);
1162 }
1163 data->glBindTexture(textype, texturedata->utexture);
1164
1165 if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
1166 return false;
1167 }
1168 }
1169 if (texturedata->nv12) {
1170 if (data->GL_ARB_multitexture_supported) {
1171 data->glActiveTextureARB(GL_TEXTURE1_ARB);
1172 }
1173 data->glBindTexture(textype, texturedata->utexture);
1174
1175 if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
1176 return false;
1177 }
1178 }
1179#endif
1180 if (data->GL_ARB_multitexture_supported) {
1181 data->glActiveTextureARB(GL_TEXTURE0_ARB);
1182 }
1183 data->glBindTexture(textype, texturedata->texture);
1184
1185 if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
1186 return false;
1187 }
1188
1189 data->drawstate.texture = texture;
1190 }
1191
1192 return true;
1193}
1194
1195static void GL_InvalidateCachedState(SDL_Renderer *renderer)
1196{
1197 GL_DrawStateCache *cache = &((GL_RenderData *)renderer->internal)->drawstate;
1198 cache->viewport_dirty = true;
1199 cache->texture = NULL;
1200 cache->drawablew = 0;
1201 cache->drawableh = 0;
1202 cache->blend = SDL_BLENDMODE_INVALID;
1203 cache->shader = SHADER_INVALID;
1204 cache->cliprect_enabled_dirty = true;
1205 cache->cliprect_dirty = true;
1206 cache->texturing_dirty = true;
1207 cache->vertex_array = false; // !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively.
1208 cache->color_array = false; // !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively.
1209 cache->texture_array = false; // !!! FIXME: this resets to false at the end of GL_RunCommandQueue, but we could cache this more aggressively.
1210 cache->color_dirty = true;
1211 cache->clear_color_dirty = true;
1212}
1213
1214static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
1215{
1216 // !!! FIXME: it'd be nice to use a vertex buffer instead of immediate mode...
1217 GL_RenderData *data = (GL_RenderData *)renderer->internal;
1218
1219 if (!GL_ActivateRenderer(renderer)) {
1220 return false;
1221 }
1222
1223 data->drawstate.target = renderer->target;
1224 if (!data->drawstate.target) {
1225 int w, h;
1226 SDL_GetWindowSizeInPixels(renderer->window, &w, &h);
1227 if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
1228 data->drawstate.viewport_dirty = true; // if the window dimensions changed, invalidate the current viewport, etc.
1229 data->drawstate.cliprect_dirty = true;
1230 data->drawstate.drawablew = w;
1231 data->drawstate.drawableh = h;
1232 }
1233 }
1234
1235#ifdef SDL_PLATFORM_MACOS
1236 // On macOS on older systems, the OpenGL view change and resize events aren't
1237 // necessarily synchronized, so just always reset it.
1238 // Workaround for: https://discourse.libsdl.org/t/sdl-2-0-22-prerelease/35306/6
1239 data->drawstate.viewport_dirty = true;
1240#endif
1241
1242 while (cmd) {
1243 switch (cmd->command) {
1244 case SDL_RENDERCMD_SETDRAWCOLOR:
1245 {
1246 const float r = cmd->data.color.color.r * cmd->data.color.color_scale;
1247 const float g = cmd->data.color.color.g * cmd->data.color.color_scale;
1248 const float b = cmd->data.color.color.b * cmd->data.color.color_scale;
1249 const float a = cmd->data.color.color.a;
1250 if (data->drawstate.color_dirty ||
1251 (r != data->drawstate.color.r) ||
1252 (g != data->drawstate.color.g) ||
1253 (b != data->drawstate.color.b) ||
1254 (a != data->drawstate.color.a)) {
1255 data->glColor4f(r, g, b, a);
1256 data->drawstate.color.r = r;
1257 data->drawstate.color.g = g;
1258 data->drawstate.color.b = b;
1259 data->drawstate.color.a = a;
1260 data->drawstate.color_dirty = false;
1261 }
1262 break;
1263 }
1264
1265 case SDL_RENDERCMD_SETVIEWPORT:
1266 {
1267 SDL_Rect *viewport = &data->drawstate.viewport;
1268 if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) {
1269 SDL_copyp(viewport, &cmd->data.viewport.rect);
1270 data->drawstate.viewport_dirty = true;
1271 data->drawstate.cliprect_dirty = true;
1272 }
1273 break;
1274 }
1275
1276 case SDL_RENDERCMD_SETCLIPRECT:
1277 {
1278 const SDL_Rect *rect = &cmd->data.cliprect.rect;
1279 if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
1280 data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
1281 data->drawstate.cliprect_enabled_dirty = true;
1282 }
1283
1284 if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) {
1285 SDL_copyp(&data->drawstate.cliprect, rect);
1286 data->drawstate.cliprect_dirty = true;
1287 }
1288 break;
1289 }
1290
1291 case SDL_RENDERCMD_CLEAR:
1292 {
1293 const float r = cmd->data.color.color.r * cmd->data.color.color_scale;
1294 const float g = cmd->data.color.color.g * cmd->data.color.color_scale;
1295 const float b = cmd->data.color.color.b * cmd->data.color.color_scale;
1296 const float a = cmd->data.color.color.a;
1297 if (data->drawstate.clear_color_dirty ||
1298 (r != data->drawstate.clear_color.r) ||
1299 (g != data->drawstate.clear_color.g) ||
1300 (b != data->drawstate.clear_color.b) ||
1301 (a != data->drawstate.clear_color.a)) {
1302 data->glClearColor(r, g, b, a);
1303 data->drawstate.clear_color.r = r;
1304 data->drawstate.clear_color.g = g;
1305 data->drawstate.clear_color.b = b;
1306 data->drawstate.clear_color.a = a;
1307 data->drawstate.clear_color_dirty = false;
1308 }
1309
1310 if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
1311 data->glDisable(GL_SCISSOR_TEST);
1312 data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
1313 }
1314
1315 data->glClear(GL_COLOR_BUFFER_BIT);
1316 break;
1317 }
1318
1319 case SDL_RENDERCMD_FILL_RECTS: // unused
1320 break;
1321
1322 case SDL_RENDERCMD_COPY: // unused
1323 break;
1324
1325 case SDL_RENDERCMD_COPY_EX: // unused
1326 break;
1327
1328 case SDL_RENDERCMD_DRAW_LINES:
1329 {
1330 if (SetDrawState(data, cmd, SHADER_SOLID, NULL)) {
1331 size_t count = cmd->data.draw.count;
1332 const GLfloat *verts = (GLfloat *)(((Uint8 *)vertices) + cmd->data.draw.first);
1333
1334 // SetDrawState handles glEnableClientState.
1335 data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, verts);
1336
1337 if (count > 2) {
1338 // joined lines cannot be grouped
1339 data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)count);
1340 } else {
1341 // let's group non joined lines
1342 SDL_RenderCommand *finalcmd = cmd;
1343 SDL_RenderCommand *nextcmd = cmd->next;
1344 SDL_BlendMode thisblend = cmd->data.draw.blend;
1345
1346 while (nextcmd) {
1347 const SDL_RenderCommandType nextcmdtype = nextcmd->command;
1348 if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
1349 break; // can't go any further on this draw call, different render command up next.
1350 } else if (nextcmd->data.draw.count != 2) {
1351 break; // can't go any further on this draw call, those are joined lines
1352 } else if (nextcmd->data.draw.blend != thisblend) {
1353 break; // can't go any further on this draw call, different blendmode copy up next.
1354 } else {
1355 finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
1356 count += nextcmd->data.draw.count;
1357 }
1358 nextcmd = nextcmd->next;
1359 }
1360
1361 data->glDrawArrays(GL_LINES, 0, (GLsizei)count);
1362 cmd = finalcmd; // skip any copy commands we just combined in here.
1363 }
1364 }
1365 break;
1366 }
1367
1368 case SDL_RENDERCMD_DRAW_POINTS:
1369 case SDL_RENDERCMD_GEOMETRY:
1370 {
1371 /* as long as we have the same copy command in a row, with the
1372 same texture, we can combine them all into a single draw call. */
1373 SDL_Texture *thistexture = cmd->data.draw.texture;
1374 SDL_BlendMode thisblend = cmd->data.draw.blend;
1375 const SDL_RenderCommandType thiscmdtype = cmd->command;
1376 SDL_RenderCommand *finalcmd = cmd;
1377 SDL_RenderCommand *nextcmd = cmd->next;
1378 size_t count = cmd->data.draw.count;
1379 int ret;
1380 while (nextcmd) {
1381 const SDL_RenderCommandType nextcmdtype = nextcmd->command;
1382 if (nextcmdtype != thiscmdtype) {
1383 break; // can't go any further on this draw call, different render command up next.
1384 } else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
1385 break; // can't go any further on this draw call, different texture/blendmode copy up next.
1386 } else {
1387 finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
1388 count += nextcmd->data.draw.count;
1389 }
1390 nextcmd = nextcmd->next;
1391 }
1392
1393 if (thistexture) {
1394 ret = SetCopyState(data, cmd);
1395 } else {
1396 ret = SetDrawState(data, cmd, SHADER_SOLID, NULL);
1397 }
1398
1399 if (ret) {
1400 const GLfloat *verts = (GLfloat *)(((Uint8 *)vertices) + cmd->data.draw.first);
1401 int op = GL_TRIANGLES; // SDL_RENDERCMD_GEOMETRY
1402 if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
1403 op = GL_POINTS;
1404 }
1405
1406 if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
1407 // SetDrawState handles glEnableClientState.
1408 data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, verts);
1409 } else {
1410 // SetDrawState handles glEnableClientState.
1411 if (thistexture) {
1412 data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 8, verts + 0);
1413 data->glColorPointer(4, GL_FLOAT, sizeof(float) * 8, verts + 2);
1414 data->glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 8, verts + 6);
1415 } else {
1416 data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 6, verts + 0);
1417 data->glColorPointer(4, GL_FLOAT, sizeof(float) * 6, verts + 2);
1418 }
1419 }
1420
1421 data->glDrawArrays(op, 0, (GLsizei)count);
1422
1423 // Restore previously set color when we're done.
1424 if (thiscmdtype != SDL_RENDERCMD_DRAW_POINTS) {
1425 const float r = data->drawstate.color.r;
1426 const float g = data->drawstate.color.g;
1427 const float b = data->drawstate.color.b;
1428 const float a = data->drawstate.color.a;
1429 data->glColor4f(r, g, b, a);
1430 }
1431 }
1432
1433 cmd = finalcmd; // skip any copy commands we just combined in here.
1434 break;
1435 }
1436
1437 case SDL_RENDERCMD_NO_OP:
1438 break;
1439 }
1440
1441 cmd = cmd->next;
1442 }
1443
1444 /* Turn off vertex array state when we're done, in case external code
1445 relies on it being off. */
1446 if (data->drawstate.vertex_array) {
1447 data->glDisableClientState(GL_VERTEX_ARRAY);
1448 data->drawstate.vertex_array = false;
1449 }
1450 if (data->drawstate.color_array) {
1451 data->glDisableClientState(GL_COLOR_ARRAY);
1452 data->drawstate.color_array = false;
1453 }
1454 if (data->drawstate.texture_array) {
1455 data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1456 data->drawstate.texture_array = false;
1457 }
1458
1459 return GL_CheckError("", renderer);
1460}
1461
1462static SDL_Surface *GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
1463{
1464 GL_RenderData *data = (GL_RenderData *)renderer->internal;
1465 SDL_PixelFormat format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ARGB8888;
1466 GLint internalFormat;
1467 GLenum targetFormat, type;
1468 SDL_Surface *surface;
1469
1470 GL_ActivateRenderer(renderer);
1471
1472 if (!convert_format(format, &internalFormat, &targetFormat, &type)) {
1473 SDL_SetError("Texture format %s not supported by OpenGL", SDL_GetPixelFormatName(format));
1474 return NULL;
1475 }
1476
1477 surface = SDL_CreateSurface(rect->w, rect->h, format);
1478 if (!surface) {
1479 return NULL;
1480 }
1481
1482 int y = rect->y;
1483 if (!renderer->target) {
1484 int w, h;
1485 SDL_GetRenderOutputSize(renderer, &w, &h);
1486 y = (h - y) - rect->h;
1487 }
1488
1489 data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
1490 data->glPixelStorei(GL_PACK_ROW_LENGTH, (surface->pitch / SDL_BYTESPERPIXEL(format)));
1491 data->glReadPixels(rect->x, y, rect->w, rect->h, targetFormat, type, surface->pixels);
1492
1493 if (!GL_CheckError("glReadPixels()", renderer)) {
1494 SDL_DestroySurface(surface);
1495 return NULL;
1496 }
1497
1498 // Flip the rows to be top-down if necessary
1499 if (!renderer->target) {
1500 SDL_FlipSurface(surface, SDL_FLIP_VERTICAL);
1501 }
1502 return surface;
1503}
1504
1505static bool GL_RenderPresent(SDL_Renderer *renderer)
1506{
1507 GL_ActivateRenderer(renderer);
1508
1509 return SDL_GL_SwapWindow(renderer->window);
1510}
1511
1512static void GL_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
1513{
1514 GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
1515 GL_TextureData *data = (GL_TextureData *)texture->internal;
1516
1517 GL_ActivateRenderer(renderer);
1518
1519 if (renderdata->drawstate.texture == texture) {
1520 renderdata->drawstate.texture = NULL;
1521 }
1522 if (renderdata->drawstate.target == texture) {
1523 renderdata->drawstate.target = NULL;
1524 }
1525
1526 if (!data) {
1527 return;
1528 }
1529 if (data->texture && !data->texture_external) {
1530 renderdata->glDeleteTextures(1, &data->texture);
1531 }
1532#ifdef SDL_HAVE_YUV
1533 if (data->yuv) {
1534 if (!data->utexture_external) {
1535 renderdata->glDeleteTextures(1, &data->utexture);
1536 }
1537 if (!data->vtexture_external) {
1538 renderdata->glDeleteTextures(1, &data->vtexture);
1539 }
1540 }
1541 if (data->nv12) {
1542 if (!data->utexture_external) {
1543 renderdata->glDeleteTextures(1, &data->utexture);
1544 }
1545 }
1546#endif
1547 SDL_free(data->pixels);
1548 SDL_free(data);
1549 texture->internal = NULL;
1550}
1551
1552static void GL_DestroyRenderer(SDL_Renderer *renderer)
1553{
1554 GL_RenderData *data = (GL_RenderData *)renderer->internal;
1555
1556 if (data) {
1557 if (data->context) {
1558 // make sure we delete the right resources!
1559 GL_ActivateRenderer(renderer);
1560 }
1561
1562 GL_ClearErrors(renderer);
1563 if (data->GL_ARB_debug_output_supported) {
1564 PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC)SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
1565
1566 // Uh oh, we don't have a safe way of removing ourselves from the callback chain, if it changed after we set our callback.
1567 // For now, just always replace the callback with the original one
1568 glDebugMessageCallbackARBFunc(data->next_error_callback, data->next_error_userparam);
1569 }
1570 if (data->shaders) {
1571 GL_DestroyShaderContext(data->shaders);
1572 }
1573 if (data->context) {
1574 while (data->framebuffers) {
1575 GL_FBOList *nextnode = data->framebuffers->next;
1576 // delete the framebuffer object
1577 data->glDeleteFramebuffersEXT(1, &data->framebuffers->FBO);
1578 GL_CheckError("", renderer);
1579 SDL_free(data->framebuffers);
1580 data->framebuffers = nextnode;
1581 }
1582 SDL_GL_DestroyContext(data->context);
1583 }
1584 SDL_free(data);
1585 }
1586}
1587
1588static bool GL_SetVSync(SDL_Renderer *renderer, const int vsync)
1589{
1590 int interval = 0;
1591
1592 if (!SDL_GL_SetSwapInterval(vsync)) {
1593 return false;
1594 }
1595
1596 if (!SDL_GL_GetSwapInterval(&interval)) {
1597 return false;
1598 }
1599
1600 if (interval != vsync) {
1601 return SDL_Unsupported();
1602 }
1603 return true;
1604}
1605
1606static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
1607{
1608 GL_RenderData *data = NULL;
1609 GLint value;
1610 SDL_WindowFlags window_flags;
1611 int profile_mask = 0, major = 0, minor = 0;
1612 bool changed_window = false;
1613 const char *hint;
1614 bool non_power_of_two_supported = false;
1615
1616 SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
1617 SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
1618 SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
1619
1620#ifndef SDL_VIDEO_VITA_PVR_OGL
1621 SDL_SyncWindow(window);
1622 window_flags = SDL_GetWindowFlags(window);
1623 if (!(window_flags & SDL_WINDOW_OPENGL) ||
1624 profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
1625
1626 changed_window = true;
1627 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
1628 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
1629 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
1630
1631 if (!SDL_RecreateWindow(window, (window_flags & ~(SDL_WINDOW_VULKAN | SDL_WINDOW_METAL)) | SDL_WINDOW_OPENGL)) {
1632 goto error;
1633 }
1634 }
1635#endif
1636
1637 SDL_SetupRendererColorspace(renderer, create_props);
1638
1639 if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
1640 SDL_SetError("Unsupported output colorspace");
1641 goto error;
1642 }
1643
1644 data = (GL_RenderData *)SDL_calloc(1, sizeof(*data));
1645 if (!data) {
1646 goto error;
1647 }
1648
1649 renderer->WindowEvent = GL_WindowEvent;
1650 renderer->SupportsBlendMode = GL_SupportsBlendMode;
1651 renderer->CreateTexture = GL_CreateTexture;
1652 renderer->UpdateTexture = GL_UpdateTexture;
1653#ifdef SDL_HAVE_YUV
1654 renderer->UpdateTextureYUV = GL_UpdateTextureYUV;
1655 renderer->UpdateTextureNV = GL_UpdateTextureNV;
1656#endif
1657 renderer->LockTexture = GL_LockTexture;
1658 renderer->UnlockTexture = GL_UnlockTexture;
1659 renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
1660 renderer->SetRenderTarget = GL_SetRenderTarget;
1661 renderer->QueueSetViewport = GL_QueueNoOp;
1662 renderer->QueueSetDrawColor = GL_QueueNoOp;
1663 renderer->QueueDrawPoints = GL_QueueDrawPoints;
1664 renderer->QueueDrawLines = GL_QueueDrawLines;
1665 renderer->QueueGeometry = GL_QueueGeometry;
1666 renderer->InvalidateCachedState = GL_InvalidateCachedState;
1667 renderer->RunCommandQueue = GL_RunCommandQueue;
1668 renderer->RenderReadPixels = GL_RenderReadPixels;
1669 renderer->RenderPresent = GL_RenderPresent;
1670 renderer->DestroyTexture = GL_DestroyTexture;
1671 renderer->DestroyRenderer = GL_DestroyRenderer;
1672 renderer->SetVSync = GL_SetVSync;
1673 renderer->internal = data;
1674 GL_InvalidateCachedState(renderer);
1675 renderer->window = window;
1676
1677 renderer->name = GL_RenderDriver.name;
1678 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888);
1679 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
1680 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888);
1681 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888);
1682
1683 data->context = SDL_GL_CreateContext(window);
1684 if (!data->context) {
1685 goto error;
1686 }
1687 if (!SDL_GL_MakeCurrent(window, data->context)) {
1688 goto error;
1689 }
1690
1691 if (!GL_LoadFunctions(data)) {
1692 goto error;
1693 }
1694
1695#ifdef SDL_PLATFORM_MACOS
1696 // Enable multi-threaded rendering
1697 /* Disabled until Ryan finishes his VBO/PBO code...
1698 CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
1699 */
1700#endif
1701
1702 // Check for debug output support
1703 if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) &&
1704 (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
1705 data->debug_enabled = true;
1706 }
1707 if (data->debug_enabled && SDL_GL_ExtensionSupported("GL_ARB_debug_output")) {
1708 PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC)SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
1709
1710 data->GL_ARB_debug_output_supported = true;
1711 data->glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION_ARB, (GLvoid **)(char *)&data->next_error_callback);
1712 data->glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM_ARB, &data->next_error_userparam);
1713 glDebugMessageCallbackARBFunc(GL_HandleDebugMessage, renderer);
1714
1715 // Make sure our callback is called when errors actually happen
1716 data->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
1717 }
1718
1719 hint = SDL_GetHint("GL_ARB_texture_non_power_of_two");
1720 if (!hint || *hint != '0') {
1721 bool isGL2 = false;
1722 const char *verstr = (const char *)data->glGetString(GL_VERSION);
1723 if (verstr) {
1724 char verbuf[16];
1725 char *ptr;
1726 SDL_strlcpy(verbuf, verstr, sizeof(verbuf));
1727 ptr = SDL_strchr(verbuf, '.');
1728 if (ptr) {
1729 *ptr = '\0';
1730 if (SDL_atoi(verbuf) >= 2) {
1731 isGL2 = true;
1732 }
1733 }
1734 }
1735 if (isGL2 || SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
1736 non_power_of_two_supported = true;
1737 }
1738 }
1739
1740 data->textype = GL_TEXTURE_2D;
1741 if (non_power_of_two_supported) {
1742 data->GL_ARB_texture_non_power_of_two_supported = true;
1743 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
1744 SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, value);
1745 } else if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
1746 SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
1747 data->GL_ARB_texture_rectangle_supported = true;
1748 data->textype = GL_TEXTURE_RECTANGLE_ARB;
1749 data->glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &value);
1750 SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, value);
1751 } else {
1752 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
1753 SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, value);
1754 }
1755
1756 // Check for multitexture support
1757 if (SDL_GL_ExtensionSupported("GL_ARB_multitexture")) {
1758 data->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)SDL_GL_GetProcAddress("glActiveTextureARB");
1759 if (data->glActiveTextureARB) {
1760 data->GL_ARB_multitexture_supported = true;
1761 data->glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &data->num_texture_units);
1762 }
1763 }
1764
1765 // Check for shader support
1766 data->shaders = GL_CreateShaderContext();
1767 SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
1768 data->shaders ? "ENABLED" : "DISABLED");
1769#ifdef SDL_HAVE_YUV
1770 // We support YV12 textures using 3 textures and a shader
1771 if (data->shaders && data->num_texture_units >= 3) {
1772 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
1773 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
1774 }
1775
1776 // We support NV12 textures using 2 textures and a shader
1777 if (data->shaders && data->num_texture_units >= 2) {
1778 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
1779 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
1780 }
1781#endif
1782#ifdef SDL_PLATFORM_MACOS
1783 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_UYVY);
1784#endif
1785
1786 if (SDL_GL_ExtensionSupported("GL_EXT_framebuffer_object")) {
1787 data->GL_EXT_framebuffer_object_supported = true;
1788 data->glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)
1789 SDL_GL_GetProcAddress("glGenFramebuffersEXT");
1790 data->glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
1791 SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
1792 data->glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
1793 SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
1794 data->glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)
1795 SDL_GL_GetProcAddress("glBindFramebufferEXT");
1796 data->glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
1797 SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
1798 } else {
1799 SDL_SetError("Can't create render targets, GL_EXT_framebuffer_object not available");
1800 goto error;
1801 }
1802
1803 // Set up parameters for rendering
1804 data->glMatrixMode(GL_MODELVIEW);
1805 data->glLoadIdentity();
1806 data->glDisable(GL_DEPTH_TEST);
1807 data->glDisable(GL_CULL_FACE);
1808 data->glDisable(GL_SCISSOR_TEST);
1809 data->glDisable(data->textype);
1810 data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1811 data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1812 // This ended up causing video discrepancies between OpenGL and Direct3D
1813 // data->glEnable(GL_LINE_SMOOTH);
1814
1815 data->drawstate.color.r = 1.0f;
1816 data->drawstate.color.g = 1.0f;
1817 data->drawstate.color.b = 1.0f;
1818 data->drawstate.color.a = 1.0f;
1819 data->drawstate.clear_color.r = 1.0f;
1820 data->drawstate.clear_color.g = 1.0f;
1821 data->drawstate.clear_color.b = 1.0f;
1822 data->drawstate.clear_color.a = 1.0f;
1823
1824 return true;
1825
1826error:
1827 if (changed_window) {
1828 // Uh oh, better try to put it back...
1829 char *error = SDL_strdup(SDL_GetError());
1830 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
1831 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
1832 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
1833 SDL_RecreateWindow(window, window_flags);
1834 SDL_SetError("%s", error);
1835 SDL_free(error);
1836 }
1837 return false;
1838}
1839
1840SDL_RenderDriver GL_RenderDriver = {
1841 GL_CreateRenderer, "opengl"
1842};
1843
1844#endif // SDL_VIDEO_RENDER_OGL
diff --git a/contrib/SDL-3.2.8/src/render/opengl/SDL_shaders_gl.c b/contrib/SDL-3.2.8/src/render/opengl/SDL_shaders_gl.c
new file mode 100644
index 0000000..b09b12e
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/render/opengl/SDL_shaders_gl.c
@@ -0,0 +1,545 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 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#ifdef SDL_VIDEO_RENDER_OGL
24
25#include <SDL3/SDL_opengl.h>
26#include "SDL_shaders_gl.h"
27
28// OpenGL shader implementation
29
30// #define DEBUG_SHADERS
31
32typedef struct
33{
34 GLhandleARB program;
35 GLhandleARB vert_shader;
36 GLhandleARB frag_shader;
37} GL_ShaderData;
38
39struct GL_ShaderContext
40{
41 GLenum (*glGetError)(void);
42
43 PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
44 PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
45 PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
46 PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
47 PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
48 PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
49 PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
50 PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
51 PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
52 PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
53 PFNGLUNIFORM1IARBPROC glUniform1iARB;
54 PFNGLUNIFORM1FARBPROC glUniform1fARB;
55 PFNGLUNIFORM3FARBPROC glUniform3fARB;
56 PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
57
58 bool GL_ARB_texture_rectangle_supported;
59
60 GL_ShaderData shaders[NUM_SHADERS];
61 const float *shader_params[NUM_SHADERS];
62};
63
64/* *INDENT-OFF* */ // clang-format off
65
66#define COLOR_VERTEX_SHADER \
67"varying vec4 v_color;\n" \
68"\n" \
69"void main()\n" \
70"{\n" \
71" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" \
72" v_color = gl_Color;\n" \
73"}" \
74
75#define TEXTURE_VERTEX_SHADER \
76"varying vec4 v_color;\n" \
77"varying vec2 v_texCoord;\n" \
78"\n" \
79"void main()\n" \
80"{\n" \
81" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" \
82" v_color = gl_Color;\n" \
83" v_texCoord = vec2(gl_MultiTexCoord0);\n" \
84"}" \
85
86#define YUV_SHADER_PROLOGUE \
87"varying vec4 v_color;\n" \
88"varying vec2 v_texCoord;\n" \
89"uniform sampler2D tex0; // Y \n" \
90"uniform sampler2D tex1; // U \n" \
91"uniform sampler2D tex2; // V \n" \
92"uniform vec3 Yoffset;\n" \
93"uniform vec3 Rcoeff;\n" \
94"uniform vec3 Gcoeff;\n" \
95"uniform vec3 Bcoeff;\n" \
96"\n" \
97
98#define YUV_SHADER_BODY \
99"\n" \
100"void main()\n" \
101"{\n" \
102" vec2 tcoord;\n" \
103" vec3 yuv, rgb;\n" \
104"\n" \
105" // Get the Y value \n" \
106" tcoord = v_texCoord;\n" \
107" yuv.x = texture2D(tex0, tcoord).r;\n" \
108"\n" \
109" // Get the U and V values \n" \
110" tcoord *= UVCoordScale;\n" \
111" yuv.y = texture2D(tex1, tcoord).r;\n" \
112" yuv.z = texture2D(tex2, tcoord).r;\n" \
113"\n" \
114" // Do the color transform \n" \
115" yuv += Yoffset;\n" \
116" rgb.r = dot(yuv, Rcoeff);\n" \
117" rgb.g = dot(yuv, Gcoeff);\n" \
118" rgb.b = dot(yuv, Bcoeff);\n" \
119"\n" \
120" // That was easy. :) \n" \
121" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
122"}" \
123
124#define NV12_SHADER_PROLOGUE \
125"varying vec4 v_color;\n" \
126"varying vec2 v_texCoord;\n" \
127"uniform sampler2D tex0; // Y \n" \
128"uniform sampler2D tex1; // U/V \n" \
129"uniform vec3 Yoffset;\n" \
130"uniform vec3 Rcoeff;\n" \
131"uniform vec3 Gcoeff;\n" \
132"uniform vec3 Bcoeff;\n" \
133"\n" \
134
135#define NV12_RA_SHADER_BODY \
136"\n" \
137"void main()\n" \
138"{\n" \
139" vec2 tcoord;\n" \
140" vec3 yuv, rgb;\n" \
141"\n" \
142" // Get the Y value \n" \
143" tcoord = v_texCoord;\n" \
144" yuv.x = texture2D(tex0, tcoord).r;\n" \
145"\n" \
146" // Get the U and V values \n" \
147" tcoord *= UVCoordScale;\n" \
148" yuv.yz = texture2D(tex1, tcoord).ra;\n" \
149"\n" \
150" // Do the color transform \n" \
151" yuv += Yoffset;\n" \
152" rgb.r = dot(yuv, Rcoeff);\n" \
153" rgb.g = dot(yuv, Gcoeff);\n" \
154" rgb.b = dot(yuv, Bcoeff);\n" \
155"\n" \
156" // That was easy. :) \n" \
157" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
158"}" \
159
160#define NV12_RG_SHADER_BODY \
161"\n" \
162"void main()\n" \
163"{\n" \
164" vec2 tcoord;\n" \
165" vec3 yuv, rgb;\n" \
166"\n" \
167" // Get the Y value \n" \
168" tcoord = v_texCoord;\n" \
169" yuv.x = texture2D(tex0, tcoord).r;\n" \
170"\n" \
171" // Get the U and V values \n" \
172" tcoord *= UVCoordScale;\n" \
173" yuv.yz = texture2D(tex1, tcoord).rg;\n" \
174"\n" \
175" // Do the color transform \n" \
176" yuv += Yoffset;\n" \
177" rgb.r = dot(yuv, Rcoeff);\n" \
178" rgb.g = dot(yuv, Gcoeff);\n" \
179" rgb.b = dot(yuv, Bcoeff);\n" \
180"\n" \
181" // That was easy. :) \n" \
182" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
183"}" \
184
185#define NV21_RA_SHADER_BODY \
186"\n" \
187"void main()\n" \
188"{\n" \
189" vec2 tcoord;\n" \
190" vec3 yuv, rgb;\n" \
191"\n" \
192" // Get the Y value \n" \
193" tcoord = v_texCoord;\n" \
194" yuv.x = texture2D(tex0, tcoord).r;\n" \
195"\n" \
196" // Get the U and V values \n" \
197" tcoord *= UVCoordScale;\n" \
198" yuv.yz = texture2D(tex1, tcoord).ar;\n" \
199"\n" \
200" // Do the color transform \n" \
201" yuv += Yoffset;\n" \
202" rgb.r = dot(yuv, Rcoeff);\n" \
203" rgb.g = dot(yuv, Gcoeff);\n" \
204" rgb.b = dot(yuv, Bcoeff);\n" \
205"\n" \
206" // That was easy. :) \n" \
207" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
208"}" \
209
210#define NV21_RG_SHADER_BODY \
211"\n" \
212"void main()\n" \
213"{\n" \
214" vec2 tcoord;\n" \
215" vec3 yuv, rgb;\n" \
216"\n" \
217" // Get the Y value \n" \
218" tcoord = v_texCoord;\n" \
219" yuv.x = texture2D(tex0, tcoord).r;\n" \
220"\n" \
221" // Get the U and V values \n" \
222" tcoord *= UVCoordScale;\n" \
223" yuv.yz = texture2D(tex1, tcoord).gr;\n" \
224"\n" \
225" // Do the color transform \n" \
226" yuv += Yoffset;\n" \
227" rgb.r = dot(yuv, Rcoeff);\n" \
228" rgb.g = dot(yuv, Gcoeff);\n" \
229" rgb.b = dot(yuv, Bcoeff);\n" \
230"\n" \
231" // That was easy. :) \n" \
232" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
233"}" \
234
235/*
236 * NOTE: Always use sampler2D, etc here. We'll #define them to the
237 * texture_rectangle versions if we choose to use that extension.
238 */
239static const char *shader_source[NUM_SHADERS][2] = {
240 // SHADER_NONE
241 { NULL, NULL },
242
243 // SHADER_SOLID
244 {
245 // vertex shader
246 COLOR_VERTEX_SHADER,
247 // fragment shader
248"varying vec4 v_color;\n"
249"\n"
250"void main()\n"
251"{\n"
252" gl_FragColor = v_color;\n"
253"}"
254 },
255
256 // SHADER_RGB
257 {
258 // vertex shader
259 TEXTURE_VERTEX_SHADER,
260 // fragment shader
261"varying vec4 v_color;\n"
262"varying vec2 v_texCoord;\n"
263"uniform sampler2D tex0;\n"
264"\n"
265"void main()\n"
266"{\n"
267" gl_FragColor = texture2D(tex0, v_texCoord);\n"
268" gl_FragColor.a = 1.0;\n"
269" gl_FragColor *= v_color;\n"
270"}"
271 },
272
273 // SHADER_RGBA
274 {
275 // vertex shader
276 TEXTURE_VERTEX_SHADER,
277 // fragment shader
278"varying vec4 v_color;\n"
279"varying vec2 v_texCoord;\n"
280"uniform sampler2D tex0;\n"
281"\n"
282"void main()\n"
283"{\n"
284" gl_FragColor = texture2D(tex0, v_texCoord) * v_color;\n"
285"}"
286 },
287#ifdef SDL_HAVE_YUV
288 // SHADER_YUV
289 {
290 // vertex shader
291 TEXTURE_VERTEX_SHADER,
292 // fragment shader
293 YUV_SHADER_PROLOGUE
294 YUV_SHADER_BODY
295 },
296 // SHADER_NV12_RA
297 {
298 // vertex shader
299 TEXTURE_VERTEX_SHADER,
300 // fragment shader
301 NV12_SHADER_PROLOGUE
302 NV12_RA_SHADER_BODY
303 },
304 // SHADER_NV12_RG
305 {
306 // vertex shader
307 TEXTURE_VERTEX_SHADER,
308 // fragment shader
309 NV12_SHADER_PROLOGUE
310 NV12_RG_SHADER_BODY
311 },
312 // SHADER_NV21_RA
313 {
314 // vertex shader
315 TEXTURE_VERTEX_SHADER,
316 // fragment shader
317 NV12_SHADER_PROLOGUE
318 NV21_RA_SHADER_BODY
319 },
320 // SHADER_NV21_RG
321 {
322 // vertex shader
323 TEXTURE_VERTEX_SHADER,
324 // fragment shader
325 NV12_SHADER_PROLOGUE
326 NV21_RG_SHADER_BODY
327 },
328#endif // SDL_HAVE_YUV
329};
330
331/* *INDENT-ON* */ // clang-format on
332
333static bool CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char *defines, const char *source)
334{
335 GLint status;
336 const char *sources[2];
337
338 sources[0] = defines;
339 sources[1] = source;
340
341 ctx->glShaderSourceARB(shader, SDL_arraysize(sources), sources, NULL);
342 ctx->glCompileShaderARB(shader);
343 ctx->glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
344 if (status == 0) {
345 bool isstack;
346 GLint length;
347 char *info;
348
349 ctx->glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
350 info = SDL_small_alloc(char, length + 1, &isstack);
351 if (info) {
352 ctx->glGetInfoLogARB(shader, length, NULL, info);
353 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to compile shader:");
354 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", defines);
355 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", source);
356 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", info);
357 SDL_small_free(info, isstack);
358 }
359 return false;
360 } else {
361 return true;
362 }
363}
364
365static bool CompileShaderProgram(GL_ShaderContext *ctx, int index, GL_ShaderData *data)
366{
367 const int num_tmus_bound = 4;
368 const char *vert_defines = "";
369 const char *frag_defines = "";
370 int i;
371 GLint location;
372
373 if (index == SHADER_NONE) {
374 return true;
375 }
376
377 ctx->glGetError();
378
379 // Make sure we use the correct sampler type for our texture type
380 if (ctx->GL_ARB_texture_rectangle_supported) {
381 frag_defines =
382 "#define sampler2D sampler2DRect\n"
383 "#define texture2D texture2DRect\n"
384 "#define UVCoordScale 0.5\n";
385 } else {
386 frag_defines =
387 "#define UVCoordScale 1.0\n";
388 }
389
390 // Create one program object to rule them all
391 data->program = ctx->glCreateProgramObjectARB();
392
393 // Create the vertex shader
394 data->vert_shader = ctx->glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
395 if (!CompileShader(ctx, data->vert_shader, vert_defines, shader_source[index][0])) {
396 return false;
397 }
398
399 // Create the fragment shader
400 data->frag_shader = ctx->glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
401 if (!CompileShader(ctx, data->frag_shader, frag_defines, shader_source[index][1])) {
402 return false;
403 }
404
405 // ... and in the darkness bind them
406 ctx->glAttachObjectARB(data->program, data->vert_shader);
407 ctx->glAttachObjectARB(data->program, data->frag_shader);
408 ctx->glLinkProgramARB(data->program);
409
410 // Set up some uniform variables
411 ctx->glUseProgramObjectARB(data->program);
412 for (i = 0; i < num_tmus_bound; ++i) {
413 char tex_name[10];
414 (void)SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i);
415 location = ctx->glGetUniformLocationARB(data->program, tex_name);
416 if (location >= 0) {
417 ctx->glUniform1iARB(location, i);
418 }
419 }
420 ctx->glUseProgramObjectARB(0);
421
422 return ctx->glGetError() == GL_NO_ERROR;
423}
424
425static void DestroyShaderProgram(GL_ShaderContext *ctx, GL_ShaderData *data)
426{
427 ctx->glDeleteObjectARB(data->vert_shader);
428 ctx->glDeleteObjectARB(data->frag_shader);
429 ctx->glDeleteObjectARB(data->program);
430}
431
432GL_ShaderContext *GL_CreateShaderContext(void)
433{
434 GL_ShaderContext *ctx;
435 bool shaders_supported;
436 int i;
437
438 ctx = (GL_ShaderContext *)SDL_calloc(1, sizeof(*ctx));
439 if (!ctx) {
440 return NULL;
441 }
442
443 if (!SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two") &&
444 (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
445 SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle"))) {
446 ctx->GL_ARB_texture_rectangle_supported = true;
447 }
448
449 // Check for shader support
450 shaders_supported = false;
451 if (SDL_GL_ExtensionSupported("GL_ARB_shader_objects") &&
452 SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") &&
453 SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") &&
454 SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) {
455 ctx->glGetError = (GLenum(*)(void))SDL_GL_GetProcAddress("glGetError");
456 ctx->glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB");
457 ctx->glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB");
458 ctx->glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB");
459 ctx->glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB");
460 ctx->glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)SDL_GL_GetProcAddress("glDeleteObjectARB");
461 ctx->glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB");
462 ctx->glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB");
463 ctx->glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB");
464 ctx->glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB");
465 ctx->glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB");
466 ctx->glUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB");
467 ctx->glUniform1fARB = (PFNGLUNIFORM1FARBPROC)SDL_GL_GetProcAddress("glUniform1fARB");
468 ctx->glUniform3fARB = (PFNGLUNIFORM3FARBPROC)SDL_GL_GetProcAddress("glUniform3fARB");
469 ctx->glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB");
470 if (ctx->glGetError &&
471 ctx->glAttachObjectARB &&
472 ctx->glCompileShaderARB &&
473 ctx->glCreateProgramObjectARB &&
474 ctx->glCreateShaderObjectARB &&
475 ctx->glDeleteObjectARB &&
476 ctx->glGetInfoLogARB &&
477 ctx->glGetObjectParameterivARB &&
478 ctx->glGetUniformLocationARB &&
479 ctx->glLinkProgramARB &&
480 ctx->glShaderSourceARB &&
481 ctx->glUniform1iARB &&
482 ctx->glUniform1fARB &&
483 ctx->glUniform3fARB &&
484 ctx->glUseProgramObjectARB) {
485 shaders_supported = true;
486 }
487 }
488
489 if (!shaders_supported) {
490 SDL_free(ctx);
491 return NULL;
492 }
493
494 // Compile all the shaders
495 for (i = 0; i < NUM_SHADERS; ++i) {
496 if (!CompileShaderProgram(ctx, i, &ctx->shaders[i])) {
497 GL_DestroyShaderContext(ctx);
498 return NULL;
499 }
500 }
501
502 // We're done!
503 return ctx;
504}
505
506void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader, const float *shader_params)
507{
508 GLint location;
509 GLhandleARB program = ctx->shaders[shader].program;
510
511 ctx->glUseProgramObjectARB(program);
512
513 if (shader_params && shader_params != ctx->shader_params[shader]) {
514 // YUV shader params are Yoffset, 0, Rcoeff, 0, Gcoeff, 0, Bcoeff, 0
515 location = ctx->glGetUniformLocationARB(program, "Yoffset");
516 if (location >= 0) {
517 ctx->glUniform3fARB(location, shader_params[0], shader_params[1], shader_params[2]);
518 }
519 location = ctx->glGetUniformLocationARB(program, "Rcoeff");
520 if (location >= 0) {
521 ctx->glUniform3fARB(location, shader_params[4], shader_params[5], shader_params[6]);
522 }
523 location = ctx->glGetUniformLocationARB(program, "Gcoeff");
524 if (location >= 0) {
525 ctx->glUniform3fARB(location, shader_params[8], shader_params[9], shader_params[10]);
526 }
527 location = ctx->glGetUniformLocationARB(program, "Bcoeff");
528 if (location >= 0) {
529 ctx->glUniform3fARB(location, shader_params[12], shader_params[13], shader_params[14]);
530 }
531 ctx->shader_params[shader] = shader_params;
532 }
533}
534
535void GL_DestroyShaderContext(GL_ShaderContext *ctx)
536{
537 int i;
538
539 for (i = 0; i < NUM_SHADERS; ++i) {
540 DestroyShaderProgram(ctx, &ctx->shaders[i]);
541 }
542 SDL_free(ctx);
543}
544
545#endif // SDL_VIDEO_RENDER_OGL
diff --git a/contrib/SDL-3.2.8/src/render/opengl/SDL_shaders_gl.h b/contrib/SDL-3.2.8/src/render/opengl/SDL_shaders_gl.h
new file mode 100644
index 0000000..374940a
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/render/opengl/SDL_shaders_gl.h
@@ -0,0 +1,52 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 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
22#ifndef SDL_shaders_gl_h_
23#define SDL_shaders_gl_h_
24
25#include "SDL_internal.h"
26
27// OpenGL shader implementation
28
29typedef enum
30{
31 SHADER_INVALID = -1,
32 SHADER_NONE,
33 SHADER_SOLID,
34 SHADER_RGB,
35 SHADER_RGBA,
36#ifdef SDL_HAVE_YUV
37 SHADER_YUV,
38 SHADER_NV12_RA,
39 SHADER_NV12_RG,
40 SHADER_NV21_RA,
41 SHADER_NV21_RG,
42#endif
43 NUM_SHADERS
44} GL_Shader;
45
46typedef struct GL_ShaderContext GL_ShaderContext;
47
48extern GL_ShaderContext *GL_CreateShaderContext(void);
49extern void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader, const float *shader_params);
50extern void GL_DestroyShaderContext(GL_ShaderContext *ctx);
51
52#endif // SDL_shaders_gl_h_