[wip, canvas, gl] implementing basic image API
This commit is contained in:
parent
5e5f8ac5e7
commit
8f834fa1a5
|
@ -1,4 +1,4 @@
|
|||
|
||||
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
|
||||
|
||||
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_canvas.exe
|
||||
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_image.exe
|
||||
|
|
|
@ -95,7 +95,7 @@ int main()
|
|||
|
||||
mg_matrix_pop();
|
||||
|
||||
mg_image_draw(image2, (mp_rect){300, 200, 300, 300});
|
||||
mg_image_draw(image, (mp_rect){300, 200, 300, 300});
|
||||
|
||||
mg_flush();
|
||||
mg_surface_present(surface);
|
||||
|
|
|
@ -39,6 +39,13 @@ typedef struct mg_gl_canvas_backend
|
|||
|
||||
} mg_gl_canvas_backend;
|
||||
|
||||
typedef struct mg_gl_image
|
||||
{
|
||||
mg_image_data interface;
|
||||
|
||||
GLuint textureID;
|
||||
} mg_gl_image;
|
||||
|
||||
//NOTE: debugger
|
||||
typedef struct debug_vertex
|
||||
{
|
||||
|
@ -66,6 +73,8 @@ enum {
|
|||
LAYOUT_VEC4_ALIGN = 16,
|
||||
LAYOUT_INT_SIZE = 4,
|
||||
LAYOUT_INT_ALIGN = 4,
|
||||
LAYOUT_MAT2x3_SIZE = sizeof(float)*6,
|
||||
LAYOUT_MAT2x3_ALIGN = 4,
|
||||
|
||||
LAYOUT_CUBIC_OFFSET = 0,
|
||||
LAYOUT_POS_OFFSET = LayoutNext(CUBIC, VEC4, VEC2),
|
||||
|
@ -75,9 +84,9 @@ enum {
|
|||
|
||||
LAYOUT_COLOR_OFFSET = 0,
|
||||
LAYOUT_CLIP_OFFSET = LayoutNext(COLOR, VEC4, VEC4),
|
||||
LAYOUT_UV_OFFSET = LayoutNext(CLIP, VEC4, VEC2),
|
||||
LAYOUT_UV_TRANSFORM_OFFSET = LayoutNext(CLIP, VEC4, MAT2x3),
|
||||
LAYOUT_SHAPE_ALIGN = 16,
|
||||
LAYOUT_SHAPE_SIZE = LayoutNext(UV, VEC2, SHAPE),
|
||||
LAYOUT_SHAPE_SIZE = LayoutNext(UV_TRANSFORM, MAT2x3, SHAPE),
|
||||
|
||||
MG_GL_CANVAS_MAX_BUFFER_LENGTH = 1<<20,
|
||||
MG_GL_CANVAS_MAX_SHAPE_BUFFER_SIZE = LAYOUT_SHAPE_SIZE * MG_GL_CANVAS_MAX_BUFFER_LENGTH,
|
||||
|
@ -108,8 +117,8 @@ void mg_gl_canvas_update_vertex_layout(mg_gl_canvas_backend* backend)
|
|||
.colorStride = LAYOUT_SHAPE_SIZE,
|
||||
.clipBuffer = backend->shapeMapping + LAYOUT_CLIP_OFFSET,
|
||||
.clipStride = LAYOUT_SHAPE_SIZE,
|
||||
.uvBuffer = backend->shapeMapping + LAYOUT_UV_OFFSET,
|
||||
.uvStride = LAYOUT_SHAPE_SIZE,
|
||||
.uvTransformBuffer = backend->shapeMapping + LAYOUT_UV_TRANSFORM_OFFSET,
|
||||
.uvTransformStride = LAYOUT_SHAPE_SIZE,
|
||||
|
||||
.indexBuffer = backend->indexMapping,
|
||||
.indexStride = LAYOUT_INT_SIZE};
|
||||
|
@ -147,7 +156,7 @@ void mg_gl_canvas_clear(mg_canvas_backend* interface, mg_color clearColor)
|
|||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 shapeCount, u32 vertexCount, u32 indexCount)
|
||||
void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, mg_image_data* imageInterface, u32 shapeCount, u32 vertexCount, u32 indexCount)
|
||||
{
|
||||
mg_gl_canvas_backend* backend = (mg_gl_canvas_backend*)interface;
|
||||
|
||||
|
@ -213,6 +222,19 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, u32 shapeCount, u32 v
|
|||
glUniform1ui(3, tileArrayLength);
|
||||
glUniform2f(4, contentsScaling.x, contentsScaling.y);
|
||||
|
||||
if(imageInterface)
|
||||
{
|
||||
//TODO: make sure this image belongs to that context
|
||||
mg_gl_image* image = (mg_gl_image*)imageInterface;
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, image->textureID);
|
||||
glUniform1ui(5, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
glUniform1ui(5, 0);
|
||||
}
|
||||
|
||||
glDispatchCompute(tileCountX, tileCountY, 1);
|
||||
|
||||
//NOTE: now blit out texture to surface
|
||||
|
@ -248,9 +270,41 @@ void mg_gl_canvas_destroy(mg_canvas_backend* interface)
|
|||
free(backend);
|
||||
}
|
||||
|
||||
void mg_gl_canvas_atlas_upload(mg_canvas_backend* interface, mp_rect rect, u8* bytes)
|
||||
mg_image_data* mg_gl_canvas_image_create(mg_canvas_backend* interface, vec2 size)
|
||||
{
|
||||
//TODO
|
||||
mg_gl_image* image = 0;
|
||||
|
||||
image = malloc_type(mg_gl_image);
|
||||
if(image)
|
||||
{
|
||||
glGenTextures(1, &image->textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, image->textureID);
|
||||
// glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, size.x, size.y);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
image->interface.size = size;
|
||||
}
|
||||
return((mg_image_data*)image);
|
||||
}
|
||||
|
||||
void mg_gl_canvas_image_destroy(mg_canvas_backend* interface, mg_image_data* imageInterface)
|
||||
{
|
||||
//TODO: check that this image belongs to this context
|
||||
mg_gl_image* image = (mg_gl_image*)imageInterface;
|
||||
glDeleteTextures(1, &image->textureID);
|
||||
free(image);
|
||||
}
|
||||
|
||||
void mg_gl_canvas_image_upload_region(mg_canvas_backend* interface,
|
||||
mg_image_data* imageInterface,
|
||||
mp_rect region,
|
||||
u8* pixels)
|
||||
{
|
||||
//TODO: check that this image belongs to this context
|
||||
mg_gl_image* image = (mg_gl_image*)imageInterface;
|
||||
glBindTexture(GL_TEXTURE_2D, image->textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, region.w, region.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
|
||||
static int mg_gl_compile_shader(const char* name, GLuint shader, const char* source)
|
||||
|
@ -375,7 +429,9 @@ mg_canvas_backend* mg_gl_canvas_create(mg_surface surface)
|
|||
backend->interface.end = mg_gl_canvas_end;
|
||||
backend->interface.clear = mg_gl_canvas_clear;
|
||||
backend->interface.drawBatch = mg_gl_canvas_draw_batch;
|
||||
backend->interface.atlasUpload = mg_gl_canvas_atlas_upload;
|
||||
backend->interface.imageCreate = mg_gl_canvas_image_create;
|
||||
backend->interface.imageDestroy = mg_gl_canvas_image_destroy;
|
||||
backend->interface.imageUploadRegion = mg_gl_canvas_image_upload_region;
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* file: glsl_shaders.h
|
||||
* note: string literals auto-generated by embed_text.py
|
||||
* date: 22/022023
|
||||
* date: 27/022023
|
||||
*
|
||||
**********************************************************************/
|
||||
#ifndef __GLSL_SHADERS_H__
|
||||
|
@ -23,7 +23,7 @@ const char* glsl_common =
|
|||
"struct shape {\n"
|
||||
" vec4 color;\n"
|
||||
" vec4 clip;\n"
|
||||
" vec2 uv;\n"
|
||||
" float uvTransform[6];\n"
|
||||
"};\n";
|
||||
|
||||
//NOTE: string imported from src\glsl_shaders\blit_vertex.glsl
|
||||
|
@ -253,9 +253,13 @@ const char* glsl_draw =
|
|||
"layout(location = 2) uniform uint tileSize;\n"
|
||||
"layout(location = 3) uniform uint tileArraySize;\n"
|
||||
"layout(location = 4) uniform vec2 scaling;\n"
|
||||
"layout(location = 5) uniform uint useTexture;\n"
|
||||
"\n"
|
||||
"layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;\n"
|
||||
"\n"
|
||||
"layout(binding = 1) uniform sampler2D srcTexture;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"bool is_top_left(ivec2 a, ivec2 b)\n"
|
||||
"{\n"
|
||||
" return( (a.y == b.y && b.x < a.x)\n"
|
||||
|
@ -363,6 +367,16 @@ const char* glsl_draw =
|
|||
" vec4 color = shapeBuffer.elements[shapeIndex].color;\n"
|
||||
" ivec4 clip = ivec4(round((shapeBuffer.elements[shapeIndex].clip * vec4(scaling, scaling) + vec4(0.5, 0.5, 0.5, 0.5)) * subPixelFactor));\n"
|
||||
"\n"
|
||||
" mat3 uvTransform = mat3(shapeBuffer.elements[shapeIndex].uvTransform[0],\n"
|
||||
" shapeBuffer.elements[shapeIndex].uvTransform[3],\n"
|
||||
" 0.,\n"
|
||||
" shapeBuffer.elements[shapeIndex].uvTransform[1],\n"
|
||||
" shapeBuffer.elements[shapeIndex].uvTransform[4],\n"
|
||||
" 0.,\n"
|
||||
" shapeBuffer.elements[shapeIndex].uvTransform[2],\n"
|
||||
" shapeBuffer.elements[shapeIndex].uvTransform[5],\n"
|
||||
" 1.);\n"
|
||||
"\n"
|
||||
" //NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge\n"
|
||||
" int cw = is_clockwise(p0, p1, p2);\n"
|
||||
" if(cw < 0)\n"
|
||||
|
@ -417,7 +431,15 @@ const char* glsl_draw =
|
|||
" {\n"
|
||||
" sampleColor[sampleIndex] = currentColor[sampleIndex];\n"
|
||||
" }\n"
|
||||
" currentColor[sampleIndex] = sampleColor[sampleIndex]*(1.-color.a) + color.a*color;\n"
|
||||
"\n"
|
||||
" vec4 nextColor = color;\n"
|
||||
" if(useTexture)\n"
|
||||
" {\n"
|
||||
" vec3 sampleFP = vec3(vec2(samplePoint).xy/(subPixelFactor*2.), 1);\n"
|
||||
" vec2 uv = (uvTransform * sampleFP).xy;\n"
|
||||
" nextColor *= texture(srcTexture, uv);\n"
|
||||
" }\n"
|
||||
" currentColor[sampleIndex] = sampleColor[sampleIndex]*(1.-nextColor.a) + nextColor.a*nextColor;\n"
|
||||
" currentShapeIndex[sampleIndex] = shapeIndex;\n"
|
||||
" flipCount[sampleIndex] = 1;\n"
|
||||
" }\n"
|
||||
|
|
|
@ -10,5 +10,5 @@ struct vertex {
|
|||
struct shape {
|
||||
vec4 color;
|
||||
vec4 clip;
|
||||
vec2 uv;
|
||||
float uvTransform[6];
|
||||
};
|
||||
|
|
|
@ -30,9 +30,13 @@ layout(location = 1) uniform uvec2 tileCount;
|
|||
layout(location = 2) uniform uint tileSize;
|
||||
layout(location = 3) uniform uint tileArraySize;
|
||||
layout(location = 4) uniform vec2 scaling;
|
||||
layout(location = 5) uniform uint useTexture;
|
||||
|
||||
layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;
|
||||
|
||||
layout(binding = 1) uniform sampler2D srcTexture;
|
||||
|
||||
|
||||
bool is_top_left(ivec2 a, ivec2 b)
|
||||
{
|
||||
return( (a.y == b.y && b.x < a.x)
|
||||
|
@ -140,6 +144,16 @@ void main()
|
|||
vec4 color = shapeBuffer.elements[shapeIndex].color;
|
||||
ivec4 clip = ivec4(round((shapeBuffer.elements[shapeIndex].clip * vec4(scaling, scaling) + vec4(0.5, 0.5, 0.5, 0.5)) * subPixelFactor));
|
||||
|
||||
mat3 uvTransform = mat3(shapeBuffer.elements[shapeIndex].uvTransform[0],
|
||||
shapeBuffer.elements[shapeIndex].uvTransform[3],
|
||||
0.,
|
||||
shapeBuffer.elements[shapeIndex].uvTransform[1],
|
||||
shapeBuffer.elements[shapeIndex].uvTransform[4],
|
||||
0.,
|
||||
shapeBuffer.elements[shapeIndex].uvTransform[2],
|
||||
shapeBuffer.elements[shapeIndex].uvTransform[5],
|
||||
1.);
|
||||
|
||||
//NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge
|
||||
int cw = is_clockwise(p0, p1, p2);
|
||||
if(cw < 0)
|
||||
|
@ -194,7 +208,15 @@ void main()
|
|||
{
|
||||
sampleColor[sampleIndex] = currentColor[sampleIndex];
|
||||
}
|
||||
currentColor[sampleIndex] = sampleColor[sampleIndex]*(1.-color.a) + color.a*color;
|
||||
|
||||
vec4 nextColor = color;
|
||||
if(useTexture)
|
||||
{
|
||||
vec3 sampleFP = vec3(vec2(samplePoint).xy/(subPixelFactor*2.), 1);
|
||||
vec2 uv = (uvTransform * sampleFP).xy;
|
||||
nextColor *= texture(srcTexture, uv);
|
||||
}
|
||||
currentColor[sampleIndex] = sampleColor[sampleIndex]*(1.-nextColor.a) + nextColor.a*nextColor;
|
||||
currentShapeIndex[sampleIndex] = shapeIndex;
|
||||
flipCount[sampleIndex] = 1;
|
||||
}
|
||||
|
|
|
@ -2749,6 +2749,9 @@ mg_canvas mg_canvas_create(mg_surface surface)
|
|||
|
||||
canvas = mg_canvas_alloc_handle(canvasData);
|
||||
mg_canvas_set_current(canvas);
|
||||
|
||||
//TODO: move that in mg_canvas_set_current() if needed?
|
||||
mg_surface_prepare(surface);
|
||||
}
|
||||
}
|
||||
return(canvas);
|
||||
|
|
|
@ -94,13 +94,19 @@ typedef void (*mg_canvas_backend_destroy_proc)(mg_canvas_backend* backend);
|
|||
typedef void (*mg_canvas_backend_begin_proc)(mg_canvas_backend* backend);
|
||||
typedef void (*mg_canvas_backend_end_proc)(mg_canvas_backend* backend);
|
||||
typedef void (*mg_canvas_backend_clear_proc)(mg_canvas_backend* backend, mg_color clearColor);
|
||||
typedef void (*mg_canvas_backend_draw_batch_proc)(mg_canvas_backend* backend, mg_image_data* imageData, u32 vertexCount, u32 shapeCount, u32 indexCount);
|
||||
typedef void (*mg_canvas_backend_draw_batch_proc)(mg_canvas_backend* backend,
|
||||
mg_image_data* imageData,
|
||||
u32 vertexCount,
|
||||
u32 shapeCount,
|
||||
u32 indexCount);
|
||||
|
||||
|
||||
typedef void (*mg_canvas_backend_atlas_upload_proc)(mg_canvas_backend* backend, mp_rect rect, u8* bytes);
|
||||
typedef mg_image_data* (*mg_canvas_backend_image_create_proc)(mg_canvas_backend* backend, vec2 size);
|
||||
typedef void (*mg_canvas_backend_image_destroy_proc)(mg_canvas_backend* backend, mg_image_data* image);
|
||||
typedef void (*mg_canvas_backend_image_upload_region_proc)(mg_canvas_backend* backend, mg_image_data* image, mp_rect region, u8* pixels);
|
||||
typedef void (*mg_canvas_backend_image_upload_region_proc)(mg_canvas_backend* backend,
|
||||
mg_image_data* image,
|
||||
mp_rect region,
|
||||
u8* pixels);
|
||||
|
||||
typedef struct mg_canvas_backend
|
||||
{
|
||||
|
@ -115,9 +121,6 @@ typedef struct mg_canvas_backend
|
|||
mg_canvas_backend_image_create_proc imageCreate;
|
||||
mg_canvas_backend_image_destroy_proc imageDestroy;
|
||||
mg_canvas_backend_image_upload_region_proc imageUploadRegion;
|
||||
|
||||
mg_canvas_backend_atlas_upload_proc atlasUpload;
|
||||
|
||||
} mg_canvas_backend;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Reference in New Issue