Auto-formatting with clang-format

This commit is contained in:
Martin Fouilleul 2023-08-19 14:49:23 +02:00
parent 0d920670a2
commit 94b9cb2bbf
168 changed files with 42897 additions and 40823 deletions

View File

@ -1,14 +1,17 @@
AllowAllArgumentsOnNextLine: false AllowAllArgumentsOnNextLine: false
BreakBeforeBraces: Allman BreakBeforeBraces: Allman
ColumnLimit: 0
Cpp11BracedListStyle: false Cpp11BracedListStyle: false
ColumnLimit: 0
BreakBeforeBinaryOperators: NonAssignment
AlignOperands: AlignAfterOperator
IndentPPDirectives: BeforeHash IndentPPDirectives: BeforeHash
IndentCaseLabels: true
IndentWidth: 4 IndentWidth: 4
TabWidth: 4
UseTab: Never
LineEnding: LF LineEnding: LF
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
PointerAlignment: Left PointerAlignment: Left
SeparateDefinitionBlocks: Always SeparateDefinitionBlocks: Always
SpaceBeforeParens: Never SpaceBeforeParens: Never
TabWidth: 4
UseTab: Never
ReflowComments: false ReflowComments: false

1
ext/.clang-format Normal file
View File

@ -0,0 +1 @@
DisableFormat: true

File diff suppressed because it is too large Load Diff

View File

@ -13,44 +13,44 @@ uniform float dissipation;
vec2 u(ivec2 coord) vec2 u(ivec2 coord)
{ {
return(texelFetch(velocity, coord, 0).xy); return (texelFetch(velocity, coord, 0).xy);
} }
vec4 q(ivec2 coord) vec4 q(ivec2 coord)
{ {
if( coord.x < 0 if(coord.x < 0
|| coord.x >= textureSize(src, 0).x || coord.x >= textureSize(src, 0).x
|| coord.y < 0 || coord.y < 0
|| coord.y >= textureSize(src, 0).y) || coord.y >= textureSize(src, 0).y)
{ {
return(vec4(0.)); return (vec4(0.));
} }
return(texelFetch(src, coord, 0)); return (texelFetch(src, coord, 0));
} }
vec4 bilerpSrc(vec2 pos) vec4 bilerpSrc(vec2 pos)
{ {
vec2 offset = fract(pos); vec2 offset = fract(pos);
ivec2 bl = ivec2(floor(pos)); ivec2 bl = ivec2(floor(pos));
ivec2 br = bl + ivec2(1, 0); ivec2 br = bl + ivec2(1, 0);
ivec2 tl = bl + ivec2(0, 1); ivec2 tl = bl + ivec2(0, 1);
ivec2 tr = bl + ivec2(1, 1); ivec2 tr = bl + ivec2(1, 1);
vec4 lerpTop = (1.-offset.x)*q(tl) + offset.x*q(tr); vec4 lerpTop = (1. - offset.x) * q(tl) + offset.x * q(tr);
vec4 lerpBottom = (1.-offset.x)*q(bl) + offset.x*q(br); vec4 lerpBottom = (1. - offset.x) * q(bl) + offset.x * q(br);
vec4 result = (1.-offset.y)*lerpBottom + offset.y*lerpTop; vec4 result = (1. - offset.y) * lerpBottom + offset.y * lerpTop;
return(result); return (result);
} }
void main() void main()
{ {
float texWidth = float(textureSize(velocity, 0).x); float texWidth = float(textureSize(velocity, 0).x);
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
vec2 samplePos = vec2(pixelCoord) - texWidth * delta * u(pixelCoord); vec2 samplePos = vec2(pixelCoord) - texWidth * delta * u(pixelCoord);
fragColor = bilerpSrc(samplePos) / (1. + dissipation*delta); fragColor = bilerpSrc(samplePos) / (1. + dissipation * delta);
} }

View File

@ -10,25 +10,34 @@ uniform sampler2D tex;
vec3 color_map(float v) vec3 color_map(float v)
{ {
float logv = log(abs(v))/log(10.0); float logv = log(abs(v)) / log(10.0);
float f = floor(logv + 7.0); float f = floor(logv + 7.0);
float i = floor(4.0*(logv + 7.0 - f)); float i = floor(4.0 * (logv + 7.0 - f));
if(f < 0.0) return vec3(0.0); if(f < 0.0)
if(f < 1.0) return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i/4.0); return vec3(0.0);
if(f < 2.0) return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i/4.0); if(f < 1.0)
if(f < 3.0) return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i/4.0); return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i / 4.0);
if(f < 4.0) return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i/4.0); if(f < 2.0)
if(f < 5.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i/4.0); return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i / 4.0);
if(f < 6.0) return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i/4.0); if(f < 3.0)
if(f < 7.0) return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i/4.0); return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i / 4.0);
if(f < 8.0) return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i/4.0); if(f < 4.0)
return vec3(1.0); return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i / 4.0);
if(f < 5.0)
return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i / 4.0);
if(f < 6.0)
return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i / 4.0);
if(f < 7.0)
return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i / 4.0);
if(f < 8.0)
return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i / 4.0);
return vec3(1.0);
} }
void main() void main()
{ {
ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(tex, 0).xy))); ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(tex, 0).xy)));
float f = texelFetch(tex, pixelCoord, 0).x; float f = texelFetch(tex, pixelCoord, 0).x;
fragColor = vec4(color_map(f), 1.0); fragColor = vec4(color_map(f), 1.0);
} }

View File

@ -9,6 +9,6 @@ uniform mat4 mvp;
void main() void main()
{ {
texCoord = 0.5*(pos + vec2(1,1)); texCoord = 0.5 * (pos + vec2(1, 1));
gl_Position = mvp * vec4(pos, 0, 1); gl_Position = mvp * vec4(pos, 0, 1);
} }

View File

@ -10,6 +10,6 @@ uniform sampler2D tex;
void main() void main()
{ {
fragColor = texture(tex, texCoord); fragColor = texture(tex, texCoord);
fragColor.a = 1.0; fragColor.a = 1.0;
} }

View File

@ -11,55 +11,64 @@ uniform sampler2D bTex;
float x(ivec2 coord) float x(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x || coord.x >= textureSize(xTex, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y) || coord.y >= textureSize(xTex, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(xTex, coord, 0).x); return (texelFetch(xTex, coord, 0).x);
} }
float b(ivec2 coord) float b(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x || coord.x >= textureSize(bTex, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y) || coord.y >= textureSize(bTex, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(bTex, coord, 0).x); return (texelFetch(bTex, coord, 0).x);
} }
vec3 color_map(float v) vec3 color_map(float v)
{ {
float logv = log(abs(v))/log(10.0); float logv = log(abs(v)) / log(10.0);
float f = floor(logv + 7.0); float f = floor(logv + 7.0);
float i = floor(4.0*(logv + 7.0 - f)); float i = floor(4.0 * (logv + 7.0 - f));
if(f < 0.0) return vec3(0.0); if(f < 0.0)
if(f < 1.0) return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i/4.0); return vec3(0.0);
if(f < 2.0) return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i/4.0); if(f < 1.0)
if(f < 3.0) return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i/4.0); return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i / 4.0);
if(f < 4.0) return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i/4.0); if(f < 2.0)
if(f < 5.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i/4.0); return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i / 4.0);
if(f < 6.0) return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i/4.0); if(f < 3.0)
if(f < 7.0) return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i/4.0); return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i / 4.0);
if(f < 8.0) return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i/4.0); if(f < 4.0)
return vec3(1.0); return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i / 4.0);
if(f < 5.0)
return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i / 4.0);
if(f < 6.0)
return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i / 4.0);
if(f < 7.0)
return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i / 4.0);
if(f < 8.0)
return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i / 4.0);
return vec3(1.0);
} }
void main() void main()
{ {
ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(xTex, 0).xy))); ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(xTex, 0).xy)));
float tl = x(pixelCoord + ivec2(-1, 1)); float tl = x(pixelCoord + ivec2(-1, 1));
float tr = x(pixelCoord + ivec2(1, 1)); float tr = x(pixelCoord + ivec2(1, 1));
float bl = x(pixelCoord + ivec2(-1, -1)); float bl = x(pixelCoord + ivec2(-1, -1));
float br = x(pixelCoord + ivec2(1, -1)); float br = x(pixelCoord + ivec2(1, -1));
float residue = b(pixelCoord) - (-tl - tr - bl - br + 4.*x(pixelCoord)); float residue = b(pixelCoord) - (-tl - tr - bl - br + 4. * x(pixelCoord));
fragColor = vec4(color_map(residue), 1); fragColor = vec4(color_map(residue), 1);
} }

View File

@ -10,9 +10,9 @@ uniform ivec2 gridSize;
void main() void main()
{ {
float margin = 32.; float margin = 32.;
float ratio = 1. - 2.*margin/float(gridSize.x); float ratio = 1. - 2. * margin / float(gridSize.x);
texCoord = margin/float(gridSize.x) + ratio*(0.5*(pos + vec2(1,1))); texCoord = margin / float(gridSize.x) + ratio * (0.5 * (pos + vec2(1, 1)));
gl_Position = mvp * vec4(pos, 0, 1); gl_Position = mvp * vec4(pos, 0, 1);
} }

View File

@ -7,6 +7,6 @@ out vec2 texCoord;
void main() void main()
{ {
texCoord = 0.5*(pos + vec2(1,1)); texCoord = 0.5 * (pos + vec2(1, 1));
gl_Position = vec4(pos, 0, 1); gl_Position = vec4(pos, 0, 1);
} }

View File

@ -10,32 +10,32 @@ uniform sampler2D src;
vec2 u(ivec2 coord) vec2 u(ivec2 coord)
{ {
return(texelFetch(src, coord, 0).xy); return (texelFetch(src, coord, 0).xy);
} }
void main() void main()
{ {
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
if( pixelCoord.x <= 0 if(pixelCoord.x <= 0
|| pixelCoord.x >= textureSize(src, 0).x || pixelCoord.x >= textureSize(src, 0).x
|| pixelCoord.y <= 0 || pixelCoord.y <= 0
|| pixelCoord.y >= textureSize(src, 0).y) || pixelCoord.y >= textureSize(src, 0).y)
{ {
fragColor = vec4(0, 0, 0, 1); fragColor = vec4(0, 0, 0, 1);
} }
else else
{ {
vec2 tl = u(pixelCoord + ivec2(-1, 0)); vec2 tl = u(pixelCoord + ivec2(-1, 0));
vec2 tr = u(pixelCoord); vec2 tr = u(pixelCoord);
vec2 bl = u(pixelCoord + ivec2(-1, -1)); vec2 bl = u(pixelCoord + ivec2(-1, -1));
vec2 br = u(pixelCoord + ivec2(0, -1)); vec2 br = u(pixelCoord + ivec2(0, -1));
float r = (tr.x + br.x)/2.; float r = (tr.x + br.x) / 2.;
float l = (tl.x + bl.x)/2.; float l = (tl.x + bl.x) / 2.;
float t = (tl.y + tr.y)/2.; float t = (tl.y + tr.y) / 2.;
float b = (bl.y + br.y)/2.; float b = (bl.y + br.y) / 2.;
fragColor = vec4(-2.*(r - l + t - b), 0, 0, 1); fragColor = vec4(-2. * (r - l + t - b), 0, 0, 1);
} }
} }

View File

@ -11,45 +11,45 @@ uniform sampler2D bTex;
float x(ivec2 coord) float x(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x || coord.x >= textureSize(xTex, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y) || coord.y >= textureSize(xTex, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(xTex, coord, 0).x); return (texelFetch(xTex, coord, 0).x);
} }
float b(ivec2 coord) float b(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x || coord.x >= textureSize(bTex, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y) || coord.y >= textureSize(bTex, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(bTex, coord, 0).x); return (texelFetch(bTex, coord, 0).x);
} }
void main() void main()
{ {
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
if( pixelCoord.x <= 0 if(pixelCoord.x <= 0
|| pixelCoord.y <= 0) || pixelCoord.y <= 0)
{ {
fragColor = vec4(0, 0, 0, 1); fragColor = vec4(0, 0, 0, 1);
} }
else else
{ {
float tl = x(pixelCoord + ivec2(-1, 1)); float tl = x(pixelCoord + ivec2(-1, 1));
float tr = x(pixelCoord + ivec2(1, 1)); float tr = x(pixelCoord + ivec2(1, 1));
float bl = x(pixelCoord + ivec2(-1, -1)); float bl = x(pixelCoord + ivec2(-1, -1));
float br = x(pixelCoord + ivec2(1, -1)); float br = x(pixelCoord + ivec2(1, -1));
float jacobi = (tl + tr + bl + br + b(pixelCoord))/4.; float jacobi = (tl + tr + bl + br + b(pixelCoord)) / 4.;
fragColor = vec4(jacobi, 0, 0, 1); fragColor = vec4(jacobi, 0, 0, 1);
} }
} }

View File

@ -12,42 +12,42 @@ uniform float invGridSize;
float e(ivec2 coord) float e(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(error, 0).x || coord.x >= textureSize(error, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(error, 0).y) || coord.y >= textureSize(error, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(error, coord, 0).x); return (texelFetch(error, coord, 0).x);
} }
float p(ivec2 coord) float p(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(src, 0).x || coord.x >= textureSize(src, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(src, 0).y) || coord.y >= textureSize(src, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(src, coord, 0).x); return (texelFetch(src, coord, 0).x);
} }
void main() void main()
{ {
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
vec2 coarseCoord = vec2(pixelCoord)/2.; vec2 coarseCoord = vec2(pixelCoord) / 2.;
vec2 offset = fract(coarseCoord); vec2 offset = fract(coarseCoord);
ivec2 bl = ivec2(floor(coarseCoord)); ivec2 bl = ivec2(floor(coarseCoord));
ivec2 br = bl + ivec2(1, 0); ivec2 br = bl + ivec2(1, 0);
ivec2 tl = bl + ivec2(0, 1); ivec2 tl = bl + ivec2(0, 1);
ivec2 tr = bl + ivec2(1, 1); ivec2 tr = bl + ivec2(1, 1);
float topLerp = (1.-offset.x)*e(tl)+ offset.x*e(tr); float topLerp = (1. - offset.x) * e(tl) + offset.x * e(tr);
float bottomLerp = (1.-offset.x)*e(bl) + offset.x*e(br); float bottomLerp = (1. - offset.x) * e(bl) + offset.x * e(br);
float bilerpError = (1.-offset.y)*bottomLerp + offset.y*topLerp; float bilerpError = (1. - offset.y) * bottomLerp + offset.y * topLerp;
fragColor = vec4(p(pixelCoord) + bilerpError, 0, 0, 1); fragColor = vec4(p(pixelCoord) + bilerpError, 0, 0, 1);
} }

View File

@ -11,51 +11,51 @@ uniform sampler2D bTex;
float x(ivec2 coord) float x(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x || coord.x >= textureSize(xTex, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y) || coord.y >= textureSize(xTex, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(xTex, coord, 0).x); return (texelFetch(xTex, coord, 0).x);
} }
float b(ivec2 coord) float b(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x || coord.x >= textureSize(bTex, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y) || coord.y >= textureSize(bTex, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(bTex, coord, 0).x); return (texelFetch(bTex, coord, 0).x);
} }
float residual(ivec2 coord) float residual(ivec2 coord)
{ {
ivec2 vr = coord + ivec2(1, 0); ivec2 vr = coord + ivec2(1, 0);
ivec2 vl = coord - ivec2(1, 0); ivec2 vl = coord - ivec2(1, 0);
ivec2 vt = coord + ivec2(0, 1); ivec2 vt = coord + ivec2(0, 1);
ivec2 vb = coord - ivec2(0, 1); ivec2 vb = coord - ivec2(0, 1);
return((x(vl) + x(vr) + x(vt) + x(vb) + b(coord) - 4.*x(coord))*4.); return ((x(vl) + x(vr) + x(vt) + x(vb) + b(coord) - 4. * x(coord)) * 4.);
} }
void main() void main()
{ {
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
float restricted = residual(2*pixelCoord + ivec2(-1, -1)) float restricted = residual(2 * pixelCoord + ivec2(-1, -1))
+ residual(2*pixelCoord + ivec2(1, -1)) + residual(2 * pixelCoord + ivec2(1, -1))
+ residual(2*pixelCoord + ivec2(1, 1)) + residual(2 * pixelCoord + ivec2(1, 1))
+ residual(2*pixelCoord + ivec2(-1, 1)) + residual(2 * pixelCoord + ivec2(-1, 1))
+ 2.*residual(2*pixelCoord + ivec2(-1, 0)) + 2. * residual(2 * pixelCoord + ivec2(-1, 0))
+ 2.*residual(2*pixelCoord + ivec2(1, 0)) + 2. * residual(2 * pixelCoord + ivec2(1, 0))
+ 2.*residual(2*pixelCoord + ivec2(0, -1)) + 2. * residual(2 * pixelCoord + ivec2(0, -1))
+ 2.*residual(2*pixelCoord + ivec2(0, 1)) + 2. * residual(2 * pixelCoord + ivec2(0, 1))
+ 4.*residual(2*pixelCoord); + 4. * residual(2 * pixelCoord);
restricted /= 16.; restricted /= 16.;
fragColor = vec4(restricted, 0, 0, 1); fragColor = vec4(restricted, 0, 0, 1);
} }

View File

@ -17,13 +17,13 @@ uniform float randomize;
void main() void main()
{ {
float d2 = dot(texCoord - splatPos, texCoord - splatPos); float d2 = dot(texCoord - splatPos, texCoord - splatPos);
float intensity = exp(-10.*d2/radius); float intensity = exp(-10. * d2 / radius);
vec2 force = splatColor.xy; vec2 force = splatColor.xy;
vec3 u = texture(src, texCoord).xyz; vec3 u = texture(src, texCoord).xyz;
vec3 uAdd = u + intensity*splatColor.xyz; vec3 uAdd = u + intensity * splatColor.xyz;
vec3 uBlend = u*(1.-intensity) + intensity * splatColor; vec3 uBlend = u * (1. - intensity) + intensity * splatColor;
fragColor = vec4(uAdd*additive + uBlend*blending, 1); fragColor = vec4(uAdd * additive + uBlend * blending, 1);
} }

View File

@ -12,36 +12,36 @@ uniform float invGridSize;
vec2 u(ivec2 coord) vec2 u(ivec2 coord)
{ {
return(texelFetch(src, coord, 0).xy); return (texelFetch(src, coord, 0).xy);
} }
float p(ivec2 coord) float p(ivec2 coord)
{ {
if( coord.x <= 0 if(coord.x <= 0
|| coord.x >= textureSize(pressure, 0).x || coord.x >= textureSize(pressure, 0).x
|| coord.y <= 0 || coord.y <= 0
|| coord.y >= textureSize(pressure, 0).y) || coord.y >= textureSize(pressure, 0).y)
{ {
return(0.); return (0.);
} }
return(texelFetch(pressure, coord, 0).x); return (texelFetch(pressure, coord, 0).x);
} }
void main() void main()
{ {
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
float tl = p(pixelCoord + ivec2(0, 1)); float tl = p(pixelCoord + ivec2(0, 1));
float tr = p(pixelCoord + ivec2(1, 1)); float tr = p(pixelCoord + ivec2(1, 1));
float bl = p(pixelCoord); float bl = p(pixelCoord);
float br = p(pixelCoord + ivec2(1, 0)); float br = p(pixelCoord + ivec2(1, 0));
float r = (tr + br)/2.; float r = (tr + br) / 2.;
float l = (tl + bl)/2.; float l = (tl + bl) / 2.;
float t = (tl + tr)/2.; float t = (tl + tr) / 2.;
float b = (bl + br)/2.; float b = (bl + br) / 2.;
vec2 gradP = vec2(r - l, t - b); vec2 gradP = vec2(r - l, t - b);
fragColor = vec4(u(pixelCoord) - gradP, 0, 1); fragColor = vec4(u(pixelCoord) - gradP, 0, 1);
} }

View File

@ -2,37 +2,37 @@
#include <orca.h> #include <orca.h>
oc_vec2 frameSize = {100, 100}; oc_vec2 frameSize = { 100, 100 };
oc_surface surface; oc_surface surface;
unsigned int program; unsigned int program;
const char* vshaderSource = const char* vshaderSource =
"attribute vec4 vPosition;\n" "attribute vec4 vPosition;\n"
"uniform mat4 transform;\n" "uniform mat4 transform;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Position = transform*vPosition;\n" " gl_Position = transform*vPosition;\n"
"}\n"; "}\n";
const char* fshaderSource = const char* fshaderSource =
"precision mediump float;\n" "precision mediump float;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n"; "}\n";
void compile_shader(GLuint shader, const char* source) void compile_shader(GLuint shader, const char* source)
{ {
glShaderSource(shader, 1, &source, 0); glShaderSource(shader, 1, &source, 0);
glCompileShader(shader); glCompileShader(shader);
int err = glGetError(); int err = glGetError();
if(err) if(err)
{ {
oc_log_info("gl error"); oc_log_info("gl error");
} }
} }
ORCA_EXPORT void oc_on_init(void) ORCA_EXPORT void oc_on_init(void)
@ -45,32 +45,32 @@ ORCA_EXPORT void oc_on_init(void)
int extensionCount = 0; int extensionCount = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
for(int i=0; i<extensionCount; i++) for(int i = 0; i < extensionCount; i++)
{ {
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i); const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
oc_log_info("GLES extension %i: %s\n", i, extension); oc_log_info("GLES extension %i: %s\n", i, extension);
} }
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER); unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram(); program = glCreateProgram();
compile_shader(vshader, vshaderSource); compile_shader(vshader, vshaderSource);
compile_shader(fshader, fshaderSource); compile_shader(fshader, fshaderSource);
glAttachShader(program, vshader); glAttachShader(program, vshader);
glAttachShader(program, fshader); glAttachShader(program, fshader);
glLinkProgram(program); glLinkProgram(program);
glUseProgram(program); glUseProgram(program);
GLfloat vertices[] = {
-0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0
};
GLfloat vertices[] = { GLuint buffer;
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0}; glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
GLuint buffer; glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
@ -85,22 +85,22 @@ ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
ORCA_EXPORT void oc_on_frame_refresh(void) ORCA_EXPORT void oc_on_frame_refresh(void)
{ {
f32 aspect = frameSize.x/frameSize.y; f32 aspect = frameSize.x / frameSize.y;
oc_surface_select(surface); oc_surface_select(surface);
glClearColor(0, 1, 1, 1); glClearColor(0, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
static float alpha = 0; static float alpha = 0;
glViewport(0, 0, frameSize.x * 2, frameSize.y * 2); glViewport(0, 0, frameSize.x * 2, frameSize.y * 2);
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0, GLfloat matrix[] = { cosf(alpha) / aspect, sinf(alpha), 0, 0,
-sinf(alpha)/aspect, cosf(alpha), 0, 0, -sinf(alpha) / aspect, cosf(alpha), 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1}; 0, 0, 0, 1 };
alpha += 2*M_PI/120; alpha += 2 * M_PI / 120;
glUniformMatrix4fv(0, 1, false, matrix); glUniformMatrix4fv(0, 1, false, matrix);

View File

@ -224,24 +224,24 @@ ORCA_EXPORT void oc_on_frame_refresh(void)
switch(result) switch(result)
{ {
case 1: case 1:
case 5: case 5:
velocity.y = -vy; velocity.y = -vy;
break; break;
case 3: case 3:
case 7: case 7:
velocity.x = -vx; velocity.x = -vx;
break; break;
case 2: case 2:
case 6: case 6:
velocity.x = -vy; velocity.x = -vy;
velocity.y = -vx; velocity.y = -vx;
break; break;
case 4: case 4:
case 8: case 8:
velocity.x = vy; velocity.x = vy;
velocity.y = vx; velocity.y = vx;
break; break;
} }
} }
} }

View File

@ -1,400 +1,396 @@
#include"orca.h" #include "orca.h"
oc_vec2 frameSize = {100, 100}; oc_vec2 frameSize = { 100, 100 };
oc_surface surface; oc_surface surface;
oc_canvas canvas; oc_canvas canvas;
oc_font font; oc_font font;
oc_ui_context ui; oc_ui_context ui;
oc_arena textArena = {0}; oc_arena textArena = { 0 };
ORCA_EXPORT void oc_on_init(void) ORCA_EXPORT void oc_on_init(void)
{ {
surface = oc_surface_canvas(); surface = oc_surface_canvas();
canvas = oc_canvas_create(); canvas = oc_canvas_create();
oc_ui_init(&ui); oc_ui_init(&ui);
//NOTE: load font //NOTE: load font
{ {
oc_file file = oc_file_open(OC_STR8("/OpenSansLatinSubset.ttf"), OC_FILE_ACCESS_READ, 0); oc_file file = oc_file_open(OC_STR8("/OpenSansLatinSubset.ttf"), OC_FILE_ACCESS_READ, 0);
if(oc_file_last_error(file) != OC_IO_OK) if(oc_file_last_error(file) != OC_IO_OK)
{ {
oc_log_error("Couldn't open file OpenSansLatinSubset.ttf\n"); oc_log_error("Couldn't open file OpenSansLatinSubset.ttf\n");
} }
u64 size = oc_file_size(file); u64 size = oc_file_size(file);
char* buffer = oc_arena_push(oc_scratch(), size); char* buffer = oc_arena_push(oc_scratch(), size);
oc_file_read(file, size, buffer); oc_file_read(file, size, buffer);
oc_file_close(file); oc_file_close(file);
oc_unicode_range ranges[5] = {OC_UNICODE_BASIC_LATIN, oc_unicode_range ranges[5] = { OC_UNICODE_BASIC_LATIN,
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT, OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
OC_UNICODE_LATIN_EXTENDED_A, OC_UNICODE_LATIN_EXTENDED_A,
OC_UNICODE_LATIN_EXTENDED_B, OC_UNICODE_LATIN_EXTENDED_B,
OC_UNICODE_SPECIALS}; OC_UNICODE_SPECIALS };
// TODO: Decide whether we're using strings or explicit pointer + length // TODO: Decide whether we're using strings or explicit pointer + length
font = oc_font_create_from_memory(oc_str8_from_buffer(size, buffer), 5, ranges); font = oc_font_create_from_memory(oc_str8_from_buffer(size, buffer), 5, ranges);
} }
oc_arena_clear(oc_scratch()); oc_arena_clear(oc_scratch());
oc_arena_init(&textArena); oc_arena_init(&textArena);
} }
ORCA_EXPORT void oc_on_resize(u32 width, u32 height) ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
{ {
oc_log_info("frame resize %u, %u", width, height); oc_log_info("frame resize %u, %u", width, height);
frameSize.x = width; frameSize.x = width;
frameSize.y = height; frameSize.y = height;
} }
ORCA_EXPORT void oc_on_raw_event(oc_event *event) ORCA_EXPORT void oc_on_raw_event(oc_event* event)
{ {
oc_ui_process_event(event); oc_ui_process_event(event);
} }
void widget_begin_view(char* str) void widget_begin_view(char* str)
{ {
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_Y, oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_Y,
.layout.spacing = 10, .layout.spacing = 10,
.layout.margin.x = 10, .layout.margin.x = 10,
.layout.margin.y = 10, .layout.margin.y = 10,
.layout.align.x = OC_UI_ALIGN_CENTER, .layout.align.x = OC_UI_ALIGN_CENTER,
.layout.align.y = OC_UI_ALIGN_START}, .layout.align.y = OC_UI_ALIGN_START },
OC_UI_STYLE_LAYOUT); OC_UI_STYLE_LAYOUT);
oc_ui_box_begin(str, OC_UI_FLAG_DRAW_BORDER);
oc_ui_label(str);
oc_ui_box_begin(str, OC_UI_FLAG_DRAW_BORDER);
oc_ui_label(str);
} }
void widget_end_view(void) void widget_end_view(void)
{ {
oc_ui_box_end(); oc_ui_box_end();
} }
#define widget_view(s) oc_defer_loop(widget_begin_view(s), widget_end_view()) #define widget_view(s) oc_defer_loop(widget_begin_view(s), widget_end_view())
ORCA_EXPORT void oc_on_frame_refresh(void) ORCA_EXPORT void oc_on_frame_refresh(void)
{ {
oc_ui_style defaultStyle = {.bgColor = {0}, oc_ui_style defaultStyle = { .bgColor = { 0 },
.color = {1, 1, 1, 1}, .color = { 1, 1, 1, 1 },
.font = font, .font = font,
.fontSize = 16, .fontSize = 16,
.borderColor = {0.278, 0.333, 0.412, 1}, .borderColor = { 0.278, 0.333, 0.412, 1 },
.borderSize = 2}; .borderSize = 2 };
oc_ui_style_mask defaultMask = OC_UI_STYLE_BG_COLOR oc_ui_style_mask defaultMask = OC_UI_STYLE_BG_COLOR
| OC_UI_STYLE_COLOR | OC_UI_STYLE_COLOR
| OC_UI_STYLE_BORDER_COLOR | OC_UI_STYLE_BORDER_COLOR
| OC_UI_STYLE_BORDER_SIZE | OC_UI_STYLE_BORDER_SIZE
| OC_UI_STYLE_FONT | OC_UI_STYLE_FONT
| OC_UI_STYLE_FONT_SIZE; | OC_UI_STYLE_FONT_SIZE;
oc_ui_frame(frameSize, &defaultStyle, defaultMask) oc_ui_frame(frameSize, &defaultStyle, defaultMask)
{ {
oc_ui_style_match_before(oc_ui_pattern_all(), &defaultStyle, defaultMask); oc_ui_style_match_before(oc_ui_pattern_all(), &defaultStyle, defaultMask);
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
.size.height = {OC_UI_SIZE_PARENT, 1}, .size.height = { OC_UI_SIZE_PARENT, 1 },
.layout.axis = OC_UI_AXIS_Y, .layout.axis = OC_UI_AXIS_Y,
.layout.align.x = OC_UI_ALIGN_CENTER, .layout.align.x = OC_UI_ALIGN_CENTER,
.layout.align.y = OC_UI_ALIGN_START, .layout.align.y = OC_UI_ALIGN_START,
.layout.spacing = 10, .layout.spacing = 10,
.layout.margin.x = 10, .layout.margin.x = 10,
.layout.margin.y = 10, .layout.margin.y = 10,
.bgColor = {0.11, 0.11, 0.11, 1}}, .bgColor = { 0.11, 0.11, 0.11, 1 } },
OC_UI_STYLE_SIZE OC_UI_STYLE_SIZE
| OC_UI_STYLE_LAYOUT | OC_UI_STYLE_LAYOUT
| OC_UI_STYLE_BG_COLOR); | OC_UI_STYLE_BG_COLOR);
oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND) oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND)
{ {
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
.size.height = {OC_UI_SIZE_CHILDREN}, .size.height = { OC_UI_SIZE_CHILDREN },
.layout.align.x = OC_UI_ALIGN_CENTER}, .layout.align.x = OC_UI_ALIGN_CENTER },
OC_UI_STYLE_SIZE OC_UI_STYLE_SIZE
|OC_UI_STYLE_LAYOUT_ALIGN_X); | OC_UI_STYLE_LAYOUT_ALIGN_X);
oc_ui_container("title", 0) oc_ui_container("title", 0)
{ {
oc_ui_style_next(&(oc_ui_style){.fontSize = 26}, OC_UI_STYLE_FONT_SIZE); oc_ui_style_next(&(oc_ui_style){ .fontSize = 26 }, OC_UI_STYLE_FONT_SIZE);
oc_ui_label("Orca UI Demo"); oc_ui_label("Orca UI Demo");
if(oc_ui_box_sig(oc_ui_box_top()).hovering) if(oc_ui_box_sig(oc_ui_box_top()).hovering)
{ {
oc_ui_tooltip("tooltip") oc_ui_tooltip("tooltip")
{ {
oc_ui_style_next(&(oc_ui_style){.bgColor = {1, 0.99, 0.82, 1}}, oc_ui_style_next(&(oc_ui_style){ .bgColor = { 1, 0.99, 0.82, 1 } },
OC_UI_STYLE_BG_COLOR); OC_UI_STYLE_BG_COLOR);
oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND) oc_ui_container("background", OC_UI_FLAG_DRAW_BACKGROUND)
{ {
oc_ui_style_next(&(oc_ui_style){.color = {0, 0, 0, 1}}, oc_ui_style_next(&(oc_ui_style){ .color = { 0, 0, 0, 1 } },
OC_UI_STYLE_COLOR); OC_UI_STYLE_COLOR);
oc_ui_label("That is a tooltip!"); oc_ui_label("That is a tooltip!");
} }
} }
} }
} }
oc_ui_menu_bar("Menu bar") oc_ui_menu_bar("Menu bar")
{ {
oc_ui_menu("Menu 1") oc_ui_menu("Menu 1")
{ {
if(oc_ui_menu_button("Option 1.1").pressed) if(oc_ui_menu_button("Option 1.1").pressed)
{ {
oc_log_info("Pressed option 1.1\n"); oc_log_info("Pressed option 1.1\n");
} }
oc_ui_menu_button("Option 1.2"); oc_ui_menu_button("Option 1.2");
oc_ui_menu_button("Option 1.3"); oc_ui_menu_button("Option 1.3");
oc_ui_menu_button("Option 1.4"); oc_ui_menu_button("Option 1.4");
} }
oc_ui_menu("Menu 2") oc_ui_menu("Menu 2")
{ {
oc_ui_menu_button("Option 2.1"); oc_ui_menu_button("Option 2.1");
oc_ui_menu_button("Option 2.2"); oc_ui_menu_button("Option 2.2");
oc_ui_menu_button("Option 2.3"); oc_ui_menu_button("Option 2.3");
oc_ui_menu_button("Option 2.4"); oc_ui_menu_button("Option 2.4");
} }
oc_ui_menu("Menu 3") oc_ui_menu("Menu 3")
{ {
oc_ui_menu_button("Option 3.1"); oc_ui_menu_button("Option 3.1");
oc_ui_menu_button("Option 3.2"); oc_ui_menu_button("Option 3.2");
oc_ui_menu_button("Option 3.3"); oc_ui_menu_button("Option 3.3");
oc_ui_menu_button("Option 3.4"); oc_ui_menu_button("Option 3.4");
} }
} }
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
.size.height = {OC_UI_SIZE_PARENT, 1, 1}}, .size.height = { OC_UI_SIZE_PARENT, 1, 1 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X}, OC_UI_STYLE_LAYOUT_AXIS); oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_X }, OC_UI_STYLE_LAYOUT_AXIS);
oc_ui_container("contents", 0) oc_ui_container("contents", 0)
{ {
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.5 },
.size.height = {OC_UI_SIZE_PARENT, 1}}, .size.height = { OC_UI_SIZE_PARENT, 1 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
oc_ui_container("left", 0) oc_ui_container("left", 0)
{ {
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X, oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_X,
.layout.spacing = 10, .layout.spacing = 10,
.layout.margin.x = 10, .layout.margin.x = 10,
.layout.margin.y = 10, .layout.margin.y = 10,
.size.width = {OC_UI_SIZE_PARENT, 1}, .size.width = { OC_UI_SIZE_PARENT, 1 },
.size.height = {OC_UI_SIZE_PARENT, 0.5}}, .size.height = { OC_UI_SIZE_PARENT, 0.5 } },
OC_UI_STYLE_LAYOUT_AXIS OC_UI_STYLE_LAYOUT_AXIS
|OC_UI_STYLE_LAYOUT_SPACING | OC_UI_STYLE_LAYOUT_SPACING
|OC_UI_STYLE_LAYOUT_MARGIN_X | OC_UI_STYLE_LAYOUT_MARGIN_X
|OC_UI_STYLE_LAYOUT_MARGIN_Y | OC_UI_STYLE_LAYOUT_MARGIN_Y
|OC_UI_STYLE_SIZE); | OC_UI_STYLE_SIZE);
oc_ui_container("up", 0) oc_ui_container("up", 0)
{ {
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.5 },
.size.height = {OC_UI_SIZE_PARENT, 1}}, .size.height = { OC_UI_SIZE_PARENT, 1 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
widget_view("Buttons") widget_view("Buttons")
{ {
if(oc_ui_button("Button A").clicked) if(oc_ui_button("Button A").clicked)
{ {
oc_log_info("A clicked"); oc_log_info("A clicked");
} }
if(oc_ui_button("Button B").clicked) if(oc_ui_button("Button B").clicked)
{ {
oc_log_info("B clicked"); oc_log_info("B clicked");
} }
if(oc_ui_button("Button C").clicked) if(oc_ui_button("Button C").clicked)
{ {
oc_log_info("C clicked"); oc_log_info("C clicked");
} }
} }
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.5 },
.size.height = {OC_UI_SIZE_PARENT, 1}}, .size.height = { OC_UI_SIZE_PARENT, 1 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
oc_ui_pattern pattern = { 0 };
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){ .kind = OC_UI_SEL_TAG, .tag = oc_ui_tag_make("checkbox") });
oc_ui_style_match_after(pattern,
&(oc_ui_style){ .bgColor = { 0, 1, 0, 1 },
.color = { 1, 1, 1, 1 } },
OC_UI_STYLE_COLOR | OC_UI_STYLE_BG_COLOR);
oc_ui_pattern pattern = {0}; widget_view("checkboxes")
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){.kind = OC_UI_SEL_TAG, .tag = oc_ui_tag_make("checkbox")}); {
oc_ui_style_match_after(pattern, static bool check1 = true;
&(oc_ui_style){.bgColor = {0, 1, 0, 1}, static bool check2 = false;
.color = {1, 1, 1, 1}}, static bool check3 = false;
OC_UI_STYLE_COLOR | OC_UI_STYLE_BG_COLOR);
widget_view("checkboxes") oc_ui_checkbox("check1", &check1);
{ oc_ui_checkbox("check2", &check2);
static bool check1 = true; oc_ui_checkbox("check3", &check3);
static bool check2 = false; }
static bool check3 = false; }
oc_ui_checkbox("check1", &check1); oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_X,
oc_ui_checkbox("check2", &check2); .size.width = { OC_UI_SIZE_PARENT, 1 },
oc_ui_checkbox("check3", &check3); .size.height = { OC_UI_SIZE_PARENT, 0.5 } },
} OC_UI_STYLE_LAYOUT_AXIS
} | OC_UI_STYLE_SIZE);
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X, oc_ui_container("down", 0)
.size.width = {OC_UI_SIZE_PARENT, 1}, {
.size.height = {OC_UI_SIZE_PARENT, 0.5}}, widget_view("Vertical Sliders")
OC_UI_STYLE_LAYOUT_AXIS {
|OC_UI_STYLE_SIZE); oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_X,
.layout.spacing = 10 },
OC_UI_STYLE_LAYOUT_AXIS
| OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("contents", 0)
{
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, 20 },
.size.height = { OC_UI_SIZE_PIXELS, 200 } },
OC_UI_STYLE_SIZE);
static f32 slider1 = 0;
oc_ui_slider("slider1", 0.2, &slider1);
oc_ui_container("down", 0) oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, 20 },
{ .size.height = { OC_UI_SIZE_PIXELS, 200 } },
widget_view("Vertical Sliders") OC_UI_STYLE_SIZE);
{ static f32 slider2 = 0;
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X, oc_ui_slider("slider2", 0.2, &slider2);
.layout.spacing = 10},
OC_UI_STYLE_LAYOUT_AXIS
|OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("contents", 0)
{
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20},
.size.height = {OC_UI_SIZE_PIXELS, 200}},
OC_UI_STYLE_SIZE);
static f32 slider1 = 0;
oc_ui_slider("slider1", 0.2, &slider1);
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, 20 },
.size.height = {OC_UI_SIZE_PIXELS, 200}}, .size.height = { OC_UI_SIZE_PIXELS, 200 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
static f32 slider2 = 0; static f32 slider3 = 0;
oc_ui_slider("slider2", 0.2, &slider2); oc_ui_slider("slider3", 0.2, &slider3);
}
}
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 20}, widget_view("Horizontal Sliders")
.size.height = {OC_UI_SIZE_PIXELS, 200}}, {
OC_UI_STYLE_SIZE); oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, 200 },
static f32 slider3 = 0; .size.height = { OC_UI_SIZE_PIXELS, 20 } },
oc_ui_slider("slider3", 0.2, &slider3); OC_UI_STYLE_SIZE);
} static f32 slider1 = 0;
} oc_ui_slider("slider1", 0.2, &slider1);
widget_view("Horizontal Sliders") oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, 200 },
{ .size.height = { OC_UI_SIZE_PIXELS, 20 } },
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200}, OC_UI_STYLE_SIZE);
.size.height = {OC_UI_SIZE_PIXELS, 20}}, static f32 slider2 = 0;
OC_UI_STYLE_SIZE); oc_ui_slider("slider2", 0.2, &slider2);
static f32 slider1 = 0;
oc_ui_slider("slider1", 0.2, &slider1);
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, 200 },
.size.height = {OC_UI_SIZE_PIXELS, 20}}, .size.height = { OC_UI_SIZE_PIXELS, 20 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
static f32 slider2 = 0; static f32 slider3 = 0;
oc_ui_slider("slider2", 0.2, &slider2); oc_ui_slider("slider3", 0.2, &slider3);
}
}
}
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 200}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 0.5 },
.size.height = {OC_UI_SIZE_PIXELS, 20}}, .size.height = { OC_UI_SIZE_PARENT, 1 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
static f32 slider3 = 0;
oc_ui_slider("slider3", 0.2, &slider3);
}
}
}
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 0.5}, oc_ui_container("right", 0)
.size.height = {OC_UI_SIZE_PARENT, 1}}, {
OC_UI_STYLE_SIZE);
oc_ui_container("right", 0) oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
{ .size.height = { OC_UI_SIZE_PARENT, 0.33 } },
OC_UI_STYLE_SIZE);
widget_view("Text box")
{
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PIXELS, 300 },
.size.height = { OC_UI_SIZE_TEXT } },
OC_UI_STYLE_SIZE);
static oc_str8 text = { 0 };
oc_ui_text_box_result res = oc_ui_text_box("textbox", oc_scratch(), text);
if(res.changed)
{
oc_arena_clear(&textArena);
text = oc_str8_push_copy(&textArena, res.text);
}
}
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1}, oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
.size.height = {OC_UI_SIZE_PARENT, 0.33}}, .size.height = { OC_UI_SIZE_PARENT, 0.33 } },
OC_UI_STYLE_SIZE); OC_UI_STYLE_SIZE);
widget_view("Text box") widget_view("Test")
{ {
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PIXELS, 300}, oc_ui_pattern pattern = { 0 };
.size.height = {OC_UI_SIZE_TEXT}}, oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){ .kind = OC_UI_SEL_TEXT, .text = OC_STR8("panel") });
OC_UI_STYLE_SIZE); oc_ui_style_match_after(pattern, &(oc_ui_style){ .bgColor = { 0.3, 0.3, 1, 1 } }, OC_UI_STYLE_BG_COLOR);
static oc_str8 text = {0};
oc_ui_text_box_result res = oc_ui_text_box("textbox", oc_scratch(), text);
if(res.changed)
{
oc_arena_clear(&textArena);
text = oc_str8_push_copy(&textArena, res.text);
}
}
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1}, static int selected = 0;
.size.height = {OC_UI_SIZE_PARENT, 0.33}}, oc_str8 options[] = { OC_STR8("option 1"),
OC_UI_STYLE_SIZE); OC_STR8("option 2"),
widget_view("Test") OC_STR8("long option 3"),
{ OC_STR8("option 4"),
oc_ui_pattern pattern = {0}; OC_STR8("option 5") };
oc_ui_pattern_push(oc_scratch(), &pattern, (oc_ui_selector){.kind = OC_UI_SEL_TEXT, .text = OC_STR8("panel")}); oc_ui_select_popup_info info = { .selectedIndex = selected,
oc_ui_style_match_after(pattern, &(oc_ui_style){.bgColor = {0.3, 0.3, 1, 1}}, OC_UI_STYLE_BG_COLOR); .optionCount = 5,
.options = options };
static int selected = 0; oc_ui_select_popup_info result = oc_ui_select_popup("popup", &info);
oc_str8 options[] = {OC_STR8("option 1"), selected = result.selectedIndex;
OC_STR8("option 2"), }
OC_STR8("long option 3"),
OC_STR8("option 4"),
OC_STR8("option 5")};
oc_ui_select_popup_info info = {.selectedIndex = selected,
.optionCount = 5,
.options = options};
oc_ui_select_popup_info result = oc_ui_select_popup("popup", &info); oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
selected = result.selectedIndex; .size.height = { OC_UI_SIZE_PARENT, 0.33 } },
} OC_UI_STYLE_SIZE);
widget_view("Color")
{
oc_ui_style_next(&(oc_ui_style){ .size.width = { OC_UI_SIZE_PARENT, 1 },
.size.height = { OC_UI_SIZE_PARENT, 0.7 },
.layout.axis = OC_UI_AXIS_X },
OC_UI_STYLE_SIZE
| OC_UI_STYLE_LAYOUT_AXIS);
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1}, oc_ui_panel("Panel", OC_UI_FLAG_DRAW_BORDER)
.size.height = {OC_UI_SIZE_PARENT, 0.33}}, {
OC_UI_STYLE_SIZE); oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_X },
widget_view("Color") OC_UI_STYLE_LAYOUT_AXIS);
{ oc_ui_container("contents", 0)
oc_ui_style_next(&(oc_ui_style){.size.width = {OC_UI_SIZE_PARENT, 1}, {
.size.height = {OC_UI_SIZE_PARENT, 0.7}, oc_ui_style_next(&(oc_ui_style){ .layout.spacing = 20 },
.layout.axis = OC_UI_AXIS_X}, OC_UI_STYLE_LAYOUT_SPACING);
OC_UI_STYLE_SIZE oc_ui_container("buttons", 0)
|OC_UI_STYLE_LAYOUT_AXIS); {
oc_ui_button("Button A");
oc_ui_button("Button B");
oc_ui_button("Button C");
oc_ui_button("Button D");
}
oc_ui_panel("Panel", OC_UI_FLAG_DRAW_BORDER) oc_ui_style_next(&(oc_ui_style){ .layout.axis = OC_UI_AXIS_X,
{ .layout.spacing = 20 },
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X}, OC_UI_STYLE_LAYOUT_SPACING
OC_UI_STYLE_LAYOUT_AXIS); | OC_UI_STYLE_LAYOUT_AXIS);
oc_ui_container("contents", 0)
{
oc_ui_style_next(&(oc_ui_style){.layout.spacing = 20},
OC_UI_STYLE_LAYOUT_SPACING);
oc_ui_container("buttons", 0)
{
oc_ui_button("Button A");
oc_ui_button("Button B");
oc_ui_button("Button C");
oc_ui_button("Button D");
}
oc_ui_style_next(&(oc_ui_style){.layout.axis = OC_UI_AXIS_X, oc_ui_container("buttons2", 0)
.layout.spacing = 20}, {
OC_UI_STYLE_LAYOUT_SPACING oc_ui_button("Button A");
|OC_UI_STYLE_LAYOUT_AXIS); oc_ui_button("Button B");
oc_ui_button("Button C");
oc_ui_button("Button D");
}
}
}
}
}
}
}
}
oc_ui_container("buttons2", 0) oc_canvas_set_current(canvas);
{
oc_ui_button("Button A");
oc_ui_button("Button B");
oc_ui_button("Button C");
oc_ui_button("Button D");
}
}
}
}
}
}
}
}
oc_canvas_set_current(canvas);
oc_surface_select(surface); oc_surface_select(surface);
oc_ui_draw(); oc_ui_draw();
oc_render(surface, canvas); oc_render(surface, canvas);
oc_surface_present(surface); oc_surface_present(surface);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,101 +6,102 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include <errno.h>
#include<string.h> #include <stdlib.h>
#include<errno.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#include"milepost.h" #include "milepost.h"
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; mp_rect windowRect = { .x = 100, .y = 100, .w = 810, .h = 610 };
mp_window window = mp_window_create(windowRect, "test", 0); mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window); mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
if(mg_surface_is_nil(surface)) if(mg_surface_is_nil(surface))
{ {
log_error("couldn't create surface\n"); log_error("couldn't create surface\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface, 0); mg_surface_swap_interval(surface, 0);
//NOTE: create canvas //NOTE: create canvas
mg_canvas canvas = mg_canvas_create(); mg_canvas canvas = mg_canvas_create();
if(mg_canvas_is_nil(canvas)) if(mg_canvas_is_nil(canvas))
{ {
log_error("Error: couldn't create canvas\n"); log_error("Error: couldn't create canvas\n");
return(-1); return (-1);
} }
//NOTE: create atlas //NOTE: create atlas
mem_arena permanentArena = {0}; mem_arena permanentArena = { 0 };
mem_arena_init(&permanentArena); mem_arena_init(&permanentArena);
mg_rect_atlas* atlas = mg_rect_atlas_create(&permanentArena, 16000, 16000); mg_rect_atlas* atlas = mg_rect_atlas_create(&permanentArena, 16000, 16000);
mg_image atlasImage = mg_image_create(surface, 16000, 16000); mg_image atlasImage = mg_image_create(surface, 16000, 16000);
str8 path1 = path_executable_relative(mem_scratch(), STR8("../../sketches/resources/triceratops.png")); str8 path1 = path_executable_relative(mem_scratch(), STR8("../../sketches/resources/triceratops.png"));
str8 path2 = path_executable_relative(mem_scratch(), STR8("../../sketches/resources/Top512.png")); str8 path2 = path_executable_relative(mem_scratch(), STR8("../../sketches/resources/Top512.png"));
mg_image_region image1 = mg_image_atlas_alloc_from_file(atlas, atlasImage, path1, false); mg_image_region image1 = mg_image_atlas_alloc_from_file(atlas, atlasImage, path1, false);
mg_image_region image2 = mg_image_atlas_alloc_from_file(atlas, atlasImage, path2, false); mg_image_region image2 = mg_image_atlas_alloc_from_file(atlas, atlasImage, path2, false);
// start app // start app
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
while(!mp_should_quit()) while(!mp_should_quit())
{ {
mp_pump_events(0); mp_pump_events(0);
mp_event* event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
default: default:
break; break;
} }
} }
mg_surface_prepare(surface); mg_surface_prepare(surface);
mg_set_color_rgba(0, 1, 1, 1); mg_set_color_rgba(0, 1, 1, 1);
mg_clear(); mg_clear();
mg_set_color_rgba(1, 1, 1, 1); mg_set_color_rgba(1, 1, 1, 1);
mg_image_draw_region(image1.image, image1.rect, (mp_rect){100, 100, 300, 300}); mg_image_draw_region(image1.image, image1.rect, (mp_rect){ 100, 100, 300, 300 });
mg_image_draw_region(image2.image, image2.rect, (mp_rect){300, 200, 300, 300}); mg_image_draw_region(image2.image, image2.rect, (mp_rect){ 300, 200, 300, 300 });
mg_render(surface, canvas); mg_render(surface, canvas);
mg_surface_present(surface); mg_surface_present(surface);
mem_arena_clear(mem_scratch()); mem_arena_clear(mem_scratch());
} }
mg_image_atlas_recycle(atlas, image1); mg_image_atlas_recycle(atlas, image1);
mg_image_atlas_recycle(atlas, image2); mg_image_atlas_recycle(atlas, image2);
mg_canvas_destroy(canvas); mg_canvas_destroy(canvas);
mg_surface_destroy(surface); mg_surface_destroy(surface);
mp_window_destroy(window); mp_window_destroy(window);
mp_terminate(); mp_terminate();
return(0); return (0);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,213 +6,214 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include <errno.h>
#include<stdio.h> #include <stdio.h>
#include<string.h> #include <stdlib.h>
#include<errno.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#include"milepost.h" #include "milepost.h"
#define LOG_SUBSYSTEM "Main" #define LOG_SUBSYSTEM "Main"
mg_font create_font() mg_font create_font()
{ {
//NOTE(martin): create font //NOTE(martin): create font
str8 fontPath = path_executable_relative(mem_scratch(), STR8("../resources/OpenSansLatinSubset.ttf")); str8 fontPath = path_executable_relative(mem_scratch(), STR8("../resources/OpenSansLatinSubset.ttf"));
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath); char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath);
FILE* fontFile = fopen(fontPathCString, "r"); FILE* fontFile = fopen(fontPathCString, "r");
if(!fontFile) if(!fontFile)
{ {
log_error("Could not load font file '%s': %s\n", fontPathCString, strerror(errno)); log_error("Could not load font file '%s': %s\n", fontPathCString, strerror(errno));
return(mg_font_nil()); return (mg_font_nil());
} }
unsigned char* fontData = 0; unsigned char* fontData = 0;
fseek(fontFile, 0, SEEK_END); fseek(fontFile, 0, SEEK_END);
u32 fontDataSize = ftell(fontFile); u32 fontDataSize = ftell(fontFile);
rewind(fontFile); rewind(fontFile);
fontData = (unsigned char*)malloc(fontDataSize); fontData = (unsigned char*)malloc(fontDataSize);
fread(fontData, 1, fontDataSize, fontFile); fread(fontData, 1, fontDataSize, fontFile);
fclose(fontFile); fclose(fontFile);
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN, unicode_range ranges[5] = { UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT, UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
UNICODE_RANGE_LATIN_EXTENDED_A, UNICODE_RANGE_LATIN_EXTENDED_A,
UNICODE_RANGE_LATIN_EXTENDED_B, UNICODE_RANGE_LATIN_EXTENDED_B,
UNICODE_RANGE_SPECIALS}; UNICODE_RANGE_SPECIALS };
mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges); mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
free(fontData); free(fontData);
return(font); return (font);
} }
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; mp_rect windowRect = { .x = 100, .y = 100, .w = 810, .h = 610 };
mp_window window = mp_window_create(windowRect, "test", 0); mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window); mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
if(mg_surface_is_nil(surface)) if(mg_surface_is_nil(surface))
{ {
printf("Error: couldn't create surface\n"); printf("Error: couldn't create surface\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface, 0); mg_surface_swap_interval(surface, 0);
mg_canvas canvas = mg_canvas_create(); mg_canvas canvas = mg_canvas_create();
if(mg_canvas_is_nil(canvas)) if(mg_canvas_is_nil(canvas))
{ {
printf("Error: couldn't create canvas\n"); printf("Error: couldn't create canvas\n");
return(-1); return (-1);
} }
mg_font font = create_font(); mg_font font = create_font();
// start app // start app
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
f32 x = 400, y = 300; f32 x = 400, y = 300;
f32 speed = 0; f32 speed = 0;
f32 dx = speed, dy = speed; f32 dx = speed, dy = speed;
f64 frameTime = 0; f64 frameTime = 0;
while(!mp_should_quit()) while(!mp_should_quit())
{ {
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC); f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
mp_pump_events(0); mp_pump_events(0);
mp_event* event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
case MP_EVENT_KEYBOARD_KEY: case MP_EVENT_KEYBOARD_KEY:
{ {
if(event->key.action == MP_KEY_PRESS || event->key.action == MP_KEY_REPEAT) if(event->key.action == MP_KEY_PRESS || event->key.action == MP_KEY_REPEAT)
{ {
f32 factor = (event->key.mods & MP_KEYMOD_SHIFT) ? 10 : 1; f32 factor = (event->key.mods & MP_KEYMOD_SHIFT) ? 10 : 1;
if(event->key.code == MP_KEY_LEFT) if(event->key.code == MP_KEY_LEFT)
{ {
x-=0.3*factor; x -= 0.3 * factor;
} }
else if(event->key.code == MP_KEY_RIGHT) else if(event->key.code == MP_KEY_RIGHT)
{ {
x+=0.3*factor; x += 0.3 * factor;
} }
else if(event->key.code == MP_KEY_UP) else if(event->key.code == MP_KEY_UP)
{ {
y-=0.3*factor; y -= 0.3 * factor;
} }
else if(event->key.code == MP_KEY_DOWN) else if(event->key.code == MP_KEY_DOWN)
{ {
y+=0.3*factor; y += 0.3 * factor;
} }
} }
} break; }
break;
default: default:
break; break;
} }
} }
if(x-200 < 0) if(x - 200 < 0)
{ {
x = 200; x = 200;
dx = speed; dx = speed;
} }
if(x+200 > contentRect.w) if(x + 200 > contentRect.w)
{ {
x = contentRect.w - 200; x = contentRect.w - 200;
dx = -speed; dx = -speed;
} }
if(y-200 < 0) if(y - 200 < 0)
{ {
y = 200; y = 200;
dy = speed; dy = speed;
} }
if(y+200 > contentRect.h) if(y + 200 > contentRect.h)
{ {
y = contentRect.h - 200; y = contentRect.h - 200;
dy = -speed; dy = -speed;
} }
x += dx; x += dx;
y += dy; y += dy;
// background // background
mg_set_color_rgba(0, 1, 1, 1); mg_set_color_rgba(0, 1, 1, 1);
mg_clear(); mg_clear();
mg_set_color_rgba(1, 0, 1, 1); mg_set_color_rgba(1, 0, 1, 1);
mg_rectangle_fill(0, 0, 100, 100); mg_rectangle_fill(0, 0, 100, 100);
// head // head
mg_set_color_rgba(1, 1, 0, 1); mg_set_color_rgba(1, 1, 0, 1);
mg_circle_fill(x, y, 200); mg_circle_fill(x, y, 200);
// smile // smile
f32 frown = frameTime > 0.033 ? -100 : 0; f32 frown = frameTime > 0.033 ? -100 : 0;
mg_set_color_rgba(0, 0, 0, 1); mg_set_color_rgba(0, 0, 0, 1);
mg_set_width(20); mg_set_width(20);
mg_move_to(x-100, y+100); mg_move_to(x - 100, y + 100);
mg_cubic_to(x-50, y+150+frown, x+50, y+150+frown, x+100, y+100); mg_cubic_to(x - 50, y + 150 + frown, x + 50, y + 150 + frown, x + 100, y + 100);
mg_stroke(); mg_stroke();
// eyes // eyes
mg_ellipse_fill(x-70, y-50, 30, 50); mg_ellipse_fill(x - 70, y - 50, 30, 50);
mg_ellipse_fill(x+70, y-50, 30, 50); mg_ellipse_fill(x + 70, y - 50, 30, 50);
// text // text
mg_set_color_rgba(0, 0, 1, 1); mg_set_color_rgba(0, 0, 1, 1);
mg_set_font(font); mg_set_font(font);
mg_set_font_size(12); mg_set_font_size(12);
mg_move_to(50, 600-50); mg_move_to(50, 600 - 50);
str8 text = str8_pushf(mem_scratch(), str8 text = str8_pushf(mem_scratch(),
"Milepost vector graphics test program (frame time = %fs, fps = %f)...", "Milepost vector graphics test program (frame time = %fs, fps = %f)...",
frameTime, frameTime,
1./frameTime); 1. / frameTime);
mg_text_outlines(text); mg_text_outlines(text);
mg_fill(); mg_fill();
printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n", printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
frameTime, frameTime,
1./frameTime); 1. / frameTime);
mg_surface_prepare(surface); mg_surface_prepare(surface);
mg_render(surface, canvas); mg_render(surface, canvas);
mg_surface_present(surface); mg_surface_present(surface);
mem_arena_clear(mem_scratch()); mem_arena_clear(mem_scratch());
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime; frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
} }
mg_font_destroy(font); mg_font_destroy(font);
mg_canvas_destroy(canvas); mg_canvas_destroy(canvas);
mg_surface_destroy(surface); mg_surface_destroy(surface);
mp_window_destroy(window); mp_window_destroy(window);
mp_terminate(); mp_terminate();
return(0); return (0);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,81 +6,82 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdio.h> #include <errno.h>
#include<stdlib.h> #include <stdio.h>
#include<string.h> #include <stdlib.h>
#include<errno.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#include"milepost.h" #include "milepost.h"
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; mp_rect windowRect = { .x = 100, .y = 100, .w = 810, .h = 610 };
mp_window window = mp_window_create(windowRect, "test", 0); mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window); mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
if(mg_surface_is_nil(surface)) if(mg_surface_is_nil(surface))
{ {
log_error("couldn't create surface\n"); log_error("couldn't create surface\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface, 0); mg_surface_swap_interval(surface, 0);
//NOTE: create canvas //NOTE: create canvas
mg_canvas canvas = mg_canvas_create(); mg_canvas canvas = mg_canvas_create();
if(mg_canvas_is_nil(canvas)) if(mg_canvas_is_nil(canvas))
{ {
printf("Error: couldn't create canvas\n"); printf("Error: couldn't create canvas\n");
return(-1); return (-1);
} }
//NOTE: create image //NOTE: create image
str8 imagePath = path_executable_relative(mem_scratch(), STR8("../../sketches/resources/triceratops.png")); str8 imagePath = path_executable_relative(mem_scratch(), STR8("../../sketches/resources/triceratops.png"));
mg_image image = mg_image_create_from_file(surface, imagePath, false); mg_image image = mg_image_create_from_file(surface, imagePath, false);
vec2 imageSize = mg_image_size(image); vec2 imageSize = mg_image_size(image);
str8 imagePath2 = path_executable_relative(mem_scratch(), STR8("../../sketches/resources/Top512.png")); str8 imagePath2 = path_executable_relative(mem_scratch(), STR8("../../sketches/resources/Top512.png"));
mg_image image2 = mg_image_create_from_file(surface, imagePath2, false); mg_image image2 = mg_image_create_from_file(surface, imagePath2, false);
vec2 imageSize2 = mg_image_size(image2); vec2 imageSize2 = mg_image_size(image2);
// start app // start app
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
while(!mp_should_quit()) while(!mp_should_quit())
{ {
mp_pump_events(0); mp_pump_events(0);
mp_event* event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
default: default:
break; break;
} }
} }
mg_surface_prepare(surface); mg_surface_prepare(surface);
mg_set_color_rgba(0, 1, 1, 1); mg_set_color_rgba(0, 1, 1, 1);
mg_clear(); mg_clear();
mg_set_color_rgba(1, 1, 1, 1); mg_set_color_rgba(1, 1, 1, 1);
/* /*
mg_matrix_push((mg_mat2x3){0.707, -0.707, 200, mg_matrix_push((mg_mat2x3){0.707, -0.707, 200,
0.707, 0.707, 100}); 0.707, 0.707, 100});
mg_set_image(image); mg_set_image(image);
@ -99,23 +100,21 @@ int main()
mg_image_draw(image2, (mp_rect){300, 200, 300, 300}); mg_image_draw(image2, (mp_rect){300, 200, 300, 300});
*/ */
mg_image_draw(image, (mp_rect){100, 100, 300, 300}); mg_image_draw(image, (mp_rect){ 100, 100, 300, 300 });
mg_image_draw(image2, (mp_rect){300, 200, 300, 300}); mg_image_draw(image2, (mp_rect){ 300, 200, 300, 300 });
mg_render(surface, canvas);
mg_surface_present(surface);
mem_arena_clear(mem_scratch());
}
mg_render(surface, canvas); mg_image_destroy(image);
mg_surface_present(surface); mg_canvas_destroy(canvas);
mg_surface_destroy(surface);
mp_window_destroy(window);
mem_arena_clear(mem_scratch()); mp_terminate();
}
mg_image_destroy(image); return (0);
mg_canvas_destroy(canvas);
mg_surface_destroy(surface);
mp_window_destroy(window);
mp_terminate();
return(0);
} }

View File

@ -1,114 +1,115 @@
#include<stdlib.h> #include <stdio.h>
#include<stdio.h> #include <stdlib.h>
#define MG_INCLUDE_GL_API 1 #define MG_INCLUDE_GL_API 1
#include"milepost.h" #include "milepost.h"
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; mp_rect windowRect = { .x = 100, .y = 100, .w = 810, .h = 610 };
mp_window window = mp_window_create(windowRect, "test", 0); mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window); mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface //NOTE: create surface
mg_surface surface1 = mg_surface_create_for_window(window, MG_CANVAS); mg_surface surface1 = mg_surface_create_for_window(window, MG_CANVAS);
if(mg_surface_is_nil(surface1)) if(mg_surface_is_nil(surface1))
{ {
printf("Error: couldn't create surface 1\n"); printf("Error: couldn't create surface 1\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface1, 0); mg_surface_swap_interval(surface1, 0);
//* //*
mg_surface surface2 = mg_surface_create_for_window(window, MG_CANVAS); mg_surface surface2 = mg_surface_create_for_window(window, MG_CANVAS);
if(mg_surface_is_nil(surface2)) if(mg_surface_is_nil(surface2))
{ {
printf("Error: couldn't create surface 2\n"); printf("Error: couldn't create surface 2\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface2, 0); mg_surface_swap_interval(surface2, 0);
//*/ //*/
mg_canvas canvas1 = mg_canvas_create(); mg_canvas canvas1 = mg_canvas_create();
if(mg_canvas_is_nil(canvas1)) if(mg_canvas_is_nil(canvas1))
{ {
printf("Error: couldn't create canvas 1\n"); printf("Error: couldn't create canvas 1\n");
return(-1); return (-1);
} }
//* //*
mg_canvas canvas2 = mg_canvas_create(); mg_canvas canvas2 = mg_canvas_create();
if(mg_canvas_is_nil(canvas2)) if(mg_canvas_is_nil(canvas2))
{ {
printf("Error: couldn't create canvas 2\n"); printf("Error: couldn't create canvas 2\n");
return(-1); return (-1);
} }
//*/ //*/
// start app // start app
mp_window_center(window); mp_window_center(window);
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
while(!mp_should_quit()) while(!mp_should_quit())
{ {
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC); f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
mp_pump_events(0); mp_pump_events(0);
mp_event* event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
default: default:
break; break;
} }
} }
mg_surface_prepare(surface1); mg_surface_prepare(surface1);
mg_canvas_set_current(canvas1); mg_canvas_set_current(canvas1);
mg_set_color_rgba(0, 0, 0.5, 0.5); mg_set_color_rgba(0, 0, 0.5, 0.5);
mg_clear(); mg_clear();
mg_set_color_rgba(1, 0, 0, 1); mg_set_color_rgba(1, 0, 0, 1);
mg_rectangle_fill(100, 100, 300, 150); mg_rectangle_fill(100, 100, 300, 150);
mg_render(surface1, canvas1); mg_render(surface1, canvas1);
//* //*
mg_surface_prepare(surface2); mg_surface_prepare(surface2);
mg_canvas_set_current(canvas2); mg_canvas_set_current(canvas2);
mg_set_color_rgba(0, 0, 0, 0); mg_set_color_rgba(0, 0, 0, 0);
mg_clear(); mg_clear();
mg_set_color_rgba(0, 0, 1, 1); mg_set_color_rgba(0, 0, 1, 1);
mg_rectangle_fill(300, 300, 300, 200); mg_rectangle_fill(300, 300, 300, 200);
mg_render(surface2, canvas2); mg_render(surface2, canvas2);
//*/ //*/
mg_surface_present(surface1); mg_surface_present(surface1);
mg_surface_present(surface2); mg_surface_present(surface2);
mem_arena_clear(mem_scratch()); mem_arena_clear(mem_scratch());
} }
mg_canvas_destroy(canvas1); mg_canvas_destroy(canvas1);
mg_surface_destroy(surface1); mg_surface_destroy(surface1);
mg_canvas_destroy(canvas2); mg_canvas_destroy(canvas2);
mg_surface_destroy(surface2); mg_surface_destroy(surface2);
mp_window_destroy(window); mp_window_destroy(window);
mp_terminate(); mp_terminate();
return(0); return (0);
} }

View File

@ -1,237 +1,243 @@
#include<stdio.h> #include <stdio.h>
#include<stdlib.h> #include <stdlib.h>
#define LOG_DEFAULT_LEVEL LOG_LEVEL_MESSAGE #define LOG_DEFAULT_LEVEL LOG_LEVEL_MESSAGE
#define LOG_COMPILE_DEBUG #define LOG_COMPILE_DEBUG
#include"milepost.h" #include "milepost.h"
#define LOG_SUBSYSTEM "Main" #define LOG_SUBSYSTEM "Main"
static const char* TEST_STRING = static const char* TEST_STRING =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla quam enim, aliquam in placerat luctus, rutrum in quam. " "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla quam enim, aliquam in placerat luctus, rutrum in quam. "
"Cras urna elit, pellentesque ac ipsum at, lobortis scelerisque eros. Aenean et turpis nibh. Maecenas lectus augue, eleifend " "Cras urna elit, pellentesque ac ipsum at, lobortis scelerisque eros. Aenean et turpis nibh. Maecenas lectus augue, eleifend "
"nec efficitur eu, faucibus eget turpis. Suspendisse vel nulla mi. Duis imperdiet neque orci, ac ultrices orci molestie a. " "nec efficitur eu, faucibus eget turpis. Suspendisse vel nulla mi. Duis imperdiet neque orci, ac ultrices orci molestie a. "
"Etiam malesuada vulputate hendrerit. Cras ultricies diam in lectus finibus, eu laoreet diam rutrum.\n" "Etiam malesuada vulputate hendrerit. Cras ultricies diam in lectus finibus, eu laoreet diam rutrum.\n"
"\n" "\n"
"Etiam dictum orci arcu, ac fermentum leo dapibus lacinia. Integer vitae elementum ex. Vestibulum tempor nunc eu hendrerit " "Etiam dictum orci arcu, ac fermentum leo dapibus lacinia. Integer vitae elementum ex. Vestibulum tempor nunc eu hendrerit "
"ornare. Nunc pretium ligula sit amet massa pulvinar, vitae imperdiet justo bibendum. Maecenas consectetur elementum mi, sed " "ornare. Nunc pretium ligula sit amet massa pulvinar, vitae imperdiet justo bibendum. Maecenas consectetur elementum mi, sed "
"vehicula neque pulvinar sit amet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tortor erat, accumsan in laoreet " "vehicula neque pulvinar sit amet. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tortor erat, accumsan in laoreet "
"quis, placerat nec enim. Nulla facilisi. Morbi vitae nibh ligula. Suspendisse in molestie magna, eget aliquet mauris. Sed " "quis, placerat nec enim. Nulla facilisi. Morbi vitae nibh ligula. Suspendisse in molestie magna, eget aliquet mauris. Sed "
"aliquam faucibus magna.\n" "aliquam faucibus magna.\n"
"\n" "\n"
"Sed metus odio, imperdiet et consequat non, faucibus nec risus. Suspendisse facilisis sem neque, id scelerisque dui mattis sit " "Sed metus odio, imperdiet et consequat non, faucibus nec risus. Suspendisse facilisis sem neque, id scelerisque dui mattis sit "
"amet. Nullam tincidunt nisl nec dui dignissim mattis. Proin fermentum ornare ipsum. Proin eleifend, mi vitae porttitor placerat, " "amet. Nullam tincidunt nisl nec dui dignissim mattis. Proin fermentum ornare ipsum. Proin eleifend, mi vitae porttitor placerat, "
"neque magna elementum turpis, eu aliquet mi urna et leo. Pellentesque interdum est mauris, sed pellentesque risus blandit in. " "neque magna elementum turpis, eu aliquet mi urna et leo. Pellentesque interdum est mauris, sed pellentesque risus blandit in. "
"Phasellus dignissim consequat eros, at aliquam elit finibus posuere. Proin suscipit tortor leo, id vulputate odio lobortis in. " "Phasellus dignissim consequat eros, at aliquam elit finibus posuere. Proin suscipit tortor leo, id vulputate odio lobortis in. "
"Vestibulum et orci ligula. Sed scelerisque nunc non nisi aliquam, vel eleifend felis suscipit. Integer posuere sapien elit, " "Vestibulum et orci ligula. Sed scelerisque nunc non nisi aliquam, vel eleifend felis suscipit. Integer posuere sapien elit, "
"lacinia ultricies nibh sodales nec.\n" "lacinia ultricies nibh sodales nec.\n"
"\n" "\n"
"Etiam aliquam purus sit amet purus ultricies tristique. Nunc maximus nunc quis magna ornare, vel interdum urna fermentum. " "Etiam aliquam purus sit amet purus ultricies tristique. Nunc maximus nunc quis magna ornare, vel interdum urna fermentum. "
"Vestibulum cursus nisl ut nulla egestas, quis mattis elit venenatis. Praesent malesuada mi non magna aliquam fringilla eget eu " "Vestibulum cursus nisl ut nulla egestas, quis mattis elit venenatis. Praesent malesuada mi non magna aliquam fringilla eget eu "
"turpis. Integer suscipit elit vel consectetur vulputate. Integer euismod, erat eget elementum tempus, magna metus consectetur " "turpis. Integer suscipit elit vel consectetur vulputate. Integer euismod, erat eget elementum tempus, magna metus consectetur "
"elit, sed feugiat urna sapien sodales sapien. Sed sit amet varius nunc. Curabitur sodales nunc justo, ac scelerisque ipsum semper " "elit, sed feugiat urna sapien sodales sapien. Sed sit amet varius nunc. Curabitur sodales nunc justo, ac scelerisque ipsum semper "
"eget. Integer ornare, velit ut hendrerit dapibus, erat mauris commodo justo, vel semper urna justo non mauris. Proin blandit, " "eget. Integer ornare, velit ut hendrerit dapibus, erat mauris commodo justo, vel semper urna justo non mauris. Proin blandit, "
"enim ut posuere placerat, leo nibh tristique eros, ut pulvinar sapien elit eget enim. Pellentesque et mauris lectus. Curabitur " "enim ut posuere placerat, leo nibh tristique eros, ut pulvinar sapien elit eget enim. Pellentesque et mauris lectus. Curabitur "
"quis lobortis leo, sit amet egestas dui. Nullam ut sapien eu justo lacinia ultrices. Ut tincidunt, sem non luctus tempus, felis " "quis lobortis leo, sit amet egestas dui. Nullam ut sapien eu justo lacinia ultrices. Ut tincidunt, sem non luctus tempus, felis "
"purus imperdiet nisi, non ultricies libero ipsum eu augue. Mauris at luctus enim.\n" "purus imperdiet nisi, non ultricies libero ipsum eu augue. Mauris at luctus enim.\n"
"\n" "\n"
"Aliquam sed tortor a justo pulvinar dictum consectetur eu felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices " "Aliquam sed tortor a justo pulvinar dictum consectetur eu felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices "
"posuere cubilia curae; Etiam vehicula porttitor volutpat. Morbi fringilla tortor nec accumsan aliquet. Aliquam in commodo neque. " "posuere cubilia curae; Etiam vehicula porttitor volutpat. Morbi fringilla tortor nec accumsan aliquet. Aliquam in commodo neque. "
"Sed laoreet tellus in consectetur aliquet. Nullam nibh eros, feugiat sit amet aliquam non, malesuada vel urna. Ut vel egestas nunc. " "Sed laoreet tellus in consectetur aliquet. Nullam nibh eros, feugiat sit amet aliquam non, malesuada vel urna. Ut vel egestas nunc. "
"Pellentesque vitae ante quis ante pharetra pretium. Nam quis eros commodo, mattis enim sed, finibus ante. Quisque lacinia tortor ut " "Pellentesque vitae ante quis ante pharetra pretium. Nam quis eros commodo, mattis enim sed, finibus ante. Quisque lacinia tortor ut "
"odio laoreet, vel viverra libero porttitor. Vestibulum vitae dapibus ex. Phasellus varius lorem sed justo sollicitudin faucibus. " "odio laoreet, vel viverra libero porttitor. Vestibulum vitae dapibus ex. Phasellus varius lorem sed justo sollicitudin faucibus. "
"Etiam aliquam lacinia consectetur. Phasellus nulla ipsum, viverra non nulla in, rhoncus posuere nunc.\n" "Etiam aliquam lacinia consectetur. Phasellus nulla ipsum, viverra non nulla in, rhoncus posuere nunc.\n"
"\n" "\n"
"Phasellus efficitur commodo tellus, eget lobortis erat porta quis. Aenean condimentum tortor ut neque dapibus, vitae vulputate quam " "Phasellus efficitur commodo tellus, eget lobortis erat porta quis. Aenean condimentum tortor ut neque dapibus, vitae vulputate quam "
"condimentum. Aliquam elementum vitae nulla vitae tristique. Suspendisse feugiat turpis ac magna dapibus, ut blandit diam tincidunt. " "condimentum. Aliquam elementum vitae nulla vitae tristique. Suspendisse feugiat turpis ac magna dapibus, ut blandit diam tincidunt. "
"Integer id dui id enim ullamcorper dictum. Maecenas malesuada vitae ex pharetra iaculis. Curabitur eu dolor consectetur, tempus augue " "Integer id dui id enim ullamcorper dictum. Maecenas malesuada vitae ex pharetra iaculis. Curabitur eu dolor consectetur, tempus augue "
"sed, finibus est. Nulla facilisi. Vivamus sed lacinia turpis, in gravida dolor. Aenean interdum consectetur enim a malesuada. Sed turpis " "sed, finibus est. Nulla facilisi. Vivamus sed lacinia turpis, in gravida dolor. Aenean interdum consectetur enim a malesuada. Sed turpis "
"nisi, lacinia et fermentum nec, pharetra id dui. Vivamus neque ligula, iaculis sed tempor eget, vehicula blandit quam. Morbi rhoncus quam " "nisi, lacinia et fermentum nec, pharetra id dui. Vivamus neque ligula, iaculis sed tempor eget, vehicula blandit quam. Morbi rhoncus quam "
"semper magna mollis luctus. Donec eu dolor ut ante ullamcorper porta. Mauris et est tristique libero pharetra faucibus.\n" "semper magna mollis luctus. Donec eu dolor ut ante ullamcorper porta. Mauris et est tristique libero pharetra faucibus.\n"
"\n" "\n"
"Duis ut elementum sem. Praesent commodo erat nec sem ultricies sollicitudin. Suspendisse a pellentesque sapien. Nunc ac magna a dui " "Duis ut elementum sem. Praesent commodo erat nec sem ultricies sollicitudin. Suspendisse a pellentesque sapien. Nunc ac magna a dui "
"elementum luctus non a mi. Cras elementum nunc sed nunc gravida, sit amet accumsan tortor pulvinar. Etiam elit arcu, pellentesque non ex " "elementum luctus non a mi. Cras elementum nunc sed nunc gravida, sit amet accumsan tortor pulvinar. Etiam elit arcu, pellentesque non ex "
"id, vestibulum pellentesque velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque habitant morbi tristique senectus " "id, vestibulum pellentesque velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque habitant morbi tristique senectus "
"et netus et malesuada fames ac turpis egestas. Proin sit amet velit eget tellus vulputate sagittis eget non massa. Cras accumsan tempor " "et netus et malesuada fames ac turpis egestas. Proin sit amet velit eget tellus vulputate sagittis eget non massa. Cras accumsan tempor "
"tortor, quis rutrum neque placerat id. Nullam a egestas eros, eu porta nisi. Aenean rutrum, sapien quis fermentum tempus, dolor orci " "tortor, quis rutrum neque placerat id. Nullam a egestas eros, eu porta nisi. Aenean rutrum, sapien quis fermentum tempus, dolor orci "
"faucibus eros, vel luctus justo leo vitae ante. Curabitur aliquam condimentum ipsum sit amet ultrices. Nullam ac velit semper, dapibus urna " "faucibus eros, vel luctus justo leo vitae ante. Curabitur aliquam condimentum ipsum sit amet ultrices. Nullam ac velit semper, dapibus urna "
"sit amet, malesuada enim. Mauris ultricies nibh orci."; "sit amet, malesuada enim. Mauris ultricies nibh orci.";
mg_font create_font(const char* path) mg_font create_font(const char* path)
{ {
//NOTE(martin): create font //NOTE(martin): create font
str8 fontPath = path_executable_relative(mem_scratch(), STR8(path)); str8 fontPath = path_executable_relative(mem_scratch(), STR8(path));
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath); char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath);
FILE* fontFile = fopen(fontPathCString, "r"); FILE* fontFile = fopen(fontPathCString, "r");
if(!fontFile) if(!fontFile)
{ {
log_error("Could not load font file '%s'\n", fontPathCString); log_error("Could not load font file '%s'\n", fontPathCString);
return(mg_font_nil()); return (mg_font_nil());
} }
unsigned char* fontData = 0; unsigned char* fontData = 0;
fseek(fontFile, 0, SEEK_END); fseek(fontFile, 0, SEEK_END);
u32 fontDataSize = ftell(fontFile); u32 fontDataSize = ftell(fontFile);
rewind(fontFile); rewind(fontFile);
fontData = (unsigned char*)malloc(fontDataSize); fontData = (unsigned char*)malloc(fontDataSize);
fread(fontData, 1, fontDataSize, fontFile); fread(fontData, 1, fontDataSize, fontFile);
fclose(fontFile); fclose(fontFile);
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN, unicode_range ranges[5] = { UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT, UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
UNICODE_RANGE_LATIN_EXTENDED_A, UNICODE_RANGE_LATIN_EXTENDED_A,
UNICODE_RANGE_LATIN_EXTENDED_B, UNICODE_RANGE_LATIN_EXTENDED_B,
UNICODE_RANGE_SPECIALS}; UNICODE_RANGE_SPECIALS };
mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges); mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
free(fontData); free(fontData);
return(font); return (font);
} }
enum { FONT_COUNT = 3 }; enum
{
FONT_COUNT = 3
};
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); mp_clock_init();
mp_rect rect = {.x = 100, .y = 100, .w = 980, .h = 600}; mp_rect rect = { .x = 100, .y = 100, .w = 980, .h = 600 };
mp_window window = mp_window_create(rect, "test", 0); mp_window window = mp_window_create(rect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window); mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface, canvas and font //NOTE: create surface, canvas and font
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
if(mg_surface_is_nil(surface)) if(mg_surface_is_nil(surface))
{ {
log_error("couldn't create surface\n"); log_error("couldn't create surface\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface, 0); mg_surface_swap_interval(surface, 0);
mg_canvas canvas = mg_canvas_create(); mg_canvas canvas = mg_canvas_create();
int fontIndex = 0; int fontIndex = 0;
mg_font fonts[FONT_COUNT] = {create_font("../../resources/OpenSansLatinSubset.ttf"), mg_font fonts[FONT_COUNT] = { create_font("../../resources/OpenSansLatinSubset.ttf"),
create_font("../../sketches/resources/CMUSerif-Roman.ttf"), create_font("../../sketches/resources/CMUSerif-Roman.ttf"),
create_font("../../sketches/resources/Courier.ttf")}; create_font("../../sketches/resources/Courier.ttf") };
mg_font_extents extents[FONT_COUNT]; mg_font_extents extents[FONT_COUNT];
f32 fontScales[FONT_COUNT]; f32 fontScales[FONT_COUNT];
f32 lineHeights[FONT_COUNT]; f32 lineHeights[FONT_COUNT];
for(int i=0; i<FONT_COUNT; i++) for(int i = 0; i < FONT_COUNT; i++)
{ {
extents[i] = mg_font_get_extents(fonts[i]); extents[i] = mg_font_get_extents(fonts[i]);
fontScales[i] = mg_font_get_scale_for_em_pixels(fonts[i], 14); fontScales[i] = mg_font_get_scale_for_em_pixels(fonts[i], 14);
lineHeights[i] = fontScales[i]*(extents[i].ascent + extents[i].descent + extents[i].leading); lineHeights[i] = fontScales[i] * (extents[i].ascent + extents[i].descent + extents[i].leading);
} }
int codePointCount = utf8_codepoint_count_for_string(STR8((char*)TEST_STRING)); int codePointCount = utf8_codepoint_count_for_string(STR8((char*)TEST_STRING));
u32* codePoints = malloc_array(utf32, codePointCount); u32* codePoints = malloc_array(utf32, codePointCount);
utf8_to_codepoints(codePointCount, codePoints, STR8((char*)TEST_STRING)); utf8_to_codepoints(codePointCount, codePoints, STR8((char*)TEST_STRING));
u32 glyphCount = 0; u32 glyphCount = 0;
for(int i=0; i<codePointCount; i++) for(int i = 0; i < codePointCount; i++)
{ {
if(codePoints[i] != ' ' && codePoints[i] != '\n') if(codePoints[i] != ' ' && codePoints[i] != '\n')
{ {
glyphCount++; glyphCount++;
} }
} }
// start app // start app
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
f64 frameTime = 0; f64 frameTime = 0;
bool tracked = false; bool tracked = false;
vec2 trackPoint = {0}; vec2 trackPoint = { 0 };
f32 zoom = 1; f32 zoom = 1;
f32 startX = 10; f32 startX = 10;
f32 startY = 10 + lineHeights[fontIndex]; f32 startY = 10 + lineHeights[fontIndex];
mp_input_state inputState = {0}; mp_input_state inputState = { 0 };
while(!mp_should_quit()) while(!mp_should_quit())
{ {
f64 startFrameTime = mp_get_time(MP_CLOCK_MONOTONIC); f64 startFrameTime = mp_get_time(MP_CLOCK_MONOTONIC);
mp_pump_events(0); mp_pump_events(0);
mp_event* event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
mp_input_process_event(&inputState, event); mp_input_process_event(&inputState, event);
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
case MP_EVENT_MOUSE_BUTTON: case MP_EVENT_MOUSE_BUTTON:
{ {
if(event->key.code == MP_MOUSE_LEFT) if(event->key.code == MP_MOUSE_LEFT)
{ {
if(event->key.action == MP_KEY_PRESS) if(event->key.action == MP_KEY_PRESS)
{ {
tracked = true; tracked = true;
vec2 mousePos = mp_mouse_position(&inputState); vec2 mousePos = mp_mouse_position(&inputState);
trackPoint.x = mousePos.x/zoom - startX; trackPoint.x = mousePos.x / zoom - startX;
trackPoint.y = mousePos.y/zoom - startY; trackPoint.y = mousePos.y / zoom - startY;
} }
else else
{ {
tracked = false; tracked = false;
} }
} }
} break; }
break;
case MP_EVENT_MOUSE_WHEEL: case MP_EVENT_MOUSE_WHEEL:
{ {
vec2 mousePos = mp_mouse_position(&inputState); vec2 mousePos = mp_mouse_position(&inputState);
f32 trackX = mousePos.x/zoom - startX; f32 trackX = mousePos.x / zoom - startX;
f32 trackY = mousePos.y/zoom - startY; f32 trackY = mousePos.y / zoom - startY;
zoom *= 1 + event->mouse.deltaY * 0.01; zoom *= 1 + event->mouse.deltaY * 0.01;
zoom = Clamp(zoom, 0.2, 10); zoom = Clamp(zoom, 0.2, 10);
startX = mousePos.x/zoom - trackX; startX = mousePos.x / zoom - trackX;
startY = mousePos.y/zoom - trackY; startY = mousePos.y / zoom - trackY;
} break; }
break;
case MP_EVENT_KEYBOARD_KEY: case MP_EVENT_KEYBOARD_KEY:
{ {
if(event->key.code == MP_KEY_SPACE && event->key.action == MP_KEY_PRESS) if(event->key.code == MP_KEY_SPACE && event->key.action == MP_KEY_PRESS)
{ {
fontIndex = (fontIndex+1)%FONT_COUNT; fontIndex = (fontIndex + 1) % FONT_COUNT;
} }
} break; }
break;
default: default:
break; break;
} }
} }
if(tracked) if(tracked)
{ {
vec2 mousePos = mp_mouse_position(&inputState); vec2 mousePos = mp_mouse_position(&inputState);
startX = mousePos.x/zoom - trackPoint.x; startX = mousePos.x / zoom - trackPoint.x;
startY = mousePos.y/zoom - trackPoint.y; startY = mousePos.y / zoom - trackPoint.y;
} }
f32 textX = startX; f32 textX = startX;
f32 textY = startY; f32 textY = startY;
/* /*
mg_set_color_rgba(1, 1, 1, 1); mg_set_color_rgba(1, 1, 1, 1);
mg_clear(); mg_clear();
mg_set_color_rgba(1, 0, 0, 1); mg_set_color_rgba(1, 0, 0, 1);
@ -241,92 +247,90 @@ int main()
} }
*/ */
mg_matrix_push((mg_mat2x3){zoom, 0, 0, mg_matrix_push((mg_mat2x3){ zoom, 0, 0,
0, zoom, 0}); 0, zoom, 0 });
mg_set_color_rgba(1, 1, 1, 1); mg_set_color_rgba(1, 1, 1, 1);
mg_clear(); mg_clear();
mg_set_font(fonts[fontIndex]); mg_set_font(fonts[fontIndex]);
mg_set_font_size(14); mg_set_font_size(14);
mg_set_color_rgba(0, 0, 0, 1); mg_set_color_rgba(0, 0, 0, 1);
mg_move_to(textX, textY); mg_move_to(textX, textY);
int startIndex = 0; int startIndex = 0;
while(startIndex < codePointCount) while(startIndex < codePointCount)
{ {
bool lineBreak = false; bool lineBreak = false;
int subIndex = 0; int subIndex = 0;
for(; (startIndex+subIndex) < codePointCount && subIndex < 120; subIndex++) for(; (startIndex + subIndex) < codePointCount && subIndex < 120; subIndex++)
{ {
if(codePoints[startIndex + subIndex] == '\n') if(codePoints[startIndex + subIndex] == '\n')
{ {
break; break;
} }
} }
u32 glyphs[512]; u32 glyphs[512];
mg_font_get_glyph_indices(fonts[fontIndex], (str32){subIndex, codePoints+startIndex}, (str32){512, glyphs}); mg_font_get_glyph_indices(fonts[fontIndex], (str32){ subIndex, codePoints + startIndex }, (str32){ 512, glyphs });
mg_glyph_outlines((str32){subIndex, glyphs}); mg_glyph_outlines((str32){ subIndex, glyphs });
mg_fill(); mg_fill();
textY += lineHeights[fontIndex]; textY += lineHeights[fontIndex];
mg_move_to(textX, textY); mg_move_to(textX, textY);
startIndex++; startIndex++;
startIndex += subIndex; startIndex += subIndex;
} }
mg_matrix_pop(); mg_matrix_pop();
mg_set_color_rgba(0, 0, 1, 1); mg_set_color_rgba(0, 0, 1, 1);
mg_set_font(fonts[fontIndex]); mg_set_font(fonts[fontIndex]);
mg_set_font_size(14); mg_set_font_size(14);
mg_move_to(10, contentRect.h - 10 - lineHeights[fontIndex]); mg_move_to(10, contentRect.h - 10 - lineHeights[fontIndex]);
str8 text = str8_pushf(mem_scratch(), str8 text = str8_pushf(mem_scratch(),
"Test program: %i glyphs, frame time = %fs, fps = %f", "Test program: %i glyphs, frame time = %fs, fps = %f",
glyphCount, glyphCount,
frameTime, frameTime,
1./frameTime); 1. / frameTime);
mg_text_outlines(text); mg_text_outlines(text);
mg_fill(); mg_fill();
f64 startFlushTime = mp_get_time(MP_CLOCK_MONOTONIC);
f64 startFlushTime = mp_get_time(MP_CLOCK_MONOTONIC); mg_surface_prepare(surface);
mg_render(surface, canvas);
mg_surface_prepare(surface); f64 startPresentTime = mp_get_time(MP_CLOCK_MONOTONIC);
mg_render(surface, canvas); mg_surface_present(surface);
f64 startPresentTime = mp_get_time(MP_CLOCK_MONOTONIC); f64 endFrameTime = mp_get_time(MP_CLOCK_MONOTONIC);
mg_surface_present(surface);
f64 endFrameTime = mp_get_time(MP_CLOCK_MONOTONIC); frameTime = (endFrameTime - startFrameTime);
frameTime = (endFrameTime - startFrameTime); printf("frame time: %.2fms (%.2fFPS), draw = %f.2ms, flush = %.2fms, present = %.2fms\n",
frameTime * 1000,
1. / frameTime,
(startFlushTime - startFrameTime) * 1000,
(startPresentTime - startFlushTime) * 1000,
(endFrameTime - startPresentTime) * 1000);
printf("frame time: %.2fms (%.2fFPS), draw = %f.2ms, flush = %.2fms, present = %.2fms\n", mp_input_next_frame(&inputState);
frameTime*1000, mem_arena_clear(mem_scratch());
1./frameTime, }
(startFlushTime - startFrameTime)*1000,
(startPresentTime - startFlushTime)*1000,
(endFrameTime - startPresentTime)*1000);
mp_input_next_frame(&inputState); for(int i = 0; i < FONT_COUNT; i++)
mem_arena_clear(mem_scratch()); {
} mg_font_destroy(fonts[i]);
}
mg_canvas_destroy(canvas);
mg_surface_destroy(surface);
mp_window_destroy(window);
mp_terminate();
return (0);
for(int i=0; i<FONT_COUNT; i++)
{
mg_font_destroy(fonts[i]);
}
mg_canvas_destroy(canvas);
mg_surface_destroy(surface);
mp_window_destroy(window);
mp_terminate();
return(0);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,136 +6,138 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdio.h> #include <errno.h>
#include<stdlib.h> #include <stdio.h>
#include<string.h> #include <stdlib.h>
#include<errno.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#include"milepost.h" #include "milepost.h"
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; mp_rect windowRect = { .x = 100, .y = 100, .w = 810, .h = 610 };
mp_window window = mp_window_create(windowRect, "test", 0); mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window); mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
mg_surface_swap_interval(surface, 1); mg_surface_swap_interval(surface, 1);
if(mg_surface_is_nil(surface)) if(mg_surface_is_nil(surface))
{ {
printf("Error: couldn't create surface\n"); printf("Error: couldn't create surface\n");
return(-1); return (-1);
} }
//TODO: create canvas //TODO: create canvas
mg_canvas canvas = mg_canvas_create(); mg_canvas canvas = mg_canvas_create();
if(mg_canvas_is_nil(canvas)) if(mg_canvas_is_nil(canvas))
{ {
printf("Error: couldn't create canvas\n"); printf("Error: couldn't create canvas\n");
return(-1); return (-1);
} }
// start app // start app
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
f64 frameTime = 0; f64 frameTime = 0;
f32 x = 0, y = 0; f32 x = 0, y = 0;
while(!mp_should_quit()) while(!mp_should_quit())
{ {
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC); f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
mp_pump_events(0); mp_pump_events(0);
mp_event* event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
case MP_EVENT_KEYBOARD_KEY: case MP_EVENT_KEYBOARD_KEY:
{ {
if(event->key.action == MP_KEY_PRESS) if(event->key.action == MP_KEY_PRESS)
{ {
if(event->key.code == MP_KEY_LEFT) if(event->key.code == MP_KEY_LEFT)
{ {
x-=1; x -= 1;
} }
if(event->key.code == MP_KEY_RIGHT) if(event->key.code == MP_KEY_RIGHT)
{ {
x+=1; x += 1;
} }
if(event->key.code == MP_KEY_UP) if(event->key.code == MP_KEY_UP)
{ {
y-=1; y -= 1;
} }
if(event->key.code == MP_KEY_DOWN) if(event->key.code == MP_KEY_DOWN)
{ {
y+=1; y += 1;
} }
} }
} break; }
break;
default: default:
break; break;
} }
} }
mg_surface_prepare(surface); mg_surface_prepare(surface);
// background // background
mg_set_color_rgba(0, 1, 1, 1); mg_set_color_rgba(0, 1, 1, 1);
mg_clear(); mg_clear();
mg_move_to(100, 100); mg_move_to(100, 100);
mg_line_to(150, 150); mg_line_to(150, 150);
mg_line_to(100, 200); mg_line_to(100, 200);
mg_line_to(50, 150); mg_line_to(50, 150);
mg_close_path(); mg_close_path();
mg_set_color_rgba(1, 0, 0, 1); mg_set_color_rgba(1, 0, 0, 1);
mg_fill(); mg_fill();
mg_move_to(200, 100); mg_move_to(200, 100);
mg_line_to(410, 100); mg_line_to(410, 100);
mg_line_to(410, 200); mg_line_to(410, 200);
mg_line_to(200, 200); mg_line_to(200, 200);
mg_close_path(); mg_close_path();
mg_set_color_rgba(0, 1, 0, 1); mg_set_color_rgba(0, 1, 0, 1);
mg_fill(); mg_fill();
mg_set_color_rgba(0, 1, 1, 0.5); mg_set_color_rgba(0, 1, 1, 0.5);
mg_rectangle_fill(120, 120, 200, 200); mg_rectangle_fill(120, 120, 200, 200);
mg_set_color_rgba(1, 0, 0.5, 1); mg_set_color_rgba(1, 0, 0.5, 1);
mg_rectangle_fill(700, 500, 200, 200); mg_rectangle_fill(700, 500, 200, 200);
mg_move_to(300, 300); mg_move_to(300, 300);
mg_quadratic_to(400, 500, 500, 300); mg_quadratic_to(400, 500, 500, 300);
mg_close_path(); mg_close_path();
mg_set_color_rgba(0, 0, 1, 1); mg_set_color_rgba(0, 0, 1, 1);
mg_fill(); mg_fill();
mg_move_to(200, 450); mg_move_to(200, 450);
mg_cubic_to(200, 250, 400, 550, 400, 450); mg_cubic_to(200, 250, 400, 550, 400, 450);
mg_close_path(); mg_close_path();
mg_set_color_rgba(1, 0.5, 0, 1); mg_set_color_rgba(1, 0.5, 0, 1);
mg_fill(); mg_fill();
/* /*
mg_set_joint(MG_JOINT_NONE); mg_set_joint(MG_JOINT_NONE);
mg_set_max_joint_excursion(20); mg_set_max_joint_excursion(20);
@ -172,22 +174,22 @@ int main()
mg_set_color_rgba(0, 0, 1, 1); mg_set_color_rgba(0, 0, 1, 1);
mg_fill(); mg_fill();
*/ */
printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n", printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
frameTime, frameTime,
1./frameTime); 1. / frameTime);
mg_render(surface, canvas); mg_render(surface, canvas);
mg_surface_present(surface); mg_surface_present(surface);
mem_arena_clear(mem_scratch()); mem_arena_clear(mem_scratch());
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime; frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
} }
mg_canvas_destroy(canvas); mg_canvas_destroy(canvas);
mg_surface_destroy(surface); mg_surface_destroy(surface);
mp_window_destroy(window); mp_window_destroy(window);
mp_terminate(); mp_terminate();
return(0); return (0);
} }

View File

@ -1,98 +1,99 @@
#include<stdlib.h> #include <stdio.h>
#include<stdio.h> #include <stdlib.h>
#define MG_INCLUDE_GL_API 1 #define MG_INCLUDE_GL_API 1
#include"milepost.h" #include "milepost.h"
mg_surface surface = {0}; mg_surface surface = { 0 };
mg_canvas canvas = {0}; mg_canvas canvas = { 0 };
i32 render_thread(void* user) i32 render_thread(void* user)
{ {
while(!mp_should_quit()) while(!mp_should_quit())
{ {
mp_event* event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
default: default:
break; break;
} }
} }
mg_surface_prepare(surface); mg_surface_prepare(surface);
mg_canvas_set_current(canvas); mg_canvas_set_current(canvas);
mg_set_color_rgba(0, 0, 0.5, 0.5); mg_set_color_rgba(0, 0, 0.5, 0.5);
mg_clear(); mg_clear();
mg_set_color_rgba(1, 0, 0, 1); mg_set_color_rgba(1, 0, 0, 1);
mg_rectangle_fill(100, 100, 300, 150); mg_rectangle_fill(100, 100, 300, 150);
mg_render(surface, canvas); mg_render(surface, canvas);
mg_surface_present(surface); mg_surface_present(surface);
mem_arena_clear(mem_scratch()); mem_arena_clear(mem_scratch());
} }
return(0); return (0);
} }
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; mp_rect windowRect = { .x = 100, .y = 100, .w = 810, .h = 610 };
mp_window window = mp_window_create(windowRect, "test", 0); mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window); mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface //NOTE: create surface
surface = mg_surface_create_for_window(window, MG_CANVAS); surface = mg_surface_create_for_window(window, MG_CANVAS);
if(mg_surface_is_nil(surface)) if(mg_surface_is_nil(surface))
{ {
printf("Error: couldn't create surface 1\n"); printf("Error: couldn't create surface 1\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface, 0); mg_surface_swap_interval(surface, 0);
canvas = mg_canvas_create(); canvas = mg_canvas_create();
if(mg_canvas_is_nil(canvas)) if(mg_canvas_is_nil(canvas))
{ {
printf("Error: couldn't create canvas 1\n"); printf("Error: couldn't create canvas 1\n");
return(-1); return (-1);
} }
mg_surface dummy = mg_surface_create_for_window(window, MG_CANVAS); mg_surface dummy = mg_surface_create_for_window(window, MG_CANVAS);
// start app // start app
mp_window_center(window); mp_window_center(window);
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
mp_thread* renderThread = mp_thread_create(render_thread, NULL); mp_thread* renderThread = mp_thread_create(render_thread, NULL);
while(!mp_should_quit()) while(!mp_should_quit())
{ {
mp_pump_events(0); mp_pump_events(0);
} }
mp_thread_join(renderThread, NULL); mp_thread_join(renderThread, NULL);
mg_canvas_destroy(canvas); mg_canvas_destroy(canvas);
mg_surface_destroy(surface); mg_surface_destroy(surface);
mp_window_destroy(window); mp_window_destroy(window);
mp_terminate(); mp_terminate();
return(0); return (0);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,116 +6,126 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include <stdio.h>
#include<stdio.h> #include <stdlib.h>
#include<string.h> #include <string.h>
#include"milepost.h" #include "milepost.h"
int main() int main()
{ {
mp_init(); mp_init();
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mp_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 };
mp_window window = mp_window_create(rect, "test", 0); mp_window window = mp_window_create(rect, "test", 0);
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
mp_window_center(window); mp_window_center(window);
while(!mp_should_quit()) while(!mp_should_quit())
{ {
mp_pump_events(0); mp_pump_events(0);
mp_event *event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
case MP_EVENT_WINDOW_RESIZE: case MP_EVENT_WINDOW_RESIZE:
{ {
printf("resized, frame = {%f, %f, %f, %f}, content = {%f, %f, %f, %f}\n", printf("resized, frame = {%f, %f, %f, %f}, content = {%f, %f, %f, %f}\n",
event->move.frame.x, event->move.frame.x,
event->move.frame.y, event->move.frame.y,
event->move.frame.w, event->move.frame.w,
event->move.frame.h, event->move.frame.h,
event->move.content.x, event->move.content.x,
event->move.content.y, event->move.content.y,
event->move.content.w, event->move.content.w,
event->move.content.h); event->move.content.h);
} break; }
break;
case MP_EVENT_WINDOW_MOVE: case MP_EVENT_WINDOW_MOVE:
{ {
printf("moved, frame = {%f, %f, %f, %f}, content = {%f, %f, %f, %f}\n", printf("moved, frame = {%f, %f, %f, %f}, content = {%f, %f, %f, %f}\n",
event->move.frame.x, event->move.frame.x,
event->move.frame.y, event->move.frame.y,
event->move.frame.w, event->move.frame.w,
event->move.frame.h, event->move.frame.h,
event->move.content.x, event->move.content.x,
event->move.content.y, event->move.content.y,
event->move.content.w, event->move.content.w,
event->move.content.h); event->move.content.h);
} break; }
break;
case MP_EVENT_MOUSE_MOVE: case MP_EVENT_MOUSE_MOVE:
{ {
printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n", printf("mouse moved, pos = {%f, %f}, delta = {%f, %f}\n",
event->mouse.x, event->mouse.x,
event->mouse.y, event->mouse.y,
event->mouse.deltaX, event->mouse.deltaX,
event->mouse.deltaY); event->mouse.deltaY);
} break; }
break;
case MP_EVENT_MOUSE_WHEEL: case MP_EVENT_MOUSE_WHEEL:
{ {
printf("mouse wheel, delta = {%f, %f}\n", printf("mouse wheel, delta = {%f, %f}\n",
event->mouse.deltaX, event->mouse.deltaX,
event->mouse.deltaY); event->mouse.deltaY);
} break; }
break;
case MP_EVENT_MOUSE_ENTER: case MP_EVENT_MOUSE_ENTER:
{ {
printf("mouse enter\n"); printf("mouse enter\n");
} break; }
break;
case MP_EVENT_MOUSE_LEAVE: case MP_EVENT_MOUSE_LEAVE:
{ {
printf("mouse leave\n"); printf("mouse leave\n");
} break; }
break;
case MP_EVENT_MOUSE_BUTTON: case MP_EVENT_MOUSE_BUTTON:
{ {
printf("mouse button %i: %i\n", printf("mouse button %i: %i\n",
event->key.code, event->key.code,
event->key.action == MP_KEY_PRESS ? 1 : 0); event->key.action == MP_KEY_PRESS ? 1 : 0);
} break; }
break;
case MP_EVENT_KEYBOARD_KEY: case MP_EVENT_KEYBOARD_KEY:
{ {
printf("key %i: %s\n", printf("key %i: %s\n",
event->key.code, event->key.code,
event->key.action == MP_KEY_PRESS ? "press" : (event->key.action == MP_KEY_RELEASE ? "release" : "repeat")); event->key.action == MP_KEY_PRESS ? "press" : (event->key.action == MP_KEY_RELEASE ? "release" : "repeat"));
} break; }
break;
case MP_EVENT_KEYBOARD_CHAR: case MP_EVENT_KEYBOARD_CHAR:
{ {
printf("entered char %s\n", event->character.sequence); printf("entered char %s\n", event->character.sequence);
} break; }
break;
default: default:
break; break;
} }
} }
mem_arena_clear(mem_scratch()); mem_arena_clear(mem_scratch());
} }
mp_terminate(); mp_terminate();
return(0); return (0);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,221 +6,222 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdio.h> #include <errno.h>
#include<stdlib.h> #include <stdio.h>
#include<string.h> #include <stdlib.h>
#include<errno.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#define MG_INCLUDE_GL_API #define MG_INCLUDE_GL_API
#include"milepost.h" #include "milepost.h"
unsigned int program; unsigned int program;
const char* vshaderSource = const char* vshaderSource =
"#version 430\n" "#version 430\n"
"attribute vec4 vPosition;\n" "attribute vec4 vPosition;\n"
"uniform mat4 transform;\n" "uniform mat4 transform;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Position = transform*vPosition;\n" " gl_Position = transform*vPosition;\n"
"}\n"; "}\n";
const char* fshaderSource = const char* fshaderSource =
"#version 430\n" "#version 430\n"
"precision mediump float;\n" "precision mediump float;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n"; "}\n";
void compile_shader(GLuint shader, const char* source) void compile_shader(GLuint shader, const char* source)
{ {
glShaderSource(shader, 1, &source, 0); glShaderSource(shader, 1, &source, 0);
glCompileShader(shader); glCompileShader(shader);
int err = glGetError(); int err = glGetError();
if(err) if(err)
{ {
printf("gl error: %i\n", err); printf("gl error: %i\n", err);
} }
int status = 0; int status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(!status) if(!status)
{ {
char buffer[256]; char buffer[256];
int size = 0; int size = 0;
glGetShaderInfoLog(shader, 256, &size, buffer); glGetShaderInfoLog(shader, 256, &size, buffer);
printf("shader error: %.*s\n", size, buffer); printf("shader error: %.*s\n", size, buffer);
} }
} }
GLfloat vertices[] = { GLfloat vertices[] = {
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0}; -0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0
};
typedef struct app_data typedef struct app_data
{ {
mp_window window; mp_window window;
mg_surface surface; mg_surface surface;
mg_canvas canvas; mg_canvas canvas;
mg_font font; mg_font font;
GLuint vertexBuffer; GLuint vertexBuffer;
} app_data; } app_data;
void process_event(app_data* app, mp_event event) void process_event(app_data* app, mp_event event)
{ {
switch(event.type) switch(event.type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
case MP_EVENT_WINDOW_RESIZE: case MP_EVENT_WINDOW_RESIZE:
{ {
log_info("resizing window!\n"); log_info("resizing window!\n");
} break; }
break;
default: default:
break; break;
} }
} }
void update_and_render(app_data* app) void update_and_render(app_data* app)
{ {
mg_surface_prepare(app->surface); mg_surface_prepare(app->surface);
glClearColor(0.3, 0.3, 1, 1); glClearColor(0.3, 0.3, 1, 1);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
static float alpha = 0; static float alpha = 0;
//f32 aspect = frameSize.x/frameSize.y; //f32 aspect = frameSize.x/frameSize.y;
f32 aspect = 800/(f32)600; f32 aspect = 800 / (f32)600;
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0, GLfloat matrix[] = { cosf(alpha) / aspect, sinf(alpha), 0, 0,
-sinf(alpha)/aspect, cosf(alpha), 0, 0, -sinf(alpha) / aspect, cosf(alpha), 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1}; 0, 0, 0, 1 };
alpha += 2*M_PI/120; alpha += 2 * M_PI / 120;
glUniformMatrix4fv(0, 1, false, matrix); glUniformMatrix4fv(0, 1, false, matrix);
glBindBuffer(GL_ARRAY_BUFFER, app->vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, app->vertexBuffer); glDrawArrays(GL_TRIANGLES, 0, 3);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3); mg_surface_present(app->surface);
mg_surface_present(app->surface); mem_arena_clear(mem_scratch());
mem_arena_clear(mem_scratch());
} }
i32 render(void* user) i32 render(void* user)
{ {
app_data* app = (app_data*)user; app_data* app = (app_data*)user;
//NOTE: init shader and gl state //NOTE: init shader and gl state
mg_surface_prepare(app->surface); mg_surface_prepare(app->surface);
GLuint vao; GLuint vao;
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
glBindVertexArray(vao); glBindVertexArray(vao);
glGenBuffers(1, &app->vertexBuffer); glGenBuffers(1, &app->vertexBuffer);
GLfloat vertices[] = { GLfloat vertices[] = {
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0}; -0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0
};
glBindBuffer(GL_ARRAY_BUFFER, app->vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, app->vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram();
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER); compile_shader(vshader, vshaderSource);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); compile_shader(fshader, fshaderSource);
program = glCreateProgram();
compile_shader(vshader, vshaderSource); glAttachShader(program, vshader);
compile_shader(fshader, fshaderSource); glAttachShader(program, fshader);
glLinkProgram(program);
glAttachShader(program, vshader); int status = 0;
glAttachShader(program, fshader); glGetProgramiv(program, GL_LINK_STATUS, &status);
glLinkProgram(program); if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
int status = 0; glUseProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
glUseProgram(program); while(!mp_should_quit())
{
mp_event* event = 0;
while(!mp_should_quit()) while((event = mp_next_event(mem_scratch())) != 0)
{ {
mp_event* event = 0; process_event(app, *event);
}
update_and_render(app);
mem_arena_clear(mem_scratch());
}
while((event = mp_next_event(mem_scratch())) != 0) return (0);
{
process_event(app, *event);
}
update_and_render(app);
mem_arena_clear(mem_scratch());
}
return(0);
} }
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; mp_rect windowRect = { .x = 100, .y = 100, .w = 810, .h = 610 };
mp_window window = mp_window_create(windowRect, "test", 0); mp_window window = mp_window_create(windowRect, "test", 0);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_GL); mg_surface surface = mg_surface_create_for_window(window, MG_GL);
if(mg_surface_is_nil(surface)) if(mg_surface_is_nil(surface))
{ {
printf("Error: couldn't create surface\n"); printf("Error: couldn't create surface\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface, 1); mg_surface_swap_interval(surface, 1);
mg_surface_deselect(); mg_surface_deselect();
// start app
mp_window_bring_to_front(window);
mp_window_focus(window);
// start app //TODO: start thread
mp_window_bring_to_front(window); app_data app = { .window = window,
mp_window_focus(window); .surface = surface };
//TODO: start thread mp_thread* renderThread = mp_thread_create(render, &app);
app_data app = {.window = window,
.surface = surface};
mp_thread* renderThread = mp_thread_create(render, &app); while(!mp_should_quit())
{
mp_pump_events(0);
}
while(!mp_should_quit()) mp_thread_join(renderThread, NULL);
{
mp_pump_events(0);
}
mp_thread_join(renderThread, NULL); mg_surface_destroy(surface);
mp_window_destroy(window);
mg_surface_destroy(surface); mp_terminate();
mp_window_destroy(window);
mp_terminate(); return (0);
return(0);
} }

View File

@ -1,291 +1,291 @@
#include<stdlib.h> #include <stdlib.h>
#include<string.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#include<stdlib.h> #include <stdio.h>
#include<stdio.h> #include <stdlib.h>
#define MG_INCLUDE_GL_API 1 #define MG_INCLUDE_GL_API 1
#include"milepost.h" #include "milepost.h"
#define LOG_SUBSYSTEM "Main" #define LOG_SUBSYSTEM "Main"
#ifdef OS_WIN64 #ifdef OS_WIN64
#include<process.h> #include <process.h>
#include<io.h> #include <io.h>
#include<fcntl.h> #include <fcntl.h>
#define dup2 _dup2 #define dup2 _dup2
#define pipe(fds) _pipe(fds, 256, O_BINARY) #define pipe(fds) _pipe(fds, 256, O_BINARY)
#define read _read #define read _read
#define write _write #define write _write
#define process_id HANDLE #define process_id HANDLE
process_id spawn_child(char* program, char** argv) process_id spawn_child(char* program, char** argv)
{ {
return((process_id)_spawnv(P_NOWAIT, program, argv)); return ((process_id)_spawnv(P_NOWAIT, program, argv));
} }
void terminate_child(process_id child) void terminate_child(process_id child)
{ {
TerminateProcess(child, 0); TerminateProcess(child, 0);
} }
#elif OS_MACOS #elif OS_MACOS
#include<unistd.h> #include <unistd.h>
#include<signal.h> #include <signal.h>
#define process_id pid_t #define process_id pid_t
process_id spawn_child(char* program, char** argv) process_id spawn_child(char* program, char** argv)
{ {
pid_t pid = fork(); pid_t pid = fork();
if(!pid) if(!pid)
{ {
char* envp[] = {0}; char* envp[] = { 0 };
execve(program, argv, envp); execve(program, argv, envp);
assert(0); assert(0);
} }
return(pid); return (pid);
} }
void terminate_child(process_id child) void terminate_child(process_id child)
{ {
kill(child, SIGTERM); kill(child, SIGTERM);
} }
#endif #endif
unsigned int program; unsigned int program;
const char* vshaderSource = const char* vshaderSource =
//"#version 320 es\n" //"#version 320 es\n"
"attribute vec4 vPosition;\n" "attribute vec4 vPosition;\n"
"uniform mat4 transform;\n" "uniform mat4 transform;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Position = transform*vPosition;\n" " gl_Position = transform*vPosition;\n"
"}\n"; "}\n";
const char* fshaderSource = const char* fshaderSource =
//"#version 320 es\n" //"#version 320 es\n"
"precision mediump float;\n" "precision mediump float;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n"; "}\n";
void compile_shader(GLuint shader, const char* source) void compile_shader(GLuint shader, const char* source)
{ {
glShaderSource(shader, 1, &source, 0); glShaderSource(shader, 1, &source, 0);
glCompileShader(shader); glCompileShader(shader);
int err = glGetError(); int err = glGetError();
if(err) if(err)
{ {
printf("gl error: %i\n", err); printf("gl error: %i\n", err);
} }
int status = 0; int status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(!status) if(!status)
{ {
char buffer[256]; char buffer[256];
int size = 0; int size = 0;
glGetShaderInfoLog(shader, 256, &size, buffer); glGetShaderInfoLog(shader, 256, &size, buffer);
printf("shader error: %.*s\n", size, buffer); printf("shader error: %.*s\n", size, buffer);
} }
} }
int child_main(int writeFd) int child_main(int writeFd)
{ {
mp_init(); mp_init();
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mp_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 };
mp_window window = mp_window_create(rect, "test", 0); mp_window window = mp_window_create(rect, "test", 0);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_remote(800, 600, MG_BACKEND_GLES); mg_surface surface = mg_surface_create_remote(800, 600, MG_BACKEND_GLES);
mg_surface_id connectionID = mg_surface_remote_id(surface); mg_surface_id connectionID = mg_surface_remote_id(surface);
mg_surface_prepare(surface); mg_surface_prepare(surface);
//NOTE: init shader and gl state //NOTE: init shader and gl state
mg_surface_prepare(surface); mg_surface_prepare(surface);
GLuint vao; GLuint vao;
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
glBindVertexArray(vao); glBindVertexArray(vao);
GLuint vertexBuffer; GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer); glGenBuffers(1, &vertexBuffer);
GLfloat vertices[] = { GLfloat vertices[] = {
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0}; -0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0
};
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram();
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER); compile_shader(vshader, vshaderSource);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); compile_shader(fshader, fshaderSource);
program = glCreateProgram();
compile_shader(vshader, vshaderSource); glAttachShader(program, vshader);
compile_shader(fshader, fshaderSource); glAttachShader(program, fshader);
glLinkProgram(program);
glAttachShader(program, vshader); int status = 0;
glAttachShader(program, fshader); glGetProgramiv(program, GL_LINK_STATUS, &status);
glLinkProgram(program); if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
int status = 0; glUseProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
glUseProgram(program); //NOTE: send context id to parent
write(writeFd, &connectionID, sizeof(connectionID));
//NOTE: send context id to parent //NOTE: render loop
write(writeFd, &connectionID, sizeof(connectionID)); while(!mp_should_quit())
{
mp_pump_events(0);
mp_event event = { 0 };
while(mp_next_event(&event))
{
switch(event.type)
{
case MP_EVENT_WINDOW_CLOSE:
{
mp_request_quit();
}
break;
//NOTE: render loop default:
while(!mp_should_quit()) break;
{ }
mp_pump_events(0); }
mp_event event = {0};
while(mp_next_event(&event))
{
switch(event.type)
{
case MP_EVENT_WINDOW_CLOSE:
{
mp_request_quit();
} break;
default: mg_surface_prepare(surface);
break;
}
}
mg_surface_prepare(surface); mp_rect rect = mg_surface_get_frame(surface);
vec2 scaling = mg_surface_contents_scaling(surface);
mp_rect rect = mg_surface_get_frame(surface); glViewport(0, 0, rect.w * scaling.x, rect.h * scaling.y);
vec2 scaling = mg_surface_contents_scaling(surface); glClearColor(0.3, 0.3, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, rect.w*scaling.x, rect.h*scaling.y); static float alpha = 0;
glClearColor(0.3, 0.3, 1, 1); //f32 aspect = frameSize.x/frameSize.y;
glClear(GL_COLOR_BUFFER_BIT); f32 aspect = 800 / (f32)600;
static float alpha = 0; GLfloat matrix[] = { cosf(alpha) / aspect, sinf(alpha), 0, 0,
//f32 aspect = frameSize.x/frameSize.y; -sinf(alpha) / aspect, cosf(alpha), 0, 0,
f32 aspect = 800/(f32)600; 0, 0, 1, 0,
0, 0, 0, 1 };
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0, alpha += 2 * M_PI / 120;
-sinf(alpha)/aspect, cosf(alpha), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1};
alpha += 2*M_PI/120; glUniformMatrix4fv(0, 1, false, matrix);
glUniformMatrix4fv(0, 1, false, matrix); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); mg_surface_present(surface);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); }
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3); mp_terminate();
mg_surface_present(surface); return (0);
}
mp_terminate();
return(0);
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
LogLevel(LOG_LEVEL_DEBUG); LogLevel(LOG_LEVEL_DEBUG);
if(argc > 1) if(argc > 1)
{ {
if(!strcmp(argv[1], "--child")) if(!strcmp(argv[1], "--child"))
{ {
int writeFd = atoi(argv[2]); int writeFd = atoi(argv[2]);
printf("child process created with file desc %i\n", writeFd); printf("child process created with file desc %i\n", writeFd);
return(child_main(writeFd)); return (child_main(writeFd));
} }
else else
{ {
return(-1); return (-1);
} }
} }
// setvbuf( stdout, NULL, _IONBF, 0 ); // setvbuf( stdout, NULL, _IONBF, 0 );
mp_init(); mp_init();
//NOTE: create main window //NOTE: create main window
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mp_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 };
mp_window window = mp_window_create(rect, "test", 0); mp_window window = mp_window_create(rect, "test", 0);
//NOTE: create surface client //NOTE: create surface client
mg_surface surface = mg_surface_create_host(window); mg_surface surface = mg_surface_create_host(window);
//NOTE setup descriptors //NOTE setup descriptors
int fileDesc[2]; int fileDesc[2];
pipe(fileDesc); pipe(fileDesc);
printf("parent process created readFd %i and writeFd %i\n", fileDesc[0], fileDesc[1]); printf("parent process created readFd %i and writeFd %i\n", fileDesc[0], fileDesc[1]);
char writeDescStr[64]; char writeDescStr[64];
snprintf(writeDescStr, 64, "%i", fileDesc[1]); snprintf(writeDescStr, 64, "%i", fileDesc[1]);
char* args[] = {"bin/example_surface_sharing", "--child", writeDescStr, 0}; char* args[] = { "bin/example_surface_sharing", "--child", writeDescStr, 0 };
process_id child = spawn_child(args[0], args); process_id child = spawn_child(args[0], args);
//NOTE: read the connection id //NOTE: read the connection id
mg_surface_id connectionID = 0; mg_surface_id connectionID = 0;
read(fileDesc[0], &connectionID, sizeof(connectionID)); read(fileDesc[0], &connectionID, sizeof(connectionID));
printf("received child connection id %llu\n", connectionID); printf("received child connection id %llu\n", connectionID);
//NOTE: connect the client //NOTE: connect the client
mg_surface_host_connect(surface, connectionID); mg_surface_host_connect(surface, connectionID);
//NOTE: show the window //NOTE: show the window
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
while(!mp_should_quit()) while(!mp_should_quit())
{ {
mp_pump_events(0); mp_pump_events(0);
mp_event event = {0}; mp_event event = { 0 };
while(mp_next_event(&event)) while(mp_next_event(&event))
{ {
switch(event.type) switch(event.type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
default: default:
break; break;
} }
} }
mg_surface_prepare(surface); mg_surface_prepare(surface);
mg_surface_present(surface); mg_surface_present(surface);
} }
terminate_child(child); terminate_child(child);
mp_terminate(); mp_terminate();
return(0); return (0);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,242 +6,248 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include <errno.h>
#include<string.h> #include <stdio.h>
#include<stdio.h> #include <stdlib.h>
#include<errno.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#include"milepost.h" #include "milepost.h"
#include"tiger.c" #include "tiger.c"
mg_font create_font() mg_font create_font()
{ {
//NOTE(martin): create font //NOTE(martin): create font
str8 fontPath = path_executable_relative(mem_scratch(), STR8("../resources/OpenSansLatinSubset.ttf")); str8 fontPath = path_executable_relative(mem_scratch(), STR8("../resources/OpenSansLatinSubset.ttf"));
char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath); char* fontPathCString = str8_to_cstring(mem_scratch(), fontPath);
FILE* fontFile = fopen(fontPathCString, "r"); FILE* fontFile = fopen(fontPathCString, "r");
if(!fontFile) if(!fontFile)
{ {
log_error("Could not load font file '%s': %s\n", fontPathCString, strerror(errno)); log_error("Could not load font file '%s': %s\n", fontPathCString, strerror(errno));
return(mg_font_nil()); return (mg_font_nil());
} }
unsigned char* fontData = 0; unsigned char* fontData = 0;
fseek(fontFile, 0, SEEK_END); fseek(fontFile, 0, SEEK_END);
u32 fontDataSize = ftell(fontFile); u32 fontDataSize = ftell(fontFile);
rewind(fontFile); rewind(fontFile);
fontData = (unsigned char*)malloc(fontDataSize); fontData = (unsigned char*)malloc(fontDataSize);
fread(fontData, 1, fontDataSize, fontFile); fread(fontData, 1, fontDataSize, fontFile);
fclose(fontFile); fclose(fontFile);
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN, unicode_range ranges[5] = { UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT, UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
UNICODE_RANGE_LATIN_EXTENDED_A, UNICODE_RANGE_LATIN_EXTENDED_A,
UNICODE_RANGE_LATIN_EXTENDED_B, UNICODE_RANGE_LATIN_EXTENDED_B,
UNICODE_RANGE_SPECIALS}; UNICODE_RANGE_SPECIALS };
mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges); mg_font font = mg_font_create_from_memory(fontDataSize, fontData, 5, ranges);
free(fontData); free(fontData);
return(font); return (font);
} }
int main() int main()
{ {
mp_init(); mp_init();
mp_clock_init(); //TODO put that in mp_init()? mp_clock_init(); //TODO put that in mp_init()?
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; mp_rect windowRect = { .x = 100, .y = 100, .w = 810, .h = 610 };
mp_window window = mp_window_create(windowRect, "test", 0); mp_window window = mp_window_create(windowRect, "test", 0);
mp_rect contentRect = mp_window_get_content_rect(window); mp_rect contentRect = mp_window_get_content_rect(window);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS); mg_surface surface = mg_surface_create_for_window(window, MG_CANVAS);
if(mg_surface_is_nil(surface)) if(mg_surface_is_nil(surface))
{ {
log_error("Couln't create surface\n"); log_error("Couln't create surface\n");
return(-1); return (-1);
} }
mg_surface_swap_interval(surface, 0); mg_surface_swap_interval(surface, 0);
//TODO: create canvas //TODO: create canvas
mg_canvas canvas = mg_canvas_create(); mg_canvas canvas = mg_canvas_create();
if(mg_canvas_is_nil(canvas)) if(mg_canvas_is_nil(canvas))
{ {
printf("Error: couldn't create canvas\n"); printf("Error: couldn't create canvas\n");
return(-1); return (-1);
} }
mg_font font = create_font(); mg_font font = create_font();
// start app // start app
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
bool tracked = false; bool tracked = false;
vec2 trackPoint = {0}; vec2 trackPoint = { 0 };
f32 zoom = 1; f32 zoom = 1;
f32 startX = 300, startY = 200; f32 startX = 300, startY = 200;
bool singlePath = false; bool singlePath = false;
int singlePathIndex = 0; int singlePathIndex = 0;
f64 frameTime = 0; f64 frameTime = 0;
mp_input_state inputState = {0}; mp_input_state inputState = { 0 };
while(!mp_should_quit()) while(!mp_should_quit())
{ {
f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC); f64 startTime = mp_get_time(MP_CLOCK_MONOTONIC);
mp_pump_events(0); mp_pump_events(0);
mp_event* event = 0; mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0) while((event = mp_next_event(mem_scratch())) != 0)
{ {
mp_input_process_event(&inputState, event); mp_input_process_event(&inputState, event);
switch(event->type) switch(event->type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
case MP_EVENT_MOUSE_BUTTON: case MP_EVENT_MOUSE_BUTTON:
{ {
if(event->key.code == MP_MOUSE_LEFT) if(event->key.code == MP_MOUSE_LEFT)
{ {
if(event->key.action == MP_KEY_PRESS) if(event->key.action == MP_KEY_PRESS)
{ {
tracked = true; tracked = true;
vec2 mousePos = mp_mouse_position(&inputState); vec2 mousePos = mp_mouse_position(&inputState);
trackPoint.x = (mousePos.x - startX)/zoom; trackPoint.x = (mousePos.x - startX) / zoom;
trackPoint.y = (mousePos.y - startY)/zoom; trackPoint.y = (mousePos.y - startY) / zoom;
} }
else else
{ {
tracked = false; tracked = false;
} }
} }
} break; }
break;
case MP_EVENT_MOUSE_WHEEL: case MP_EVENT_MOUSE_WHEEL:
{ {
vec2 mousePos = mp_mouse_position(&inputState); vec2 mousePos = mp_mouse_position(&inputState);
f32 pinX = (mousePos.x - startX)/zoom; f32 pinX = (mousePos.x - startX) / zoom;
f32 pinY = (mousePos.y - startY)/zoom; f32 pinY = (mousePos.y - startY) / zoom;
zoom *= 1 + event->mouse.deltaY * 0.01; zoom *= 1 + event->mouse.deltaY * 0.01;
zoom = Clamp(zoom, 0.5, 5); zoom = Clamp(zoom, 0.5, 5);
startX = mousePos.x - pinX*zoom; startX = mousePos.x - pinX * zoom;
startY = mousePos.y - pinY*zoom; startY = mousePos.y - pinY * zoom;
} break; }
break;
case MP_EVENT_KEYBOARD_KEY: case MP_EVENT_KEYBOARD_KEY:
{ {
if(event->key.action == MP_KEY_PRESS || event->key.action == MP_KEY_REPEAT) if(event->key.action == MP_KEY_PRESS || event->key.action == MP_KEY_REPEAT)
{ {
switch(event->key.code) switch(event->key.code)
{ {
case MP_KEY_SPACE: case MP_KEY_SPACE:
singlePath = !singlePath; singlePath = !singlePath;
break; break;
case MP_KEY_UP: case MP_KEY_UP:
{ {
if(event->key.mods & MP_KEYMOD_SHIFT) if(event->key.mods & MP_KEYMOD_SHIFT)
{ {
singlePathIndex++; singlePathIndex++;
} }
else else
{ {
zoom += 0.001; zoom += 0.001;
} }
} break; }
break;
case MP_KEY_DOWN: case MP_KEY_DOWN:
{ {
if(event->key.mods & MP_KEYMOD_SHIFT) if(event->key.mods & MP_KEYMOD_SHIFT)
{ {
singlePathIndex--; singlePathIndex--;
} }
else else
{ {
zoom -= 0.001; zoom -= 0.001;
} }
} break; }
} break;
} }
} break; }
}
break;
default: default:
break; break;
} }
} }
if(tracked) if(tracked)
{ {
vec2 mousePos = mp_mouse_position(&inputState); vec2 mousePos = mp_mouse_position(&inputState);
startX = mousePos.x - trackPoint.x*zoom; startX = mousePos.x - trackPoint.x * zoom;
startY = mousePos.y - trackPoint.y*zoom; startY = mousePos.y - trackPoint.y * zoom;
} }
mg_surface_prepare(surface); mg_surface_prepare(surface);
mg_set_color_rgba(1, 0, 1, 1); mg_set_color_rgba(1, 0, 1, 1);
mg_clear(); mg_clear();
mg_matrix_push((mg_mat2x3){zoom, 0, startX, mg_matrix_push((mg_mat2x3){ zoom, 0, startX,
0, zoom, startY}); 0, zoom, startY });
draw_tiger(singlePath, singlePathIndex); draw_tiger(singlePath, singlePathIndex);
if(singlePath) if(singlePath)
{ {
printf("display single path %i\n", singlePathIndex); printf("display single path %i\n", singlePathIndex);
printf("viewpos = (%f, %f), zoom = %f\n", startX, startY, zoom); printf("viewpos = (%f, %f), zoom = %f\n", startX, startY, zoom);
} }
mg_matrix_pop(); mg_matrix_pop();
// text // text
mg_set_color_rgba(0, 0, 1, 1); mg_set_color_rgba(0, 0, 1, 1);
mg_set_font(font); mg_set_font(font);
mg_set_font_size(12); mg_set_font_size(12);
mg_move_to(50, 600-50); mg_move_to(50, 600 - 50);
str8 text = str8_pushf(mem_scratch(), str8 text = str8_pushf(mem_scratch(),
"Milepost vector graphics test program (frame time = %fs, fps = %f)...", "Milepost vector graphics test program (frame time = %fs, fps = %f)...",
frameTime, frameTime,
1./frameTime); 1. / frameTime);
mg_text_outlines(text); mg_text_outlines(text);
mg_fill(); mg_fill();
printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n", printf("Milepost vector graphics test program (frame time = %fs, fps = %f)...\n",
frameTime, frameTime,
1./frameTime); 1. / frameTime);
mg_render(surface, canvas); mg_render(surface, canvas);
mg_surface_present(surface); mg_surface_present(surface);
mp_input_next_frame(&inputState); mp_input_next_frame(&inputState);
mem_arena_clear(mem_scratch()); mem_arena_clear(mem_scratch());
frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime; frameTime = mp_get_time(MP_CLOCK_MONOTONIC) - startTime;
} }
mg_font_destroy(font); mg_font_destroy(font);
mg_canvas_destroy(canvas); mg_canvas_destroy(canvas);
mg_surface_destroy(surface); mg_surface_destroy(surface);
mp_window_destroy(window); mp_window_destroy(window);
mp_terminate(); mp_terminate();
return(0); return (0);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,158 +6,158 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdio.h> #include <stdio.h>
#include<string.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#define MG_INCLUDE_GL_API #define MG_INCLUDE_GL_API
#include"milepost.h" #include "milepost.h"
unsigned int program; unsigned int program;
const char* vshaderSource = const char* vshaderSource =
"#version 430\n" "#version 430\n"
"attribute vec4 vPosition;\n" "attribute vec4 vPosition;\n"
"uniform mat4 transform;\n" "uniform mat4 transform;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Position = transform*vPosition;\n" " gl_Position = transform*vPosition;\n"
"}\n"; "}\n";
const char* fshaderSource = const char* fshaderSource =
"#version 430\n" "#version 430\n"
"precision mediump float;\n" "precision mediump float;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n"; "}\n";
void compile_shader(GLuint shader, const char* source) void compile_shader(GLuint shader, const char* source)
{ {
glShaderSource(shader, 1, &source, 0); glShaderSource(shader, 1, &source, 0);
glCompileShader(shader); glCompileShader(shader);
int err = glGetError(); int err = glGetError();
if(err) if(err)
{ {
printf("gl error: %i\n", err); printf("gl error: %i\n", err);
} }
int status = 0; int status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(!status) if(!status)
{ {
char buffer[256]; char buffer[256];
int size = 0; int size = 0;
glGetShaderInfoLog(shader, 256, &size, buffer); glGetShaderInfoLog(shader, 256, &size, buffer);
printf("shader error: %.*s\n", size, buffer); printf("shader error: %.*s\n", size, buffer);
} }
} }
int main() int main()
{ {
mp_init(); mp_init();
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mp_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 };
mp_window window = mp_window_create(rect, "test", 0); mp_window window = mp_window_create(rect, "test", 0);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_GL); mg_surface surface = mg_surface_create_for_window(window, MG_GL);
//NOTE: init shader and gl state //NOTE: init shader and gl state
mg_surface_prepare(surface); mg_surface_prepare(surface);
GLuint vao; GLuint vao;
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
glBindVertexArray(vao); glBindVertexArray(vao);
GLuint vertexBuffer; GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer); glGenBuffers(1, &vertexBuffer);
GLfloat vertices[] = { GLfloat vertices[] = {
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0}; -0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0
};
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram();
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER); compile_shader(vshader, vshaderSource);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); compile_shader(fshader, fshaderSource);
program = glCreateProgram();
compile_shader(vshader, vshaderSource); glAttachShader(program, vshader);
compile_shader(fshader, fshaderSource); glAttachShader(program, fshader);
glLinkProgram(program);
glAttachShader(program, vshader); int status = 0;
glAttachShader(program, fshader); glGetProgramiv(program, GL_LINK_STATUS, &status);
glLinkProgram(program); if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
int status = 0; glUseProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
glUseProgram(program); mp_window_bring_to_front(window);
// mp_window_focus(window);
mp_window_bring_to_front(window); while(!mp_should_quit())
// mp_window_focus(window); {
mp_pump_events(0);
mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0)
{
switch(event->type)
{
case MP_EVENT_WINDOW_CLOSE:
{
mp_request_quit();
}
break;
while(!mp_should_quit()) default:
{ break;
mp_pump_events(0); }
mp_event* event = 0; }
while((event = mp_next_event(mem_scratch())) != 0)
{
switch(event->type)
{
case MP_EVENT_WINDOW_CLOSE:
{
mp_request_quit();
} break;
default: mg_surface_prepare(surface);
break;
}
}
mg_surface_prepare(surface); glClearColor(0.3, 0.3, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.3, 0.3, 1, 1); static float alpha = 0;
glClear(GL_COLOR_BUFFER_BIT); //f32 aspect = frameSize.x/frameSize.y;
f32 aspect = 800 / (f32)600;
static float alpha = 0; GLfloat matrix[] = { cosf(alpha) / aspect, sinf(alpha), 0, 0,
//f32 aspect = frameSize.x/frameSize.y; -sinf(alpha) / aspect, cosf(alpha), 0, 0,
f32 aspect = 800/(f32)600; 0, 0, 1, 0,
0, 0, 0, 1 };
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0, alpha += 2 * M_PI / 120;
-sinf(alpha)/aspect, cosf(alpha), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1};
alpha += 2*M_PI/120; glUniformMatrix4fv(0, 1, false, matrix);
glUniformMatrix4fv(0, 1, false, matrix); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); mg_surface_present(surface);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3); mem_arena_clear(mem_scratch());
}
mg_surface_present(surface); mp_terminate();
mem_arena_clear(mem_scratch()); return (0);
}
mp_terminate();
return(0);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,160 +6,160 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdio.h> #include <stdio.h>
#include<stdlib.h> #include <stdlib.h>
#include<string.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#define MG_INCLUDE_GL_API 1 #define MG_INCLUDE_GL_API 1
#include"milepost.h" #include "milepost.h"
unsigned int program; unsigned int program;
const char* vshaderSource = const char* vshaderSource =
//"#version 320 es\n" //"#version 320 es\n"
"attribute vec4 vPosition;\n" "attribute vec4 vPosition;\n"
"uniform mat4 transform;\n" "uniform mat4 transform;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_Position = transform*vPosition;\n" " gl_Position = transform*vPosition;\n"
"}\n"; "}\n";
const char* fshaderSource = const char* fshaderSource =
//"#version 320 es\n" //"#version 320 es\n"
"precision mediump float;\n" "precision mediump float;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n"; "}\n";
void compile_shader(GLuint shader, const char* source) void compile_shader(GLuint shader, const char* source)
{ {
glShaderSource(shader, 1, &source, 0); glShaderSource(shader, 1, &source, 0);
glCompileShader(shader); glCompileShader(shader);
int err = glGetError(); int err = glGetError();
if(err) if(err)
{ {
printf("gl error: %i\n", err); printf("gl error: %i\n", err);
} }
int status = 0; int status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(!status) if(!status)
{ {
char buffer[256]; char buffer[256];
int size = 0; int size = 0;
glGetShaderInfoLog(shader, 256, &size, buffer); glGetShaderInfoLog(shader, 256, &size, buffer);
printf("shader error: %.*s\n", size, buffer); printf("shader error: %.*s\n", size, buffer);
} }
} }
int main() int main()
{ {
mp_init(); mp_init();
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mp_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 };
mp_window window = mp_window_create(rect, "test", 0); mp_window window = mp_window_create(rect, "test", 0);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_GLES); mg_surface surface = mg_surface_create_for_window(window, MG_GLES);
mg_surface_prepare(surface); mg_surface_prepare(surface);
//NOTE: init shader and gl state //NOTE: init shader and gl state
GLuint vao; GLuint vao;
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
glBindVertexArray(vao); glBindVertexArray(vao);
GLuint vertexBuffer; GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer); glGenBuffers(1, &vertexBuffer);
GLfloat vertices[] = { GLfloat vertices[] = {
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0}; -0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0
};
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram();
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER); compile_shader(vshader, vshaderSource);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); compile_shader(fshader, fshaderSource);
program = glCreateProgram();
compile_shader(vshader, vshaderSource); glAttachShader(program, vshader);
compile_shader(fshader, fshaderSource); glAttachShader(program, fshader);
glLinkProgram(program);
glAttachShader(program, vshader); int status = 0;
glAttachShader(program, fshader); glGetProgramiv(program, GL_LINK_STATUS, &status);
glLinkProgram(program); if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
int status = 0; glUseProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
glUseProgram(program); mp_window_bring_to_front(window);
// mp_window_focus(window);
mp_window_bring_to_front(window); while(!mp_should_quit())
// mp_window_focus(window); {
mp_pump_events(0);
mp_event* event = 0;
while((event = mp_next_event(mem_scratch())) != 0)
{
switch(event->type)
{
case MP_EVENT_WINDOW_CLOSE:
{
mp_request_quit();
}
break;
while(!mp_should_quit()) default:
{ break;
mp_pump_events(0); }
mp_event* event = 0; }
while((event = mp_next_event(mem_scratch())) != 0)
{
switch(event->type)
{
case MP_EVENT_WINDOW_CLOSE:
{
mp_request_quit();
} break;
default: // mg_surface_prepare(surface);
break;
}
}
// mg_surface_prepare(surface); glClearColor(0.3, 0.3, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.3, 0.3, 1, 1); static float alpha = 0;
glClear(GL_COLOR_BUFFER_BIT); //f32 aspect = frameSize.x/frameSize.y;
f32 aspect = 800 / (f32)600;
static float alpha = 0; GLfloat matrix[] = { cosf(alpha) / aspect, sinf(alpha), 0, 0,
//f32 aspect = frameSize.x/frameSize.y; -sinf(alpha) / aspect, cosf(alpha), 0, 0,
f32 aspect = 800/(f32)600; 0, 0, 1, 0,
0, 0, 0, 1 };
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0, alpha += 2 * M_PI / 120;
-sinf(alpha)/aspect, cosf(alpha), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1};
alpha += 2*M_PI/120; glUniformMatrix4fv(0, 1, false, matrix);
glUniformMatrix4fv(0, 1, false, matrix); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); mg_surface_present(surface);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3); mem_arena_clear(mem_scratch());
}
mg_surface_present(surface); mg_surface_destroy(surface);
mp_window_destroy(window);
mp_terminate();
mem_arena_clear(mem_scratch()); return (0);
}
mg_surface_destroy(surface);
mp_window_destroy(window);
mp_terminate();
return(0);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: main.cpp * @file: main.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,121 +6,122 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include <stdlib.h>
#include<string.h> #include <string.h>
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC #define _USE_MATH_DEFINES //NOTE: necessary for MSVC
#include<math.h> #include <math.h>
#include"milepost.h" #include "milepost.h"
#include"mtl_surface.h" #include "mtl_surface.h"
#define LOG_SUBSYSTEM "Main" #define LOG_SUBSYSTEM "Main"
#import<Metal/Metal.h> #import <Metal/Metal.h>
#import<QuartzCore/CAMetalLayer.h> #import <QuartzCore/CAMetalLayer.h>
#include"vertex.h" #include "vertex.h"
static const my_vertex triangle[3] = {{{250, -250},{1, 0, 0, 1}}, static const my_vertex triangle[3] = { { { 250, -250 }, { 1, 0, 0, 1 } },
{{-250, -250},{0, 1, 0, 1}}, { { -250, -250 }, { 0, 1, 0, 1 } },
{{0, 250},{0, 0, 1, 1}}}; { { 0, 250 }, { 0, 0, 1, 1 } } };
int main() int main()
{ {
LogLevel(LOG_LEVEL_DEBUG); LogLevel(LOG_LEVEL_DEBUG);
mp_init(); mp_init();
mp_rect rect = {.x = 100, .y = 100, .w = 800, .h = 600}; mp_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 };
mp_window window = mp_window_create(rect, "test", 0); mp_window window = mp_window_create(rect, "test", 0);
//NOTE: create surface //NOTE: create surface
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_METAL); mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_METAL);
//NOTE(martin): load the library //NOTE(martin): load the library
id<MTLDevice> device = MTLCreateSystemDefaultDevice(); id<MTLDevice> device = MTLCreateSystemDefaultDevice();
str8 shaderPath = path_executable_relative(mem_scratch(), STR8("triangle_shader.metallib")); str8 shaderPath = path_executable_relative(mem_scratch(), STR8("triangle_shader.metallib"));
const char* shaderPathCString = str8_to_cstring(mem_scratch(), shaderPath); const char* shaderPathCString = str8_to_cstring(mem_scratch(), shaderPath);
NSString* metalFileName = [[NSString alloc] initWithCString: shaderPathCString encoding: NSUTF8StringEncoding]; NSString* metalFileName = [[NSString alloc] initWithCString:shaderPathCString encoding:NSUTF8StringEncoding];
NSError* err = 0; NSError* err = 0;
id<MTLLibrary> library = [device newLibraryWithFile: metalFileName error:&err]; id<MTLLibrary> library = [device newLibraryWithFile:metalFileName error:&err];
if(err != nil) if(err != nil)
{ {
const char* errStr = [[err localizedDescription] UTF8String]; const char* errStr = [[err localizedDescription] UTF8String];
printf("error : %s\n", errStr); printf("error : %s\n", errStr);
return(-1); return (-1);
} }
id<MTLFunction> vertexFunction = [library newFunctionWithName:@"VertexShader"]; id<MTLFunction> vertexFunction = [library newFunctionWithName:@"VertexShader"];
id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"FragmentShader"]; id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"FragmentShader"];
//NOTE(martin): create a render pipeline //NOTE(martin): create a render pipeline
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; MTLRenderPipelineDescriptor* pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipelineStateDescriptor.label = @"My simple pipeline"; pipelineStateDescriptor.label = @"My simple pipeline";
pipelineStateDescriptor.vertexFunction = vertexFunction; pipelineStateDescriptor.vertexFunction = vertexFunction;
pipelineStateDescriptor.fragmentFunction = fragmentFunction; pipelineStateDescriptor.fragmentFunction = fragmentFunction;
CAMetalLayer* layer = mg_mtl_surface_layer(surface); CAMetalLayer* layer = mg_mtl_surface_layer(surface);
pipelineStateDescriptor.colorAttachments[0].pixelFormat = layer.pixelFormat; pipelineStateDescriptor.colorAttachments[0].pixelFormat = layer.pixelFormat;
id<MTLRenderPipelineState> pipelineState = [device newRenderPipelineStateWithDescriptor: pipelineStateDescriptor error:&err]; id<MTLRenderPipelineState> pipelineState = [device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&err];
if(err != nil) if(err != nil)
{ {
const char* errStr = [[err localizedDescription] UTF8String]; const char* errStr = [[err localizedDescription] UTF8String];
printf("error : %s\n", errStr); printf("error : %s\n", errStr);
return(-1); return (-1);
} }
// start app // start app
mp_window_bring_to_front(window); mp_window_bring_to_front(window);
mp_window_focus(window); mp_window_focus(window);
while(!mp_should_quit()) while(!mp_should_quit())
{ {
mp_pump_events(0); mp_pump_events(0);
mp_event event = {0}; mp_event event = { 0 };
while(mp_next_event(&event)) while(mp_next_event(&event))
{ {
switch(event.type) switch(event.type)
{ {
case MP_EVENT_WINDOW_CLOSE: case MP_EVENT_WINDOW_CLOSE:
{ {
mp_request_quit(); mp_request_quit();
} break; }
break;
default: default:
break; break;
} }
} }
vector_uint2 viewportSize; vector_uint2 viewportSize;
viewportSize.x = 800; viewportSize.x = 800;
viewportSize.y = 600; viewportSize.y = 600;
mg_surface_prepare(surface); mg_surface_prepare(surface);
id<CAMetalDrawable> drawable = mg_mtl_surface_drawable(surface); id<CAMetalDrawable> drawable = mg_mtl_surface_drawable(surface);
id<MTLCommandBuffer> commandBuffer = mg_mtl_surface_command_buffer(surface); id<MTLCommandBuffer> commandBuffer = mg_mtl_surface_command_buffer(surface);
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
renderPassDescriptor.colorAttachments[0].texture = drawable.texture; renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
//Set the pipeline state //Set the pipeline state
[encoder setRenderPipelineState:pipelineState]; [encoder setRenderPipelineState:pipelineState];
//Send data to the shader and add draw call //Send data to the shader and add draw call
[encoder setVertexBytes: triangle length:sizeof(triangle) atIndex: vertexInputIndexVertices]; [encoder setVertexBytes:triangle length:sizeof(triangle) atIndex:vertexInputIndexVertices];
[encoder setVertexBytes: &viewportSize length:sizeof(viewportSize) atIndex: vertexInputIndexViewportSize]; [encoder setVertexBytes:&viewportSize length:sizeof(viewportSize) atIndex:vertexInputIndexViewportSize];
[encoder drawPrimitives: MTLPrimitiveTypeTriangle vertexStart: 0 vertexCount: 3]; [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3];
[encoder endEncoding]; [encoder endEncoding];
mg_surface_present(surface); mg_surface_present(surface);
} }
mp_terminate(); mp_terminate();
return(0); return (0);
} }

View File

@ -2,16 +2,18 @@
#ifndef __VERTEX_H__ #ifndef __VERTEX_H__
#define __VERTEX_H__ #define __VERTEX_H__
#include<simd/simd.h> #include <simd/simd.h>
typedef struct typedef struct
{ {
vector_float2 pos; vector_float2 pos;
vector_float4 col; vector_float4 col;
} my_vertex; } my_vertex;
typedef enum { vertexInputIndexVertices = 0, typedef enum
vertexInputIndexViewportSize = 1 } vertexInputIndex; {
vertexInputIndexVertices = 0,
vertexInputIndexViewportSize = 1
} vertexInputIndex;
#endif //__VERTEX_H__ #endif //__VERTEX_H__

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: app.c * @file: app.c
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,10 +6,10 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include"platform/platform_debug.h" #include "app_internal.h"
#include"app_internal.h" #include "platform/platform_debug.h"
oc_app oc_appData = {0}; oc_app oc_appData = { 0 };
//--------------------------------------------------------------- //---------------------------------------------------------------
// Window handles // Window handles
@ -17,63 +17,63 @@ oc_app oc_appData = {0};
void oc_init_window_handles() void oc_init_window_handles()
{ {
oc_list_init(&oc_appData.windowFreeList); oc_list_init(&oc_appData.windowFreeList);
for(int i=0; i<OC_APP_MAX_WINDOWS; i++) for(int i = 0; i < OC_APP_MAX_WINDOWS; i++)
{ {
oc_appData.windowPool[i].generation = 1; oc_appData.windowPool[i].generation = 1;
oc_list_append(&oc_appData.windowFreeList, &oc_appData.windowPool[i].freeListElt); oc_list_append(&oc_appData.windowFreeList, &oc_appData.windowPool[i].freeListElt);
} }
} }
bool oc_window_handle_is_null(oc_window window) bool oc_window_handle_is_null(oc_window window)
{ {
return(window.h == 0); return (window.h == 0);
} }
oc_window oc_window_null_handle() oc_window oc_window_null_handle()
{ {
return((oc_window){.h = 0}); return ((oc_window){ .h = 0 });
} }
oc_window_data* oc_window_alloc() oc_window_data* oc_window_alloc()
{ {
return(oc_list_pop_entry(&oc_appData.windowFreeList, oc_window_data, freeListElt)); return (oc_list_pop_entry(&oc_appData.windowFreeList, oc_window_data, freeListElt));
} }
oc_window_data* oc_window_ptr_from_handle(oc_window handle) oc_window_data* oc_window_ptr_from_handle(oc_window handle)
{ {
u32 index = handle.h>>32; u32 index = handle.h >> 32;
u32 generation = handle.h & 0xffffffff; u32 generation = handle.h & 0xffffffff;
if(index >= OC_APP_MAX_WINDOWS) if(index >= OC_APP_MAX_WINDOWS)
{ {
return(0); return (0);
} }
oc_window_data* window = &oc_appData.windowPool[index]; oc_window_data* window = &oc_appData.windowPool[index];
if(window->generation != generation) if(window->generation != generation)
{ {
return(0); return (0);
} }
else else
{ {
return(window); return (window);
} }
} }
oc_window oc_window_handle_from_ptr(oc_window_data* window) oc_window oc_window_handle_from_ptr(oc_window_data* window)
{ {
OC_DEBUG_ASSERT( (window - oc_appData.windowPool) >= 0 OC_DEBUG_ASSERT((window - oc_appData.windowPool) >= 0
&& (window - oc_appData.windowPool) < OC_APP_MAX_WINDOWS); && (window - oc_appData.windowPool) < OC_APP_MAX_WINDOWS);
u64 h = ((u64)(window - oc_appData.windowPool))<<32 u64 h = ((u64)(window - oc_appData.windowPool)) << 32
| ((u64)window->generation); | ((u64)window->generation);
return((oc_window){h}); return ((oc_window){ h });
} }
void oc_window_recycle_ptr(oc_window_data* window) void oc_window_recycle_ptr(oc_window_data* window)
{ {
window->generation++; window->generation++;
oc_list_push(&oc_appData.windowFreeList, &window->freeListElt); oc_list_push(&oc_appData.windowFreeList, &window->freeListElt);
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
@ -82,13 +82,13 @@ void oc_window_recycle_ptr(oc_window_data* window)
static void oc_init_common() static void oc_init_common()
{ {
oc_init_window_handles(); oc_init_window_handles();
oc_ringbuffer_init(&oc_appData.eventQueue, 16); oc_ringbuffer_init(&oc_appData.eventQueue, 16);
} }
static void oc_terminate_common() static void oc_terminate_common()
{ {
oc_ringbuffer_cleanup(&oc_appData.eventQueue); oc_ringbuffer_cleanup(&oc_appData.eventQueue);
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
@ -97,87 +97,87 @@ static void oc_terminate_common()
void oc_queue_event(oc_event* event) void oc_queue_event(oc_event* event)
{ {
oc_ringbuffer* queue = &oc_appData.eventQueue; oc_ringbuffer* queue = &oc_appData.eventQueue;
if(oc_ringbuffer_write_available(queue) < sizeof(oc_event)) if(oc_ringbuffer_write_available(queue) < sizeof(oc_event))
{ {
oc_log_error("event queue full\n"); oc_log_error("event queue full\n");
} }
else else
{ {
bool error = false; bool error = false;
oc_ringbuffer_reserve(queue, sizeof(oc_event), (u8*)event); oc_ringbuffer_reserve(queue, sizeof(oc_event), (u8*)event);
if(event->type == OC_EVENT_PATHDROP) if(event->type == OC_EVENT_PATHDROP)
{ {
oc_list_for(&event->paths.list, elt, oc_str8_elt, listElt) oc_list_for(&event->paths.list, elt, oc_str8_elt, listElt)
{ {
oc_str8* path = &elt->string; oc_str8* path = &elt->string;
if(oc_ringbuffer_write_available(queue) < (sizeof(u64) + path->len)) if(oc_ringbuffer_write_available(queue) < (sizeof(u64) + path->len))
{ {
oc_log_error("event queue full\n"); oc_log_error("event queue full\n");
error = true; error = true;
break; break;
} }
else else
{ {
oc_ringbuffer_reserve(queue, sizeof(u64), (u8*)&path->len); oc_ringbuffer_reserve(queue, sizeof(u64), (u8*)&path->len);
oc_ringbuffer_reserve(queue, path->len, (u8*)path->ptr); oc_ringbuffer_reserve(queue, path->len, (u8*)path->ptr);
} }
} }
} }
if(error) if(error)
{ {
oc_ringbuffer_rewind(queue); oc_ringbuffer_rewind(queue);
} }
else else
{ {
oc_ringbuffer_commit(queue); oc_ringbuffer_commit(queue);
} }
} }
} }
oc_event* oc_next_event(oc_arena* arena) oc_event* oc_next_event(oc_arena* arena)
{ {
//NOTE: pop and return event from queue //NOTE: pop and return event from queue
oc_event* event = 0; oc_event* event = 0;
oc_ringbuffer* queue = &oc_appData.eventQueue; oc_ringbuffer* queue = &oc_appData.eventQueue;
if(oc_ringbuffer_read_available(queue) >= sizeof(oc_event)) if(oc_ringbuffer_read_available(queue) >= sizeof(oc_event))
{ {
event = oc_arena_push_type(arena, oc_event); event = oc_arena_push_type(arena, oc_event);
u64 read = oc_ringbuffer_read(queue, sizeof(oc_event), (u8*)event); u64 read = oc_ringbuffer_read(queue, sizeof(oc_event), (u8*)event);
OC_DEBUG_ASSERT(read == sizeof(oc_event)); OC_DEBUG_ASSERT(read == sizeof(oc_event));
if(event->type == OC_EVENT_PATHDROP) if(event->type == OC_EVENT_PATHDROP)
{ {
u64 pathCount = event->paths.eltCount; u64 pathCount = event->paths.eltCount;
event->paths = (oc_str8_list){0}; event->paths = (oc_str8_list){ 0 };
for(int i=0; i<pathCount; i++) for(int i = 0; i < pathCount; i++)
{ {
if(oc_ringbuffer_read_available(queue) < sizeof(u64)) if(oc_ringbuffer_read_available(queue) < sizeof(u64))
{ {
oc_log_error("malformed path payload: no string size\n"); oc_log_error("malformed path payload: no string size\n");
break; break;
} }
u64 len = 0; u64 len = 0;
oc_ringbuffer_read(queue, sizeof(u64), (u8*)&len); oc_ringbuffer_read(queue, sizeof(u64), (u8*)&len);
if(oc_ringbuffer_read_available(queue) < len) if(oc_ringbuffer_read_available(queue) < len)
{ {
oc_log_error("malformed path payload: string shorter than expected\n"); oc_log_error("malformed path payload: string shorter than expected\n");
break; break;
} }
char* buffer = oc_arena_push_array(arena, char, len); char* buffer = oc_arena_push_array(arena, char, len);
oc_ringbuffer_read(queue, len, (u8*)buffer); oc_ringbuffer_read(queue, len, (u8*)buffer);
oc_str8_list_push(arena, &event->paths, oc_str8_from_buffer(len, buffer)); oc_str8_list_push(arena, &event->paths, oc_str8_from_buffer(len, buffer));
} }
} }
} }
return(event); return (event);
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
@ -186,32 +186,32 @@ oc_event* oc_next_event(oc_arena* arena)
void oc_window_set_content_position(oc_window window, oc_vec2 position) void oc_window_set_content_position(oc_window window, oc_vec2 position)
{ {
oc_rect rect = oc_window_get_content_rect(window); oc_rect rect = oc_window_get_content_rect(window);
rect.x = position.x; rect.x = position.x;
rect.y = position.y; rect.y = position.y;
oc_window_set_content_rect(window, rect); oc_window_set_content_rect(window, rect);
} }
void oc_window_set_content_size(oc_window window, oc_vec2 size) void oc_window_set_content_size(oc_window window, oc_vec2 size)
{ {
oc_rect rect = oc_window_get_content_rect(window); oc_rect rect = oc_window_get_content_rect(window);
rect.w = size.x; rect.w = size.x;
rect.h = size.y; rect.h = size.y;
oc_window_set_content_rect(window, rect); oc_window_set_content_rect(window, rect);
} }
void oc_window_set_frame_position(oc_window window, oc_vec2 position) void oc_window_set_frame_position(oc_window window, oc_vec2 position)
{ {
oc_rect frame = oc_window_get_frame_rect(window); oc_rect frame = oc_window_get_frame_rect(window);
frame.x = position.x; frame.x = position.x;
frame.y = position.y; frame.y = position.y;
oc_window_set_frame_rect(window, frame); oc_window_set_frame_rect(window, frame);
} }
void oc_window_set_frame_size(oc_window window, oc_vec2 size) void oc_window_set_frame_size(oc_window window, oc_vec2 size)
{ {
oc_rect frame = oc_window_get_frame_rect(window); oc_rect frame = oc_window_get_frame_rect(window);
frame.w = size.x; frame.w = size.x;
frame.h = size.y; frame.h = size.y;
oc_window_set_frame_rect(window, frame); oc_window_set_frame_rect(window, frame);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: platform_app.h * @file: platform_app.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -9,378 +9,396 @@
#ifndef __APP_H_ #ifndef __APP_H_
#define __APP_H_ #define __APP_H_
#include"util/typedefs.h" #include "util/lists.h"
#include"util/utf8.h" #include "util/memory.h"
#include"util/lists.h" #include "util/typedefs.h"
#include"util/memory.h" #include "util/utf8.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Typedefs, enums and constants // Typedefs, enums and constants
//-------------------------------------------------------------------- //--------------------------------------------------------------------
typedef struct oc_window { u64 h; } oc_window; typedef struct oc_window
{
u64 h;
} oc_window;
typedef enum { OC_MOUSE_CURSOR_ARROW, typedef enum
OC_MOUSE_CURSOR_RESIZE_0, {
OC_MOUSE_CURSOR_RESIZE_90, OC_MOUSE_CURSOR_ARROW,
OC_MOUSE_CURSOR_RESIZE_45, OC_MOUSE_CURSOR_RESIZE_0,
OC_MOUSE_CURSOR_RESIZE_135, OC_MOUSE_CURSOR_RESIZE_90,
OC_MOUSE_CURSOR_TEXT } oc_mouse_cursor; OC_MOUSE_CURSOR_RESIZE_45,
OC_MOUSE_CURSOR_RESIZE_135,
OC_MOUSE_CURSOR_TEXT
} oc_mouse_cursor;
typedef i32 oc_window_style; typedef i32 oc_window_style;
static const oc_window_style OC_WINDOW_STYLE_NO_TITLE = 0x01<<0, static const oc_window_style OC_WINDOW_STYLE_NO_TITLE = 0x01 << 0,
OC_WINDOW_STYLE_FIXED_SIZE = 0x01<<1, OC_WINDOW_STYLE_FIXED_SIZE = 0x01 << 1,
OC_WINDOW_STYLE_NO_CLOSE = 0x01<<2, OC_WINDOW_STYLE_NO_CLOSE = 0x01 << 2,
OC_WINDOW_STYLE_NO_MINIFY = 0x01<<3, OC_WINDOW_STYLE_NO_MINIFY = 0x01 << 3,
OC_WINDOW_STYLE_NO_FOCUS = 0x01<<4, OC_WINDOW_STYLE_NO_FOCUS = 0x01 << 4,
OC_WINDOW_STYLE_FLOAT = 0x01<<5, OC_WINDOW_STYLE_FLOAT = 0x01 << 5,
OC_WINDOW_STYLE_POPUPMENU = 0x01<<6, OC_WINDOW_STYLE_POPUPMENU = 0x01 << 6,
OC_WINDOW_STYLE_NO_BUTTONS = 0x01<<7; OC_WINDOW_STYLE_NO_BUTTONS = 0x01 << 7;
typedef enum { OC_EVENT_NONE, typedef enum
OC_EVENT_KEYBOARD_MODS, //TODO: remove, keep only key? {
OC_EVENT_KEYBOARD_KEY, OC_EVENT_NONE,
OC_EVENT_KEYBOARD_CHAR, OC_EVENT_KEYBOARD_MODS, //TODO: remove, keep only key?
OC_EVENT_MOUSE_BUTTON, OC_EVENT_KEYBOARD_KEY,
OC_EVENT_MOUSE_MOVE, OC_EVENT_KEYBOARD_CHAR,
OC_EVENT_MOUSE_WHEEL, OC_EVENT_MOUSE_BUTTON,
OC_EVENT_MOUSE_ENTER, OC_EVENT_MOUSE_MOVE,
OC_EVENT_MOUSE_LEAVE, OC_EVENT_MOUSE_WHEEL,
OC_EVENT_WINDOW_RESIZE, OC_EVENT_MOUSE_ENTER,
OC_EVENT_WINDOW_MOVE, OC_EVENT_MOUSE_LEAVE,
OC_EVENT_WINDOW_FOCUS, OC_EVENT_WINDOW_RESIZE,
OC_EVENT_WINDOW_UNFOCUS, OC_EVENT_WINDOW_MOVE,
OC_EVENT_WINDOW_HIDE, // rename to minimize? OC_EVENT_WINDOW_FOCUS,
OC_EVENT_WINDOW_SHOW, // rename to restore? OC_EVENT_WINDOW_UNFOCUS,
OC_EVENT_WINDOW_CLOSE, OC_EVENT_WINDOW_HIDE, // rename to minimize?
OC_EVENT_PATHDROP, OC_EVENT_WINDOW_SHOW, // rename to restore?
OC_EVENT_FRAME, OC_EVENT_WINDOW_CLOSE,
OC_EVENT_QUIT } oc_event_type; OC_EVENT_PATHDROP,
OC_EVENT_FRAME,
OC_EVENT_QUIT
} oc_event_type;
typedef enum { OC_KEY_NO_ACTION, typedef enum
OC_KEY_PRESS, {
OC_KEY_RELEASE, OC_KEY_NO_ACTION,
OC_KEY_REPEAT } oc_key_action; OC_KEY_PRESS,
OC_KEY_RELEASE,
OC_KEY_REPEAT
} oc_key_action;
typedef enum { OC_KEY_UNKNOWN = 0, typedef enum
OC_KEY_SPACE = 32, {
OC_KEY_APOSTROPHE = 39, /* ' */ OC_KEY_UNKNOWN = 0,
OC_KEY_COMMA = 44, /* , */ OC_KEY_SPACE = 32,
OC_KEY_MINUS = 45, // - OC_KEY_APOSTROPHE = 39, /* ' */
OC_KEY_PERIOD = 46, // . OC_KEY_COMMA = 44, /* , */
OC_KEY_SLASH = 47, // / OC_KEY_MINUS = 45, // -
OC_KEY_0 = 48, OC_KEY_PERIOD = 46, // .
OC_KEY_1 = 49, OC_KEY_SLASH = 47, // /
OC_KEY_2 = 50, OC_KEY_0 = 48,
OC_KEY_3 = 51, OC_KEY_1 = 49,
OC_KEY_4 = 52, OC_KEY_2 = 50,
OC_KEY_5 = 53, OC_KEY_3 = 51,
OC_KEY_6 = 54, OC_KEY_4 = 52,
OC_KEY_7 = 55, OC_KEY_5 = 53,
OC_KEY_8 = 56, OC_KEY_6 = 54,
OC_KEY_9 = 57, OC_KEY_7 = 55,
OC_KEY_SEMICOLON = 59, // ; OC_KEY_8 = 56,
OC_KEY_EQUAL = 61, // = OC_KEY_9 = 57,
OC_KEY_A = 65, OC_KEY_SEMICOLON = 59, // ;
OC_KEY_B = 66, OC_KEY_EQUAL = 61, // =
OC_KEY_C = 67, OC_KEY_A = 65,
OC_KEY_D = 68, OC_KEY_B = 66,
OC_KEY_E = 69, OC_KEY_C = 67,
OC_KEY_F = 70, OC_KEY_D = 68,
OC_KEY_G = 71, OC_KEY_E = 69,
OC_KEY_H = 72, OC_KEY_F = 70,
OC_KEY_I = 73, OC_KEY_G = 71,
OC_KEY_J = 74, OC_KEY_H = 72,
OC_KEY_K = 75, OC_KEY_I = 73,
OC_KEY_L = 76, OC_KEY_J = 74,
OC_KEY_M = 77, OC_KEY_K = 75,
OC_KEY_N = 78, OC_KEY_L = 76,
OC_KEY_O = 79, OC_KEY_M = 77,
OC_KEY_P = 80, OC_KEY_N = 78,
OC_KEY_Q = 81, OC_KEY_O = 79,
OC_KEY_R = 82, OC_KEY_P = 80,
OC_KEY_S = 83, OC_KEY_Q = 81,
OC_KEY_T = 84, OC_KEY_R = 82,
OC_KEY_U = 85, OC_KEY_S = 83,
OC_KEY_V = 86, OC_KEY_T = 84,
OC_KEY_W = 87, OC_KEY_U = 85,
OC_KEY_X = 88, OC_KEY_V = 86,
OC_KEY_Y = 89, OC_KEY_W = 87,
OC_KEY_Z = 90, OC_KEY_X = 88,
OC_KEY_LEFT_BRACKET = 91, // [ OC_KEY_Y = 89,
OC_KEY_BACKSLASH = 92, // \ */ OC_KEY_Z = 90,
OC_KEY_RIGHT_BRACKET = 93, // ] OC_KEY_LEFT_BRACKET = 91, // [
OC_KEY_GRAVE_ACCENT = 96, // ` OC_KEY_BACKSLASH = 92, // \ */
OC_KEY_WORLD_1 = 161, // non-US #1 OC_KEY_RIGHT_BRACKET = 93, // ]
OC_KEY_WORLD_2 = 162, // non-US #2 OC_KEY_GRAVE_ACCENT = 96, // `
OC_KEY_ESCAPE = 256, OC_KEY_WORLD_1 = 161, // non-US #1
OC_KEY_ENTER = 257, OC_KEY_WORLD_2 = 162, // non-US #2
OC_KEY_TAB = 258, OC_KEY_ESCAPE = 256,
OC_KEY_BACKSPACE = 259, OC_KEY_ENTER = 257,
OC_KEY_INSERT = 260, OC_KEY_TAB = 258,
OC_KEY_DELETE = 261, OC_KEY_BACKSPACE = 259,
OC_KEY_RIGHT = 262, OC_KEY_INSERT = 260,
OC_KEY_LEFT = 263, OC_KEY_DELETE = 261,
OC_KEY_DOWN = 264, OC_KEY_RIGHT = 262,
OC_KEY_UP = 265, OC_KEY_LEFT = 263,
OC_KEY_PAGE_UP = 266, OC_KEY_DOWN = 264,
OC_KEY_PAGE_DOWN = 267, OC_KEY_UP = 265,
OC_KEY_HOME = 268, OC_KEY_PAGE_UP = 266,
OC_KEY_END = 269, OC_KEY_PAGE_DOWN = 267,
OC_KEY_CAPS_LOCK = 280, OC_KEY_HOME = 268,
OC_KEY_SCROLL_LOCK = 281, OC_KEY_END = 269,
OC_KEY_NUM_LOCK = 282, OC_KEY_CAPS_LOCK = 280,
OC_KEY_PRINT_SCREEN = 283, OC_KEY_SCROLL_LOCK = 281,
OC_KEY_PAUSE = 284, OC_KEY_NUM_LOCK = 282,
OC_KEY_F1 = 290, OC_KEY_PRINT_SCREEN = 283,
OC_KEY_F2 = 291, OC_KEY_PAUSE = 284,
OC_KEY_F3 = 292, OC_KEY_F1 = 290,
OC_KEY_F4 = 293, OC_KEY_F2 = 291,
OC_KEY_F5 = 294, OC_KEY_F3 = 292,
OC_KEY_F6 = 295, OC_KEY_F4 = 293,
OC_KEY_F7 = 296, OC_KEY_F5 = 294,
OC_KEY_F8 = 297, OC_KEY_F6 = 295,
OC_KEY_F9 = 298, OC_KEY_F7 = 296,
OC_KEY_F10 = 299, OC_KEY_F8 = 297,
OC_KEY_F11 = 300, OC_KEY_F9 = 298,
OC_KEY_F12 = 301, OC_KEY_F10 = 299,
OC_KEY_F13 = 302, OC_KEY_F11 = 300,
OC_KEY_F14 = 303, OC_KEY_F12 = 301,
OC_KEY_F15 = 304, OC_KEY_F13 = 302,
OC_KEY_F16 = 305, OC_KEY_F14 = 303,
OC_KEY_F17 = 306, OC_KEY_F15 = 304,
OC_KEY_F18 = 307, OC_KEY_F16 = 305,
OC_KEY_F19 = 308, OC_KEY_F17 = 306,
OC_KEY_F20 = 309, OC_KEY_F18 = 307,
OC_KEY_F21 = 310, OC_KEY_F19 = 308,
OC_KEY_F22 = 311, OC_KEY_F20 = 309,
OC_KEY_F23 = 312, OC_KEY_F21 = 310,
OC_KEY_F24 = 313, OC_KEY_F22 = 311,
OC_KEY_F25 = 314, OC_KEY_F23 = 312,
OC_KEY_KP_0 = 320, OC_KEY_F24 = 313,
OC_KEY_KP_1 = 321, OC_KEY_F25 = 314,
OC_KEY_KP_2 = 322, OC_KEY_KP_0 = 320,
OC_KEY_KP_3 = 323, OC_KEY_KP_1 = 321,
OC_KEY_KP_4 = 324, OC_KEY_KP_2 = 322,
OC_KEY_KP_5 = 325, OC_KEY_KP_3 = 323,
OC_KEY_KP_6 = 326, OC_KEY_KP_4 = 324,
OC_KEY_KP_7 = 327, OC_KEY_KP_5 = 325,
OC_KEY_KP_8 = 328, OC_KEY_KP_6 = 326,
OC_KEY_KP_9 = 329, OC_KEY_KP_7 = 327,
OC_KEY_KP_DECIMAL = 330, OC_KEY_KP_8 = 328,
OC_KEY_KP_DIVIDE = 331, OC_KEY_KP_9 = 329,
OC_KEY_KP_MULTIPLY = 332, OC_KEY_KP_DECIMAL = 330,
OC_KEY_KP_SUBTRACT = 333, OC_KEY_KP_DIVIDE = 331,
OC_KEY_KP_ADD = 334, OC_KEY_KP_MULTIPLY = 332,
OC_KEY_KP_ENTER = 335, OC_KEY_KP_SUBTRACT = 333,
OC_KEY_KP_EQUAL = 336, OC_KEY_KP_ADD = 334,
OC_KEY_LEFT_SHIFT = 340, OC_KEY_KP_ENTER = 335,
OC_KEY_LEFT_CONTROL = 341, OC_KEY_KP_EQUAL = 336,
OC_KEY_LEFT_ALT = 342, OC_KEY_LEFT_SHIFT = 340,
OC_KEY_LEFT_SUPER = 343, OC_KEY_LEFT_CONTROL = 341,
OC_KEY_RIGHT_SHIFT = 344, OC_KEY_LEFT_ALT = 342,
OC_KEY_RIGHT_CONTROL = 345, OC_KEY_LEFT_SUPER = 343,
OC_KEY_RIGHT_ALT = 346, OC_KEY_RIGHT_SHIFT = 344,
OC_KEY_RIGHT_SUPER = 347, OC_KEY_RIGHT_CONTROL = 345,
OC_KEY_MENU = 348, OC_KEY_RIGHT_ALT = 346,
OC_KEY_COUNT } oc_key_code; OC_KEY_RIGHT_SUPER = 347,
OC_KEY_MENU = 348,
OC_KEY_COUNT
} oc_key_code;
typedef enum { typedef enum
OC_KEYMOD_NONE = 0x00, {
OC_KEYMOD_ALT = 0x01, OC_KEYMOD_NONE = 0x00,
OC_KEYMOD_SHIFT = 0x02, OC_KEYMOD_ALT = 0x01,
OC_KEYMOD_CTRL = 0x04, OC_KEYMOD_SHIFT = 0x02,
OC_KEYMOD_CMD = 0x08, OC_KEYMOD_CTRL = 0x04,
OC_KEYMOD_MAIN_MODIFIER = 0x16 /* CMD on Mac, CTRL on Win32 */ } oc_keymod_flags; OC_KEYMOD_CMD = 0x08,
OC_KEYMOD_MAIN_MODIFIER = 0x16 /* CMD on Mac, CTRL on Win32 */
} oc_keymod_flags;
typedef enum { typedef enum
OC_MOUSE_LEFT = 0x00, {
OC_MOUSE_RIGHT = 0x01, OC_MOUSE_LEFT = 0x00,
OC_MOUSE_MIDDLE = 0x02, OC_MOUSE_RIGHT = 0x01,
OC_MOUSE_EXT1 = 0x03, OC_MOUSE_MIDDLE = 0x02,
OC_MOUSE_EXT2 = 0x04, OC_MOUSE_EXT1 = 0x03,
OC_MOUSE_BUTTON_COUNT } oc_mouse_button; OC_MOUSE_EXT2 = 0x04,
OC_MOUSE_BUTTON_COUNT
} oc_mouse_button;
typedef struct oc_key_event // keyboard and mouse buttons input typedef struct oc_key_event // keyboard and mouse buttons input
{ {
oc_key_action action; oc_key_action action;
i32 code; i32 code;
oc_keymod_flags mods; oc_keymod_flags mods;
char label[8]; char label[8];
u8 labelLen; u8 labelLen;
int clickCount; int clickCount;
} oc_key_event; } oc_key_event;
typedef struct oc_char_event // character input typedef struct oc_char_event // character input
{ {
oc_utf32 codepoint; oc_utf32 codepoint;
char sequence[8]; char sequence[8];
u8 seqLen; u8 seqLen;
} oc_char_event; } oc_char_event;
typedef struct oc_mouse_event // mouse move/scroll typedef struct oc_mouse_event // mouse move/scroll
{ {
f32 x; f32 x;
f32 y; f32 y;
f32 deltaX; f32 deltaX;
f32 deltaY; f32 deltaY;
oc_keymod_flags mods; oc_keymod_flags mods;
} oc_mouse_event; } oc_mouse_event;
typedef struct oc_move_event // window resize / move typedef struct oc_move_event // window resize / move
{ {
oc_rect frame; oc_rect frame;
oc_rect content; oc_rect content;
} oc_move_event; } oc_move_event;
typedef struct oc_event typedef struct oc_event
{ {
//TODO clipboard and path drop //TODO clipboard and path drop
oc_window window; oc_window window;
oc_event_type type; oc_event_type type;
union union
{ {
oc_key_event key; oc_key_event key;
oc_char_event character; oc_char_event character;
oc_mouse_event mouse; oc_mouse_event mouse;
oc_move_event move; oc_move_event move;
oc_str8_list paths; oc_str8_list paths;
}; };
} oc_event; } oc_event;
//NOTE: these APIs are not directly available to Orca apps //NOTE: these APIs are not directly available to Orca apps
#if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA) #if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// app management // app management
//-------------------------------------------------------------------- //--------------------------------------------------------------------
ORCA_API void oc_init(void); ORCA_API void oc_init(void);
ORCA_API void oc_terminate(void); ORCA_API void oc_terminate(void);
ORCA_API bool oc_should_quit(void); ORCA_API bool oc_should_quit(void);
ORCA_API void oc_cancel_quit(void); ORCA_API void oc_cancel_quit(void);
ORCA_API void oc_request_quit(void); ORCA_API void oc_request_quit(void);
ORCA_API void oc_set_cursor(oc_mouse_cursor cursor); ORCA_API void oc_set_cursor(oc_mouse_cursor cursor);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Main loop and events handling // Main loop and events handling
//-------------------------------------------------------------------- //--------------------------------------------------------------------
/*NOTE: /*NOTE:
oc_pump_events() pumps system events into the event queue. A timeout of 0 polls for events, oc_pump_events() pumps system events into the event queue. A timeout of 0 polls for events,
while a timeout of -1 blocks for events. A timeout > 0 blocks until new events are available while a timeout of -1 blocks for events. A timeout > 0 blocks until new events are available
or the timeout elapses. or the timeout elapses.
oc_next_event() get the next event from the event queue, allocating from the passed arena oc_next_event() get the next event from the event queue, allocating from the passed arena
*/ */
ORCA_API void oc_pump_events(f64 timeout); ORCA_API void oc_pump_events(f64 timeout);
ORCA_API oc_event* oc_next_event(oc_arena* arena); ORCA_API oc_event* oc_next_event(oc_arena* arena);
typedef void(*oc_live_resize_callback)(oc_event event, void* data); typedef void (*oc_live_resize_callback)(oc_event event, void* data);
ORCA_API void oc_set_live_resize_callback(oc_live_resize_callback callback, void* data); ORCA_API void oc_set_live_resize_callback(oc_live_resize_callback callback, void* data);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// window management // window management
//-------------------------------------------------------------------- //--------------------------------------------------------------------
ORCA_API bool oc_window_handle_is_null(oc_window window); ORCA_API bool oc_window_handle_is_null(oc_window window);
ORCA_API oc_window oc_window_null_handle(void); ORCA_API oc_window oc_window_null_handle(void);
ORCA_API oc_window oc_window_create(oc_rect contentRect, oc_str8 title, oc_window_style style); ORCA_API oc_window oc_window_create(oc_rect contentRect, oc_str8 title, oc_window_style style);
ORCA_API void oc_window_destroy(oc_window window); ORCA_API void oc_window_destroy(oc_window window);
ORCA_API void* oc_window_native_pointer(oc_window window); ORCA_API void* oc_window_native_pointer(oc_window window);
ORCA_API bool oc_window_should_close(oc_window window); ORCA_API bool oc_window_should_close(oc_window window);
ORCA_API void oc_window_request_close(oc_window window); ORCA_API void oc_window_request_close(oc_window window);
ORCA_API void oc_window_cancel_close(oc_window window); ORCA_API void oc_window_cancel_close(oc_window window);
ORCA_API bool oc_window_is_hidden(oc_window window); ORCA_API bool oc_window_is_hidden(oc_window window);
ORCA_API void oc_window_hide(oc_window window); ORCA_API void oc_window_hide(oc_window window);
ORCA_API void oc_window_show(oc_window window); ORCA_API void oc_window_show(oc_window window);
ORCA_API bool oc_window_is_minimized(oc_window window); ORCA_API bool oc_window_is_minimized(oc_window window);
ORCA_API bool oc_window_is_maximized(oc_window window); ORCA_API bool oc_window_is_maximized(oc_window window);
ORCA_API void oc_window_minimize(oc_window window); ORCA_API void oc_window_minimize(oc_window window);
ORCA_API void oc_window_maximize(oc_window window); ORCA_API void oc_window_maximize(oc_window window);
ORCA_API void oc_window_restore(oc_window window); ORCA_API void oc_window_restore(oc_window window);
ORCA_API bool oc_window_has_focus(oc_window window); ORCA_API bool oc_window_has_focus(oc_window window);
ORCA_API void oc_window_focus(oc_window window); ORCA_API void oc_window_focus(oc_window window);
ORCA_API void oc_window_unfocus(oc_window window); ORCA_API void oc_window_unfocus(oc_window window);
ORCA_API void oc_window_send_to_back(oc_window window); ORCA_API void oc_window_send_to_back(oc_window window);
ORCA_API void oc_window_bring_to_front(oc_window window); ORCA_API void oc_window_bring_to_front(oc_window window);
ORCA_API oc_rect oc_window_get_frame_rect(oc_window window); ORCA_API oc_rect oc_window_get_frame_rect(oc_window window);
ORCA_API void oc_window_set_frame_rect(oc_window window, oc_rect rect); ORCA_API void oc_window_set_frame_rect(oc_window window, oc_rect rect);
ORCA_API void oc_window_set_frame_position(oc_window window, oc_vec2 position); ORCA_API void oc_window_set_frame_position(oc_window window, oc_vec2 position);
ORCA_API void oc_window_set_frame_size(oc_window window, oc_vec2 size); ORCA_API void oc_window_set_frame_size(oc_window window, oc_vec2 size);
ORCA_API oc_rect oc_window_get_content_rect(oc_window window); ORCA_API oc_rect oc_window_get_content_rect(oc_window window);
ORCA_API void oc_window_set_content_rect(oc_window window, oc_rect rect); ORCA_API void oc_window_set_content_rect(oc_window window, oc_rect rect);
ORCA_API void oc_window_set_content_position(oc_window window, oc_vec2 position); ORCA_API void oc_window_set_content_position(oc_window window, oc_vec2 position);
ORCA_API void oc_window_set_content_size(oc_window window, oc_vec2 size); ORCA_API void oc_window_set_content_size(oc_window window, oc_vec2 size);
ORCA_API void oc_window_center(oc_window window); ORCA_API void oc_window_center(oc_window window);
ORCA_API oc_rect oc_window_content_rect_for_frame_rect(oc_rect frameRect, oc_window_style style); ORCA_API oc_rect oc_window_content_rect_for_frame_rect(oc_rect frameRect, oc_window_style style);
ORCA_API oc_rect oc_window_frame_rect_for_content_rect(oc_rect contentRect, oc_window_style style); ORCA_API oc_rect oc_window_frame_rect_for_content_rect(oc_rect contentRect, oc_window_style style);
//--------------------------------------------------------------- //---------------------------------------------------------------
// Dispatching stuff to the main thread // Dispatching stuff to the main thread
//--------------------------------------------------------------- //---------------------------------------------------------------
typedef i32 (*oc_dispatch_proc)(void* user); typedef i32 (*oc_dispatch_proc)(void* user);
ORCA_API i32 oc_dispatch_on_main_thread_sync(oc_window main_window, oc_dispatch_proc proc, void* user); ORCA_API i32 oc_dispatch_on_main_thread_sync(oc_window main_window, oc_dispatch_proc proc, void* user);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Clipboard // Clipboard
//-------------------------------------------------------------------- //--------------------------------------------------------------------
ORCA_API void oc_clipboard_clear(void); ORCA_API void oc_clipboard_clear(void);
ORCA_API void oc_clipboard_set_string(oc_str8 string); ORCA_API void oc_clipboard_set_string(oc_str8 string);
ORCA_API oc_str8 oc_clipboard_get_string(oc_arena* arena); ORCA_API oc_str8 oc_clipboard_get_string(oc_arena* arena);
ORCA_API oc_str8 oc_clipboard_copy_string(oc_str8 backing); ORCA_API oc_str8 oc_clipboard_copy_string(oc_str8 backing);
ORCA_API bool oc_clipboard_has_tag(const char* tag); ORCA_API bool oc_clipboard_has_tag(const char* tag);
ORCA_API void oc_clipboard_set_data_for_tag(const char* tag, oc_str8 data); ORCA_API void oc_clipboard_set_data_for_tag(const char* tag, oc_str8 data);
ORCA_API oc_str8 oc_clipboard_get_data_for_tag(oc_arena* arena, const char* tag); ORCA_API oc_str8 oc_clipboard_get_data_for_tag(oc_arena* arena, const char* tag);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// native open/save/alert windows // native open/save/alert windows
//-------------------------------------------------------------------- //--------------------------------------------------------------------
ORCA_API oc_str8 oc_open_dialog(oc_arena* arena, ORCA_API oc_str8 oc_open_dialog(oc_arena* arena,
oc_str8 title, oc_str8 title,
oc_str8 defaultPath, oc_str8 defaultPath,
oc_str8_list filters, oc_str8_list filters,
bool directory); bool directory);
ORCA_API oc_str8 oc_save_dialog(oc_arena* arena, ORCA_API oc_str8 oc_save_dialog(oc_arena* arena,
oc_str8 title, oc_str8 title,
oc_str8 defaultPath, oc_str8 defaultPath,
oc_str8_list filters); oc_str8_list filters);
ORCA_API int oc_alert_popup(oc_str8 title, ORCA_API int oc_alert_popup(oc_str8 title,
oc_str8 message, oc_str8 message,
oc_str8_list options); oc_str8_list options);
//--------------------------------------------------------------------
// file system stuff... //TODO: move elsewhere
//--------------------------------------------------------------------
ORCA_API int oc_file_move(oc_str8 from, oc_str8 to);
ORCA_API int oc_file_remove(oc_str8 path);
//-------------------------------------------------------------------- ORCA_API int oc_directory_create(oc_str8 path);
// file system stuff... //TODO: move elsewhere
//--------------------------------------------------------------------
ORCA_API int oc_file_move(oc_str8 from, oc_str8 to);
ORCA_API int oc_file_remove(oc_str8 path);
ORCA_API int oc_directory_create(oc_str8 path);
#endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA) #endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
@ -388,5 +406,4 @@ ORCA_API int oc_directory_create(oc_str8 path);
} // extern "C" } // extern "C"
#endif #endif
#endif //__APP_H_ #endif //__APP_H_

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: app_internal.h * @file: app_internal.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -9,17 +9,17 @@
#ifndef __APP_INTERNAL_H_ #ifndef __APP_INTERNAL_H_
#define __APP_INTERNAL_H_ #define __APP_INTERNAL_H_
#include"app.h" #include "app.h"
#include"platform/platform.h" #include "platform/platform.h"
#include"util/ringbuffer.h" #include "util/ringbuffer.h"
#if OC_PLATFORM_WINDOWS #if OC_PLATFORM_WINDOWS
#include"win32_app.h" #include "win32_app.h"
#elif OC_PLATFORM_MACOS #elif OC_PLATFORM_MACOS
#include"osx_app.h" #include "osx_app.h"
#else #else
#error "platform not supported yet" #error "platform not supported yet"
#endif #endif
//--------------------------------------------------------------- //---------------------------------------------------------------
@ -28,64 +28,65 @@
typedef struct oc_frame_stats typedef struct oc_frame_stats
{ {
f64 start; f64 start;
f64 workTime; f64 workTime;
f64 remainingTime; f64 remainingTime;
f64 targetFramePeriod; f64 targetFramePeriod;
} oc_frame_stats; } oc_frame_stats;
typedef struct oc_window_data typedef struct oc_window_data
{ {
oc_list_elt freeListElt; oc_list_elt freeListElt;
u32 generation; u32 generation;
oc_window_style style; oc_window_style style;
bool shouldClose; //TODO could be in status flags bool shouldClose; //TODO could be in status flags
bool hidden; bool hidden;
bool minimized; bool minimized;
OC_PLATFORM_WINDOW_DATA OC_PLATFORM_WINDOW_DATA
} oc_window_data; } oc_window_data;
//--------------------------------------------------------------- //---------------------------------------------------------------
// Global App State // Global App State
//--------------------------------------------------------------- //---------------------------------------------------------------
typedef struct oc_key_utf8 typedef struct oc_key_utf8
{ {
u8 labelLen; u8 labelLen;
char label[8]; char label[8];
} oc_key_utf8; } oc_key_utf8;
enum
enum { OC_APP_MAX_WINDOWS = 128 }; {
OC_APP_MAX_WINDOWS = 128
};
typedef struct oc_app typedef struct oc_app
{ {
bool init; bool init;
bool shouldQuit; bool shouldQuit;
bool minimized; bool minimized;
oc_str8 pendingPathDrop; oc_str8 pendingPathDrop;
oc_arena eventArena; oc_arena eventArena;
oc_ringbuffer eventQueue; oc_ringbuffer eventQueue;
oc_frame_stats frameStats; oc_frame_stats frameStats;
oc_window_data windowPool[OC_APP_MAX_WINDOWS]; oc_window_data windowPool[OC_APP_MAX_WINDOWS];
oc_list windowFreeList; oc_list windowFreeList;
oc_live_resize_callback liveResizeCallback; oc_live_resize_callback liveResizeCallback;
void* liveResizeData; void* liveResizeData;
oc_key_utf8 keyLabels[512]; oc_key_utf8 keyLabels[512];
int keyCodes[512]; int keyCodes[512];
int nativeKeys[OC_KEY_COUNT]; int nativeKeys[OC_KEY_COUNT];
OC_PLATFORM_APP_DATA OC_PLATFORM_APP_DATA
} oc_app; } oc_app;
#endif // __APP_INTERNAL_H_ #endif // __APP_INTERNAL_H_

View File

@ -1,4 +1,4 @@
#include"orca.h" #include "orca.h"
//This is used to pass raw events from the runtime //This is used to pass raw events from the runtime
ORCA_EXPORT oc_event oc_rawEvent; ORCA_EXPORT oc_event oc_rawEvent;

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: osx_app.h * @file: osx_app.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -9,28 +9,28 @@
#ifndef __OSX_APP_H_ #ifndef __OSX_APP_H_
#define __OSX_APP_H_ #define __OSX_APP_H_
#include"app.h" #include "app.h"
#include"graphics/graphics.h" #include "graphics/graphics.h"
#ifdef __OBJC__ #ifdef __OBJC__
#import<Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#else #else
#define NSWindow void #define NSWindow void
#define NSView void #define NSView void
#define NSObject void #define NSObject void
#define NSTimer void #define NSTimer void
#define NSCursor void #define NSCursor void
#define CALayer void #define CALayer void
#define CAContext void #define CAContext void
#endif #endif
#include<Carbon/Carbon.h> #include <Carbon/Carbon.h>
typedef struct oc_osx_window_data typedef struct oc_osx_window_data
{ {
NSWindow* nsWindow; NSWindow* nsWindow;
NSView* nsView; NSView* nsView;
NSObject* nsWindowDelegate; NSObject* nsWindowDelegate;
} oc_osx_window_data; } oc_osx_window_data;
@ -40,12 +40,12 @@ const u32 OC_APP_MAX_VIEWS = 128;
typedef struct oc_osx_app_data typedef struct oc_osx_app_data
{ {
NSTimer* frameTimer; NSTimer* frameTimer;
NSCursor* cursor; NSCursor* cursor;
TISInputSourceRef kbLayoutInputSource; TISInputSourceRef kbLayoutInputSource;
void* kbLayoutUnicodeData; void* kbLayoutUnicodeData;
id kbLayoutListener; id kbLayoutListener;
} oc_osx_app_data; } oc_osx_app_data;
@ -55,33 +55,31 @@ typedef struct oc_osx_app_data
// Surface layer // Surface layer
//----------------------------------------------- //-----------------------------------------------
#ifdef __OBJC__ #ifdef __OBJC__
//NOTE: these private interfaces for surface sharing need to be declared explicitly here //NOTE: these private interfaces for surface sharing need to be declared explicitly here
typedef uint32_t CGSConnectionID; typedef uint32_t CGSConnectionID;
CGSConnectionID CGSMainConnectionID(void); CGSConnectionID CGSMainConnectionID(void);
typedef uint32_t CAContextID; typedef uint32_t CAContextID;
@interface CAContext : NSObject @interface CAContext : NSObject
{ {
} }
+ (id)contextWithCGSConnection:(CAContextID)contextId options:(NSDictionary*)optionsDict; + (id)contextWithCGSConnection:(CAContextID)contextId options:(NSDictionary*)optionsDict;
@property(readonly) CAContextID contextId; @property(readonly) CAContextID contextId;
@property(retain) CALayer *layer; @property(retain) CALayer* layer;
@end @end
@interface CALayerHost : CALayer @interface CALayerHost : CALayer
{ {
} }
@property CAContextID contextId; @property CAContextID contextId;
@end @end
#endif #endif
typedef struct oc_layer typedef struct oc_layer
{ {
CALayer* caLayer; CALayer* caLayer;
CAContext* caContext; CAContext* caContext;
} oc_layer; } oc_layer;
#endif //__OSX_APP_H_ #endif //__OSX_APP_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -10,37 +10,37 @@
#ifndef __WIN32_APP_H_ #ifndef __WIN32_APP_H_
#define __WIN32_APP_H_ #define __WIN32_APP_H_
#include"app.h" #include "app.h"
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define UNICODE #define UNICODE
#include<windows.h> #include <windows.h>
typedef struct oc_win32_window_data typedef struct oc_win32_window_data
{ {
HWND hWnd; HWND hWnd;
oc_list layers; oc_list layers;
} oc_win32_window_data; } oc_win32_window_data;
typedef struct oc_window_data oc_window_data; typedef struct oc_window_data oc_window_data;
typedef struct oc_layer typedef struct oc_layer
{ {
oc_window_data* parent; oc_window_data* parent;
oc_list_elt listElt; oc_list_elt listElt;
HWND hWnd; HWND hWnd;
} oc_layer; } oc_layer;
#define OC_PLATFORM_WINDOW_DATA oc_win32_window_data win32; #define OC_PLATFORM_WINDOW_DATA oc_win32_window_data win32;
typedef struct oc_win32_app_data typedef struct oc_win32_app_data
{ {
u32 savedConsoleCodePage; u32 savedConsoleCodePage;
int mouseCaptureMask; int mouseCaptureMask;
bool mouseTracked; bool mouseTracked;
oc_vec2 lastMousePos; oc_vec2 lastMousePos;
u32 wheelScrollLines; u32 wheelScrollLines;
} oc_win32_app_data; } oc_win32_app_data;
@ -48,7 +48,7 @@ typedef struct oc_win32_app_data
enum OC_WM_USER enum OC_WM_USER
{ {
OC_WM_USER_DISPATCH_PROC = 0x0400, // WM_USER messages are defined from 0x400 to 0x7FFF OC_WM_USER_DISPATCH_PROC = 0x0400, // WM_USER messages are defined from 0x400 to 0x7FFF
}; };
#endif __WIN32_APP_H_ #endif __WIN32_APP_H_

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: egl_surface.cpp * @file: egl_surface.cpp
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -8,176 +8,178 @@
*****************************************************************/ *****************************************************************/
#define EGL_EGLEXT_PROTOTYPES #define EGL_EGLEXT_PROTOTYPES
#include<EGL/egl.h> #include "app/app_internal.h"
#include<EGL/eglext.h> #include "gl_loader.h"
#include"app/app_internal.h" #include "graphics_surface.h"
#include"graphics_surface.h" #include <EGL/egl.h>
#include"gl_loader.h" #include <EGL/eglext.h>
#if OC_PLATFORM_MACOS #if OC_PLATFORM_MACOS
//NOTE: EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE on osx defaults to CGL backend, which doesn't handle SwapInterval correctly //NOTE: EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE on osx defaults to CGL backend, which doesn't handle SwapInterval correctly
#define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE #define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE
//NOTE: hardcode GLES versions for now //NOTE: hardcode GLES versions for now
//TODO: use version hints, once we have all api versions correctly categorized by glapi.py //TODO: use version hints, once we have all api versions correctly categorized by glapi.py
#define OC_GLES_VERSION_MAJOR 3 #define OC_GLES_VERSION_MAJOR 3
#define OC_GLES_VERSION_MINOR 0 #define OC_GLES_VERSION_MINOR 0
#define oc_gl_load_gles oc_gl_load_gles31 #define oc_gl_load_gles oc_gl_load_gles31
#else #else
#define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE #define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
#define OC_GLES_VERSION_MAJOR 3 #define OC_GLES_VERSION_MAJOR 3
#define OC_GLES_VERSION_MINOR 1 #define OC_GLES_VERSION_MINOR 1
#define oc_gl_load_gles oc_gl_load_gles32 #define oc_gl_load_gles oc_gl_load_gles32
#endif #endif
typedef struct oc_egl_surface typedef struct oc_egl_surface
{ {
oc_surface_data interface; oc_surface_data interface;
EGLDisplay eglDisplay; EGLDisplay eglDisplay;
EGLConfig eglConfig; EGLConfig eglConfig;
EGLContext eglContext; EGLContext eglContext;
EGLSurface eglSurface; EGLSurface eglSurface;
oc_gl_api api; oc_gl_api api;
} oc_egl_surface; } oc_egl_surface;
void oc_egl_surface_destroy(oc_surface_data* interface) void oc_egl_surface_destroy(oc_surface_data* interface)
{ {
oc_egl_surface* surface = (oc_egl_surface*)interface; oc_egl_surface* surface = (oc_egl_surface*)interface;
if(&surface->api == oc_gl_get_api()) if(&surface->api == oc_gl_get_api())
{ {
oc_gl_deselect_api(); oc_gl_deselect_api();
} }
if(eglGetCurrentContext() == surface->eglContext) if(eglGetCurrentContext() == surface->eglContext)
{ {
eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
} }
eglDestroyContext(surface->eglDisplay, surface->eglContext); eglDestroyContext(surface->eglDisplay, surface->eglContext);
eglDestroySurface(surface->eglDisplay, surface->eglSurface); eglDestroySurface(surface->eglDisplay, surface->eglSurface);
oc_surface_cleanup((oc_surface_data*)surface); oc_surface_cleanup((oc_surface_data*)surface);
free(surface); free(surface);
} }
void oc_egl_surface_prepare(oc_surface_data* interface) void oc_egl_surface_prepare(oc_surface_data* interface)
{ {
oc_egl_surface* surface = (oc_egl_surface*)interface; oc_egl_surface* surface = (oc_egl_surface*)interface;
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext); eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
oc_gl_select_api(&surface->api); oc_gl_select_api(&surface->api);
} }
void oc_egl_surface_present(oc_surface_data* interface) void oc_egl_surface_present(oc_surface_data* interface)
{ {
oc_egl_surface* surface = (oc_egl_surface*)interface; oc_egl_surface* surface = (oc_egl_surface*)interface;
eglSwapBuffers(surface->eglDisplay, surface->eglSurface); eglSwapBuffers(surface->eglDisplay, surface->eglSurface);
} }
void oc_egl_surface_deselect(oc_surface_data* interface) void oc_egl_surface_deselect(oc_surface_data* interface)
{ {
oc_egl_surface* surface = (oc_egl_surface*)interface; oc_egl_surface* surface = (oc_egl_surface*)interface;
eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
oc_gl_deselect_api(); oc_gl_deselect_api();
} }
void oc_egl_surface_swap_interval(oc_surface_data* interface, int swap) void oc_egl_surface_swap_interval(oc_surface_data* interface, int swap)
{ {
oc_egl_surface* surface = (oc_egl_surface*)interface; oc_egl_surface* surface = (oc_egl_surface*)interface;
eglSwapInterval(surface->eglDisplay, swap); eglSwapInterval(surface->eglDisplay, swap);
} }
void oc_egl_surface_init(oc_egl_surface* surface) void oc_egl_surface_init(oc_egl_surface* surface)
{ {
void* nativeLayer = surface->interface.nativeLayer((oc_surface_data*)surface); void* nativeLayer = surface->interface.nativeLayer((oc_surface_data*)surface);
surface->interface.api = OC_GLES; surface->interface.api = OC_GLES;
surface->interface.destroy = oc_egl_surface_destroy; surface->interface.destroy = oc_egl_surface_destroy;
surface->interface.prepare = oc_egl_surface_prepare; surface->interface.prepare = oc_egl_surface_prepare;
surface->interface.present = oc_egl_surface_present; surface->interface.present = oc_egl_surface_present;
surface->interface.deselect = oc_egl_surface_deselect; surface->interface.deselect = oc_egl_surface_deselect;
surface->interface.swapInterval = oc_egl_surface_swap_interval; surface->interface.swapInterval = oc_egl_surface_swap_interval;
EGLAttrib displayAttribs[] = { EGLAttrib displayAttribs[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE, OC_EGL_PLATFORM_ANGLE_TYPE, EGL_PLATFORM_ANGLE_TYPE_ANGLE, OC_EGL_PLATFORM_ANGLE_TYPE,
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
EGL_NONE}; EGL_NONE
};
surface->eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, (void*)EGL_DEFAULT_DISPLAY, displayAttribs); surface->eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, (void*)EGL_DEFAULT_DISPLAY, displayAttribs);
eglInitialize(surface->eglDisplay, NULL, NULL); eglInitialize(surface->eglDisplay, NULL, NULL);
EGLint const configAttributes[] = { EGLint const configAttributes[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8, EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8, EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 24, EGL_DEPTH_SIZE, 24,
EGL_STENCIL_SIZE, 8, EGL_STENCIL_SIZE, 8,
EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLE_BUFFERS, 0,
EGL_SAMPLES, EGL_DONT_CARE, EGL_SAMPLES, EGL_DONT_CARE,
EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT, EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
EGL_NONE }; EGL_NONE
};
int numConfigs = 0; int numConfigs = 0;
eglChooseConfig(surface->eglDisplay, configAttributes, &surface->eglConfig, 1, &numConfigs); eglChooseConfig(surface->eglDisplay, configAttributes, &surface->eglConfig, 1, &numConfigs);
EGLint const surfaceAttributes[] = {EGL_NONE}; EGLint const surfaceAttributes[] = { EGL_NONE };
surface->eglSurface = eglCreateWindowSurface(surface->eglDisplay, surface->eglSurface = eglCreateWindowSurface(surface->eglDisplay,
surface->eglConfig, surface->eglConfig,
nativeLayer, nativeLayer,
surfaceAttributes); surfaceAttributes);
eglBindAPI(EGL_OPENGL_ES_API); eglBindAPI(EGL_OPENGL_ES_API);
EGLint contextAttributes[] = { EGLint contextAttributes[] = {
EGL_CONTEXT_MAJOR_VERSION_KHR, OC_GLES_VERSION_MAJOR, EGL_CONTEXT_MAJOR_VERSION_KHR, OC_GLES_VERSION_MAJOR,
EGL_CONTEXT_MINOR_VERSION_KHR, OC_GLES_VERSION_MINOR, EGL_CONTEXT_MINOR_VERSION_KHR, OC_GLES_VERSION_MINOR,
EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE, EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE,
EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE, EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE,
EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE, EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE,
EGL_NONE}; EGL_NONE
};
surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes); surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes);
eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext); eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext);
oc_gl_load_gles(&surface->api, (oc_gl_load_proc)eglGetProcAddress); oc_gl_load_gles(&surface->api, (oc_gl_load_proc)eglGetProcAddress);
eglSwapInterval(surface->eglDisplay, 1); eglSwapInterval(surface->eglDisplay, 1);
} }
oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height) oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height)
{ {
oc_egl_surface* surface = 0; oc_egl_surface* surface = 0;
surface = oc_malloc_type(oc_egl_surface); surface = oc_malloc_type(oc_egl_surface);
if(surface) if(surface)
{ {
memset(surface, 0, sizeof(oc_egl_surface)); memset(surface, 0, sizeof(oc_egl_surface));
oc_surface_init_remote((oc_surface_data*)surface, width, height); oc_surface_init_remote((oc_surface_data*)surface, width, height);
oc_egl_surface_init(surface); oc_egl_surface_init(surface);
} }
return((oc_surface_data*)surface); return ((oc_surface_data*)surface);
} }
oc_surface_data* oc_egl_surface_create_for_window(oc_window window) oc_surface_data* oc_egl_surface_create_for_window(oc_window window)
{ {
oc_egl_surface* surface = 0; oc_egl_surface* surface = 0;
oc_window_data* windowData = oc_window_ptr_from_handle(window); oc_window_data* windowData = oc_window_ptr_from_handle(window);
if(windowData) if(windowData)
{ {
surface = oc_malloc_type(oc_egl_surface); surface = oc_malloc_type(oc_egl_surface);
if(surface) if(surface)
{ {
memset(surface, 0, sizeof(oc_egl_surface)); memset(surface, 0, sizeof(oc_egl_surface));
oc_surface_init_for_window((oc_surface_data*)surface, windowData); oc_surface_init_for_window((oc_surface_data*)surface, windowData);
oc_egl_surface_init(surface); oc_egl_surface_init(surface);
} }
} }
return((oc_surface_data*)surface); return ((oc_surface_data*)surface);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: egl_surface.h * @file: egl_surface.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -9,8 +9,8 @@
#ifndef __EGL_SURFACE_H_ #ifndef __EGL_SURFACE_H_
#define __EGL_SURFACE_H_ #define __EGL_SURFACE_H_
#include"graphics_surface.h" #include "app/app.h"
#include"app/app.h" #include "graphics_surface.h"
oc_surface_data* oc_egl_surface_create_for_window(oc_window window); oc_surface_data* oc_egl_surface_create_for_window(oc_window window);
oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height); oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,9 +8,9 @@
#ifndef __GL_LOADER_H__ #ifndef __GL_LOADER_H__
#define __GL_LOADER_H__ #define __GL_LOADER_H__
#include"gl_api.h" #include "gl_api.h"
typedef void*(*oc_gl_load_proc)(const char* name); typedef void* (*oc_gl_load_proc)(const char* name);
void oc_gl_load_gl41(oc_gl_api* api, oc_gl_load_proc loadProc); void oc_gl_load_gl41(oc_gl_api* api, oc_gl_load_proc loadProc);
void oc_gl_load_gl43(oc_gl_api* api, oc_gl_load_proc loadProc); void oc_gl_load_gl43(oc_gl_api* api, oc_gl_load_proc loadProc);

View File

@ -6,13 +6,17 @@ layout(std430) buffer;
layout(binding = 0) restrict readonly buffer pathQueueBufferSSBO layout(binding = 0) restrict readonly buffer pathQueueBufferSSBO
{ {
oc_gl_path_queue elements[]; oc_gl_path_queue elements[];
} pathQueueBuffer; }
pathQueueBuffer;
layout(binding = 1) restrict buffer tileQueueBufferSSBO layout(binding = 1) restrict buffer tileQueueBufferSSBO
{ {
oc_gl_tile_queue elements[]; oc_gl_tile_queue elements[];
} tileQueueBuffer; }
tileQueueBuffer;
layout(location = 0) uniform int pathQueueBufferStart; layout(location = 0) uniform int pathQueueBufferStart;
@ -20,32 +24,32 @@ shared int nextRowIndex;
void main() void main()
{ {
int pathIndex = int(gl_WorkGroupID.x); int pathIndex = int(gl_WorkGroupID.x);
int localID = int(gl_LocalInvocationID.x); int localID = int(gl_LocalInvocationID.x);
if(localID == 0) if(localID == 0)
{ {
nextRowIndex = 0; nextRowIndex = 0;
} }
barrier(); barrier();
int rowIndex = 0; int rowIndex = 0;
oc_gl_path_queue pathQueue = pathQueueBuffer.elements[pathQueueBufferStart + pathIndex]; oc_gl_path_queue pathQueue = pathQueueBuffer.elements[pathQueueBufferStart + pathIndex];
int tileQueueBase = pathQueue.tileQueues; int tileQueueBase = pathQueue.tileQueues;
int rowSize = pathQueue.area.z; int rowSize = pathQueue.area.z;
int rowCount = pathQueue.area.w; int rowCount = pathQueue.area.w;
rowIndex = atomicAdd(nextRowIndex, 1); rowIndex = atomicAdd(nextRowIndex, 1);
while(rowIndex < rowCount) while(rowIndex < rowCount)
{ {
int sum = 0; int sum = 0;
for(int x = rowSize-1; x >= 0; x--) for(int x = rowSize - 1; x >= 0; x--)
{ {
int tileIndex = tileQueueBase + rowIndex * rowSize.x + x; int tileIndex = tileQueueBase + rowIndex * rowSize.x + x;
int offset = tileQueueBuffer.elements[tileIndex].windingOffset; int offset = tileQueueBuffer.elements[tileIndex].windingOffset;
tileQueueBuffer.elements[tileIndex].windingOffset = sum; tileQueueBuffer.elements[tileIndex].windingOffset = sum;
sum += offset; sum += offset;
} }
rowIndex = atomicAdd(nextRowIndex, 1); rowIndex = atomicAdd(nextRowIndex, 1);
} }
} }

View File

@ -6,22 +6,25 @@ layout(std430) buffer;
layout(binding = 0) coherent restrict readonly buffer screenTilesCountBufferSSBO layout(binding = 0) coherent restrict readonly buffer screenTilesCountBufferSSBO
{ {
int elements[]; int elements[];
} screenTilesCountBuffer; }
screenTilesCountBuffer;
layout(binding = 1) coherent restrict writeonly buffer dispatchBufferSSBO layout(binding = 1) coherent restrict writeonly buffer dispatchBufferSSBO
{ {
oc_gl_dispatch_indirect_command elements[]; oc_gl_dispatch_indirect_command elements[];
} dispatchBuffer; }
dispatchBuffer;
layout(location = 0) uniform uint maxWorkGroupCount; layout(location = 0) uniform uint maxWorkGroupCount;
void main() void main()
{ {
uint totalWorkGroupCount = screenTilesCountBuffer.elements[0]; uint totalWorkGroupCount = screenTilesCountBuffer.elements[0];
dispatchBuffer.elements[0].num_groups_x = totalWorkGroupCount > maxWorkGroupCount ? maxWorkGroupCount : totalWorkGroupCount; dispatchBuffer.elements[0].num_groups_x = totalWorkGroupCount > maxWorkGroupCount ? maxWorkGroupCount : totalWorkGroupCount;
dispatchBuffer.elements[0].num_groups_y = (totalWorkGroupCount + maxWorkGroupCount - 1) / maxWorkGroupCount; dispatchBuffer.elements[0].num_groups_y = (totalWorkGroupCount + maxWorkGroupCount - 1) / maxWorkGroupCount;
dispatchBuffer.elements[0].num_groups_z = 1; dispatchBuffer.elements[0].num_groups_z = 1;
} }

View File

@ -4,9 +4,9 @@ precision mediump float;
in vec2 uv; in vec2 uv;
out vec4 fragColor; out vec4 fragColor;
layout(location=0) uniform sampler2D tex; layout(location = 0) uniform sampler2D tex;
void main() void main()
{ {
fragColor = texture(tex, uv); fragColor = texture(tex, uv);
} }

View File

@ -5,11 +5,11 @@ out vec2 uv;
void main() void main()
{ {
/* generate (0, 0) (1, 0) (1, 1) (1, 1) (0, 1) (0, 0)*/ /* generate (0, 0) (1, 0) (1, 1) (1, 1) (0, 1) (0, 0)*/
float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u); float x = float(((uint(gl_VertexID) + 2u) / 3u) % 2u);
float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u); float y = float(((uint(gl_VertexID) + 1u) / 3u) % 2u);
gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f); gl_Position = vec4(-1.0f + x * 2.0f, -1.0f + y * 2.0f, 0.0f, 1.0f);
uv = vec2(x, 1-y); uv = vec2(x, 1 - y);
} }

View File

@ -11,17 +11,17 @@ layout(std430) buffer;
#define OC_GL_CUBIC 3 #define OC_GL_CUBIC 3
// curve config // curve config
#define OC_GL_BL 1 /* curve on bottom left */ #define OC_GL_BL 1 /* curve on bottom left */
#define OC_GL_BR 2 /* curve on bottom right */ #define OC_GL_BR 2 /* curve on bottom right */
#define OC_GL_TL 3 /* curve on top left */ #define OC_GL_TL 3 /* curve on top left */
#define OC_GL_TR 4 /* curve on top right */ #define OC_GL_TR 4 /* curve on top right */
// Operations // Operations
#define OC_GL_OP_FILL 0 #define OC_GL_OP_FILL 0
#define OC_GL_OP_CLIP_FILL 1 #define OC_GL_OP_CLIP_FILL 1
#define OC_GL_OP_START 2 #define OC_GL_OP_START 2
#define OC_GL_OP_END 3 #define OC_GL_OP_END 3
#define OC_GL_OP_SEGMENT 4 #define OC_GL_OP_SEGMENT 4
// MSAA // MSAA
#define OC_GL_MAX_SAMPLE_COUNT 8 #define OC_GL_MAX_SAMPLE_COUNT 8
@ -29,158 +29,160 @@ layout(std430) buffer;
struct oc_gl_path struct oc_gl_path
{ {
mat3 uvTransform; mat3 uvTransform;
vec4 color; vec4 color;
vec4 box; vec4 box;
vec4 clip; vec4 clip;
int cmd; int cmd;
int textureID; int textureID;
}; };
struct oc_gl_path_elt struct oc_gl_path_elt
{ {
vec2 p[4]; vec2 p[4];
int pathIndex; int pathIndex;
int kind; int kind;
}; };
struct oc_gl_segment struct oc_gl_segment
{ {
int kind; int kind;
int pathIndex; int pathIndex;
int config; int config;
int windingIncrement; int windingIncrement;
vec4 box; vec4 box;
mat3 implicitMatrix; mat3 implicitMatrix;
vec2 hullVertex; vec2 hullVertex;
float sign; float sign;
}; };
struct oc_gl_path_queue struct oc_gl_path_queue
{ {
ivec4 area; ivec4 area;
int tileQueues; int tileQueues;
}; };
struct oc_gl_tile_op struct oc_gl_tile_op
{ {
int kind; int kind;
int next; int next;
int index; int index;
int windingOffsetOrCrossRight; int windingOffsetOrCrossRight;
}; };
struct oc_gl_tile_queue struct oc_gl_tile_queue
{ {
int windingOffset; int windingOffset;
int first; int first;
int last; int last;
}; };
struct oc_gl_screen_tile struct oc_gl_screen_tile
{ {
uvec2 tileCoord; uvec2 tileCoord;
int first; int first;
}; };
struct oc_gl_dispatch_indirect_command struct oc_gl_dispatch_indirect_command
{ {
uint num_groups_x; uint num_groups_x;
uint num_groups_y; uint num_groups_y;
uint num_groups_z; uint num_groups_z;
}; };
float ccw(vec2 a, vec2 b, vec2 c) float ccw(vec2 a, vec2 b, vec2 c)
{ {
return((b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x)); return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x));
} }
int side_of_segment(vec2 p, oc_gl_segment seg) int side_of_segment(vec2 p, oc_gl_segment seg)
{ {
int side = 0; int side = 0;
if(p.y > seg.box.w || p.y <= seg.box.y) if(p.y > seg.box.w || p.y <= seg.box.y)
{ {
if(p.x > seg.box.x && p.x <= seg.box.z) if(p.x > seg.box.x && p.x <= seg.box.z)
{ {
if(p.y > seg.box.w) if(p.y > seg.box.w)
{ {
side = (seg.config == OC_GL_TL || seg.config == OC_GL_BR)? -1 : 1; side = (seg.config == OC_GL_TL || seg.config == OC_GL_BR) ? -1 : 1;
} }
else else
{ {
side = (seg.config == OC_GL_TL || seg.config == OC_GL_BR)? 1 : -1; side = (seg.config == OC_GL_TL || seg.config == OC_GL_BR) ? 1 : -1;
} }
} }
} }
else if(p.x > seg.box.z) else if(p.x > seg.box.z)
{ {
side = 1; side = 1;
} }
else if(p.x <= seg.box.x) else if(p.x <= seg.box.x)
{ {
side = -1; side = -1;
} }
else else
{ {
vec2 a, b, c; vec2 a, b, c;
switch(seg.config) switch(seg.config)
{ {
case OC_GL_TL: case OC_GL_TL:
a = seg.box.xy; a = seg.box.xy;
b = seg.box.zw; b = seg.box.zw;
break; break;
case OC_GL_BR: case OC_GL_BR:
a = seg.box.zw; a = seg.box.zw;
b = seg.box.xy; b = seg.box.xy;
break; break;
case OC_GL_TR: case OC_GL_TR:
a = seg.box.xw; a = seg.box.xw;
b = seg.box.zy; b = seg.box.zy;
break; break;
case OC_GL_BL: case OC_GL_BL:
a = seg.box.zy; a = seg.box.zy;
b = seg.box.xw; b = seg.box.xw;
break; break;
} }
c = seg.hullVertex; c = seg.hullVertex;
if(ccw(a, b, p) < 0) if(ccw(a, b, p) < 0)
{ {
// other side of the diagonal // other side of the diagonal
side = (seg.config == OC_GL_BR || seg.config == OC_GL_TR) ? -1 : 1; side = (seg.config == OC_GL_BR || seg.config == OC_GL_TR) ? -1 : 1;
} }
else if(ccw(b, c, p) < 0 || ccw(c, a, p) < 0) else if(ccw(b, c, p) < 0 || ccw(c, a, p) < 0)
{ {
// same side of the diagonal, but outside curve hull // same side of the diagonal, but outside curve hull
side = (seg.config == OC_GL_BL || seg.config == OC_GL_TL) ? -1 : 1; side = (seg.config == OC_GL_BL || seg.config == OC_GL_TL) ? -1 : 1;
} }
else else
{ {
// inside curve hull // inside curve hull
switch(seg.kind) switch(seg.kind)
{ {
case OC_GL_LINE: case OC_GL_LINE:
side = 1; side = 1;
break; break;
case OC_GL_QUADRATIC: case OC_GL_QUADRATIC:
{ {
vec3 ph = {p.x, p.y, 1}; vec3 ph = { p.x, p.y, 1 };
vec3 klm = seg.implicitMatrix * ph; vec3 klm = seg.implicitMatrix * ph;
side = ((klm.x*klm.x - klm.y)*klm.z < 0)? -1 : 1; side = ((klm.x * klm.x - klm.y) * klm.z < 0) ? -1 : 1;
} break; }
break;
case OC_GL_CUBIC: case OC_GL_CUBIC:
{ {
vec3 ph = {p.x, p.y, 1}; vec3 ph = { p.x, p.y, 1 };
vec3 klm = seg.implicitMatrix * ph; vec3 klm = seg.implicitMatrix * ph;
side = (seg.sign*(klm.x*klm.x*klm.x - klm.y*klm.z) < 0)? -1 : 1; side = (seg.sign * (klm.x * klm.x * klm.x - klm.y * klm.z) < 0) ? -1 : 1;
} break; }
} break;
} }
} }
return(side); }
return (side);
} }

View File

@ -6,39 +6,52 @@ layout(std430) buffer;
layout(binding = 0) restrict readonly buffer pathBufferSSBO layout(binding = 0) restrict readonly buffer pathBufferSSBO
{ {
oc_gl_path elements[]; oc_gl_path elements[];
} pathBuffer; }
pathBuffer;
layout(binding = 1) restrict readonly buffer pathQueueBufferSSBO layout(binding = 1) restrict readonly buffer pathQueueBufferSSBO
{ {
oc_gl_path_queue elements[]; oc_gl_path_queue elements[];
} pathQueueBuffer; }
pathQueueBuffer;
layout(binding = 2) restrict readonly buffer tileQueueBufferSSBO layout(binding = 2) restrict readonly buffer tileQueueBufferSSBO
{ {
oc_gl_tile_queue elements[]; oc_gl_tile_queue elements[];
} tileQueueBuffer; }
tileQueueBuffer;
layout(binding = 3) coherent restrict buffer tileOpCountBufferSSBO layout(binding = 3) coherent restrict buffer tileOpCountBufferSSBO
{ {
int elements[]; int elements[];
} tileOpCountBuffer; }
tileOpCountBuffer;
layout(binding = 4) restrict buffer tileOpBufferSSBO layout(binding = 4) restrict buffer tileOpBufferSSBO
{ {
oc_gl_tile_op elements[]; oc_gl_tile_op elements[];
} tileOpBuffer; }
tileOpBuffer;
layout(binding = 5) restrict writeonly buffer screenTilesBufferSSBO layout(binding = 5) restrict writeonly buffer screenTilesBufferSSBO
{ {
oc_gl_screen_tile elements[]; oc_gl_screen_tile elements[];
} screenTilesBuffer; }
screenTilesBuffer;
layout(binding = 6) coherent restrict buffer screenTilesCountBufferSSBO layout(binding = 6) coherent restrict buffer screenTilesCountBufferSSBO
{ {
int elements[]; int elements[];
} screenTilesCountBuffer; }
screenTilesCountBuffer;
layout(location = 0) uniform int tileSize; layout(location = 0) uniform int tileSize;
layout(location = 1) uniform float scale; layout(location = 1) uniform float scale;
@ -47,147 +60,147 @@ layout(location = 3) uniform int pathBufferStart;
void main() void main()
{ {
ivec2 tileCoord = ivec2(gl_WorkGroupID.xy); ivec2 tileCoord = ivec2(gl_WorkGroupID.xy);
int tileIndex = -1; int tileIndex = -1;
int lastOpIndex = -1; int lastOpIndex = -1;
for(int pathIndex = 0; pathIndex < pathCount; pathIndex++) for(int pathIndex = 0; pathIndex < pathCount; pathIndex++)
{ {
oc_gl_path_queue pathQueue = pathQueueBuffer.elements[pathIndex]; oc_gl_path_queue pathQueue = pathQueueBuffer.elements[pathIndex];
ivec2 pathTileCoord = tileCoord - pathQueue.area.xy; ivec2 pathTileCoord = tileCoord - pathQueue.area.xy;
vec4 pathBox = pathBuffer.elements[pathBufferStart + pathIndex].box; vec4 pathBox = pathBuffer.elements[pathBufferStart + pathIndex].box;
vec4 pathClip = pathBuffer.elements[pathBufferStart + pathIndex].clip; vec4 pathClip = pathBuffer.elements[pathBufferStart + pathIndex].clip;
float xMax = min(pathBox.z, pathClip.z); float xMax = min(pathBox.z, pathClip.z);
int tileMax = int(xMax * scale) / tileSize; int tileMax = int(xMax * scale) / tileSize;
int pathTileMax = tileMax - pathQueue.area.x; int pathTileMax = tileMax - pathQueue.area.x;
if( pathTileCoord.x >= 0 if(pathTileCoord.x >= 0
&& pathTileCoord.x <= pathTileMax && pathTileCoord.x <= pathTileMax
&& pathTileCoord.y >= 0 && pathTileCoord.y >= 0
&& pathTileCoord.y < pathQueue.area.w) && pathTileCoord.y < pathQueue.area.w)
{ {
if(tileIndex < 0) if(tileIndex < 0)
{ {
tileIndex = int(atomicAdd(screenTilesCountBuffer.elements[0], 1)); tileIndex = int(atomicAdd(screenTilesCountBuffer.elements[0], 1));
screenTilesBuffer.elements[tileIndex].tileCoord = uvec2(tileCoord); screenTilesBuffer.elements[tileIndex].tileCoord = uvec2(tileCoord);
screenTilesBuffer.elements[tileIndex].first = -1; screenTilesBuffer.elements[tileIndex].first = -1;
} }
int pathTileIndex = pathQueue.tileQueues + pathTileCoord.y * pathQueue.area.z + pathTileCoord.x; int pathTileIndex = pathQueue.tileQueues + pathTileCoord.y * pathQueue.area.z + pathTileCoord.x;
oc_gl_tile_queue tileQueue = tileQueueBuffer.elements[pathTileIndex]; oc_gl_tile_queue tileQueue = tileQueueBuffer.elements[pathTileIndex];
int windingOffset = tileQueue.windingOffset; int windingOffset = tileQueue.windingOffset;
int firstOpIndex = tileQueue.first; int firstOpIndex = tileQueue.first;
vec4 tileBox = vec4(tileCoord.x, tileCoord.y, tileCoord.x+1, tileCoord.y+1); vec4 tileBox = vec4(tileCoord.x, tileCoord.y, tileCoord.x + 1, tileCoord.y + 1);
tileBox *= tileSize; tileBox *= tileSize;
vec4 clip = pathBuffer.elements[pathBufferStart + pathIndex].clip * scale; vec4 clip = pathBuffer.elements[pathBufferStart + pathIndex].clip * scale;
if( tileBox.x >= clip.z if(tileBox.x >= clip.z
|| tileBox.z < clip.x || tileBox.z < clip.x
|| tileBox.y >= clip.w || tileBox.y >= clip.w
|| tileBox.w < clip.y) || tileBox.w < clip.y)
{ {
//NOTE: tile is fully outside clip, cull it //NOTE: tile is fully outside clip, cull it
//TODO: move that test up //TODO: move that test up
} }
else if(firstOpIndex == -1) else if(firstOpIndex == -1)
{ {
if((windingOffset & 1) != 0) if((windingOffset & 1) != 0)
{ {
//NOTE: tile is full covered. Add path start op (with winding offset). //NOTE: tile is full covered. Add path start op (with winding offset).
// Additionally if color is opaque and tile is fully inside clip, trim tile list. // Additionally if color is opaque and tile is fully inside clip, trim tile list.
int pathOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1); int pathOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
if(pathOpIndex >= tileOpBuffer.elements.length()) if(pathOpIndex >= tileOpBuffer.elements.length())
{ {
return; return;
} }
tileOpBuffer.elements[pathOpIndex].kind = OC_GL_OP_CLIP_FILL; tileOpBuffer.elements[pathOpIndex].kind = OC_GL_OP_CLIP_FILL;
tileOpBuffer.elements[pathOpIndex].next = -1; tileOpBuffer.elements[pathOpIndex].next = -1;
tileOpBuffer.elements[pathOpIndex].index = pathIndex; tileOpBuffer.elements[pathOpIndex].index = pathIndex;
tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset; tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
if(lastOpIndex < 0) if(lastOpIndex < 0)
{ {
screenTilesBuffer.elements[tileIndex].first = pathOpIndex; screenTilesBuffer.elements[tileIndex].first = pathOpIndex;
} }
else else
{ {
tileOpBuffer.elements[lastOpIndex].next = pathOpIndex; tileOpBuffer.elements[lastOpIndex].next = pathOpIndex;
} }
if( tileBox.x >= clip.x if(tileBox.x >= clip.x
&& tileBox.z < clip.z && tileBox.z < clip.z
&& tileBox.y >= clip.y && tileBox.y >= clip.y
&& tileBox.w < clip.w) && tileBox.w < clip.w)
{ {
tileOpBuffer.elements[pathOpIndex].kind = OC_GL_OP_FILL; tileOpBuffer.elements[pathOpIndex].kind = OC_GL_OP_FILL;
if( pathBuffer.elements[pathBufferStart + pathIndex].color.a == 1 if(pathBuffer.elements[pathBufferStart + pathIndex].color.a == 1
&& pathBuffer.elements[pathBufferStart + pathIndex].textureID < 0) && pathBuffer.elements[pathBufferStart + pathIndex].textureID < 0)
{ {
screenTilesBuffer.elements[tileIndex].first = pathOpIndex; screenTilesBuffer.elements[tileIndex].first = pathOpIndex;
} }
} }
lastOpIndex = pathOpIndex; lastOpIndex = pathOpIndex;
} }
// else, tile is fully uncovered, skip path // else, tile is fully uncovered, skip path
} }
else else
{ {
//NOTE: add path start op (with winding offset) //NOTE: add path start op (with winding offset)
int startOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1); int startOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
if(startOpIndex >= tileOpBuffer.elements.length()) if(startOpIndex >= tileOpBuffer.elements.length())
{ {
return; return;
} }
tileOpBuffer.elements[startOpIndex].kind = OC_GL_OP_START; tileOpBuffer.elements[startOpIndex].kind = OC_GL_OP_START;
tileOpBuffer.elements[startOpIndex].next = -1; tileOpBuffer.elements[startOpIndex].next = -1;
tileOpBuffer.elements[startOpIndex].index = pathIndex; tileOpBuffer.elements[startOpIndex].index = pathIndex;
tileOpBuffer.elements[startOpIndex].windingOffsetOrCrossRight = windingOffset; tileOpBuffer.elements[startOpIndex].windingOffsetOrCrossRight = windingOffset;
if(lastOpIndex < 0) if(lastOpIndex < 0)
{ {
screenTilesBuffer.elements[tileIndex].first = startOpIndex; screenTilesBuffer.elements[tileIndex].first = startOpIndex;
} }
else else
{ {
tileOpBuffer.elements[lastOpIndex].next = startOpIndex; tileOpBuffer.elements[lastOpIndex].next = startOpIndex;
} }
lastOpIndex = startOpIndex; lastOpIndex = startOpIndex;
//NOTE: chain remaining path ops to end of tile list //NOTE: chain remaining path ops to end of tile list
tileOpBuffer.elements[lastOpIndex].next = firstOpIndex; tileOpBuffer.elements[lastOpIndex].next = firstOpIndex;
lastOpIndex = tileQueue.last; lastOpIndex = tileQueue.last;
//NOTE: add path end op //NOTE: add path end op
int endOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1); int endOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
if(endOpIndex >= tileOpBuffer.elements.length()) if(endOpIndex >= tileOpBuffer.elements.length())
{ {
return; return;
} }
tileOpBuffer.elements[endOpIndex].kind = OC_GL_OP_END; tileOpBuffer.elements[endOpIndex].kind = OC_GL_OP_END;
tileOpBuffer.elements[endOpIndex].next = -1; tileOpBuffer.elements[endOpIndex].next = -1;
tileOpBuffer.elements[endOpIndex].index = pathIndex; tileOpBuffer.elements[endOpIndex].index = pathIndex;
tileOpBuffer.elements[endOpIndex].windingOffsetOrCrossRight = windingOffset; tileOpBuffer.elements[endOpIndex].windingOffsetOrCrossRight = windingOffset;
if(lastOpIndex < 0) if(lastOpIndex < 0)
{ {
screenTilesBuffer.elements[tileIndex].first = endOpIndex; screenTilesBuffer.elements[tileIndex].first = endOpIndex;
} }
else else
{ {
tileOpBuffer.elements[lastOpIndex].next = endOpIndex; tileOpBuffer.elements[lastOpIndex].next = endOpIndex;
} }
lastOpIndex = endOpIndex; lastOpIndex = endOpIndex;
} }
} }
} }
} }

View File

@ -6,23 +6,31 @@ layout(std430) buffer;
layout(binding = 0) restrict readonly buffer pathBufferSSBO layout(binding = 0) restrict readonly buffer pathBufferSSBO
{ {
oc_gl_path elements[]; oc_gl_path elements[];
} pathBuffer; }
pathBuffer;
layout(binding = 1) restrict writeonly buffer pathQueueBufferSSBO layout(binding = 1) restrict writeonly buffer pathQueueBufferSSBO
{ {
oc_gl_path_queue elements[]; oc_gl_path_queue elements[];
} pathQueueBuffer; }
pathQueueBuffer;
layout(binding = 2) coherent restrict buffer tileQueueCountBufferSSBO layout(binding = 2) coherent restrict buffer tileQueueCountBufferSSBO
{ {
int elements[]; int elements[];
} tileQueueCountBuffer; }
tileQueueCountBuffer;
layout(binding = 3) restrict writeonly buffer tileQueueBufferSSBO layout(binding = 3) restrict writeonly buffer tileQueueBufferSSBO
{ {
oc_gl_tile_queue elements[]; oc_gl_tile_queue elements[];
} tileQueueBuffer; }
tileQueueBuffer;
layout(location = 0) uniform int tileSize; layout(location = 0) uniform int tileSize;
layout(location = 1) uniform float scale; layout(location = 1) uniform float scale;
@ -31,40 +39,40 @@ layout(location = 3) uniform int pathQueueBufferStart;
void main() void main()
{ {
uint pathIndex = gl_WorkGroupID.x; uint pathIndex = gl_WorkGroupID.x;
const oc_gl_path path = pathBuffer.elements[pathIndex + pathBufferStart]; const oc_gl_path path = pathBuffer.elements[pathIndex + pathBufferStart];
//NOTE: we don't clip on the right, since we need those tiles to accurately compute //NOTE: we don't clip on the right, since we need those tiles to accurately compute
// the prefix sum of winding increments in the backprop pass. // the prefix sum of winding increments in the backprop pass.
vec4 clippedBox = vec4(max(path.box.x, path.clip.x), vec4 clippedBox = vec4(max(path.box.x, path.clip.x),
max(path.box.y, path.clip.y), max(path.box.y, path.clip.y),
path.box.z, path.box.z,
min(path.box.w, path.clip.w)); min(path.box.w, path.clip.w));
ivec2 firstTile = ivec2(clippedBox.xy*scale)/tileSize; ivec2 firstTile = ivec2(clippedBox.xy * scale) / tileSize;
ivec2 lastTile = ivec2(clippedBox.zw*scale)/tileSize; ivec2 lastTile = ivec2(clippedBox.zw * scale) / tileSize;
int nTilesX = max(0, lastTile.x - firstTile.x + 1); int nTilesX = max(0, lastTile.x - firstTile.x + 1);
int nTilesY = max(0, lastTile.y - firstTile.y + 1); int nTilesY = max(0, lastTile.y - firstTile.y + 1);
int tileCount = nTilesX * nTilesY; int tileCount = nTilesX * nTilesY;
int tileQueuesIndex = atomicAdd(tileQueueCountBuffer.elements[0], tileCount); int tileQueuesIndex = atomicAdd(tileQueueCountBuffer.elements[0], tileCount);
if(tileQueuesIndex + tileCount >= tileQueueBuffer.elements.length()) if(tileQueuesIndex + tileCount >= tileQueueBuffer.elements.length())
{ {
pathQueueBuffer.elements[pathIndex].area = ivec4(0); pathQueueBuffer.elements[pathIndex].area = ivec4(0);
pathQueueBuffer.elements[pathIndex].tileQueues = 0; pathQueueBuffer.elements[pathIndex].tileQueues = 0;
} }
else else
{ {
pathQueueBuffer.elements[pathQueueBufferStart + pathIndex].area = ivec4(firstTile.x, firstTile.y, nTilesX, nTilesY); pathQueueBuffer.elements[pathQueueBufferStart + pathIndex].area = ivec4(firstTile.x, firstTile.y, nTilesX, nTilesY);
pathQueueBuffer.elements[pathQueueBufferStart + pathIndex].tileQueues = tileQueuesIndex; pathQueueBuffer.elements[pathQueueBufferStart + pathIndex].tileQueues = tileQueuesIndex;
for(int i=0; i<tileCount; i++) for(int i = 0; i < tileCount; i++)
{ {
tileQueueBuffer.elements[tileQueuesIndex + i].first = -1; tileQueueBuffer.elements[tileQueuesIndex + i].first = -1;
tileQueueBuffer.elements[tileQueuesIndex + i].last = -1; tileQueueBuffer.elements[tileQueuesIndex + i].last = -1;
tileQueueBuffer.elements[tileQueuesIndex + i].windingOffset = 0; tileQueueBuffer.elements[tileQueuesIndex + i].windingOffset = 0;
} }
} }
} }

View File

@ -6,29 +6,38 @@ layout(std430) buffer;
layout(binding = 0) restrict readonly buffer pathBufferSSBO layout(binding = 0) restrict readonly buffer pathBufferSSBO
{ {
oc_gl_path elements[]; oc_gl_path elements[];
} pathBuffer; }
pathBuffer;
layout(binding = 1) restrict readonly buffer segmentBufferSSBO layout(binding = 1) restrict readonly buffer segmentBufferSSBO
{ {
oc_gl_segment elements[]; oc_gl_segment elements[];
} segmentBuffer; }
segmentBuffer;
layout(binding = 2) restrict readonly buffer tileOpBufferSSBO layout(binding = 2) restrict readonly buffer tileOpBufferSSBO
{ {
oc_gl_tile_op elements[]; oc_gl_tile_op elements[];
} tileOpBuffer; }
tileOpBuffer;
layout(binding = 3) restrict readonly buffer screenTilesBufferSSBO layout(binding = 3) restrict readonly buffer screenTilesBufferSSBO
{ {
oc_gl_screen_tile elements[]; oc_gl_screen_tile elements[];
} screenTilesBuffer; }
screenTilesBuffer;
layout(binding = 4) restrict readonly buffer screenTilesCountBufferSSBO layout(binding = 4) restrict readonly buffer screenTilesCountBufferSSBO
{ {
int elements[]; int elements[];
} screenTilesCountBuffer; }
screenTilesCountBuffer;
layout(location = 0) uniform float scale; layout(location = 0) uniform float scale;
layout(location = 1) uniform int msaaSampleCount; layout(location = 1) uniform int msaaSampleCount;
@ -48,196 +57,197 @@ layout(binding = 8) uniform sampler2D srcTexture7;
void main() void main()
{ {
uint tileIndex = gl_WorkGroupID.y * maxWorkGroupCount + gl_WorkGroupID.x; uint tileIndex = gl_WorkGroupID.y * maxWorkGroupCount + gl_WorkGroupID.x;
if(tileIndex >= screenTilesCountBuffer.elements[0]) if(tileIndex >= screenTilesCountBuffer.elements[0])
{ {
return; return;
} }
uvec2 tileCoord = screenTilesBuffer.elements[tileIndex].tileCoord; uvec2 tileCoord = screenTilesBuffer.elements[tileIndex].tileCoord;
ivec2 pixelCoord = ivec2(tileCoord * gl_WorkGroupSize.x + gl_LocalInvocationID.xy); ivec2 pixelCoord = ivec2(tileCoord * gl_WorkGroupSize.x + gl_LocalInvocationID.xy);
vec2 centerCoord = vec2(pixelCoord) + vec2(0.5, 0.5); vec2 centerCoord = vec2(pixelCoord) + vec2(0.5, 0.5);
/* /*
if((pixelCoord.x % 16) == 0 || (pixelCoord.y % 16) == 0) if((pixelCoord.x % 16) == 0 || (pixelCoord.y % 16) == 0)
{ {
imageStore(outTexture, pixelCoord, vec4(0, 0, 0, 1)); imageStore(outTexture, pixelCoord, vec4(0, 0, 0, 1));
return; return;
} }
*/ */
vec2 sampleCoords[OC_GL_MAX_SAMPLE_COUNT] = { vec2 sampleCoords[OC_GL_MAX_SAMPLE_COUNT] = {
centerCoord + vec2(1, 3)/16, centerCoord + vec2(1, 3) / 16,
centerCoord + vec2(-1, -3)/16, centerCoord + vec2(-1, -3) / 16,
centerCoord + vec2(5, -1)/16, centerCoord + vec2(5, -1) / 16,
centerCoord + vec2(-3, 5)/16, centerCoord + vec2(-3, 5) / 16,
centerCoord + vec2(-5, -5)/16, centerCoord + vec2(-5, -5) / 16,
centerCoord + vec2(-7, 1)/16, centerCoord + vec2(-7, 1) / 16,
centerCoord + vec2(3, -7)/16, centerCoord + vec2(3, -7) / 16,
centerCoord + vec2(7, 7)/16 centerCoord + vec2(7, 7) / 16
}; };
int sampleCount = msaaSampleCount; int sampleCount = msaaSampleCount;
if(sampleCount != 8) if(sampleCount != 8)
{ {
sampleCount = 1; sampleCount = 1;
sampleCoords[0] = centerCoord; sampleCoords[0] = centerCoord;
} }
const int srcSampleCount = 2; const int srcSampleCount = 2;
vec2 imgSampleCoords[OC_GL_MAX_SRC_SAMPLE_COUNT] = { vec2 imgSampleCoords[OC_GL_MAX_SRC_SAMPLE_COUNT] = {
centerCoord + vec2(-0.25, 0.25), centerCoord + vec2(-0.25, 0.25),
centerCoord + vec2(+0.25, +0.25), centerCoord + vec2(+0.25, +0.25),
centerCoord + vec2(+0.25, -0.25), centerCoord + vec2(+0.25, -0.25),
centerCoord + vec2(-0.25, +0.25)}; centerCoord + vec2(-0.25, +0.25)
};
vec4 color = vec4(0); vec4 color = vec4(0);
int winding[OC_GL_MAX_SAMPLE_COUNT]; int winding[OC_GL_MAX_SAMPLE_COUNT];
for(int i=0; i<sampleCount; i++) for(int i = 0; i < sampleCount; i++)
{ {
winding[i] = 0; winding[i] = 0;
} }
int pathIndex = 0; int pathIndex = 0;
int opIndex = screenTilesBuffer.elements[tileIndex].first; int opIndex = screenTilesBuffer.elements[tileIndex].first;
while(opIndex >= 0) while(opIndex >= 0)
{ {
oc_gl_tile_op op = tileOpBuffer.elements[opIndex]; oc_gl_tile_op op = tileOpBuffer.elements[opIndex];
if(op.kind == OC_GL_OP_START) if(op.kind == OC_GL_OP_START)
{ {
for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++) for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
{ {
winding[sampleIndex] = op.windingOffsetOrCrossRight; winding[sampleIndex] = op.windingOffsetOrCrossRight;
} }
} }
else if(op.kind == OC_GL_OP_SEGMENT) else if(op.kind == OC_GL_OP_SEGMENT)
{ {
int segIndex = op.index; int segIndex = op.index;
oc_gl_segment seg = segmentBuffer.elements[segIndex]; oc_gl_segment seg = segmentBuffer.elements[segIndex];
for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++) for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
{ {
vec2 sampleCoord = sampleCoords[sampleIndex]; vec2 sampleCoord = sampleCoords[sampleIndex];
if( (sampleCoord.y > seg.box.y) if((sampleCoord.y > seg.box.y)
&&(sampleCoord.y <= seg.box.w) && (sampleCoord.y <= seg.box.w)
&&(side_of_segment(sampleCoord, seg) < 0)) && (side_of_segment(sampleCoord, seg) < 0))
{ {
winding[sampleIndex] += seg.windingIncrement; winding[sampleIndex] += seg.windingIncrement;
} }
if(op.windingOffsetOrCrossRight != 0) if(op.windingOffsetOrCrossRight != 0)
{ {
if( (seg.config == OC_GL_BR || seg.config == OC_GL_TL) if((seg.config == OC_GL_BR || seg.config == OC_GL_TL)
&&(sampleCoord.y > seg.box.w)) && (sampleCoord.y > seg.box.w))
{ {
winding[sampleIndex] += seg.windingIncrement; winding[sampleIndex] += seg.windingIncrement;
} }
else if( (seg.config == OC_GL_BL || seg.config == OC_GL_TR) else if((seg.config == OC_GL_BL || seg.config == OC_GL_TR)
&&(sampleCoord.y > seg.box.y)) && (sampleCoord.y > seg.box.y))
{ {
winding[sampleIndex] -= seg.windingIncrement; winding[sampleIndex] -= seg.windingIncrement;
} }
} }
} }
} }
else else
{ {
int pathIndex = op.index; int pathIndex = op.index;
vec4 nextColor = pathBuffer.elements[pathBufferStart + pathIndex].color; vec4 nextColor = pathBuffer.elements[pathBufferStart + pathIndex].color;
nextColor.rgb *= nextColor.a; nextColor.rgb *= nextColor.a;
int textureID = pathBuffer.elements[pathBufferStart+pathIndex].textureID; int textureID = pathBuffer.elements[pathBufferStart + pathIndex].textureID;
if(textureID >= 0) if(textureID >= 0)
{ {
vec4 texColor = vec4(0); vec4 texColor = vec4(0);
for(int sampleIndex = 0; sampleIndex<srcSampleCount; sampleIndex++) for(int sampleIndex = 0; sampleIndex < srcSampleCount; sampleIndex++)
{ {
vec2 sampleCoord = imgSampleCoords[sampleIndex]; vec2 sampleCoord = imgSampleCoords[sampleIndex];
vec3 ph = vec3(sampleCoord.xy, 1); vec3 ph = vec3(sampleCoord.xy, 1);
vec2 uv = (pathBuffer.elements[pathBufferStart + pathIndex].uvTransform * ph).xy; vec2 uv = (pathBuffer.elements[pathBufferStart + pathIndex].uvTransform * ph).xy;
if(textureID == 0) if(textureID == 0)
{ {
texColor += texture(srcTexture0, uv); texColor += texture(srcTexture0, uv);
} }
else if(textureID == 1) else if(textureID == 1)
{ {
texColor += texture(srcTexture1, uv); texColor += texture(srcTexture1, uv);
} }
else if(textureID == 2) else if(textureID == 2)
{ {
texColor += texture(srcTexture2, uv); texColor += texture(srcTexture2, uv);
} }
else if(textureID == 3) else if(textureID == 3)
{ {
texColor += texture(srcTexture3, uv); texColor += texture(srcTexture3, uv);
} }
else if(textureID == 4) else if(textureID == 4)
{ {
texColor += texture(srcTexture4, uv); texColor += texture(srcTexture4, uv);
} }
else if(textureID == 5) else if(textureID == 5)
{ {
texColor += texture(srcTexture5, uv); texColor += texture(srcTexture5, uv);
} }
else if(textureID == 6) else if(textureID == 6)
{ {
texColor += texture(srcTexture6, uv); texColor += texture(srcTexture6, uv);
} }
else if(textureID == 7) else if(textureID == 7)
{ {
texColor += texture(srcTexture7, uv); texColor += texture(srcTexture7, uv);
} }
} }
texColor /= srcSampleCount; texColor /= srcSampleCount;
texColor.rgb *= texColor.a; texColor.rgb *= texColor.a;
nextColor *= texColor; nextColor *= texColor;
} }
if(op.kind == OC_GL_OP_FILL) if(op.kind == OC_GL_OP_FILL)
{ {
color = color*(1-nextColor.a) + nextColor; color = color * (1 - nextColor.a) + nextColor;
} }
else else
{ {
vec4 clip = pathBuffer.elements[pathBufferStart + pathIndex].clip * scale; vec4 clip = pathBuffer.elements[pathBufferStart + pathIndex].clip * scale;
float coverage = 0; float coverage = 0;
for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++) for(int sampleIndex = 0; sampleIndex < sampleCount; sampleIndex++)
{ {
vec2 sampleCoord = sampleCoords[sampleIndex]; vec2 sampleCoord = sampleCoords[sampleIndex];
if( sampleCoord.x >= clip.x if(sampleCoord.x >= clip.x
&& sampleCoord.x < clip.z && sampleCoord.x < clip.z
&& sampleCoord.y >= clip.y && sampleCoord.y >= clip.y
&& sampleCoord.y < clip.w) && sampleCoord.y < clip.w)
{ {
bool filled = op.kind == OC_GL_OP_CLIP_FILL bool filled = op.kind == OC_GL_OP_CLIP_FILL
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == OC_GL_FILL || (pathBuffer.elements[pathBufferStart + pathIndex].cmd == OC_GL_FILL
&& ((winding[sampleIndex] & 1) != 0)) && ((winding[sampleIndex] & 1) != 0))
||(pathBuffer.elements[pathBufferStart + pathIndex].cmd == OC_GL_STROKE || (pathBuffer.elements[pathBufferStart + pathIndex].cmd == OC_GL_STROKE
&& (winding[sampleIndex] != 0)); && (winding[sampleIndex] != 0));
if(filled) if(filled)
{ {
coverage++; coverage++;
} }
} }
winding[sampleIndex] = op.windingOffsetOrCrossRight; winding[sampleIndex] = op.windingOffsetOrCrossRight;
} }
coverage /= sampleCount; coverage /= sampleCount;
color = coverage*(color*(1-nextColor.a) + nextColor) + (1.-coverage)*color; color = coverage * (color * (1 - nextColor.a) + nextColor) + (1. - coverage) * color;
} }
} }
opIndex = op.next; opIndex = op.next;
} }
imageStore(outTexture, pixelCoord, color); imageStore(outTexture, pixelCoord, color);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: graphics.h * @file: graphics.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -9,78 +9,80 @@
#ifndef __GRAPHICS_H_ #ifndef __GRAPHICS_H_
#define __GRAPHICS_H_ #define __GRAPHICS_H_
#include"util/typedefs.h" #include "app/app.h"
#include"platform/platform.h" #include "platform/platform.h"
#include"app/app.h" #include "util/typedefs.h"
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
//NOTE(martin): backends selection //NOTE(martin): backends selection
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
typedef enum { typedef enum
OC_NONE, {
OC_METAL, OC_NONE,
OC_GL, OC_METAL,
OC_GLES, OC_GL,
OC_CANVAS, OC_GLES,
OC_HOST } oc_surface_api; OC_CANVAS,
OC_HOST
} oc_surface_api;
//NOTE: these macros are used to select which backend to include when building milepost //NOTE: these macros are used to select which backend to include when building milepost
// they can be overridden by passing them to the compiler command line // they can be overridden by passing them to the compiler command line
#if OC_PLATFORM_MACOS #if OC_PLATFORM_MACOS
#ifndef OC_COMPILE_METAL #ifndef OC_COMPILE_METAL
#define OC_COMPILE_METAL 1 #define OC_COMPILE_METAL 1
#endif #endif
#ifndef OC_COMPILE_GLES #ifndef OC_COMPILE_GLES
#define OC_COMPILE_GLES 1 #define OC_COMPILE_GLES 1
#endif #endif
#ifndef OC_COMPILE_CANVAS #ifndef OC_COMPILE_CANVAS
#if !OC_COMPILE_METAL #if !OC_COMPILE_METAL
#error "Canvas surface requires a Metal backend on macOS. Make sure you define OC_COMPILE_METAL to 1." #error "Canvas surface requires a Metal backend on macOS. Make sure you define OC_COMPILE_METAL to 1."
#endif #endif
#define OC_COMPILE_CANVAS 1 #define OC_COMPILE_CANVAS 1
#endif #endif
#define OC_COMPILE_GL 0 #define OC_COMPILE_GL 0
#elif OC_PLATFORM_WINDOWS #elif OC_PLATFORM_WINDOWS
#ifndef OC_COMPILE_GL #ifndef OC_COMPILE_GL
#define OC_COMPILE_GL 1 #define OC_COMPILE_GL 1
#endif #endif
#ifndef OC_COMPILE_GLES #ifndef OC_COMPILE_GLES
#define OC_COMPILE_GLES 1 #define OC_COMPILE_GLES 1
#endif #endif
#ifndef OC_COMPILE_CANVAS #ifndef OC_COMPILE_CANVAS
#if !OC_COMPILE_GL #if !OC_COMPILE_GL
#error "Canvas surface requires an OpenGL backend on Windows. Make sure you define OC_COMPILE_GL to 1." #error "Canvas surface requires an OpenGL backend on Windows. Make sure you define OC_COMPILE_GL to 1."
#endif #endif
#define OC_COMPILE_CANVAS 1 #define OC_COMPILE_CANVAS 1
#endif #endif
#elif PLATFORM_LINUX #elif PLATFORM_LINUX
#ifndef OC_COMPILE_GL #ifndef OC_COMPILE_GL
#define OC_COMPILE_GL 1 #define OC_COMPILE_GL 1
#endif #endif
#ifndef OC_COMPILE_CANVAS #ifndef OC_COMPILE_CANVAS
#if !OC_COMPILE_GL #if !OC_COMPILE_GL
#error "Canvas surface requires an OpenGL backend on Linux. Make sure you define OC_COMPILE_GL to 1." #error "Canvas surface requires an OpenGL backend on Linux. Make sure you define OC_COMPILE_GL to 1."
#endif #endif
#define OC_COMPILE_CANVAS 1 #define OC_COMPILE_CANVAS 1
#endif #endif
#endif #endif
//NOTE: these macros are used to select backend-specific APIs to include when using milepost //NOTE: these macros are used to select backend-specific APIs to include when using milepost
#ifdef OC_EXPOSE_SURFACE_METAL #ifdef OC_EXPOSE_SURFACE_METAL
#include"mtl_surface.h" #include "mtl_surface.h"
#endif #endif
#ifdef OC_EXPOSE_SURFACE_WGL #ifdef OC_EXPOSE_SURFACE_WGL
#include"wgl_surface.h" #include "wgl_surface.h"
#endif #endif
//TODO: expose nsgl surface when supported, expose egl surface, etc... //TODO: expose nsgl surface when supported, expose egl surface, etc...
@ -92,7 +94,10 @@ ORCA_API bool oc_is_surface_api_available(oc_surface_api api);
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
//NOTE(martin): graphics surface //NOTE(martin): graphics surface
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
typedef struct oc_surface { u64 h; } oc_surface; typedef struct oc_surface
{
u64 h;
} oc_surface;
ORCA_API oc_surface oc_surface_nil(void); ORCA_API oc_surface oc_surface_nil(void);
ORCA_API bool oc_surface_is_nil(oc_surface surface); ORCA_API bool oc_surface_is_nil(oc_surface surface);
@ -121,51 +126,69 @@ ORCA_API void oc_surface_host_connect(oc_surface surface, oc_surface_id remoteId
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
//NOTE(martin): graphics canvas structs //NOTE(martin): graphics canvas structs
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
typedef struct oc_canvas { u64 h; } oc_canvas; typedef struct oc_canvas
typedef struct oc_font { u64 h; } oc_font; {
typedef struct oc_image { u64 h; } oc_image; u64 h;
} oc_canvas;
typedef struct oc_font
{
u64 h;
} oc_font;
typedef struct oc_image
{
u64 h;
} oc_image;
typedef struct oc_color typedef struct oc_color
{ {
union union
{ {
struct struct
{ {
f32 r; f32 r;
f32 g; f32 g;
f32 b; f32 b;
f32 a; f32 a;
}; };
f32 c[4];
}; f32 c[4];
};
} oc_color; } oc_color;
typedef enum {OC_JOINT_MITER = 0, typedef enum
OC_JOINT_BEVEL, {
OC_JOINT_NONE } oc_joint_type; OC_JOINT_MITER = 0,
OC_JOINT_BEVEL,
OC_JOINT_NONE
} oc_joint_type;
typedef enum {OC_CAP_NONE = 0, typedef enum
OC_CAP_SQUARE } oc_cap_type; {
OC_CAP_NONE = 0,
OC_CAP_SQUARE
} oc_cap_type;
typedef struct oc_font_extents typedef struct oc_font_extents
{ {
f32 ascent; // the extent above the baseline (by convention a positive value extends above the baseline) f32 ascent; // the extent above the baseline (by convention a positive value extends above the baseline)
f32 descent; // the extent below the baseline (by convention, positive value extends below the baseline) f32 descent; // the extent below the baseline (by convention, positive value extends below the baseline)
f32 leading; // spacing between one row's descent and the next row's ascent f32 leading; // spacing between one row's descent and the next row's ascent
f32 xHeight; // height of the lower case letter 'x' f32 xHeight; // height of the lower case letter 'x'
f32 capHeight; // height of the upper case letter 'M' f32 capHeight; // height of the upper case letter 'M'
f32 width; // maximum width of the font f32 width; // maximum width of the font
} oc_font_extents; } oc_font_extents;
typedef struct oc_text_extents typedef struct oc_text_extents
{ {
f32 xBearing; f32 xBearing;
f32 yBearing; f32 yBearing;
f32 width; f32 width;
f32 height; f32 height;
f32 xAdvance; f32 xAdvance;
f32 yAdvance; f32 yAdvance;
} oc_text_extents; } oc_text_extents;
@ -238,8 +261,8 @@ ORCA_API void oc_rect_atlas_recycle(oc_rect_atlas* atlas, oc_rect rect);
//NOTE: image atlas helpers //NOTE: image atlas helpers
typedef struct oc_image_region typedef struct oc_image_region
{ {
oc_image image; oc_image image;
oc_rect rect; oc_rect rect;
} oc_image_region; } oc_image_region;
ORCA_API oc_image_region oc_image_atlas_alloc_from_rgba8(oc_rect_atlas* atlas, oc_image backingImage, u32 width, u32 height, u8* pixels); ORCA_API oc_image_region oc_image_atlas_alloc_from_rgba8(oc_rect_atlas* atlas, oc_image backingImage, u32 width, u32 height, u8* pixels);

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: graphics_common.h * @file: graphics_common.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -8,75 +8,80 @@
#ifndef __GRAPHICS_COMMON_H_ #ifndef __GRAPHICS_COMMON_H_
#define __GRAPHICS_COMMON_H_ #define __GRAPHICS_COMMON_H_
#include"graphics.h" #include "graphics.h"
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// canvas structs // canvas structs
//------------------------------------------------------------------------ //------------------------------------------------------------------------
typedef enum { OC_PATH_MOVE, typedef enum
OC_PATH_LINE, {
OC_PATH_QUADRATIC, OC_PATH_MOVE,
OC_PATH_CUBIC } oc_path_elt_type; OC_PATH_LINE,
OC_PATH_QUADRATIC,
OC_PATH_CUBIC
} oc_path_elt_type;
typedef struct oc_path_elt typedef struct oc_path_elt
{ {
oc_path_elt_type type; oc_path_elt_type type;
oc_vec2 p[3]; oc_vec2 p[3];
} oc_path_elt; } oc_path_elt;
typedef struct oc_path_descriptor typedef struct oc_path_descriptor
{ {
u32 startIndex; u32 startIndex;
u32 count; u32 count;
oc_vec2 startPoint; oc_vec2 startPoint;
} oc_path_descriptor; } oc_path_descriptor;
typedef struct oc_attributes typedef struct oc_attributes
{ {
f32 width; f32 width;
f32 tolerance; f32 tolerance;
oc_color color; oc_color color;
oc_joint_type joint; oc_joint_type joint;
f32 maxJointExcursion; f32 maxJointExcursion;
oc_cap_type cap; oc_cap_type cap;
oc_font font; oc_font font;
f32 fontSize; f32 fontSize;
oc_image image; oc_image image;
oc_rect srcRegion; oc_rect srcRegion;
oc_mat2x3 transform; oc_mat2x3 transform;
oc_rect clip; oc_rect clip;
} oc_attributes; } oc_attributes;
typedef enum { OC_CMD_FILL, typedef enum
OC_CMD_STROKE, {
OC_CMD_JUMP OC_CMD_FILL,
} oc_primitive_cmd; OC_CMD_STROKE,
OC_CMD_JUMP
} oc_primitive_cmd;
typedef struct oc_primitive typedef struct oc_primitive
{ {
oc_primitive_cmd cmd; oc_primitive_cmd cmd;
oc_attributes attributes; oc_attributes attributes;
union union
{ {
oc_path_descriptor path; oc_path_descriptor path;
oc_rect rect; oc_rect rect;
u32 jump; u32 jump;
}; };
} oc_primitive; } oc_primitive;
ORCA_API void oc_surface_render_commands(oc_surface surface, ORCA_API void oc_surface_render_commands(oc_surface surface,
oc_color clearColor, oc_color clearColor,
u32 primitiveCount, u32 primitiveCount,
oc_primitive* primitives, oc_primitive* primitives,
u32 eltCount, u32 eltCount,
oc_path_elt* elements); oc_path_elt* elements);
#endif //__GRAPHICS_COMMON_H_ #endif //__GRAPHICS_COMMON_H_

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: graphics_surface.c * @file: graphics_surface.c
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,13 +6,13 @@
* *
*****************************************************************/ *****************************************************************/
#include"graphics_surface.h" #include "graphics_surface.h"
//--------------------------------------------------------------- //---------------------------------------------------------------
// per-thread selected surface // per-thread selected surface
//--------------------------------------------------------------- //---------------------------------------------------------------
oc_thread_local oc_surface oc_selectedSurface = {0}; oc_thread_local oc_surface oc_selectedSurface = { 0 };
//--------------------------------------------------------------- //---------------------------------------------------------------
// typed handles functions // typed handles functions
@ -20,26 +20,26 @@ oc_thread_local oc_surface oc_selectedSurface = {0};
oc_surface oc_surface_handle_alloc(oc_surface_data* surface) oc_surface oc_surface_handle_alloc(oc_surface_data* surface)
{ {
oc_surface handle = {.h = oc_graphics_handle_alloc(OC_GRAPHICS_HANDLE_SURFACE, (void*)surface) }; oc_surface handle = { .h = oc_graphics_handle_alloc(OC_GRAPHICS_HANDLE_SURFACE, (void*)surface) };
return(handle); return (handle);
} }
oc_surface_data* oc_surface_data_from_handle(oc_surface handle) oc_surface_data* oc_surface_data_from_handle(oc_surface handle)
{ {
oc_surface_data* data = oc_graphics_data_from_handle(OC_GRAPHICS_HANDLE_SURFACE, handle.h); oc_surface_data* data = oc_graphics_data_from_handle(OC_GRAPHICS_HANDLE_SURFACE, handle.h);
return(data); return (data);
} }
oc_image oc_image_handle_alloc(oc_image_data* image) oc_image oc_image_handle_alloc(oc_image_data* image)
{ {
oc_image handle = {.h = oc_graphics_handle_alloc(OC_GRAPHICS_HANDLE_IMAGE, (void*)image) }; oc_image handle = { .h = oc_graphics_handle_alloc(OC_GRAPHICS_HANDLE_IMAGE, (void*)image) };
return(handle); return (handle);
} }
oc_image_data* oc_image_data_from_handle(oc_image handle) oc_image_data* oc_image_data_from_handle(oc_image handle)
{ {
oc_image_data* data = oc_graphics_data_from_handle(OC_GRAPHICS_HANDLE_IMAGE, handle.h); oc_image_data* data = oc_graphics_data_from_handle(OC_GRAPHICS_HANDLE_IMAGE, handle.h);
return(data); return (data);
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
@ -47,304 +47,305 @@ oc_image_data* oc_image_data_from_handle(oc_image handle)
//--------------------------------------------------------------- //---------------------------------------------------------------
#if OC_COMPILE_GL #if OC_COMPILE_GL
#if OC_PLATFORM_WINDOWS #if OC_PLATFORM_WINDOWS
#include"wgl_surface.h" #include "wgl_surface.h"
#define oc_gl_surface_create_for_window oc_wgl_surface_create_for_window #define oc_gl_surface_create_for_window oc_wgl_surface_create_for_window
#endif #endif
#endif #endif
#if OC_COMPILE_GLES #if OC_COMPILE_GLES
#include"egl_surface.h" #include "egl_surface.h"
#endif #endif
#if OC_COMPILE_METAL #if OC_COMPILE_METAL
#include"mtl_surface.h" #include "mtl_surface.h"
#endif #endif
#if OC_COMPILE_CANVAS #if OC_COMPILE_CANVAS
#if OC_PLATFORM_MACOS #if OC_PLATFORM_MACOS
oc_surface_data* oc_mtl_canvas_surface_create_for_window(oc_window window); oc_surface_data* oc_mtl_canvas_surface_create_for_window(oc_window window);
#elif OC_PLATFORM_WINDOWS #elif OC_PLATFORM_WINDOWS
oc_surface_data* oc_gl_canvas_surface_create_for_window(oc_window window); oc_surface_data* oc_gl_canvas_surface_create_for_window(oc_window window);
#endif #endif
#endif #endif
bool oc_is_surface_backend_available(oc_surface_api api) bool oc_is_surface_backend_available(oc_surface_api api)
{ {
bool result = false; bool result = false;
switch(api) switch(api)
{ {
#if OC_COMPILE_METAL #if OC_COMPILE_METAL
case OC_METAL: case OC_METAL:
#endif #endif
#if OC_COMPILE_GL #if OC_COMPILE_GL
case OC_GL: case OC_GL:
#endif #endif
#if OC_COMPILE_GLES #if OC_COMPILE_GLES
case OC_GLES: case OC_GLES:
#endif #endif
#if OC_COMPILE_CANVAS #if OC_COMPILE_CANVAS
case OC_CANVAS: case OC_CANVAS:
#endif #endif
result = true; result = true;
break; break;
default: default:
break; break;
} }
return(result); return (result);
} }
oc_surface oc_surface_nil() { return((oc_surface){.h = 0}); } oc_surface oc_surface_nil() { return ((oc_surface){ .h = 0 }); }
bool oc_surface_is_nil(oc_surface surface) { return(surface.h == 0); }
bool oc_surface_is_nil(oc_surface surface) { return (surface.h == 0); }
oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api) oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api)
{ {
if(oc_graphicsData.init) if(oc_graphicsData.init)
{ {
oc_graphics_init(); oc_graphics_init();
} }
oc_surface surfaceHandle = oc_surface_nil(); oc_surface surfaceHandle = oc_surface_nil();
oc_surface_data* surface = 0; oc_surface_data* surface = 0;
switch(api) switch(api)
{ {
#if OC_COMPILE_GL #if OC_COMPILE_GL
case OC_GL: case OC_GL:
surface = oc_gl_surface_create_for_window(window); surface = oc_gl_surface_create_for_window(window);
break; break;
#endif #endif
#if OC_COMPILE_GLES #if OC_COMPILE_GLES
case OC_GLES: case OC_GLES:
surface = oc_egl_surface_create_for_window(window); surface = oc_egl_surface_create_for_window(window);
break; break;
#endif #endif
#if OC_COMPILE_METAL #if OC_COMPILE_METAL
case OC_METAL: case OC_METAL:
surface = oc_mtl_surface_create_for_window(window); surface = oc_mtl_surface_create_for_window(window);
break; break;
#endif #endif
#if OC_COMPILE_CANVAS #if OC_COMPILE_CANVAS
case OC_CANVAS: case OC_CANVAS:
#if OC_PLATFORM_MACOS #if OC_PLATFORM_MACOS
surface = oc_mtl_canvas_surface_create_for_window(window); surface = oc_mtl_canvas_surface_create_for_window(window);
#elif OC_PLATFORM_WINDOWS #elif OC_PLATFORM_WINDOWS
surface = oc_gl_canvas_surface_create_for_window(window); surface = oc_gl_canvas_surface_create_for_window(window);
#endif #endif
break; break;
#endif #endif
default: default:
break; break;
} }
if(surface) if(surface)
{ {
surfaceHandle = oc_surface_handle_alloc(surface); surfaceHandle = oc_surface_handle_alloc(surface);
oc_surface_select(surfaceHandle); oc_surface_select(surfaceHandle);
} }
return(surfaceHandle); return (surfaceHandle);
} }
oc_surface oc_surface_create_remote(u32 width, u32 height, oc_surface_api api) oc_surface oc_surface_create_remote(u32 width, u32 height, oc_surface_api api)
{ {
if(!oc_graphicsData.init) if(!oc_graphicsData.init)
{ {
oc_graphics_init(); oc_graphics_init();
} }
oc_surface surfaceHandle = oc_surface_nil(); oc_surface surfaceHandle = oc_surface_nil();
oc_surface_data* surface = 0; oc_surface_data* surface = 0;
switch(api) switch(api)
{ {
#if OC_COMPILE_GLES #if OC_COMPILE_GLES
case OC_GLES: case OC_GLES:
surface = oc_egl_surface_create_remote(width, height); surface = oc_egl_surface_create_remote(width, height);
break; break;
#endif #endif
default: default:
break; break;
} }
if(surface) if(surface)
{ {
surfaceHandle = oc_surface_handle_alloc(surface); surfaceHandle = oc_surface_handle_alloc(surface);
oc_surface_select(surfaceHandle); oc_surface_select(surfaceHandle);
} }
return(surfaceHandle); return (surfaceHandle);
} }
oc_surface oc_surface_create_host(oc_window window) oc_surface oc_surface_create_host(oc_window window)
{ {
if(!oc_graphicsData.init) if(!oc_graphicsData.init)
{ {
oc_graphics_init(); oc_graphics_init();
} }
oc_surface handle = oc_surface_nil(); oc_surface handle = oc_surface_nil();
oc_surface_data* surface = 0; oc_surface_data* surface = 0;
#if OC_PLATFORM_MACOS #if OC_PLATFORM_MACOS
surface = oc_osx_surface_create_host(window); surface = oc_osx_surface_create_host(window);
#elif OC_PLATFORM_WINDOWS #elif OC_PLATFORM_WINDOWS
surface = oc_win32_surface_create_host(window); surface = oc_win32_surface_create_host(window);
#endif #endif
if(surface) if(surface)
{ {
handle = oc_surface_handle_alloc(surface); handle = oc_surface_handle_alloc(surface);
} }
return(handle); return (handle);
} }
void oc_surface_destroy(oc_surface handle) void oc_surface_destroy(oc_surface handle)
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
oc_surface_data* surface = oc_surface_data_from_handle(handle); oc_surface_data* surface = oc_surface_data_from_handle(handle);
if(surface) if(surface)
{ {
if(oc_selectedSurface.h == handle.h) if(oc_selectedSurface.h == handle.h)
{ {
oc_surface_deselect(); oc_surface_deselect();
} }
if(surface->backend && surface->backend->destroy) if(surface->backend && surface->backend->destroy)
{ {
surface->backend->destroy(surface->backend); surface->backend->destroy(surface->backend);
} }
surface->destroy(surface); surface->destroy(surface);
oc_graphics_handle_recycle(handle.h); oc_graphics_handle_recycle(handle.h);
} }
} }
void oc_surface_deselect() void oc_surface_deselect()
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
oc_surface_data* prevSurface = oc_surface_data_from_handle(oc_selectedSurface); oc_surface_data* prevSurface = oc_surface_data_from_handle(oc_selectedSurface);
if(prevSurface && prevSurface->deselect) if(prevSurface && prevSurface->deselect)
{ {
prevSurface->deselect(prevSurface); prevSurface->deselect(prevSurface);
} }
oc_selectedSurface = oc_surface_nil(); oc_selectedSurface = oc_surface_nil();
} }
void oc_surface_select(oc_surface surface) void oc_surface_select(oc_surface surface)
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
if(surface.h != oc_selectedSurface.h) if(surface.h != oc_selectedSurface.h)
{ {
oc_surface_deselect(); oc_surface_deselect();
} }
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->prepare) if(surfaceData && surfaceData->prepare)
{ {
surfaceData->prepare(surfaceData); surfaceData->prepare(surfaceData);
oc_selectedSurface = surface; oc_selectedSurface = surface;
} }
} }
void oc_surface_present(oc_surface surface) void oc_surface_present(oc_surface surface)
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->present) if(surfaceData && surfaceData->present)
{ {
surfaceData->present(surfaceData); surfaceData->present(surfaceData);
} }
} }
void oc_surface_swap_interval(oc_surface surface, int swap) void oc_surface_swap_interval(oc_surface surface, int swap)
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->swapInterval) if(surfaceData && surfaceData->swapInterval)
{ {
surfaceData->swapInterval(surfaceData, swap); surfaceData->swapInterval(surfaceData, swap);
} }
} }
oc_vec2 oc_surface_get_size(oc_surface surface) oc_vec2 oc_surface_get_size(oc_surface surface)
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
oc_vec2 size = {0}; oc_vec2 size = { 0 };
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->getSize) if(surfaceData && surfaceData->getSize)
{ {
size = surfaceData->getSize(surfaceData); size = surfaceData->getSize(surfaceData);
} }
return(size); return (size);
} }
oc_vec2 oc_surface_contents_scaling(oc_surface surface) oc_vec2 oc_surface_contents_scaling(oc_surface surface)
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
oc_vec2 scaling = {1, 1}; oc_vec2 scaling = { 1, 1 };
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->contentsScaling) if(surfaceData && surfaceData->contentsScaling)
{ {
scaling = surfaceData->contentsScaling(surfaceData); scaling = surfaceData->contentsScaling(surfaceData);
} }
return(scaling); return (scaling);
} }
void oc_surface_set_hidden(oc_surface surface, bool hidden) void oc_surface_set_hidden(oc_surface surface, bool hidden)
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->setHidden) if(surfaceData && surfaceData->setHidden)
{ {
surfaceData->setHidden(surfaceData, hidden); surfaceData->setHidden(surfaceData, hidden);
} }
} }
bool oc_surface_get_hidden(oc_surface surface) bool oc_surface_get_hidden(oc_surface surface)
{ {
OC_DEBUG_ASSERT(oc_graphicsData.init); OC_DEBUG_ASSERT(oc_graphicsData.init);
bool res = false; bool res = false;
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->getHidden) if(surfaceData && surfaceData->getHidden)
{ {
res = surfaceData->getHidden(surfaceData); res = surfaceData->getHidden(surfaceData);
} }
return(res); return (res);
} }
void* oc_surface_native_layer(oc_surface surface) void* oc_surface_native_layer(oc_surface surface)
{ {
void* res = 0; void* res = 0;
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->nativeLayer) if(surfaceData && surfaceData->nativeLayer)
{ {
res = surfaceData->nativeLayer(surfaceData); res = surfaceData->nativeLayer(surfaceData);
} }
return(res); return (res);
} }
oc_surface_id oc_surface_remote_id(oc_surface handle) oc_surface_id oc_surface_remote_id(oc_surface handle)
{ {
oc_surface_id remoteId = 0; oc_surface_id remoteId = 0;
oc_surface_data* surface = oc_surface_data_from_handle(handle); oc_surface_data* surface = oc_surface_data_from_handle(handle);
if(surface && surface->remoteID) if(surface && surface->remoteID)
{ {
remoteId = surface->remoteID(surface); remoteId = surface->remoteID(surface);
} }
return(remoteId); return (remoteId);
} }
void oc_surface_host_connect(oc_surface handle, oc_surface_id remoteID) void oc_surface_host_connect(oc_surface handle, oc_surface_id remoteID)
{ {
oc_surface_data* surface = oc_surface_data_from_handle(handle); oc_surface_data* surface = oc_surface_data_from_handle(handle);
if(surface && surface->hostConnect) if(surface && surface->hostConnect)
{ {
surface->hostConnect(surface, remoteID); surface->hostConnect(surface, remoteID);
} }
} }
void oc_surface_render_commands(oc_surface surface, void oc_surface_render_commands(oc_surface surface,
@ -354,21 +355,21 @@ void oc_surface_render_commands(oc_surface surface,
u32 eltCount, u32 eltCount,
oc_path_elt* elements) oc_path_elt* elements)
{ {
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surface.h != oc_selectedSurface.h) if(surface.h != oc_selectedSurface.h)
{ {
oc_log_error("surface is not selected. Make sure to call oc_surface_select() before drawing onto a surface.\n"); oc_log_error("surface is not selected. Make sure to call oc_surface_select() before drawing onto a surface.\n");
} }
else if(surfaceData && surfaceData->backend) else if(surfaceData && surfaceData->backend)
{ {
surfaceData->backend->render(surfaceData->backend, surfaceData->backend->render(surfaceData->backend,
clearColor, clearColor,
primitiveCount, primitiveCount,
primitives, primitives,
eltCount, eltCount,
elements); elements);
} }
} }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------
@ -377,78 +378,78 @@ void oc_surface_render_commands(oc_surface surface,
oc_vec2 oc_image_size(oc_image image) oc_vec2 oc_image_size(oc_image image)
{ {
oc_vec2 res = {0}; oc_vec2 res = { 0 };
oc_image_data* imageData = oc_image_data_from_handle(image); oc_image_data* imageData = oc_image_data_from_handle(image);
if(imageData) if(imageData)
{ {
res = imageData->size; res = imageData->size;
} }
return(res); return (res);
} }
oc_image oc_image_create(oc_surface surface, u32 width, u32 height) oc_image oc_image_create(oc_surface surface, u32 width, u32 height)
{ {
oc_image image = oc_image_nil(); oc_image image = oc_image_nil();
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surface.h != oc_selectedSurface.h) if(surface.h != oc_selectedSurface.h)
{ {
oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n"); oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n");
} }
else if(surfaceData && surfaceData->backend) else if(surfaceData && surfaceData->backend)
{ {
OC_DEBUG_ASSERT(surfaceData->api == OC_CANVAS); OC_DEBUG_ASSERT(surfaceData->api == OC_CANVAS);
oc_image_data* imageData = surfaceData->backend->imageCreate(surfaceData->backend, (oc_vec2){width, height}); oc_image_data* imageData = surfaceData->backend->imageCreate(surfaceData->backend, (oc_vec2){ width, height });
if(imageData) if(imageData)
{ {
imageData->surface = surface; imageData->surface = surface;
image = oc_image_handle_alloc(imageData); image = oc_image_handle_alloc(imageData);
} }
} }
return(image); return (image);
} }
void oc_image_destroy(oc_image image) void oc_image_destroy(oc_image image)
{ {
oc_image_data* imageData = oc_image_data_from_handle(image); oc_image_data* imageData = oc_image_data_from_handle(image);
if(imageData) if(imageData)
{ {
if(imageData->surface.h != oc_selectedSurface.h) if(imageData->surface.h != oc_selectedSurface.h)
{ {
oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n"); oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n");
} }
else else
{ {
oc_surface_data* surface = oc_surface_data_from_handle(imageData->surface); oc_surface_data* surface = oc_surface_data_from_handle(imageData->surface);
if(surface && surface->backend) if(surface && surface->backend)
{ {
surface->backend->imageDestroy(surface->backend, imageData); surface->backend->imageDestroy(surface->backend, imageData);
oc_graphics_handle_recycle(image.h); oc_graphics_handle_recycle(image.h);
} }
} }
} }
} }
void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels) void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels)
{ {
oc_image_data* imageData = oc_image_data_from_handle(image); oc_image_data* imageData = oc_image_data_from_handle(image);
if(imageData) if(imageData)
{ {
if(imageData->surface.h != oc_selectedSurface.h) if(imageData->surface.h != oc_selectedSurface.h)
{ {
oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n"); oc_log_error("surface is not selected. Make sure to call oc_surface_select() before modifying graphics resources.\n");
} }
else else
{ {
oc_surface_data* surfaceData = oc_surface_data_from_handle(imageData->surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(imageData->surface);
if(surfaceData) if(surfaceData)
{ {
OC_DEBUG_ASSERT(surfaceData->backend); OC_DEBUG_ASSERT(surfaceData->backend);
surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels); surfaceData->backend->imageUploadRegion(surfaceData->backend, imageData, region, pixels);
} }
} }
} }
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: graphics_surface.h * @file: graphics_surface.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -8,102 +8,103 @@
#ifndef __GRAPHICS_SURFACE_H_ #ifndef __GRAPHICS_SURFACE_H_
#define __GRAPHICS_SURFACE_H_ #define __GRAPHICS_SURFACE_H_
#include"graphics_common.h" #include "app/app_internal.h"
#include"app/app_internal.h" #include "graphics_common.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
//--------------------------------------------------------------- //---------------------------------------------------------------
// surface interface // surface interface
//--------------------------------------------------------------- //---------------------------------------------------------------
typedef struct oc_surface_data oc_surface_data; typedef struct oc_surface_data oc_surface_data;
typedef struct oc_canvas_backend oc_canvas_backend; typedef struct oc_canvas_backend oc_canvas_backend;
typedef void (*oc_surface_destroy_proc)(oc_surface_data* surface); typedef void (*oc_surface_destroy_proc)(oc_surface_data* surface);
typedef void (*oc_surface_select_proc)(oc_surface_data* surface); typedef void (*oc_surface_select_proc)(oc_surface_data* surface);
typedef void (*oc_surface_deselect_proc)(oc_surface_data* surface); typedef void (*oc_surface_deselect_proc)(oc_surface_data* surface);
typedef void (*oc_surface_present_proc)(oc_surface_data* surface); typedef void (*oc_surface_present_proc)(oc_surface_data* surface);
typedef void (*oc_surface_swap_interval_proc)(oc_surface_data* surface, int swap); typedef void (*oc_surface_swap_interval_proc)(oc_surface_data* surface, int swap);
typedef oc_vec2 (*oc_surface_get_size_proc)(oc_surface_data* surface); typedef oc_vec2 (*oc_surface_get_size_proc)(oc_surface_data* surface);
typedef oc_vec2 (*oc_surface_contents_scaling_proc)(oc_surface_data* surface); typedef oc_vec2 (*oc_surface_contents_scaling_proc)(oc_surface_data* surface);
typedef bool (*oc_surface_get_hidden_proc)(oc_surface_data* surface); typedef bool (*oc_surface_get_hidden_proc)(oc_surface_data* surface);
typedef void (*oc_surface_set_hidden_proc)(oc_surface_data* surface, bool hidden); typedef void (*oc_surface_set_hidden_proc)(oc_surface_data* surface, bool hidden);
typedef void* (*oc_surface_native_layer_proc)(oc_surface_data* surface); typedef void* (*oc_surface_native_layer_proc)(oc_surface_data* surface);
typedef oc_surface_id (*oc_surface_remote_id_proc)(oc_surface_data* surface); typedef oc_surface_id (*oc_surface_remote_id_proc)(oc_surface_data* surface);
typedef void (*oc_surface_host_connect_proc)(oc_surface_data* surface, oc_surface_id remoteId); typedef void (*oc_surface_host_connect_proc)(oc_surface_data* surface, oc_surface_id remoteId);
typedef struct oc_surface_data typedef struct oc_surface_data
{ {
oc_surface_api api; oc_surface_api api;
oc_layer layer; oc_layer layer;
oc_surface_destroy_proc destroy; oc_surface_destroy_proc destroy;
oc_surface_select_proc prepare; oc_surface_select_proc prepare;
oc_surface_present_proc present; oc_surface_present_proc present;
oc_surface_deselect_proc deselect; oc_surface_deselect_proc deselect;
oc_surface_swap_interval_proc swapInterval; oc_surface_swap_interval_proc swapInterval;
oc_surface_get_size_proc getSize; oc_surface_get_size_proc getSize;
oc_surface_contents_scaling_proc contentsScaling; oc_surface_contents_scaling_proc contentsScaling;
oc_surface_get_hidden_proc getHidden; oc_surface_get_hidden_proc getHidden;
oc_surface_set_hidden_proc setHidden; oc_surface_set_hidden_proc setHidden;
oc_surface_native_layer_proc nativeLayer; oc_surface_native_layer_proc nativeLayer;
oc_surface_remote_id_proc remoteID; oc_surface_remote_id_proc remoteID;
oc_surface_host_connect_proc hostConnect; oc_surface_host_connect_proc hostConnect;
oc_canvas_backend* backend; oc_canvas_backend* backend;
} oc_surface_data; } oc_surface_data;
oc_surface oc_surface_handle_alloc(oc_surface_data* surface); oc_surface oc_surface_handle_alloc(oc_surface_data* surface);
oc_surface_data* oc_surface_data_from_handle(oc_surface handle); oc_surface_data* oc_surface_data_from_handle(oc_surface handle);
void oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window); void oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window);
void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height); void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height);
void oc_surface_init_host(oc_surface_data* surface, oc_window_data* window); void oc_surface_init_host(oc_surface_data* surface, oc_window_data* window);
void oc_surface_cleanup(oc_surface_data* surface); void oc_surface_cleanup(oc_surface_data* surface);
void* oc_surface_native_layer(oc_surface surface); void* oc_surface_native_layer(oc_surface surface);
//--------------------------------------------------------------- //---------------------------------------------------------------
// canvas backend interface // canvas backend interface
//--------------------------------------------------------------- //---------------------------------------------------------------
typedef struct oc_image_data typedef struct oc_image_data
{ {
oc_list_elt listElt; oc_list_elt listElt;
u32 generation; u32 generation;
oc_surface surface; oc_surface surface;
oc_vec2 size; oc_vec2 size;
} oc_image_data; } oc_image_data;
typedef void (*oc_canvas_backend_destroy_proc)(oc_canvas_backend* backend); typedef void (*oc_canvas_backend_destroy_proc)(oc_canvas_backend* backend);
typedef oc_image_data* (*oc_canvas_backend_image_create_proc)(oc_canvas_backend* backend, oc_vec2 size); typedef oc_image_data* (*oc_canvas_backend_image_create_proc)(oc_canvas_backend* backend, oc_vec2 size);
typedef void (*oc_canvas_backend_image_destroy_proc)(oc_canvas_backend* backend, oc_image_data* image); typedef void (*oc_canvas_backend_image_destroy_proc)(oc_canvas_backend* backend, oc_image_data* image);
typedef void (*oc_canvas_backend_image_upload_region_proc)(oc_canvas_backend* backend, typedef void (*oc_canvas_backend_image_upload_region_proc)(oc_canvas_backend* backend,
oc_image_data* image, oc_image_data* image,
oc_rect region, oc_rect region,
u8* pixels); u8* pixels);
typedef void (*oc_canvas_backend_render_proc)(oc_canvas_backend* backend, typedef void (*oc_canvas_backend_render_proc)(oc_canvas_backend* backend,
oc_color clearColor, oc_color clearColor,
u32 primitiveCount, u32 primitiveCount,
oc_primitive* primitives, oc_primitive* primitives,
u32 eltCount, u32 eltCount,
oc_path_elt* pathElements); oc_path_elt* pathElements);
typedef struct oc_canvas_backend typedef struct oc_canvas_backend
{ {
oc_canvas_backend_destroy_proc destroy; oc_canvas_backend_destroy_proc destroy;
oc_canvas_backend_image_create_proc imageCreate; oc_canvas_backend_image_create_proc imageCreate;
oc_canvas_backend_image_destroy_proc imageDestroy; oc_canvas_backend_image_destroy_proc imageDestroy;
oc_canvas_backend_image_upload_region_proc imageUploadRegion; oc_canvas_backend_image_upload_region_proc imageUploadRegion;
oc_canvas_backend_render_proc render; oc_canvas_backend_render_proc render;
} oc_canvas_backend; } oc_canvas_backend;
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: mtl_renderer.h * @file: mtl_renderer.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -9,103 +9,111 @@
#ifndef __MTL_RENDERER_H_ #ifndef __MTL_RENDERER_H_
#define __MTL_RENDERER_H_ #define __MTL_RENDERER_H_
#include<simd/simd.h> #include <simd/simd.h>
typedef enum { typedef enum
OC_MTL_FILL, {
OC_MTL_STROKE, OC_MTL_FILL,
OC_MTL_STROKE,
} oc_mtl_cmd; } oc_mtl_cmd;
typedef struct oc_mtl_path typedef struct oc_mtl_path
{ {
oc_mtl_cmd cmd; oc_mtl_cmd cmd;
matrix_float3x3 uvTransform; matrix_float3x3 uvTransform;
vector_float4 color; vector_float4 color;
vector_float4 box; vector_float4 box;
vector_float4 clip; vector_float4 clip;
int texture; int texture;
} oc_mtl_path; } oc_mtl_path;
typedef enum { typedef enum
OC_MTL_LINE = 1, {
OC_MTL_QUADRATIC, OC_MTL_LINE = 1,
OC_MTL_CUBIC, OC_MTL_QUADRATIC,
OC_MTL_CUBIC,
} oc_mtl_seg_kind; } oc_mtl_seg_kind;
typedef struct oc_mtl_path_elt typedef struct oc_mtl_path_elt
{ {
int pathIndex; int pathIndex;
oc_mtl_seg_kind kind; oc_mtl_seg_kind kind;
vector_float2 p[4]; vector_float2 p[4];
} oc_mtl_path_elt; } oc_mtl_path_elt;
typedef enum { typedef enum
OC_MTL_BL, // curve on bottom left {
OC_MTL_BR, // curve on bottom right OC_MTL_BL, // curve on bottom left
OC_MTL_TL, // curve on top left OC_MTL_BR, // curve on bottom right
OC_MTL_TR // curve on top right OC_MTL_TL, // curve on top left
OC_MTL_TR // curve on top right
} oc_mtl_seg_config; } oc_mtl_seg_config;
typedef struct oc_mtl_segment typedef struct oc_mtl_segment
{ {
oc_mtl_seg_kind kind; oc_mtl_seg_kind kind;
int pathIndex; int pathIndex;
oc_mtl_seg_config config; //TODO pack these oc_mtl_seg_config config; //TODO pack these
int windingIncrement; int windingIncrement;
vector_float4 box; vector_float4 box;
matrix_float3x3 implicitMatrix; matrix_float3x3 implicitMatrix;
float sign; float sign;
vector_float2 hullVertex; vector_float2 hullVertex;
int debugID; int debugID;
} oc_mtl_segment; } oc_mtl_segment;
typedef struct oc_mtl_path_queue typedef struct oc_mtl_path_queue
{ {
vector_int4 area; vector_int4 area;
int tileQueues; int tileQueues;
} oc_mtl_path_queue; } oc_mtl_path_queue;
#ifdef __METAL_VERSION__ #ifdef __METAL_VERSION__
using namespace metal; using namespace metal;
#endif #endif
typedef enum { OC_MTL_OP_FILL, typedef enum
OC_MTL_OP_CLIP_FILL, {
OC_MTL_OP_START, OC_MTL_OP_FILL,
OC_MTL_OP_END, OC_MTL_OP_CLIP_FILL,
OC_MTL_OP_SEGMENT } oc_mtl_tile_op_kind; OC_MTL_OP_START,
OC_MTL_OP_END,
OC_MTL_OP_SEGMENT
} oc_mtl_tile_op_kind;
typedef struct oc_mtl_tile_op typedef struct oc_mtl_tile_op
{ {
oc_mtl_tile_op_kind kind; oc_mtl_tile_op_kind kind;
int index; int index;
int next; int next;
union
{ union
bool crossRight; {
int windingOffset; bool crossRight;
}; int windingOffset;
};
} oc_mtl_tile_op; } oc_mtl_tile_op;
typedef struct oc_mtl_tile_queue typedef struct oc_mtl_tile_queue
{ {
atomic_int windingOffset; atomic_int windingOffset;
atomic_int first; atomic_int first;
int last; int last;
} oc_mtl_tile_queue; } oc_mtl_tile_queue;
typedef struct oc_mtl_screen_tile typedef struct oc_mtl_screen_tile
{ {
vector_uint2 tileCoord; vector_uint2 tileCoord;
int first; int first;
} oc_mtl_screen_tile; } oc_mtl_screen_tile;
enum { enum
OC_MTL_MAX_IMAGES_PER_BATCH = 30 {
OC_MTL_MAX_IMAGES_PER_BATCH = 30
}; };
#endif //__MTL_RENDERER_H_ #endif //__MTL_RENDERER_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: mtl_surface.h * @file: mtl_surface.h
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -9,10 +9,10 @@
#ifndef __MTL_SURFACE_H_ #ifndef __MTL_SURFACE_H_
#define __MTL_SURFACE_H_ #define __MTL_SURFACE_H_
#include"graphics_surface.h" #include "graphics_surface.h"
#ifdef __OBJC__ #ifdef __OBJC__
#import<Metal/Metal.h> #import <Metal/Metal.h>
#endif #endif
oc_surface_data* oc_mtl_surface_create_for_window(oc_window window); oc_surface_data* oc_mtl_surface_create_for_window(oc_window window);

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: mtl_surface.m * @file: mtl_surface.m
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,63 +6,65 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#import<Metal/Metal.h> #import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
#import<QuartzCore/CAMetalLayer.h> #include <simd/simd.h>
#include<simd/simd.h>
#include"graphics_surface.h" #include "app/osx_app.h"
#include"util/macros.h" #include "graphics_surface.h"
#include"app/osx_app.h" #include "util/macros.h"
typedef struct oc_mtl_surface typedef struct oc_mtl_surface
{ {
oc_surface_data interface; oc_surface_data interface;
// permanent mtl resources // permanent mtl resources
id<MTLDevice> device; id<MTLDevice> device;
CAMetalLayer* mtlLayer; CAMetalLayer* mtlLayer;
id<MTLCommandQueue> commandQueue; id<MTLCommandQueue> commandQueue;
// transient metal resources // transient metal resources
id<CAMetalDrawable> drawable; id<CAMetalDrawable> drawable;
id<MTLCommandBuffer> commandBuffer; id<MTLCommandBuffer> commandBuffer;
} oc_mtl_surface; } oc_mtl_surface;
void oc_mtl_surface_destroy(oc_surface_data* interface) void oc_mtl_surface_destroy(oc_surface_data* interface)
{ {
oc_mtl_surface* surface = (oc_mtl_surface*)interface; oc_mtl_surface* surface = (oc_mtl_surface*)interface;
@autoreleasepool @autoreleasepool
{ {
//NOTE: when GPU frame capture is enabled, if we release resources before all work is completed, //NOTE: when GPU frame capture is enabled, if we release resources before all work is completed,
// libMetalCapture crashes... the following hack avoids this crash by enqueuing a last (empty) // libMetalCapture crashes... the following hack avoids this crash by enqueuing a last (empty)
// command buffer and waiting for it to complete, ensuring all previous buffers have completed // command buffer and waiting for it to complete, ensuring all previous buffers have completed
id<MTLCommandBuffer> endBuffer = [surface->commandQueue commandBuffer]; id<MTLCommandBuffer> endBuffer = [surface->commandQueue commandBuffer];
[endBuffer commit]; [endBuffer commit];
[endBuffer waitUntilCompleted]; [endBuffer waitUntilCompleted];
[surface->commandQueue release]; [surface->commandQueue release];
[surface->mtlLayer removeFromSuperlayer]; [surface->mtlLayer removeFromSuperlayer];
[surface->mtlLayer release]; [surface->mtlLayer release];
[surface->device release]; [surface->device release];
} }
//NOTE: we don't use oc_layer_cleanup here, because the CAMetalLayer is taken care off by the surface itself //NOTE: we don't use oc_layer_cleanup here, because the CAMetalLayer is taken care off by the surface itself
} }
void oc_mtl_surface_acquire_command_buffer(oc_mtl_surface* surface) void oc_mtl_surface_acquire_command_buffer(oc_mtl_surface* surface)
{ {
if(surface->commandBuffer == nil) if(surface->commandBuffer == nil)
{ {
surface->commandBuffer = [surface->commandQueue commandBuffer]; surface->commandBuffer = [surface->commandQueue commandBuffer];
[surface->commandBuffer retain]; [surface->commandBuffer retain];
} }
} }
void oc_mtl_surface_acquire_drawable(oc_mtl_surface* surface) void oc_mtl_surface_acquire_drawable(oc_mtl_surface* surface)
{@autoreleasepool{ {
/*WARN(martin): @autoreleasepool
{
/*WARN(martin):
//TODO: we should stop trying to render if we detect that the app is in the background //TODO: we should stop trying to render if we detect that the app is in the background
or occluded or occluded
@ -70,50 +72,51 @@ void oc_mtl_surface_acquire_drawable(oc_mtl_surface* surface)
for too long. for too long.
*/ */
//NOTE: returned drawable could be nil if we stall for more than 1s, although that never seem to happen in practice? //NOTE: returned drawable could be nil if we stall for more than 1s, although that never seem to happen in practice?
if(surface->drawable == nil) if(surface->drawable == nil)
{ {
surface->drawable = [surface->mtlLayer nextDrawable]; surface->drawable = [surface->mtlLayer nextDrawable];
if(surface->drawable) if(surface->drawable)
{ {
[surface->drawable retain]; [surface->drawable retain];
} }
} }
}} }
}
void oc_mtl_surface_prepare(oc_surface_data* interface) void oc_mtl_surface_prepare(oc_surface_data* interface)
{ {
oc_mtl_surface* surface = (oc_mtl_surface*)interface; oc_mtl_surface* surface = (oc_mtl_surface*)interface;
oc_mtl_surface_acquire_command_buffer(surface); oc_mtl_surface_acquire_command_buffer(surface);
} }
void oc_mtl_surface_present(oc_surface_data* interface) void oc_mtl_surface_present(oc_surface_data* interface)
{ {
oc_mtl_surface* surface = (oc_mtl_surface*)interface; oc_mtl_surface* surface = (oc_mtl_surface*)interface;
@autoreleasepool @autoreleasepool
{ {
if(surface->commandBuffer != nil) if(surface->commandBuffer != nil)
{ {
if(surface->drawable != nil) if(surface->drawable != nil)
{ {
[surface->commandBuffer presentDrawable: surface->drawable]; [surface->commandBuffer presentDrawable:surface->drawable];
[surface->drawable release]; [surface->drawable release];
surface->drawable = nil; surface->drawable = nil;
} }
[surface->commandBuffer commit]; [surface->commandBuffer commit];
[surface->commandBuffer release]; [surface->commandBuffer release];
surface->commandBuffer = nil; surface->commandBuffer = nil;
} }
} }
} }
void oc_mtl_surface_swap_interval(oc_surface_data* interface, int swap) void oc_mtl_surface_swap_interval(oc_surface_data* interface, int swap)
{ {
oc_mtl_surface* surface = (oc_mtl_surface*)interface; oc_mtl_surface* surface = (oc_mtl_surface*)interface;
@autoreleasepool @autoreleasepool
{ {
[surface->mtlLayer setDisplaySyncEnabled: (swap ? YES : NO)]; [surface->mtlLayer setDisplaySyncEnabled:(swap ? YES : NO)];
} }
} }
/* /*
@ -138,7 +141,6 @@ void oc_mtl_surface_set_frame(oc_surface_data* interface, oc_rect frame)
} }
*/ */
//TODO fix that according to real scaling, depending on the monitor settings //TODO fix that according to real scaling, depending on the monitor settings
static const f32 OC_MTL_SURFACE_CONTENTS_SCALING = 2; static const f32 OC_MTL_SURFACE_CONTENTS_SCALING = 2;
@ -148,135 +150,134 @@ static const int OC_MTL_MAX_FRAMES_IN_FLIGHT = 2;
oc_surface_data* oc_mtl_surface_create_for_window(oc_window window) oc_surface_data* oc_mtl_surface_create_for_window(oc_window window)
{ {
oc_mtl_surface* surface = 0; oc_mtl_surface* surface = 0;
oc_window_data* windowData = oc_window_ptr_from_handle(window); oc_window_data* windowData = oc_window_ptr_from_handle(window);
if(windowData) if(windowData)
{ {
surface = (oc_mtl_surface*)malloc(sizeof(oc_mtl_surface)); surface = (oc_mtl_surface*)malloc(sizeof(oc_mtl_surface));
oc_surface_init_for_window((oc_surface_data*)surface, windowData); oc_surface_init_for_window((oc_surface_data*)surface, windowData);
//NOTE(martin): setup interface functions //NOTE(martin): setup interface functions
surface->interface.api = OC_METAL; surface->interface.api = OC_METAL;
surface->interface.destroy = oc_mtl_surface_destroy; surface->interface.destroy = oc_mtl_surface_destroy;
surface->interface.prepare = oc_mtl_surface_prepare; surface->interface.prepare = oc_mtl_surface_prepare;
surface->interface.deselect = 0; surface->interface.deselect = 0;
surface->interface.present = oc_mtl_surface_present; surface->interface.present = oc_mtl_surface_present;
surface->interface.swapInterval = oc_mtl_surface_swap_interval; surface->interface.swapInterval = oc_mtl_surface_swap_interval;
@autoreleasepool @autoreleasepool
{ {
//----------------------------------------------------------- //-----------------------------------------------------------
//NOTE(martin): create a mtl device and a mtl layer and //NOTE(martin): create a mtl device and a mtl layer and
//----------------------------------------------------------- //-----------------------------------------------------------
/*WARN(martin): /*WARN(martin):
Calling MTLCreateDefaultSystemDevice(), as advised by the doc, hangs Discord's screen sharing... Calling MTLCreateDefaultSystemDevice(), as advised by the doc, hangs Discord's screen sharing...
The workaround I found, which doesn't make sense, is to set the mtlLayer.device to mtlLayer.preferredDevice, The workaround I found, which doesn't make sense, is to set the mtlLayer.device to mtlLayer.preferredDevice,
even if mtlLayer.preferredDevice is the same value as returned by MTLCreateDefaultSystemDevice(). even if mtlLayer.preferredDevice is the same value as returned by MTLCreateDefaultSystemDevice().
This works for now and allows screen sharing while using orca, but we'll have to revisit this when we want This works for now and allows screen sharing while using orca, but we'll have to revisit this when we want
more control over what GPU gets used. more control over what GPU gets used.
*/ */
surface->device = nil; surface->device = nil;
//Select a discrete GPU, if possible //Select a discrete GPU, if possible
NSArray<id<MTLDevice>>* devices = MTLCopyAllDevices(); NSArray<id<MTLDevice>>* devices = MTLCopyAllDevices();
for(id<MTLDevice> device in devices) for(id<MTLDevice> device in devices)
{ {
if(!device.isRemovable && !device.isLowPower) if(!device.isRemovable && !device.isLowPower)
{ {
surface->device = device; surface->device = device;
break; break;
} }
} }
if(surface->device == nil) if(surface->device == nil)
{ {
oc_log_warning("Couldn't select a discrete GPU, using first available device\n"); oc_log_warning("Couldn't select a discrete GPU, using first available device\n");
surface->device = devices[0]; surface->device = devices[0];
} }
//surface->device = MTLCreateSystemDefaultDevice(); //surface->device = MTLCreateSystemDefaultDevice();
surface->mtlLayer = [CAMetalLayer layer]; surface->mtlLayer = [CAMetalLayer layer];
[surface->mtlLayer retain]; [surface->mtlLayer retain];
surface->mtlLayer.device = surface->device; surface->mtlLayer.device = surface->device;
[surface->mtlLayer setOpaque:NO];
surface->mtlLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
[surface->interface.layer.caLayer addSublayer:(CALayer*)surface->mtlLayer];
[surface->mtlLayer setOpaque:NO]; //-----------------------------------------------------------
surface->mtlLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; //NOTE(martin): set the size and scaling
[surface->interface.layer.caLayer addSublayer: (CALayer*)surface->mtlLayer]; //-----------------------------------------------------------
NSRect frame = [[windowData->osx.nsWindow contentView] frame];
CGSize size = frame.size;
surface->mtlLayer.frame = (CGRect){ { 0, 0 }, size };
size.width *= OC_MTL_SURFACE_CONTENTS_SCALING;
size.height *= OC_MTL_SURFACE_CONTENTS_SCALING;
surface->mtlLayer.drawableSize = size;
surface->mtlLayer.contentsScale = OC_MTL_SURFACE_CONTENTS_SCALING;
//----------------------------------------------------------- surface->mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
//NOTE(martin): set the size and scaling
//-----------------------------------------------------------
NSRect frame = [[windowData->osx.nsWindow contentView] frame];
CGSize size = frame.size;
surface->mtlLayer.frame = (CGRect){{0, 0}, size};
size.width *= OC_MTL_SURFACE_CONTENTS_SCALING;
size.height *= OC_MTL_SURFACE_CONTENTS_SCALING;
surface->mtlLayer.drawableSize = size;
surface->mtlLayer.contentsScale = OC_MTL_SURFACE_CONTENTS_SCALING;
surface->mtlLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; //NOTE(martin): handling resizing
// surface->mtlLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
// surface->mtlLayer.needsDisplayOnBoundsChange = YES;
//NOTE(martin): handling resizing //-----------------------------------------------------------
// surface->mtlLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable; //NOTE(martin): create a command queue
// surface->mtlLayer.needsDisplayOnBoundsChange = YES; //-----------------------------------------------------------
surface->commandQueue = [surface->device newCommandQueue];
[surface->commandQueue retain];
//----------------------------------------------------------- //NOTE(martin): command buffer and drawable are set on demand and at the end of each present() call
//NOTE(martin): create a command queue surface->drawable = nil;
//----------------------------------------------------------- surface->commandBuffer = nil;
surface->commandQueue = [surface->device newCommandQueue]; }
[surface->commandQueue retain]; }
return ((oc_surface_data*)surface);
//NOTE(martin): command buffer and drawable are set on demand and at the end of each present() call
surface->drawable = nil;
surface->commandBuffer = nil;
}
}
return((oc_surface_data*)surface);
} }
void* oc_mtl_surface_layer(oc_surface surface) void* oc_mtl_surface_layer(oc_surface surface)
{ {
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->api == OC_METAL) if(surfaceData && surfaceData->api == OC_METAL)
{ {
oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData; oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData;
return(mtlSurface->mtlLayer); return (mtlSurface->mtlLayer);
} }
else else
{ {
return(nil); return (nil);
} }
} }
void* oc_mtl_surface_drawable(oc_surface surface) void* oc_mtl_surface_drawable(oc_surface surface)
{ {
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->api == OC_METAL) if(surfaceData && surfaceData->api == OC_METAL)
{ {
oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData; oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData;
oc_mtl_surface_acquire_drawable(mtlSurface); oc_mtl_surface_acquire_drawable(mtlSurface);
return(mtlSurface->drawable); return (mtlSurface->drawable);
} }
else else
{ {
return(nil); return (nil);
} }
} }
void* oc_mtl_surface_command_buffer(oc_surface surface) void* oc_mtl_surface_command_buffer(oc_surface surface)
{ {
oc_surface_data* surfaceData = oc_surface_data_from_handle(surface); oc_surface_data* surfaceData = oc_surface_data_from_handle(surface);
if(surfaceData && surfaceData->api == OC_METAL) if(surfaceData && surfaceData->api == OC_METAL)
{ {
oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData; oc_mtl_surface* mtlSurface = (oc_mtl_surface*)surfaceData;
oc_mtl_surface_acquire_command_buffer(mtlSurface); oc_mtl_surface_acquire_command_buffer(mtlSurface);
return(mtlSurface->commandBuffer); return (mtlSurface->commandBuffer);
} }
else else
{ {
return(nil); return (nil);
} }
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: wgl_surface.c * @file: wgl_surface.c
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -6,273 +6,272 @@
* @revision: * @revision:
* *
*****************************************************************/ *****************************************************************/
#include"app/win32_app.h" #include "app/win32_app.h"
#include"graphics_surface.h" #include "gl_loader.h"
#include"gl_loader.h" #include "graphics_surface.h"
#include<GL/wglext.h> #include "util/macros.h"
#include"util/macros.h" #include <GL/wglext.h>
#define OC_WGL_PROC_LIST \ #define OC_WGL_PROC_LIST \
OC_WGL_PROC(WGLCHOOSEPIXELFORMATARB, wglChoosePixelFormatARB) \ OC_WGL_PROC(WGLCHOOSEPIXELFORMATARB, wglChoosePixelFormatARB) \
OC_WGL_PROC(WGLCREATECONTEXTATTRIBSARB, wglCreateContextAttribsARB) \ OC_WGL_PROC(WGLCREATECONTEXTATTRIBSARB, wglCreateContextAttribsARB) \
OC_WGL_PROC(WGLMAKECONTEXTCURRENTARB, wglMakeContextCurrentARB) \ OC_WGL_PROC(WGLMAKECONTEXTCURRENTARB, wglMakeContextCurrentARB) \
OC_WGL_PROC(WGLSWAPINTERVALEXT, wglSwapIntervalEXT) \ OC_WGL_PROC(WGLSWAPINTERVALEXT, wglSwapIntervalEXT)
//NOTE: wgl function pointers declarations //NOTE: wgl function pointers declarations
#define OC_WGL_PROC(type, name) OC_CAT3(PFN, type, PROC) name = 0; #define OC_WGL_PROC(type, name) OC_CAT3(PFN, type, PROC) name = 0;
OC_WGL_PROC_LIST OC_WGL_PROC_LIST
#undef OC_WGL_PROC #undef OC_WGL_PROC
//NOTE: wgl loader //NOTE: wgl loader
typedef struct oc_wgl_dummy_context typedef struct oc_wgl_dummy_context
{ {
bool init; bool init;
HWND hWnd; HWND hWnd;
HDC hDC; HDC hDC;
HGLRC glContext; HGLRC glContext;
} oc_wgl_dummy_context; } oc_wgl_dummy_context;
static oc_wgl_dummy_context oc_wglDummyContext = {0}; static oc_wgl_dummy_context oc_wglDummyContext = { 0 };
static void oc_wgl_init() static void oc_wgl_init()
{ {
if(!oc_wglDummyContext.init) if(!oc_wglDummyContext.init)
{ {
//NOTE: create a dummy window //NOTE: create a dummy window
WNDCLASS windowClass = {.style = CS_OWNDC, WNDCLASS windowClass = { .style = CS_OWNDC,
.lpfnWndProc = DefWindowProc, .lpfnWndProc = DefWindowProc,
.hInstance = GetModuleHandleW(NULL), .hInstance = GetModuleHandleW(NULL),
.lpszClassName = "oc_wgl_helper_window_class", .lpszClassName = "oc_wgl_helper_window_class",
.hCursor = LoadCursor(0, IDC_ARROW)}; .hCursor = LoadCursor(0, IDC_ARROW) };
if(!RegisterClass(&windowClass)) if(!RegisterClass(&windowClass))
{ {
//TODO: error //TODO: error
goto quit; goto quit;
} }
oc_wglDummyContext.hWnd = CreateWindow("oc_wgl_helper_window_class", oc_wglDummyContext.hWnd = CreateWindow("oc_wgl_helper_window_class",
"dummy", "dummy",
WS_OVERLAPPEDWINDOW, WS_OVERLAPPEDWINDOW,
0, 0, 100, 100, 0, 0, 100, 100,
0, 0, windowClass.hInstance, 0); 0, 0, windowClass.hInstance, 0);
if(!oc_wglDummyContext.hWnd) if(!oc_wglDummyContext.hWnd)
{ {
//TODO: error //TODO: error
goto quit; goto quit;
} }
oc_wglDummyContext.hDC = GetDC(oc_wglDummyContext.hWnd); oc_wglDummyContext.hDC = GetDC(oc_wglDummyContext.hWnd);
PIXELFORMATDESCRIPTOR pixelFormatDesc = PIXELFORMATDESCRIPTOR pixelFormatDesc = {
{ sizeof(PIXELFORMATDESCRIPTOR),
sizeof(PIXELFORMATDESCRIPTOR), 1,
1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. 32, // Colordepth of the framebuffer.
32, // Colordepth of the framebuffer. 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0,
0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 24, // Number of bits for the depthbuffer
24, // Number of bits for the depthbuffer 8, // Number of bits for the stencilbuffer
8, // Number of bits for the stencilbuffer 0, // Number of Aux buffers in the framebuffer.
0, // Number of Aux buffers in the framebuffer. PFD_MAIN_PLANE,
PFD_MAIN_PLANE, 0,
0, 0, 0, 0
0, 0, 0 };
};
int pixelFormat = ChoosePixelFormat(oc_wglDummyContext.hDC, &pixelFormatDesc); int pixelFormat = ChoosePixelFormat(oc_wglDummyContext.hDC, &pixelFormatDesc);
SetPixelFormat(oc_wglDummyContext.hDC, pixelFormat, &pixelFormatDesc); SetPixelFormat(oc_wglDummyContext.hDC, pixelFormat, &pixelFormatDesc);
oc_wglDummyContext.glContext = wglCreateContext(oc_wglDummyContext.hDC); oc_wglDummyContext.glContext = wglCreateContext(oc_wglDummyContext.hDC);
wglMakeCurrent(oc_wglDummyContext.hDC, oc_wglDummyContext.glContext); wglMakeCurrent(oc_wglDummyContext.hDC, oc_wglDummyContext.glContext);
//NOTE(martin): now load WGL extension functions //NOTE(martin): now load WGL extension functions
#define OC_WGL_PROC(type, name) name = (OC_CAT3(PFN, type, PROC))wglGetProcAddress( #name ); #define OC_WGL_PROC(type, name) name = (OC_CAT3(PFN, type, PROC))wglGetProcAddress(#name);
OC_WGL_PROC_LIST OC_WGL_PROC_LIST
#undef OC_WGL_PROC #undef OC_WGL_PROC
oc_wglDummyContext.init = true; oc_wglDummyContext.init = true;
} }
else else
{ {
wglMakeCurrent(oc_wglDummyContext.hDC, oc_wglDummyContext.glContext); wglMakeCurrent(oc_wglDummyContext.hDC, oc_wglDummyContext.glContext);
} }
quit:; quit:;
} }
#undef OC_WGL_PROC_LIST #undef OC_WGL_PROC_LIST
typedef struct oc_wgl_surface typedef struct oc_wgl_surface
{ {
oc_surface_data interface; oc_surface_data interface;
HDC hDC; HDC hDC;
HGLRC glContext; HGLRC glContext;
//NOTE: this may be a bit wasteful to have one api struct per surface, but win32 docs says that loading procs //NOTE: this may be a bit wasteful to have one api struct per surface, but win32 docs says that loading procs
// from different contexts might select different implementations (eg. depending on context version/pixel format) // from different contexts might select different implementations (eg. depending on context version/pixel format)
oc_gl_api api; oc_gl_api api;
} oc_wgl_surface; } oc_wgl_surface;
void oc_wgl_surface_destroy(oc_surface_data* interface) void oc_wgl_surface_destroy(oc_surface_data* interface)
{ {
oc_wgl_surface* surface = (oc_wgl_surface*)interface; oc_wgl_surface* surface = (oc_wgl_surface*)interface;
if(surface->glContext == wglGetCurrentContext()) if(surface->glContext == wglGetCurrentContext())
{ {
wglMakeCurrent(NULL, NULL); wglMakeCurrent(NULL, NULL);
} }
wglDeleteContext(surface->glContext); wglDeleteContext(surface->glContext);
oc_surface_cleanup(interface); oc_surface_cleanup(interface);
free(surface); free(surface);
} }
void oc_wgl_surface_prepare(oc_surface_data* interface) void oc_wgl_surface_prepare(oc_surface_data* interface)
{ {
oc_wgl_surface* surface = (oc_wgl_surface*)interface; oc_wgl_surface* surface = (oc_wgl_surface*)interface;
wglMakeCurrent(surface->hDC, surface->glContext); wglMakeCurrent(surface->hDC, surface->glContext);
oc_gl_select_api(&surface->api); oc_gl_select_api(&surface->api);
} }
void oc_wgl_surface_present(oc_surface_data* interface) void oc_wgl_surface_present(oc_surface_data* interface)
{ {
oc_wgl_surface* surface = (oc_wgl_surface*)interface; oc_wgl_surface* surface = (oc_wgl_surface*)interface;
SwapBuffers(surface->hDC); SwapBuffers(surface->hDC);
} }
void oc_wgl_surface_deselect(oc_surface_data* interface) void oc_wgl_surface_deselect(oc_surface_data* interface)
{ {
wglMakeCurrent(NULL, NULL); wglMakeCurrent(NULL, NULL);
oc_gl_deselect_api(); oc_gl_deselect_api();
} }
void oc_wgl_surface_swap_interval(oc_surface_data* interface, int swap) void oc_wgl_surface_swap_interval(oc_surface_data* interface, int swap)
{ {
oc_wgl_surface* surface = (oc_wgl_surface*)interface; oc_wgl_surface* surface = (oc_wgl_surface*)interface;
wglSwapIntervalEXT(swap); wglSwapIntervalEXT(swap);
} }
void* oc_wgl_get_proc(const char* name) void* oc_wgl_get_proc(const char* name)
{ {
void* p = wglGetProcAddress(name); void* p = wglGetProcAddress(name);
if( p == 0 if(p == 0
|| p == (void*)0x01 || p == (void*)0x01
|| p == (void*)0x02 || p == (void*)0x02
|| p == (void*)0x03 || p == (void*)0x03
|| p == (void*)(-1)) || p == (void*)(-1))
{ {
//TODO: should we avoid re-loading every time? //TODO: should we avoid re-loading every time?
HMODULE module = LoadLibrary("opengl32.dll"); HMODULE module = LoadLibrary("opengl32.dll");
p = (void*)GetProcAddress(module, name); p = (void*)GetProcAddress(module, name);
} }
return(p); return (p);
} }
oc_surface_data* oc_wgl_surface_create_for_window(oc_window window) oc_surface_data* oc_wgl_surface_create_for_window(oc_window window)
{ {
oc_wgl_surface* surface = 0; oc_wgl_surface* surface = 0;
oc_window_data* windowData = oc_window_ptr_from_handle(window); oc_window_data* windowData = oc_window_ptr_from_handle(window);
if(windowData) if(windowData)
{ {
oc_wgl_init(); oc_wgl_init();
//NOTE: fill surface data and load api //NOTE: fill surface data and load api
surface = oc_malloc_type(oc_wgl_surface); surface = oc_malloc_type(oc_wgl_surface);
if(surface) if(surface)
{ {
memset(surface, 0, sizeof(oc_wgl_surface)); memset(surface, 0, sizeof(oc_wgl_surface));
oc_surface_init_for_window((oc_surface_data*)surface, windowData); oc_surface_init_for_window((oc_surface_data*)surface, windowData);
surface->interface.api = OC_GL; surface->interface.api = OC_GL;
surface->interface.destroy = oc_wgl_surface_destroy; surface->interface.destroy = oc_wgl_surface_destroy;
surface->interface.prepare = oc_wgl_surface_prepare; surface->interface.prepare = oc_wgl_surface_prepare;
surface->interface.present = oc_wgl_surface_present; surface->interface.present = oc_wgl_surface_present;
surface->interface.swapInterval = oc_wgl_surface_swap_interval; surface->interface.swapInterval = oc_wgl_surface_swap_interval;
surface->interface.deselect = oc_wgl_surface_deselect; surface->interface.deselect = oc_wgl_surface_deselect;
surface->hDC = GetDC(surface->interface.layer.hWnd); surface->hDC = GetDC(surface->interface.layer.hWnd);
//NOTE(martin): create the pixel format and gl context //NOTE(martin): create the pixel format and gl context
PIXELFORMATDESCRIPTOR pixelFormatDesc = PIXELFORMATDESCRIPTOR pixelFormatDesc = {
{ sizeof(PIXELFORMATDESCRIPTOR),
sizeof(PIXELFORMATDESCRIPTOR), 1,
1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. 32, // Colordepth of the framebuffer.
32, // Colordepth of the framebuffer. 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0,
0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 24, // Number of bits for the depthbuffer
24, // Number of bits for the depthbuffer 8, // Number of bits for the stencilbuffer
8, // Number of bits for the stencilbuffer 0, // Number of Aux buffers in the framebuffer.
0, // Number of Aux buffers in the framebuffer. PFD_MAIN_PLANE,
PFD_MAIN_PLANE, 0,
0, 0, 0, 0
0, 0, 0 };
};
int pixelFormatAttrs[] = { int pixelFormatAttrs[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_TRANSPARENT_ARB, TRUE, WGL_TRANSPARENT_ARB, TRUE,
WGL_COLOR_BITS_ARB, 32, WGL_COLOR_BITS_ARB, 32,
WGL_RED_BITS_ARB, 8, WGL_RED_BITS_ARB, 8,
WGL_GREEN_BITS_ARB, 8, WGL_GREEN_BITS_ARB, 8,
WGL_BLUE_BITS_ARB, 8, WGL_BLUE_BITS_ARB, 8,
WGL_ALPHA_BITS_ARB, 8, WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 24, WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8, WGL_STENCIL_BITS_ARB, 8,
0}; 0
};
u32 numFormats = 0; u32 numFormats = 0;
int pixelFormat = 0; int pixelFormat = 0;
wglChoosePixelFormatARB(surface->hDC, pixelFormatAttrs, 0, 1, &pixelFormat, &numFormats); wglChoosePixelFormatARB(surface->hDC, pixelFormatAttrs, 0, 1, &pixelFormat, &numFormats);
if(!pixelFormat) if(!pixelFormat)
{ {
//TODO: error //TODO: error
} }
SetPixelFormat(surface->hDC, pixelFormat, &pixelFormatDesc); SetPixelFormat(surface->hDC, pixelFormat, &pixelFormatDesc);
int contextAttrs[] = { int contextAttrs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 4, WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4, WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0}; 0
};
surface->glContext = wglCreateContextAttribsARB(surface->hDC, oc_wglDummyContext.glContext, contextAttrs); surface->glContext = wglCreateContextAttribsARB(surface->hDC, oc_wglDummyContext.glContext, contextAttrs);
if(!surface->glContext) if(!surface->glContext)
{ {
//TODO error //TODO error
int error = GetLastError(); int error = GetLastError();
printf("error: %i\n", error); printf("error: %i\n", error);
} }
//NOTE: make gl context current and load api //NOTE: make gl context current and load api
wglMakeCurrent(surface->hDC, surface->glContext); wglMakeCurrent(surface->hDC, surface->glContext);
wglSwapIntervalEXT(1); wglSwapIntervalEXT(1);
oc_gl_load_gl44(&surface->api, oc_wgl_get_proc); oc_gl_load_gl44(&surface->api, oc_wgl_get_proc);
} }
} }
return((oc_surface_data*)surface); return ((oc_surface_data*)surface);
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: wgl_surface.c * @file: wgl_surface.c
* @author: Martin Fouilleul * @author: Martin Fouilleul
@ -9,7 +9,7 @@
#ifndef __WGL_SURFACE_H_ #ifndef __WGL_SURFACE_H_
#define __WGL_SURFACE_H_ #define __WGL_SURFACE_H_
#include"graphics_surface.h" #include "graphics_surface.h"
oc_surface_data* oc_wgl_surface_create_for_window(oc_window window); oc_surface_data* oc_wgl_surface_create_for_window(oc_window window);

View File

@ -1,14 +1,14 @@
#include "platform/platform_debug.h"
#include <features.h> #include <features.h>
#include"platform/platform_debug.h"
#undef assert #undef assert
#ifdef NDEBUG #ifdef NDEBUG
#define assert(x) (void)0 #define assert(x) (void)0
#else #else
#define assert(x) OC_ASSERT(x) #define assert(x) OC_ASSERT(x)
#endif #endif
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus) #if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
#define static_assert _Static_assert #define static_assert _Static_assert
#endif #endif

View File

@ -1,134 +1,134 @@
#define EPERM 1 #define EPERM 1
#define ENOENT 2 #define ENOENT 2
#define ESRCH 3 #define ESRCH 3
#define EINTR 4 #define EINTR 4
#define EIO 5 #define EIO 5
#define ENXIO 6 #define ENXIO 6
#define E2BIG 7 #define E2BIG 7
#define ENOEXEC 8 #define ENOEXEC 8
#define EBADF 9 #define EBADF 9
#define ECHILD 10 #define ECHILD 10
#define EAGAIN 11 #define EAGAIN 11
#define ENOMEM 12 #define ENOMEM 12
#define EACCES 13 #define EACCES 13
#define EFAULT 14 #define EFAULT 14
#define ENOTBLK 15 #define ENOTBLK 15
#define EBUSY 16 #define EBUSY 16
#define EEXIST 17 #define EEXIST 17
#define EXDEV 18 #define EXDEV 18
#define ENODEV 19 #define ENODEV 19
#define ENOTDIR 20 #define ENOTDIR 20
#define EISDIR 21 #define EISDIR 21
#define EINVAL 22 #define EINVAL 22
#define ENFILE 23 #define ENFILE 23
#define EMFILE 24 #define EMFILE 24
#define ENOTTY 25 #define ENOTTY 25
#define ETXTBSY 26 #define ETXTBSY 26
#define EFBIG 27 #define EFBIG 27
#define ENOSPC 28 #define ENOSPC 28
#define ESPIPE 29 #define ESPIPE 29
#define EROFS 30 #define EROFS 30
#define EMLINK 31 #define EMLINK 31
#define EPIPE 32 #define EPIPE 32
#define EDOM 33 #define EDOM 33
#define ERANGE 34 #define ERANGE 34
#define EDEADLK 35 #define EDEADLK 35
#define ENAMETOOLONG 36 #define ENAMETOOLONG 36
#define ENOLCK 37 #define ENOLCK 37
#define ENOSYS 38 #define ENOSYS 38
#define ENOTEMPTY 39 #define ENOTEMPTY 39
#define ELOOP 40 #define ELOOP 40
#define EWOULDBLOCK EAGAIN #define EWOULDBLOCK EAGAIN
#define ENOMSG 42 #define ENOMSG 42
#define EIDRM 43 #define EIDRM 43
#define ECHRNG 44 #define ECHRNG 44
#define EL2NSYNC 45 #define EL2NSYNC 45
#define EL3HLT 46 #define EL3HLT 46
#define EL3RST 47 #define EL3RST 47
#define ELNRNG 48 #define ELNRNG 48
#define EUNATCH 49 #define EUNATCH 49
#define ENOCSI 50 #define ENOCSI 50
#define EL2HLT 51 #define EL2HLT 51
#define EBADE 52 #define EBADE 52
#define EBADR 53 #define EBADR 53
#define EXFULL 54 #define EXFULL 54
#define ENOANO 55 #define ENOANO 55
#define EBADRQC 56 #define EBADRQC 56
#define EBADSLT 57 #define EBADSLT 57
#define EDEADLOCK EDEADLK #define EDEADLOCK EDEADLK
#define EBFONT 59 #define EBFONT 59
#define ENOSTR 60 #define ENOSTR 60
#define ENODATA 61 #define ENODATA 61
#define ETIME 62 #define ETIME 62
#define ENOSR 63 #define ENOSR 63
#define ENONET 64 #define ENONET 64
#define ENOPKG 65 #define ENOPKG 65
#define EREMOTE 66 #define EREMOTE 66
#define ENOLINK 67 #define ENOLINK 67
#define EADV 68 #define EADV 68
#define ESRMNT 69 #define ESRMNT 69
#define ECOMM 70 #define ECOMM 70
#define EPROTO 71 #define EPROTO 71
#define EMULTIHOP 72 #define EMULTIHOP 72
#define EDOTDOT 73 #define EDOTDOT 73
#define EBADMSG 74 #define EBADMSG 74
#define EOVERFLOW 75 #define EOVERFLOW 75
#define ENOTUNIQ 76 #define ENOTUNIQ 76
#define EBADFD 77 #define EBADFD 77
#define EREMCHG 78 #define EREMCHG 78
#define ELIBACC 79 #define ELIBACC 79
#define ELIBBAD 80 #define ELIBBAD 80
#define ELIBSCN 81 #define ELIBSCN 81
#define ELIBMAX 82 #define ELIBMAX 82
#define ELIBEXEC 83 #define ELIBEXEC 83
#define EILSEQ 84 #define EILSEQ 84
#define ERESTART 85 #define ERESTART 85
#define ESTRPIPE 86 #define ESTRPIPE 86
#define EUSERS 87 #define EUSERS 87
#define ENOTSOCK 88 #define ENOTSOCK 88
#define EDESTADDRREQ 89 #define EDESTADDRREQ 89
#define EMSGSIZE 90 #define EMSGSIZE 90
#define EPROTOTYPE 91 #define EPROTOTYPE 91
#define ENOPROTOOPT 92 #define ENOPROTOOPT 92
#define EPROTONOSUPPORT 93 #define EPROTONOSUPPORT 93
#define ESOCKTNOSUPPORT 94 #define ESOCKTNOSUPPORT 94
#define EOPNOTSUPP 95 #define EOPNOTSUPP 95
#define ENOTSUP EOPNOTSUPP #define ENOTSUP EOPNOTSUPP
#define EPFNOSUPPORT 96 #define EPFNOSUPPORT 96
#define EAFNOSUPPORT 97 #define EAFNOSUPPORT 97
#define EADDRINUSE 98 #define EADDRINUSE 98
#define EADDRNOTAVAIL 99 #define EADDRNOTAVAIL 99
#define ENETDOWN 100 #define ENETDOWN 100
#define ENETUNREACH 101 #define ENETUNREACH 101
#define ENETRESET 102 #define ENETRESET 102
#define ECONNABORTED 103 #define ECONNABORTED 103
#define ECONNRESET 104 #define ECONNRESET 104
#define ENOBUFS 105 #define ENOBUFS 105
#define EISCONN 106 #define EISCONN 106
#define ENOTCONN 107 #define ENOTCONN 107
#define ESHUTDOWN 108 #define ESHUTDOWN 108
#define ETOOMANYREFS 109 #define ETOOMANYREFS 109
#define ETIMEDOUT 110 #define ETIMEDOUT 110
#define ECONNREFUSED 111 #define ECONNREFUSED 111
#define EHOSTDOWN 112 #define EHOSTDOWN 112
#define EHOSTUNREACH 113 #define EHOSTUNREACH 113
#define EALREADY 114 #define EALREADY 114
#define EINPROGRESS 115 #define EINPROGRESS 115
#define ESTALE 116 #define ESTALE 116
#define EUCLEAN 117 #define EUCLEAN 117
#define ENOTNAM 118 #define ENOTNAM 118
#define ENAVAIL 119 #define ENAVAIL 119
#define EISNAM 120 #define EISNAM 120
#define EREMOTEIO 121 #define EREMOTEIO 121
#define EDQUOT 122 #define EDQUOT 122
#define ENOMEDIUM 123 #define ENOMEDIUM 123
#define EMEDIUMTYPE 124 #define EMEDIUMTYPE 124
#define ECANCELED 125 #define ECANCELED 125
#define ENOKEY 126 #define ENOKEY 126
#define EKEYEXPIRED 127 #define EKEYEXPIRED 127
#define EKEYREVOKED 128 #define EKEYREVOKED 128
#define EKEYREJECTED 129 #define EKEYREJECTED 129
#define EOWNERDEAD 130 #define EOWNERDEAD 130
#define ENOTRECOVERABLE 131 #define ENOTRECOVERABLE 131
#define ERFKILL 132 #define ERFKILL 132
#define EHWPOISON 133 #define EHWPOISON 133

View File

@ -1,8 +1,9 @@
#ifndef _ERRNO_H #ifndef _ERRNO_H
#define _ERRNO_H #define _ERRNO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
#include <features.h> #include <features.h>
@ -10,13 +11,14 @@ extern "C" {
#include <bits/errno.h> #include <bits/errno.h>
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((const)) __attribute__((const))
#endif #endif
int *__errno_location(void); int*
__errno_location(void);
#define errno (*__errno_location()) #define errno (*__errno_location())
#ifdef _GNU_SOURCE #ifdef _GNU_SOURCE
extern char *program_invocation_short_name, *program_invocation_name; extern char *program_invocation_short_name, *program_invocation_name;
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -24,4 +26,3 @@ extern char *program_invocation_short_name, *program_invocation_name;
#endif #endif
#endif #endif

View File

@ -2,10 +2,11 @@
#define _FLOAT_H #define _FLOAT_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
int __flt_rounds(void); int __flt_rounds(void);
#define FLT_ROUNDS (__flt_rounds()) #define FLT_ROUNDS (__flt_rounds())
#define FLT_RADIX 2 #define FLT_RADIX 2

View File

@ -2,90 +2,99 @@
#define _MATH_H #define _MATH_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
// NOTE(orca): not doing anything fancy for float_t and double_t // NOTE(orca): not doing anything fancy for float_t and double_t
typedef float float_t; typedef float float_t;
typedef double double_t; typedef double double_t;
#define NAN __builtin_nanf("") #define NAN __builtin_nanf("")
#define INFINITY __builtin_inff() #define INFINITY __builtin_inff()
#define FP_NAN 0 #define FP_NAN 0
#define FP_INFINITE 1 #define FP_INFINITE 1
#define FP_ZERO 2 #define FP_ZERO 2
#define FP_SUBNORMAL 3 #define FP_SUBNORMAL 3
#define FP_NORMAL 4 #define FP_NORMAL 4
int __fpclassify(double); int __fpclassify(double);
int __fpclassifyf(float); int __fpclassifyf(float);
int __fpclassifyl(long double); int __fpclassifyl(long double);
static __inline unsigned __FLOAT_BITS(float __f) static __inline unsigned __FLOAT_BITS(float __f)
{ {
union {float __f; unsigned __i;} __u; union
__u.__f = __f; {
return __u.__i; float __f;
} unsigned __i;
static __inline unsigned long long __DOUBLE_BITS(double __f) } __u;
{
union {double __f; unsigned long long __i;} __u;
__u.__f = __f;
return __u.__i;
}
#define fpclassify(x) ( \ __u.__f = __f;
sizeof(x) == sizeof(float) ? __fpclassifyf(x) : \ return __u.__i;
sizeof(x) == sizeof(double) ? __fpclassify(x) : \ }
__fpclassifyl(x) )
#define isinf(x) ( \ static __inline unsigned long long __DOUBLE_BITS(double __f)
sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) == 0x7f800000 : \ {
sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) == 0x7ffULL<<52 : \ union
__fpclassifyl(x) == FP_INFINITE) {
double __f;
unsigned long long __i;
} __u;
#define isnan(x) ( \ __u.__f = __f;
sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) > 0x7f800000 : \ return __u.__i;
sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) > 0x7ffULL<<52 : \ }
__fpclassifyl(x) == FP_NAN)
double acos(double); #define fpclassify(x) ( \
sizeof(x) == sizeof(float) ? __fpclassifyf(x) : sizeof(x) == sizeof(double) ? __fpclassify(x) \
: __fpclassifyl(x))
double ceil(double); #define isinf(x) ( \
sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) == 0x7f800000 : sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL >> 1) == 0x7ffULL << 52 \
: __fpclassifyl(x) == FP_INFINITE)
double cos(double); #define isnan(x) ( \
float cosf(float); sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) > 0x7f800000 : sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL >> 1) > 0x7ffULL << 52 \
: __fpclassifyl(x) == FP_NAN)
double fabs(double); double acos(double);
double floor(double); double ceil(double);
double fmod(double, double); double cos(double);
float cosf(float);
double pow(double, double); double fabs(double);
double scalbn(double, int); double floor(double);
double sin(double); double fmod(double, double);
float sinf(float);
double sqrt(double); double pow(double, double);
float sqrtf(float);
#define M_E 2.7182818284590452354 /* e */ double scalbn(double, int);
#define M_LOG2E 1.4426950408889634074 /* log_2 e */
#define M_LOG10E 0.43429448190325182765 /* log_10 e */ double sin(double);
#define M_LN2 0.69314718055994530942 /* log_e 2 */ float sinf(float);
#define M_LN10 2.30258509299404568402 /* log_e 10 */
#define M_PI 3.14159265358979323846 /* pi */ double sqrt(double);
#define M_PI_2 1.57079632679489661923 /* pi/2 */ float sqrtf(float);
#define M_PI_4 0.78539816339744830962 /* pi/4 */
#define M_1_PI 0.31830988618379067154 /* 1/pi */ #define M_E 2.7182818284590452354 /* e */
#define M_2_PI 0.63661977236758134308 /* 2/pi */ #define M_LOG2E 1.4426950408889634074 /* log_2 e */
#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ #define M_LOG10E 0.43429448190325182765 /* log_10 e */
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ #define M_LN2 0.69314718055994530942 /* log_e 2 */
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ #define M_LN10 2.30258509299404568402 /* log_e 10 */
#define M_PI 3.14159265358979323846 /* pi */
#define M_PI_2 1.57079632679489661923 /* pi/2 */
#define M_PI_4 0.78539816339744830962 /* pi/4 */
#define M_1_PI 0.31830988618379067154 /* 1/pi */
#define M_2_PI 0.63661977236758134308 /* 2/pi */
#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,4 +1,4 @@
/************************************************************//** /************************************************************/ /**
* *
* @file: stdarg.h * @file: stdarg.h
* @author: Martin Fouilleul * @author: Martin Fouilleul

View File

@ -2,12 +2,13 @@
#define _STDLIB_H #define _STDLIB_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
#define abort(...) OC_ABORT(__VA_ARGS__) #define abort(...) OC_ABORT(__VA_ARGS__)
int abs (int); int abs(int);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,13 +1,13 @@
#include"stb/stb_sprintf.h" #include "stb/stb_sprintf.h"
void* memset(void* b, int c, size_t n); void* memset(void* b, int c, size_t n);
void* memcpy(void *restrict dst, const void *restrict src, size_t n); void* memcpy(void* restrict dst, const void* restrict src, size_t n);
void* memmove(void *dst, const void *src, size_t n); void* memmove(void* dst, const void* src, size_t n);
int memcmp(const void *s1, const void *s2, size_t n); int memcmp(const void* s1, const void* s2, size_t n);
size_t strlen(const char *s); size_t strlen(const char* s);
int strcmp(const char *s1, const char *s2); int strcmp(const char* s1, const char* s2);
int strncmp(const char *s1, const char *s2, size_t n); int strncmp(const char* s1, const char* s2, size_t n);
char* strcpy(char *restrict s1, const char *restrict s2); char* strcpy(char* restrict s1, const char* restrict s2);
#define vsnprintf stbsp_vsnprintf #define vsnprintf stbsp_vsnprintf

View File

@ -51,21 +51,21 @@
#include "libm.h" #include "libm.h"
static const double static const double
C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
double __cos(double x, double y) double __cos(double x, double y)
{ {
double_t hz,z,r,w; double_t hz, z, r, w;
z = x*x; z = x * x;
w = z*z; w = z * z;
r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)); r = z * (C1 + z * (C2 + z * C3)) + w * w * (C4 + z * (C5 + z * C6));
hz = 0.5*z; hz = 0.5 * z;
w = 1.0-hz; w = 1.0 - hz;
return w + (((1.0-w)-hz) + (z*r-x*y)); return w + (((1.0 - w) - hz) + (z * r - x * y));
} }

View File

@ -18,18 +18,18 @@
/* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */ /* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */
static const double static const double
C0 = -0x1ffffffd0c5e81.0p-54, /* -0.499999997251031003120 */ C0 = -0x1ffffffd0c5e81.0p-54, /* -0.499999997251031003120 */
C1 = 0x155553e1053a42.0p-57, /* 0.0416666233237390631894 */ C1 = 0x155553e1053a42.0p-57, /* 0.0416666233237390631894 */
C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */ C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */
C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */ C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
float __cosdf(double x) float __cosdf(double x)
{ {
double_t r, w, z; double_t r, w, z;
/* Try to optimize for parallel evaluation as in __tandf.c. */ /* Try to optimize for parallel evaluation as in __tandf.c. */
z = x*x; z = x * x;
w = z*z; w = z * z;
r = C2+z*C3; r = C2 + z * C3;
return ((1.0+z*C0) + w*C1) + (w*z)*r; return ((1.0 + z * C0) + w * C1) + (w * z) * r;
} }

View File

@ -2,7 +2,7 @@
int errno; int errno;
int *__errno_location(void) int* __errno_location(void)
{ {
// NOTE(orca): We might need a better solution if we eventually support wasm threads. // NOTE(orca): We might need a better solution if we eventually support wasm threads.
return &errno; return &errno;

View File

@ -2,5 +2,5 @@
double __math_invalid(double x) double __math_invalid(double x)
{ {
return (x - x) / (x - x); return (x - x) / (x - x);
} }

View File

@ -2,5 +2,5 @@
float __math_invalidf(float x) float __math_invalidf(float x)
{ {
return (x - x) / (x - x); return (x - x) / (x - x);
} }

View File

@ -2,5 +2,5 @@
double __math_oflow(uint32_t sign) double __math_oflow(uint32_t sign)
{ {
return __math_xflow(sign, 0x1p769); return __math_xflow(sign, 0x1p769);
} }

View File

@ -2,5 +2,5 @@
double __math_uflow(uint32_t sign) double __math_uflow(uint32_t sign)
{ {
return __math_xflow(sign, 0x1p-767); return __math_xflow(sign, 0x1p-767);
} }

View File

@ -3,6 +3,6 @@
double __math_xflow(uint32_t sign, double y) double __math_xflow(uint32_t sign, double y)
{ {
// NOTE(orca): no fp barriers // NOTE(orca): no fp barriers
// return eval_as_double(fp_barrier(sign ? -y : y) * y); // return eval_as_double(fp_barrier(sign ? -y : y) * y);
return eval_as_double((sign ? -y : y) * y); return eval_as_double((sign ? -y : y) * y);
} }

View File

@ -19,10 +19,10 @@
#include "libm.h" #include "libm.h"
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #if FLT_EVAL_METHOD == 0 || FLT_EVAL_METHOD == 1
#define EPS DBL_EPSILON #define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2 #elif FLT_EVAL_METHOD == 2
#define EPS LDBL_EPSILON #define EPS LDBL_EPSILON
#endif #endif
/* /*
@ -35,156 +35,190 @@
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
*/ */
static const double static const double
toint = 1.5/EPS, toint = 1.5 / EPS,
pio4 = 0x1.921fb54442d18p-1, pio4 = 0x1.921fb54442d18p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
/* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ /* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */
int __rem_pio2(double x, double *y) int __rem_pio2(double x, double* y)
{ {
union {double f; uint64_t i;} u = {x}; union
double_t z,w,t,r,fn; {
double tx[3],ty[2]; double f;
uint32_t ix; uint64_t i;
int sign, n, ex, ey, i; } u = { x };
sign = u.i>>63; double_t z, w, t, r, fn;
ix = u.i>>32 & 0x7fffffff; double tx[3], ty[2];
if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ uint32_t ix;
if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ int sign, n, ex, ey, i;
goto medium; /* cancellation -- use medium case */
if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ sign = u.i >> 63;
if (!sign) { ix = u.i >> 32 & 0x7fffffff;
z = x - pio2_1; /* one round good to 85 bits */ if(ix <= 0x400f6a7a)
y[0] = z - pio2_1t; { /* |x| ~<= 5pi/4 */
y[1] = (z-y[0]) - pio2_1t; if((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */
return 1; goto medium; /* cancellation -- use medium case */
} else { if(ix <= 0x4002d97c)
z = x + pio2_1; { /* |x| ~<= 3pi/4 */
y[0] = z + pio2_1t; if(!sign)
y[1] = (z-y[0]) + pio2_1t; {
return -1; z = x - pio2_1; /* one round good to 85 bits */
} y[0] = z - pio2_1t;
} else { y[1] = (z - y[0]) - pio2_1t;
if (!sign) { return 1;
z = x - 2*pio2_1; }
y[0] = z - 2*pio2_1t; else
y[1] = (z-y[0]) - 2*pio2_1t; {
return 2; z = x + pio2_1;
} else { y[0] = z + pio2_1t;
z = x + 2*pio2_1; y[1] = (z - y[0]) + pio2_1t;
y[0] = z + 2*pio2_1t; return -1;
y[1] = (z-y[0]) + 2*pio2_1t; }
return -2; }
} else
} {
} if(!sign)
if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ {
if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ z = x - 2 * pio2_1;
if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ y[0] = z - 2 * pio2_1t;
goto medium; y[1] = (z - y[0]) - 2 * pio2_1t;
if (!sign) { return 2;
z = x - 3*pio2_1; }
y[0] = z - 3*pio2_1t; else
y[1] = (z-y[0]) - 3*pio2_1t; {
return 3; z = x + 2 * pio2_1;
} else { y[0] = z + 2 * pio2_1t;
z = x + 3*pio2_1; y[1] = (z - y[0]) + 2 * pio2_1t;
y[0] = z + 3*pio2_1t; return -2;
y[1] = (z-y[0]) + 3*pio2_1t; }
return -3; }
} }
} else { if(ix <= 0x401c463b)
if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ { /* |x| ~<= 9pi/4 */
goto medium; if(ix <= 0x4015fdbc)
if (!sign) { { /* |x| ~<= 7pi/4 */
z = x - 4*pio2_1; if(ix == 0x4012d97c) /* |x| ~= 3pi/2 */
y[0] = z - 4*pio2_1t; goto medium;
y[1] = (z-y[0]) - 4*pio2_1t; if(!sign)
return 4; {
} else { z = x - 3 * pio2_1;
z = x + 4*pio2_1; y[0] = z - 3 * pio2_1t;
y[0] = z + 4*pio2_1t; y[1] = (z - y[0]) - 3 * pio2_1t;
y[1] = (z-y[0]) + 4*pio2_1t; return 3;
return -4; }
} else
} {
} z = x + 3 * pio2_1;
if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ y[0] = z + 3 * pio2_1t;
medium: y[1] = (z - y[0]) + 3 * pio2_1t;
/* rint(x/(pi/2)) */ return -3;
fn = (double_t)x*invpio2 + toint - toint; }
n = (int32_t)fn; }
r = x - fn*pio2_1; else
w = fn*pio2_1t; /* 1st round, good to 85 bits */ {
/* Matters with directed rounding. */ if(ix == 0x401921fb) /* |x| ~= 4pi/2 */
if (predict_false(r - w < -pio4)) { goto medium;
n--; if(!sign)
fn--; {
r = x - fn*pio2_1; z = x - 4 * pio2_1;
w = fn*pio2_1t; y[0] = z - 4 * pio2_1t;
} else if (predict_false(r - w > pio4)) { y[1] = (z - y[0]) - 4 * pio2_1t;
n++; return 4;
fn++; }
r = x - fn*pio2_1; else
w = fn*pio2_1t; {
} z = x + 4 * pio2_1;
y[0] = r - w; y[0] = z + 4 * pio2_1t;
u.f = y[0]; y[1] = (z - y[0]) + 4 * pio2_1t;
ey = u.i>>52 & 0x7ff; return -4;
ex = ix>>20; }
if (ex - ey > 16) { /* 2nd round, good to 118 bits */ }
t = r; }
w = fn*pio2_2; if(ix < 0x413921fb)
r = t - w; { /* |x| ~< 2^20*(pi/2), medium size */
w = fn*pio2_2t - ((t-r)-w); medium:
y[0] = r - w; /* rint(x/(pi/2)) */
u.f = y[0]; fn = (double_t)x * invpio2 + toint - toint;
ey = u.i>>52 & 0x7ff; n = (int32_t)fn;
if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */ r = x - fn * pio2_1;
t = r; w = fn * pio2_1t; /* 1st round, good to 85 bits */
w = fn*pio2_3; /* Matters with directed rounding. */
r = t - w; if(predict_false(r - w < -pio4))
w = fn*pio2_3t - ((t-r)-w); {
y[0] = r - w; n--;
} fn--;
} r = x - fn * pio2_1;
y[1] = (r - y[0]) - w; w = fn * pio2_1t;
return n; }
} else if(predict_false(r - w > pio4))
/* {
n++;
fn++;
r = x - fn * pio2_1;
w = fn * pio2_1t;
}
y[0] = r - w;
u.f = y[0];
ey = u.i >> 52 & 0x7ff;
ex = ix >> 20;
if(ex - ey > 16)
{ /* 2nd round, good to 118 bits */
t = r;
w = fn * pio2_2;
r = t - w;
w = fn * pio2_2t - ((t - r) - w);
y[0] = r - w;
u.f = y[0];
ey = u.i >> 52 & 0x7ff;
if(ex - ey > 49)
{ /* 3rd round, good to 151 bits, covers all cases */
t = r;
w = fn * pio2_3;
r = t - w;
w = fn * pio2_3t - ((t - r) - w);
y[0] = r - w;
}
}
y[1] = (r - y[0]) - w;
return n;
}
/*
* all other (large) arguments * all other (large) arguments
*/ */
if (ix >= 0x7ff00000) { /* x is inf or NaN */ if(ix >= 0x7ff00000)
y[0] = y[1] = x - x; { /* x is inf or NaN */
return 0; y[0] = y[1] = x - x;
} return 0;
/* set z = scalbn(|x|,-ilogb(x)+23) */ }
u.f = x; /* set z = scalbn(|x|,-ilogb(x)+23) */
u.i &= (uint64_t)-1>>12; u.f = x;
u.i |= (uint64_t)(0x3ff + 23)<<52; u.i &= (uint64_t)-1 >> 12;
z = u.f; u.i |= (uint64_t)(0x3ff + 23) << 52;
for (i=0; i < 2; i++) { z = u.f;
tx[i] = (double)(int32_t)z; for(i = 0; i < 2; i++)
z = (z-tx[i])*0x1p24; {
} tx[i] = (double)(int32_t)z;
tx[i] = z; z = (z - tx[i]) * 0x1p24;
/* skip zero terms, first term is non-zero */ }
while (tx[i] == 0.0) tx[i] = z;
i--; /* skip zero terms, first term is non-zero */
n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1); while(tx[i] == 0.0)
if (sign) { i--;
y[0] = -ty[0]; n = __rem_pio2_large(tx, ty, (int)(ix >> 20) - (0x3ff + 23), i + 1, 1);
y[1] = -ty[1]; if(sign)
return -n; {
} y[0] = -ty[0];
y[0] = ty[0]; y[1] = -ty[1];
y[1] = ty[1]; return -n;
return n; }
y[0] = ty[0];
y[1] = ty[1];
return n;
} }

File diff suppressed because it is too large Load Diff

View File

@ -22,10 +22,10 @@
#include "libm.h" #include "libm.h"
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #if FLT_EVAL_METHOD == 0 || FLT_EVAL_METHOD == 1
#define EPS DBL_EPSILON #define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2 #elif FLT_EVAL_METHOD == 2
#define EPS LDBL_EPSILON #define EPS LDBL_EPSILON
#endif #endif
/* /*
@ -34,53 +34,64 @@
* pio2_1t: pi/2 - pio2_1 * pio2_1t: pi/2 - pio2_1
*/ */
static const double static const double
toint = 1.5/EPS, toint = 1.5 / EPS,
pio4 = 0x1.921fb6p-1, pio4 = 0x1.921fb6p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */ pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */ pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
int __rem_pio2f(float x, double *y) int __rem_pio2f(float x, double* y)
{ {
union {float f; uint32_t i;} u = {x}; union
double tx[1],ty[1]; {
double_t fn; float f;
uint32_t ix; uint32_t i;
int n, sign, e0; } u = { x };
ix = u.i & 0x7fffffff; double tx[1], ty[1];
/* 25+53 bit pi is good enough for medium size */ double_t fn;
if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */ uint32_t ix;
/* Use a specialized rint() to get fn. */ int n, sign, e0;
fn = (double_t)x*invpio2 + toint - toint;
n = (int32_t)fn; ix = u.i & 0x7fffffff;
*y = x - fn*pio2_1 - fn*pio2_1t; /* 25+53 bit pi is good enough for medium size */
/* Matters with directed rounding. */ if(ix < 0x4dc90fdb)
if (predict_false(*y < -pio4)) { { /* |x| ~< 2^28*(pi/2), medium size */
n--; /* Use a specialized rint() to get fn. */
fn--; fn = (double_t)x * invpio2 + toint - toint;
*y = x - fn*pio2_1 - fn*pio2_1t; n = (int32_t)fn;
} else if (predict_false(*y > pio4)) { *y = x - fn * pio2_1 - fn * pio2_1t;
n++; /* Matters with directed rounding. */
fn++; if(predict_false(*y < -pio4))
*y = x - fn*pio2_1 - fn*pio2_1t; {
} n--;
return n; fn--;
} *y = x - fn * pio2_1 - fn * pio2_1t;
if(ix>=0x7f800000) { /* x is inf or NaN */ }
*y = x-x; else if(predict_false(*y > pio4))
return 0; {
} n++;
/* scale x into [2^23, 2^24-1] */ fn++;
sign = u.i>>31; *y = x - fn * pio2_1 - fn * pio2_1t;
e0 = (ix>>23) - (0x7f+23); /* e0 = ilogb(|x|)-23, positive */ }
u.i = ix - (e0<<23); return n;
tx[0] = u.f; }
n = __rem_pio2_large(tx,ty,e0,1,0); if(ix >= 0x7f800000)
if (sign) { { /* x is inf or NaN */
*y = -ty[0]; *y = x - x;
return -n; return 0;
} }
*y = ty[0]; /* scale x into [2^23, 2^24-1] */
return n; sign = u.i >> 31;
e0 = (ix >> 23) - (0x7f + 23); /* e0 = ilogb(|x|)-23, positive */
u.i = ix - (e0 << 23);
tx[0] = u.f;
n = __rem_pio2_large(tx, ty, e0, 1, 0);
if(sign)
{
*y = -ty[0];
return -n;
}
*y = ty[0];
return n;
} }

View File

@ -42,23 +42,23 @@
#include "libm.h" #include "libm.h"
static const double static const double
S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
double __sin(double x, double y, int iy) double __sin(double x, double y, int iy)
{ {
double_t z,r,v,w; double_t z, r, v, w;
z = x*x; z = x * x;
w = z*z; w = z * z;
r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6); r = S2 + z * (S3 + z * S4) + z * w * (S5 + z * S6);
v = z*x; v = z * x;
if (iy == 0) if(iy == 0)
return x + v*(S1 + z*r); return x + v * (S1 + z * r);
else else
return x - ((z*(0.5*y - v*r) - y) - v*S1); return x - ((z * (0.5 * y - v * r) - y) - v * S1);
} }

View File

@ -18,19 +18,19 @@
/* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */ /* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */
static const double static const double
S1 = -0x15555554cbac77.0p-55, /* -0.166666666416265235595 */ S1 = -0x15555554cbac77.0p-55, /* -0.166666666416265235595 */
S2 = 0x111110896efbb2.0p-59, /* 0.0083333293858894631756 */ S2 = 0x111110896efbb2.0p-59, /* 0.0083333293858894631756 */
S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */ S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */
S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */ S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */
float __sindf(double x) float __sindf(double x)
{ {
double_t r, s, w, z; double_t r, s, w, z;
/* Try to optimize for parallel evaluation as in __tandf.c. */ /* Try to optimize for parallel evaluation as in __tandf.c. */
z = x*x; z = x * x;
w = z*z; w = z * z;
r = S3 + z*S4; r = S3 + z * S4;
s = z*x; s = z * x;
return (x + s*(S1 + z*S2)) + s*w*r; return (x + s * (S1 + z * S2)) + s * w * r;
} }

View File

@ -2,5 +2,5 @@
int abs(int a) int abs(int a)
{ {
return a>0 ? a : -a; return a > 0 ? a : -a;
} }

View File

@ -36,66 +36,70 @@
#include "libm.h" #include "libm.h"
static const double static const double
pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
static double R(double z) static double R(double z)
{ {
double_t p, q; double_t p, q;
p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4))); q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
return p/q; return p / q;
} }
double acos(double x) double acos(double x)
{ {
double z,w,s,c,df; double z, w, s, c, df;
uint32_t hx,ix; uint32_t hx, ix;
GET_HIGH_WORD(hx, x); GET_HIGH_WORD(hx, x);
ix = hx & 0x7fffffff; ix = hx & 0x7fffffff;
/* |x| >= 1 or nan */ /* |x| >= 1 or nan */
if (ix >= 0x3ff00000) { if(ix >= 0x3ff00000)
uint32_t lx; {
uint32_t lx;
GET_LOW_WORD(lx,x); GET_LOW_WORD(lx, x);
if ((ix-0x3ff00000 | lx) == 0) { if((ix - 0x3ff00000 | lx) == 0)
/* acos(1)=0, acos(-1)=pi */ {
if (hx >> 31) /* acos(1)=0, acos(-1)=pi */
return 2*pio2_hi + 0x1p-120f; if(hx >> 31)
return 0; return 2 * pio2_hi + 0x1p-120f;
} return 0;
return 0/(x-x); }
} return 0 / (x - x);
/* |x| < 0.5 */ }
if (ix < 0x3fe00000) { /* |x| < 0.5 */
if (ix <= 0x3c600000) /* |x| < 2**-57 */ if(ix < 0x3fe00000)
return pio2_hi + 0x1p-120f; {
return pio2_hi - (x - (pio2_lo-x*R(x*x))); if(ix <= 0x3c600000) /* |x| < 2**-57 */
} return pio2_hi + 0x1p-120f;
/* x < -0.5 */ return pio2_hi - (x - (pio2_lo - x * R(x * x)));
if (hx >> 31) { }
z = (1.0+x)*0.5; /* x < -0.5 */
s = sqrt(z); if(hx >> 31)
w = R(z)*s-pio2_lo; {
return 2*(pio2_hi - (s+w)); z = (1.0 + x) * 0.5;
} s = sqrt(z);
/* x > 0.5 */ w = R(z) * s - pio2_lo;
z = (1.0-x)*0.5; return 2 * (pio2_hi - (s + w));
s = sqrt(z); }
df = s; /* x > 0.5 */
SET_LOW_WORD(df,0); z = (1.0 - x) * 0.5;
c = (z-df*df)/(s+df); s = sqrt(z);
w = R(z)*s+c; df = s;
return 2*(df+w); SET_LOW_WORD(df, 0);
c = (z - df * df) / (s + df);
w = R(z) * s + c;
return 2 * (df + w);
} }

View File

@ -1,31 +1,37 @@
#include "libm.h" #include "libm.h"
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #if FLT_EVAL_METHOD == 0 || FLT_EVAL_METHOD == 1
#define EPS DBL_EPSILON #define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2 #elif FLT_EVAL_METHOD == 2
#define EPS LDBL_EPSILON #define EPS LDBL_EPSILON
#endif #endif
static const double_t toint = 1/EPS; static const double_t toint = 1 / EPS;
double ceil(double x) double ceil(double x)
{ {
union {double f; uint64_t i;} u = {x}; union
int e = u.i >> 52 & 0x7ff; {
double_t y; double f;
uint64_t i;
} u = { x };
if (e >= 0x3ff+52 || x == 0) int e = u.i >> 52 & 0x7ff;
return x; double_t y;
/* y = int(x) - x, where int(x) is an integer neighbor of x */
if (u.i >> 63) if(e >= 0x3ff + 52 || x == 0)
y = x - toint + toint - x; return x;
else /* y = int(x) - x, where int(x) is an integer neighbor of x */
y = x + toint - toint - x; if(u.i >> 63)
/* special case because of non-nearest rounding modes */ y = x - toint + toint - x;
if (e <= 0x3ff-1) { else
FORCE_EVAL(y); y = x + toint - toint - x;
return u.i >> 63 ? -0.0 : 1; /* special case because of non-nearest rounding modes */
} if(e <= 0x3ff - 1)
if (y < 0) {
return x + y + 1; FORCE_EVAL(y);
return x + y; return u.i >> 63 ? -0.0 : 1;
}
if(y < 0)
return x + y + 1;
return x + y;
} }

View File

@ -44,34 +44,40 @@
double cos(double x) double cos(double x)
{ {
double y[2]; double y[2];
uint32_t ix; uint32_t ix;
unsigned n; unsigned n;
GET_HIGH_WORD(ix, x); GET_HIGH_WORD(ix, x);
ix &= 0x7fffffff; ix &= 0x7fffffff;
/* |x| ~< pi/4 */ /* |x| ~< pi/4 */
if (ix <= 0x3fe921fb) { if(ix <= 0x3fe921fb)
if (ix < 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */ {
/* raise inexact if x!=0 */ if(ix < 0x3e46a09e)
FORCE_EVAL(x + 0x1p120f); { /* |x| < 2**-27 * sqrt(2) */
return 1.0; /* raise inexact if x!=0 */
} FORCE_EVAL(x + 0x1p120f);
return __cos(x, 0); return 1.0;
} }
return __cos(x, 0);
}
/* cos(Inf or NaN) is NaN */ /* cos(Inf or NaN) is NaN */
if (ix >= 0x7ff00000) if(ix >= 0x7ff00000)
return x-x; return x - x;
/* argument reduction */ /* argument reduction */
n = __rem_pio2(x, y); n = __rem_pio2(x, y);
switch (n&3) { switch(n & 3)
case 0: return __cos(y[0], y[1]); {
case 1: return -__sin(y[0], y[1], 1); case 0:
case 2: return -__cos(y[0], y[1]); return __cos(y[0], y[1]);
default: case 1:
return __sin(y[0], y[1], 1); return -__sin(y[0], y[1], 1);
} case 2:
return -__cos(y[0], y[1]);
default:
return __sin(y[0], y[1], 1);
}
} }

View File

@ -18,61 +18,71 @@
/* Small multiples of pi/2 rounded to double precision. */ /* Small multiples of pi/2 rounded to double precision. */
static const double static const double
c1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */ c1pio2 = 1 * M_PI_2, /* 0x3FF921FB, 0x54442D18 */
c2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */ c2pio2 = 2 * M_PI_2, /* 0x400921FB, 0x54442D18 */
c3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */ c3pio2 = 3 * M_PI_2, /* 0x4012D97C, 0x7F3321D2 */
c4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */ c4pio2 = 4 * M_PI_2; /* 0x401921FB, 0x54442D18 */
float cosf(float x) float cosf(float x)
{ {
double y; double y;
uint32_t ix; uint32_t ix;
unsigned n, sign; unsigned n, sign;
GET_FLOAT_WORD(ix, x); GET_FLOAT_WORD(ix, x);
sign = ix >> 31; sign = ix >> 31;
ix &= 0x7fffffff; ix &= 0x7fffffff;
if (ix <= 0x3f490fda) { /* |x| ~<= pi/4 */ if(ix <= 0x3f490fda)
if (ix < 0x39800000) { /* |x| < 2**-12 */ { /* |x| ~<= pi/4 */
/* raise inexact if x != 0 */ if(ix < 0x39800000)
FORCE_EVAL(x + 0x1p120f); { /* |x| < 2**-12 */
return 1.0f; /* raise inexact if x != 0 */
} FORCE_EVAL(x + 0x1p120f);
return __cosdf(x); return 1.0f;
} }
if (ix <= 0x407b53d1) { /* |x| ~<= 5*pi/4 */ return __cosdf(x);
if (ix > 0x4016cbe3) /* |x| ~> 3*pi/4 */ }
return -__cosdf(sign ? x+c2pio2 : x-c2pio2); if(ix <= 0x407b53d1)
else { { /* |x| ~<= 5*pi/4 */
if (sign) if(ix > 0x4016cbe3) /* |x| ~> 3*pi/4 */
return __sindf(x + c1pio2); return -__cosdf(sign ? x + c2pio2 : x - c2pio2);
else else
return __sindf(c1pio2 - x); {
} if(sign)
} return __sindf(x + c1pio2);
if (ix <= 0x40e231d5) { /* |x| ~<= 9*pi/4 */ else
if (ix > 0x40afeddf) /* |x| ~> 7*pi/4 */ return __sindf(c1pio2 - x);
return __cosdf(sign ? x+c4pio2 : x-c4pio2); }
else { }
if (sign) if(ix <= 0x40e231d5)
return __sindf(-x - c3pio2); { /* |x| ~<= 9*pi/4 */
else if(ix > 0x40afeddf) /* |x| ~> 7*pi/4 */
return __sindf(x - c3pio2); return __cosdf(sign ? x + c4pio2 : x - c4pio2);
} else
} {
if(sign)
return __sindf(-x - c3pio2);
else
return __sindf(x - c3pio2);
}
}
/* cos(Inf or NaN) is NaN */ /* cos(Inf or NaN) is NaN */
if (ix >= 0x7f800000) if(ix >= 0x7f800000)
return x-x; return x - x;
/* general argument reduction needed */ /* general argument reduction needed */
n = __rem_pio2f(x,&y); n = __rem_pio2f(x, &y);
switch (n&3) { switch(n & 3)
case 0: return __cosdf(y); {
case 1: return __sindf(-y); case 0:
case 2: return -__cosdf(y); return __cosdf(y);
default: case 1:
return __sindf(y); return __sindf(-y);
} case 2:
return -__cosdf(y);
default:
return __sindf(y);
}
} }

View File

@ -12,15 +12,17 @@
#define EXP_POLY_ORDER 5 #define EXP_POLY_ORDER 5
#define EXP_USE_TOINT_NARROW 0 #define EXP_USE_TOINT_NARROW 0
#define EXP2_POLY_ORDER 5 #define EXP2_POLY_ORDER 5
extern const struct exp_data {
double invln2N; extern const struct exp_data
double shift; {
double negln2hiN; double invln2N;
double negln2loN; double shift;
double poly[4]; /* Last four coefficients. */ double negln2hiN;
double exp2_shift; double negln2loN;
double exp2_poly[EXP2_POLY_ORDER]; double poly[4]; /* Last four coefficients. */
uint64_t tab[2*(1 << EXP_TABLE_BITS)]; double exp2_shift;
double exp2_poly[EXP2_POLY_ORDER];
uint64_t tab[2 * (1 << EXP_TABLE_BITS)];
} __exp_data; } __exp_data;
#endif #endif

View File

@ -3,7 +3,12 @@
double fabs(double x) double fabs(double x)
{ {
union {double f; uint64_t i;} u = {x}; union
u.i &= -1ULL/2; {
return u.f; double f;
uint64_t i;
} u = { x };
u.i &= -1ULL / 2;
return u.f;
} }

View File

@ -1,31 +1,37 @@
#include "libm.h" #include "libm.h"
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 #if FLT_EVAL_METHOD == 0 || FLT_EVAL_METHOD == 1
#define EPS DBL_EPSILON #define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2 #elif FLT_EVAL_METHOD == 2
#define EPS LDBL_EPSILON #define EPS LDBL_EPSILON
#endif #endif
static const double_t toint = 1/EPS; static const double_t toint = 1 / EPS;
double floor(double x) double floor(double x)
{ {
union {double f; uint64_t i;} u = {x}; union
int e = u.i >> 52 & 0x7ff; {
double_t y; double f;
uint64_t i;
} u = { x };
if (e >= 0x3ff+52 || x == 0) int e = u.i >> 52 & 0x7ff;
return x; double_t y;
/* y = int(x) - x, where int(x) is an integer neighbor of x */
if (u.i >> 63) if(e >= 0x3ff + 52 || x == 0)
y = x - toint + toint - x; return x;
else /* y = int(x) - x, where int(x) is an integer neighbor of x */
y = x + toint - toint - x; if(u.i >> 63)
/* special case because of non-nearest rounding modes */ y = x - toint + toint - x;
if (e <= 0x3ff-1) { else
FORCE_EVAL(y); y = x + toint - toint - x;
return u.i >> 63 ? -1 : 0; /* special case because of non-nearest rounding modes */
} if(e <= 0x3ff - 1)
if (y > 0) {
return x + y - 1; FORCE_EVAL(y);
return x + y; return u.i >> 63 ? -1 : 0;
}
if(y > 0)
return x + y - 1;
return x + y;
} }

Some files were not shown because too many files have changed in this diff Show More