diff --git a/Framework/App.cs b/Framework/App.cs
index b43f1f5..c56a925 100644
--- a/Framework/App.cs
+++ b/Framework/App.cs
@@ -265,9 +265,9 @@ public static bool MouseVisible
///
/// Runs the Application with the given Module automatically registered.
- /// Functionally the same as calling followed by
+ /// Functionally the same as calling followed by
///
- public static void Run(string applicationName, int width, int height, bool fullscreen = false) where T : Module, new()
+ public static void Run(string applicationName, int width, int height, bool fullscreen = false, Renderers renderer = Renderers.None) where T : Module, new()
{
Register();
Run(applicationName, width, height, fullscreen);
@@ -276,7 +276,7 @@ public static bool MouseVisible
///
/// Runs the Application
///
- public static void Run(string applicationName, int width, int height, bool fullscreen = false)
+ public static void Run(string applicationName, int width, int height, bool fullscreen = false, Renderers renderer = Renderers.None)
{
Debug.Assert(!Running, "Application is already running");
Debug.Assert(!Exiting, "Application is still exiting");
@@ -301,6 +301,7 @@ public static void Run(string applicationName, int width, int height, bool fulls
applicationName = name,
width = width,
height = height,
+ renderer = renderer,
flags = App.flags,
onText = Input.OnText,
onKey = Input.OnKey,
diff --git a/Framework/Graphics/Batcher.cs b/Framework/Graphics/Batcher.cs
index ed0b547..fa9b03d 100644
--- a/Framework/Graphics/Batcher.cs
+++ b/Framework/Graphics/Batcher.cs
@@ -1638,7 +1638,8 @@ public void Text(SpriteFont font, ReadOnlySpan text, Vector2 position, Vec
if (last != 0)
at.X += font.GetKerning(last, ch.Codepoint);
- Image(ch.Subtexture, at + ch.Offset, color);
+ if (ch.Subtexture.Texture != null)
+ Image(ch.Subtexture, at + ch.Offset, color);
last = ch.Codepoint;
at.X += ch.Advance;
diff --git a/Framework/Graphics/ShaderDefaults.cs b/Framework/Graphics/ShaderDefaults.cs
index ccdd16c..bd18a2b 100644
--- a/Framework/Graphics/ShaderDefaults.cs
+++ b/Framework/Graphics/ShaderDefaults.cs
@@ -7,37 +7,37 @@ internal static class ShaderDefaults
[Renderers.OpenGL] = new()
{
VertexShader =
- "#version 330\n" +
- "uniform mat4 u_matrix;\n" +
- "layout(location=0) in vec2 a_position;\n" +
- "layout(location=1) in vec2 a_tex;\n" +
- "layout(location=2) in vec4 a_color;\n" +
- "layout(location=3) in vec4 a_type;\n" +
- "out vec2 v_tex;\n" +
- "out vec4 v_col;\n" +
- "out vec4 v_type;\n" +
- "void main(void)\n" +
- "{\n" +
- " gl_Position = u_matrix * vec4(a_position.xy, 0, 1);\n" +
- " v_tex = a_tex;\n" +
- " v_col = a_color;\n" +
- " v_type = a_type;\n" +
- "}",
- FragmentShader =
- "#version 330\n" +
- "uniform sampler2D u_texture;\n" +
- "in vec2 v_tex;\n" +
- "in vec4 v_col;\n" +
- "in vec4 v_type;\n" +
- "out vec4 o_color;\n" +
- "void main(void)\n" +
- "{\n" +
- " vec4 color = texture(u_texture, v_tex);\n" +
- " o_color = \n" +
- " v_type.x * color * v_col + \n" +
- " v_type.y * color.a * v_col + \n" +
- " v_type.z * v_col;\n" +
- "}"
+ @"#version 330
+ uniform mat4 u_matrix;
+ layout(location=0) in vec2 a_position;
+ layout(location=1) in vec2 a_tex;
+ layout(location=2) in vec4 a_color;
+ layout(location=3) in vec4 a_type;
+ out vec2 v_tex;
+ out vec4 v_col;
+ out vec4 v_type;
+ void main(void)
+ {
+ gl_Position = u_matrix * vec4(a_position.xy, 0, 1);
+ v_tex = a_tex;
+ v_col = a_color;
+ v_type = a_type;
+ }",
+ FragmentShader =
+ @"#version 330
+ uniform sampler2D u_texture;
+ in vec2 v_tex;
+ in vec4 v_col;
+ in vec4 v_type;
+ out vec4 o_color;
+ void main(void)
+ {
+ vec4 color = texture(u_texture, v_tex);
+ o_color =
+ v_type.x * color * v_col +
+ v_type.y * color.a * v_col +
+ v_type.z * v_col;
+ }"
}
};
}
diff --git a/Framework/Storage/Content.cs b/Framework/Storage/Content.cs
new file mode 100644
index 0000000..49f1748
--- /dev/null
+++ b/Framework/Storage/Content.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Foster.Framework.Storage
+{
+ ///
+ /// Default Content implementation.
+ /// Should work well for PC, etc, but can be overridden for custom handling.
+ ///
+ public class Content
+ {
+ public string CurrentDirectory { get; set; } = "";
+
+ private class ContentEnumerator : IEnumerator
+ {
+ public string[] Locations;
+ public int Index = -1;
+
+ public string Current
+ {
+ get
+ {
+ try
+ {
+ return Locations[Index];
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+ object IEnumerator.Current => Current;
+
+ public ContentEnumerator(string[] locations)
+ {
+ Locations = locations;
+ }
+
+ public bool MoveNext()
+ {
+ Index++;
+ if (Index >= Locations.Length)
+ return false;
+ return true;
+ }
+
+ public void Reset() => Index = -1;
+
+ public void Dispose() { }
+ }
+
+ public Content() { }
+ public Content(string content) : this()
+ {
+ CurrentDirectory = content;
+ }
+
+ #region Directory
+ public virtual bool FileExists(string relativePath)
+ {
+ return File.Exists(CurrentDirectory + relativePath);
+ }
+ public virtual bool DirectoryExists(string relativePath)
+ {
+ return Directory.Exists(CurrentDirectory + relativePath);
+ }
+ public virtual bool Exists(string name)
+ {
+ return FileExists(name) || DirectoryExists(name);
+ }
+
+ public virtual IEnumerator EnumerateFiles(string path, string searchPattern, bool recursive)
+ {
+ return new ContentEnumerator(
+ Directory.GetFiles(
+ CurrentDirectory + path,
+ searchPattern,
+ recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly
+ ));
+ }
+
+ public virtual IEnumerator EnumerateDirectories(string path, string searchPattern, bool recursive)
+ {
+
+ return new ContentEnumerator(
+ Directory.GetDirectories(
+ CurrentDirectory + path,
+ searchPattern,
+ recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly
+ ));
+ }
+
+ #endregion
+
+ #region File
+
+ public virtual Stream OpenRead(string relativePath)
+ {
+ return File.OpenRead(CurrentDirectory + relativePath);
+ }
+
+ public virtual byte[] ReadAllBytes(string relativePath)
+ {
+ return File.ReadAllBytes(CurrentDirectory + relativePath);
+ }
+
+ public virtual string ReadAllText(string relativePath)
+ {
+ return File.ReadAllText(CurrentDirectory + relativePath);
+ }
+
+ #endregion
+ }
+}
diff --git a/Framework/Storage/UserStorage.cs b/Framework/Storage/UserStorage.cs
new file mode 100644
index 0000000..860509f
--- /dev/null
+++ b/Framework/Storage/UserStorage.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Foster.Framework.Storage
+{
+ ///
+ /// A storage location for user data (save files, etc)
+ ///
+ public static class UserStorage
+ {
+ public static WritableContent Provider { get; set; } = new WritableContent(App.UserPath);
+
+ #region Directory
+
+ public static bool FileExists(string relativePath)
+ => Provider.FileExists(relativePath);
+ public static bool DirectoryExists(string relativePath)
+ => Provider.DirectoryExists(relativePath);
+ public static bool Exists(string name)
+ => Provider.Exists(name);
+
+ public static IEnumerator EnumerateFiles(string path, string searchPattern, bool recursive)
+ => Provider.EnumerateFiles(path, searchPattern, recursive);
+ public static IEnumerator EnumerateDirectories(string path, string searchPattern, bool recursive)
+ => Provider.EnumerateDirectories(path, searchPattern, recursive);
+
+ public static void CreateDirectory(string path)
+ => Provider.CreateDirectory(path);
+ public static void DeleteDirectory(string path, bool recursive)
+ => Provider.DeleteDirectory(path, recursive);
+ public static void DeleteFile(string path)
+ => Provider.DeleteFile(path);
+
+ #endregion
+
+ #region File
+
+ public static Stream OpenRead(string relativePath)
+ => Provider.OpenRead(relativePath);
+
+ public static byte[] ReadAllBytes(string relativePath)
+ => Provider.ReadAllBytes(relativePath);
+
+ public static string ReadAllText(string relativePath)
+ => Provider.ReadAllText(relativePath);
+
+
+ public static Stream OpenWrite(string path)
+ => Provider.OpenWrite(path);
+ public static void WriteAllBytes(string path, byte[] bytes)
+ => Provider.WriteAllBytes(path, bytes);
+ public static void WriteAllText(string path, string text)
+ => Provider.WriteAllText(path, text);
+
+ #endregion
+
+ }
+}
diff --git a/Framework/Storage/WritableContent.cs b/Framework/Storage/WritableContent.cs
new file mode 100644
index 0000000..e0eb453
--- /dev/null
+++ b/Framework/Storage/WritableContent.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Foster.Framework.Storage
+{
+ ///
+ /// A Content that may also be written to.
+ ///
+ public class WritableContent : Content
+ {
+ public WritableContent() { }
+ public WritableContent(string currentDirectory) : base(currentDirectory) { }
+
+ #region Directory
+ public virtual void CreateDirectory(string path)
+ {
+ Directory.CreateDirectory(CurrentDirectory + path);
+ }
+
+ public virtual void DeleteDirectory(string path, bool recursive)
+ {
+ Directory.Delete(CurrentDirectory + path, recursive);
+ }
+
+ public virtual void DeleteFile(string path)
+ {
+ File.Delete(CurrentDirectory + path);
+ }
+
+ #endregion
+
+ #region File
+
+ public virtual Stream OpenWrite(string path)
+ {
+ return File.OpenWrite(CurrentDirectory + path);
+ }
+
+ public virtual void WriteAllBytes(string path, byte[] bytes)
+ {
+ File.WriteAllBytes(CurrentDirectory + path, bytes);
+ }
+
+ public virtual void WriteAllText(string path, string text)
+ {
+ File.WriteAllText(CurrentDirectory + path, text);
+ }
+
+ #endregion
+ }
+}
diff --git a/Framework/Utility/Ease.cs b/Framework/Utility/Ease.cs
index 449e7ff..1357827 100644
--- a/Framework/Utility/Ease.cs
+++ b/Framework/Utility/Ease.cs
@@ -5,53 +5,70 @@ namespace Foster.Framework;
///
/// Ease Delegates
///
-public static class Ease
+public struct Ease
{
public delegate float Easer(float t);
- public static readonly Easer Linear = (float t) => t;
+ #region Ease
+ public Easer In { get; set; }
+ public Easer Out { get; set; }
+ public Easer InOut { get; set; }
- public static readonly Easer SineIn = (float t) => -(float)Math.Cos(Calc.HalfPI * t) + 1;
- public static readonly Easer SineOut = (float t) => (float)Math.Sin(Calc.HalfPI * t);
- public static readonly Easer SineInOut = (float t) => -(MathF.Cos(MathF.PI * t) - 1f) / 2f;
+ public Ease(Easer @in, Easer? @out = null, Easer? inOut = null)
+ {
+ In = @in;
+ if (@out != null)
+ Out = @out;
+ else
+ Out = Invert(@in);
+ if (inOut != null)
+ InOut = inOut;
+ else
+ InOut = Follow(In, Out);
+ }
+
+ public float Apply(float t)
+ {
+ if (t <= 0)
+ return 0;
+ if (t >= 1)
+ return 1;
+ return InOut(t);
+ }
- public static readonly Easer QuadIn = (float t) => t * t;
- public static readonly Easer QuadOut = Invert(QuadIn);
- public static readonly Easer QuadInOut = Follow(QuadIn, QuadOut);
+ #endregion
- public static readonly Easer CubeIn = (float t) => t * t * t;
- public static readonly Easer CubeOut = Invert(CubeIn);
- public static readonly Easer CubeInOut = Follow(CubeIn, CubeOut);
+ #region Easers
- public static readonly Easer QuintIn = (float t) => t * t * t * t * t;
- public static readonly Easer QuintOut = Invert(QuintIn);
- public static readonly Easer QuintInOut = Follow(QuintIn, QuintOut);
+ public static readonly Easer Linear = t => t;
+ public static readonly Ease Quad = new(t => t * t);
+ public static readonly Ease Cube = new(t => t * t * t);
+ public static readonly Ease Quart = new(t => t * t * t * t);
+ public static readonly Ease Quint = new(t => t * t * t * t * t);
- public static readonly Easer ExpoIn = (float t) => (float)Math.Pow(2, 10 * (t - 1));
- public static readonly Easer ExpoOut = Invert(ExpoIn);
- public static readonly Easer ExpoInOut = Follow(ExpoIn, ExpoOut);
+ public static readonly Ease Sine = new(
+ (float t) => -(float)Math.Cos(Calc.HalfPI * t) + 1,
+ (float t) => (float)Math.Sin(Calc.HalfPI * t),
+ (float t) => -(MathF.Cos(MathF.PI * t) - 1f) / 2f);
- public static readonly Easer BackIn = (float t) => t * t * (2.70158f * t - 1.70158f);
- public static readonly Easer BackOut = Invert(BackIn);
- public static readonly Easer BackInOut = Follow(BackIn, BackOut);
+ public static readonly Ease Expo = new(t => (float)Math.Pow(2, 10 * (t - 1)));
- public static readonly Easer BigBackIn = (float t) => t * t * (4f * t - 3f);
- public static readonly Easer BigBackOut = Invert(BigBackIn);
- public static readonly Easer BigBackInOut = Follow(BigBackIn, BigBackOut);
+ public static readonly Ease Back = new(t => t * t * (2.70158f * t - 1.70158f));
+ public static readonly Ease BigBack = new(t => t * t * (4f * t - 3f));
- public static readonly Easer ElasticIn = (float t) =>
+ public static readonly Ease Elastic = new(
+ (float t) =>
{
var ts = t * t;
var tc = ts * t;
return (33 * tc * ts + -59 * ts * ts + 32 * tc + -5 * ts);
- };
- public static readonly Easer ElasticOut = (float t) =>
+ },
+ (float t) =>
{
var ts = t * t;
var tc = ts * t;
return (33 * tc * ts + -106 * ts * ts + 126 * tc + -67 * ts + 15 * t);
- };
- public static readonly Easer ElasticInOut = Follow(ElasticIn, ElasticOut);
+ });
private const float B1 = 1f / 2.75f;
private const float B2 = 2f / 2.75f;
@@ -60,7 +77,7 @@ public static class Ease
private const float B5 = 2.25f / 2.75f;
private const float B6 = 2.625f / 2.75f;
- public static readonly Easer BounceIn = (float t) =>
+ public static readonly Ease Bounce = new((float t) =>
{
t = 1 - t;
if (t < B1)
@@ -70,9 +87,8 @@ public static class Ease
if (t < B4)
return 1 - (7.5625f * (t - B5) * (t - B5) + .9375f);
return 1 - (7.5625f * (t - B6) * (t - B6) + .984375f);
- };
-
- public static readonly Easer BounceOut = (float t) =>
+ },
+ (float t) =>
{
if (t < B1)
return 7.5625f * t * t;
@@ -81,30 +97,7 @@ public static class Ease
if (t < B4)
return 7.5625f * (t - B5) * (t - B5) + .9375f;
return 7.5625f * (t - B6) * (t - B6) + .984375f;
- };
-
- public static readonly Easer BounceInOut = (float t) =>
- {
- if (t < .5f)
- {
- t = 1 - t * 2;
- if (t < B1)
- return (1 - 7.5625f * t * t) / 2;
- if (t < B2)
- return (1 - (7.5625f * (t - B3) * (t - B3) + .75f)) / 2;
- if (t < B4)
- return (1 - (7.5625f * (t - B5) * (t - B5) + .9375f)) / 2;
- return (1 - (7.5625f * (t - B6) * (t - B6) + .984375f)) / 2;
- }
- t = t * 2 - 1;
- if (t < B1)
- return (7.5625f * t * t) / 2 + .5f;
- if (t < B2)
- return (7.5625f * (t - B3) * (t - B3) + .75f) / 2 + .5f;
- if (t < B4)
- return (7.5625f * (t - B5) * (t - B5) + .9375f) / 2 + .5f;
- return (7.5625f * (t - B6) * (t - B6) + .984375f) / 2 + .5f;
- };
+ });
public static Easer Invert(Easer easer)
{
@@ -123,4 +116,53 @@ public static float UpDown(float eased)
else
return 1 - (eased - .5f) * 2;
}
+
+ #endregion
+
+ #region Obsolete Compatibility
+
+ // redirections to ease implementations
+ [Obsolete("Use Sine.In instead")]
+ public static readonly Easer SineIn = Sine.In;
+ [Obsolete("Use Sine.Out instead")]
+ public static readonly Easer SineOut = Sine.Out;
+ [Obsolete("Use Sine.InOut instead")]
+ public static readonly Easer SineInOut = Sine.InOut;
+
+ [Obsolete("Use Expo.In instead")]
+ public static readonly Easer ExpoIn = Expo.In;
+ [Obsolete("Use Expo.Out instead")]
+ public static readonly Easer ExpoOut = Expo.Out;
+ [Obsolete("Use Expo.InOut instead")]
+ public static readonly Easer ExpoInOut = Expo.InOut;
+
+ [Obsolete("Use Back.In instead")]
+ public static readonly Easer BackIn = Back.In;
+ [Obsolete("Use Back.Out instead")]
+ public static readonly Easer BackOut = Back.Out;
+ [Obsolete("Use Back.InOut instead")]
+ public static readonly Easer BackInOut = Back.InOut;
+
+ [Obsolete("Use BigBack.In instead")]
+ public static readonly Easer BigBackIn = BigBack.In;
+ [Obsolete("Use BigBack.Out instead")]
+ public static readonly Easer BigBackOut = BigBack.Out;
+ [Obsolete("Use BigBack.InOut instead")]
+ public static readonly Easer BigBackInOut = BigBack.InOut;
+
+ [Obsolete("Use Elastic.In instead")]
+ public static readonly Easer ElasticIn = Elastic.In;
+ [Obsolete("Use Elastic.Out instead")]
+ public static readonly Easer ElasticOut = Elastic.Out;
+ [Obsolete("Use Elastic.InOut instead")]
+ public static readonly Easer ElasticInOut = Elastic.InOut;
+
+ [Obsolete("Use Bounce.In instead")]
+ public static readonly Easer BounceIn = Bounce.In;
+ [Obsolete("Use Bounce.Out instead")]
+ public static readonly Easer BounceOut = Bounce.Out;
+ [Obsolete("Use Bounce.InOut instead")]
+ public static readonly Easer BounceInOut = Bounce.InOut;
+
+ #endregion
}
diff --git a/Platform/libs/lib64/libFosterPlatform.so b/Platform/libs/lib64/libFosterPlatform.so
index d5de6d7..05e037a 100755
Binary files a/Platform/libs/lib64/libFosterPlatform.so and b/Platform/libs/lib64/libFosterPlatform.so differ
diff --git a/Platform/libs/libarm64/libFosterPlatform.so b/Platform/libs/libarm64/libFosterPlatform.so
index 3abba78..eff1dd8 100644
Binary files a/Platform/libs/libarm64/libFosterPlatform.so and b/Platform/libs/libarm64/libFosterPlatform.so differ
diff --git a/Platform/libs/osx/libFosterPlatform.dylib b/Platform/libs/osx/libFosterPlatform.dylib
index e3a4abd..bb584af 100644
Binary files a/Platform/libs/osx/libFosterPlatform.dylib and b/Platform/libs/osx/libFosterPlatform.dylib differ
diff --git a/Platform/libs/x64/FosterPlatform.dll b/Platform/libs/x64/FosterPlatform.dll
index cff447c..4b5b758 100644
Binary files a/Platform/libs/x64/FosterPlatform.dll and b/Platform/libs/x64/FosterPlatform.dll differ
diff --git a/Platform/src/foster_renderer_opengl.c b/Platform/src/foster_renderer_opengl.c
index 4a77e41..f0d0011 100644
--- a/Platform/src/foster_renderer_opengl.c
+++ b/Platform/src/foster_renderer_opengl.c
@@ -348,7 +348,7 @@ GL_FUNCTIONS
#define FOSTER_RECT_EQUAL(a, b) ((a).x == (b).x && (a).y == (b).y && (a).w == (b).w && (a).h == (b).h)
-typedef struct FosterTexure_OpenGL
+typedef struct FosterTexture_OpenGL
{
GLuint id;
int width;
@@ -359,7 +359,7 @@ typedef struct FosterTexure_OpenGL
GLenum glType;
GLenum glAttachment;
FosterTextureSampler sampler;
-
+
// Because Shader uniforms assign textures, it's possible for the user to
// dispose of a texture but still have it assigned in a shader. Thus we use
// a simple ref counter to determine when it's safe to delete the wrapping
@@ -417,9 +417,9 @@ typedef struct FosterMesh_OpenGL
typedef struct
{
// GL function pointers
- #define GL_FUNC(name, ret, ...) gl ## name ## Fn gl ## name;
+#define GL_FUNC(name, ret, ...) gl ## name ## Fn gl ## name;
GL_FUNCTIONS
- #undef GL_FUNC
+#undef GL_FUNC
// GL context
void* context;
@@ -431,6 +431,8 @@ typedef struct
GLuint stateProgram;
GLuint stateFrameBuffer;
GLuint stateVertexArray;
+ GLuint stateArrayBuffer;
+ GLuint stateElementBuffer;
int stateFrameBufferWidth;
int stateFrameBufferHeight;
int stateHasScissor;
@@ -449,8 +451,8 @@ typedef struct
int max_samples;
int max_texture_image_units;
int max_texture_size;
-
} FosterOpenGLState;
+
static FosterOpenGLState fgl;
// debug callback
@@ -468,23 +470,23 @@ void APIENTRY FosterMessage_OpenGL(GLenum source, GLenum type, GLuint id, GLenum
switch (type)
{
- case GL_DEBUG_TYPE_ERROR: typeName = "ERROR"; break;
- case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeName = "DEPRECATED BEHAVIOR"; break;
- case GL_DEBUG_TYPE_MARKER: typeName = "MARKER"; break;
- case GL_DEBUG_TYPE_OTHER: typeName = "OTHER"; break;
- case GL_DEBUG_TYPE_PERFORMANCE: typeName = "PEROFRMANCE"; break;
- case GL_DEBUG_TYPE_POP_GROUP: typeName = "POP GROUP"; break;
- case GL_DEBUG_TYPE_PORTABILITY: typeName = "PORTABILITY"; break;
- case GL_DEBUG_TYPE_PUSH_GROUP: typeName = "PUSH GROUP"; break;
- case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeName = "UNDEFINED BEHAVIOR"; break;
+ case GL_DEBUG_TYPE_ERROR: typeName = "ERROR"; break;
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeName = "DEPRECATED BEHAVIOR"; break;
+ case GL_DEBUG_TYPE_MARKER: typeName = "MARKER"; break;
+ case GL_DEBUG_TYPE_OTHER: typeName = "OTHER"; break;
+ case GL_DEBUG_TYPE_PERFORMANCE: typeName = "PEROFRMANCE"; break;
+ case GL_DEBUG_TYPE_POP_GROUP: typeName = "POP GROUP"; break;
+ case GL_DEBUG_TYPE_PORTABILITY: typeName = "PORTABILITY"; break;
+ case GL_DEBUG_TYPE_PUSH_GROUP: typeName = "PUSH GROUP"; break;
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeName = "UNDEFINED BEHAVIOR"; break;
}
switch (severity)
{
- case GL_DEBUG_SEVERITY_HIGH: severityName = "HIGH"; break;
- case GL_DEBUG_SEVERITY_MEDIUM: severityName = "MEDIUM"; break;
- case GL_DEBUG_SEVERITY_LOW: severityName = "LOW"; break;
- case GL_DEBUG_SEVERITY_NOTIFICATION: severityName = "NOTIFICATION"; break;
+ case GL_DEBUG_SEVERITY_HIGH: severityName = "HIGH"; break;
+ case GL_DEBUG_SEVERITY_MEDIUM: severityName = "MEDIUM"; break;
+ case GL_DEBUG_SEVERITY_LOW: severityName = "LOW"; break;
+ case GL_DEBUG_SEVERITY_NOTIFICATION: severityName = "NOTIFICATION"; break;
}
if (type == GL_DEBUG_TYPE_ERROR)
@@ -522,12 +524,12 @@ GLenum FosterBlendOpToGL(FosterBlendOp operation)
{
switch (operation)
{
- case FOSTER_BLEND_OP_ADD: return GL_FUNC_ADD;
- case FOSTER_BLEND_OP_SUBTRACT: return GL_FUNC_SUBTRACT;
- case FOSTER_BLEND_OP_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT;
- case FOSTER_BLEND_OP_MIN: return GL_MIN;
- case FOSTER_BLEND_OP_MAX: return GL_MAX;
- default: return GL_FUNC_ADD;
+ case FOSTER_BLEND_OP_ADD: return GL_FUNC_ADD;
+ case FOSTER_BLEND_OP_SUBTRACT: return GL_FUNC_SUBTRACT;
+ case FOSTER_BLEND_OP_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT;
+ case FOSTER_BLEND_OP_MIN: return GL_MIN;
+ case FOSTER_BLEND_OP_MAX: return GL_MAX;
+ default: return GL_FUNC_ADD;
};
}
@@ -535,25 +537,25 @@ GLenum FosterBlendFactorToGL(FosterBlendFactor factor)
{
switch (factor)
{
- case FOSTER_BLEND_FACTOR_Zero: return GL_ZERO;
- case FOSTER_BLEND_FACTOR_One: return GL_ONE;
- case FOSTER_BLEND_FACTOR_SrcColor: return GL_SRC_COLOR;
- case FOSTER_BLEND_FACTOR_OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR;
- case FOSTER_BLEND_FACTOR_DstColor: return GL_DST_COLOR;
- case FOSTER_BLEND_FACTOR_OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR;
- case FOSTER_BLEND_FACTOR_SrcAlpha: return GL_SRC_ALPHA;
- case FOSTER_BLEND_FACTOR_OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
- case FOSTER_BLEND_FACTOR_DstAlpha: return GL_DST_ALPHA;
- case FOSTER_BLEND_FACTOR_OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA;
- case FOSTER_BLEND_FACTOR_ConstantColor: return GL_CONSTANT_COLOR;
- case FOSTER_BLEND_FACTOR_OneMinusConstantColor: return GL_ONE_MINUS_CONSTANT_COLOR;
- case FOSTER_BLEND_FACTOR_ConstantAlpha: return GL_CONSTANT_ALPHA;
- case FOSTER_BLEND_FACTOR_OneMinusConstantAlpha: return GL_ONE_MINUS_CONSTANT_ALPHA;
- case FOSTER_BLEND_FACTOR_SrcAlphaSaturate: return GL_SRC_ALPHA_SATURATE;
- case FOSTER_BLEND_FACTOR_Src1Color: return GL_SRC1_COLOR;
- case FOSTER_BLEND_FACTOR_OneMinusSrc1Color: return GL_ONE_MINUS_SRC1_COLOR;
- case FOSTER_BLEND_FACTOR_Src1Alpha: return GL_SRC1_ALPHA;
- case FOSTER_BLEND_FACTOR_OneMinusSrc1Alpha: return GL_ONE_MINUS_SRC1_ALPHA;
+ case FOSTER_BLEND_FACTOR_Zero: return GL_ZERO;
+ case FOSTER_BLEND_FACTOR_One: return GL_ONE;
+ case FOSTER_BLEND_FACTOR_SrcColor: return GL_SRC_COLOR;
+ case FOSTER_BLEND_FACTOR_OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR;
+ case FOSTER_BLEND_FACTOR_DstColor: return GL_DST_COLOR;
+ case FOSTER_BLEND_FACTOR_OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR;
+ case FOSTER_BLEND_FACTOR_SrcAlpha: return GL_SRC_ALPHA;
+ case FOSTER_BLEND_FACTOR_OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
+ case FOSTER_BLEND_FACTOR_DstAlpha: return GL_DST_ALPHA;
+ case FOSTER_BLEND_FACTOR_OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA;
+ case FOSTER_BLEND_FACTOR_ConstantColor: return GL_CONSTANT_COLOR;
+ case FOSTER_BLEND_FACTOR_OneMinusConstantColor: return GL_ONE_MINUS_CONSTANT_COLOR;
+ case FOSTER_BLEND_FACTOR_ConstantAlpha: return GL_CONSTANT_ALPHA;
+ case FOSTER_BLEND_FACTOR_OneMinusConstantAlpha: return GL_ONE_MINUS_CONSTANT_ALPHA;
+ case FOSTER_BLEND_FACTOR_SrcAlphaSaturate: return GL_SRC_ALPHA_SATURATE;
+ case FOSTER_BLEND_FACTOR_Src1Color: return GL_SRC1_COLOR;
+ case FOSTER_BLEND_FACTOR_OneMinusSrc1Color: return GL_ONE_MINUS_SRC1_COLOR;
+ case FOSTER_BLEND_FACTOR_Src1Alpha: return GL_SRC1_ALPHA;
+ case FOSTER_BLEND_FACTOR_OneMinusSrc1Alpha: return GL_ONE_MINUS_SRC1_ALPHA;
};
return GL_ZERO;
@@ -563,13 +565,13 @@ FosterUniformType FosterUniformTypeFromGL(GLenum value)
{
switch (value)
{
- case GL_FLOAT: return FOSTER_UNIFORM_TYPE_FLOAT;
- case GL_FLOAT_VEC2: return FOSTER_UNIFORM_TYPE_FLOAT2;
- case GL_FLOAT_VEC3: return FOSTER_UNIFORM_TYPE_FLOAT3;
- case GL_FLOAT_VEC4: return FOSTER_UNIFORM_TYPE_FLOAT4;
- case GL_FLOAT_MAT3x2: return FOSTER_UNIFORM_TYPE_MAT3X2;
- case GL_FLOAT_MAT4: return FOSTER_UNIFORM_TYPE_MAT4X4;
- case GL_SAMPLER_2D: return FOSTER_UNIFORM_TYPE_SAMPLER2D;
+ case GL_FLOAT: return FOSTER_UNIFORM_TYPE_FLOAT;
+ case GL_FLOAT_VEC2: return FOSTER_UNIFORM_TYPE_FLOAT2;
+ case GL_FLOAT_VEC3: return FOSTER_UNIFORM_TYPE_FLOAT3;
+ case GL_FLOAT_VEC4: return FOSTER_UNIFORM_TYPE_FLOAT4;
+ case GL_FLOAT_MAT3x2: return FOSTER_UNIFORM_TYPE_MAT3X2;
+ case GL_FLOAT_MAT4: return FOSTER_UNIFORM_TYPE_MAT4X4;
+ case GL_SAMPLER_2D: return FOSTER_UNIFORM_TYPE_SAMPLER2D;
};
return FOSTER_UNIFORM_TYPE_NONE;
@@ -578,7 +580,26 @@ FosterUniformType FosterUniformTypeFromGL(GLenum value)
GLuint FosterMeshAssignAttributes_OpenGL(GLuint buffer, GLenum bufferType, FosterVertexFormat* format, GLint divisor)
{
// bind
- fgl.glBindBuffer(bufferType, buffer);
+ switch (bufferType)
+ {
+ case GL_ARRAY_BUFFER:
+ if (fgl.stateArrayBuffer != buffer)
+ {
+ fgl.glBindBuffer(bufferType, buffer);
+ fgl.stateArrayBuffer = buffer;
+ }
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ if (fgl.stateElementBuffer != buffer)
+ {
+ fgl.glBindBuffer(bufferType, buffer);
+ fgl.stateElementBuffer = buffer;
+ }
+ break;
+ default:
+ fgl.glBindBuffer(bufferType, buffer);
+ break;
+ }
// TODO: disable existing enabled attributes?
// ...
@@ -717,7 +738,10 @@ void FosterBindTexture(int slot, GLuint id)
}
if (fgl.stateTextureSlots[slot] != id)
+ {
fgl.glBindTexture(GL_TEXTURE_2D, id);
+ fgl.stateTextureSlots[slot] = id;
+ }
}
// Same as FosterBindTexture, except it the resulting global state doesn't
@@ -733,6 +757,7 @@ void FosterEnsureTextureSlotIs(int slot, GLuint id)
}
fgl.glBindTexture(GL_TEXTURE_2D, id);
+ fgl.stateTextureSlots[slot] = id;
}
}
@@ -756,7 +781,7 @@ void FosterSetTextureSampler(FosterTexture_OpenGL* tex, FosterTextureSampler sam
if (tex->sampler.wrapY != sampler.wrapY)
fgl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, FosterWrapToGL(sampler.wrapY));
-
+
tex->sampler = sampler;
}
}
@@ -899,15 +924,15 @@ void FosterSetCompare(FosterCompare compare)
switch (compare)
{
- case FOSTER_COMPARE_NONE: break;
- case FOSTER_COMPARE_ALWAYS: fgl.glDepthFunc(GL_ALWAYS); break;
- case FOSTER_COMPARE_EQUAL: fgl.glDepthFunc(GL_EQUAL); break;
- case FOSTER_COMPARE_GREATER: fgl.glDepthFunc(GL_GREATER); break;
- case FOSTER_COMPARE_GREATOR_OR_EQUAL: fgl.glDepthFunc(GL_GEQUAL); break;
- case FOSTER_COMPARE_LESS: fgl.glDepthFunc(GL_LESS); break;
- case FOSTER_COMPARE_LESS_OR_EQUAL: fgl.glDepthFunc(GL_LEQUAL); break;
- case FOSTER_COMPARE_NEVER: fgl.glDepthFunc(GL_NEVER); break;
- case FOSTER_COMPARE_NOT_EQUAL: fgl.glDepthFunc(GL_NOTEQUAL); break;
+ case FOSTER_COMPARE_NONE: break;
+ case FOSTER_COMPARE_ALWAYS: fgl.glDepthFunc(GL_ALWAYS); break;
+ case FOSTER_COMPARE_EQUAL: fgl.glDepthFunc(GL_EQUAL); break;
+ case FOSTER_COMPARE_GREATER: fgl.glDepthFunc(GL_GREATER); break;
+ case FOSTER_COMPARE_GREATOR_OR_EQUAL: fgl.glDepthFunc(GL_GEQUAL); break;
+ case FOSTER_COMPARE_LESS: fgl.glDepthFunc(GL_LESS); break;
+ case FOSTER_COMPARE_LESS_OR_EQUAL: fgl.glDepthFunc(GL_LEQUAL); break;
+ case FOSTER_COMPARE_NEVER: fgl.glDepthFunc(GL_NEVER); break;
+ case FOSTER_COMPARE_NOT_EQUAL: fgl.glDepthFunc(GL_NOTEQUAL); break;
}
}
}
@@ -943,9 +968,9 @@ void FosterSetCull(FosterCull cull)
switch (cull)
{
- case FOSTER_CULL_NONE: break;
- case FOSTER_CULL_BACK: fgl.glCullFace(GL_BACK); break;
- case FOSTER_CULL_FRONT: fgl.glCullFace(GL_FRONT); break;
+ case FOSTER_CULL_NONE: break;
+ case FOSTER_CULL_BACK: fgl.glCullFace(GL_BACK); break;
+ case FOSTER_CULL_FRONT: fgl.glCullFace(GL_FRONT); break;
}
}
}
@@ -1043,7 +1068,7 @@ bool FosterInitialize_OpenGL()
// zero out texture state
fgl.stateActiveTextureSlot = 0;
fgl.glActiveTexture(GL_TEXTURE0);
- for (int i = 0; i < FOSTER_MAX_UNIFORM_TEXTURES; i ++)
+ for (int i = 0; i < FOSTER_MAX_UNIFORM_TEXTURES; i++)
fgl.stateTextureSlots[i] = 0;
// log
@@ -1099,24 +1124,24 @@ FosterTexture* FosterTextureCreate_OpenGL(int width, int height, FosterTextureFo
switch (format)
{
- case FOSTER_TEXTURE_FORMAT_R8:
- result.glInternalFormat = GL_RED;
- result.glFormat = GL_RED;
- result.glType = GL_UNSIGNED_BYTE;
- break;
- case FOSTER_TEXTURE_FORMAT_R8G8B8A8:
- result.glInternalFormat = GL_RGBA;
- result.glFormat = GL_RGBA;
- result.glType = GL_UNSIGNED_BYTE;
- break;
- case FOSTER_TEXTURE_FORMAT_DEPTH24_STENCIL8:
- result.glInternalFormat = GL_DEPTH24_STENCIL8;
- result.glFormat = GL_DEPTH_STENCIL;
- result.glType = GL_UNSIGNED_INT_24_8;
- break;
- default:
- FosterLogError("Invalid Texture Format (%i)", format);
- return NULL;
+ case FOSTER_TEXTURE_FORMAT_R8:
+ result.glInternalFormat = GL_RED;
+ result.glFormat = GL_RED;
+ result.glType = GL_UNSIGNED_BYTE;
+ break;
+ case FOSTER_TEXTURE_FORMAT_R8G8B8A8:
+ result.glInternalFormat = GL_RGBA;
+ result.glFormat = GL_RGBA;
+ result.glType = GL_UNSIGNED_BYTE;
+ break;
+ case FOSTER_TEXTURE_FORMAT_DEPTH24_STENCIL8:
+ result.glInternalFormat = GL_DEPTH24_STENCIL8;
+ result.glFormat = GL_DEPTH_STENCIL;
+ result.glType = GL_UNSIGNED_INT_24_8;
+ break;
+ default:
+ FosterLogError("Invalid Texture Format (%i)", format);
+ return NULL;
}
fgl.glGenTextures(1, &result.id);
@@ -1168,7 +1193,7 @@ FosterTarget* FosterTargetCreate_OpenGL(int width, int height, FosterTextureForm
result.height = height;
result.attachmentCount = attachmentCount;
result.colorAttachmentCount = 0;
- for (int i = 0; i < FOSTER_MAX_TARGET_ATTACHMENTS; i ++)
+ for (int i = 0; i < FOSTER_MAX_TARGET_ATTACHMENTS; i++)
result.attachments[i] = NULL;
fgl.glGenFramebuffers(1, &result.id);
@@ -1180,7 +1205,7 @@ FosterTarget* FosterTargetCreate_OpenGL(int width, int height, FosterTextureForm
if (tex == NULL)
{
- for (int j = 0; j < i; j ++)
+ for (int j = 0; j < i; j++)
FosterTextureDestroy_OpenGL((FosterTexture*)tex);
FosterLogError("Failed to create Target Attachment");
FosterBindFrameBuffer(NULL);
@@ -1221,7 +1246,7 @@ void FosterTargetDestroy_OpenGL(FosterTarget* target)
{
FosterTarget_OpenGL* tar = (FosterTarget_OpenGL*)target;
- for (int i = 0; i < FOSTER_MAX_TARGET_ATTACHMENTS; i ++)
+ for (int i = 0; i < FOSTER_MAX_TARGET_ATTACHMENTS; i++)
{
if (tar->attachments[i] != NULL)
FosterTextureDestroy_OpenGL((FosterTexture*)tar->attachments[i]);
@@ -1332,7 +1357,7 @@ FosterShader* FosterShaderCreate_OpenGL(FosterShaderData* data)
shader->uniformCount = 0;
shader->uniforms = NULL;
- for (int i = 0; i < FOSTER_MAX_UNIFORM_TEXTURES; i ++)
+ for (int i = 0; i < FOSTER_MAX_UNIFORM_TEXTURES; i++)
{
shader->textures[i] = NULL;
shader->samplers[i].filter = FOSTER_TEXTURE_FILTER_LINEAR;
@@ -1359,7 +1384,7 @@ FosterShader* FosterShaderCreate_OpenGL(FosterShaderData* data)
// get the name & properties
GLsizei nameLen;
- char nameBuf[256];
+ char nameBuf[256];
fgl.glGetActiveUniform(id, i, 255, &nameLen, &uniform->glSize, &uniform->glType, nameBuf);
// array names end with "[0]", and we don't want that
@@ -1374,7 +1399,7 @@ FosterShader* FosterShaderCreate_OpenGL(FosterShaderData* data)
// allocate enough room for the name
uniform->name = (char*)SDL_malloc(nameLen + 8);
SDL_strlcpy(uniform->name, nameBuf, nameLen + 1);
-
+
// get GL location
uniform->glLocation = fgl.glGetUniformLocation(id, uniform->name);
@@ -1398,7 +1423,7 @@ void FosterShaderGetUniforms_OpenGL(FosterShader* shader, FosterUniformInfo* out
int t = 0;
- for (int i = 0; t < max && i < it->uniformCount; i ++)
+ for (int i = 0; t < max && i < it->uniformCount; i++)
{
FosterUniform_OpenGL* uniform = it->uniforms + i;
@@ -1447,24 +1472,24 @@ void FosterShaderSetUniform_OpenGL(FosterShader* shader, int index, float* value
switch (uniform->glType)
{
- case GL_FLOAT:
- fgl.glUniform1fv(uniform->glLocation, (GLint)uniform->glSize, values);
- return;
- case GL_FLOAT_VEC2:
- fgl.glUniform2fv(uniform->glLocation, (GLint)uniform->glSize, values);
- return;
- case GL_FLOAT_VEC3:
- fgl.glUniform3fv(uniform->glLocation, (GLint)uniform->glSize, values);
- return;
- case GL_FLOAT_VEC4:
- fgl.glUniform4fv(uniform->glLocation, (GLint)uniform->glSize, values);
- return;
- case GL_FLOAT_MAT3x2:
- fgl.glUniformMatrix3x2fv(uniform->glLocation, (GLint)uniform->glSize, 0, values);
- return;
- case GL_FLOAT_MAT4:
- fgl.glUniformMatrix4fv(uniform->glLocation, (GLint)uniform->glSize, 0, values);
- return;
+ case GL_FLOAT:
+ fgl.glUniform1fv(uniform->glLocation, (GLint)uniform->glSize, values);
+ return;
+ case GL_FLOAT_VEC2:
+ fgl.glUniform2fv(uniform->glLocation, (GLint)uniform->glSize, values);
+ return;
+ case GL_FLOAT_VEC3:
+ fgl.glUniform3fv(uniform->glLocation, (GLint)uniform->glSize, values);
+ return;
+ case GL_FLOAT_VEC4:
+ fgl.glUniform4fv(uniform->glLocation, (GLint)uniform->glSize, values);
+ return;
+ case GL_FLOAT_MAT3x2:
+ fgl.glUniformMatrix3x2fv(uniform->glLocation, (GLint)uniform->glSize, 0, values);
+ return;
+ case GL_FLOAT_MAT4:
+ fgl.glUniformMatrix4fv(uniform->glLocation, (GLint)uniform->glSize, 0, values);
+ return;
}
FosterLogError("Failed to set uniform '%s', unsupported type '%i'", uniform->name, uniform->glType);
@@ -1487,7 +1512,7 @@ void FosterShaderSetTexture_OpenGL(FosterShader* shader, int index, FosterTextur
return;
}
- for (int i = 0; i < uniform->glSize && uniform->samplerIndex + i < FOSTER_MAX_UNIFORM_TEXTURES; i ++)
+ for (int i = 0; i < uniform->glSize && uniform->samplerIndex + i < FOSTER_MAX_UNIFORM_TEXTURES; i++)
{
int index = uniform->samplerIndex + i;
FosterTextureReturnReference(it->textures[index]);
@@ -1512,7 +1537,7 @@ void FosterShaderSetSampler_OpenGL(FosterShader* shader, int index, FosterTextur
return;
}
- for (int i = 0; i < uniform->glSize && uniform->samplerIndex + i < FOSTER_MAX_UNIFORM_TEXTURES; i ++)
+ for (int i = 0; i < uniform->glSize && uniform->samplerIndex + i < FOSTER_MAX_UNIFORM_TEXTURES; i++)
it->samplers[uniform->samplerIndex + i] = values[i];
}
@@ -1521,10 +1546,10 @@ void FosterShaderDestroy_OpenGL(FosterShader* shader)
FosterShader_OpenGL* it = (FosterShader_OpenGL*)shader;
fgl.glDeleteProgram(it->id);
- for (int i = 0; i < FOSTER_MAX_UNIFORM_TEXTURES; i ++)
+ for (int i = 0; i < FOSTER_MAX_UNIFORM_TEXTURES; i++)
FosterTextureReturnReference(it->textures[i]);
- for (int i = 0; i < it->uniformCount; i ++)
+ for (int i = 0; i < it->uniformCount; i++)
{
SDL_free(it->uniforms[i].name);
SDL_free(it->uniforms[i].samplerName);
@@ -1574,8 +1599,16 @@ void FosterMeshSetVertexData_OpenGL(FosterMesh* mesh, void* data, int dataSize,
FosterBindArray(it->id);
if (it->vertexBuffer == 0)
+ {
fgl.glGenBuffers(1, &(it->vertexBuffer));
- fgl.glBindBuffer(GL_ARRAY_BUFFER, it->vertexBuffer);
+ fgl.glBindBuffer(GL_ARRAY_BUFFER, it->vertexBuffer);
+ fgl.stateArrayBuffer = it->vertexBuffer;
+ }
+ else if (fgl.stateArrayBuffer != it->vertexBuffer)
+ {
+ fgl.glBindBuffer(GL_ARRAY_BUFFER, it->vertexBuffer);
+ fgl.stateArrayBuffer = it->vertexBuffer;
+ }
// expand vertex buffer if needed
int totalSize = dataDestOffset + dataSize;
@@ -1595,17 +1628,17 @@ void FosterMeshSetIndexFormat_OpenGL(FosterMesh* mesh, FosterIndexFormat format)
switch (format)
{
- case FOSTER_INDEX_FORMAT_SIXTEEN:
- it->indexFormat = GL_UNSIGNED_SHORT;
- it->indexSize = 2;
- break;
- case FOSTER_INDEX_FORMAT_THIRTY_TWO:
- it->indexFormat = GL_UNSIGNED_INT;
- it->indexSize = 4;
- break;
- default:
- FosterLogError("Invalid Index Format '%i'", format);
- break;
+ case FOSTER_INDEX_FORMAT_SIXTEEN:
+ it->indexFormat = GL_UNSIGNED_SHORT;
+ it->indexSize = 2;
+ break;
+ case FOSTER_INDEX_FORMAT_THIRTY_TWO:
+ it->indexFormat = GL_UNSIGNED_INT;
+ it->indexSize = 4;
+ break;
+ default:
+ FosterLogError("Invalid Index Format '%i'", format);
+ break;
}
}
@@ -1615,9 +1648,16 @@ void FosterMeshSetIndexData_OpenGL(FosterMesh* mesh, void* data, int dataSize, i
FosterBindArray(it->id);
if (it->indexBuffer == 0)
+ {
fgl.glGenBuffers(1, &(it->indexBuffer));
- fgl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->indexBuffer);
-
+ fgl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->indexBuffer);
+ fgl.stateElementBuffer = it->indexBuffer;
+ }
+ else if (fgl.stateElementBuffer != it->indexBuffer)
+ {
+ fgl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->indexBuffer);
+ fgl.stateElementBuffer = it->indexBuffer;
+ }
// expand buffer if needed
int totalSize = dataDestOffset + dataSize;
if (totalSize > it->indexBufferSize)
@@ -1668,7 +1708,7 @@ void FosterDraw_OpenGL(FosterDrawCommand* command)
GLuint textureSlots[FOSTER_MAX_UNIFORM_TEXTURES];
// update samplers
- for (int i = 0; i < FOSTER_MAX_UNIFORM_TEXTURES; i ++)
+ for (int i = 0; i < FOSTER_MAX_UNIFORM_TEXTURES; i++)
{
FosterTexture_OpenGL* tex = shader->textures[i];
if (shader->textures[i] != NULL)
@@ -1677,14 +1717,14 @@ void FosterDraw_OpenGL(FosterDrawCommand* command)
// bind textures
int slot = 0;
- for (int i = 0; i < shader->uniformCount; i ++)
+ for (int i = 0; i < shader->uniformCount; i++)
{
FosterUniform_OpenGL* uniform = shader->uniforms + i;
if (uniform->glType != GL_SAMPLER_2D)
continue;
// bind textures & update sampler state
- for (int n = 0; n < uniform->glSize && slot < FOSTER_MAX_UNIFORM_TEXTURES; n ++)
+ for (int n = 0; n < uniform->glSize && slot < FOSTER_MAX_UNIFORM_TEXTURES; n++)
{
FosterTexture_OpenGL* tex = shader->textures[uniform->samplerIndex + n];
@@ -1743,7 +1783,7 @@ void FosterClear_OpenGL(FosterClearCommand* command)
fgl.glColorMask(true, true, true, true);
fgl.glClearColor(command->color.r / 255.0f, command->color.g / 255.0f, command->color.b / 255.0f, command->color.a / 255.0f);
}
-
+
if ((command->mask & FOSTER_CLEAR_MASK_DEPTH) == FOSTER_CLEAR_MASK_DEPTH)
{
FosterSetDepthMask(1);
@@ -1807,4 +1847,3 @@ bool FosterGetDevice_OpenGL(FosterRenderDevice* device)
#endif
-