[canvas] Put primitive's transform in the attributes struct. When rendering, set current transform at the beginning of mg_next_shape(). (This avoid using an additional prevTransform matrix to correctly setup uvTransform when mg_finalize_shape() at the beginning of mg_next_shape())

This commit is contained in:
Martin Fouilleul 2023-02-27 15:01:44 +01:00
parent d195fb1f61
commit 30aa6a4a48
1 changed files with 16 additions and 25 deletions

View File

@ -59,6 +59,7 @@ typedef struct mg_attributes
mg_image image;
mp_rect srcRegion;
mg_mat2x3 transform;
mp_rect clip;
} mg_attributes;
@ -90,7 +91,6 @@ typedef struct mg_primitive
{
mg_primitive_cmd cmd;
mg_attributes attributes;
mg_mat2x3 transform;
union
{
@ -99,7 +99,6 @@ typedef struct mg_primitive
mg_rounded_rect roundedRect;
utf32 codePoint;
u32 jump;
mg_mat2x3 matrix; //TODO remove when we use transform everywhere
};
} mg_primitive;
@ -220,17 +219,17 @@ typedef struct mg_canvas_data
mg_resource_pool imagePool;
/*
vec2 atlasPos;
u32 atlasLineHeight;
mg_image blankImage;
*/
//NOTE: these are used at render time
mp_rect clip;
mg_mat2x3 transform;
mg_mat2x3 prevTransform; //TODO: [cleanup] use only one transform
mg_image currentImage;
mp_rect currentSrcRegion;
mg_image image;
mp_rect srcRegion;
vec4 shapeExtents;
u32 nextShapeIndex;
@ -732,8 +731,8 @@ void mg_push_command(mg_canvas_data* canvas, mg_primitive primitive)
//NOTE(martin): push primitive and updates current stream, eventually patching a pending jump.
ASSERT(canvas->primitiveCount < MG_MAX_PRIMITIVE_COUNT);
canvas->primitives[canvas->primitiveCount] = primitive;
canvas->primitives[canvas->primitiveCount].transform = mg_matrix_stack_top(canvas);
canvas->primitives[canvas->primitiveCount].attributes = canvas->attributes;
canvas->primitives[canvas->primitiveCount].attributes.transform = mg_matrix_stack_top(canvas);
canvas->primitiveCount++;
}
@ -770,9 +769,9 @@ void mg_finalize_shape(mg_canvas_data* canvas)
if(canvas->nextShapeIndex)
{
//NOTE: set shape's uv transform for the _current_ shape
vec2 texSize = mg_image_size(canvas->currentImage);
vec2 texSize = mg_image_size(canvas->image);
mp_rect srcRegion = canvas->currentSrcRegion;
mp_rect srcRegion = canvas->srcRegion;
mp_rect destRegion = {canvas->shapeExtents.x,
canvas->shapeExtents.y,
@ -786,7 +785,7 @@ void mg_finalize_shape(mg_canvas_data* canvas)
mg_mat2x3 userToDestRegion = {1, 0, -destRegion.x,
0, 1, -destRegion.y};
mg_mat2x3 screenToUser = mg_mat2x3_inv(canvas->prevTransform);
mg_mat2x3 screenToUser = mg_mat2x3_inv(canvas->transform);
mg_mat2x3 uvTransform = srcRegionToTexture;
uvTransform = mg_mat2x3_mul_m(uvTransform, destRegionToSrcRegion);
@ -798,14 +797,14 @@ void mg_finalize_shape(mg_canvas_data* canvas)
*(mg_mat2x3*)(layout->uvTransformBuffer + index*layout->uvTransformStride) = uvTransform;
}
canvas->prevTransform = canvas->transform;
}
u32 mg_next_shape(mg_canvas_data* canvas, mg_attributes* attributes)
{
mg_finalize_shape(canvas);
canvas->currentSrcRegion = attributes->srcRegion;
canvas->transform = attributes->transform;
canvas->srcRegion = attributes->srcRegion;
canvas->shapeExtents = (vec4){FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX};
mg_vertex_layout* layout = &canvas->backend->vertexLayout;
@ -2748,15 +2747,8 @@ mg_canvas mg_canvas_create(mg_surface surface)
0, 1, 0}};
//TODO: review this ////////////////////////////////////////////////////////////////////////
canvas = mg_canvas_alloc_handle(canvasData);
mg_canvas_set_current(canvas);
//NOTE: create a blank image
//WARN: this requires setting the current context before
u8 bytes[4] = {255, 255, 255, 255};
canvasData->blankImage = mg_image_create_from_rgba8(1, 1, bytes);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
return(canvas);
@ -2888,7 +2880,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->currentImage = mg_image_nil();
canvas->image = mg_image_nil();
canvas->backend->begin(canvas->backend);
@ -2902,13 +2894,12 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
mg_primitive* primitive = &(primitives[nextIndex]);
nextIndex++;
if(i && primitive->attributes.image.h != canvas->currentImage.h)
if(i && primitive->attributes.image.h != canvas->image.h)
{
mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->currentImage);
mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->image);
mg_draw_batch(canvas, imageData);
canvas->currentImage = primitive->attributes.image;
canvas->image = primitive->attributes.image;
}
canvas->transform = primitive->transform;
switch(primitive->cmd)
{
@ -2996,7 +2987,7 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
}
exit_command_loop: ;
mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->currentImage);
mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->image);
mg_draw_batch(canvas, imageData);
canvas->backend->end(canvas->backend);