[RELEASE] u22-v03

This version is submitted to U22 breau.
This commit is contained in:
2020-09-14 00:00:00 +00:00
parent 360595de37
commit 84c3a02b9a
357 changed files with 29223 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
add_library(gleasy
atlas.c
framebuffer.c
program.c
shader.c
)
target_link_libraries(gleasy
GLEW::GLEW
OpenGL::GL
container
math
memory
)

194
util/gleasy/atlas.c Normal file
View File

@@ -0,0 +1,194 @@
#include "./atlas.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <GL/glew.h>
#include "util/container/array.h"
#include "util/math/algorithm.h"
#include "util/memory/memory.h"
#include "./misc.h"
#include "./texture.h"
struct gleasy_atlas_t {
int32_t width;
int32_t height;
int32_t consumed_y;
int32_t consumed_x;
int32_t line_height;
gleasy_texture_2d_t tex;
CONTAINER_ARRAY uint8_t* resize_buffer;
};
static void gleasy_atlas_resize_bitmap_(
gleasy_atlas_t* atlas,
gleasy_atlas_bitmap_t* out,
const gleasy_atlas_bitmap_t* in) {
assert(atlas != NULL);
assert(out != NULL);
assert(in != NULL);
*out = (typeof(*out)) {
.width = math_int32_next_power2(MATH_MAX(in->width, 4)),
.height = math_int32_next_power2(MATH_MAX(in->height, 4)),
.format = in->format,
.type = in->type,
.buffer = in->buffer,
};
if (out->width == in->width && out->height == in->height) return;
const size_t type = GLEASY_GET_BYTE_SIZE_OF_TYPE(out->type);
const size_t fmt = GLEASY_GET_CHANNELS_OF_TEXTURE_FORMAT(out->format);
const size_t pixel = type*fmt;
assert(pixel > 0);
container_array_resize(atlas->resize_buffer, out->width*out->height*pixel);
out->buffer = atlas->resize_buffer;
const int32_t ymax = out->height * pixel;
const int32_t xmax = out->width * pixel;
const uint8_t* src = in->buffer;
uint8_t* dst = atlas->resize_buffer;
for (int32_t y = 0; y < ymax; ++y) {
for (int32_t x = 0; x < xmax; ++x) {
if (x < in->width && y < in->height) {
*dst = *(src++);
} else {
*dst = 0;
}
++dst;
}
}
}
static bool gleasy_atlas_allocate_area_(
gleasy_atlas_t* atlas,
int32_t* x,
int32_t* y,
int32_t width,
int32_t height,
int32_t actual_width,
int32_t actual_height) {
assert(atlas != NULL);
assert(x != NULL);
assert(y != NULL);
assert(width > 0);
assert(height > 0);
assert(actual_width > 0);
assert(actual_height > 0);
if (atlas->consumed_x + actual_width > atlas->width) {
atlas->consumed_x = 0;
atlas->consumed_y += atlas->line_height+1;
atlas->line_height = 0;
}
if (atlas->consumed_y + actual_height > atlas->height) {
return false;
}
*x = atlas->consumed_x;
*y = atlas->consumed_y;
atlas->consumed_x += width+1;
atlas->line_height = MATH_MAX(atlas->line_height, height);
return true;
}
gleasy_atlas_t* gleasy_atlas_new(
GLenum format, int32_t width, int32_t height, bool aa) {
assert(width > 0);
assert(height > 0);
gleasy_atlas_t* atlas = memory_new(sizeof(*atlas));
*atlas = (typeof(*atlas)) {
.width = math_int32_next_power2(width),
.height = math_int32_next_power2(height),
};
glGenTextures(1, &atlas->tex);
glBindTexture(GL_TEXTURE_2D, atlas->tex);
const GLenum filter = aa? GL_LINEAR: GL_NEAREST;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexImage2D(GL_TEXTURE_2D, 0, format,
atlas->width, atlas->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
assert(glGetError() == GL_NO_ERROR);
container_array_reserve(atlas->resize_buffer, width*height*4);
return atlas;
}
void gleasy_atlas_delete(gleasy_atlas_t* atlas) {
if (atlas == NULL) return;
glDeleteTextures(1, &atlas->tex);
container_array_delete(atlas->resize_buffer);
memory_delete(atlas);
}
void gleasy_atlas_clear(gleasy_atlas_t* atlas) {
assert(atlas != NULL);
atlas->consumed_y = 0;
atlas->consumed_x = 0;
atlas->line_height = 0;
}
bool gleasy_atlas_add(
gleasy_atlas_t* atlas,
gleasy_atlas_geometry_t* geo,
const gleasy_atlas_bitmap_t* bitmap) {
assert(atlas != NULL);
assert(geo != NULL);
assert(bitmap != NULL);
gleasy_atlas_bitmap_t resized;
gleasy_atlas_resize_bitmap_(atlas, &resized, bitmap);
int32_t x, y;
if (!gleasy_atlas_allocate_area_(atlas,
&x, &y, bitmap->width, bitmap->height, resized.width, resized.height)) {
return false;
}
*geo = (typeof(*geo)) {
.left = x*1.0f / atlas->width,
.right = (x+bitmap->width)*1.0f / atlas->width,
.top = y*1.0f / atlas->height,
.bottom = (y+bitmap->height)*1.0f / atlas->height,
};
glBindTexture(GL_TEXTURE_2D, atlas->tex);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y,
resized.width,
resized.height,
resized.format,
resized.type,
resized.buffer);
assert(glGetError() == GL_NO_ERROR);
return true;
}
gleasy_texture_2d_t gleasy_atlas_get_texture(const gleasy_atlas_t* atlas) {
assert(atlas != NULL);
return atlas->tex;
}

