[win32, gl canvas] bound check intermediate buffers in canvas shaders
This commit is contained in:
		
							parent
							
								
									680deb35b0
								
							
						
					
					
						commit
						a35f0b82b2
					
				| 
						 | 
					@ -62,6 +62,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))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							log_error("Couln't create surface\n");
 | 
				
			||||||
 | 
							return(-1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	mg_surface_swap_interval(surface, 0);
 | 
						mg_surface_swap_interval(surface, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//TODO: create canvas
 | 
						//TODO: create canvas
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,6 +106,11 @@ 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if(pathOpIndex >= tileOpBuffer.elements.length())
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											return;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					tileOpBuffer.elements[pathOpIndex].kind = MG_GL_OP_CLIP_FILL;
 | 
										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;
 | 
				
			||||||
| 
						 | 
					@ -141,6 +146,10 @@ void main()
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				//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())
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				tileOpBuffer.elements[startOpIndex].kind = MG_GL_OP_START;
 | 
									tileOpBuffer.elements[startOpIndex].kind = MG_GL_OP_START;
 | 
				
			||||||
				tileOpBuffer.elements[startOpIndex].next = -1;
 | 
									tileOpBuffer.elements[startOpIndex].next = -1;
 | 
				
			||||||
| 
						 | 
					@ -163,6 +172,10 @@ void main()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				//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())
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				tileOpBuffer.elements[endOpIndex].kind = MG_GL_OP_END;
 | 
									tileOpBuffer.elements[endOpIndex].kind = MG_GL_OP_END;
 | 
				
			||||||
				tileOpBuffer.elements[endOpIndex].next = -1;
 | 
									tileOpBuffer.elements[endOpIndex].next = -1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,13 +50,21 @@ void main()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int tileQueuesIndex = atomicAdd(tileQueueCountBuffer.elements[0], tileCount);
 | 
						int tileQueuesIndex = atomicAdd(tileQueueCountBuffer.elements[0], tileCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pathQueueBuffer.elements[pathQueueBufferStart + pathIndex].area = ivec4(firstTile.x, firstTile.y, nTilesX, nTilesY);
 | 
						if(tileQueuesIndex + tileCount >= tileQueueBuffer.elements.length())
 | 
				
			||||||
	pathQueueBuffer.elements[pathQueueBufferStart + pathIndex].tileQueues = tileQueuesIndex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for(int i=0; i<tileCount; i++)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		tileQueueBuffer.elements[tileQueuesIndex + i].first = -1;
 | 
							pathQueueBuffer.elements[pathIndex].area = ivec4(0);
 | 
				
			||||||
		tileQueueBuffer.elements[tileQueuesIndex + i].last = -1;
 | 
							pathQueueBuffer.elements[pathIndex].tileQueues = 0;
 | 
				
			||||||
		tileQueueBuffer.elements[tileQueuesIndex + i].windingOffset = 0;
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							pathQueueBuffer.elements[pathQueueBufferStart + pathIndex].area = ivec4(firstTile.x, firstTile.y, nTilesX, nTilesY);
 | 
				
			||||||
 | 
							pathQueueBuffer.elements[pathQueueBufferStart + pathIndex].tileQueues = tileQueuesIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for(int i=0; i<tileCount; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								tileQueueBuffer.elements[tileQueuesIndex + i].first = -1;
 | 
				
			||||||
 | 
								tileQueueBuffer.elements[tileQueuesIndex + i].last = -1;
 | 
				
			||||||
 | 
								tileQueueBuffer.elements[tileQueuesIndex + i].windingOffset = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,29 +105,33 @@ void bin_to_tiles(int segIndex)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				int tileOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
 | 
									int tileOpIndex = atomicAdd(tileOpCountBuffer.elements[0], 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				tileOpBuffer.elements[tileOpIndex].kind = MG_GL_OP_SEGMENT;
 | 
									if(tileOpIndex < tileOpBuffer.elements.length())
 | 
				
			||||||
				tileOpBuffer.elements[tileOpIndex].index = segIndex;
 | 
					 | 
				
			||||||
				tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 0;
 | 
					 | 
				
			||||||
				tileOpBuffer.elements[tileOpIndex].next = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				int tileQueueIndex = pathQueue.tileQueues + y*pathArea.z + x;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				tileOpBuffer.elements[tileOpIndex].next = atomicExchange(tileQueueBuffer.elements[tileQueueIndex].first, tileOpIndex);
 | 
					 | 
				
			||||||
				if(tileOpBuffer.elements[tileOpIndex].next == -1)
 | 
					 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					tileQueueBuffer.elements[tileQueueIndex].last = tileOpIndex;
 | 
										tileOpBuffer.elements[tileOpIndex].kind = MG_GL_OP_SEGMENT;
 | 
				
			||||||
				}
 | 
										tileOpBuffer.elements[tileOpIndex].index = segIndex;
 | 
				
			||||||
 | 
										tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 0;
 | 
				
			||||||
 | 
										tileOpBuffer.elements[tileOpIndex].next = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				//NOTE: if the segment crosses the tile's bottom boundary, update the tile's winding offset
 | 
										int tileQueueIndex = pathQueue.tileQueues + y*pathArea.z + x;
 | 
				
			||||||
				if(crossB)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					atomicAdd(tileQueueBuffer.elements[tileQueueIndex].windingOffset, seg.windingIncrement);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				//NOTE: if the segment crosses the right boundary, mark it.
 | 
										tileOpBuffer.elements[tileOpIndex].next = atomicExchange(tileQueueBuffer.elements[tileQueueIndex].first,
 | 
				
			||||||
				if(crossR)
 | 
										                                                         tileOpIndex);
 | 
				
			||||||
				{
 | 
										if(tileOpBuffer.elements[tileOpIndex].next == -1)
 | 
				
			||||||
					tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 1;
 | 
										{
 | 
				
			||||||
 | 
											tileQueueBuffer.elements[tileQueueIndex].last = tileOpIndex;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										//NOTE: if the segment crosses the tile's bottom boundary, update the tile's winding offset
 | 
				
			||||||
 | 
										if(crossB)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											atomicAdd(tileQueueBuffer.elements[tileQueueIndex].windingOffset, seg.windingIncrement);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										//NOTE: if the segment crosses the right boundary, mark it.
 | 
				
			||||||
 | 
										if(crossR)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											tileOpBuffer.elements[tileOpIndex].windingOffsetOrCrossRight = 1;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -138,88 +142,90 @@ int push_segment(in vec2 p[4], int kind, int pathIndex)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int segIndex = atomicAdd(segmentCountBuffer.elements[0], 1);
 | 
						int segIndex = atomicAdd(segmentCountBuffer.elements[0], 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vec2 s, c, e;
 | 
						if(segIndex < segmentBuffer.elements.length())
 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch(kind)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case MG_GL_LINE:
 | 
							vec2 s, c, e;
 | 
				
			||||||
			s = p[0];
 | 
					 | 
				
			||||||
			c = p[0];
 | 
					 | 
				
			||||||
			e = p[1];
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case MG_GL_QUADRATIC:
 | 
							switch(kind)
 | 
				
			||||||
			s = p[0];
 | 
					 | 
				
			||||||
			c = p[1];
 | 
					 | 
				
			||||||
			e = p[2];
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case MG_GL_CUBIC:
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			s = p[0];
 | 
								case MG_GL_LINE:
 | 
				
			||||||
			float sqrNorm0 = dot(p[1]-p[0], p[1]-p[0]);
 | 
									s = p[0];
 | 
				
			||||||
			float sqrNorm1 = dot(p[3]-p[2], p[3]-p[2]);
 | 
									c = p[0];
 | 
				
			||||||
			if(sqrNorm0 < sqrNorm1)
 | 
									e = p[1];
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case MG_GL_QUADRATIC:
 | 
				
			||||||
 | 
									s = p[0];
 | 
				
			||||||
 | 
									c = p[1];
 | 
				
			||||||
 | 
									e = p[2];
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case MG_GL_CUBIC:
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				c = p[2];
 | 
									s = p[0];
 | 
				
			||||||
 | 
									float sqrNorm0 = dot(p[1]-p[0], p[1]-p[0]);
 | 
				
			||||||
 | 
									float sqrNorm1 = dot(p[3]-p[2], p[3]-p[2]);
 | 
				
			||||||
 | 
									if(sqrNorm0 < sqrNorm1)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										c = p[2];
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										c = p[1];
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									e = p[3];
 | 
				
			||||||
 | 
								} break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool goingUp = e.y >= s.y;
 | 
				
			||||||
 | 
							bool goingRight = e.x >= s.x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vec4 box = vec4(min(s.x, e.x),
 | 
				
			||||||
 | 
						                	min(s.y, e.y),
 | 
				
			||||||
 | 
						                	max(s.x, e.x),
 | 
				
			||||||
 | 
						                	max(s.y, e.y));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							segmentBuffer.elements[segIndex].kind = kind;
 | 
				
			||||||
 | 
							segmentBuffer.elements[segIndex].pathIndex = pathIndex;
 | 
				
			||||||
 | 
							segmentBuffer.elements[segIndex].windingIncrement = goingUp ? 1 : -1;
 | 
				
			||||||
 | 
							segmentBuffer.elements[segIndex].box = box;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							float dx = c.x - box.x;
 | 
				
			||||||
 | 
							float dy = c.y - box.y;
 | 
				
			||||||
 | 
							float alpha = (box.w - box.y)/(box.z - box.x);
 | 
				
			||||||
 | 
							float ofs = box.w - box.y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(goingUp == goingRight)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if(kind == MG_GL_LINE)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									segmentBuffer.elements[segIndex].config = MG_GL_BR;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if(dy > alpha*dx)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									segmentBuffer.elements[segIndex].config = MG_GL_TL;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				c = p[1];
 | 
									segmentBuffer.elements[segIndex].config = MG_GL_BR;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			e = p[3];
 | 
					 | 
				
			||||||
		} break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool goingUp = e.y >= s.y;
 | 
					 | 
				
			||||||
	bool goingRight = e.x >= s.x;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	vec4 box = vec4(min(s.x, e.x),
 | 
					 | 
				
			||||||
	                min(s.y, e.y),
 | 
					 | 
				
			||||||
	                max(s.x, e.x),
 | 
					 | 
				
			||||||
	                max(s.y, e.y));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	segmentBuffer.elements[segIndex].kind = kind;
 | 
					 | 
				
			||||||
	segmentBuffer.elements[segIndex].pathIndex = pathIndex;
 | 
					 | 
				
			||||||
	segmentBuffer.elements[segIndex].windingIncrement = goingUp ? 1 : -1;
 | 
					 | 
				
			||||||
	segmentBuffer.elements[segIndex].box = box;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	float dx = c.x - box.x;
 | 
					 | 
				
			||||||
	float dy = c.y - box.y;
 | 
					 | 
				
			||||||
	float alpha = (box.w - box.y)/(box.z - box.x);
 | 
					 | 
				
			||||||
	float ofs = box.w - box.y;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(goingUp == goingRight)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if(kind == MG_GL_LINE)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			segmentBuffer.elements[segIndex].config = MG_GL_BR;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if(dy > alpha*dx)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			segmentBuffer.elements[segIndex].config = MG_GL_TL;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			segmentBuffer.elements[segIndex].config = MG_GL_BR;
 | 
								if(kind == MG_GL_LINE)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									segmentBuffer.elements[segIndex].config = MG_GL_TR;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if(dy < ofs - alpha*dx)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									segmentBuffer.elements[segIndex].config = MG_GL_BL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									segmentBuffer.elements[segIndex].config = MG_GL_TR;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if(kind == MG_GL_LINE)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			segmentBuffer.elements[segIndex].config = MG_GL_TR;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if(dy < ofs - alpha*dx)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			segmentBuffer.elements[segIndex].config = MG_GL_BL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			segmentBuffer.elements[segIndex].config = MG_GL_TR;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return(segIndex);
 | 
						return(segIndex);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -229,9 +235,11 @@ int push_segment(in vec2 p[4], int kind, int pathIndex)
 | 
				
			||||||
void line_setup(vec2 p[4], int pathIndex)
 | 
					void line_setup(vec2 p[4], int pathIndex)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int segIndex = push_segment(p, MG_GL_LINE, pathIndex);
 | 
						int segIndex = push_segment(p, MG_GL_LINE, pathIndex);
 | 
				
			||||||
	segmentBuffer.elements[segIndex].hullVertex = p[0];
 | 
						if(segIndex < segmentBuffer.elements.length())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
	bin_to_tiles(segIndex);
 | 
							segmentBuffer.elements[segIndex].hullVertex = p[0];
 | 
				
			||||||
 | 
							bin_to_tiles(segIndex);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vec2 quadratic_blossom(vec2 p[4], float u, float v)
 | 
					vec2 quadratic_blossom(vec2 p[4], float u, float v)
 | 
				
			||||||
| 
						 | 
					@ -298,27 +306,30 @@ void quadratic_emit(vec2 p[4], int pathIndex)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int segIndex = push_segment(p, MG_GL_QUADRATIC, pathIndex);
 | 
						int segIndex = push_segment(p, MG_GL_QUADRATIC, pathIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//NOTE: compute implicit equation matrix
 | 
						if(segIndex < segmentBuffer.elements.length())
 | 
				
			||||||
	float det = p[0].x*(p[1].y-p[2].y) + p[1].x*(p[2].y-p[0].y) + p[2].x*(p[0].y - p[1].y);
 | 
						{
 | 
				
			||||||
 | 
							//NOTE: compute implicit equation matrix
 | 
				
			||||||
 | 
							float det = p[0].x*(p[1].y-p[2].y) + p[1].x*(p[2].y-p[0].y) + p[2].x*(p[0].y - p[1].y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	float a = p[0].y - p[1].y + 0.5*(p[2].y - p[0].y);
 | 
							float a = p[0].y - p[1].y + 0.5*(p[2].y - p[0].y);
 | 
				
			||||||
	float b = p[1].x - p[0].x + 0.5*(p[0].x - p[2].x);
 | 
							float b = p[1].x - p[0].x + 0.5*(p[0].x - p[2].x);
 | 
				
			||||||
	float c = p[0].x*p[1].y - p[1].x*p[0].y + 0.5*(p[2].x*p[0].y - p[0].x*p[2].y);
 | 
							float c = p[0].x*p[1].y - p[1].x*p[0].y + 0.5*(p[2].x*p[0].y - p[0].x*p[2].y);
 | 
				
			||||||
	float d = p[0].y - p[1].y;
 | 
							float d = p[0].y - p[1].y;
 | 
				
			||||||
	float e = p[1].x - p[0].x;
 | 
							float e = p[1].x - p[0].x;
 | 
				
			||||||
	float f = p[0].x*p[1].y - p[1].x*p[0].y;
 | 
							float f = p[0].x*p[1].y - p[1].x*p[0].y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	float flip = (  segmentBuffer.elements[segIndex].config == MG_GL_TL
 | 
							float flip = (  segmentBuffer.elements[segIndex].config == MG_GL_TL
 | 
				
			||||||
	             || segmentBuffer.elements[segIndex].config == MG_GL_BL)? -1 : 1;
 | 
						             	|| segmentBuffer.elements[segIndex].config == MG_GL_BL)? -1 : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	float g = flip*(p[2].x*(p[0].y - p[1].y) + p[0].x*(p[1].y - p[2].y) + p[1].x*(p[2].y - p[0].y));
 | 
							float g = flip*(p[2].x*(p[0].y - p[1].y) + p[0].x*(p[1].y - p[2].y) + p[1].x*(p[2].y - p[0].y));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	segmentBuffer.elements[segIndex].implicitMatrix = (1/det)*mat3(a, d, 0.,
 | 
							segmentBuffer.elements[segIndex].implicitMatrix = (1/det)*mat3(a, d, 0.,
 | 
				
			||||||
	                                                               b, e, 0.,
 | 
						                                                               	b, e, 0.,
 | 
				
			||||||
	                                                               c, f, g);
 | 
						                                                               	c, f, g);
 | 
				
			||||||
	segmentBuffer.elements[segIndex].hullVertex = p[1];
 | 
							segmentBuffer.elements[segIndex].hullVertex = p[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bin_to_tiles(segIndex);
 | 
							bin_to_tiles(segIndex);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void quadratic_setup(vec2 p[4], int pathIndex)
 | 
					void quadratic_setup(vec2 p[4], int pathIndex)
 | 
				
			||||||
| 
						 | 
					@ -654,71 +665,74 @@ void cubic_emit(cubic_info curve, vec2 p[4], float s0, float s1, vec2 sp[4], int
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int segIndex = push_segment(sp, MG_GL_CUBIC, pathIndex);
 | 
						int segIndex = push_segment(sp, MG_GL_CUBIC, pathIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vec2 v0 = p[0];
 | 
						if(segIndex < segmentBuffer.elements.length())
 | 
				
			||||||
	vec2 v1 = p[3];
 | 
					 | 
				
			||||||
	vec2 v2;
 | 
					 | 
				
			||||||
	mat3 K;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//TODO: haul that up in caller
 | 
					 | 
				
			||||||
	float sqrNorm0 = dot(p[1]-p[0], p[1]-p[0]);
 | 
					 | 
				
			||||||
	float sqrNorm1 = dot(p[2]-p[3], p[2]-p[3]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(dot(p[0]-p[3], p[0]-p[3]) > 1e-5)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if(sqrNorm0 >= sqrNorm1)
 | 
							vec2 v0 = p[0];
 | 
				
			||||||
 		{
 | 
							vec2 v1 = p[3];
 | 
				
			||||||
 			v2 = p[1];
 | 
							vec2 v2;
 | 
				
			||||||
			K = mat3(curve.K[0].xyz, curve.K[3].xyz, curve.K[1].xyz);
 | 
							mat3 K;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//TODO: haul that up in caller
 | 
				
			||||||
 | 
							float sqrNorm0 = dot(p[1]-p[0], p[1]-p[0]);
 | 
				
			||||||
 | 
							float sqrNorm1 = dot(p[2]-p[3], p[2]-p[3]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(dot(p[0]-p[3], p[0]-p[3]) > 1e-5)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if(sqrNorm0 >= sqrNorm1)
 | 
				
			||||||
 | 
					 			{
 | 
				
			||||||
 | 
					 				v2 = p[1];
 | 
				
			||||||
 | 
									K = mat3(curve.K[0].xyz, curve.K[3].xyz, curve.K[1].xyz);
 | 
				
			||||||
 | 
					 			}
 | 
				
			||||||
 | 
					 			else
 | 
				
			||||||
 | 
					 			{
 | 
				
			||||||
 | 
									v2 = p[2];
 | 
				
			||||||
 | 
									K = mat3(curve.K[0].xyz, curve.K[3].xyz, curve.K[2].xyz);
 | 
				
			||||||
 | 
					 			}
 | 
				
			||||||
 		}
 | 
					 		}
 | 
				
			||||||
 		else
 | 
					 		else
 | 
				
			||||||
 		{
 | 
					 		{
 | 
				
			||||||
 | 
								v1 = p[1];
 | 
				
			||||||
			v2 = p[2];
 | 
								v2 = p[2];
 | 
				
			||||||
			K = mat3(curve.K[0].xyz, curve.K[3].xyz, curve.K[2].xyz);
 | 
								K = mat3(curve.K[0].xyz, curve.K[1].xyz, curve.K[2].xyz);
 | 
				
			||||||
 		}
 | 
					 		}
 | 
				
			||||||
 	}
 | 
					 		//NOTE: set matrices
 | 
				
			||||||
 	else
 | 
					 | 
				
			||||||
 	{
 | 
					 | 
				
			||||||
		v1 = p[1];
 | 
					 | 
				
			||||||
		v2 = p[2];
 | 
					 | 
				
			||||||
		K = mat3(curve.K[0].xyz, curve.K[1].xyz, curve.K[2].xyz);
 | 
					 | 
				
			||||||
 	}
 | 
					 | 
				
			||||||
 	//NOTE: set matrices
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 	//TODO: should we compute matrix relative to a base point to avoid loss of precision
 | 
					 		//TODO: should we compute matrix relative to a base point to avoid loss of precision
 | 
				
			||||||
 	//      when computing barycentric matrix?
 | 
					 		//      when computing barycentric matrix?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mat3 B = barycentric_matrix(v0, v1, v2);
 | 
							mat3 B = barycentric_matrix(v0, v1, v2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 	segmentBuffer.elements[segIndex].implicitMatrix = K*B;
 | 
					 		segmentBuffer.elements[segIndex].implicitMatrix = K*B;
 | 
				
			||||||
	segmentBuffer.elements[segIndex].hullVertex = select_hull_vertex(sp[0], sp[1], sp[2], sp[3]);
 | 
							segmentBuffer.elements[segIndex].hullVertex = select_hull_vertex(sp[0], sp[1], sp[2], sp[3]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  	//NOTE: compute sign flip
 | 
					  		//NOTE: compute sign flip
 | 
				
			||||||
  	segmentBuffer.elements[segIndex].sign = 1;
 | 
					  		segmentBuffer.elements[segIndex].sign = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  	if(  curve.kind == CUBIC_SERPENTINE
 | 
					  		if(  curve.kind == CUBIC_SERPENTINE
 | 
				
			||||||
	  || curve.kind == CUBIC_CUSP)
 | 
						  	|| curve.kind == CUBIC_CUSP)
 | 
				
			||||||
  	{
 | 
					  		{
 | 
				
			||||||
		segmentBuffer.elements[segIndex].sign = (curve.d1 < 0)? -1 : 1;
 | 
								segmentBuffer.elements[segIndex].sign = (curve.d1 < 0)? -1 : 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if(curve.kind == CUBIC_LOOP)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								float d1 = curve.d1;
 | 
				
			||||||
 | 
								float d2 = curve.d2;
 | 
				
			||||||
 | 
								float d3 = curve.d3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								float H0 = d3*d1-square(d2) + d1*d2*s0 - square(d1)*square(s0);
 | 
				
			||||||
 | 
								float H1 = d3*d1-square(d2) + d1*d2*s1 - square(d1)*square(s1);
 | 
				
			||||||
 | 
								float H = (abs(H0) > abs(H1)) ? H0 : H1;
 | 
				
			||||||
 | 
								segmentBuffer.elements[segIndex].sign = (H*d1 > 0) ? -1 : 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(sp[3].y > sp[0].y)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								segmentBuffer.elements[segIndex].sign *= -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//NOTE: bin to tiles
 | 
				
			||||||
 | 
							bin_to_tiles(segIndex);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if(curve.kind == CUBIC_LOOP)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		float d1 = curve.d1;
 | 
					 | 
				
			||||||
		float d2 = curve.d2;
 | 
					 | 
				
			||||||
		float d3 = curve.d3;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		float H0 = d3*d1-square(d2) + d1*d2*s0 - square(d1)*square(s0);
 | 
					 | 
				
			||||||
		float H1 = d3*d1-square(d2) + d1*d2*s1 - square(d1)*square(s1);
 | 
					 | 
				
			||||||
		float H = (abs(H0) > abs(H1)) ? H0 : H1;
 | 
					 | 
				
			||||||
		segmentBuffer.elements[segIndex].sign = (H*d1 > 0) ? -1 : 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(sp[3].y > sp[0].y)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		segmentBuffer.elements[segIndex].sign *= -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//NOTE: bin to tiles
 | 
					 | 
				
			||||||
	bin_to_tiles(segIndex);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void cubic_setup(vec2 p[4], int pathIndex)
 | 
					void cubic_setup(vec2 p[4], int pathIndex)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue