From 49e693d9b3c7322b53a7e98a07ca4c14209b6729 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Aug 27 2015 20:40:56 +0000 Subject: Refactor --- diff --git a/c++/contourgl/Makefile b/c++/contourgl/Makefile index 9a6d776..dfe2f43 100644 --- a/c++/contourgl/Makefile +++ b/c++/contourgl/Makefile @@ -1,9 +1,55 @@ DEPLIBS = gl x11 OpenCL CXXFLAGS = -O0 -g -Wall -fmessage-length=0 `pkg-config --cflags $(DEPLIBS)` -DGL_GLEXT_PROTOTYPES -DEPS = clcontext.h contour.h contourgl.h contourbuilder.h geometry.h polyspan.h rendersw.h shaders.h test.h triangulator.h \ - clcontext.cpp contour.cpp contourgl.cpp contourbuilder.cpp polyspan.cpp rendersw.cpp shaders.cpp test.cpp triangulator.cpp -OBJS = clcontext.o contour.o contourgl.o contourbuilder.o polyspan.o rendersw.o shaders.o test.o triangulator.o + +HEADERS = \ + clcontext.h \ + contour.h \ + contourbuilder.h \ + environment.h \ + geometry.h \ + glcontext.h \ + measure.h \ + polyspan.h \ + rendersw.h \ + shaders.h \ + test.h \ + triangulator.h \ + utils.h + +SOURCES = \ + contourgl.cpp \ + clcontext.cpp \ + contour.cpp \ + contourbuilder.cpp \ + environment.cpp \ + geometry.cpp \ + glcontext.cpp \ + measure.cpp \ + polyspan.cpp \ + rendersw.cpp \ + shaders.cpp \ + test.cpp \ + triangulator.cpp \ + utils.cpp + +OBJS = \ + contourgl.o \ + clcontext.o \ + contour.o \ + contourbuilder.o \ + environment.o \ + geometry.o \ + glcontext.o \ + measure.o \ + polyspan.o \ + rendersw.o \ + shaders.o \ + test.o \ + triangulator.o \ + utils.o + +DEPS = $(HEADERS) $(SOURCES) LIBS = `pkg-config --libs $(DEPLIBS)` TARGET = contourgl diff --git a/c++/contourgl/clcontext.h b/c++/contourgl/clcontext.h index 57fe157..2114f9a 100644 --- a/c++/contourgl/clcontext.h +++ b/c++/contourgl/clcontext.h @@ -15,6 +15,9 @@ along with this program. If not, see . */ +#ifndef _CLCONTEXT_H_ +#define _CLCONTEXT_H_ + #include #include @@ -31,3 +34,5 @@ public: void hello(); }; + +#endif diff --git a/c++/contourgl/contourgl.cpp b/c++/contourgl/contourgl.cpp index 3e8655f..b1a2546 100644 --- a/c++/contourgl/contourgl.cpp +++ b/c++/contourgl/contourgl.cpp @@ -15,168 +15,22 @@ along with this program. If not, see . */ -#include -#include - #include -#include - -#include -#include -#include -#include "clcontext.h" #include "test.h" -#include "shaders.h" - - -#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 -typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display*, GLXFBConfig, GLXContext, Bool, const int*); using namespace std; -clock_t get_clock() { - return clock(); -} - int main() { - // open display (we will use default display and screen 0) - Display *display = XOpenDisplay(NULL); - assert(display); - - // choose config - int config_attribs[] = { - GLX_DOUBLEBUFFER, False, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_STENCIL_SIZE, 8, - GLX_ACCUM_RED_SIZE, 8, - GLX_ACCUM_GREEN_SIZE, 8, - GLX_ACCUM_BLUE_SIZE, 8, - GLX_ACCUM_ALPHA_SIZE, 8, - GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, - None }; - int nelements = 0; - GLXFBConfig *configs = glXChooseFBConfig(display, 0, config_attribs, &nelements); - assert(configs != NULL && nelements > 0); - GLXFBConfig config = configs[0]; - assert(config); - - // create pbuffer - int pbuffer_width = 256; - int pbuffer_height = 256; - int pbuffer_attribs[] = { - GLX_PBUFFER_WIDTH, pbuffer_width, - GLX_PBUFFER_HEIGHT, pbuffer_height, - None }; - GLXPbuffer pbuffer = glXCreatePbuffer(display, config, pbuffer_attribs); - assert(pbuffer); - - // create context - int context_attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 3, - None }; - GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); - GLXContext context = glXCreateContextAttribsARB(display, config, NULL, True, context_attribs); - assert(context); - - // make context current - glXMakeContextCurrent(display, pbuffer, pbuffer, context); - - // frame buffer - int framebuffer_width = 512; - int framebuffer_height = 512; - int framebuffer_samples = 16; - bool antialising = false; - bool hdr = false; - - GLenum internal_format = hdr ? GL_RGBA16F : GL_RGBA; - GLenum color_type = hdr ? GL_FLOAT : GL_UNSIGNED_BYTE; - - GLuint multisample_texture_id = 0; - glGenTextures(1, &multisample_texture_id); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, multisample_texture_id); - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, framebuffer_samples, internal_format, framebuffer_width, framebuffer_height, GL_TRUE); - - GLuint multisample_renderbuffer_id = 0; - glGenRenderbuffers(1, &multisample_renderbuffer_id); - glBindRenderbuffer(GL_RENDERBUFFER, multisample_renderbuffer_id); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, framebuffer_samples, GL_STENCIL_INDEX8, framebuffer_width, framebuffer_height); - - GLuint multisample_framebuffer_id = 0; - glGenFramebuffers(1, &multisample_framebuffer_id); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, multisample_framebuffer_id); - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, multisample_renderbuffer_id); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, multisample_texture_id, 0); - - GLuint texture_id = 0; - glGenTextures(1, &texture_id); - glBindTexture(GL_TEXTURE_2D, texture_id); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, framebuffer_width, framebuffer_height, 0, GL_RGBA, color_type, NULL); - - GLuint renderbuffer_id = 0; - glGenRenderbuffers(1, &renderbuffer_id); - glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_id); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, framebuffer_width, framebuffer_height); - - GLuint framebuffer_id = 0; - glGenFramebuffers(1, &framebuffer_id); - glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_id); - glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer_id); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0); - - cout << "Framebuffer status:" << setbase(16) - << " 0x" << glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) - << " 0x" << glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) - << setbase(10) << endl; - - // set view port - glViewport(0, 0, framebuffer_width, framebuffer_height); - - if (antialising) - glEnable(GL_MULTISAMPLE); - else - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_id); - - Shaders::initialize(); - - // do something - //Test::test1(); - //Test::test2(); - //Test::test3(); - //Test::test4(); - - ClContext().hello(); - - Shaders::deinitialize(); - - // deinitialization - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &framebuffer_id); - - glBindTexture(GL_TEXTURE_2D, 0); - glDeleteTextures(1, &texture_id); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &multisample_framebuffer_id); - - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glDeleteRenderbuffers(1, &multisample_renderbuffer_id); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); - glDeleteTextures(1, &multisample_texture_id); + Environment e; + Test test(e); - glXMakeContextCurrent(display, None, None, NULL); - glXDestroyContext(display, context); - glXDestroyPbuffer(display, pbuffer); - XCloseDisplay(display); + e.cl.hello(); + test.test2(); + test.test3(); + test.test4(); cout << "done" << endl; return 0; diff --git a/c++/contourgl/environment.cpp b/c++/contourgl/environment.cpp new file mode 100644 index 0000000..068019c --- /dev/null +++ b/c++/contourgl/environment.cpp @@ -0,0 +1,18 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "environment.h" diff --git a/c++/contourgl/environment.h b/c++/contourgl/environment.h new file mode 100644 index 0000000..49c0cb5 --- /dev/null +++ b/c++/contourgl/environment.h @@ -0,0 +1,32 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _ENVIRONMENT_H_ +#define _ENVIRONMENT_H_ + +#include "glcontext.h" +#include "clcontext.h" +#include "shaders.h" + +class Environment { +public: + GlContext gl; + ClContext cl; + Shaders shaders; +}; + +#endif diff --git a/c++/contourgl/geometry.cpp b/c++/contourgl/geometry.cpp new file mode 100644 index 0000000..8d9a1e8 --- /dev/null +++ b/c++/contourgl/geometry.cpp @@ -0,0 +1,18 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "geometry.h" diff --git a/c++/contourgl/glcontext.cpp b/c++/contourgl/glcontext.cpp new file mode 100644 index 0000000..06cfcca --- /dev/null +++ b/c++/contourgl/glcontext.cpp @@ -0,0 +1,175 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#include +#include + +#include "glcontext.h" + + +using namespace std; + + +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display*, GLXFBConfig, GLXContext, Bool, const int*); + + +GlContext::GlContext(): + display(), + pbuffer(), + context(), + texture_id(), + framebuffer_id(), + renderbuffer_id(), + multisample_texture_id(), + multisample_renderbuffer_id(), + multisample_framebuffer_id() +{ + + // options + + int framebuffer_width = 512; + int framebuffer_height = 512; + int framebuffer_samples = 16; + bool antialising = false; + bool hdr = false; + + // display + + display = XOpenDisplay(NULL); + assert(display); + + // config + + int config_attribs[] = { + GLX_DOUBLEBUFFER, False, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + GLX_ACCUM_RED_SIZE, 8, + GLX_ACCUM_GREEN_SIZE, 8, + GLX_ACCUM_BLUE_SIZE, 8, + GLX_ACCUM_ALPHA_SIZE, 8, + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, + None }; + int nelements = 0; + GLXFBConfig *configs = glXChooseFBConfig(display, 0, config_attribs, &nelements); + assert(configs != NULL && nelements > 0); + GLXFBConfig config = configs[0]; + assert(config); + + // pbuffer + + int pbuffer_width = 256; + int pbuffer_height = 256; + int pbuffer_attribs[] = { + GLX_PBUFFER_WIDTH, pbuffer_width, + GLX_PBUFFER_HEIGHT, pbuffer_height, + None }; + pbuffer = glXCreatePbuffer(display, config, pbuffer_attribs); + assert(pbuffer); + + // context + + int context_attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + None }; + GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + context = glXCreateContextAttribsARB(display, config, NULL, True, context_attribs); + assert(context); + + glXMakeContextCurrent(display, pbuffer, pbuffer, context); + + // frame buffer + + GLenum internal_format = hdr ? GL_RGBA16F : GL_RGBA; + GLenum color_type = hdr ? GL_FLOAT : GL_UNSIGNED_BYTE; + + glGenTextures(1, &texture_id); + glBindTexture(GL_TEXTURE_2D, texture_id); + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, framebuffer_width, framebuffer_height, 0, GL_RGBA, color_type, NULL); + + glGenRenderbuffers(1, &renderbuffer_id); + glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_id); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, framebuffer_width, framebuffer_height); + + glGenFramebuffers(1, &framebuffer_id); + glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_id); + glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer_id); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0); + + glGenTextures(1, &multisample_texture_id); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, multisample_texture_id); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, framebuffer_samples, internal_format, framebuffer_width, framebuffer_height, GL_TRUE); + + glGenRenderbuffers(1, &multisample_renderbuffer_id); + glBindRenderbuffer(GL_RENDERBUFFER, multisample_renderbuffer_id); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, framebuffer_samples, GL_STENCIL_INDEX8, framebuffer_width, framebuffer_height); + + glGenFramebuffers(1, &multisample_framebuffer_id); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, multisample_framebuffer_id); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, multisample_renderbuffer_id); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, multisample_texture_id, 0); + + cout << "Framebuffer status:" << setbase(16) + << " 0x" << glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) + << " 0x" << glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) + << setbase(10) << endl; + + if (antialising) + glEnable(GL_MULTISAMPLE); + else + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_id); + + // view port + + glViewport(0, 0, framebuffer_width, framebuffer_height); +} + +GlContext::~GlContext() { + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &framebuffer_id); + + glBindTexture(GL_TEXTURE_2D, 0); + glDeleteTextures(1, &texture_id); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &multisample_framebuffer_id); + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glDeleteRenderbuffers(1, &multisample_renderbuffer_id); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + glDeleteTextures(1, &multisample_texture_id); + + glXMakeContextCurrent(display, None, None, NULL); + glXDestroyContext(display, context); + glXDestroyPbuffer(display, pbuffer); + XCloseDisplay(display); +} + +void GlContext::check(const std::string &s) { + if (GLenum error = glGetError()) + cout << s << " GL error: 0x" << setbase(16) << error << setbase(10) << endl; +} diff --git a/c++/contourgl/glcontext.h b/c++/contourgl/glcontext.h new file mode 100644 index 0000000..6fc8597 --- /dev/null +++ b/c++/contourgl/glcontext.h @@ -0,0 +1,48 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _GLCONTEXT_H_ +#define _GLCONTEXT_H_ + +#include + +#include +#include +#include + + +class GlContext { +public: + Display *display; + GLXPbuffer pbuffer; + GLXContext context; + + GLuint texture_id; + GLuint framebuffer_id; + GLuint renderbuffer_id; + + GLuint multisample_texture_id; + GLuint multisample_renderbuffer_id; + GLuint multisample_framebuffer_id; + + GlContext(); + ~GlContext(); + + void check(const std::string &s = std::string()); +}; + +#endif diff --git a/c++/contourgl/measure.cpp b/c++/contourgl/measure.cpp new file mode 100644 index 0000000..b57a5c8 --- /dev/null +++ b/c++/contourgl/measure.cpp @@ -0,0 +1,79 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include + +#include "measure.h" +#include "utils.h" +#include "glcontext.h" + + +using namespace std; + + +std::vector Measure::stack; + + +Measure::Measure(const std::string &filename): + filename(filename), + surface(), + tga(filename.size() > 4 && filename.substr(filename.size()-4, 4) == ".tga"), + sub_tasks(), + t() +{ + stack.push_back(this); + t = clock(); +} + +Measure::Measure(const std::string &filename, Surface &surface): + filename(filename), + surface(&surface), + tga(filename.size() > 4 && filename.substr(filename.size()-4, 4) == ".tga"), + sub_tasks(), + t() +{ + stack.push_back(this); + t = clock(); +} + +Measure::~Measure() { + if (!surface && tga) glFinish(); + + clock_t dt = sub_tasks ? sub_tasks : clock() - t; + Real ms = 1000.0*(Real)(clock() - t)/(Real)(CLOCKS_PER_SEC); + cout << setw(8) << fixed << setprecision(3) + << ms << " ms - " << filename << flush << endl; + + if (tga) { + if (surface) + Utils::save_surface(*surface, filename); + else + Utils::save_viewport(filename); + } + + if (surface) { + surface->clear(); + } else { + glClear(GL_COLOR_BUFFER_BIT); + glFinish(); + } + + stack.pop_back(); + if (!stack.empty()) stack.back()->sub_tasks += dt; +} + diff --git a/c++/contourgl/measure.h b/c++/contourgl/measure.h new file mode 100644 index 0000000..c8ff69a --- /dev/null +++ b/c++/contourgl/measure.h @@ -0,0 +1,46 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _MEASURE_H_ +#define _MEASURE_H_ + +#include + +#include +#include + +#include "rendersw.h" + + +class Measure { +private: + static std::vector stack; + std::string filename; + Surface *surface; + bool tga; + clock_t sub_tasks; + clock_t t; + + Measure(const Measure&): surface(), tga(), sub_tasks(), t() { } + Measure& operator= (const Measure&) { return *this; } +public: + Measure(const std::string &filename); + Measure(const std::string &filename, Surface &surface); + ~Measure(); +}; + +#endif diff --git a/c++/contourgl/shaders.cpp b/c++/contourgl/shaders.cpp index 87d34cc..ad33974 100644 --- a/c++/contourgl/shaders.cpp +++ b/c++/contourgl/shaders.cpp @@ -25,18 +25,6 @@ using namespace std; -Shaders* Shaders::instance = NULL; - -void Shaders::initialize() { - assert(!instance); - instance = new Shaders(); -} - -void Shaders::deinitialize() { - assert(instance); - delete instance; -} - Shaders::Shaders(): simple_vertex_id(), simpleProgramId(), @@ -149,14 +137,12 @@ void Shaders::check_program(GLuint id, const char *name) { } void Shaders::simple() { - assert(instance); - glUseProgram(instance->simpleProgramId); + glUseProgram(simpleProgramId); } void Shaders::color(const Color &c) { - assert(instance); - glUseProgram(instance->colorProgramId); - glUniform4fv(instance->colorUniform, 1, c.channels); + glUseProgram(colorProgramId); + glUniform4fv(colorUniform, 1, c.channels); } diff --git a/c++/contourgl/shaders.h b/c++/contourgl/shaders.h index 33d9fa5..649ce12 100644 --- a/c++/contourgl/shaders.h +++ b/c++/contourgl/shaders.h @@ -15,6 +15,9 @@ along with this program. If not, see . */ +#ifndef _SHADERS_H_ +#define _SHADERS_H_ + #include #include #include @@ -22,7 +25,7 @@ #include "rendersw.h" class Shaders { -private: +public: GLuint simple_vertex_id; GLuint simpleProgramId; @@ -30,18 +33,14 @@ private: GLuint colorProgramId; GLint colorUniform; - Shaders(); - ~Shaders(); - - static Shaders *instance; - void check_shader(GLuint id, const char *src); void check_program(GLuint id, const char *name); -public: - static void initialize(); - static void deinitialize(); + Shaders(); + ~Shaders(); - static void simple(); - static void color(const Color &c); + void simple(); + void color(const Color &c); }; + +#endif diff --git a/c++/contourgl/test.cpp b/c++/contourgl/test.cpp index 3ac52f9..d973de4 100644 --- a/c++/contourgl/test.cpp +++ b/c++/contourgl/test.cpp @@ -15,267 +15,53 @@ along with this program. If not, see . */ -#include - #include #include -#include - -#include -#include -#include #include "test.h" - -#include "contour.h" -#include "rendersw.h" #include "contourbuilder.h" -#include "shaders.h" #include "triangulator.h" +#include "measure.h" +#include "utils.h" using namespace std; -class Test::Helper { -public: - static void save_rgba( - const void *buffer, - int width, - int height, - bool flip, - const string &filename ) - { - // create file - ofstream f(("results/" + filename).c_str(), ofstream::out | ofstream::trunc | ofstream::binary); - - // write header - unsigned char targa_header[] = { - 0, // Length of the image ID field (0 - no ID field) - 0, // Whether a color map is included (0 - no colormap) - 2, // Compression and color types (2 - uncompressed true-color image) - 0, 0, 0, 0, 0, // Color map specification (not need for us) - 0, 0, // X-origin - 0, 0, // Y-origin - (unsigned char)(width & 0xff), // Image width - (unsigned char)(width >> 8), - (unsigned char)(height & 0xff), // Image height - (unsigned char)(height >> 8), - 32, // Bits per pixel - 0 // Image descriptor (keep zero for capability) - }; - f.write((char*)targa_header, sizeof(targa_header)); - - // write data - if (flip) { - int line_size = 4*width; - const char *end = (char*)buffer; - const char *current = end + height*line_size; - while(current > end) { - current -= line_size; - f.write(current, line_size); - } - } else { - f.write((const char*)buffer, 4*width*height); - } - } - - static void save_viewport(const string &filename) { - glFinish(); - - GLint vp[4] = {}; - glGetIntegerv(GL_VIEWPORT, vp); - - GLint draw_buffer = 0, read_buffer = 0; - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_buffer); - glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_buffer); - if (draw_buffer != read_buffer) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint)read_buffer); - glBindFramebuffer(GL_READ_FRAMEBUFFER, (GLuint)draw_buffer); - glBlitFramebuffer(vp[0], vp[1], vp[2], vp[3], vp[0], vp[1], vp[2], vp[3], GL_COLOR_BUFFER_BIT, GL_NEAREST); - glFinish(); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint)draw_buffer); - glBindFramebuffer(GL_READ_FRAMEBUFFER, (GLuint)read_buffer); - } - - char *buffer = new char[vp[2]*vp[3]*4]; - glReadPixels(vp[0], vp[1], vp[2], vp[3], GL_BGRA, GL_UNSIGNED_BYTE, buffer); - - - save_rgba(buffer, vp[2], vp[3], false, filename); - delete buffer; - } +void Test::draw_contour(int start, int count, bool even_odd, bool invert, const Color &color) { + glEnable(GL_STENCIL_TEST); - static void save_surface(const Surface &surface, const string &filename) { - unsigned char *buffer = new unsigned char[4*surface.count()]; - unsigned char *j = buffer; - for(Color *i = surface.data, *end = i + surface.count(); i != end; ++i, j += 4) { - j[0] = (unsigned char)roundf(max(0.f, min(1.f, i->b))*255.f); - j[1] = (unsigned char)roundf(max(0.f, min(1.f, i->g))*255.f); - j[2] = (unsigned char)roundf(max(0.f, min(1.f, i->r))*255.f); - j[3] = (unsigned char)roundf(max(0.f, min(1.f, i->a))*255.f); - } - save_rgba(buffer, surface.width, surface.height, false, filename); - delete buffer; - } - - static void draw_contour_strip(const vector &c) { - glBegin(GL_TRIANGLE_STRIP); - for(vector::const_iterator i = c.begin(); i != c.end(); ++i) { - glVertex2d(i->x, i->y); - glVertex2d(-1.0, i->y); - } - glEnd(); - } - - static void draw_contour_strip(const Contour &c) { - glBegin(GL_TRIANGLE_STRIP); - const Contour::ChunkList &chunks = c.get_chunks(); - Vector prev; - for(Contour::ChunkList::const_iterator i = chunks.begin(); i != chunks.end(); ++i) { - if ( i->type == Contour::LINE - || i->type == Contour::CLOSE) - { - glVertex2d(i->p1.x, i->p1.y); - glVertex2d(-1.0, i->p1.y); - prev.x = -1.0; - prev.y = i->p1.y; - } else { - glVertex2d(prev.x, prev.y); - glVertex2d(prev.x, prev.y); - glVertex2d(i->p1.x, i->p1.y); - glVertex2d(i->p1.x, i->p1.y); - prev = i->p1; - } - } - glEnd(); - } - - static void draw_contour_strip(const int &count) { - glDrawArrays(GL_TRIANGLE_STRIP, 4, count); - } - - template - static void draw_contour(const T &c, bool even_odd, bool invert) { - glEnable(GL_STENCIL_TEST); - - // render mask - GLint draw_buffer; - glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer); - glDrawBuffer(GL_NONE); - glClear(GL_STENCIL_BUFFER_BIT); - glStencilFunc(GL_ALWAYS, 0, 0); - if (even_odd) { - glStencilOp(GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP); - } else { - glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP); - glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP); - } - Shaders::simple(); - draw_contour_strip(c); - glDrawBuffer((GLenum)draw_buffer); - - // fill mask - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - if (!even_odd && !invert) - glStencilFunc(GL_NOTEQUAL, 0, -1); - if (!even_odd && invert) - glStencilFunc(GL_EQUAL, 0, -1); - if ( even_odd && !invert) - glStencilFunc(GL_EQUAL, 1, 1); - if ( even_odd && invert) - glStencilFunc(GL_EQUAL, 0, 1); - - Shaders::color(Color(0.f, 0.f, 1.f, 1.f)); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glDisable(GL_STENCIL_TEST); - } - - static void draw_contour(int start, int count, bool even_odd, bool invert, const Color &color) { - glEnable(GL_STENCIL_TEST); - - // render mask - GLint draw_buffer; - glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer); - glDrawBuffer(GL_NONE); - glClear(GL_STENCIL_BUFFER_BIT); - glStencilFunc(GL_ALWAYS, 0, 0); - if (even_odd) { - glStencilOp(GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP); - } else { - glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP); - glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP); - } - Shaders::simple(); - glDrawArrays(GL_TRIANGLE_STRIP, start, count); - glDrawBuffer((GLenum)draw_buffer); - - // fill mask - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - if (!even_odd && !invert) - glStencilFunc(GL_NOTEQUAL, 0, -1); - if (!even_odd && invert) - glStencilFunc(GL_EQUAL, 0, -1); - if ( even_odd && !invert) - glStencilFunc(GL_EQUAL, 1, 1); - if ( even_odd && invert) - glStencilFunc(GL_EQUAL, 0, 1); - - Shaders::color(color); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glDisable(GL_STENCIL_TEST); - } - - static Vector get_frame_size() { - int vp[4] = {}; - glGetIntegerv(GL_VIEWPORT, vp); - return Vector((Real)vp[2], (Real)vp[3]); - } - -}; - -Test::Wrapper::Wrapper(const std::string &filename): - filename(filename), - surface(), - tga(filename.size() > 4 && filename.substr(filename.size()-4, 4) == ".tga"), - t(get_clock()) -{ } - -Test::Wrapper::Wrapper(const std::string &filename, Surface &surface): - filename(filename), - surface(&surface), - tga(filename.size() > 4 && filename.substr(filename.size()-4, 4) == ".tga"), - t(get_clock()) -{ } - -Test::Wrapper::~Wrapper() { - if (!surface && tga) glFinish(); - Real ms = 1000.0*(Real)(get_clock() - t)/(Real)(CLOCKS_PER_SEC); - cout << setw(8) << fixed << setprecision(3) - << ms << " ms - " << filename << flush << endl; - - if (tga) { - if (surface) - Helper::save_surface(*surface, filename); - else - Helper::save_viewport(filename); - } - - if (surface) { - surface->clear(); + // render mask + GLint draw_buffer; + glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer); + glDrawBuffer(GL_NONE); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilFunc(GL_ALWAYS, 0, 0); + if (even_odd) { + glStencilOp(GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP); } else { - glClear(GL_COLOR_BUFFER_BIT); - glFinish(); - } -} - -void Test::check_gl(const std::string &s) { - GLenum error = glGetError(); - if (error) { - cout << s << " GL error: 0x" << setbase(16) << error << setbase(10) << endl; - } + glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP); + glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP); + } + e.shaders.simple(); + glDrawArrays(GL_TRIANGLE_STRIP, start, count); + glDrawBuffer((GLenum)draw_buffer); + + // fill mask + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + if (!even_odd && !invert) + glStencilFunc(GL_NOTEQUAL, 0, -1); + if (!even_odd && invert) + glStencilFunc(GL_EQUAL, 0, -1); + if ( even_odd && !invert) + glStencilFunc(GL_EQUAL, 1, 1); + if ( even_odd && invert) + glStencilFunc(GL_EQUAL, 0, 1); + + e.shaders.color(color); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisable(GL_STENCIL_TEST); } void Test::load(std::vector &contours, const std::string &filename) { @@ -354,63 +140,12 @@ void Test::load(std::vector &contours, const std::string &filename) } -void Test::test1() { - // OpenGl 2 code - - vector c; - ContourBuilder::build_simple(c); - cout << c.size() << " vertices" << endl; - - glPushAttrib(GL_ALL_ATTRIB_BITS); - - int random = (int)get_clock(); - { - Wrapper t("test_1_control_timer_200000_simple_ops"); - int j = random; - for(long long i = 0; i < 200000; ++i) - if (j > i) ++j; - glColor4f(j%2, j%2, j%2, j%2); - } - - glColor4f(0.f, 0.f, 1.f, 1.f); - - { - Wrapper t("test_1_contour.tga"); - glBegin(GL_LINE_STRIP); - for(vector::const_iterator i = c.begin(); i != c.end(); ++i) - glVertex2d(i->x, i->y); - glEnd(); - } - - { - Wrapper t("test_1_contour_fill.tga"); - Helper::draw_contour(c, false, false); - } - - { - Wrapper t("test_1_contour_fill_invert.tga"); - Helper::draw_contour(c, false, true); - } - - { - Wrapper t("test_1_contour_evenodd.tga"); - Helper::draw_contour(c, true, false); - } - - { - Wrapper t("test_1_contour_evenodd_invert.tga"); - Helper::draw_contour(c, true, true); - } - - glPopAttrib(); -} - void Test::test2() { Contour c, cc; ContourBuilder::build(cc); cout << cc.get_chunks().size() << " commands" << endl; - Vector frame_size = Helper::get_frame_size(); + Vector frame_size = Utils::get_frame_size(); Rect bounds; bounds.p0 = Vector(-1.0, -1.0); @@ -418,7 +153,7 @@ void Test::test2() { Vector min_size(1.75/frame_size.x, 1.75/frame_size.y); { - Wrapper t("test_2_split"); + Measure t("test_2_split"); cc.split(c, bounds, min_size); } @@ -431,7 +166,7 @@ void Test::test2() { vector< vec2 > vertices; { - Wrapper t("test_2_init_buffer"); + Measure t("test_2_init_buffer"); vertices.resize(4+4*chunks.size()); glGenBuffers(1, &buffer_id); glBindBuffer(GL_ARRAY_BUFFER, buffer_id); @@ -448,7 +183,7 @@ void Test::test2() { glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL); - Shaders::color(Color(0.f, 0.f, 1.f, 1.f)); + e.shaders.color(Color(0.f, 0.f, 1.f, 1.f)); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()); glFinish(); glClear(GL_COLOR_BUFFER_BIT); @@ -456,7 +191,7 @@ void Test::test2() { } { - Wrapper t("test_2_prepare_data"); + Measure t("test_2_prepare_data"); vertices.push_back(vec2(bounds.p0.x, bounds.p0.y)); vertices.push_back(vec2(bounds.p0.x, bounds.p1.y)); vertices.push_back(vec2(bounds.p1.x, bounds.p0.y)); @@ -480,7 +215,7 @@ void Test::test2() { } { - Wrapper t("test_2_send_data"); + Measure t("test_2_send_data"); glBufferSubData( GL_ARRAY_BUFFER, 0, vertices.size()*sizeof(vertices.front()), @@ -488,35 +223,35 @@ void Test::test2() { } { - Wrapper t("test_2_simple_fill.tga"); + Measure t("test_2_simple_fill.tga"); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } { - Wrapper t("test_2_array.tga"); + Measure t("test_2_array.tga"); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDrawArrays(GL_TRIANGLE_STRIP, 4, count); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } { - Wrapper t("test_2_contour_fill.tga"); - Helper::draw_contour(count, false, false); + Measure t("test_2_contour_fill.tga"); + draw_contour(4, count, false, false, Color(0.f, 0.f, 1.f, 1.f)); } { - Wrapper t("test_2_contour_fill_invert.tga"); - Helper::draw_contour(count, false, true); + Measure t("test_2_contour_fill_invert.tga"); + draw_contour(4, count, false, true, Color(0.f, 0.f, 1.f, 1.f)); } { - Wrapper t("test_2_contour_evenodd.tga"); - Helper::draw_contour(count, true, false); + Measure t("test_2_contour_evenodd.tga"); + draw_contour(4, count, true, false, Color(0.f, 0.f, 1.f, 1.f)); } { - Wrapper t("test_2_contour_evenodd_invert.tga"); - Helper::draw_contour(count, true, true); + Measure t("test_2_contour_evenodd_invert.tga"); + draw_contour(4, count, true, true, Color(0.f, 0.f, 1.f, 1.f)); } glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -528,7 +263,7 @@ void Test::test3() { ContourBuilder::build(c); cout << c.get_chunks().size() << " commands" << endl; - Vector frame_size = Helper::get_frame_size(); + Vector frame_size = Utils::get_frame_size(); int width = (int)frame_size.x; int height = (int)frame_size.y; @@ -548,7 +283,7 @@ void Test::test3() { Color color(0.f, 0.f, 1.f, 1.f); { - Wrapper t("test_3_build_polyspan"); + Measure t("test_3_build_polyspan"); c.to_polyspan(polyspan); } @@ -557,7 +292,7 @@ void Test::test3() { glPushAttrib(GL_ALL_ATTRIB_BITS); glColor4d(0.0, 0.0, 1.0, 1.0); { - Wrapper t("test_3_polyspan_gl_lines.tga"); + Measure t("test_3_polyspan_gl_lines.tga"); glBegin(GL_LINE_STRIP); for(Polyspan::cover_array::const_iterator i = polyspan.get_covers().begin(); i != polyspan.get_covers().end(); ++i) glVertex2d((double)i->x/1024.0*2.0 - 1.0, (double)i->y/1024.0*2.0 - 1.0); @@ -567,33 +302,33 @@ void Test::test3() { { - Wrapper t("test_3_polyspan_sort"); + Measure t("test_3_polyspan_sort"); polyspan.sort_marks(); } { - Wrapper t("test_3_polyspan_fill.tga", surface); + Measure t("test_3_polyspan_fill.tga", surface); RenderSW::polyspan(surface, polyspan, color, false, false); } { - Wrapper t("test_3_polyspan_fill_invert.tga", surface); + Measure t("test_3_polyspan_fill_invert.tga", surface); RenderSW::polyspan(surface, polyspan, color, false, true); } { - Wrapper t("test_3_polyspan_evenodd.tga", surface); + Measure t("test_3_polyspan_evenodd.tga", surface); RenderSW::polyspan(surface, polyspan, color, true, false); } { - Wrapper t("test_3_polyspan_evenodd_invert.tga", surface); + Measure t("test_3_polyspan_evenodd_invert.tga", surface); RenderSW::polyspan(surface, polyspan, color, true, true); } } void Test::test4() { - Vector frame_size = Helper::get_frame_size(); + Vector frame_size = Utils::get_frame_size(); int width = (int)frame_size.x; int height = (int)frame_size.y; @@ -631,7 +366,7 @@ void Test::test4() { vector counts(contours_gl.size()); { - Wrapper t("test_4_gl_init_buffer"); + Measure t("test_4_gl_init_buffer"); vertices.resize(4 + 4*commands_count + 2*contours_gl.size()); glGenBuffers(1, &buffer_id); glBindBuffer(GL_ARRAY_BUFFER, buffer_id); @@ -648,7 +383,7 @@ void Test::test4() { glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL); - Shaders::color(Color(0.f, 0.f, 1.f, 1.f)); + e.shaders.color(Color(0.f, 0.f, 1.f, 1.f)); glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()); glFinish(); glClear(GL_COLOR_BUFFER_BIT); @@ -656,7 +391,7 @@ void Test::test4() { } { - Wrapper t("test_4_gl_stencil_prepare_data"); + Measure t("test_4_gl_stencil_prepare_data"); vertices.push_back(vec2(bounds_gl.p0.x, bounds_gl.p0.y)); vertices.push_back(vec2(bounds_gl.p0.x, bounds_gl.p1.y)); vertices.push_back(vec2(bounds_gl.p1.x, bounds_gl.p0.y)); @@ -684,7 +419,7 @@ void Test::test4() { } { - Wrapper 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()), @@ -692,14 +427,14 @@ void Test::test4() { } { - Wrapper t("test_4_gl_stencil_points.tga"); + Measure t("test_4_gl_stencil_points.tga"); glDrawArrays(GL_POINTS, 0, vertices.size()); } { - Wrapper t("test_4_gl_stencil_render.tga"); + Measure t("test_4_gl_stencil_render.tga"); for(int i = 0; i < (int)contours_gl.size(); ++i) { - Helper::draw_contour( + draw_contour( starts[i], counts[i], contours_gl[i].invert, @@ -719,7 +454,7 @@ void Test::test4() { vertices.reserve(commands_count); { - Wrapper t("test_4_gl_init_index_buffer"); + Measure t("test_4_gl_init_index_buffer"); triangles.resize(3*commands_count); glGenBuffers(1, &index_buffer_id); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id); @@ -732,7 +467,7 @@ void Test::test4() { } { - Wrapper t("test_4_gl_triangulate"); + Measure t("test_4_gl_triangulate"); int index_offset = 4; for(int i = 0; i < (int)contours_gl.size(); ++i) { triangle_starts[i] = (int)triangles.size(); @@ -745,7 +480,7 @@ void Test::test4() { cout << triangles.size() << " triangles" << endl; { - Wrapper t("test_4_gl_triangles_prepare_vertices"); + Measure t("test_4_gl_triangles_prepare_vertices"); for(int i = 0; i < (int)contours_gl.size(); ++i) { const Contour::ChunkList &chunks = contours_gl[i].contour.get_chunks(); for(Contour::ChunkList::const_iterator j = chunks.begin(); j != chunks.end(); ++j) @@ -754,7 +489,7 @@ void Test::test4() { } { - Wrapper t("test_4_gl_triangles_send_data"); + Measure t("test_4_gl_triangles_send_data"); glBufferSubData( GL_ARRAY_BUFFER, 4*sizeof(vertices.front()), vertices.size()*sizeof(vertices.front()), @@ -766,9 +501,9 @@ void Test::test4() { } { - Wrapper t("test_4_gl_triangles_render.tga"); + Measure t("test_4_gl_triangles_render.tga"); for(int i = 0; i < (int)contours_gl.size(); ++i) { - Shaders::color(contours_gl[i].color); + e.shaders.color(contours_gl[i].color); glDrawElements(GL_TRIANGLES, triangle_counts[i], GL_UNSIGNED_INT, (char*)NULL + triangle_starts[i]*sizeof(int)); } } @@ -783,7 +518,7 @@ void Test::test4() { vector polyspans(contours_sw.size()); { - Wrapper t("test_4_sw_build_polyspans"); + 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]); @@ -794,7 +529,7 @@ void Test::test4() { Surface surface(width, height); { - Wrapper t("test_4_sw_render_polyspans.tga", surface); + Measure t("test_4_sw_render_polyspans.tga", surface); for(int i = 0; i < (int)contours_sw.size(); ++i) RenderSW::polyspan(surface, polyspans[i], contours_sw[i].color, contours_sw[i].evenodd, contours_sw[i].invert); } diff --git a/c++/contourgl/test.h b/c++/contourgl/test.h index 0431fb8..68fac43 100644 --- a/c++/contourgl/test.h +++ b/c++/contourgl/test.h @@ -22,29 +22,10 @@ #include #include "contour.h" -#include "rendersw.h" - -class Surface; - -clock_t get_clock(); +#include "environment.h" class Test { public: - class Wrapper { - private: - std::string filename; - Surface *surface; - bool tga; - clock_t t; - - Wrapper(const Wrapper&): surface(), tga(), t() { } - Wrapper& operator= (const Wrapper&) { return *this; } - public: - Wrapper(const std::string &filename); - Wrapper(const std::string &filename, Surface &surface); - ~Wrapper(); - }; - struct ContourInfo { bool invert; bool antialias; @@ -54,19 +35,18 @@ public: ContourInfo(): invert(), antialias(), evenodd() { } }; -private: - class Helper; - -public: - static void check_gl(const std::string &s = std::string()); + Environment &e; - static void load(std::vector &contours, const std::string &filename); + Test(Environment &e): e(e) { } + ~Test() { } - static void test1(); - static void test2(); - static void test3(); + void draw_contour(int start, int count, bool even_odd, bool invert, const Color &color); + void load(std::vector &contours, const std::string &filename); - static void test4(); + void test1(); + void test2(); + void test3(); + void test4(); }; #endif diff --git a/c++/contourgl/utils.cpp b/c++/contourgl/utils.cpp new file mode 100644 index 0000000..f93fd3e --- /dev/null +++ b/c++/contourgl/utils.cpp @@ -0,0 +1,111 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#include "utils.h" +#include "glcontext.h" + + +using namespace std; + + +Vector Utils::get_frame_size() { + int vp[4] = {}; + glGetIntegerv(GL_VIEWPORT, vp); + return Vector((Real)vp[2], (Real)vp[3]); +} + +void Utils::save_rgba( + const void *buffer, + int width, + int height, + bool flip, + const string &filename ) +{ + // create file + ofstream f(("results/" + filename).c_str(), ofstream::out | ofstream::trunc | ofstream::binary); + + // write header + unsigned char targa_header[] = { + 0, // Length of the image ID field (0 - no ID field) + 0, // Whether a color map is included (0 - no colormap) + 2, // Compression and color types (2 - uncompressed true-color image) + 0, 0, 0, 0, 0, // Color map specification (not need for us) + 0, 0, // X-origin + 0, 0, // Y-origin + (unsigned char)(width & 0xff), // Image width + (unsigned char)(width >> 8), + (unsigned char)(height & 0xff), // Image height + (unsigned char)(height >> 8), + 32, // Bits per pixel + 0 // Image descriptor (keep zero for capability) + }; + f.write((char*)targa_header, sizeof(targa_header)); + + // write data + if (flip) { + int line_size = 4*width; + const char *end = (char*)buffer; + const char *current = end + height*line_size; + while(current > end) { + current -= line_size; + f.write(current, line_size); + } + } else { + f.write((const char*)buffer, 4*width*height); + } +} + +void Utils::save_viewport(const string &filename) { + glFinish(); + + GLint vp[4] = {}; + glGetIntegerv(GL_VIEWPORT, vp); + + GLint draw_buffer = 0, read_buffer = 0; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_buffer); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_buffer); + if (draw_buffer != read_buffer) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint)read_buffer); + glBindFramebuffer(GL_READ_FRAMEBUFFER, (GLuint)draw_buffer); + glBlitFramebuffer(vp[0], vp[1], vp[2], vp[3], vp[0], vp[1], vp[2], vp[3], GL_COLOR_BUFFER_BIT, GL_NEAREST); + glFinish(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, (GLuint)draw_buffer); + glBindFramebuffer(GL_READ_FRAMEBUFFER, (GLuint)read_buffer); + } + + char *buffer = new char[vp[2]*vp[3]*4]; + glReadPixels(vp[0], vp[1], vp[2], vp[3], GL_BGRA, GL_UNSIGNED_BYTE, buffer); + + + save_rgba(buffer, vp[2], vp[3], false, filename); + delete buffer; +} + +void Utils::save_surface(const Surface &surface, const string &filename) { + unsigned char *buffer = new unsigned char[4*surface.count()]; + unsigned char *j = buffer; + for(Color *i = surface.data, *end = i + surface.count(); i != end; ++i, j += 4) { + j[0] = (unsigned char)roundf(max(0.f, min(1.f, i->b))*255.f); + j[1] = (unsigned char)roundf(max(0.f, min(1.f, i->g))*255.f); + j[2] = (unsigned char)roundf(max(0.f, min(1.f, i->r))*255.f); + j[3] = (unsigned char)roundf(max(0.f, min(1.f, i->a))*255.f); + } + save_rgba(buffer, surface.width, surface.height, false, filename); + delete buffer; +} diff --git a/c++/contourgl/utils.h b/c++/contourgl/utils.h new file mode 100644 index 0000000..9639734 --- /dev/null +++ b/c++/contourgl/utils.h @@ -0,0 +1,42 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include + +#include "geometry.h" +#include "rendersw.h" + +class Utils { +public: + static Vector get_frame_size(); + + static void save_rgba( + const void *buffer, + int width, + int height, + bool flip, + const std::string &filename ); + + static void save_viewport(const std::string &filename); + + static void save_surface(const Surface &surface, const std::string &filename); +}; + +#endif