|
|
|
|
@@ -1,3 +1,4 @@
|
|
|
|
|
#include "epoxy/gl.h"
|
|
|
|
|
#include "gtk/gtk.h"
|
|
|
|
|
|
|
|
|
|
#include "../core/raster.h"
|
|
|
|
|
@@ -8,6 +9,114 @@
|
|
|
|
|
#define VKTR_CANVAS_HEIGHT 400
|
|
|
|
|
#define VKTR_CANVAS_SIZE (VKTR_CANVAS_WIDTH * VKTR_CANVAS_HEIGHT * 4)
|
|
|
|
|
|
|
|
|
|
static GLuint shader_program;
|
|
|
|
|
static GLuint vao;
|
|
|
|
|
|
|
|
|
|
static const char* vertex_shader_src =
|
|
|
|
|
"#version 300 es\n" // <- ES version
|
|
|
|
|
"layout(location = 0) in vec2 aPos;\n"
|
|
|
|
|
"void main() {\n"
|
|
|
|
|
" gl_Position = vec4(aPos, 0.0, 1.0);\n"
|
|
|
|
|
"}\n";
|
|
|
|
|
|
|
|
|
|
static const char* fragment_shader_src =
|
|
|
|
|
"#version 300 es\n" // <- ES version
|
|
|
|
|
"precision mediump float;\n" // required in ES for fragment color
|
|
|
|
|
"out vec4 FragColor;\n"
|
|
|
|
|
"void main() {\n"
|
|
|
|
|
" FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
|
|
|
|
|
"}\n";
|
|
|
|
|
|
|
|
|
|
static GLuint compile_shader(GLenum type, const char* src) {
|
|
|
|
|
GLuint shader = glCreateShader(type);
|
|
|
|
|
glShaderSource(shader, 1, &src, NULL);
|
|
|
|
|
glCompileShader(shader);
|
|
|
|
|
|
|
|
|
|
GLint success;
|
|
|
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
|
|
|
|
if (!success) {
|
|
|
|
|
char info[512];
|
|
|
|
|
glGetShaderInfoLog(shader, 512, NULL, info);
|
|
|
|
|
g_error("Shader compile failed: %s", info);
|
|
|
|
|
}
|
|
|
|
|
return shader;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void init_shader(void) {
|
|
|
|
|
GLuint vertex = compile_shader(GL_VERTEX_SHADER, vertex_shader_src);
|
|
|
|
|
GLuint fragment = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_src);
|
|
|
|
|
|
|
|
|
|
shader_program = glCreateProgram();
|
|
|
|
|
glAttachShader(shader_program, vertex);
|
|
|
|
|
glAttachShader(shader_program, fragment);
|
|
|
|
|
glLinkProgram(shader_program);
|
|
|
|
|
|
|
|
|
|
GLint success;
|
|
|
|
|
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
|
|
|
|
|
if (!success) {
|
|
|
|
|
char info[512];
|
|
|
|
|
glGetProgramInfoLog(shader_program, 512, NULL, info);
|
|
|
|
|
g_error("Shader link failed: %s", info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glDeleteShader(vertex);
|
|
|
|
|
glDeleteShader(fragment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void init_geometry(void) {
|
|
|
|
|
// Vertices for a rectangle in NDC coordinates
|
|
|
|
|
float vertices[] = {
|
|
|
|
|
-0.5f, -0.5f, // bottom-left
|
|
|
|
|
0.5f, -0.5f, // bottom-right
|
|
|
|
|
0.5f, 0.5f, // top-right
|
|
|
|
|
-0.5f, 0.5f // top-left
|
|
|
|
|
};
|
|
|
|
|
unsigned int indices[] = {0, 1, 2, 2, 3, 0};
|
|
|
|
|
|
|
|
|
|
GLuint vbo, ebo;
|
|
|
|
|
glGenVertexArrays(1, &vao);
|
|
|
|
|
glGenBuffers(1, &vbo);
|
|
|
|
|
glGenBuffers(1, &ebo);
|
|
|
|
|
|
|
|
|
|
glBindVertexArray(vao);
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
|
|
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
|
|
|
|
|
GL_STATIC_DRAW);
|
|
|
|
|
|
|
|
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),
|
|
|
|
|
(void*)0);
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean render(GtkGLArea* area, GdkGLContext* context) {
|
|
|
|
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
|
|
|
|
|
|
glUseProgram(shader_program);
|
|
|
|
|
glBindVertexArray(vao);
|
|
|
|
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
glUseProgram(0);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void realize(GtkGLArea* area, gpointer user_data) {
|
|
|
|
|
gtk_gl_area_make_current(area);
|
|
|
|
|
|
|
|
|
|
if (gtk_gl_area_get_error(area) != NULL)
|
|
|
|
|
return; // context creation failed
|
|
|
|
|
|
|
|
|
|
init_shader();
|
|
|
|
|
init_geometry();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut) {
|
|
|
|
|
canvasOut->canvasWidget = state->workspaceCanvas;
|
|
|
|
|
canvasOut->width = VKTR_CANVAS_WIDTH;
|
|
|
|
|
@@ -20,10 +129,14 @@ void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut) {
|
|
|
|
|
VKTR_CANVAS_WIDTH, VKTR_CANVAS_HEIGHT, GDK_MEMORY_R8G8B8A8,
|
|
|
|
|
canvasOut->canvasPixelBytes, VKTR_CANVAS_WIDTH * 4);
|
|
|
|
|
|
|
|
|
|
gtk_picture_set_paintable(canvasOut->canvasWidget,
|
|
|
|
|
GDK_PAINTABLE(canvasOut->canvasTexture));
|
|
|
|
|
gtk_picture_set_content_fit(GTK_PICTURE(canvasOut->canvasWidget),
|
|
|
|
|
GTK_CONTENT_FIT_CONTAIN);
|
|
|
|
|
g_signal_connect(canvasOut->canvasWidget, "realize", G_CALLBACK(realize),
|
|
|
|
|
NULL);
|
|
|
|
|
g_signal_connect(canvasOut->canvasWidget, "render", G_CALLBACK(render),
|
|
|
|
|
NULL);
|
|
|
|
|
// gtk_picture_set_paintable(canvasOut->canvasWidget,
|
|
|
|
|
// GDK_PAINTABLE(canvasOut->canvasTexture));
|
|
|
|
|
// gtk_picture_set_content_fit(GTK_PICTURE(canvasOut->canvasWidget),
|
|
|
|
|
// GTK_CONTENT_FIT_CONTAIN);
|
|
|
|
|
// g_object_unref(bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -38,8 +151,8 @@ void vektor_canvas_update(VektorCanvas* canvas) {
|
|
|
|
|
canvas->width, canvas->height, GDK_MEMORY_R8G8B8A8,
|
|
|
|
|
canvas->canvasPixelBytes, canvas->width * 4);
|
|
|
|
|
|
|
|
|
|
gtk_picture_set_paintable(canvas->canvasWidget,
|
|
|
|
|
GDK_PAINTABLE(canvas->canvasTexture));
|
|
|
|
|
// gtk_picture_set_paintable(canvas->canvasWidget,
|
|
|
|
|
// GDK_PAINTABLE(canvas->canvasTexture));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vektor_canvas_fill(VektorCanvas* canvas, VektorColor color) {
|
|
|
|
|
|