Blame c++/contourgl/cl/contour-fs.cl

Ivan Mahonin d989ab
/*
Ivan Mahonin d989ab
    ......... 2015 Ivan Mahonin
Ivan Mahonin d989ab
Ivan Mahonin d989ab
    This program is free software: you can redistribute it and/or modify
Ivan Mahonin d989ab
    it under the terms of the GNU General Public License as published by
Ivan Mahonin d989ab
    the Free Software Foundation, either version 3 of the License, or
Ivan Mahonin d989ab
    (at your option) any later version.
Ivan Mahonin d989ab
Ivan Mahonin d989ab
    This program is distributed in the hope that it will be useful,
Ivan Mahonin d989ab
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Ivan Mahonin d989ab
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ivan Mahonin d989ab
    GNU General Public License for more details.
Ivan Mahonin d989ab
Ivan Mahonin d989ab
    You should have received a copy of the GNU General Public License
Ivan Mahonin d989ab
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
Ivan Mahonin d989ab
*/
Ivan Mahonin d989ab
Ivan Mahonin 013f0c
// paths format:
Ivan Mahonin 013f0c
//   {
Ivan Mahonin 013f0c
//     int count,
Ivan Mahonin 013f0c
//     paths: [
Ivan Mahonin 013f0c
//       {
Ivan Mahonin 013f0c
//         int point_count,
Ivan Mahonin 013f0c
//         int flags,
Ivan Mahonin 013f0c
//         float4 color,
Ivan Mahonin 013f0c
//         points: [ float2, ... ]
Ivan Mahonin 013f0c
//       },
Ivan Mahonin 013f0c
//       ...
Ivan Mahonin 013f0c
//     ]
Ivan Mahonin 013f0c
//   }
Ivan Mahonin 013f0c
Ivan Mahonin 67876c
Ivan Mahonin 013f0c
kernel void draw(
Ivan Mahonin 2517eb
	const int width,
Ivan Mahonin 2517eb
	const int height,
Ivan Mahonin c7fa36
	global int *mark_buffer,
Ivan Mahonin 2517eb
	global float4 *image,
Ivan Mahonin 2517eb
	global const char *paths_buffer )
