Commit 7497ac2b authored by pcy's avatar pcy
Browse files

marshal strings correctly

parent d8e1eb46
...@@ -89,14 +89,7 @@ namespace PoroCYon.FNAGLSL { ...@@ -89,14 +89,7 @@ namespace PoroCYon.FNAGLSL {
uint sh = GL.CreateShader(kvp.Key); uint sh = GL.CreateShader(kvp.Key);
if (sh == 0) GL.Throw(); if (sh == 0) GL.Throw();
byte[] utf8src = Encoding.UTF8.GetBytes(kvp.Value); GL.ShaderSource(sh, kvp.Value);
fixed (byte* sbuf = utf8src) {
sbyte** uurgh = stackalloc sbyte*[1];
*uurgh = (sbyte*)sbuf;
int* uurgh2 = stackalloc int[1];
*uurgh2 = utf8src.Length;
GL.ShaderSource(sh, 1, uurgh, uurgh2);
}
GL.Throw(); GL.Throw();
GL.CompileShader(sh); GL.CompileShader(sh);
......
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using SDL2; using SDL2;
...@@ -11,6 +12,52 @@ using static SDL2.SDL; ...@@ -11,6 +12,52 @@ using static SDL2.SDL;
namespace PoroCYon.FNAGLSL { namespace PoroCYon.FNAGLSL {
public static unsafe partial class GL { public static unsafe partial class GL {
internal readonly static UTF8Encoding utf8 = new UTF8Encoding(false, true);
static byte[] utf8buf = new byte[64];
internal static byte[] GetNullTermUTF8(string s, bool newarr = false) {
int nbytes = utf8.GetByteCount(s);
byte[] ret;
if (newarr) {
ret = new byte[nbytes + 1];
} else {
if (utf8buf.Length < nbytes + 1)
Array.Resize<byte>(ref utf8buf, nbytes + 1);
ret = utf8buf;
}
utf8.GetBytes(s, 0, s.Length, ret, 0);
ret[nbytes] = 0;
return ret;
}
internal static string StrFromNullTermUTF8(byte[] s) {
fixed (byte* b = s) {
return StrFromNullTermUTF8((sbyte*)b, s.Length);
}
}
internal static string StrFromNullTermUTF8(sbyte[] s) {
fixed (sbyte* b = s) {
return StrFromNullTermUTF8(b, s.Length);
}
}
static long strlen(sbyte* s) {
long r = 0;
for (; *s != 0; ++s, ++r) ;
return r;
}
internal static string StrFromNullTermUTF8(sbyte* s, int nbytes = -1) {
if (nbytes < 0) {
nbytes = (int)strlen(s);;
} /*else {
long sl = strlen(s);
if (nbytes > sl) nbytes = (int)sl;
}*/
return new String(s, 0, nbytes, utf8);
}
public static void Throw() { public static void Throw() {
GLError err = GetError(); GLError err = GetError();
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using GLenum = System.UInt32; using GLenum = System.UInt32;
...@@ -87,9 +88,43 @@ namespace PoroCYon.FNAGLSL { ...@@ -87,9 +88,43 @@ namespace PoroCYon.FNAGLSL {
delegate void ShaderSource_T(GLuint sh, GLsizei count, delegate void ShaderSource_T(GLuint sh, GLsizei count,
GLchar** str, GLint* len); GLchar** str, GLint* len);
static ShaderSource_T _ShaderSource; static ShaderSource_T _ShaderSource;
public static void ShaderSource(GLuint sh, GLsizei count, public static void ShaderSource(GLuint sh, string[] srcs) {
GLchar** str, GLint* len) { int count = srcs.Length;
_ShaderSource(sh, count, str, len);
// marshal the string array...
byte[][] strs = new byte[count][];
GLint[] lens = new GLint[count];
// convert all the strings to utf8
int totallen = 0;
for (int i = 0; i < count; ++i) {
strs[i] = GetNullTermUTF8(srcs[i]);
totallen += (lens[i] = strs[i].Length);
}
// rearrange pointer crap so that GL can use it
byte[] bytesbytes = new byte[totallen];
GLchar*[] ptrs = new GLchar*[count];
fixed (byte* bbp = bytesbytes) {
int totalidx = 0;
for (int i = 0; i < count; ++i) {
Array.Copy(strs[i], 0, bytesbytes, totalidx, lens[i]);
ptrs[i] = (GLchar*)&bbp[totalidx];
totalidx += lens[i];
}
// now we can actually call the function
fixed (GLchar** strp = ptrs) {
fixed (GLint* lenp = lens) {
_ShaderSource(sh, count, strp, lenp);
}
}
}
}
readonly static string[] strarr = new string[1];
public static void ShaderSource(GLuint sh, string src) {
strarr[0] = src;
ShaderSource(sh, strarr);
} }
delegate void CompileShader_T(GLuint sh); delegate void CompileShader_T(GLuint sh);
...@@ -113,7 +148,7 @@ namespace PoroCYon.FNAGLSL { ...@@ -113,7 +148,7 @@ namespace PoroCYon.FNAGLSL {
GLsizei len = 0; GLsizei len = 0;
fixed (GLchar* logp = logbuf) { fixed (GLchar* logp = logbuf) {
_GetShaderInfoLog(sh, maxl, &len, logp); _GetShaderInfoLog(sh, maxl, &len, logp);
return new String(logp, 0, len, Encoding.UTF8); return StrFromNullTermUTF8(logp, len);
} }
} }
...@@ -145,7 +180,7 @@ namespace PoroCYon.FNAGLSL { ...@@ -145,7 +180,7 @@ namespace PoroCYon.FNAGLSL {
GLsizei len = 0; GLsizei len = 0;
fixed (GLchar* logp = logbuf) { fixed (GLchar* logp = logbuf) {
_GetProgramInfoLog(prgm, maxl, &len, logp); _GetProgramInfoLog(prgm, maxl, &len, logp);
return new String(logp, 0, len, Encoding.UTF8); return StrFromNullTermUTF8(logp, len);
} }
} }
...@@ -189,14 +224,14 @@ namespace PoroCYon.FNAGLSL { ...@@ -189,14 +224,14 @@ namespace PoroCYon.FNAGLSL {
(GLsizei)(NAMEBUF_MAX_LEN*sizeof(GLchar)), (GLsizei)(NAMEBUF_MAX_LEN*sizeof(GLchar)),
&namelen, psize, &_typ, namebuf); &namelen, psize, &_typ, namebuf);
} }
name = new String(namebuf, 0, namelen, Encoding.UTF8); name = StrFromNullTermUTF8(namebuf, namelen);
type = (GLSLType)_typ; type = (GLSLType)_typ;
} }
delegate GLint GetAttribLocation_T(GLuint prgm, GLchar* name); delegate GLint GetAttribLocation_T(GLuint prgm, GLchar* name);
static GetAttribLocation_T _GetAttribLocation; static GetAttribLocation_T _GetAttribLocation;
public static GLint GetAttribLocation(GLuint prgm, string name) { public static GLint GetAttribLocation(GLuint prgm, string name) {
byte[] blargh = Encoding.UTF8.GetBytes(name); byte[] blargh = GetNullTermUTF8(name);
fixed (byte* bb = blargh) { fixed (byte* bb = blargh) {
return _GetAttribLocation(prgm, (GLchar*)bb); return _GetAttribLocation(prgm, (GLchar*)bb);
...@@ -214,14 +249,14 @@ namespace PoroCYon.FNAGLSL { ...@@ -214,14 +249,14 @@ namespace PoroCYon.FNAGLSL {
// marshal the string array... // marshal the string array...
// convert all the string to utf8 // convert all the strings to utf8
int totallen = 0; int totallen = 0;
byte[][] bytes = new byte[names.Length][]; byte[][] bytes = new byte[names.Length][];
for (int i = 0; i < names.Length; ++i) { for (int i = 0; i < names.Length; ++i) {
bytes[i] = Encoding.UTF8.GetBytes(names[i]); bytes[i] = GetNullTermUTF8(names[i], true);
totallen += bytes[i].Length; totallen += bytes[i].Length;
} }
// rearrange pointer crap to that glGetUniformIndices can read it // rearrange pointer crap so that glGetUniformIndices can read it
byte[] bytesbytes = new byte[totallen]; byte[] bytesbytes = new byte[totallen];
GLchar*[] ptrs = new GLchar*[names.Length]; GLchar*[] ptrs = new GLchar*[names.Length];
fixed (byte* bbp = bytesbytes) { fixed (byte* bbp = bytesbytes) {
...@@ -285,7 +320,7 @@ namespace PoroCYon.FNAGLSL { ...@@ -285,7 +320,7 @@ namespace PoroCYon.FNAGLSL {
(GLsizei)(NAMEBUF_MAX_LEN*sizeof(GLchar)), (GLsizei)(NAMEBUF_MAX_LEN*sizeof(GLchar)),
&namelen, psize, &_typ, namebuf); &namelen, psize, &_typ, namebuf);
} }
name = new String(namebuf, 0, namelen, Encoding.UTF8); name = StrFromNullTermUTF8(namebuf, namelen);
type = (GLSLType)_typ; type = (GLSLType)_typ;
} }
...@@ -294,7 +329,7 @@ namespace PoroCYon.FNAGLSL { ...@@ -294,7 +329,7 @@ namespace PoroCYon.FNAGLSL {
public static GLint GetUniformLocation(GLuint prgm, string name) { public static GLint GetUniformLocation(GLuint prgm, string name) {
if (name == null) throw new ArgumentNullException("name"); if (name == null) throw new ArgumentNullException("name");
byte[] bytes = Encoding.UTF8.GetBytes(name); byte[] bytes = GetNullTermUTF8(name);
fixed (byte* bp = bytes) { fixed (byte* bp = bytes) {
return _GetUniformLocation(prgm, (GLchar*)bp); return _GetUniformLocation(prgm, (GLchar*)bp);
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment