Merge branch 'main' into orca_ui
This commit is contained in:
commit
2214974804
|
@ -63,6 +63,11 @@ int main()
|
||||||
|
|
||||||
//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))
|
||||||
|
{
|
||||||
|
printf("Error: couldn't create surface\n");
|
||||||
|
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();
|
||||||
|
|
|
@ -53,6 +53,14 @@ enum {
|
||||||
LAYOUT_PATH_ELT_SIZE = sizeof(mg_gl_path_elt),
|
LAYOUT_PATH_ELT_SIZE = sizeof(mg_gl_path_elt),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct mg_gl_dispatch_indirect_command
|
||||||
|
{
|
||||||
|
u32 num_groups_x;
|
||||||
|
u32 num_groups_y;
|
||||||
|
u32 num_groups_z;
|
||||||
|
|
||||||
|
} mg_gl_dispatch_indirect_command;
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//NOTE: these are just here for the sizes...
|
//NOTE: these are just here for the sizes...
|
||||||
|
|
||||||
|
@ -96,6 +104,11 @@ typedef struct mg_gl_tile_queue
|
||||||
|
|
||||||
} mg_gl_tile_queue;
|
} mg_gl_tile_queue;
|
||||||
|
|
||||||
|
typedef struct mg_gl_screen_tile
|
||||||
|
{
|
||||||
|
u32 tileCoord[2];
|
||||||
|
i32 first;
|
||||||
|
} mg_gl_screen_tile;
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -140,6 +153,7 @@ typedef struct mg_gl_canvas_backend
|
||||||
GLuint tileOpBuffer;
|
GLuint tileOpBuffer;
|
||||||
GLuint tileOpCountBuffer;
|
GLuint tileOpCountBuffer;
|
||||||
GLuint screenTilesBuffer;
|
GLuint screenTilesBuffer;
|
||||||
|
GLuint rasterDispatchBuffer;
|
||||||
|
|
||||||
GLuint dummyVertexBuffer;
|
GLuint dummyVertexBuffer;
|
||||||
|
|
||||||
|
@ -958,6 +972,10 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, elementBuffer);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, elementBuffer);
|
||||||
glFlushMappedBufferRange(GL_SHADER_STORAGE_BUFFER, elementBufferOffset, eltCount*sizeof(mg_gl_path_elt));
|
glFlushMappedBufferRange(GL_SHADER_STORAGE_BUFFER, elementBufferOffset, eltCount*sizeof(mg_gl_path_elt));
|
||||||
|
|
||||||
|
//NOTE: clear out texture
|
||||||
|
u8 clearColor[4] = {0};
|
||||||
|
glClearTexImage(backend->outTexture, 0, GL_RGBA, GL_BYTE, clearColor);
|
||||||
|
|
||||||
//NOTE: clear counters
|
//NOTE: clear counters
|
||||||
int zero = 0;
|
int zero = 0;
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->segmentCountBuffer);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->segmentCountBuffer);
|
||||||
|
@ -969,6 +987,9 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->tileOpCountBuffer);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->tileOpCountBuffer);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), &zero, GL_DYNAMIC_COPY);
|
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int), &zero, GL_DYNAMIC_COPY);
|
||||||
|
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->rasterDispatchBuffer);
|
||||||
|
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(mg_gl_dispatch_indirect_command), &zero, GL_DYNAMIC_COPY);
|
||||||
|
|
||||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||||
|
|
||||||
//NOTE: path setup pass
|
//NOTE: path setup pass
|
||||||
|
@ -1048,6 +1069,7 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileOpCountBuffer);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, backend->tileOpCountBuffer);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, backend->tileOpBuffer);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, backend->tileOpBuffer);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, backend->screenTilesBuffer);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, backend->screenTilesBuffer);
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, backend->rasterDispatchBuffer);
|
||||||
|
|
||||||
glUniform1i(0, tileSize);
|
glUniform1i(0, tileSize);
|
||||||
glUniform1f(1, scale);
|
glUniform1f(1, scale);
|
||||||
|
@ -1090,7 +1112,9 @@ void mg_gl_render_batch(mg_gl_canvas_backend* backend,
|
||||||
{
|
{
|
||||||
glUniform1ui(2, 0);
|
glUniform1ui(2, 0);
|
||||||
}
|
}
|
||||||
glDispatchCompute(nTilesX, nTilesY, 1);
|
|
||||||
|
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, backend->rasterDispatchBuffer);
|
||||||
|
glDispatchComputeIndirect(0);
|
||||||
|
|
||||||
//NOTE: blit pass
|
//NOTE: blit pass
|
||||||
glUseProgram(backend->blit);
|
glUseProgram(backend->blit);
|
||||||
|
@ -1526,7 +1550,12 @@ mg_canvas_backend* gl_canvas_backend_create(mg_wgl_surface* surface)
|
||||||
|
|
||||||
glGenBuffers(1, &backend->screenTilesBuffer);
|
glGenBuffers(1, &backend->screenTilesBuffer);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->screenTilesBuffer);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->screenTilesBuffer);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, nTilesX*nTilesY*sizeof(int), 0, GL_DYNAMIC_COPY);
|
glBufferData(GL_SHADER_STORAGE_BUFFER, nTilesX*nTilesY*sizeof(mg_gl_screen_tile), 0, GL_DYNAMIC_COPY);
|
||||||
|
|
||||||
|
glGenBuffers(1, &backend->rasterDispatchBuffer);
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->rasterDispatchBuffer);
|
||||||
|
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(mg_gl_dispatch_indirect_command), 0, GL_DYNAMIC_COPY);
|
||||||
|
|
||||||
|
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,11 +17,15 @@ layout(std430) buffer;
|
||||||
#define MG_GL_TR 4 /* curve on top right */
|
#define MG_GL_TR 4 /* curve on top right */
|
||||||
|
|
||||||
// Operations
|
// Operations
|
||||||
#define MG_GL_OP_START 0
|
#define MG_GL_OP_FILL 0
|
||||||
#define MG_GL_OP_SEGMENT 1
|
#define MG_GL_OP_CLIP_FILL 1
|
||||||
|
#define MG_GL_OP_START 2
|
||||||
|
#define MG_GL_OP_END 3
|
||||||
|
#define MG_GL_OP_SEGMENT 4
|
||||||
|
|
||||||
// MSAA
|
// MSAA
|
||||||
#define MG_GL_MAX_SAMPLE_COUNT 8
|
#define MG_GL_MAX_SAMPLE_COUNT 8
|
||||||
|
#define MG_GL_MAX_SRC_SAMPLE_COUNT 4
|
||||||
|
|
||||||
struct mg_gl_path
|
struct mg_gl_path
|
||||||
{
|
{
|
||||||
|
@ -72,6 +76,19 @@ struct mg_gl_tile_queue
|
||||||
int last;
|
int last;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mg_gl_screen_tile
|
||||||
|
{
|
||||||
|
uvec2 tileCoord;
|
||||||
|
int first;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mg_gl_dispatch_indirect_command
|
||||||
|
{
|
||||||
|
uint num_groups_x;
|
||||||
|
uint num_groups_y;
|
||||||
|
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));
|
||||||
|
|
|
@ -31,9 +31,15 @@ layout(binding = 4) restrict buffer tileOpBufferSSBO
|
||||||
|
|
||||||
layout(binding = 5) restrict writeonly buffer screenTilesBufferSSBO
|
layout(binding = 5) restrict writeonly buffer screenTilesBufferSSBO
|
||||||
{
|
{
|
||||||
int elements[];
|
mg_gl_screen_tile elements[];
|
||||||
} screenTilesBuffer;
|
} screenTilesBuffer;
|
||||||
|
|
||||||
|
layout(binding = 6) coherent restrict buffer dispatchBufferSSBO
|
||||||
|
{
|
||||||
|
mg_gl_dispatch_indirect_command elements[];
|
||||||
|
} dispatchBuffer;
|
||||||
|
|
||||||
|
|
||||||
layout(location = 0) uniform int tileSize;
|
layout(location = 0) uniform int tileSize;
|
||||||
layout(location = 1) uniform float scale;
|
layout(location = 1) uniform float scale;
|
||||||
layout(location = 2) uniform int pathCount;
|
layout(location = 2) uniform int pathCount;
|
||||||
|
@ -41,13 +47,14 @@ layout(location = 3) uniform int cullSolidTiles;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ivec2 nTiles = ivec2(gl_NumWorkGroups.xy);
|
|
||||||
ivec2 tileCoord = ivec2(gl_WorkGroupID.xy);
|
ivec2 tileCoord = ivec2(gl_WorkGroupID.xy);
|
||||||
int tileIndex = tileCoord.y * nTiles.x + tileCoord.x;
|
int tileIndex = -1;
|
||||||
|
|
||||||
screenTilesBuffer.elements[tileIndex] = -1;
|
|
||||||
int lastOpIndex = -1;
|
int lastOpIndex = -1;
|
||||||
|
|
||||||
|
dispatchBuffer.elements[0].num_groups_y = 1;
|
||||||
|
dispatchBuffer.elements[0].num_groups_z = 1;
|
||||||
|
|
||||||
for(int pathIndex = 0; pathIndex < pathCount; pathIndex++)
|
for(int pathIndex = 0; pathIndex < pathCount; pathIndex++)
|
||||||
{
|
{
|
||||||
mg_gl_path_queue pathQueue = pathQueueBuffer.elements[pathIndex];
|
mg_gl_path_queue pathQueue = pathQueueBuffer.elements[pathIndex];
|
||||||
|
@ -65,13 +72,32 @@ void main()
|
||||||
&& pathTileCoord.y >= 0
|
&& pathTileCoord.y >= 0
|
||||||
&& pathTileCoord.y < pathQueue.area.w)
|
&& pathTileCoord.y < pathQueue.area.w)
|
||||||
{
|
{
|
||||||
|
if(tileIndex < 0)
|
||||||
|
{
|
||||||
|
tileIndex = int(atomicAdd(dispatchBuffer.elements[0].num_groups_x, 1));
|
||||||
|
screenTilesBuffer.elements[tileIndex].tileCoord = uvec2(tileCoord);
|
||||||
|
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;
|
||||||
mg_gl_tile_queue tileQueue = tileQueueBuffer.elements[pathTileIndex];
|
mg_gl_tile_queue tileQueue = tileQueueBuffer.elements[pathTileIndex];
|
||||||
|
|
||||||
int windingOffset = tileQueue.windingOffset;
|
int windingOffset = tileQueue.windingOffset;
|
||||||
int firstOpIndex = tileQueue.first;
|
int firstOpIndex = tileQueue.first;
|
||||||
|
|
||||||
if(firstOpIndex == -1)
|
vec4 tileBox = vec4(tileCoord.x, tileCoord.y, tileCoord.x+1, tileCoord.y+1);
|
||||||
|
tileBox *= tileSize;
|
||||||
|
vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
|
||||||
|
|
||||||
|
if( tileBox.x >= clip.z
|
||||||
|
|| tileBox.z < clip.x
|
||||||
|
|| tileBox.y >= clip.w
|
||||||
|
|| tileBox.w < clip.y)
|
||||||
|
{
|
||||||
|
//NOTE: tile is fully outside clip, cull it
|
||||||
|
//TODO: move that test up
|
||||||
|
}
|
||||||
|
else if(firstOpIndex == -1)
|
||||||
{
|
{
|
||||||
if((windingOffset & 1) != 0)
|
if((windingOffset & 1) != 0)
|
||||||
{
|
{
|
||||||
|
@ -79,29 +105,33 @@ void main()
|
||||||
// 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);
|
||||||
|
|
||||||
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_START;
|
tileOpBuffer.elements[pathOpIndex].kind = MG_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;
|
||||||
|
|
||||||
vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
|
if(lastOpIndex < 0)
|
||||||
vec4 tileBox = vec4(tileCoord.x, tileCoord.y, tileCoord.x+1, tileCoord.y+1);
|
|
||||||
tileBox *= tileSize;
|
|
||||||
|
|
||||||
if( lastOpIndex < 0
|
|
||||||
||(pathBuffer.elements[pathIndex].color.a == 1
|
|
||||||
&& cullSolidTiles != 0
|
|
||||||
&& tileBox.x >= clip.x
|
|
||||||
&& tileBox.z < clip.z
|
|
||||||
&& tileBox.y >= clip.y
|
|
||||||
&& tileBox.w < clip.w))
|
|
||||||
{
|
{
|
||||||
screenTilesBuffer.elements[tileIndex] = pathOpIndex;
|
screenTilesBuffer.elements[tileIndex].first = pathOpIndex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tileOpBuffer.elements[lastOpIndex].next = pathOpIndex;
|
tileOpBuffer.elements[lastOpIndex].next = pathOpIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( tileBox.x >= clip.x
|
||||||
|
&& tileBox.z < clip.z
|
||||||
|
&& tileBox.y >= clip.y
|
||||||
|
&& tileBox.w < clip.w)
|
||||||
|
{
|
||||||
|
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_FILL;
|
||||||
|
|
||||||
|
if( pathBuffer.elements[pathIndex].color.a == 1
|
||||||
|
&& cullSolidTiles != 0)
|
||||||
|
{
|
||||||
|
screenTilesBuffer.elements[tileIndex].first = pathOpIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
lastOpIndex = pathOpIndex;
|
lastOpIndex = pathOpIndex;
|
||||||
}
|
}
|
||||||
// else, tile is fully uncovered, skip path
|
// else, tile is fully uncovered, skip path
|
||||||
|
@ -109,26 +139,44 @@ void main()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//NOTE: add path start op (with winding offset)
|
//NOTE: add path start op (with winding offset)
|
||||||
int pathOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
|
int startOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
|
||||||
|
|
||||||
tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_START;
|
tileOpBuffer.elements[startOpIndex].kind = MG_GL_OP_START;
|
||||||
tileOpBuffer.elements[pathOpIndex].next = -1;
|
tileOpBuffer.elements[startOpIndex].next = -1;
|
||||||
tileOpBuffer.elements[pathOpIndex].index = pathIndex;
|
tileOpBuffer.elements[startOpIndex].index = pathIndex;
|
||||||
tileOpBuffer.elements[pathOpIndex].windingOffsetOrCrossRight = windingOffset;
|
tileOpBuffer.elements[startOpIndex].windingOffsetOrCrossRight = windingOffset;
|
||||||
|
|
||||||
if(lastOpIndex < 0)
|
if(lastOpIndex < 0)
|
||||||
{
|
{
|
||||||
screenTilesBuffer.elements[tileIndex] = pathOpIndex;
|
screenTilesBuffer.elements[tileIndex].first = startOpIndex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tileOpBuffer.elements[lastOpIndex].next = pathOpIndex;
|
tileOpBuffer.elements[lastOpIndex].next = startOpIndex;
|
||||||
}
|
}
|
||||||
lastOpIndex = pathOpIndex;
|
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
|
||||||
|
int endOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
|
||||||
|
|
||||||
|
tileOpBuffer.elements[endOpIndex].kind = MG_GL_OP_END;
|
||||||
|
tileOpBuffer.elements[endOpIndex].next = -1;
|
||||||
|
tileOpBuffer.elements[endOpIndex].index = pathIndex;
|
||||||
|
tileOpBuffer.elements[endOpIndex].windingOffsetOrCrossRight = windingOffset;
|
||||||
|
|
||||||
|
if(lastOpIndex < 0)
|
||||||
|
{
|
||||||
|
screenTilesBuffer.elements[tileIndex].first = endOpIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tileOpBuffer.elements[lastOpIndex].next = endOpIndex;
|
||||||
|
}
|
||||||
|
lastOpIndex = endOpIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ layout(binding = 2) restrict readonly buffer tileOpBufferSSBO
|
||||||
|
|
||||||
layout(binding = 3) restrict readonly buffer screenTilesBufferSSBO
|
layout(binding = 3) restrict readonly buffer screenTilesBufferSSBO
|
||||||
{
|
{
|
||||||
int elements[];
|
mg_gl_screen_tile elements[];
|
||||||
} screenTilesBuffer;
|
} screenTilesBuffer;
|
||||||
|
|
||||||
layout(location = 0) uniform float scale;
|
layout(location = 0) uniform float scale;
|
||||||
|
@ -33,11 +33,10 @@ layout(binding = 1) uniform sampler2D srcTexture;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
uvec2 nTiles = gl_NumWorkGroups.xy;
|
uint tileIndex = gl_WorkGroupID.x;
|
||||||
uvec2 tileCoord = gl_WorkGroupID.xy;
|
uvec2 tileCoord = screenTilesBuffer.elements[tileIndex].tileCoord;
|
||||||
uint tileIndex = tileCoord.y * nTiles.x + tileCoord.x;
|
ivec2 pixelCoord = ivec2(tileCoord * gl_WorkGroupSize.x + gl_LocalInvocationID.xy);
|
||||||
|
|
||||||
ivec2 pixelCoord = ivec2(gl_WorkGroupID.xy*uvec2(16, 16) + gl_LocalInvocationID.xy);
|
|
||||||
vec2 centerCoord = vec2(pixelCoord) + vec2(0.5, 0.5);
|
vec2 centerCoord = vec2(pixelCoord) + vec2(0.5, 0.5);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,7 +46,6 @@ void main()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
vec2 sampleCoords[MG_GL_MAX_SAMPLE_COUNT] = {
|
vec2 sampleCoords[MG_GL_MAX_SAMPLE_COUNT] = {
|
||||||
centerCoord + vec2(1, 3)/16,
|
centerCoord + vec2(1, 3)/16,
|
||||||
centerCoord + vec2(-1, -3)/16,
|
centerCoord + vec2(-1, -3)/16,
|
||||||
|
@ -66,57 +64,35 @@ void main()
|
||||||
sampleCoords[0] = centerCoord;
|
sampleCoords[0] = centerCoord;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 color[MG_GL_MAX_SAMPLE_COUNT];
|
const int srcSampleCount = 2;
|
||||||
|
|
||||||
|
vec2 imgSampleCoords[MG_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)};
|
||||||
|
|
||||||
|
vec4 color = vec4(0);
|
||||||
int winding[MG_GL_MAX_SAMPLE_COUNT];
|
int winding[MG_GL_MAX_SAMPLE_COUNT];
|
||||||
|
|
||||||
for(int i=0; i<sampleCount; i++)
|
for(int i=0; i<sampleCount; i++)
|
||||||
{
|
{
|
||||||
winding[i] = 0;
|
winding[i] = 0;
|
||||||
color[i] = vec4(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pathIndex = 0;
|
int pathIndex = 0;
|
||||||
int opIndex = screenTilesBuffer.elements[tileIndex];
|
int opIndex = screenTilesBuffer.elements[tileIndex].first;
|
||||||
|
|
||||||
while(opIndex >= 0)
|
while(opIndex >= 0)
|
||||||
{
|
{
|
||||||
mg_gl_tile_op op = tileOpBuffer.elements[opIndex];
|
mg_gl_tile_op op = tileOpBuffer.elements[opIndex];
|
||||||
opIndex = op.next;
|
|
||||||
|
|
||||||
if(op.kind == MG_GL_OP_START)
|
if(op.kind == MG_GL_OP_START)
|
||||||
{
|
{
|
||||||
vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
|
|
||||||
vec4 nextColor = pathBuffer.elements[pathIndex].color;
|
|
||||||
nextColor.rgb *= nextColor.a;
|
|
||||||
|
|
||||||
if(useTexture != 0)
|
|
||||||
{
|
|
||||||
vec3 ph = vec3(centerCoord.xy, 1);
|
|
||||||
vec2 uv = (pathBuffer.elements[pathIndex].uvTransform * ph).xy;
|
|
||||||
vec4 texColor = texture(srcTexture, uv);
|
|
||||||
texColor.rgb *= texColor.a;
|
|
||||||
nextColor *= texColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++)
|
for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++)
|
||||||
{
|
{
|
||||||
vec2 sampleCoord = sampleCoords[sampleIndex];
|
|
||||||
|
|
||||||
if( sampleCoord.x >= clip.x
|
|
||||||
&& sampleCoord.x < clip.z
|
|
||||||
&& sampleCoord.y >= clip.y
|
|
||||||
&& sampleCoord.y < clip.w)
|
|
||||||
{
|
|
||||||
bool filled = (pathBuffer.elements[pathIndex].cmd == MG_GL_FILL && ((winding[sampleIndex] & 1) != 0))
|
|
||||||
||(pathBuffer.elements[pathIndex].cmd == MG_GL_STROKE && (winding[sampleIndex] != 0));
|
|
||||||
if(filled)
|
|
||||||
{
|
|
||||||
color[sampleIndex] = color[sampleIndex]*(1-nextColor.a) + nextColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
winding[sampleIndex] = op.windingOffsetOrCrossRight;
|
winding[sampleIndex] = op.windingOffsetOrCrossRight;
|
||||||
}
|
}
|
||||||
pathIndex = op.index;
|
|
||||||
}
|
}
|
||||||
else if(op.kind == MG_GL_OP_SEGMENT)
|
else if(op.kind == MG_GL_OP_SEGMENT)
|
||||||
{
|
{
|
||||||
|
@ -149,24 +125,38 @@ void main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
int pathIndex = op.index;
|
||||||
|
|
||||||
vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
|
|
||||||
|
|
||||||
vec4 pixelColor = vec4(0);
|
|
||||||
vec4 nextColor = pathBuffer.elements[pathIndex].color;
|
vec4 nextColor = pathBuffer.elements[pathIndex].color;
|
||||||
nextColor.rgb *= nextColor.a;
|
nextColor.rgb *= nextColor.a;
|
||||||
|
|
||||||
if(useTexture != 0)
|
if(useTexture != 0)
|
||||||
{
|
{
|
||||||
vec3 ph = vec3(centerCoord.xy, 1);
|
vec4 texColor = vec4(0);
|
||||||
|
for(int sampleIndex = 0; sampleIndex<srcSampleCount; sampleIndex++)
|
||||||
|
{
|
||||||
|
vec2 sampleCoord = imgSampleCoords[sampleIndex];
|
||||||
|
vec3 ph = vec3(sampleCoord.xy, 1);
|
||||||
vec2 uv = (pathBuffer.elements[pathIndex].uvTransform * ph).xy;
|
vec2 uv = (pathBuffer.elements[pathIndex].uvTransform * ph).xy;
|
||||||
vec4 texColor = texture(srcTexture, uv);
|
texColor += texture(srcTexture, uv);
|
||||||
|
}
|
||||||
|
texColor /= srcSampleCount;
|
||||||
texColor.rgb *= texColor.a;
|
texColor.rgb *= texColor.a;
|
||||||
nextColor *= texColor;
|
nextColor *= texColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int sampleIndex=0; sampleIndex<sampleCount; sampleIndex++)
|
if(op.kind == MG_GL_OP_FILL)
|
||||||
|
{
|
||||||
|
color = color*(1-nextColor.a) + nextColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec4 clip = pathBuffer.elements[pathIndex].clip * scale;
|
||||||
|
float coverage = 0;
|
||||||
|
|
||||||
|
for(int sampleIndex = 0; sampleIndex<sampleCount; sampleIndex++)
|
||||||
{
|
{
|
||||||
vec2 sampleCoord = sampleCoords[sampleIndex];
|
vec2 sampleCoord = sampleCoords[sampleIndex];
|
||||||
|
|
||||||
|
@ -175,16 +165,22 @@ void main()
|
||||||
&& sampleCoord.y >= clip.y
|
&& sampleCoord.y >= clip.y
|
||||||
&& sampleCoord.y < clip.w)
|
&& sampleCoord.y < clip.w)
|
||||||
{
|
{
|
||||||
bool filled = (pathBuffer.elements[pathIndex].cmd == MG_GL_FILL && ((winding[sampleIndex] & 1) != 0))
|
bool filled = op.kind == MG_GL_OP_CLIP_FILL
|
||||||
|
||(pathBuffer.elements[pathIndex].cmd == MG_GL_FILL && ((winding[sampleIndex] & 1) != 0))
|
||||||
||(pathBuffer.elements[pathIndex].cmd == MG_GL_STROKE && (winding[sampleIndex] != 0));
|
||(pathBuffer.elements[pathIndex].cmd == MG_GL_STROKE && (winding[sampleIndex] != 0));
|
||||||
if(filled)
|
if(filled)
|
||||||
{
|
{
|
||||||
color[sampleIndex] = color[sampleIndex]*(1-nextColor.a) + nextColor;
|
coverage++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pixelColor += color[sampleIndex];
|
winding[sampleIndex] = op.windingOffsetOrCrossRight;
|
||||||
|
}
|
||||||
|
coverage /= sampleCount;
|
||||||
|
color = coverage*(color*(1-nextColor.a) + nextColor) + (1.-coverage)*color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opIndex = op.next;
|
||||||
}
|
}
|
||||||
pixelColor /= sampleCount;
|
|
||||||
|
|
||||||
imageStore(outTexture, pixelCoord, pixelColor);
|
imageStore(outTexture, pixelCoord, color);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1409,7 +1409,7 @@ const u32 MG_MTL_DEFAULT_PATH_BUFFER_LEN = (4<<10),
|
||||||
MG_MTL_DEFAULT_SEGMENT_BUFFER_LEN = (4<<10),
|
MG_MTL_DEFAULT_SEGMENT_BUFFER_LEN = (4<<10),
|
||||||
MG_MTL_DEFAULT_PATH_QUEUE_BUFFER_LEN = (4<<10),
|
MG_MTL_DEFAULT_PATH_QUEUE_BUFFER_LEN = (4<<10),
|
||||||
MG_MTL_DEFAULT_TILE_QUEUE_BUFFER_LEN = (4<<10),
|
MG_MTL_DEFAULT_TILE_QUEUE_BUFFER_LEN = (4<<10),
|
||||||
MG_MTL_DEFAULT_TILE_OP_BUFFER_LEN = (4<<14);
|
MG_MTL_DEFAULT_TILE_OP_BUFFER_LEN = (4<<20);
|
||||||
|
|
||||||
mg_canvas_backend* mtl_canvas_backend_create(mg_mtl_surface* surface)
|
mg_canvas_backend* mtl_canvas_backend_create(mg_mtl_surface* surface)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue