[canvas] decompose image atlas API into simple rect atlas API + image atlas helpers. This avoids creating a bunch of new types/handles, and exposes the underlying image/sourceRegion so that user code can freely use these for more complex scenarios (eg drawing only a sub-region of an atlased image, or using an atlas image for arbitrary path filling)
This commit is contained in:
parent
d4bceba7e9
commit
3615775168
|
@ -42,12 +42,17 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: create atlas
|
//NOTE: create atlas
|
||||||
|
mem_arena permanentArena = {0};
|
||||||
|
mem_arena_init(&permanentArena);
|
||||||
|
|
||||||
|
mg_rect_atlas* atlas = mg_rect_atlas_create(&permanentArena, 16000, 16000);
|
||||||
|
mg_image atlasImage = mg_image_create(16000, 16000);
|
||||||
|
|
||||||
str8 path1 = mp_app_get_resource_path(mem_scratch(), "../resources/triceratops.png");
|
str8 path1 = mp_app_get_resource_path(mem_scratch(), "../resources/triceratops.png");
|
||||||
str8 path2 = mp_app_get_resource_path(mem_scratch(), "../resources/Top512.png");
|
str8 path2 = mp_app_get_resource_path(mem_scratch(), "../resources/Top512.png");
|
||||||
|
|
||||||
mg_image_atlas atlas = mg_image_atlas_create(16000, 16000);
|
mg_image_region image1 = mg_image_atlas_alloc_from_file(atlas, atlasImage, path1, true);
|
||||||
mg_image image1 = mg_image_upload_from_file(atlas, path1, true);
|
mg_image_region image2 = mg_image_atlas_alloc_from_file(atlas, atlasImage, path2, true);
|
||||||
mg_image image2 = mg_image_upload_from_file(atlas, path2, true);
|
|
||||||
|
|
||||||
// start app
|
// start app
|
||||||
mp_window_bring_to_front(window);
|
mp_window_bring_to_front(window);
|
||||||
|
@ -78,8 +83,8 @@ int main()
|
||||||
|
|
||||||
mg_set_color_rgba(1, 1, 1, 1);
|
mg_set_color_rgba(1, 1, 1, 1);
|
||||||
|
|
||||||
mg_image_draw(image1, (mp_rect){100, 100, 300, 300});
|
mg_image_draw_region(image1.image, image1.rect, (mp_rect){100, 100, 300, 300});
|
||||||
mg_image_draw(image2, (mp_rect){300, 200, 300, 300});
|
mg_image_draw_region(image2.image, image2.rect, (mp_rect){300, 200, 300, 300});
|
||||||
|
|
||||||
mg_flush();
|
mg_flush();
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
@ -87,9 +92,9 @@ int main()
|
||||||
mem_arena_clear(mem_scratch());
|
mem_arena_clear(mem_scratch());
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_image_recycle(image1);
|
mg_image_atlas_recycle(atlas, image1);
|
||||||
mg_image_recycle(image2);
|
mg_image_atlas_recycle(atlas, image2);
|
||||||
mg_image_atlas_destroy(atlas);
|
|
||||||
mg_canvas_destroy(canvas);
|
mg_canvas_destroy(canvas);
|
||||||
mg_surface_destroy(surface);
|
mg_surface_destroy(surface);
|
||||||
mp_window_destroy(window);
|
mp_window_destroy(window);
|
||||||
|
|
|
@ -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_texture.exe
|
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_image.exe
|
|
@ -8,4 +8,4 @@ INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
LIBS="-L$BINDIR -lmilepost"
|
LIBS="-L$BINDIR -lmilepost"
|
||||||
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||||
|
|
||||||
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_texture main.c
|
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_image main.c
|
|
@ -41,14 +41,14 @@ int main()
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: create texture
|
//NOTE: create image
|
||||||
str8 texturePath = mp_app_get_resource_path(mem_scratch(), "../resources/triceratops.png");
|
str8 imagePath = mp_app_get_resource_path(mem_scratch(), "../resources/triceratops.png");
|
||||||
mg_texture texture = mg_texture_create_from_file(texturePath, true);
|
mg_image image = mg_image_create_from_file(imagePath, true);
|
||||||
vec2 textureSize = mg_texture_size(texture);
|
vec2 imageSize = mg_image_size(image);
|
||||||
|
|
||||||
str8 texturePath2 = mp_app_get_resource_path(mem_scratch(), "../resources/Top512.png");
|
str8 imagePath2 = mp_app_get_resource_path(mem_scratch(), "../resources/Top512.png");
|
||||||
mg_texture texture2 = mg_texture_create_from_file(texturePath2, true);
|
mg_image image2 = mg_image_create_from_file(imagePath2, true);
|
||||||
vec2 textureSize2 = mg_texture_size(texture2);
|
vec2 imageSize2 = mg_image_size(image2);
|
||||||
|
|
||||||
// start app
|
// start app
|
||||||
mp_window_bring_to_front(window);
|
mp_window_bring_to_front(window);
|
||||||
|
@ -82,8 +82,8 @@ int main()
|
||||||
mg_matrix_push((mg_mat2x3){0.707, -0.707, 200,
|
mg_matrix_push((mg_mat2x3){0.707, -0.707, 200,
|
||||||
0.707, 0.707, 100});
|
0.707, 0.707, 100});
|
||||||
|
|
||||||
mg_set_texture(texture);
|
mg_set_image(image);
|
||||||
mg_set_texture_source_region((mp_rect){500, 500, 2000, 1400});
|
mg_set_image_source_region((mp_rect){500, 500, 2000, 1400});
|
||||||
|
|
||||||
mg_move_to(0, 0);
|
mg_move_to(0, 0);
|
||||||
mg_line_to(200, 0);
|
mg_line_to(200, 0);
|
||||||
|
@ -95,7 +95,7 @@ int main()
|
||||||
|
|
||||||
mg_matrix_pop();
|
mg_matrix_pop();
|
||||||
|
|
||||||
mg_texture_draw(texture2, (mp_rect){300, 200, 300, 300});
|
mg_image_draw(image2, (mp_rect){300, 200, 300, 300});
|
||||||
|
|
||||||
mg_flush();
|
mg_flush();
|
||||||
mg_surface_present(surface);
|
mg_surface_present(surface);
|
||||||
|
@ -103,7 +103,7 @@ int main()
|
||||||
mem_arena_clear(mem_scratch());
|
mem_arena_clear(mem_scratch());
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_texture_destroy(texture);
|
mg_image_destroy(image);
|
||||||
mg_canvas_destroy(canvas);
|
mg_canvas_destroy(canvas);
|
||||||
mg_surface_destroy(surface);
|
mg_surface_destroy(surface);
|
||||||
mp_window_destroy(window);
|
mp_window_destroy(window);
|
|
@ -39,12 +39,12 @@ typedef struct mg_gl_canvas_backend
|
||||||
|
|
||||||
} mg_gl_canvas_backend;
|
} mg_gl_canvas_backend;
|
||||||
|
|
||||||
typedef struct mg_gl_texture
|
typedef struct mg_gl_image
|
||||||
{
|
{
|
||||||
mg_texture_data interface;
|
mg_image_data interface;
|
||||||
|
|
||||||
GLuint textureID;
|
GLuint textureID;
|
||||||
} mg_gl_texture;
|
} mg_gl_image;
|
||||||
|
|
||||||
//NOTE: debugger
|
//NOTE: debugger
|
||||||
typedef struct debug_vertex
|
typedef struct debug_vertex
|
||||||
|
@ -156,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, mg_texture_data* textureInterface, 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;
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, mg_texture_data* text
|
||||||
//NOTE: then we fire the drawing shader that will select only triangles in its tile
|
//NOTE: then we fire the drawing shader that will select only triangles in its tile
|
||||||
glUseProgram(backend->drawProgram);
|
glUseProgram(backend->drawProgram);
|
||||||
|
|
||||||
glBindTextureTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
|
glBindImageTexture(0, backend->outTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
|
||||||
|
|
||||||
glUniform1ui(0, indexCount);
|
glUniform1ui(0, indexCount);
|
||||||
glUniform2ui(1, tileCountX, tileCountY);
|
glUniform2ui(1, tileCountX, tileCountY);
|
||||||
|
@ -222,12 +222,12 @@ void mg_gl_canvas_draw_batch(mg_canvas_backend* interface, mg_texture_data* text
|
||||||
glUniform1ui(3, tileArrayLength);
|
glUniform1ui(3, tileArrayLength);
|
||||||
glUniform2f(4, contentsScaling.x, contentsScaling.y);
|
glUniform2f(4, contentsScaling.x, contentsScaling.y);
|
||||||
|
|
||||||
if(textureInterface)
|
if(imageInterface)
|
||||||
{
|
{
|
||||||
//TODO: make sure this texture belongs to that context
|
//TODO: make sure this image belongs to that context
|
||||||
mg_gl_texture* texture = (mg_gl_texture*)textureInterface;
|
mg_gl_image* image = (mg_gl_image*)imageInterface;
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->textureID);
|
glBindTexture(GL_TEXTURE_2D, image->textureID);
|
||||||
glUniform1ui(5, 1);
|
glUniform1ui(5, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -270,41 +270,41 @@ void mg_gl_canvas_destroy(mg_canvas_backend* interface)
|
||||||
free(backend);
|
free(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_texture_data* mg_gl_canvas_texture_create(mg_canvas_backend* interface, vec2 size)
|
mg_image_data* mg_gl_canvas_image_create(mg_canvas_backend* interface, vec2 size)
|
||||||
{
|
{
|
||||||
mg_gl_texture* texture = 0;
|
mg_gl_image* image = 0;
|
||||||
|
|
||||||
texture = malloc_type(mg_gl_texture);
|
image = malloc_type(mg_gl_image);
|
||||||
if(texture)
|
if(image)
|
||||||
{
|
{
|
||||||
glGenTextures(1, &texture->textureID);
|
glGenTextures(1, &image->textureID);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->textureID);
|
glBindTexture(GL_TEXTURE_2D, image->textureID);
|
||||||
// glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, size.x, size.y);
|
// 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_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
texture->interface.size = size;
|
image->interface.size = size;
|
||||||
}
|
}
|
||||||
return((mg_texture_data*)texture);
|
return((mg_image_data*)image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_gl_canvas_texture_destroy(mg_canvas_backend* interface, mg_texture_data* textureInterface)
|
void mg_gl_canvas_image_destroy(mg_canvas_backend* interface, mg_image_data* imageInterface)
|
||||||
{
|
{
|
||||||
//TODO: check that this texture belongs to this context
|
//TODO: check that this image belongs to this context
|
||||||
mg_gl_texture* texture = (mg_gl_texture*)textureInterface;
|
mg_gl_image* image = (mg_gl_image*)imageInterface;
|
||||||
glDeleteTextures(1, &texture->textureID);
|
glDeleteTextures(1, &image->textureID);
|
||||||
free(texture);
|
free(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_gl_canvas_texture_upload_region(mg_canvas_backend* interface,
|
void mg_gl_canvas_image_upload_region(mg_canvas_backend* interface,
|
||||||
mg_texture_data* textureInterface,
|
mg_image_data* imageInterface,
|
||||||
mp_rect region,
|
mp_rect region,
|
||||||
u8* pixels)
|
u8* pixels)
|
||||||
{
|
{
|
||||||
//TODO: check that this texture belongs to this context
|
//TODO: check that this image belongs to this context
|
||||||
mg_gl_texture* texture = (mg_gl_texture*)textureInterface;
|
mg_gl_image* image = (mg_gl_image*)imageInterface;
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->textureID);
|
glBindTexture(GL_TEXTURE_2D, image->textureID);
|
||||||
glTexTexture2D(GL_TEXTURE_2D, 0, GL_RGBA8, region.w, region.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
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)
|
||||||
|
@ -429,9 +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.textureCreate = mg_gl_canvas_texture_create;
|
backend->interface.imageCreate = mg_gl_canvas_image_create;
|
||||||
backend->interface.textureDestroy = mg_gl_canvas_texture_destroy;
|
backend->interface.imageDestroy = mg_gl_canvas_image_destroy;
|
||||||
backend->interface.textureUploadRegion = mg_gl_canvas_texture_upload_region;
|
backend->interface.imageUploadRegion = mg_gl_canvas_image_upload_region;
|
||||||
|
|
||||||
mg_surface_prepare(surface);
|
mg_surface_prepare(surface);
|
||||||
|
|
||||||
|
|
290
src/graphics.c
290
src/graphics.c
|
@ -56,7 +56,7 @@ typedef struct mg_attributes
|
||||||
mg_font font;
|
mg_font font;
|
||||||
f32 fontSize;
|
f32 fontSize;
|
||||||
|
|
||||||
mg_texture texture;
|
mg_image image;
|
||||||
mp_rect srcRegion;
|
mp_rect srcRegion;
|
||||||
|
|
||||||
mg_mat2x3 transform;
|
mg_mat2x3 transform;
|
||||||
|
@ -123,7 +123,7 @@ typedef struct mg_glyph_data
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
MG_STREAM_MAX_COUNT = 128,
|
MG_STREAM_MAX_COUNT = 128,
|
||||||
MG_TEXTURE_MAX_COUNT = 128
|
MG_IMAGE_MAX_COUNT = 128
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -153,7 +153,6 @@ typedef struct mg_font_data
|
||||||
|
|
||||||
typedef struct mg_canvas_data mg_canvas_data;
|
typedef struct mg_canvas_data mg_canvas_data;
|
||||||
typedef struct mg_image_data mg_image_data;
|
typedef struct mg_image_data mg_image_data;
|
||||||
typedef struct mg_image_atlas_data mg_image_atlas_data;
|
|
||||||
|
|
||||||
typedef struct mg_resource_slot
|
typedef struct mg_resource_slot
|
||||||
{
|
{
|
||||||
|
@ -162,9 +161,7 @@ typedef struct mg_resource_slot
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
mg_surface_data* surface;
|
mg_surface_data* surface;
|
||||||
mg_texture_data* texture;
|
|
||||||
mg_image_data* image;
|
mg_image_data* image;
|
||||||
mg_image_atlas_data* atlas;
|
|
||||||
mg_canvas_data* canvas;
|
mg_canvas_data* canvas;
|
||||||
mg_font_data* font;
|
mg_font_data* font;
|
||||||
//...
|
//...
|
||||||
|
@ -221,8 +218,6 @@ typedef struct mg_canvas_data
|
||||||
u32 primitiveCount;
|
u32 primitiveCount;
|
||||||
mg_primitive primitives[MG_MAX_PRIMITIVE_COUNT];
|
mg_primitive primitives[MG_MAX_PRIMITIVE_COUNT];
|
||||||
|
|
||||||
mg_resource_pool texturePool;
|
|
||||||
mg_resource_pool imageAtlasPool;
|
|
||||||
mg_resource_pool imagePool;
|
mg_resource_pool imagePool;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -234,7 +229,7 @@ typedef struct mg_canvas_data
|
||||||
//NOTE: these are used at render time
|
//NOTE: these are used at render time
|
||||||
mp_rect clip;
|
mp_rect clip;
|
||||||
mg_mat2x3 transform;
|
mg_mat2x3 transform;
|
||||||
mg_texture texture;
|
mg_image image;
|
||||||
mp_rect srcRegion;
|
mp_rect srcRegion;
|
||||||
|
|
||||||
vec4 shapeExtents;
|
vec4 shapeExtents;
|
||||||
|
@ -395,33 +390,33 @@ mg_canvas_data* mg_canvas_data_from_handle(mg_canvas canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// texture handles
|
// image handles
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
|
||||||
mg_texture mg_texture_nil() { return((mg_texture){.h = 0}); }
|
mg_image mg_image_nil() { return((mg_image){.h = 0}); }
|
||||||
bool mg_texture_is_nil(mg_texture texture) { return(texture.h == 0); }
|
bool mg_image_is_nil(mg_image image) { return(image.h == 0); }
|
||||||
|
|
||||||
mg_texture mg_texture_alloc_handle(mg_canvas_data* canvas, mg_texture_data* texture)
|
mg_image mg_image_alloc_handle(mg_canvas_data* canvas, mg_image_data* image)
|
||||||
{
|
{
|
||||||
mg_resource_slot* slot = mg_resource_slot_alloc(&canvas->texturePool);
|
mg_resource_slot* slot = mg_resource_slot_alloc(&canvas->imagePool);
|
||||||
if(!slot)
|
if(!slot)
|
||||||
{
|
{
|
||||||
LOG_ERROR("no more canvas slots\n");
|
LOG_ERROR("no more canvas slots\n");
|
||||||
return(mg_texture_nil());
|
return(mg_image_nil());
|
||||||
}
|
}
|
||||||
slot->texture = texture;
|
slot->image = image;
|
||||||
u64 h = mg_resource_handle_from_slot(&canvas->texturePool, slot);
|
u64 h = mg_resource_handle_from_slot(&canvas->imagePool, slot);
|
||||||
mg_texture handle = {h};
|
mg_image handle = {h};
|
||||||
return(handle);
|
return(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_texture_data* mg_texture_data_from_handle(mg_canvas_data* canvas, mg_texture handle)
|
mg_image_data* mg_image_data_from_handle(mg_canvas_data* canvas, mg_image handle)
|
||||||
{
|
{
|
||||||
mg_texture_data* data = 0;
|
mg_image_data* data = 0;
|
||||||
mg_resource_slot* slot = mg_resource_slot_from_handle(&canvas->texturePool, handle.h);
|
mg_resource_slot* slot = mg_resource_slot_from_handle(&canvas->imagePool, handle.h);
|
||||||
if(slot)
|
if(slot)
|
||||||
{
|
{
|
||||||
data = slot->texture;
|
data = slot->image;
|
||||||
}
|
}
|
||||||
return(data);
|
return(data);
|
||||||
}
|
}
|
||||||
|
@ -775,7 +770,7 @@ void mg_finalize_shape(mg_canvas_data* canvas)
|
||||||
if(canvas->nextShapeIndex)
|
if(canvas->nextShapeIndex)
|
||||||
{
|
{
|
||||||
//NOTE: set shape's uv transform for the _current_ shape
|
//NOTE: set shape's uv transform for the _current_ shape
|
||||||
vec2 texSize = mg_texture_size(canvas->texture);
|
vec2 texSize = mg_image_size(canvas->image);
|
||||||
|
|
||||||
mp_rect srcRegion = canvas->srcRegion;
|
mp_rect srcRegion = canvas->srcRegion;
|
||||||
|
|
||||||
|
@ -784,7 +779,7 @@ void mg_finalize_shape(mg_canvas_data* canvas)
|
||||||
canvas->shapeExtents.z - canvas->shapeExtents.x,
|
canvas->shapeExtents.z - canvas->shapeExtents.x,
|
||||||
canvas->shapeExtents.w - canvas->shapeExtents.y};
|
canvas->shapeExtents.w - canvas->shapeExtents.y};
|
||||||
|
|
||||||
mg_mat2x3 srcRegionToTexture = {1/texSize.x, 0, srcRegion.x/texSize.x,
|
mg_mat2x3 srcRegionToImage = {1/texSize.x, 0, srcRegion.x/texSize.x,
|
||||||
0, 1/texSize.y, srcRegion.y/texSize.y};
|
0, 1/texSize.y, srcRegion.y/texSize.y};
|
||||||
mg_mat2x3 destRegionToSrcRegion = {srcRegion.w/destRegion.w, 0, 0,
|
mg_mat2x3 destRegionToSrcRegion = {srcRegion.w/destRegion.w, 0, 0,
|
||||||
0, srcRegion.h/destRegion.h, 0};
|
0, srcRegion.h/destRegion.h, 0};
|
||||||
|
@ -793,7 +788,7 @@ void mg_finalize_shape(mg_canvas_data* canvas)
|
||||||
|
|
||||||
mg_mat2x3 screenToUser = mg_mat2x3_inv(canvas->transform);
|
mg_mat2x3 screenToUser = mg_mat2x3_inv(canvas->transform);
|
||||||
|
|
||||||
mg_mat2x3 uvTransform = srcRegionToTexture;
|
mg_mat2x3 uvTransform = srcRegionToImage;
|
||||||
uvTransform = mg_mat2x3_mul_m(uvTransform, destRegionToSrcRegion);
|
uvTransform = mg_mat2x3_mul_m(uvTransform, destRegionToSrcRegion);
|
||||||
uvTransform = mg_mat2x3_mul_m(uvTransform, userToDestRegion);
|
uvTransform = mg_mat2x3_mul_m(uvTransform, userToDestRegion);
|
||||||
uvTransform = mg_mat2x3_mul_m(uvTransform, screenToUser);
|
uvTransform = mg_mat2x3_mul_m(uvTransform, screenToUser);
|
||||||
|
@ -1038,7 +1033,7 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4])
|
||||||
| 0 -sl^3 -sm^3 0 |
|
| 0 -sl^3 -sm^3 0 |
|
||||||
|
|
||||||
This matrix is then multiplied by M3^(-1) on the left which yelds the bezier coefficients of k, l, m, n
|
This matrix is then multiplied by M3^(-1) on the left which yelds the bezier coefficients of k, l, m, n
|
||||||
which are assigned as a 4D texture coordinates to control points.
|
which are assigned as a 4D image coordinates to control points.
|
||||||
|
|
||||||
|
|
||||||
| 1 0 0 0 |
|
| 1 0 0 0 |
|
||||||
|
@ -1101,7 +1096,7 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4])
|
||||||
| 0 -sd^2*se -sd*se^2 0 |
|
| 0 -sd^2*se -sd*se^2 0 |
|
||||||
|
|
||||||
This matrix is then multiplied by M3^(-1) on the left which yelds the bezier coefficients of k, l, m, n
|
This matrix is then multiplied by M3^(-1) on the left which yelds the bezier coefficients of k, l, m, n
|
||||||
which are assigned as a 4D texture coordinates to control points.
|
which are assigned as a 4D image coordinates to control points.
|
||||||
|
|
||||||
|
|
||||||
| 1 0 0 0 |
|
| 1 0 0 0 |
|
||||||
|
@ -1142,7 +1137,7 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4])
|
||||||
| 0 -sl^3 0 0 |
|
| 0 -sl^3 0 0 |
|
||||||
|
|
||||||
This matrix is then multiplied by M3^(-1) on the left which yelds the bezier coefficients of k, l, m, n
|
This matrix is then multiplied by M3^(-1) on the left which yelds the bezier coefficients of k, l, m, n
|
||||||
which are assigned as a 4D texture coordinates to control points.
|
which are assigned as a 4D image coordinates to control points.
|
||||||
|
|
||||||
|
|
||||||
| 1 0 0 0 |
|
| 1 0 0 0 |
|
||||||
|
@ -2859,13 +2854,13 @@ void mg_do_clip_push(mg_canvas_data* canvas, mp_rect clip)
|
||||||
mg_clip_stack_push(canvas, r);
|
mg_clip_stack_push(canvas, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_draw_batch(mg_canvas_data* canvas, mg_texture_data* texture)
|
void mg_draw_batch(mg_canvas_data* canvas, mg_image_data* image)
|
||||||
{
|
{
|
||||||
mg_finalize_shape(canvas);
|
mg_finalize_shape(canvas);
|
||||||
|
|
||||||
if(canvas->backend && canvas->backend->drawBatch && canvas->indexCount)
|
if(canvas->backend && canvas->backend->drawBatch && canvas->indexCount)
|
||||||
{
|
{
|
||||||
canvas->backend->drawBatch(canvas->backend, texture, canvas->nextShapeIndex, canvas->vertexCount, canvas->indexCount);
|
canvas->backend->drawBatch(canvas->backend, image, canvas->nextShapeIndex, canvas->vertexCount, canvas->indexCount);
|
||||||
}
|
}
|
||||||
mg_reset_shape_index(canvas);
|
mg_reset_shape_index(canvas);
|
||||||
|
|
||||||
|
@ -2889,7 +2884,7 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
|
||||||
|
|
||||||
canvas->clip = (mp_rect){-FLT_MAX/2, -FLT_MAX/2, FLT_MAX, FLT_MAX};
|
canvas->clip = (mp_rect){-FLT_MAX/2, -FLT_MAX/2, FLT_MAX, FLT_MAX};
|
||||||
|
|
||||||
canvas->texture = mg_texture_nil();
|
canvas->image = mg_image_nil();
|
||||||
|
|
||||||
canvas->backend->begin(canvas->backend);
|
canvas->backend->begin(canvas->backend);
|
||||||
|
|
||||||
|
@ -2903,11 +2898,11 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
|
||||||
mg_primitive* primitive = &(primitives[nextIndex]);
|
mg_primitive* primitive = &(primitives[nextIndex]);
|
||||||
nextIndex++;
|
nextIndex++;
|
||||||
|
|
||||||
if(i && primitive->attributes.texture.h != canvas->texture.h)
|
if(i && primitive->attributes.image.h != canvas->image.h)
|
||||||
{
|
{
|
||||||
mg_texture_data* textureData = mg_texture_data_from_handle(canvas, canvas->texture);
|
mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->image);
|
||||||
mg_draw_batch(canvas, textureData);
|
mg_draw_batch(canvas, imageData);
|
||||||
canvas->texture = primitive->attributes.texture;
|
canvas->image = primitive->attributes.image;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(primitive->cmd)
|
switch(primitive->cmd)
|
||||||
|
@ -2996,8 +2991,8 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
|
||||||
}
|
}
|
||||||
exit_command_loop: ;
|
exit_command_loop: ;
|
||||||
|
|
||||||
mg_texture_data* textureData = mg_texture_data_from_handle(canvas, canvas->texture);
|
mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->image);
|
||||||
mg_draw_batch(canvas, textureData);
|
mg_draw_batch(canvas, imageData);
|
||||||
|
|
||||||
canvas->backend->end(canvas->backend);
|
canvas->backend->end(canvas->backend);
|
||||||
|
|
||||||
|
@ -3154,18 +3149,18 @@ void mg_set_text_flip(bool flip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_set_texture(mg_texture texture)
|
void mg_set_image(mg_image image)
|
||||||
{
|
{
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
canvas->attributes.texture = texture;
|
canvas->attributes.image = image;
|
||||||
vec2 size = mg_texture_size(texture);
|
vec2 size = mg_image_size(image);
|
||||||
canvas->attributes.srcRegion = (mp_rect){0, 0, size.x, size.y};
|
canvas->attributes.srcRegion = (mp_rect){0, 0, size.x, size.y};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_set_texture_source_region(mp_rect region)
|
void mg_set_image_source_region(mp_rect region)
|
||||||
{
|
{
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
if(canvas)
|
if(canvas)
|
||||||
|
@ -3634,37 +3629,37 @@ void mg_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle)
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): textures
|
//NOTE(martin): images
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
mg_texture mg_texture_create(u32 width, u32 height)
|
mg_image mg_image_create(u32 width, u32 height)
|
||||||
{
|
{
|
||||||
mg_texture texture = mg_texture_nil();
|
mg_image image = mg_image_nil();
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
mg_texture_data* textureData = canvas->backend->textureCreate(canvas->backend, (vec2){width, height});
|
mg_image_data* imageData = canvas->backend->imageCreate(canvas->backend, (vec2){width, height});
|
||||||
if(textureData)
|
if(imageData)
|
||||||
{
|
{
|
||||||
texture = mg_texture_alloc_handle(canvas, textureData);
|
image = mg_image_alloc_handle(canvas, imageData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(texture);
|
return(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_texture mg_texture_create_from_rgba8(u32 width, u32 height, u8* pixels)
|
mg_image mg_image_create_from_rgba8(u32 width, u32 height, u8* pixels)
|
||||||
{
|
{
|
||||||
mg_texture texture = mg_texture_create(width, height);
|
mg_image image = mg_image_create(width, height);
|
||||||
if(!mg_texture_is_nil(texture))
|
if(!mg_image_is_nil(image))
|
||||||
{
|
{
|
||||||
mg_texture_upload_region_rgba8(texture, (mp_rect){0, 0, width, height}, pixels);
|
mg_image_upload_region_rgba8(image, (mp_rect){0, 0, width, height}, pixels);
|
||||||
}
|
}
|
||||||
return(texture);
|
return(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_texture mg_texture_create_from_data(str8 data, bool flip)
|
mg_image mg_image_create_from_data(str8 data, bool flip)
|
||||||
{
|
{
|
||||||
mg_texture texture = mg_texture_nil();
|
mg_image image = mg_image_nil();
|
||||||
int width, height, channels;
|
int width, height, channels;
|
||||||
|
|
||||||
stbi_set_flip_vertically_on_load(flip ? 1 : 0);
|
stbi_set_flip_vertically_on_load(flip ? 1 : 0);
|
||||||
|
@ -3672,15 +3667,15 @@ mg_texture mg_texture_create_from_data(str8 data, bool flip)
|
||||||
|
|
||||||
if(pixels)
|
if(pixels)
|
||||||
{
|
{
|
||||||
texture = mg_texture_create_from_rgba8(width, height, pixels);
|
image = mg_image_create_from_rgba8(width, height, pixels);
|
||||||
free(pixels);
|
free(pixels);
|
||||||
}
|
}
|
||||||
return(texture);
|
return(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_texture mg_texture_create_from_file(str8 path, bool flip)
|
mg_image mg_image_create_from_file(str8 path, bool flip)
|
||||||
{
|
{
|
||||||
mg_texture texture = mg_texture_nil();
|
mg_image image = mg_image_nil();
|
||||||
int width, height, channels;
|
int width, height, channels;
|
||||||
|
|
||||||
const char* cpath = str8_to_cstring(mem_scratch(), path);
|
const char* cpath = str8_to_cstring(mem_scratch(), path);
|
||||||
|
@ -3689,85 +3684,85 @@ mg_texture mg_texture_create_from_file(str8 path, bool flip)
|
||||||
u8* pixels = stbi_load(cpath, &width, &height, &channels, 4);
|
u8* pixels = stbi_load(cpath, &width, &height, &channels, 4);
|
||||||
if(pixels)
|
if(pixels)
|
||||||
{
|
{
|
||||||
texture = mg_texture_create_from_rgba8(width, height, pixels);
|
image = mg_image_create_from_rgba8(width, height, pixels);
|
||||||
free(pixels);
|
free(pixels);
|
||||||
}
|
}
|
||||||
return(texture);
|
return(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_texture_destroy(mg_texture texture)
|
void mg_image_destroy(mg_image image)
|
||||||
{
|
{
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
mg_texture_data* textureData = mg_texture_data_from_handle(canvas, texture);
|
mg_image_data* imageData = mg_image_data_from_handle(canvas, image);
|
||||||
if(textureData)
|
if(imageData)
|
||||||
{
|
{
|
||||||
canvas->backend->textureDestroy(canvas->backend, textureData);
|
canvas->backend->imageDestroy(canvas->backend, imageData);
|
||||||
mg_resource_handle_recycle(&canvas->texturePool, texture.h);
|
mg_resource_handle_recycle(&canvas->imagePool, image.h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_texture_upload_region_rgba8(mg_texture texture, mp_rect region, u8* pixels)
|
void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels)
|
||||||
{
|
{
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
mg_texture_data* textureData = mg_texture_data_from_handle(canvas, texture);
|
mg_image_data* imageData = mg_image_data_from_handle(canvas, image);
|
||||||
if(textureData)
|
if(imageData)
|
||||||
{
|
{
|
||||||
canvas->backend->textureUploadRegion(canvas->backend, textureData, region, pixels);
|
canvas->backend->imageUploadRegion(canvas->backend, imageData, region, pixels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 mg_texture_size(mg_texture texture)
|
vec2 mg_image_size(mg_image image)
|
||||||
{
|
{
|
||||||
vec2 res = {0};
|
vec2 res = {0};
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
mg_texture_data* textureData = mg_texture_data_from_handle(canvas, texture);
|
mg_image_data* imageData = mg_image_data_from_handle(canvas, image);
|
||||||
if(textureData)
|
if(imageData)
|
||||||
{
|
{
|
||||||
res = textureData->size;
|
res = imageData->size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_texture_draw_region(mg_texture texture, mp_rect srcRegion, mp_rect dstRegion)
|
void mg_image_draw_region(mg_image image, mp_rect srcRegion, mp_rect dstRegion)
|
||||||
{
|
{
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
mg_texture oldTexture = canvas->attributes.texture;
|
mg_image oldImage = canvas->attributes.image;
|
||||||
mp_rect oldSrcRegion = canvas->attributes.srcRegion;
|
mp_rect oldSrcRegion = canvas->attributes.srcRegion;
|
||||||
mg_color oldColor = canvas->attributes.color;
|
mg_color oldColor = canvas->attributes.color;
|
||||||
|
|
||||||
canvas->attributes.texture = texture;
|
canvas->attributes.image = image;
|
||||||
canvas->attributes.srcRegion = srcRegion;
|
canvas->attributes.srcRegion = srcRegion;
|
||||||
canvas->attributes.color = (mg_color){1, 1, 1, 1};
|
canvas->attributes.color = (mg_color){1, 1, 1, 1};
|
||||||
|
|
||||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_RECT_FILL, .rect = dstRegion});
|
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_RECT_FILL, .rect = dstRegion});
|
||||||
|
|
||||||
canvas->attributes.texture = oldTexture;
|
canvas->attributes.image = oldImage;
|
||||||
canvas->attributes.srcRegion = oldSrcRegion;
|
canvas->attributes.srcRegion = oldSrcRegion;
|
||||||
canvas->attributes.color = oldColor;
|
canvas->attributes.color = oldColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_texture_draw_region_rounded(mg_texture texture, mp_rect srcRegion, mp_rect dstRegion, f32 roundness)
|
void mg_image_draw_region_rounded(mg_image image, mp_rect srcRegion, mp_rect dstRegion, f32 roundness)
|
||||||
{
|
{
|
||||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
mg_texture oldTexture = canvas->attributes.texture;
|
mg_image oldImage = canvas->attributes.image;
|
||||||
mp_rect oldSrcRegion = canvas->attributes.srcRegion;
|
mp_rect oldSrcRegion = canvas->attributes.srcRegion;
|
||||||
mg_color oldColor = canvas->attributes.color;
|
mg_color oldColor = canvas->attributes.color;
|
||||||
|
|
||||||
canvas->attributes.texture = texture;
|
canvas->attributes.image = image;
|
||||||
canvas->attributes.srcRegion = srcRegion;
|
canvas->attributes.srcRegion = srcRegion;
|
||||||
canvas->attributes.color = (mg_color){1, 1, 1, 1};
|
canvas->attributes.color = (mg_color){1, 1, 1, 1};
|
||||||
|
|
||||||
|
@ -3778,23 +3773,126 @@ void mg_texture_draw_region_rounded(mg_texture texture, mp_rect srcRegion, mp_re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_texture_draw(mg_texture texture, mp_rect rect)
|
void mg_image_draw(mg_image image, mp_rect rect)
|
||||||
{
|
{
|
||||||
vec2 size = mg_texture_size(texture);
|
vec2 size = mg_image_size(image);
|
||||||
mg_texture_draw_region(texture, (mp_rect){0, 0, size.x, size.y}, rect);
|
mg_image_draw_region(image, (mp_rect){0, 0, size.x, size.y}, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_texture_draw_rounded(mg_texture texture, mp_rect rect, f32 roundness)
|
void mg_image_draw_rounded(mg_image image, mp_rect rect, f32 roundness)
|
||||||
{
|
{
|
||||||
vec2 size = mg_texture_size(texture);
|
vec2 size = mg_image_size(image);
|
||||||
mg_texture_draw_region_rounded(texture, (mp_rect){0, 0, size.x, size.y}, rect, roundness);
|
mg_image_draw_region_rounded(image, (mp_rect){0, 0, size.x, size.y}, rect, roundness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
//NOTE(martin): atlasing
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//NOTE: rectangle allocator
|
||||||
|
typedef struct mg_rect_atlas
|
||||||
|
{
|
||||||
|
mem_arena* arena;
|
||||||
|
ivec2 size;
|
||||||
|
ivec2 pos;
|
||||||
|
u32 lineHeight;
|
||||||
|
|
||||||
|
} mg_rect_atlas;
|
||||||
|
|
||||||
|
mg_rect_atlas* mg_rect_atlas_create(mem_arena* arena, i32 width, i32 height)
|
||||||
|
{
|
||||||
|
mg_rect_atlas* atlas = mem_arena_alloc_type(arena, mg_rect_atlas);
|
||||||
|
memset(atlas, 0, sizeof(mg_rect_atlas));
|
||||||
|
atlas->arena = arena;
|
||||||
|
atlas->size = (ivec2){width, height};
|
||||||
|
return(atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_rect mg_rect_atlas_alloc(mg_rect_atlas* atlas, i32 width, i32 height)
|
||||||
|
{
|
||||||
|
mp_rect rect = {0, 0, 0, 0};
|
||||||
|
if(width > 0 && height > 0)
|
||||||
|
{
|
||||||
|
if(atlas->pos.x + width >= atlas->size.x)
|
||||||
|
{
|
||||||
|
atlas->pos.x = 0;
|
||||||
|
atlas->pos.y += (atlas->lineHeight + 1);
|
||||||
|
atlas->lineHeight = 0;
|
||||||
|
}
|
||||||
|
if( atlas->pos.x + width < atlas->size.x
|
||||||
|
&& atlas->pos.y + height < atlas->size.y)
|
||||||
|
{
|
||||||
|
rect = (mp_rect){atlas->pos.x, atlas->pos.y, width, height};
|
||||||
|
|
||||||
|
atlas->pos.x += (width + 1);
|
||||||
|
atlas->lineHeight = maximum(atlas->lineHeight, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_rect_atlas_recycle(mg_rect_atlas* atlas, mp_rect rect)
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_image_region mg_image_atlas_alloc_from_rgba8(mg_rect_atlas* atlas, mg_image backingImage, u32 width, u32 height, u8* pixels)
|
||||||
|
{
|
||||||
|
mg_image_region imageRgn = {0};
|
||||||
|
|
||||||
|
mp_rect rect = mg_rect_atlas_alloc(atlas, width, height);
|
||||||
|
if(rect.w == width && rect.h == height)
|
||||||
|
{
|
||||||
|
mg_image_upload_region_rgba8(backingImage, rect, pixels);
|
||||||
|
imageRgn.rect = rect;
|
||||||
|
imageRgn.image = backingImage;
|
||||||
|
}
|
||||||
|
return(imageRgn);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_image_region mg_image_atlas_alloc_from_data(mg_rect_atlas* atlas, mg_image backingImage, str8 data, bool flip)
|
||||||
|
{
|
||||||
|
mg_image_region imageRgn = {0};
|
||||||
|
|
||||||
|
stbi_set_flip_vertically_on_load(flip ? 1 : 0);
|
||||||
|
|
||||||
|
int width, height, channels;
|
||||||
|
u8* pixels = stbi_load_from_memory((u8*)data.ptr, data.len, &width, &height, &channels, 4);
|
||||||
|
if(pixels)
|
||||||
|
{
|
||||||
|
imageRgn = mg_image_atlas_alloc_from_rgba8(atlas, backingImage, width, height, pixels);
|
||||||
|
free(pixels);
|
||||||
|
}
|
||||||
|
return(imageRgn);
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_image_region mg_image_atlas_alloc_from_file(mg_rect_atlas* atlas, mg_image backingImage, str8 path, bool flip)
|
||||||
|
{
|
||||||
|
mg_image_region imageRgn = {0};
|
||||||
|
|
||||||
|
stbi_set_flip_vertically_on_load(flip ? 1 : 0);
|
||||||
|
|
||||||
|
const char* cpath = str8_to_cstring(mem_scratch(), path);
|
||||||
|
int width, height, channels;
|
||||||
|
u8* pixels = stbi_load(cpath, &width, &height, &channels, 4);
|
||||||
|
if(pixels)
|
||||||
|
{
|
||||||
|
imageRgn = mg_image_atlas_alloc_from_rgba8(atlas, backingImage, width, height, pixels);
|
||||||
|
free(pixels);
|
||||||
|
}
|
||||||
|
return(imageRgn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_image_atlas_recycle(mg_rect_atlas* atlas, mg_image_region imageRgn)
|
||||||
|
{
|
||||||
|
mg_rect_atlas_recycle(atlas, imageRgn.rect);
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): image atlas
|
//NOTE(martin): image atlas
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
mg_image_atlas mg_image_atlas_nil(){ return((mg_image_atlas){.h = 0}); }
|
mg_image_atlas mg_image_atlas_nil(){ return((mg_image_atlas){.h = 0}); }
|
||||||
bool mg_image_atlas_is_nil(mg_image_atlas atlas) { return(atlas.h == 0); }
|
bool mg_image_atlas_is_nil(mg_image_atlas atlas) { return(atlas.h == 0); }
|
||||||
|
|
||||||
|
@ -3804,7 +3902,7 @@ bool mg_image_is_nil(mg_image atlas) { return(atlas.h == 0); }
|
||||||
|
|
||||||
typedef struct mg_image_atlas_data
|
typedef struct mg_image_atlas_data
|
||||||
{
|
{
|
||||||
mg_texture texture;
|
mg_image image;
|
||||||
vec2 pos;
|
vec2 pos;
|
||||||
u32 lineHeight;
|
u32 lineHeight;
|
||||||
|
|
||||||
|
@ -3813,7 +3911,7 @@ typedef struct mg_image_atlas_data
|
||||||
typedef struct mg_image_data
|
typedef struct mg_image_data
|
||||||
{
|
{
|
||||||
mg_image_atlas atlas;
|
mg_image_atlas atlas;
|
||||||
mg_texture texture;
|
mg_image image;
|
||||||
mp_rect rect;
|
mp_rect rect;
|
||||||
|
|
||||||
} mg_image_data;
|
} mg_image_data;
|
||||||
|
@ -3857,7 +3955,7 @@ mg_image_atlas mg_image_atlas_create(u32 width, u32 height)
|
||||||
if(atlas)
|
if(atlas)
|
||||||
{
|
{
|
||||||
memset(atlas, 0, sizeof(mg_image_atlas_data));
|
memset(atlas, 0, sizeof(mg_image_atlas_data));
|
||||||
atlas->texture = mg_texture_create(width, height);
|
atlas->image = mg_image_create(width, height);
|
||||||
|
|
||||||
slot->atlas = atlas;
|
slot->atlas = atlas;
|
||||||
handle.h = mg_resource_handle_from_slot(&canvas->imageAtlasPool, slot);
|
handle.h = mg_resource_handle_from_slot(&canvas->imageAtlasPool, slot);
|
||||||
|
@ -3879,7 +3977,7 @@ void mg_image_atlas_destroy(mg_image_atlas handle)
|
||||||
mg_image_atlas_data* atlas = mg_image_atlas_data_from_handle(canvas, handle);
|
mg_image_atlas_data* atlas = mg_image_atlas_data_from_handle(canvas, handle);
|
||||||
if(atlas)
|
if(atlas)
|
||||||
{
|
{
|
||||||
mg_texture_destroy(atlas->texture);
|
mg_image_destroy(atlas->image);
|
||||||
free(atlas);
|
free(atlas);
|
||||||
mg_resource_handle_recycle(&canvas->imageAtlasPool, handle.h);
|
mg_resource_handle_recycle(&canvas->imageAtlasPool, handle.h);
|
||||||
}
|
}
|
||||||
|
@ -3889,7 +3987,7 @@ void mg_image_atlas_destroy(mg_image_atlas handle)
|
||||||
mp_rect mg_image_atlas_allocate(mg_image_atlas_data* atlas, u32 width, u32 height)
|
mp_rect mg_image_atlas_allocate(mg_image_atlas_data* atlas, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
mp_rect rect = {0, 0, 0, 0};
|
mp_rect rect = {0, 0, 0, 0};
|
||||||
vec2 atlasSize = mg_texture_size(atlas->texture);
|
vec2 atlasSize = mg_image_size(atlas->image);
|
||||||
|
|
||||||
if(atlas->pos.x + width >= atlasSize.x)
|
if(atlas->pos.x + width >= atlasSize.x)
|
||||||
{
|
{
|
||||||
|
@ -3929,10 +4027,10 @@ mg_image mg_image_upload_from_rgba8(mg_image_atlas atlasHandle, u32 width, u32 h
|
||||||
if(rect.w == width && rect.h == height)
|
if(rect.w == width && rect.h == height)
|
||||||
{
|
{
|
||||||
image->rect = rect;
|
image->rect = rect;
|
||||||
image->texture = atlas->texture;
|
image->image = atlas->image;
|
||||||
image->atlas = atlasHandle;
|
image->atlas = atlasHandle;
|
||||||
|
|
||||||
mg_texture_upload_region_rgba8(atlas->texture, rect, pixels);
|
mg_image_upload_region_rgba8(atlas->image, rect, pixels);
|
||||||
|
|
||||||
slot->image = image;
|
slot->image = image;
|
||||||
res.h = mg_resource_handle_from_slot(&canvas->imagePool, slot);
|
res.h = mg_resource_handle_from_slot(&canvas->imagePool, slot);
|
||||||
|
@ -3976,7 +4074,7 @@ void mg_image_draw(mg_image handle, mp_rect rect)
|
||||||
mg_image_data* image = mg_image_data_from_handle(canvas, handle);
|
mg_image_data* image = mg_image_data_from_handle(canvas, handle);
|
||||||
if(image)
|
if(image)
|
||||||
{
|
{
|
||||||
mg_texture_draw_region(image->texture, image->rect, rect);
|
mg_image_draw_region(image->image, image->rect, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4013,7 +4111,7 @@ mg_image mg_image_upload_from_file(mg_image_atlas atlas, str8 path, bool flip)
|
||||||
}
|
}
|
||||||
return(image);
|
return(image);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#undef LOG_SUBSYSTEM
|
#undef LOG_SUBSYSTEM
|
||||||
|
|
|
@ -106,7 +106,7 @@ MP_API void mg_surface_set_hidden(mg_surface surface, bool hidden);
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
typedef struct mg_canvas { u64 h; } mg_canvas;
|
typedef struct mg_canvas { u64 h; } mg_canvas;
|
||||||
typedef struct mg_font { u64 h; } mg_font;
|
typedef struct mg_font { u64 h; } mg_font;
|
||||||
typedef struct mg_texture { u64 h; } mg_texture;
|
typedef struct mg_image { u64 h; } mg_image;
|
||||||
|
|
||||||
typedef struct mg_mat2x3
|
typedef struct mg_mat2x3
|
||||||
{
|
{
|
||||||
|
@ -198,30 +198,53 @@ MP_API mp_rect mg_text_bounding_box_utf32(mg_font font, f32 fontSize, str32 text
|
||||||
MP_API mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text);
|
MP_API mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): textures
|
//NOTE(martin): images
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
MP_API mg_texture mg_texture_nil();
|
MP_API mg_image mg_image_nil();
|
||||||
MP_API bool mg_texture_is_nil(mg_texture a);
|
MP_API bool mg_image_is_nil(mg_image a);
|
||||||
|
|
||||||
MP_API mg_texture mg_texture_create(u32 width, u32 height);
|
MP_API mg_image mg_image_create(u32 width, u32 height);
|
||||||
MP_API mg_texture mg_texture_create_from_rgba8(u32 width, u32 height, u8* pixels);
|
MP_API mg_image mg_image_create_from_rgba8(u32 width, u32 height, u8* pixels);
|
||||||
MP_API mg_texture mg_texture_create_from_data(str8 data, bool flip);
|
MP_API mg_image mg_image_create_from_data(str8 data, bool flip);
|
||||||
MP_API mg_texture mg_texture_create_from_file(str8 path, bool flip);
|
MP_API mg_image mg_image_create_from_file(str8 path, bool flip);
|
||||||
|
|
||||||
MP_API void mg_texture_destroy(mg_texture texture);
|
MP_API void mg_image_destroy(mg_image image);
|
||||||
|
|
||||||
MP_API void mg_texture_upload_region_rgba8(mg_texture texture, mp_rect region, u8* pixels);
|
MP_API void mg_image_upload_region_rgba8(mg_image image, mp_rect region, u8* pixels);
|
||||||
MP_API vec2 mg_texture_size(mg_texture texture);
|
MP_API vec2 mg_image_size(mg_image image);
|
||||||
|
|
||||||
MP_API void mg_texture_draw_region(mg_texture texture, mp_rect srcRegion, mp_rect dstRegion);
|
MP_API void mg_image_draw_region(mg_image image, mp_rect srcRegion, mp_rect dstRegion);
|
||||||
MP_API void mg_texture_draw_region_rounded(mg_texture texture, mp_rect srcRect, mp_rect dstRegion, f32 roundness);
|
MP_API void mg_image_draw_region_rounded(mg_image image, mp_rect srcRect, mp_rect dstRegion, f32 roundness);
|
||||||
MP_API void mg_texture_draw(mg_texture texture, mp_rect rect);
|
MP_API void mg_image_draw(mg_image image, mp_rect rect);
|
||||||
MP_API void mg_texture_draw_rounded(mg_texture texture, mp_rect rect, f32 roundness);
|
MP_API void mg_image_draw_rounded(mg_image image, mp_rect rect, f32 roundness);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
//NOTE(martin): atlasing
|
||||||
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//NOTE: rectangle allocator
|
||||||
|
typedef struct mg_rect_atlas mg_rect_atlas;
|
||||||
|
|
||||||
|
mg_rect_atlas* mg_rect_atlas_create(mem_arena* arena, i32 width, i32 height);
|
||||||
|
mp_rect mg_rect_atlas_alloc(mg_rect_atlas* atlas, i32 width, i32 height);
|
||||||
|
void mg_rect_atlas_recycle(mg_rect_atlas* atlas, mp_rect rect);
|
||||||
|
|
||||||
|
//NOTE: image atlas helpers
|
||||||
|
typedef struct mg_image_region
|
||||||
|
{
|
||||||
|
mg_image image;
|
||||||
|
mp_rect rect;
|
||||||
|
} mg_image_region;
|
||||||
|
|
||||||
|
mg_image_region mg_image_atlas_alloc_from_rgba8(mg_rect_atlas* atlas, mg_image backingImage, u32 width, u32 height, u8* pixels);
|
||||||
|
mg_image_region mg_image_atlas_alloc_from_data(mg_rect_atlas* atlas, mg_image backingImage, str8 data, bool flip);
|
||||||
|
mg_image_region mg_image_atlas_alloc_from_file(mg_rect_atlas* atlas, mg_image backingImage, str8 path, bool flip);
|
||||||
|
void mg_image_atlas_recycle(mg_rect_atlas* atlas, mg_image_region imageRgn);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): image
|
//NOTE(martin): image
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
typedef struct mg_image_atlas { u64 h; } mg_image_atlas;
|
typedef struct mg_image_atlas { u64 h; } mg_image_atlas;
|
||||||
typedef struct mg_image { u64 h; } mg_image;
|
typedef struct mg_image { u64 h; } mg_image;
|
||||||
|
|
||||||
|
@ -235,7 +258,7 @@ MP_API void mg_image_draw(mg_image image, mp_rect rect);
|
||||||
// helpers
|
// helpers
|
||||||
MP_API mg_image mg_image_upload_from_data(mg_image_atlas atlas, str8 data, bool flip);
|
MP_API mg_image mg_image_upload_from_data(mg_image_atlas atlas, str8 data, bool flip);
|
||||||
MP_API mg_image mg_image_upload_from_file(mg_image_atlas atlas, str8 file, bool flip);
|
MP_API mg_image mg_image_upload_from_file(mg_image_atlas atlas, str8 file, bool flip);
|
||||||
|
*/
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): transform, viewport and clipping
|
//NOTE(martin): transform, viewport and clipping
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
@ -260,8 +283,8 @@ MP_API void mg_set_cap(mg_cap_type cap);
|
||||||
MP_API void mg_set_font(mg_font font);
|
MP_API void mg_set_font(mg_font font);
|
||||||
MP_API void mg_set_font_size(f32 size);
|
MP_API void mg_set_font_size(f32 size);
|
||||||
MP_API void mg_set_text_flip(bool flip);
|
MP_API void mg_set_text_flip(bool flip);
|
||||||
MP_API void mg_set_texture(mg_texture texture);
|
MP_API void mg_set_image(mg_image image);
|
||||||
MP_API void mg_set_texture_source_region(mp_rect region);
|
MP_API void mg_set_image_source_region(mp_rect region);
|
||||||
|
|
||||||
MP_API mg_color mg_get_color();
|
MP_API mg_color mg_get_color();
|
||||||
MP_API f32 mg_get_width();
|
MP_API f32 mg_get_width();
|
||||||
|
|
|
@ -52,13 +52,13 @@ mg_surface_data* mg_surface_data_from_handle(mg_surface handle);
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// canvas backend interface
|
// canvas backend interface
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
typedef struct mg_texture_data
|
typedef struct mg_image_data
|
||||||
{
|
{
|
||||||
list_elt listElt;
|
list_elt listElt;
|
||||||
u32 generation;
|
u32 generation;
|
||||||
vec2 size;
|
vec2 size;
|
||||||
|
|
||||||
} mg_texture_data;
|
} mg_image_data;
|
||||||
|
|
||||||
typedef struct mg_vertex_layout
|
typedef struct mg_vertex_layout
|
||||||
{
|
{
|
||||||
|
@ -95,16 +95,16 @@ 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,
|
typedef void (*mg_canvas_backend_draw_batch_proc)(mg_canvas_backend* backend,
|
||||||
mg_texture_data* textureData,
|
mg_image_data* imageData,
|
||||||
u32 vertexCount,
|
u32 vertexCount,
|
||||||
u32 shapeCount,
|
u32 shapeCount,
|
||||||
u32 indexCount);
|
u32 indexCount);
|
||||||
|
|
||||||
|
|
||||||
typedef mg_texture_data* (*mg_canvas_backend_texture_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_texture_destroy_proc)(mg_canvas_backend* backend, mg_texture_data* texture);
|
typedef void (*mg_canvas_backend_image_destroy_proc)(mg_canvas_backend* backend, mg_image_data* image);
|
||||||
typedef void (*mg_canvas_backend_texture_upload_region_proc)(mg_canvas_backend* backend,
|
typedef void (*mg_canvas_backend_image_upload_region_proc)(mg_canvas_backend* backend,
|
||||||
mg_texture_data* texture,
|
mg_image_data* image,
|
||||||
mp_rect region,
|
mp_rect region,
|
||||||
u8* pixels);
|
u8* pixels);
|
||||||
|
|
||||||
|
@ -118,9 +118,9 @@ typedef struct mg_canvas_backend
|
||||||
mg_canvas_backend_clear_proc clear;
|
mg_canvas_backend_clear_proc clear;
|
||||||
mg_canvas_backend_draw_batch_proc drawBatch;
|
mg_canvas_backend_draw_batch_proc drawBatch;
|
||||||
|
|
||||||
mg_canvas_backend_texture_create_proc textureCreate;
|
mg_canvas_backend_image_create_proc imageCreate;
|
||||||
mg_canvas_backend_texture_destroy_proc textureDestroy;
|
mg_canvas_backend_image_destroy_proc imageDestroy;
|
||||||
mg_canvas_backend_texture_upload_region_proc textureUploadRegion;
|
mg_canvas_backend_image_upload_region_proc imageUploadRegion;
|
||||||
} mg_canvas_backend;
|
} mg_canvas_backend;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -51,11 +51,11 @@ typedef struct mg_mtl_canvas_backend
|
||||||
|
|
||||||
} mg_mtl_canvas_backend;
|
} mg_mtl_canvas_backend;
|
||||||
|
|
||||||
typedef struct mg_mtl_texture_data
|
typedef struct mg_mtl_image_data
|
||||||
{
|
{
|
||||||
mg_texture_data interface;
|
mg_image_data interface;
|
||||||
id<MTLTexture> texture;
|
id<MTLTexture> texture;
|
||||||
} mg_mtl_texture_data;
|
} mg_mtl_image_data;
|
||||||
|
|
||||||
|
|
||||||
mg_mtl_surface* mg_mtl_canvas_get_surface(mg_mtl_canvas_backend* canvas)
|
mg_mtl_surface* mg_mtl_canvas_get_surface(mg_mtl_canvas_backend* canvas)
|
||||||
|
@ -139,7 +139,7 @@ void mg_mtl_canvas_clear(mg_canvas_backend* interface, mg_color clearColor)
|
||||||
backend->clearColor = clearColor;
|
backend->clearColor = clearColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_mtl_canvas_draw_batch(mg_canvas_backend* interface, mg_texture_data* texture, u32 shapeCount, u32 vertexCount, u32 indexCount)
|
void mg_mtl_canvas_draw_batch(mg_canvas_backend* interface, mg_image_data* image, u32 shapeCount, u32 vertexCount, u32 indexCount)
|
||||||
{
|
{
|
||||||
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
||||||
mg_mtl_surface* surface = mg_mtl_canvas_get_surface(backend);
|
mg_mtl_surface* surface = mg_mtl_canvas_get_surface(backend);
|
||||||
|
@ -226,10 +226,10 @@ void mg_mtl_canvas_draw_batch(mg_canvas_backend* interface, mg_texture_data* tex
|
||||||
[encoder setComputePipelineState:backend->computePipeline];
|
[encoder setComputePipelineState:backend->computePipeline];
|
||||||
[encoder setTexture: backend->outTexture atIndex: 0];
|
[encoder setTexture: backend->outTexture atIndex: 0];
|
||||||
int useTexture = 0;
|
int useTexture = 0;
|
||||||
if(texture)
|
if(image)
|
||||||
{
|
{
|
||||||
mg_mtl_texture_data* mtlTexture = (mg_mtl_texture_data*)texture;
|
mg_mtl_image_data* mtlImage = (mg_mtl_image_data*)image;
|
||||||
[encoder setTexture: mtlTexture->texture atIndex: 1];
|
[encoder setTexture: mtlImage->texture atIndex: 1];
|
||||||
useTexture = 1;
|
useTexture = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,9 +333,9 @@ void mg_mtl_canvas_destroy(mg_canvas_backend* interface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_texture_data* mg_mtl_canvas_texture_create(mg_canvas_backend* interface, vec2 size)
|
mg_image_data* mg_mtl_canvas_image_create(mg_canvas_backend* interface, vec2 size)
|
||||||
{
|
{
|
||||||
mg_mtl_texture_data* texture = 0;
|
mg_mtl_image_data* image = 0;
|
||||||
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
mg_mtl_canvas_backend* backend = (mg_mtl_canvas_backend*)interface;
|
||||||
mg_mtl_surface* surface = mg_mtl_canvas_get_surface(backend);
|
mg_mtl_surface* surface = mg_mtl_canvas_get_surface(backend);
|
||||||
|
|
||||||
|
@ -343,8 +343,8 @@ mg_texture_data* mg_mtl_canvas_texture_create(mg_canvas_backend* interface, vec2
|
||||||
{
|
{
|
||||||
@autoreleasepool{
|
@autoreleasepool{
|
||||||
|
|
||||||
texture = malloc_type(mg_mtl_texture_data);
|
image = malloc_type(mg_mtl_image_data);
|
||||||
if(texture)
|
if(image)
|
||||||
{
|
{
|
||||||
MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
|
MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
|
||||||
texDesc.textureType = MTLTextureType2D;
|
texDesc.textureType = MTLTextureType2D;
|
||||||
|
@ -354,38 +354,38 @@ mg_texture_data* mg_mtl_canvas_texture_create(mg_canvas_backend* interface, vec2
|
||||||
texDesc.width = size.x;
|
texDesc.width = size.x;
|
||||||
texDesc.height = size.y;
|
texDesc.height = size.y;
|
||||||
|
|
||||||
texture->texture = [surface->device newTextureWithDescriptor:texDesc];
|
image->texture = [surface->device newTextureWithDescriptor:texDesc];
|
||||||
if(texture->texture != nil)
|
if(image->texture != nil)
|
||||||
{
|
{
|
||||||
[texture->texture retain];
|
[image->texture retain];
|
||||||
texture->interface.size = size;
|
image->interface.size = size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
free(texture);
|
free(image);
|
||||||
texture = 0;
|
image = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return((mg_texture_data*)texture);
|
return((mg_image_data*)image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_mtl_canvas_texture_destroy(mg_canvas_backend* backendInterface, mg_texture_data* textureInterface)
|
void mg_mtl_canvas_image_destroy(mg_canvas_backend* backendInterface, mg_image_data* imageInterface)
|
||||||
{
|
{
|
||||||
mg_mtl_texture_data* texture = (mg_mtl_texture_data*)textureInterface;
|
mg_mtl_image_data* image = (mg_mtl_image_data*)imageInterface;
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
[texture->texture release];
|
[image->texture release];
|
||||||
free(texture);
|
free(image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_mtl_canvas_texture_upload_region(mg_canvas_backend* backendInterface, mg_texture_data* textureInterface, mp_rect region, u8* pixels)
|
void mg_mtl_canvas_image_upload_region(mg_canvas_backend* backendInterface, mg_image_data* imageInterface, mp_rect region, u8* pixels)
|
||||||
{@autoreleasepool{
|
{@autoreleasepool{
|
||||||
mg_mtl_texture_data* texture = (mg_mtl_texture_data*)textureInterface;
|
mg_mtl_image_data* image = (mg_mtl_image_data*)imageInterface;
|
||||||
MTLRegion mtlRegion = MTLRegionMake2D(region.x, region.y, region.w, region.h);
|
MTLRegion mtlRegion = MTLRegionMake2D(region.x, region.y, region.w, region.h);
|
||||||
[texture->texture replaceRegion:mtlRegion
|
[image->texture replaceRegion:mtlRegion
|
||||||
mipmapLevel:0
|
mipmapLevel:0
|
||||||
withBytes:(void*)pixels
|
withBytes:(void*)pixels
|
||||||
bytesPerRow: 4 * region.w];
|
bytesPerRow: 4 * region.w];
|
||||||
|
@ -410,9 +410,9 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
|
||||||
backend->interface.clear = mg_mtl_canvas_clear;
|
backend->interface.clear = mg_mtl_canvas_clear;
|
||||||
backend->interface.drawBatch = mg_mtl_canvas_draw_batch;
|
backend->interface.drawBatch = mg_mtl_canvas_draw_batch;
|
||||||
|
|
||||||
backend->interface.textureCreate = mg_mtl_canvas_texture_create;
|
backend->interface.imageCreate = mg_mtl_canvas_image_create;
|
||||||
backend->interface.textureDestroy = mg_mtl_canvas_texture_destroy;
|
backend->interface.imageDestroy = mg_mtl_canvas_image_destroy;
|
||||||
backend->interface.textureUploadRegion = mg_mtl_canvas_texture_upload_region;
|
backend->interface.imageUploadRegion = mg_mtl_canvas_image_upload_region;
|
||||||
|
|
||||||
mp_rect frame = mg_surface_get_frame(surface);
|
mp_rect frame = mg_surface_get_frame(surface);
|
||||||
backend->viewPort = (mp_rect){0, 0, frame.w, frame.h};
|
backend->viewPort = (mp_rect){0, 0, frame.w, frame.h};
|
||||||
|
|
|
@ -41,6 +41,16 @@ typedef union
|
||||||
f32 c[2];
|
f32 c[2];
|
||||||
} vec2;
|
} vec2;
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
i32 x;
|
||||||
|
i32 y;
|
||||||
|
};
|
||||||
|
i32 c[2];
|
||||||
|
} ivec2;
|
||||||
|
|
||||||
typedef union
|
typedef union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
|
|
Loading…
Reference in New Issue