[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; mg_image image;
mp_rect srcRegion; mp_rect srcRegion;
mg_mat2x3 transform;
mp_rect clip; mp_rect clip;
} mg_attributes; } mg_attributes;
@ -90,7 +91,6 @@ typedef struct mg_primitive
{ {
mg_primitive_cmd cmd; mg_primitive_cmd cmd;
mg_attributes attributes; mg_attributes attributes;
mg_mat2x3 transform;
union union
{ {
@ -99,7 +99,6 @@ typedef struct mg_primitive
mg_rounded_rect roundedRect; mg_rounded_rect roundedRect;
utf32 codePoint; utf32 codePoint;
u32 jump; u32 jump;
mg_mat2x3 matrix; //TODO remove when we use transform everywhere
}; };
} mg_primitive; } mg_primitive;
@ -220,17 +219,17 @@ typedef struct mg_canvas_data
mg_resource_pool imagePool; mg_resource_pool imagePool;
/*
vec2 atlasPos; vec2 atlasPos;
u32 atlasLineHeight; u32 atlasLineHeight;
mg_image blankImage; mg_image blankImage;
*/
//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_mat2x3 prevTransform; //TODO: [cleanup] use only one transform mg_image image;
mp_rect srcRegion;
mg_image currentImage;
mp_rect currentSrcRegion;
vec4 shapeExtents; vec4 shapeExtents;
u32 nextShapeIndex; 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. //NOTE(martin): push primitive and updates current stream, eventually patching a pending jump.
ASSERT(canvas->primitiveCount < MG_MAX_PRIMITIVE_COUNT); ASSERT(canvas->primitiveCount < MG_MAX_PRIMITIVE_COUNT);
canvas->primitives[canvas->primitiveCount] = primitive; 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 = canvas->attributes;
canvas->primitives[canvas->primitiveCount].attributes.transform = mg_matrix_stack_top(canvas);
canvas->primitiveCount++; canvas->primitiveCount++;
} }
@ -770,9 +769,9 @@ 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_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, mp_rect destRegion = {canvas->shapeExtents.x,
canvas->shapeExtents.y, canvas->shapeExtents.y,
@ -786,7 +785,7 @@ void mg_finalize_shape(mg_canvas_data* canvas)
mg_mat2x3 userToDestRegion = {1, 0, -destRegion.x, mg_mat2x3 userToDestRegion = {1, 0, -destRegion.x,
0, 1, -destRegion.y}; 0, 1, -destRegion.y};
mg_mat2x3 screenToUser = mg_mat2x3_inv(canvas->prevTransform); mg_mat2x3 screenToUser = mg_mat2x3_inv(canvas->transform);
mg_mat2x3 uvTransform = srcRegionToTexture; mg_mat2x3 uvTransform = srcRegionToTexture;
uvTransform = mg_mat2x3_mul_m(uvTransform, destRegionToSrcRegion); 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; *(mg_mat2x3*)(layout->uvTransformBuffer + index*layout->uvTransformStride) = uvTransform;
} }
canvas->prevTransform = canvas->transform;
} }
u32 mg_next_shape(mg_canvas_data* canvas, mg_attributes* attributes) u32 mg_next_shape(mg_canvas_data* canvas, mg_attributes* attributes)
{ {
mg_finalize_shape(canvas); 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}; canvas->shapeExtents = (vec4){FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX};
mg_vertex_layout* layout = &canvas->backend->vertexLayout; mg_vertex_layout* layout = &canvas->backend->vertexLayout;
@ -2748,15 +2747,8 @@ mg_canvas mg_canvas_create(mg_surface surface)
0, 1, 0}}; 0, 1, 0}};
//TODO: review this ////////////////////////////////////////////////////////////////////////
canvas = mg_canvas_alloc_handle(canvasData); canvas = mg_canvas_alloc_handle(canvasData);
mg_canvas_set_current(canvas); 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); 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->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); 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]); mg_primitive* primitive = &(primitives[nextIndex]);
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); mg_draw_batch(canvas, imageData);
canvas->currentImage = primitive->attributes.image; canvas->image = primitive->attributes.image;
} }
canvas->transform = primitive->transform;
switch(primitive->cmd) switch(primitive->cmd)
{ {
@ -2996,7 +2987,7 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
} }
exit_command_loop: ; 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); mg_draw_batch(canvas, imageData);
canvas->backend->end(canvas->backend); canvas->backend->end(canvas->backend);