From 4aa63db8dd1f2ac0c78aa9c542487550dbadb6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 18 Apr 2022 17:14:27 +0200 Subject: [PATCH] Start preview feature. Add dummy triangle to test OpenGL. --- gds-render-gui.c | 22 ++- main.c | 5 + preview-rendering/CMakeLists.txt | 8 + .../preview-rendering/preview-rendering-gui.h | 14 ++ preview-rendering/src/preview-rendering-gui.c | 167 ++++++++++++++++++ preview-rendering/src/preview-rendering.c | 4 + resources/preview-window.glade | 43 +++++ resources/resources.xml | 5 + resources/shaders/polygon.fs.glsl | 9 + resources/shaders/polygon.vs.glsl | 12 ++ 10 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 preview-rendering/include/preview-rendering/preview-rendering-gui.h create mode 100644 preview-rendering/src/preview-rendering-gui.c create mode 100644 resources/preview-window.glade create mode 100644 resources/shaders/polygon.fs.glsl create mode 100644 resources/shaders/polygon.vs.glsl diff --git a/gds-render-gui.c b/gds-render-gui.c index 33f756f..29e07a5 100644 --- a/gds-render-gui.c +++ b/gds-render-gui.c @@ -44,6 +44,10 @@ #include #include +#ifdef GDS_RENDER_OPGENGL_PREVIEW +#include +#endif + /** @brief Columns of selection tree view */ enum cell_store_columns { CELL_SEL_LIBRARY = 0, @@ -68,6 +72,9 @@ struct _GdsRenderGui { /* Custom fields */ GtkWindow *main_window; +#ifdef GDS_RENDER_OPGENGL_PREVIEW + OpenGlPreviewGui *preview_gui; +#endif GtkWidget *convert_button; GtkWidget *open_button; GtkWidget *load_layer_button; @@ -189,8 +196,8 @@ static gboolean cell_store_filter_visible_func(GtkTreeModel *model, GtkTreeIter gtk_tree_model_get(model, iter, CELL_SEL_CELL, &cell, CELL_SEL_LIBRARY, &lib, -1); - /* Show always, if this is a pure lib entry */ - if (lib && !cell) { + /* Show always, if this is a pure lib entry */ + if (lib && !cell) { result = TRUE; goto exit_filter; } @@ -665,6 +672,9 @@ static void gds_render_gui_dispose(GObject *gobject) g_clear_object(&self->save_layer_button); g_clear_object(&self->open_button); g_clear_object(&self->select_all_button); +#ifdef GDS_RENDER_OPGENGL_PREVIEW + g_clear_object(&self->preview_gui); +#endif if (self->main_window) { g_signal_handlers_destroy(self->main_window); @@ -768,7 +778,15 @@ static void gds_render_gui_init(GdsRenderGui *self) GtkWidget *activity_bar_box; GtkWidget *auto_color_button; GtkWidget *auto_naming_button; +#ifdef GDS_RENDER_OPGENGL_PREVIEW + OpenGlPreviewGui *preview_gui; + preview_gui = opengl_preview_gui_new(); + /* No need to reference the preview gui. It is already referenced upon creation */ + self->preview_gui = preview_gui; + + opengl_preview_gui_show(preview_gui); +#endif main_builder = gtk_builder_new_from_resource("/gui/main.glade"); self->cell_tree_view = GTK_TREE_VIEW(gtk_builder_get_object(main_builder, "cell-tree")); diff --git a/main.c b/main.c index c31a426..258f519 100644 --- a/main.c +++ b/main.c @@ -96,6 +96,11 @@ static void app_about(GSimpleAction *action, GVariant *parameter, gpointer user_ comment_text = g_string_new(_("gds-render is a free tool for rendering GDS2 layout files into vector graphics.")); g_string_append_printf(comment_text, _("\n\nFull git commit: %s"), _app_git_commit); +#ifdef GDS_RENDER_OPGENGL_PREVIEW + g_string_append_printf(comment_text, _("\nOpenGL Previev: Availabe")); +#else + g_string_append_printf(comment_text, _("\nOpenGL Previev: Unavailabe")); +#endif builder = gtk_builder_new_from_resource("/gui/about.glade"); dialog = GTK_DIALOG(gtk_builder_get_object(builder, "about-dialog")); gtk_window_set_transient_for(GTK_WINDOW(dialog), NULL); diff --git a/preview-rendering/CMakeLists.txt b/preview-rendering/CMakeLists.txt index a67e8ab..2927aee 100644 --- a/preview-rendering/CMakeLists.txt +++ b/preview-rendering/CMakeLists.txt @@ -1,7 +1,15 @@ project(opengl-preview) cmake_minimum_required(VERSION 3.0) +find_package(PkgConfig REQUIRED) +pkg_check_modules(EPOXY REQUIRED epoxy) +pkg_search_module(GLIB REQUIRED glib-2.0) +pkg_check_modules(GTK3 REQUIRED gtk+-3.0) + aux_source_directory("src" SRCS) add_library(${PROJECT_NAME} STATIC ${SRCS}) target_include_directories(${PROJECT_NAME} PUBLIC "include") +target_include_directories(${PROJECT_NAME} PRIVATE ${EPOXY_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS}) +target_link_directories(${PROJECT_NAME} PUBLIC ${EPOXY_LINK_DIRS} ${GLIB_LINK_DIRS} ${GTK3_LINK_DIRS}) +target_link_libraries(${PROJECT_NAME} ${GLIB_LDFLAGS} ${EPOXY_LDFLAGS} ${GTK3_LDFLAGS}) diff --git a/preview-rendering/include/preview-rendering/preview-rendering-gui.h b/preview-rendering/include/preview-rendering/preview-rendering-gui.h new file mode 100644 index 0000000..8aeb698 --- /dev/null +++ b/preview-rendering/include/preview-rendering/preview-rendering-gui.h @@ -0,0 +1,14 @@ +#ifndef _PREVIEW_RENDERING_GUI_H_ +#define _PREVIEW_RENDERING_GUI_H_ + +#include + +G_DECLARE_FINAL_TYPE(OpenGlPreviewGui, opengl_preview_gui, GDS_RENDER, OPENGL_PREVIEW_GUI, GObject) + +#define TYPE_GDS_RENDER_OPENGL_PREVIEW_GUI (opengl_preview_gui_get_type()) + +OpenGlPreviewGui *opengl_preview_gui_new(void); + +void opengl_preview_gui_show(OpenGlPreviewGui *self); + +#endif /* _PREVIEW_RENDERING_GUI_H_ */ diff --git a/preview-rendering/src/preview-rendering-gui.c b/preview-rendering/src/preview-rendering-gui.c new file mode 100644 index 0000000..a3a1cab --- /dev/null +++ b/preview-rendering/src/preview-rendering-gui.c @@ -0,0 +1,167 @@ +#include +#include + +struct _OpenGlPreviewGui { + GObject super; + GtkWindow *main_window; + GtkGLArea *gl_area; + unsigned int polygon_shader_prog; + unsigned int vao; + unsigned int vbo; + float color[4]; +}; + +G_DEFINE_TYPE(OpenGlPreviewGui, opengl_preview_gui, G_TYPE_OBJECT) + +static void opengl_preview_gui_dispose(GObject *gobj) +{ + OpenGlPreviewGui *self; + + self = GDS_RENDER_OPENGL_PREVIEW_GUI(gobj); + + g_clear_object(&self->gl_area); + + if (self->main_window) { + gtk_widget_destroy(GTK_WIDGET(self->main_window)); + self->main_window = NULL; + } + + G_OBJECT_CLASS(opengl_preview_gui_parent_class)->dispose(gobj); +} + +static void opengl_preview_gui_class_init(OpenGlPreviewGuiClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS(klass); + + oclass->dispose = opengl_preview_gui_dispose; +} + +static gboolean gl_area_render(GtkGLArea *area, GdkGLContext *context, gpointer user) +{ + OpenGlPreviewGui *gui; + + int loc; + + gui = GDS_RENDER_OPENGL_PREVIEW_GUI(user); + gtk_gl_area_make_current(area); + + glClearColor (0, 0, 0, 1.0); + glClear (GL_COLOR_BUFFER_BIT); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glUseProgram(gui->polygon_shader_prog); + glBindVertexArray(gui->vao); + loc = glGetUniformLocation(gui->polygon_shader_prog, "const_color"); + glUniform4fv(loc, 1, gui->color); + glDrawArrays(GL_TRIANGLES, 0, 3); + + glFlush(); + + return TRUE; +} + +static int compile_shader_from_resource(GLenum shader_type, const char *res_name, unsigned int *shader) +{ + int success; + GBytes *res_bytes; + const char *data; + gsize size; + int size_int; + int sh; + + res_bytes = g_resources_lookup_data(res_name, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); + data = g_bytes_get_data(res_bytes, &size); + sh = glCreateShader(shader_type); + size_int = (int)size; + glShaderSource(sh, 1, &data, &size_int); + glCompileShader(sh); + glGetShaderiv(sh, GL_COMPILE_STATUS, &success); + g_bytes_unref(res_bytes); + if (shader) + *shader = sh; + return success; +} + +static gboolean gl_area_realize(GtkGLArea *area, gpointer user) +{ + unsigned int vbo; + unsigned int vs; + unsigned int fs; + unsigned int prog; + unsigned int vao; + OpenGlPreviewGui *gui; + int success; + + gui = GDS_RENDER_OPENGL_PREVIEW_GUI(user); + + gui->color[0] = 0.6f; + gui->color[1] = 0.5f; + gui->color[2] = 0.12f; + gui->color[3] = 1.0f; + + gtk_gl_area_make_current(area); + + if (!compile_shader_from_resource(GL_VERTEX_SHADER, "/shaders/polygon.vs", &vs)) { + g_warning("Error compiling vertex shader"); + } + if (!compile_shader_from_resource(GL_FRAGMENT_SHADER, "/shaders/polygon.fs", &fs)) { + g_warning("Error compiling fragment shader"); + } + + prog = glCreateProgram(); + glAttachShader(prog, vs); + glAttachShader(prog, fs); + glLinkProgram(prog); + glGetProgramiv(prog, GL_LINK_STATUS, &success); + if (!success) { + g_warning("Error linking shader"); + } + glUseProgram(prog); + glDeleteShader(vs); + glDeleteShader(fs); + + + float vertices[] = { + -0.5f, -0.5f, + 0.5f, -0.5f, + 0.0f, 0.5f, + }; + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (void *)0); + glEnableVertexAttribArray(0); + + + + gui->polygon_shader_prog = prog; + gui->vao = vao; + gui->vbo = vbo; + + return TRUE; + +} + +static void opengl_preview_gui_init(OpenGlPreviewGui *self) +{ + GtkBuilder *builder; + + builder = gtk_builder_new_from_resource("/gui/preview-window.glade"); + self->main_window = GTK_WINDOW(gtk_builder_get_object(builder, "main-window")); + self->gl_area = GTK_GL_AREA(gtk_builder_get_object(builder, "gl-area")); + g_signal_connect(self->gl_area, "render", G_CALLBACK(gl_area_render), self); + g_signal_connect(self->gl_area, "realize", G_CALLBACK(gl_area_realize), self); + g_object_ref(self->gl_area); +} + +OpenGlPreviewGui *opengl_preview_gui_new(void) +{ + return GDS_RENDER_OPENGL_PREVIEW_GUI(g_object_new(TYPE_GDS_RENDER_OPENGL_PREVIEW_GUI, NULL)); +} + +void opengl_preview_gui_show(OpenGlPreviewGui *self) +{ + gtk_widget_show(GTK_WIDGET(self->main_window)); +} diff --git a/preview-rendering/src/preview-rendering.c b/preview-rendering/src/preview-rendering.c index 816849b..ce3660e 100644 --- a/preview-rendering/src/preview-rendering.c +++ b/preview-rendering/src/preview-rendering.c @@ -1,4 +1,8 @@ +#include + int foobar(void) { + GLuint foo; + glGenBuffers(1, &foo); return 42; } diff --git a/resources/preview-window.glade b/resources/preview-window.glade new file mode 100644 index 0000000..dcebed2 --- /dev/null +++ b/resources/preview-window.glade @@ -0,0 +1,43 @@ + + + + + + False + 1024 + 500 + + + True + False + bottom + + + button + True + True + True + + + False + True + 0 + + + + + True + True + False + True + + + True + True + 1 + + + + + + diff --git a/resources/resources.xml b/resources/resources.xml index 393bbe2..291c54a 100644 --- a/resources/resources.xml +++ b/resources/resources.xml @@ -5,6 +5,7 @@ about.glade layer-widget.glade dialog.glade + preview-window.glade color-palette.txt @@ -12,6 +13,10 @@ ../icon/gds-render.svg + + ./shaders/polygon.fs.glsl + ./shaders/polygon.vs.glsl + diff --git a/resources/shaders/polygon.fs.glsl b/resources/shaders/polygon.fs.glsl new file mode 100644 index 0000000..4a7e412 --- /dev/null +++ b/resources/shaders/polygon.fs.glsl @@ -0,0 +1,9 @@ +#version 330 core + +out vec4 FragColor; +in vec4 vertex_color; + +void main() +{ + FragColor = vertex_color; +} diff --git a/resources/shaders/polygon.vs.glsl b/resources/shaders/polygon.vs.glsl new file mode 100644 index 0000000..2a9532f --- /dev/null +++ b/resources/shaders/polygon.vs.glsl @@ -0,0 +1,12 @@ +#version 330 core + +//uniform mat4 mvp; +uniform vec4 const_color; + +layout (location = 0) in vec2 input_vertex; +out vec4 vertex_color; +void main() +{ + gl_Position = vec4(input_vertex.x, input_vertex.y, 0.0, 1.0); + vertex_color = const_color; +}