56
util/gleasy/atlas.h Normal file
View File

@@ -0,0 +1,56 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <GL/glew.h>
#include "./texture.h"
struct gleasy_atlas_t;
typedef struct gleasy_atlas_t gleasy_atlas_t;
typedef struct {
float left;
float right;
float top;
float bottom;
} gleasy_atlas_geometry_t;
typedef struct {
int32_t width;
int32_t height;
GLenum format;
GLenum type;
const uint8_t* buffer;
} gleasy_atlas_bitmap_t;
gleasy_atlas_t*
gleasy_atlas_new(
GLenum format,
int32_t width,
int32_t height,
bool aa
);
void
gleasy_atlas_delete(
gleasy_atlas_t* atlas
);
void
gleasy_atlas_clear(
gleasy_atlas_t* atlas
);
bool
gleasy_atlas_add(
gleasy_atlas_t* atlas,
gleasy_atlas_geometry_t* geo,
const gleasy_atlas_bitmap_t* bitmap
);
gleasy_texture_2d_t
gleasy_atlas_get_texture(
const gleasy_atlas_t* atlas
);

7
util/gleasy/buffer.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <GL/glew.h>
typedef GLuint gleasy_buffer_array_t;
typedef GLuint gleasy_buffer_element_array_t;
typedef GLuint gleasy_buffer_uniform_t;

96
util/gleasy/framebuffer.c Normal file
View File