Ivan Mahonin d989ab
{
Ivan Mahonin 5890eb
	const float e = 1e-6f;
Ivan Mahonin 013f0c
Ivan Mahonin 2517eb
	int id = (int)get_local_id(0);
Ivan Mahonin 2517eb
	int count = (int)get_local_size(0);
Ivan Mahonin 013f0c
	
Ivan Mahonin 013f0c
	int paths_count = *(global int *)paths_buffer;
Ivan Mahonin 2517eb
	global const char *paths = paths_buffer + sizeof(int);
Ivan Mahonin c7fa36
	
Ivan Mahonin 013f0c
	int pixels_count = width*height;
Ivan Mahonin 013f0c
	float2 size = (float2)((float)width, (float)height); 
Ivan Mahonin c7fa36
	int w1 = width - 1;
Ivan Mahonin c7fa36
	int h1 = height - 1;
Ivan Mahonin c7fa36
	
Ivan Mahonin 2517eb
	local int bound_minx;
Ivan Mahonin 2517eb
	local int bound_miny;
Ivan Mahonin 2517eb
	local int bound_maxx;
Ivan Mahonin 2517eb
	local int bound_maxy;
Ivan Mahonin 013f0c
	
Ivan Mahonin 013f0c
	// draw paths
Ivan Mahonin 013f0c
	for(int p = 0; p < paths_count; ++p) {
Ivan Mahonin 2517eb
		int points_count = *(global const int *)paths; paths += sizeof(int);
Ivan Mahonin 2517eb
		int flags        = *(global const int *)paths; paths += sizeof(int);
Ivan Mahonin c7fa36
		
Ivan Mahonin 013f0c
		float4 color;
Ivan Mahonin 2517eb
		color.x = *(global const float *)paths; paths += sizeof(float);
Ivan Mahonin 2517eb
		color.y = *(global const float *)paths; paths += sizeof(float);
Ivan Mahonin 2517eb
		color.z = *(global const float *)paths; paths += sizeof(float);
Ivan Mahonin 2517eb
		color.w = *(global const float *)paths; paths += sizeof(float);
Ivan Mahonin c7fa36
		
Ivan Mahonin 2517eb
		global const float *points = (global const float *)paths;
Ivan Mahonin 013f0c
		paths += 2*points_count*sizeof(float);
Ivan Mahonin 013f0c
		
Ivan Mahonin 013f0c
		int segments_count = points_count - 1;
Ivan Mahonin 013f0c
		if (segments_count <= 0) continue;
Ivan Mahonin 013f0c
		
Ivan Mahonin 2517eb
		bool invert  = flags & 1;
Ivan Mahonin 2517eb
		bool evenodd = flags & 2;
Ivan Mahonin 013f0c
		
Ivan Mahonin 2517eb
		if (id == 0) {
Ivan Mahonin 2517eb
			bound_minx = invert ?  0 : (int)floor(points[0] + e);
Ivan Mahonin 2517eb
			bound_miny = invert ?  0 : (int)floor(points[1] + e);
Ivan Mahonin 2517eb
			bound_maxx = invert ? w1 : bound_minx;
Ivan Mahonin 2517eb
			bound_maxy = invert ? h1 : bound_miny;
Ivan Mahonin 2517eb
		}
Ivan Mahonin 2517eb
		barrier(CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE);
Ivan Mahonin d989ab
Ivan Mahonin 013f0c
		// trace path
Ivan Mahonin 013f0c
		for(int i = id; i < segments_count; i += count) {
Ivan Mahonin 013f0c
			int ii = 2*i;
Ivan Mahonin 013f0c
			float2 p0 = { points[ii + 0], points[ii + 1] };
Ivan Mahonin 013f0c
			float2 p1 = { points[ii + 2], points[ii + 3] };
Ivan Mahonin 013f0c
			
Ivan Mahonin 2517eb
			int p1x = (int)floor(p1.x + e);
Ivan Mahonin 2517eb
			int p1y = (int)floor(p1.y + e);
Ivan Mahonin 2517eb
			atomic_min(&bound_minx, p1x);
Ivan Mahonin 2517eb
			atomic_min(&bound_miny, p1y);
Ivan Mahonin 2517eb
			atomic_max(&bound_maxx, p1x);
Ivan Mahonin 2517eb
			atomic_max(&bound_maxy, p1y);
Ivan Mahonin 013f0c
				
Ivan Mahonin 013f0c
			bool flipx = p1.x < p0.x;
Ivan Mahonin 013f0c
			bool flipy = p1.y < p0.y;
Ivan Mahonin 013f0c
			if (flipx) { p0.x = size.x - p0.x; p1.x = size.x - p1.x; }
Ivan Mahonin 013f0c
			if (flipy) { p0.y = size.y - p0.y; p1.y = size.y - p1.y; }
Ivan Mahonin 013f0c
			float2 d = p1 - p0;
Ivan Mahonin 013f0c
			float kx = fabs(d.y) < e ? 1e10 : d.x/d.y;
Ivan Mahonin 013f0c
			float ky = fabs(d.x) < e ? 1e10 : d.y/d.x;
Ivan Mahonin 013f0c
			
Ivan Mahonin 013f0c
			while(p0.x != p1.x || p0.y != p1.y) {
Ivan Mahonin 013f0c
				int ix = (int)floor(p0.x + e);
Ivan Mahonin 013f0c
				int iy = (int)floor(p0.y + e);
Ivan Mahonin 013f0c
				if (iy > h1) break;
Ivan Mahonin 0b3288
Ivan Mahonin 2517eb
				float px = (float)(ix + 1);
Ivan Mahonin 2517eb
				float py = (float)(iy + 1);
Ivan Mahonin 013f0c
				float2 pp1 = p1;
Ivan Mahonin 2517eb
				if (pp1.x > px) { pp1.x = px; pp1.y = p0.y + ky*(px - p0.x); }
Ivan Mahonin 2517eb
				if (pp1.y > py) { pp1.y = py; pp1.x = p0.x + kx*(py - p0.y); }
Ivan Mahonin 013f0c
				
Ivan Mahonin 013f0c
				if (iy >= 0) {
Ivan Mahonin 013f0c
					// calc values
Ivan Mahonin 013f0c
					float cover = pp1.y - p0.y;
Ivan Mahonin 2517eb
					float area = px - 0.5f*(p0.x + pp1.x);
Ivan Mahonin 013f0c
					if (flipx) { ix = w1 - ix; area = 1.f - area; }
Ivan Mahonin 013f0c
					if (flipy) { iy = h1 - iy; cover = -cover; }
Ivan Mahonin 013f0c
					ix = clamp(ix, 0, w1);
Ivan Mahonin 013f0c
					
Ivan Mahonin 013f0c
					// store in buffer
Ivan Mahonin 013f0c
					global int *mark = mark_buffer + (iy*width + ix)*2;
Ivan Mahonin 013f0c
					atomic_add(mark, (int)round(area*cover*65536.f));
Ivan Mahonin 013f0c
					atomic_add(mark + 1, (int)round(cover*65536.f));
Ivan Mahonin 013f0c
				}
Ivan Mahonin 013f0c
				
Ivan Mahonin 013f0c
				p0 = pp1;
Ivan Mahonin 013f0c
			}
Ivan Mahonin 013f0c
		}
Ivan Mahonin 2517eb
		barrier(CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE);
Ivan Mahonin 2517eb
Ivan Mahonin 2517eb
		// read bounds
Ivan Mahonin 2517eb
		int minx = max(bound_minx, 0);
Ivan Mahonin 2517eb
		int miny = max(bound_miny, 0);
Ivan Mahonin 2517eb
		int maxx = min(bound_maxx, w1);
Ivan Mahonin 2517eb
		int maxy = min(bound_maxy, h1);
Ivan Mahonin 2517eb
		barrier(CLK_GLOBAL_MEM_FENCE | CLK_LOCAL_MEM_FENCE);
Ivan Mahonin 2517eb
Ivan Mahonin 013f0c
		// fill
Ivan Mahonin 2517eb
		for(int row = miny + id; row <= maxy; row += count) {
Ivan Mahonin 2517eb
			global int *mark = mark_buffer + (row*width + minx)*2;
Ivan Mahonin 2517eb
			global float4 *pixel = image + row*width + minx;
Ivan Mahonin 2517eb
			global float4 *pixel_end = pixel - minx + maxx + 1;
Ivan Mahonin 2517eb
			int icover = 0;
Ivan Mahonin 2517eb
			
Ivan Mahonin 2517eb
			while(pixel < pixel_end) {
Ivan Mahonin 013f0c
				// read mark (alpha, cover)
Ivan Mahonin 2517eb
				int ialpha = abs(icover + *mark); *mark = 0; ++mark;
Ivan Mahonin 2517eb
				icover += *mark;                  *mark = 0; ++mark;
Ivan Mahonin 2517eb
				
Ivan Mahonin 2517eb
				if (evenodd) ialpha = 65536 - abs(ialpha%131072 - 65536);
Ivan Mahonin 2517eb
				if (invert)  ialpha = 65536 - ialpha;
Ivan Mahonin 013f0c
				
Ivan Mahonin 2517eb
				//if (!ialpha) continue;
Ivan Mahonin 013f0c
				
Ivan Mahonin 013f0c
				// write color
Ivan Mahonin 2517eb
				float alpha = (float)ialpha/65536.f*color.w;
Ivan Mahonin 2517eb
				*pixel = *pixel*(1.f - alpha) + color*alpha;
Ivan Mahonin 2517eb
				++pixel;
Ivan Mahonin 013f0c
			}
Ivan Mahonin 013f0c
		}
Ivan Mahonin d989ab
	}
Ivan Mahonin d989ab
}
Ivan Mahonin 013f0c