diff --git a/c++/contourgl/cl/contour-base.cl b/c++/contourgl/cl/contour-base.cl index d854ce3..b7f7357 100644 --- a/c++/contourgl/cl/contour-base.cl +++ b/c++/contourgl/cl/contour-base.cl @@ -88,6 +88,9 @@ kernel void path( } } +// TODO: +// different implementations for: +// antialiased, transparent, inverted, evenodd contours and combinations (total 16 implementations) kernel void fill( int width, int height, @@ -103,56 +106,50 @@ kernel void fill( int id = get_global_id(0); if (id >= height) return; - int w1 = width - 1; global int4 *row = mark_buffer + id*width; + global int4 *mark; global float4 *image_row = image + id*width; + global float4 *pixel; - int cover = 0; - int ialpha; - int2 c0 = { 0, id }; - int2 c1 = c0; - int4 empty_mark = { 0, 0, 0, 0 }; - while(c0.x < w1) { - int4 mark; - while(c1.x < width) { - mark = row[c1.x]; - empty_mark.z = c1.x | (c1.x + 1); - row[c1.x] = empty_mark; - if (mark.x || mark.y) break; - c1.x = min(mark.z, width); + int icover = 0; + //int ialpha; + int c0 = 0; + int c1 = 0; + int i = 0; + float alpha; + int4 m; + while(c0 < width) { + while(c1 < width) { + mark = &row[c1]; + m = *mark; + *mark = (int4)(0, 0, c1 | (c1 + 1), 0); + if (m.x || m.y) break; + c1 = m.z; } + c1 = min(c1, width); - ialpha = abs(cover); - ialpha = evenodd ? scale - abs((ialpha % scale2) - scale) - : min(ialpha, scale); - if (invert) ialpha = scale - ialpha; - if (ialpha > scale05) { - while(c0.x < c1.x) { - image_row[c0.x] = color; - ++c0.x; - } - } + //ialpha = abs(icover); + //ialpha = evenodd ? scale - abs((ialpha % scale2) - scale) + // : min(ialpha, scale); + //if (invert) ialpha = scale - ialpha; + if (abs(icover) > scale05) + while(c0 < c1) + image_row[c0++] = color; - if (c1.x >= width) return; + if (c1 >= width) return; - ialpha = abs(mark.x + cover); - ialpha = evenodd ? scale - abs((ialpha % scale2) - scale) - : min(ialpha, scale); - if (invert) ialpha = scale - ialpha; - if (ialpha > 4) { - float alpha = (float)ialpha/(float)scale; - float alpha_inv = 1.f - alpha; - global float4 *pixel = &image_row[c1.x]; - float4 cl = *pixel; - cl.x = cl.x*alpha_inv + color.x*alpha; - cl.y = cl.y*alpha_inv + color.y*alpha; - cl.z = cl.z*alpha_inv + color.z*alpha; - cl.w = min(cl.w + alpha, 1.f); - *pixel = cl; - } + //ialpha = abs(mark.x + icover); + //ialpha = evenodd ? scale - abs((ialpha % scale2) - scale) + // : min(ialpha, scale); + //if (invert) ialpha = scale - ialpha; + + alpha = (float)abs(m.x + icover)/(float)scale; + pixel = &image_row[c1]; + *pixel = (float4)( pixel->xyz*(1.f - alpha) + color.xyz*alpha, + min(pixel->w + alpha, 1.f) ); - c0.x = c1.x + 1; - c1.x = min(mark.z, width); - cover += mark.y; + c0 = c1 + 1; + c1 = m.z; + icover += m.y; } } diff --git a/c++/contourgl/clrender.cpp b/c++/contourgl/clrender.cpp index bb079af..e72bc79 100644 --- a/c++/contourgl/clrender.cpp +++ b/c++/contourgl/clrender.cpp @@ -455,6 +455,7 @@ ClRender3::~ClRender3() { clReleaseKernel(contour_path_kernel); clReleaseKernel(contour_fill_kernel); + clReleaseKernel(contour_clear_kernel); clReleaseProgram(contour_program); } @@ -579,7 +580,7 @@ void ClRender3::draw(const Path &path) { if (miny >= maxy || path.begin >= path.end) return; cl.err |= clSetKernelArg(contour_path_kernel, 4, sizeof(path.begin), &path.begin); - cl.err |= clSetKernelArg(contour_path_kernel, 5, sizeof(path.begin), &path.end); + cl.err |= clSetKernelArg(contour_path_kernel, 5, sizeof(path.end), &path.end); assert(!cl.err); cl.err |= clSetKernelArg(contour_fill_kernel, 1, sizeof(maxy), &maxy); // restrict height diff --git a/c++/contourgl/contourgl.cpp b/c++/contourgl/contourgl.cpp index e2063dd..dc2e668 100644 --- a/c++/contourgl/contourgl.cpp +++ b/c++/contourgl/contourgl.cpp @@ -49,6 +49,8 @@ int main() { gldata = data; Test::transform(gldata, bounds_frame, bounds_gl); + + /* { Environment e(width, height, false, false, 8); Measure t("test_lines_gl_stencil.tga", true); Test::test_gl_stencil(e, gldata); } @@ -70,8 +72,11 @@ int main() { Measure t("test_lines_cl3.tga", surface, true); Test::test_cl3(e, data, surface); } } + */ + { Measure t("test_lines_downgrade", true); Test::downgrade(data, datalow); } + /* gldata = datalow; Test::transform(gldata, bounds_frame, bounds_gl); { Environment e(width, height, false, false, 8); @@ -80,8 +85,10 @@ int main() { { Environment e(width, height, false, true, 8); Measure t("test_lineslow_gl_stencil_aa.tga", true); Test::test_gl_stencil(e, gldata); } + */ { Environment e(width, height, false, false, 8); + /* { Surface surface(width, height); Measure t("test_lineslow_sw.tga", surface, true); Test::test_sw(e, datalow, surface); } @@ -91,6 +98,7 @@ int main() { { Surface surface(width, height); Measure t("test_lineslow_cl2.tga", surface, true); Test::test_cl2(e, datalow, surface); } + */ { Surface surface(width, height); Measure t("test_lineslow_cl3.tga", surface, true); Test::test_cl3(e, datalow, surface); } diff --git a/c++/contourgl/measure.cpp b/c++/contourgl/measure.cpp index 4d0413d..82944a7 100644 --- a/c++/contourgl/measure.cpp +++ b/c++/contourgl/measure.cpp @@ -50,10 +50,29 @@ void Measure::init() { Measure::~Measure() { if (!surface && tga) glFinish(); - timespec spec; - clock_gettime(CLOCK_MONOTONIC , &spec); - long long dt = subs ? subs : spec.tv_sec*1000000000 + spec.tv_nsec - t; - Real ms = 1000.0*(Real)dt*(Real)(1e-9); + long long dt; + if (has_subs) { + dt = subs; + if (!repeats.empty()) { + // remove 25% of minimal values and 25% of maximum values + for(int i = (int)repeats.size()/10; i; --i) { + vector::iterator j, jj; + for(jj = j = repeats.begin(); j != repeats.end(); ++j) if (*j < *jj) jj = j; + repeats.erase(jj); + for(jj = j = repeats.begin(); j != repeats.end(); ++j) if (*j > *jj) jj = j; + repeats.erase(jj); + } + // get average + long long sum = 0; + for(vector::iterator j = repeats.begin(); j != repeats.end(); ++j) sum += *j; + dt += sum/repeats.size(); + } + } else { + timespec spec; + clock_gettime(CLOCK_MONOTONIC , &spec); + dt = spec.tv_sec*1000000000 + spec.tv_nsec - t; + } + Real ms = 1000.0*1e-9*(Real)dt; if (!hide) cout << string((stack.size()-1)*2, ' ') << "end " @@ -78,6 +97,10 @@ Measure::~Measure() { } stack.pop_back(); - if (!stack.empty()) stack.back()->subs += dt; + if (!stack.empty()) { + stack.back()->has_subs = true; + if (repeat) stack.back()->repeats.push_back(dt); + else stack.back()->subs += dt; + } } diff --git a/c++/contourgl/measure.h b/c++/contourgl/measure.h index ebd8ded..ecc4861 100644 --- a/c++/contourgl/measure.h +++ b/c++/contourgl/measure.h @@ -27,24 +27,29 @@ class Measure { private: static std::vector stack; + std::string filename; - Surface *surface; + Surface* surface; bool tga; bool hide; bool hide_subs; + bool repeat; + + bool has_subs; long long subs; long long t; + std::vector repeats; - Measure(const Measure&): surface(), tga(), hide(), hide_subs(), subs(), t() { } + Measure(const Measure&): surface(), tga(), hide(), hide_subs(), repeat(), has_subs(), subs(), t() { } Measure& operator= (const Measure&) { return *this; } void init(); public: - Measure(const std::string &filename, bool hide_subs = false): - filename(filename), surface(), tga(), hide(), hide_subs(hide_subs), subs(), t() + Measure(const std::string &filename, bool hide_subs = false, bool repeat = false): + filename(filename), surface(), tga(), hide(), hide_subs(hide_subs), repeat(repeat), has_subs(), subs(), t() { init(); } - Measure(const std::string &filename, Surface &surface, bool hide_subs = false): - filename(filename), surface(&surface), tga(), hide(), hide_subs(hide_subs), subs(), t() + Measure(const std::string &filename, Surface &surface, bool hide_subs = false, bool repeat = false): + filename(filename), surface(&surface), tga(), hide(), hide_subs(hide_subs), repeat(repeat), has_subs(), subs(), t() { init(); } ~Measure(); diff --git a/c++/contourgl/test.cpp b/c++/contourgl/test.cpp index 634b79e..506ba21 100644 --- a/c++/contourgl/test.cpp +++ b/c++/contourgl/test.cpp @@ -386,28 +386,29 @@ void Test::test_cl3(Environment &e, Data &data, Surface &surface) { ClRender3 clr(e.cl); // warm-up - { - clr.send_surface(&surface); clr.send_points(&points.front(), (int)points.size()); - for(int ii = 0; ii < 100; ++ii) - for(vector::const_iterator i = paths.begin(); i != paths.end(); ++i) - clr.draw(*i); - clr.wait(); clr.send_points(NULL, 0); clr.send_surface(NULL); - } + clr.send_surface(&surface); + clr.send_points(&points.front(), (int)points.size()); + for(int ii = 0; ii < 1000; ++ii) + for(vector::const_iterator i = paths.begin(); i != paths.end(); ++i) + clr.draw(*i); + clr.wait(); // measure - /*{ - clr.send_surface(&surface); clr.send_points(&points.front(), (int)points.size()); - for(int ii = 0; ii < 100; ++ii) + { + for(int ii = 0; ii < 1000; ++ii) { + Measure t("render", false, true); for(vector::const_iterator i = paths.begin(); i != paths.end(); ++i) clr.draw(*i); - clr.wait(); clr.send_points(NULL, 0); clr.send_surface(NULL); - }*/ + clr.wait(); + } + } + clr.send_points(NULL, 0); + clr.send_surface(NULL); // actual task clr.send_surface(&surface); clr.send_points(&points.front(), (int)points.size()); { - Measure t("render"); for(vector::const_iterator i = paths.begin(); i != paths.end(); ++i) clr.draw(*i); clr.wait();