@@ -0,0 +1,96 @@
#include "./framebuffer.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "./texture.h"
void gleasy_framebuffer_initialize(
gleasy_framebuffer_t* fb, int32_t width, int32_t height, int32_t samples) {
assert(fb != NULL);
assert(width > 0);
assert(height > 0);
assert(0 < samples && samples < GL_MAX_SAMPLES);
*fb = (typeof(*fb)) {
.width = width,
.height = height,
};
glGenRenderbuffers(1, &fb->colorbuf_msaa);
glBindRenderbuffer(GL_RENDERBUFFER, fb->colorbuf_msaa);
glRenderbufferStorageMultisample(
GL_RENDERBUFFER, samples, GL_RGBA, width, height);
assert(glGetError() == GL_NO_ERROR);
glGenTextures(1, &fb->colorbuf);
glBindTexture(GL_TEXTURE_2D, fb->colorbuf);
glTexImage2D(GL_TEXTURE_2D,
0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
assert(glGetError() == GL_NO_ERROR);
GLuint fbo[2];
glGenFramebuffers(2, fbo);
fb->id_msaa = fbo[0];
fb->id = fbo[1];
glBindFramebuffer(GL_FRAMEBUFFER, fb->id_msaa);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb->colorbuf_msaa);
assert(glGetError() == GL_NO_ERROR);
glBindFramebuffer(GL_FRAMEBUFFER, fb->id);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->colorbuf, 0);
assert(glGetError() == GL_NO_ERROR);
}
void gleasy_framebuffer_deinitialize(gleasy_framebuffer_t* fb) {
assert(fb != NULL);
GLuint fbo[] = {fb->id_msaa, fb->id};
glDeleteFramebuffers(2, fbo);
glDeleteTextures(1, &fb->colorbuf);
glDeleteRenderbuffers(1, &fb->colorbuf_msaa);
}
void gleasy_framebuffer_bind(const gleasy_framebuffer_t* fb) {
assert(fb != NULL);
glBindFramebuffer(GL_FRAMEBUFFER, fb->id_msaa);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "gleasy: framebuffer is in invalid state\n");
abort();
}
}
void gleasy_framebuffer_flush(const gleasy_framebuffer_t* fb) {
assert(fb != NULL);
gleasy_framebuffer_flush_to_other(fb, fb->id);
}
void gleasy_framebuffer_flush_to_other(const gleasy_framebuffer_t* fb, GLuint id) {
assert(fb != NULL);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb->id_msaa);
glBlitFramebuffer(
0, 0, fb->width, fb->height,
0, 0, fb->width, fb->height,
GL_COLOR_BUFFER_BIT,
GL_NEAREST);
assert(glGetError() == GL_NO_ERROR);
}

47
util/gleasy/framebuffer.h Normal file
View File

@@ -0,0 +1,47 @@
#pragma once
#include <stdint.h>
#include <GL/glew.h>
#include "./texture.h"
typedef struct {
int32_t width;
int32_t height;
GLuint id_msaa;
GLuint colorbuf_msaa;
GLuint id;
gleasy_texture_2d_t colorbuf;
} gleasy_framebuffer_t;
void
gleasy_framebuffer_initialize(
gleasy_framebuffer_t* fb,
int32_t width,
int32_t height,
int32_t samples
);
void
gleasy_framebuffer_deinitialize(
gleasy_framebuffer_t* fb
);
void
gleasy_framebuffer_bind(
const gleasy_framebuffer_t* fb
);
void
gleasy_framebuffer_flush(
const gleasy_framebuffer_t* fb
);
void
gleasy_framebuffer_flush_to_other(
const gleasy_framebuffer_t* fb,
GLuint id
);

18
util/gleasy/misc.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include <GL/glew.h>
#define GLEASY_GET_BYTE_SIZE_OF_TYPE(t) ( \
(t) == GL_UNSIGNED_BYTE? 1: \
(t) == GL_BYTE? 1: \
(t) == GL_SHORT? 2: \
(t) == GL_UNSIGNED_SHORT? 2: \
(t) == GL_INT? 4: \
(t) == GL_UNSIGNED_INT? 4: \
(t) == GL_FLOAT? 4: 0)
#define GLEASY_GET_CHANNELS_OF_TEXTURE_FORMAT(f) ( \
(f) == GL_RGBA? 4: \
(f) == GL_RGB? 3: \
(f) == GL_RG? 2: \
(f) == GL_RED? 1: 0)

66
util/gleasy/program.c Normal file
View File

