GTK4_GG_hack/graph_stack.c

324 lines
10 KiB
C

/*
* Gem-graph OpenGL experiments
*
* Desc: GL functions
*
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
*
* This file is part of Gem-graph.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <time.h>
#include "contain.h"
#include "graph_area.h"
#include "parsing.h"
#define TEST 0
struct graphic_stack_t *graphic_stack = NULL;
size_t graphic_stack_size = 0;
int *free_stack_slot = NULL;
size_t free_stack_slot_size = 0;
/*
* Prints verbose human-readable debug messages
*
* @param source, XXX
* type, XXX
* id, XXX
* severity, XXX
* length, XXX
* msg, XXX
* data, XXX
*
* @return void
*/
static void graphics_debug_callback(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length,
const GLchar *msg, const void *data)
{
const char *errsource;
const char *errtype;
const char *errseverity;
const GLubyte *string;
GLenum code;
switch (source) {
case GL_DEBUG_SOURCE_API: errsource = "API"; break;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM: errsource = "WINDOW SYSTEM"; break;
case GL_DEBUG_SOURCE_SHADER_COMPILER: errsource = "SHADER COMPILER"; break;
case GL_DEBUG_SOURCE_THIRD_PARTY: errsource = "THIRD PARTY"; break;
case GL_DEBUG_SOURCE_APPLICATION: errsource = "APPLICATION"; break;
case GL_DEBUG_SOURCE_OTHER: errsource = "UNKNOWN"; break;
default: errsource = "UNKNOWN"; break;
}
switch (type) {
case GL_DEBUG_TYPE_ERROR: errtype = "ERROR"; break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: errtype = "DEPRECATED BEHAVIOR";break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: errtype = "UNDEFINED BEHAVIOR"; break;
case GL_DEBUG_TYPE_PORTABILITY: errtype = "PORTABILITY"; break;
case GL_DEBUG_TYPE_PERFORMANCE: errtype = "PERFORMANCE"; break;
case GL_DEBUG_TYPE_OTHER: errtype = "OTHER"; break;
case GL_DEBUG_TYPE_MARKER: errtype = "MARKER"; break;
default: errtype = "UNKNOWN"; break;
}
switch (severity) {
case GL_DEBUG_SEVERITY_HIGH: errseverity = "CRITICAL"; break;
case GL_DEBUG_SEVERITY_MEDIUM: errseverity = "ERROR"; break;
case GL_DEBUG_SEVERITY_LOW: errseverity = "WARNING"; break;
case GL_DEBUG_SEVERITY_NOTIFICATION: errseverity = "INFO"; break;
default: errseverity = "UNKNOWN"; break;
}
code = glGetError();
string = gluErrorString(code);
g_printerr("[%s] %s (%s) from %s: %s\n",
errseverity, string, errtype, errsource, msg);
}
/* -------------------------------------------------------------------------- */
/*
* Initializes graphical stack
*
* @param gl_area, ptr to the gl_area widget
*
* @return id if initialized
*/
int graphics_init(void *error_buffer)
{
int cur_id = 0;
struct graphic_stack_t *stack;
g_printerr("[debug] graphics_init()\n");
if (graphic_stack == NULL) {
graphic_stack = g_malloc0(sizeof(struct graphic_stack_t));
graphic_stack_size = 1;
g_printerr("[debug] graphics_init(): init graphic_stack @ %p\n", graphic_stack);
} else {
// Check if there are free slots
if (free_stack_slot_size) {
// We get the last free slot registered
cur_id = free_stack_slot[free_stack_slot_size-1];
// Unregister it (ofc)
free_stack_slot = g_realloc(free_stack_slot,
free_stack_slot_size-- *
sizeof(int));
} else {
cur_id = graphic_stack_size;
graphic_stack = g_realloc(graphic_stack,
++graphic_stack_size *
sizeof(struct graphic_stack_t));
}
}
memset(&graphic_stack[cur_id], 0, sizeof(struct graphic_stack_t));
g_printerr("[debug] graphics_init() : graphic_stack (@0x%p) has %ld elements\n",
graphic_stack,
graphic_stack_size);
stack = &graphic_stack[cur_id];
stack->id = cur_id;
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glEnable(GL_MULTISAMPLE);
if (!graphics_init_shaders(cur_id)) return -1;
print_stack(cur_id);
graphics_init_buffers(cur_id);
glDebugMessageCallback(graphics_debug_callback, NULL);
//print_stack(cur_id);
return cur_id;
}
/*
* Shutdowns a gl_area
*
* @param gl_area, ptr to the gl_area widget
*
* @return true if success
*/
bool graphics_shutdown(const int id, void *error_buffer)
{
struct graphic_stack_t *stack;
if (id >= graphic_stack_size ||
graphic_stack_size == 0 ||
graphic_stack == NULL)
return false;
stack = &graphic_stack[id];
//XXX
free(stack->arrows_ptr);
stack->arrows_ptr = NULL;
stack->arrows_nb = 0;
glDeleteBuffers(1, &stack->position_buffer);
glDeleteBuffers(1, &stack->color_buffer);
glDeleteProgram(stack->program);
g_free(stack->buffer_vertex_origin);
g_free(stack->buffer_colors_origin);
g_free(stack->buffer_lines_origin);
g_free(stack->buffer_plans_origin);
if (graphic_stack_size == 1) {
free(graphic_stack);
graphic_stack = NULL;
graphic_stack_size = 0;
} else {
memset(&graphic_stack[id], 0, sizeof(struct graphic_stack_t));
free_stack_slot = g_realloc(free_stack_slot,
++free_stack_slot_size *
sizeof(int));
free_stack_slot[free_stack_slot_size-1] = id;
}
return true;
}
/* TODO
* #pragma omp parallel schedule(static, 12)
* void __attribute__((optimize("no-unroll-loops"))) main_test_graphics (void) {}
*
// assert : space dimensions (x,y,z) > 0
// assert : arrows localization within space and sites
// assert : no more than one arrow per address
// notify : weights are replaced, NOT added (could be !)
*
* Init space and arrows (= initial state)
* and allows ulterior creations, suppressions or modifications of the arrows[] array
*
* draws the space()
* triggers set_arrows() that modifies the list () and draws arrows
*
* Initialisation du générateur pseudo-aléatoire
* Attention, les vertex centraux de chaque unité d'espace (cube)
* peuvent être redondants (max 6)
*/
void graphics_model_setup (const int stack_id)
{
/*------------------------------------------------------------------------*/
/* I N I T I A L D A T A S P E C I F I C A T I O N */
/*------------------------------------------------------------------------*/
struct graphic_stack_t *stack = &graphic_stack[stack_id];
char dimension;
long space_X;
long space_Y;
long space_Z;
long announced_arrows_nb;
int density_max;
char multiplicity;
dimension = model_get_dim();
g_print("[GRAPH DEBUG] dim = %d\n", dimension);
space_X = 1;
space_Y = 1;
space_Z = 1;
switch(dimension) {
case 3:
space_Z = model_get_dim_value("z");
;
case 2:
space_Y = model_get_dim_value("y");
;
// even in 1D, we must be able to see a grid (or not !)
if (!space_Y)
space_Y = 1;
case 1:
space_X = model_get_dim_value("x");
;
if (!space_X)
space_X = 1;
default:
break;
}
g_print("[GRAPH DEBUG] x = %ld\n", space_X);
g_print("[GRAPH DEBUG] y = %ld\n", space_Y);
g_print("[GRAPH DEBUG] z = %ld\n", space_Z);
density_max = space_X * space_Y * space_Z;
stack->arrows_nb = 0;
multiplicity = model_get_multiplicity();
g_print("[GRAPH DEBUG] site_multiplicity = %d, density_max = %d\n", multiplicity, density_max);
/*------------------------------------------------------------------------*/
/* S P A C E D R A W I N G */
/*------------------------------------------------------------------------*/
draw_space_ridges_vertex (stack_id, stack->buffer_vertex_size, space_X, space_Y, space_Z);
draw_space_ridges_lines (stack_id);
draw_grids_on_space_faces_vertex (stack_id, space_X, space_Y, space_Z);
draw_grids_on_space_faces_lines (stack_id, stack->buffer_lines_size, space_X, space_Y, space_Z);
stack->buffer_vertex_0_arrow = stack->buffer_vertex_size;
stack->buffer_colors_0_arrow = stack->buffer_colors_size;
stack->buffer_lines_0_arrow = stack->buffer_lines_size;
/*------------------------------------------------------------------------*/
/* A R R O W S D R A W I N G */
/*------------------------------------------------------------------------*/
char state_id[30] = {0};
struct arrow_t arrow = {0};
assert(model_get_next_state((char *)&state_id));
g_print("[GRAPH DEBUG] first state is = %s\n", state_id);
announced_arrows_nb = model_get_state_arrows_count(state_id);
g_print("[GRAPH DEBUG] announced_arrows_nb is = %ld\n", announced_arrows_nb);
while (model_get_next_arrow(&arrow, (char *)&state_id, dimension)) {
g_print("[GRAPH DEBUG] cur arrow has x = %d\n", arrow.x);
stack->arrows_nb = set_arrow (stack_id, stack->arrows_nb, space_X, space_Y, space_Z, arrow.load, arrow.site, arrow.x, arrow.y, arrow.z);
}
if (stack->arrows_nb != announced_arrows_nb)
g_printerr("ARGH : not all arrows have been parsed !\n");
}