working on gles 3.1 canvas on windows

This commit is contained in:
martinfouilleul 2023-01-31 15:51:50 +01:00
parent c5ae556f22
commit 8e87837fcc
5 changed files with 379 additions and 0 deletions

43
scripts/embed_text.py Normal file
View File

@ -0,0 +1,43 @@
import os
from datetime import datetime
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("inputFiles", nargs="+")
parser.add_argument("-o", "--output")
args = parser.parse_args()
output = open(args.output, "w")
output.write("/*********************************************************************\n")
output.write("*\n")
output.write("*\tfile: %s\n" % os.path.basename(args.output))
output.write("*\tnote: string literals auto-generated by embed_text.py\n")
output.write("*\tdate: %s\n" % datetime.now().strftime("%d/%m%Y"))
output.write("*\n")
output.write("**********************************************************************/\n")
outSymbol = (os.path.splitext(os.path.basename(args.output))[0]).upper()
output.write("#ifndef __%s_H__\n" % outSymbol)
output.write("#define __%s_H__\n" % outSymbol)
output.write("\n\n")
for fileName in args.inputFiles:
f = open(fileName, "r")
lines = f.read().splitlines()
output.write("//NOTE: string imported from %s\n" % fileName)
stringName = os.path.splitext(os.path.basename(fileName))[0]
output.write("const char* %s = " % stringName)
for line in lines:
output.write("\n\"%s\\n\"" % line)
output.write(";\n\n")
f.close()
output.write("#endif // __%s_H__\n" % outSymbol)
output.close()

238
src/gles_canvas.c Normal file
View File