@@ -0,0 +1,66 @@
#include "./program.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/math/algorithm.h"
#include "./shader.h"
gleasy_program_t gleasy_program_new(
const char* header, size_t header_len,
const char* vsrc, size_t vsrc_len,
const char* fsrc, size_t fsrc_len) {
assert(header != NULL || header_len == 0);
assert(vsrc != NULL || vsrc_len == 0);
assert(fsrc != NULL || fsrc_len == 0);
gleasy_program_t program = glCreateProgram();
if (program == 0) {
fprintf(stderr, "failed to create program");
abort();
}
const gleasy_shader_t vshader =
gleasy_shader_new(GL_VERTEX_SHADER, header, header_len, vsrc, vsrc_len);
const gleasy_shader_t fshader =
gleasy_shader_new(GL_FRAGMENT_SHADER, header, header_len, fsrc, fsrc_len);
glAttachShader(program, vshader);
glDeleteShader(vshader);
glAttachShader(program, fshader);
glDeleteShader(fshader);
glLinkProgram(program);
GLint ok;
glGetProgramiv(program, GL_LINK_STATUS, &ok);
if (ok == GL_FALSE) {
char log[1024];
const int len =
gleasy_program_get_log(program, log, sizeof(log)/sizeof(log[0]));
fprintf(stderr, "failed to link program\n%.*s\n", len, log);
abort();
}
return program;
}
size_t gleasy_program_get_log(
gleasy_program_t program, char* dst, size_t maxlen) {
assert(program != 0);
GLint len;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
if (dst == NULL) return len;
len = MATH_MIN(len, (GLint) maxlen);
if (len == 0) return 0;
glGetProgramInfoLog(program, len, &len, (GLchar*) dst);
return len;
}

24
util/gleasy/program.h Normal file
View File

@@ -0,0 +1,24 @@
#pragma once
#include <stddef.h>
#include <GL/glew.h>
typedef GLuint gleasy_program_t;
gleasy_program_t /* OWNERSHIP */
gleasy_program_new(
const char* header,
size_t header_len,
const char* vsrc,
size_t vsrc_len,
const char* fsrc,
size_t fsrc_len
);
size_t
gleasy_program_get_log(
gleasy_program_t program,
char* dst, /* when NULL, returns actual size */
size_t maxlen
);

57
util/gleasy/shader.c Normal file
View File

@@ -0,0 +1,57 @@
#include "./shader.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <GL/glew.h>
#include "util/math/algorithm.h"
gleasy_shader_t gleasy_shader_new(
GLenum type,
const char* header, size_t header_len,
const char* src, size_t src_len) {
assert(header != NULL || header_len == 0);
assert(src != NULL || src_len == 0);
const GLuint shader = glCreateShader(type);
if (shader == 0) {
fprintf(stderr, "failed to create shader\n");
abort();
}
const GLchar* srcs[] = { header, src, };
const GLint lens[] = { header_len, src_len, };
const size_t offset = (header_len == 0? 1: 0);
glShaderSource(shader, 2-offset, srcs+offset, lens+offset);
glCompileShader(shader);
GLint ok;
glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
if (ok == GL_FALSE) {
char log[1024];
const int loglen =
gleasy_shader_get_log(shader, log, sizeof(log)/sizeof(log[0]));
fprintf(stderr, "failed to compile shader\n%.*s\n", loglen, log);
abort();
}
return shader;
}
size_t gleasy_shader_get_log(
gleasy_shader_t shader, char* dst, size_t maxlen) {
assert(shader != 0);
GLint len;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (dst == NULL) return len;
len = MATH_MIN(len, (GLint) maxlen);
if (len == 0) return 0;
glGetShaderInfoLog(shader, len, &len, (GLchar*) dst);
return len;
}

23
util/gleasy/shader.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#include <stddef.h>
#include <GL/glew.h>
typedef GLuint gleasy_shader_t;
gleasy_shader_t /* OWNERSHIP */
gleasy_shader_new(
GLenum type,
const char* header,
size_t header_len,
const char* src,
size_t src_len
);
size_t
gleasy_shader_get_log(
gleasy_shader_t shader,
char* dst, /* when NULL, returns actual size */
size_t maxlen
);

5
util/gleasy/texture.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
#include <GL/glew.h>
typedef GLuint gleasy_texture_2d_t;