[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
|
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_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_flush();
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
|
|
@ -39,6 +39,13 @@ typedef struct mg_gl_canvas_backend
|
||||||
|
|
||||||
} mg_gl_canvas_backend;
|
} mg_gl_canvas_backend;
|
||||||
|
|
||||||
|
typedef struct mg_gl_image
|
||||||
|
{
|
||||||
|
mg_image_data interface;
|
||||||
|
|
||||||
|
GLuint textureID;
|
||||||
|
} mg_gl_image;
|
||||||
|
|
||||||
//NOTE: debugger
|
//NOTE: debugger
|
||||||
typedef struct debug_vertex
|
typedef struct debug_vertex
|
||||||
{
|
{
|
||||||
|
@ -66,6 +73,8 @@ enum {
|
||||||
LAYOUT_VEC4_ALIGN = 16,
|
LAYOUT_VEC4_ALIGN = 16,
|
||||||
LAYOUT_INT_SIZE = 4,
|
LAYOUT_INT_SIZE = 4,
|
||||||
LAYOUT_INT_ALIGN = 4,
|
LAYOUT_INT_ALIGN = 4,
|
||||||
|
LAYOUT_MAT2x3_SIZE = sizeof(float)*6,
|
||||||
|
LAYOUT_MAT2x3_ALIGN = 4,
|
||||||
|
|
||||||
LAYOUT_CUBIC_OFFSET = 0,
|
LAYOUT_CUBIC_OFFSET = 0,
|
||||||
LAYOUT_POS_OFFSET = LayoutNext(CUBIC, VEC4, VEC2),
|
LAYOUT_POS_OFFSET = LayoutNext(CUBIC, VEC4, VEC2),
|
||||||
|
@ -75,9 +84,9 @@ enum {
|
||||||
|
|
||||||
LAYOUT_COLOR_OFFSET = 0,
|
LAYOUT_COLOR_OFFSET = 0,
|
||||||
LAYOUT_CLIP_OFFSET = LayoutNext(COLOR, VEC4, VEC4),
|
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_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_BUFFER_LENGTH = 1<<20,
|
||||||
MG_GL_CANVAS_MAX_SHAPE_BUFFER_SIZE = LAYOUT_SHAPE_SIZE * MG_GL_CANVAS_MAX_BUFFER_LENGTH,
|
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,
|
.colorStride = LAYOUT_SHAPE_SIZE,
|
||||||
.clipBuffer = backend->shapeMapping + LAYOUT_CLIP_OFFSET,
|
.clipBuffer = backend->shapeMapping + LAYOUT_CLIP_OFFSET,
|
||||||
.clipStride = LAYOUT_SHAPE_SIZE,
|
.clipStride = LAYOUT_SHAPE_SIZE,
|
||||||
.uvBuffer = backend->shapeMapping + LAYOUT_UV_OFFSET,
|
.uvTransformBuffer = backend->shapeMapping + LAYOUT_UV_TRANSFORM_OFFSET,
|
||||||
.uvStride = LAYOUT_SHAPE_SIZE,
|
.uvTransformStride = LAYOUT_SHAPE_SIZE,
|
||||||
|
|
||||||
.indexBuffer = backend->indexMapping,
|
.indexBuffer = backend->indexMapping,
|
||||||
.indexStride = LAYOUT_INT_SIZE};
|
.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);
|
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;
|
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);
|
glUniform1ui(3, tileArrayLength);
|
||||||
glUniform2f(4, contentsScaling.x, contentsScaling.y);
|
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);
|
glDispatchCompute(tileCountX, tileCountY, 1);
|
||||||
|
|
||||||
//NOTE: now blit out texture to surface
|
//NOTE: now blit out texture to surface
|
||||||
|
@ -248,9 +270,41 @@ void mg_gl_canvas_destroy(mg_canvas_backend* interface)
|
||||||
free(backend);
|
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)
|
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.end = mg_gl_canvas_end;
|
||||||
backend->interface.clear = mg_gl_canvas_clear;
|
backend->interface.clear = mg_gl_canvas_clear;
|
||||||
backend->interface.drawBatch = mg_gl_canvas_draw_batch;
|
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);
|
mg_surface_prepare(surface);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
*
|
*
|
||||||
* file: glsl_shaders.h
|
* file: glsl_shaders.h
|
||||||
* note: string literals auto-generated by embed_text.py
|
* note: string literals auto-generated by embed_text.py
|
||||||
* date: 22/022023
|
* date: 27/022023
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
#ifndef __GLSL_SHADERS_H__
|
#ifndef __GLSL_SHADERS_H__
|
||||||
|
@ -23,7 +23,7 @@ const char* glsl_common =
|
||||||
"struct shape {\n"
|
"struct shape {\n"
|
||||||
" vec4 color;\n"
|
" vec4 color;\n"
|
||||||
" vec4 clip;\n"
|
" vec4 clip;\n"
|
||||||
" vec2 uv;\n"
|
" float uvTransform[6];\n"
|
||||||
"};\n";
|
"};\n";
|
||||||
|
|
||||||
//NOTE: string imported from src\glsl_shaders\blit_vertex.glsl
|
//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 = 2) uniform uint tileSize;\n"
|
||||||
"layout(location = 3) uniform uint tileArraySize;\n"
|
"layout(location = 3) uniform uint tileArraySize;\n"
|
||||||
"layout(location = 4) uniform vec2 scaling;\n"
|
"layout(location = 4) uniform vec2 scaling;\n"
|
||||||
|
"layout(location = 5) uniform uint useTexture;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;\n"
|
"layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"layout(binding = 1) uniform sampler2D srcTexture;\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
"bool is_top_left(ivec2 a, ivec2 b)\n"
|
"bool is_top_left(ivec2 a, ivec2 b)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" return( (a.y == b.y && b.x < a.x)\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"
|
" 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"
|
" ivec4 clip = ivec4(round((shapeBuffer.elements[shapeIndex].clip * vec4(scaling, scaling) + vec4(0.5, 0.5, 0.5, 0.5)) * subPixelFactor));\n"
|
||||||
"\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"
|
" //NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge\n"
|
||||||
" int cw = is_clockwise(p0, p1, p2);\n"
|
" int cw = is_clockwise(p0, p1, p2);\n"
|
||||||
" if(cw < 0)\n"
|
" if(cw < 0)\n"
|
||||||
|
@ -417,7 +431,15 @@ const char* glsl_draw =
|
||||||
" {\n"
|
" {\n"
|
||||||
" sampleColor[sampleIndex] = currentColor[sampleIndex];\n"
|
" sampleColor[sampleIndex] = currentColor[sampleIndex];\n"
|
||||||
" }\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"
|
" currentShapeIndex[sampleIndex] = shapeIndex;\n"
|
||||||
" flipCount[sampleIndex] = 1;\n"
|
" flipCount[sampleIndex] = 1;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
|
|
|
@ -10,5 +10,5 @@ struct vertex {
|
||||||
struct shape {
|
struct shape {
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec4 clip;
|
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 = 2) uniform uint tileSize;
|
||||||
layout(location = 3) uniform uint tileArraySize;
|
layout(location = 3) uniform uint tileArraySize;
|
||||||
layout(location = 4) uniform vec2 scaling;
|
layout(location = 4) uniform vec2 scaling;
|
||||||
|
layout(location = 5) uniform uint useTexture;
|
||||||
|
|
||||||
layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;
|
layout(rgba8, binding = 0) uniform restrict writeonly image2D outTexture;
|
||||||
|
|
||||||
|
layout(binding = 1) uniform sampler2D srcTexture;
|
||||||
|
|
||||||
|
|
||||||
bool is_top_left(ivec2 a, ivec2 b)
|
bool is_top_left(ivec2 a, ivec2 b)
|
||||||
{
|
{
|
||||||
return( (a.y == b.y && b.x < a.x)
|
return( (a.y == b.y && b.x < a.x)
|
||||||
|
@ -140,6 +144,16 @@ void main()
|
||||||
vec4 color = shapeBuffer.elements[shapeIndex].color;
|
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));
|
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
|
//NOTE(martin): reorder triangle counter-clockwise and compute bias for each edge
|
||||||
int cw = is_clockwise(p0, p1, p2);
|
int cw = is_clockwise(p0, p1, p2);
|
||||||
if(cw < 0)
|
if(cw < 0)
|
||||||
|
@ -194,7 +208,15 @@ void main()
|
||||||
{
|
{
|
||||||
sampleColor[sampleIndex] = currentColor[sampleIndex];
|
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;
|
currentShapeIndex[sampleIndex] = shapeIndex;
|
||||||
flipCount[sampleIndex] = 1;
|
flipCount[sampleIndex] = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2749,6 +2749,9 @@ mg_canvas mg_canvas_create(mg_surface surface)
|
||||||
|
|
||||||
canvas = mg_canvas_alloc_handle(canvasData);
|
canvas = mg_canvas_alloc_handle(canvasData);
|
||||||
mg_canvas_set_current(canvas);
|
mg_canvas_set_current(canvas);
|
||||||
|
|
||||||
|
//TODO: move that in mg_canvas_set_current() if needed?
|
||||||
|
mg_surface_prepare(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(canvas);
|
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_begin_proc)(mg_canvas_backend* backend);
|
||||||
typedef void (*mg_canvas_backend_end_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_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 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_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
|
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_create_proc imageCreate;
|
||||||
mg_canvas_backend_image_destroy_proc imageDestroy;
|
mg_canvas_backend_image_destroy_proc imageDestroy;
|
||||||
mg_canvas_backend_image_upload_region_proc imageUploadRegion;
|
mg_canvas_backend_image_upload_region_proc imageUploadRegion;
|
||||||
|
|
||||||
mg_canvas_backend_atlas_upload_proc atlasUpload;
|
|
||||||
|
|
||||||
} mg_canvas_backend;
|
} mg_canvas_backend;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
Loading…
Reference in New Issue