@ -0,0 +1,238 @@
/************************************************************//**
*
* @file: gles_canvas.c
* @author: Martin Fouilleul
* @date: 29/01/2023
* @revision:
*
*****************************************************************/
#include"graphics_internal.h"
#include"macro_helpers.h"
#include"gles_canvas_shaders.h"
#define LOG_SUBSYSTEM "Graphics"
typedef struct mg_gles_canvas_backend
{
mg_canvas_backend interface;
mg_surface surface;
GLint dummyVertexBuffer;
GLint vertexBuffer;
GLint indexBuffer;
GLint program;
char* indexMapping;
char* vertexMapping;
} mg_gles_canvas_backend;
mg_gles_surface* mg_gles_canvas_get_surface(mg_gles_canvas_backend* canvas)
{
mg_gles_surface* res = 0;
mg_surface_data* data = mg_surface_data_from_handle(canvas->surface);
if(data && data->backend == MG_BACKEND_GLES)
{
res = (mg_gles_surface*)data;
}
return(res);
}
void mg_gles_canvas_draw_buffers(mg_canvas_backend* interface, u32 vertexCount, u32 indexCount, mg_color clearColor)
{
mg_gles_canvas_backend* backend = (mg_gles_canvas_backend*)interface;
mg_gles_surface* surface = mg_gles_canvas_get_surface(backend);
if(!surface)
{
return;
}
//WARN: dummy test code
indexCount = 3;
*(vec2*)(interface->vertexLayout.posBuffer) = (vec2){400, 300};
*(vec2*)(interface->vertexLayout.posBuffer + interface->vertexLayout.posStride) = (vec2){450, 300};
*(vec2*)(interface->vertexLayout.posBuffer + 2*interface->vertexLayout.posStride) = (vec2){400, 350};
for(int i=0; i<3; i++)
{
*(vec4*)(interface->vertexLayout.cubicBuffer + i*interface->vertexLayout.cubicStride) = (vec4){1, 1, 1, 1};
*(vec2*)(interface->vertexLayout.uvBuffer + i*interface->vertexLayout.uvStride) = (vec2){0, 0};
*(vec4*)(interface->vertexLayout.colorBuffer + i*interface->vertexLayout.colorStride) = (vec4){1, 0, 0, 1};
*(vec4*)(interface->vertexLayout.clipBuffer + i*interface->vertexLayout.clipStride) = (vec4){-FLT_MAX/2, -FLT_MAX/2, FLT_MAX, FLT_MAX};
*(u32*)(interface->vertexLayout.zIndexBuffer + i*interface->vertexLayout.zIndexStride) = 1;
*(u32*)(interface->vertexLayout.indexBuffer + i*interface->vertexLayout.indexStride) = i;
}
// end dummy test code
glUseProgram(backend->program);
glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, backend->vertexBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, backend->indexBuffer);
glUniform1i(0, indexCount);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
#define LayoutNext(prevName, prevType, nextType) \
AlignUpOnPow2(_cat3_(LAYOUT_, prevName, _OFFSET)+_cat3_(LAYOUT_, prevType, _SIZE), _cat3_(LAYOUT_, nextType, _ALIGN))
enum {
LAYOUT_VEC2_SIZE = 8,
LAYOUT_VEC2_ALIGN = 8,
LAYOUT_VEC4_SIZE = 16,
LAYOUT_VEC4_ALIGN = 16,
LAYOUT_INT_SIZE = 4,
LAYOUT_INT_ALIGN = 4,
LAYOUT_POS_OFFSET = 0,
LAYOUT_CUBIC_OFFSET = LayoutNext(POS, VEC2, VEC4),
LAYOUT_UV_OFFSET = LayoutNext(CUBIC, VEC4, VEC2),
LAYOUT_COLOR_OFFSET = LayoutNext(UV, VEC2, VEC4),
LAYOUT_CLIP_OFFSET = LayoutNext(COLOR, VEC4, VEC4),
LAYOUT_ZINDEX_OFFSET = LayoutNext(CLIP, VEC4, INT),
LAYOUT_VERTEX_ALIGN = 16,
LAYOUT_VERTEX_SIZE = LayoutNext(ZINDEX, INT, VERTEX),
};
enum {
MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH = 1<<20,
MG_GLES_CANVAS_VERTEX_BUFFER_SIZE = MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_VERTEX_SIZE,
MG_GLES_CANVAS_INDEX_BUFFER_SIZE = MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH * LAYOUT_INT_SIZE,
};
void mg_gles_canvas_update_vertex_layout(mg_gles_canvas_backend* backend)
{
if(backend->vertexMapping)
{
glUnmapBuffer(backend->vertexBuffer);
}
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->vertexBuffer);
backend->vertexMapping = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, MG_GLES_CANVAS_VERTEX_BUFFER_SIZE, GL_MAP_WRITE_BIT);
if(backend->indexMapping)
{
free(backend->indexMapping);
}
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->indexBuffer);
backend->indexMapping = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, MG_GLES_CANVAS_INDEX_BUFFER_SIZE, GL_MAP_WRITE_BIT);
backend->interface.vertexLayout = (mg_vertex_layout){
.maxVertexCount = MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH,
.maxIndexCount = MG_GLES_CANVAS_DEFAULT_BUFFER_LENGTH,
.posBuffer = backend->vertexMapping + LAYOUT_POS_OFFSET,
.posStride = LAYOUT_VERTEX_SIZE,
.cubicBuffer = backend->vertexMapping + LAYOUT_CUBIC_OFFSET,
.cubicStride = LAYOUT_VERTEX_SIZE,
.uvBuffer = backend->vertexMapping + LAYOUT_UV_OFFSET,
.uvStride = LAYOUT_VERTEX_SIZE,
.colorBuffer = backend->vertexMapping + LAYOUT_COLOR_OFFSET,
.colorStride = LAYOUT_VERTEX_SIZE,
.clipBuffer = backend->vertexMapping + LAYOUT_CLIP_OFFSET,
.clipStride = LAYOUT_VERTEX_SIZE,
.zIndexBuffer = backend->vertexMapping + LAYOUT_ZINDEX_OFFSET,
.zIndexStride = LAYOUT_VERTEX_SIZE,
.indexBuffer = backend->indexMapping,
.indexStride = LAYOUT_INT_SIZE};
}
void mg_gles_canvas_destroy(mg_canvas_backend* interface)
{
mg_gles_canvas_backend* backend = (mg_gles_canvas_backend*)interface;
//TODO
}
void mg_gles_canvas_atlas_upload(mg_canvas_backend* interface, mp_rect rect, u8* bytes)
{
//TODO
}
void compile_shader(GLuint shader, const char* source)
{
glShaderSource(shader, 1, &source, 0);
glCompileShader(shader);
int err = glGetError();
if(err)
{
printf("gl error: %i\n", err);
}
int status = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(!status)
{
char buffer[256];
int size = 0;
glGetShaderInfoLog(shader, 256, &size, buffer);
printf("shader error: %.*s\n", size, buffer);
}
}
mg_canvas_backend* mg_gles_canvas_create(mg_surface surface)
{
mg_gles_canvas_backend* backend = 0;
mg_surface_data* surfaceData = mg_surface_data_from_handle(surface);
if(surfaceData && surfaceData->backend == MG_BACKEND_GLES)
{
mg_gles_surface* glesSurface = (mg_gles_surface*)surfaceData;
backend = malloc_type(mg_gles_canvas_backend);
memset(backend, 0, sizeof(mg_gles_canvas_backend));
backend->surface = surface;
//NOTE(martin): setup interface functions
backend->interface.destroy = mg_gles_canvas_destroy;
backend->interface.drawBuffers = mg_gles_canvas_draw_buffers;
backend->interface.atlasUpload = mg_gles_canvas_atlas_upload;
mg_surface_prepare(surface);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &backend->vertexBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->vertexBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GLES_CANVAS_VERTEX_BUFFER_SIZE, 0, GL_DYNAMIC_DRAW);
glGenBuffers(1, &backend->indexBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, backend->indexBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, MG_GLES_CANVAS_INDEX_BUFFER_SIZE, 0, GL_DYNAMIC_DRAW);
glGenBuffers(1, &backend->dummyVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, backend->dummyVertexBuffer);
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
backend->program = glCreateProgram();
compile_shader(vertexShader, gles_canvas_vertex);
compile_shader(fragmentShader, gles_canvas_fragment);
glAttachShader(backend->program, vertexShader);
glAttachShader(backend->program, fragmentShader);
glLinkProgram(backend->program);
int status = 0;
glGetProgramiv(backend->program, GL_LINK_STATUS, &status);
if(!status)
{
char buffer[256];
int size = 0;
glGetProgramInfoLog(backend->program, 256, &size, buffer);
printf("link error: %.*s\n", size, buffer);
}
glUseProgram(backend->program);
mg_gles_canvas_update_vertex_layout(backend);
}
return((mg_canvas_backend*)backend);
}
#undef LOG_SUBSYSTEM

