diff --git a/c++/contourgl/cl/contour.cl b/c++/contourgl/cl/contour.cl index d03cd67..cbe5244 100644 --- a/c++/contourgl/cl/contour.cl +++ b/c++/contourgl/cl/contour.cl @@ -15,71 +15,69 @@ along with this program. If not, see . */ -__kernel void clear2f( - __global float2 *buffer ) +kernel void clear( + global int2 *mark_buffer ) { - const float2 v = { 0.f, 0.f }; - buffer[get_global_id(0)] = v; + const int2 v = { 0, 0 }; + mark_buffer[get_global_id(0)] = v; } -__kernel void lines( - int width, - __global float4 *lines, - __global int2 *rows, - __global float2 *mark_buffer ) +kernel void path( + int width, + int height, + global int *mark_buffer, + global float2 *path ) { const float e = 1e-6f; - int2 row = rows[get_global_id(0)]; - sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE - | CLK_ADDRESS_NONE - | CLK_FILTER_NEAREST; - int w = width; - for(__global float4 *i = lines + row.x, *end = i + row.y; i < end; ++i) { - float4 line = *i; - float2 p0 = { line.x, line.y }; - float2 p1 = { line.z, line.w }; - - int iy0 = (int)floor(fmin(p0.y, p1.y) + e); - int iy1 = (int)floor(fmax(p0.y, p1.y) - e); - - float2 d = p1 - p0; - float kx = fabs(d.y) < e ? 0.f : d.x/d.y; - float ky = fabs(d.x) < e ? 0.f : d.y/d.x; - - for(int r = iy0; r <= iy1; ++r) { - float y = (float)r; - float2 pya = { p0.x + kx*(y - p0.y), y }; - float2 pyb = { p0.x + kx*(y + 1.0 - p0.y), y + 1.f }; - float2 pp0 = p0.y - y < -e ? pya - : (p0.y - y > 1.f + e ? pyb : p0); - float2 pp1 = p1.y - y < -e ? pya - : (p1.y - y > 1.f + e ? pyb : p1); + size_t id = get_global_id(0); + + float2 s = { (float)width, (float)height }; + int w1 = width - 1; + int h1 = height - 1; - int ix0 = (int)floor(fmin(pp0.x, pp1.x) + e); - int ix1 = (int)floor(fmax(pp0.x, pp1.x) - e); - for(int c = ix0; c <= ix1; ++c) { - float x = (float)c; - float2 pxa = { x, p0.y + ky*(x - p0.x) }; - float2 pxb = { x + 1.0, p0.y + ky*(x + 1.0 - p0.x) }; - float2 ppp0 = pp0.x - x < -e ? pxa - : (pp0.x - x > 1.f + e ? pxb : pp0); - float2 ppp1 = pp1.x - x < -e ? pxa - : (pp1.x - x > 1.f + e ? pxb : pp1); + float2 p0 = path[id]; + float2 p1 = path[id + 1]; + bool flipx = p1.x < p0.x; + bool flipy = p1.y < p0.y; + if (flipx) { p0.x = s.x - p0.x; p1.x = s.x - p1.x; } + if (flipy) { p0.y = s.y - p0.y; p1.y = s.y - p1.y; } + float2 d = p1 - p0; + float kx = fabs(d.y) < e ? 1e10 : d.x/d.y; + float ky = fabs(d.x) < e ? 1e10 : d.y/d.x; + + while(p0.x != p1.x || p0.y != p1.y) { + int ix = (int)floor(p0.x + e); + int iy = (int)floor(p0.y + e); + if (iy > h1) break; - float2 m; - m.y = ppp1.y - ppp0.y; - m.x = (x + 1.f - 0.5f*(ppp0.x + ppp1.x))*m.y; - mark_buffer[r*w + c] += m; - } + float2 px, py; + px.x = (float)(ix + 1); + px.y = p0.y + ky*(px.x - p0.x); + py.y = max((float)(iy + 1), 0.f); + py.x = p0.x + kx*(py.y - p0.y); + float2 pp1 = p1; + if (pp1.x > px.x) pp1 = px; + if (pp1.y > py.y) pp1 = py; + + if (iy >= 0) { + float cover = pp1.y - p0.y; + float area = px.x - 0.5f*(p0.x + pp1.x); + if (flipx) { ix = w1 - ix; area = 1.f - area; } + if (flipy) { iy = h1 - iy; cover = -cover; } + global int *mark = mark_buffer + 2*(iy*width + clamp(ix, 0, w1)); + atomic_add(mark, (int)round(area*cover*65536)); + atomic_add(mark + 1, (int)round(cover*65536)); } + + p0 = pp1; } } -__kernel void fill( +kernel void fill( int width, - __global float2 *mark_buffer, - __read_only image2d_t surface_read_image, - __write_only image2d_t surface_write_image, + global int2 *mark_buffer, + read_only image2d_t surface_read_image, + write_only image2d_t surface_write_image, float4 color, int invert, int evenodd ) @@ -91,14 +89,15 @@ __kernel void fill( | CLK_FILTER_NEAREST; float4 cl = color; float cover = 0.f; - __global float2 *mark = mark_buffer + id*w; + global int2 *mark = mark_buffer + id*w; + const int2 izero = { 0, 0 }; for(int2 coord = { 0, id }; coord.x < w; ++coord.x, ++mark) { - float2 m = *mark; - - float alpha = fabs(m.x + cover); - cover += m.y; + int2 im = *mark; + //*mark = izero; + float alpha = fabs((float)im.x/65536.f + cover); + cover += (float)im.y/65536.f; alpha = evenodd ? (1.f - fabs(1.f - alpha - 2.f*floor(0.5f*alpha))) - : fmin(alpha, 1.f); + : fmin(alpha, 1.f); alpha *= cl.w; if (invert) alpha = 1.f - alpha; float alpha_inv = 1.f - alpha; diff --git a/c++/contourgl/clcontext.cpp b/c++/contourgl/clcontext.cpp index 15c876d..4cb448b 100644 --- a/c++/contourgl/clcontext.cpp +++ b/c++/contourgl/clcontext.cpp @@ -69,12 +69,15 @@ ClContext::ClContext(): err(), context(), queue() { // context - context = clCreateContext(0, 1, &devices.front(), NULL, NULL, &err); + cl_context_properties context_props[] = { + CL_CONTEXT_PLATFORM, (cl_context_properties)platform, + CL_NONE }; + context = clCreateContext(context_props, 1, &devices.front(), callback, NULL, &err); assert(context); // command queue - queue = clCreateCommandQueue(context, devices[0], 0, NULL); + queue = clCreateCommandQueue(context, devices.front(), CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, NULL); assert(queue); } @@ -84,6 +87,8 @@ ClContext::~ClContext() { clReleaseContext(context); } +void ClContext::callback(const char *, const void *, size_t, void *) { } + cl_program ClContext::load_program(const std::string &filename) { ifstream f(("cl/" + filename).c_str()); string text((istreambuf_iterator(f)), istreambuf_iterator()); diff --git a/c++/contourgl/clcontext.h b/c++/contourgl/clcontext.h index 6ced007..6061d43 100644 --- a/c++/contourgl/clcontext.h +++ b/c++/contourgl/clcontext.h @@ -36,6 +36,7 @@ public: void hello(); cl_program load_program(const std::string &filename); + static void callback(const char *, const void *, size_t, void *); }; #endif diff --git a/c++/contourgl/clrender.cpp b/c++/contourgl/clrender.cpp index f6335c6..ae918a4 100644 --- a/c++/contourgl/clrender.cpp +++ b/c++/contourgl/clrender.cpp @@ -29,44 +29,40 @@ using namespace std; ClRender::ClRender(ClContext &cl): cl(cl), contour_program(), - contour_lines_kernel(), + contour_path_kernel(), contour_fill_kernel(), surface(), - rows_buffer(), + path_buffer(), mark_buffer(), surface_image(), - prev_event(), - rows_count(), - even_rows_count(), - odd_rows_count() + prev_event() { contour_program = cl.load_program("contour.cl"); - contour_clear2f_kernel = clCreateKernel(contour_program, "clear2f", NULL); - assert(contour_clear2f_kernel); - contour_lines_kernel = clCreateKernel(contour_program, "lines", NULL); - assert(contour_lines_kernel); + contour_clear_kernel = clCreateKernel(contour_program, "clear", NULL); + assert(contour_clear_kernel); + contour_path_kernel = clCreateKernel(contour_program, "path", NULL); + assert(contour_path_kernel); contour_fill_kernel = clCreateKernel(contour_program, "fill", NULL); assert(contour_fill_kernel); } ClRender::~ClRender() { send_surface(NULL); - clReleaseKernel(contour_clear2f_kernel); + send_path(NULL, 0); + clReleaseKernel(contour_clear_kernel); clReleaseKernel(contour_fill_kernel); - clReleaseKernel(contour_lines_kernel); + clReleaseKernel(contour_path_kernel); clReleaseProgram(contour_program); } void ClRender::send_surface(Surface *surface) { - if (this->surface == surface) return; + if (!surface && !this->surface) return; - cl.err = clFinish(cl.queue); - prev_event = NULL; + cl.err |= clFinish(cl.queue); assert(!cl.err); + prev_event = NULL; if (this->surface) { - rows.clear(); - clReleaseMemObject(rows_buffer); clReleaseMemObject(mark_buffer); clReleaseMemObject(surface_image); } @@ -76,24 +72,28 @@ void ClRender::send_surface(Surface *surface) { if (this->surface) { //Measure t("ClRender::send_surface"); - rows_count = surface->height; - even_rows_count = (rows_count+1)/2; - odd_rows_count = rows_count - even_rows_count; - rows.resize(rows_count); - marks.resize(surface->count()); - - rows_buffer = clCreateBuffer( - cl.context, CL_MEM_READ_ONLY, - rows.size()*sizeof(rows.front()), NULL, - NULL ); - assert(rows_buffer); - mark_buffer = clCreateBuffer( cl.context, CL_MEM_READ_WRITE, - surface->count()*sizeof(cl_float2), NULL, + surface->count()*sizeof(cl_int2), NULL, NULL ); assert(mark_buffer); + cl.err |= clSetKernelArg(contour_clear_kernel, 0, sizeof(mark_buffer), &mark_buffer); + assert(!cl.err); + + size_t pixels_count = (size_t)surface->count(); + cl.err |= clEnqueueNDRangeKernel( + cl.queue, + contour_clear_kernel, + 1, + NULL, + &pixels_count, + NULL, + 0, + NULL, + NULL ); + assert(!cl.err); + cl_image_format surface_format = { }; surface_format.image_channel_order = CL_RGBA; surface_format.image_channel_data_type = CL_FLOAT; @@ -107,10 +107,25 @@ void ClRender::send_surface(Surface *surface) { size_t origin[3] = { }; size_t region[3] = { (size_t)surface->width, (size_t)surface->height, 1 }; cl.err |= clEnqueueWriteImage( - cl.queue, surface_image, CL_TRUE, + cl.queue, surface_image, CL_FALSE, origin, region, 0, 0, surface->data, - 0, NULL, &prev_event ); + 0, NULL, NULL ); + assert(!cl.err); + + int width = surface->width; + int height = surface->height; + cl.err |= clSetKernelArg(contour_path_kernel, 0, sizeof(width), &width); + cl.err |= clSetKernelArg(contour_path_kernel, 1, sizeof(height), &height); + cl.err |= clSetKernelArg(contour_path_kernel, 2, sizeof(mark_buffer), &mark_buffer); + assert(!cl.err); + + cl.err |= clSetKernelArg(contour_fill_kernel, 0, sizeof(width), &width); + cl.err |= clSetKernelArg(contour_fill_kernel, 1, sizeof(mark_buffer), &mark_buffer); + cl.err |= clSetKernelArg(contour_fill_kernel, 2, sizeof(surface_image), &surface_image); + cl.err |= clSetKernelArg(contour_fill_kernel, 3, sizeof(surface_image), &surface_image); + assert(!cl.err); + cl.err |= clFinish(cl.queue); assert(!cl.err); } } @@ -122,213 +137,111 @@ Surface* ClRender::receive_surface() { size_t origin[3] = { }; size_t region[3] = { (size_t)surface->width, (size_t)surface->height, 1 }; cl.err |= clEnqueueReadImage( - cl.queue, surface_image, CL_TRUE, + cl.queue, surface_image, CL_FALSE, origin, region, 0, 0, surface->data, prev_event ? 1 : 0, &prev_event, NULL ); assert(!cl.err); - clFinish(cl.queue); + + cl.err |= clFinish(cl.queue); + assert(!cl.err); prev_event = NULL; } return surface; } +void ClRender::send_path(const vec2f *path, int count) { + if (!path_buffer && (!path || count <=0)) return; -void ClRender::contour(const Contour &contour, const Rect &rect, const Color &color, bool invert, bool evenodd) { - //Measure t("ClRender::contour"); - - Contour transformed, splitted; - Rect to(1.0, 1.0, surface->width - 1.0, surface->height - 1.0); - - { - //Measure t("clone"); - transformed = contour; - } - - { - //Measure t("transform"); - transformed.transform(rect, to); - } - - { - Measure t("split"); - splitted.allow_split_lines = true; - transformed.split(splitted, to, Vector(0.5, 0.5)); - } - - vector lines; - vector sorted_lines; - vector line_rows; - - { - Measure t("sort lines"); - - // reset rows - for(int i = 0; i < (int)rows_count; ++i) - rows[i].second = 0; - - // count lines - Vector prev; - lines.reserve(splitted.get_chunks().size()); - line_rows.reserve(splitted.get_chunks().size()); - float x0 = (float)to.p0.x; - float x1 = (float)to.p1.x; - for(Contour::ChunkList::const_iterator i = splitted.get_chunks().begin(); i != splitted.get_chunks().end(); ++i) { - if ( i->type == Contour::LINE - || i->type == Contour::CLOSE ) - { - if (i->p1.y > to.p0.y && i->p1.y < to.p1.y) { - line2f l(vec2f(prev), vec2f(i->p1)); - l.p0.x = min(max(l.p0.x, x0), x1); - l.p1.x = min(max(l.p1.x, x0), x1); - assert( (int)floorf(l.p0.x) >= 0 && (int)floorf(l.p0.x) < surface->width - && (int)floorf(l.p1.x) >= 0 && (int)floorf(l.p1.x) < surface->width - && (int)floorf(l.p0.y) >= 0 && (int)floorf(l.p1.y) < surface->height - && (int)floorf(l.p1.y) >= 0 && (int)floorf(l.p1.y) < surface->height - && abs((int)floorf(l.p1.x) - (int)floorf(l.p0.x)) <= 1 - && abs((int)floorf(l.p1.y) - (int)floorf(l.p0.y)) <= 1 ); - int row = (int)floorf(min(l.p0.y, l.p1.y)); - row = row % 2 ? row/2 : even_rows_count + row/2; - assert(row >= 0 && row < (int)rows_count); - line_rows.push_back(row); - lines.push_back(l); - ++rows[row].second; - } - } - prev = i->p1; - } + cl.err |= clFinish(cl.queue); + assert(!cl.err); + prev_event = NULL; - // calc rows offsets - int lines_count = (int)lines.size(); - rows[0].first = rows[0].second; - for(int i = 1; i < (int)rows_count; ++i) - rows[i].first = rows[i-1].first + rows[i].second; - - // make sorted list - sorted_lines.resize(lines_count); - for(int i = 0; i < lines_count; ++i) { - assert(rows[line_rows[i]].first > 0 && rows[line_rows[i]].first <= lines_count); - sorted_lines[ --rows[line_rows[i]].first ] = lines[i]; - } + if (path_buffer) { + clReleaseMemObject(path_buffer); + path_buffer = NULL; } - if (sorted_lines.empty()) return; + if (path && count > 0) { + //Measure t("ClRender::send_path"); - cl_mem lines_buffer = NULL; - - { - Measure t("create lines buffer"); - - lines_buffer = clCreateBuffer( + path_buffer = clCreateBuffer( cl.context, CL_MEM_READ_ONLY, - sorted_lines.size()*sizeof(sorted_lines.front()), NULL, + count*sizeof(*path), NULL, NULL ); - assert(lines_buffer); - } - - { - Measure t("enqueue commands"); - - // kernel args - - int width = surface->width; - - cl.err |= clSetKernelArg(contour_clear2f_kernel, 0, sizeof(mark_buffer), &mark_buffer); - assert(!cl.err); - - cl.err |= clSetKernelArg(contour_lines_kernel, 0, sizeof(width), &width); - cl.err |= clSetKernelArg(contour_lines_kernel, 1, sizeof(lines_buffer), &lines_buffer); - cl.err |= clSetKernelArg(contour_lines_kernel, 2, sizeof(rows_buffer), &rows_buffer); - cl.err |= clSetKernelArg(contour_lines_kernel, 3, sizeof(mark_buffer), &mark_buffer); - assert(!cl.err); - - int iinvert = invert, ievenodd = evenodd; - cl.err |= clSetKernelArg(contour_fill_kernel, 0, sizeof(width), &width); - cl.err |= clSetKernelArg(contour_fill_kernel, 1, sizeof(mark_buffer), &mark_buffer); - cl.err |= clSetKernelArg(contour_fill_kernel, 2, sizeof(surface_image), &surface_image); - cl.err |= clSetKernelArg(contour_fill_kernel, 3, sizeof(surface_image), &surface_image); - cl.err |= clSetKernelArg(contour_fill_kernel, 4, sizeof(color), &color); - cl.err |= clSetKernelArg(contour_fill_kernel, 5, sizeof(int), &iinvert); - cl.err |= clSetKernelArg(contour_fill_kernel, 6, sizeof(int), &ievenodd); - assert(!cl.err); - - // init buffers - - cl_event prepare_buffers_events[3] = { }; + assert(path_buffer); cl.err |= clEnqueueWriteBuffer( - cl.queue, lines_buffer, CL_TRUE, - 0, sorted_lines.size()*sizeof(sorted_lines.front()), &sorted_lines.front(), - 0, NULL, &prepare_buffers_events[0] ); + cl.queue, path_buffer, CL_FALSE, + 0, count*sizeof(*path), path, + 0, NULL, NULL ); assert(!cl.err); - cl.err |= clEnqueueWriteBuffer( - cl.queue, rows_buffer, CL_TRUE, - 0, rows.size()*sizeof(rows.front()), &rows.front(), - 0, NULL, &prepare_buffers_events[1] ); + int path_size = count; + cl.err |= clSetKernelArg(contour_path_kernel, 3, sizeof(path_buffer), &path_buffer); assert(!cl.err); - size_t count = (size_t)surface->count(); - cl.err |= clEnqueueNDRangeKernel( - cl.queue, - contour_clear2f_kernel, - 1, - NULL, - &count, - NULL, - prev_event ? 1 : 0, - &prev_event, - &prepare_buffers_events[2] ); + cl.err |= clFinish(cl.queue); assert(!cl.err); + } +} - // build marks - - cl_event lines_odd_event = NULL; - cl.err |= clEnqueueNDRangeKernel( - cl.queue, - contour_lines_kernel, - 1, - NULL, - &even_rows_count, - NULL, - 3, - prepare_buffers_events, - &lines_odd_event ); - assert(!cl.err); +void ClRender::path(int start, int count, const Color &color, bool invert, bool evenodd) { + //Measure t("ClRender::contour"); - cl_event lines_even_event = NULL; - cl.err |= clEnqueueNDRangeKernel( - cl.queue, - contour_lines_kernel, - 1, - &even_rows_count, - &odd_rows_count, - NULL, - 1, - &lines_odd_event, - &lines_even_event ); - assert(!cl.err); + if (count <= 1) return; - // fill + // kernel args + int iinvert = invert, ievenodd = evenodd; + cl.err |= clSetKernelArg(contour_fill_kernel, 4, sizeof(color), &color); + cl.err |= clSetKernelArg(contour_fill_kernel, 5, sizeof(int), &iinvert); + cl.err |= clSetKernelArg(contour_fill_kernel, 6, sizeof(int), &ievenodd); + assert(!cl.err); - cl.err |= clEnqueueNDRangeKernel( - cl.queue, - contour_fill_kernel, - 1, - NULL, - &rows_count, - NULL, - 1, - &lines_even_event, - &prev_event ); - assert(!cl.err); + // clear + + size_t pixels_count = (size_t)surface->count(); + cl.err |= clEnqueueNDRangeKernel( + cl.queue, + contour_clear_kernel, + 1, + NULL, + &pixels_count, + NULL, + 0, + NULL, + NULL ); + assert(!cl.err); - clWaitForEvents(1, &lines_even_event); - } + // build marks + + cl_event path_event = NULL; + size_t sstart = start; + size_t scount = count-1; + cl.err |= clEnqueueNDRangeKernel( + cl.queue, + contour_path_kernel, + 1, + &sstart, + &scount, + NULL, + prev_event ? 1 : 0, + &prev_event, + &path_event ); + assert(!cl.err); - { - Measure t("release lines buffer"); - clReleaseMemObject(lines_buffer); - } + // fill + size_t sheight = surface->height; + cl.err |= clEnqueueNDRangeKernel( + cl.queue, + contour_fill_kernel, + 1, + NULL, + &sheight, + NULL, + 1, + &path_event, + &prev_event ); + assert(!cl.err); } diff --git a/c++/contourgl/clrender.h b/c++/contourgl/clrender.h index 703195b..649c89b 100644 --- a/c++/contourgl/clrender.h +++ b/c++/contourgl/clrender.h @@ -30,31 +30,25 @@ class ClRender { private: ClContext &cl; cl_program contour_program; - cl_kernel contour_clear2f_kernel; - cl_kernel contour_lines_kernel; + cl_kernel contour_clear_kernel; + cl_kernel contour_path_kernel; cl_kernel contour_fill_kernel; Surface *surface; - cl_mem rows_buffer; + cl_mem path_buffer; cl_mem mark_buffer; cl_mem surface_image; cl_event prev_event; - size_t rows_count; - size_t even_rows_count; - size_t odd_rows_count; - - typedef std::pair Row; - std::vector rows; - std::vector marks; - public: ClRender(ClContext &cl); ~ClRender(); void send_surface(Surface *surface); Surface* receive_surface(); - void contour(const Contour &contour, const Rect &rect, const Color &color, bool invert, bool evenodd); + void send_path(const vec2f *path, int count); + void path(int start, int count, const Color &color, bool invert, bool evenodd); + void wait(); }; diff --git a/c++/contourgl/glcontext.cpp b/c++/contourgl/glcontext.cpp index ea3623a..218f5a1 100644 --- a/c++/contourgl/glcontext.cpp +++ b/c++/contourgl/glcontext.cpp @@ -48,8 +48,8 @@ GlContext::GlContext(): int framebuffer_width = 512; int framebuffer_height = 512; int framebuffer_samples = 16; - bool antialising = true; - bool hdr = false; + bool antialising = false; + bool hdr = true; // display diff --git a/c++/contourgl/test.cpp b/c++/contourgl/test.cpp index 5995b82..cbe4a57 100644 --- a/c++/contourgl/test.cpp +++ b/c++/contourgl/test.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "test.h" #include "contourbuilder.h" @@ -340,6 +341,8 @@ void Test::test4() { bounds_sw.p0 = Vector(); bounds_sw.p1 = frame_size; + Rect bounds_cl = bounds_sw; + Rect bounds_file; bounds_file.p0 = Vector(0.0, 450.0); bounds_file.p1 = Vector(500.0, -50.0); @@ -422,7 +425,7 @@ void Test::test4() { } { - Measure t("test_4_gl_stencil_send_data"); + //Measure t("test_4_gl_stencil_send_data"); glBufferSubData( GL_ARRAY_BUFFER, 0, vertices.size()*sizeof(vertices.front()), @@ -435,7 +438,7 @@ void Test::test4() { } { - Measure t("test_4_gl_stencil.tga"); + Measure t("test_4_gl_stencil_render.tga"); for(int i = 0; i < (int)contours_gl.size(); ++i) { draw_contour( starts[i], @@ -448,16 +451,16 @@ void Test::test4() { } // gl_triangles - /* + { - Measure t("test_4_gl_triangles.tga", true); + Measure t("test_4_gl_triangles", false); GLuint index_buffer_id = 0; vector triangle_starts(contours_gl.size()); vector triangle_counts(contours_gl.size()); vector triangles; - vertices.clear(); + vector vertices; vertices.reserve(commands_count); { @@ -484,7 +487,7 @@ void Test::test4() { } } - //cout << triangles.size() << " triangles" << endl; + cout << triangles.size() << " triangles" << endl; { //Measure t("test_4_gl_triangles_prepare_vertices"); @@ -508,12 +511,13 @@ void Test::test4() { } { - Measure t("test_4_gl_triangles_render"); + Measure t("test_4_gl_triangles.tga"); for(int i = 0; i < (int)contours_gl.size(); ++i) { e.shaders.color(contours_gl[i].color); glDrawElements(GL_TRIANGLES, triangle_counts[i], GL_UNSIGNED_INT, (char*)NULL + triangle_starts[i]*sizeof(int)); } } + } */ } @@ -522,22 +526,26 @@ void Test::test4() { // software Surface surface(width, height); - Measure t("test_4_sw.tga", surface, true); + Measure t("test_4_sw.tga", surface, false); vector contours_sw = contours; for(vector::iterator i = contours_sw.begin(); i != contours_sw.end(); ++i) i->contour.transform(bounds_file, bounds_sw); + int count = 0; vector polyspans(contours_sw.size()); { Measure t("test_4_sw_build_polyspans"); for(int i = 0; i < (int)contours_sw.size(); ++i) { polyspans[i].init(0, 0, width, height); contours_sw[i].contour.to_polyspan(polyspans[i]); + count += polyspans[i].get_covers().size(); polyspans[i].sort_marks(); } } + cout << setbase(10) << count << endl; + { Measure t("test_4_sw_render_polyspans"); for(int i = 0; i < (int)contours_sw.size(); ++i) @@ -549,14 +557,40 @@ void Test::test4() { // cl Surface surface(width, height); + + Measure t("test_4_cl.tga", surface, true); + vector contours_cl = contours; + vector paths; + vector starts(contours_cl.size()); + vector counts(contours_cl.size()); + for(int i = 0; i < (int)contours_cl.size(); ++i) { + contours_cl[i].contour.transform(bounds_file, bounds_cl); + starts[i] = paths.size(); + for(Contour::ChunkList::const_iterator j = contours_cl[i].contour.get_chunks().begin(); j != contours_cl[i].contour.get_chunks().end(); ++j) + paths.push_back(vec2f(j->p1)); + paths.push_back(paths[starts[i]]); + counts[i] = paths.size() - starts[i]; + } + ClRender clr(e.cl); + clr.send_surface(&surface); + clr.send_path(&paths.front(), paths.size()); + { - Measure t("test_4_cl.tga", surface, true); - clr.send_surface(&surface); - for(vector::const_iterator i = contours_cl.begin(); i != contours_cl.end(); ++i) - clr.contour(i->contour, bounds_file, i->color, i->invert, i->evenodd); - clr.receive_surface(); + Measure t("test_4_cl_render"); + for(int i = 0; i < (int)contours_cl.size(); ++i) + clr.path(starts[i], counts[i], contours_cl[i].color, contours_cl[i].invert, contours_cl[i].evenodd); + clr.wait(); } + + clr.receive_surface(); + } +} + +void ClRender::wait() { + if (prev_event) { + clWaitForEvents(1, &prev_event); + prev_event = NULL; } }