58
src/gles_canvas_shaders.h Normal file
View File

@ -0,0 +1,58 @@
/*********************************************************************
*
* file: gles_canvas_shaders.h
* note: string literals auto-generated by embed_text.py
* date: 31/012023
*
**********************************************************************/
#ifndef __GLES_CANVAS_SHADERS_H__
#define __GLES_CANVAS_SHADERS_H__
//NOTE: string imported from src\gles_canvas_shaders\gles_canvas_fragment.glsl
const char* gles_canvas_fragment =
"#version 310 es\n"
"\n"
"precision mediump float;\n"
"layout(std430) buffer;\n"
"\n"
"struct vertex {\n"
" vec2 pos;\n"
" vec4 cubic;\n"
" vec2 uv;\n"
" vec4 color;\n"
" vec4 clip;\n"
" int zIndex;\n"
"};\n"
"\n"
"layout(binding = 0) buffer vertexBufferSSBO {\n"
" vertex elements[];\n"
"} vertexBuffer ;\n"
"\n"
"layout(binding = 1) buffer indexBufferSSBO {\n"
" vec2 elements[];\n"
"} indexBuffer ;\n"
"\n"
"layout(location = 0) uniform int indexCount;\n"
"layout(location = 0) out vec4 fragColor;\n"
"\n"
"void main()\n"
"{\n"
" fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
"}\n";
//NOTE: string imported from src\gles_canvas_shaders\gles_canvas_vertex.glsl
const char* gles_canvas_vertex =
"#version 310 es\n"
"\n"
"precision mediump float;\n"
"\n"
"void main()\n"
"{\n"
" float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u);\n"
" float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u);\n"
"\n"
" gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);\n"
"}\n";
#endif // __GLES_CANVAS_SHADERS_H__

View File

@ -0,0 +1,29 @@
#version 310 es
precision mediump float;
layout(std430) buffer;
struct vertex {
vec2 pos;
vec4 cubic;
vec2 uv;
vec4 color;
vec4 clip;
int zIndex;
};
layout(binding = 0) buffer vertexBufferSSBO {
vertex elements[];
} vertexBuffer ;
layout(binding = 1) buffer indexBufferSSBO {
vec2 elements[];
} indexBuffer ;
layout(location = 0) uniform int indexCount;
layout(location = 0) out vec4 fragColor;
void main()
{
fragColor = vec4(0.0, 1.0, 0.0, 1.0);
}

View File

@ -0,0 +1,11 @@
#version 310 es
precision mediump float;
void main()
{
float x = float(((uint(gl_VertexID) + 2u) / 3u)%2u);
float y = float(((uint(gl_VertexID) + 1u) / 3u)%2u);
gl_Position = vec4(-1.0f + x*2.0f, -1.0f+y*2.0f, 0.0f, 1.0f);
}