texture tests; fix blit with destination underflow left

This commit is contained in:
uosfz 2026-05-20 15:45:26 +02:00
parent de62a28d6b
commit 14c314dd0f
Signed by: uosfz
SSH key fingerprint: SHA256:FlktuluyhTQg3jHZNLKwxOOC5hbfrUXM0tz3IA3lGJo
4 changed files with 130 additions and 10 deletions

View file

@ -88,7 +88,7 @@ void app_calculator_on_selector(void *self, struct Component *btn) {
void app_calculator_on_load_result(void *self, struct Component *btn) {
struct app_calculator *app = self;
char to = app->acc_label->data.label.text[1];
char to = app_component_textline_get(self, app->acc_label)[0];
struct Component *dst = (to == 'A') ? app->a : app->b;
app_component_textline_set(self, dst, app_component_textline_get(self, app->out));
}
@ -103,7 +103,7 @@ void app_calculator_on_load_reg(void *self, struct Component *btn) {
void app_calculator_on_save_reg(void *self, struct Component *btn) {
struct app_calculator *app = self;
int reg_idx = app->reg_label->data.label.text[1] - '0';
int reg_idx = app_component_textline_get(self, app->reg_label)[0] - '0';
app_component_textline_set(self, app->registers[reg_idx], app_component_textline_get(self, app->out));
}
@ -162,12 +162,12 @@ struct AppCreation app_calculator_create() {
btn_div->data.button.textline.width = short_field_width;
struct Component *stack_btn = app_component_new_stack(true, 4, btn_add, btn_sub, btn_mul, btn_div);
struct Component *sel_acc = selector("acc", " A ", short_field_width, short_field_width, short_field_width,
struct Component *sel_acc = selector("acc", "A", short_field_width, short_field_width, short_field_width,
&app->acc_btn_left,
&app->acc_label,
&app->acc_btn_right
);
struct Component *sel_reg = selector("reg", " 0 ", short_field_width, short_field_width, short_field_width,
struct Component *sel_reg = selector("reg", "0", short_field_width, short_field_width, short_field_width,
&app->reg_btn_left,
&app->reg_label,
&app->reg_btn_right

View file

@ -166,6 +166,7 @@ void tron_init_leaderboard(void *self) {
x = 0;
y += app_text_height();
s[1]++;
}
}

View file

@ -52,11 +52,16 @@ void tex_blit(
{
ASSERT(dst_tex != NULL && src_tex != NULL);
struct rect real_dst = (dst_pos != NULL) ? *dst_pos : TEX_RECT(*dst_tex);
int dst_off_x = (real_dst.x < 0) ? -real_dst.x : 0;
int dst_off_y = (real_dst.y < 0) ? -real_dst.y : 0;
rect_clamp(&real_dst, &TEX_RECT(*dst_tex));
struct rect real_src = (src_pos != NULL) ? *src_pos : TEX_RECT(*src_tex);
// we start where the visible part starts
rect_translate(&real_src, dst_off_x, dst_off_y);
rect_clamp(&real_src, &TEX_RECT(*src_tex));
struct rect real_dst = (dst_pos != NULL) ? *dst_pos : TEX_RECT(*dst_tex);
rect_clamp(&real_dst, &TEX_RECT(*dst_tex));
int minw = (RECT_WIDTH(real_src) < RECT_WIDTH(real_dst)) ? RECT_WIDTH(real_src) : RECT_WIDTH(real_dst);
int minh = (RECT_HEIGHT(real_src) < RECT_HEIGHT(real_dst)) ? RECT_HEIGHT(real_src) : RECT_HEIGHT(real_dst);

View file

@ -2,12 +2,13 @@
#include "rect.h"
#include "texture.h"
#include "test.h"
#include "tlsf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
uint32_t color_format(struct color col) {
return ((uint32_t)col.r << 16) | ((uint32_t)col.b << 8) | (uint32_t)col.g;
return ((uint32_t)col.r << 16) | ((uint32_t)col.g << 8) | (uint32_t)col.b;
}
#define WIDTH 20
@ -46,7 +47,7 @@ static void verify_mem(struct rect rect, struct color col) {
}
void test_fill_region() {
struct tex tex = TEX_CREATE(WIDTH, HEIGHT, mem);
struct tex tex = TEX_INIT(WIDTH, HEIGHT, mem);
memset(mem, 0, MEMSIZE);
// --- standard fill inside range ---
@ -73,7 +74,7 @@ void test_fill_region() {
}
void test_fill_region_view() {
struct tex tex = TEX_CREATE(WIDTH, HEIGHT, mem);
struct tex tex = TEX_INIT(WIDTH, HEIGHT, mem);
struct tex view = tex_view(&tex, &RECT_XYWH(2, 1, WIDTH-4, HEIGHT-2));
TEST_ASSERT(view.width == WIDTH-4 && view.height == HEIGHT-2 && view.stride == tex.stride);
TEST_ASSERT((char*)view.data == (char*)tex.data + 1*tex.stride + 2*4);
@ -96,8 +97,121 @@ void test_fill_region_view() {
verify_mem(global_rect, col);
}
void *kern_alloc(size_t size) {
void *res = malloc(size);
TEST_ASSERT(res);
return res;
}
#define COLOR_RG(r, g) COLOR_RGB(r, g, 0)
bool tex_equal(struct tex a, struct tex b) {
if (a.width != b.width || a.height != b.height) {
return false;
}
char *da = a.data;
char *db = b.data;
// row-based because they may have different strides
for (size_t row = 0; row < a.height; row++) {
if (memcmp(da, db, 4 * a.width)) {
return false;
}
da += a.stride;
db += b.stride;
}
return true;
}
void texs_init(struct tex canvas, struct tex img) {
TEX_SET_FOR_EACH(canvas, COLOR_RG(x, y));
TEX_SET_FOR_EACH(img, COLOR_RG(100+x, 100+y));
}
struct color color2(int x, int y) {
if (x == 0 || x == 4 || y == 0 || y == 4) {
return COLOR_RG(x, y);
}
return COLOR_RG(100+x-1, 100+y-1);
}
struct color color3(int x, int y) {
if (x == 0 || x == 3 || x == 4 || y == 0 || y == 4) {
return COLOR_RG(x, y);
}
return COLOR_RG(100+x-1, 100+y-1);
}
struct color color4(int x, int y) {
if (x==2 && y==3) return COLOR_RG(101, 102);
if (x==3 && y==3) return COLOR_RG(102, 102);
return COLOR_RG(x, y);
}
struct color color5(int x, int y) {
if (y==0 || y==1 || x==2 || x==3 || x==4) {
return COLOR_RG(x, y);
}
return COLOR_RG(100+x+1, 100+y-2);
}
struct color color6(int x, int y) {
if (x>0 || y>1) {
return COLOR_RG(x, y);
}
return COLOR_RG(100+x+2, 100+y+1);
}
void test_blit() {
struct tex canvas = TEX_ALLOC(5, 5);
struct tex img = TEX_ALLOC(3, 3);
struct tex target = TEX_ALLOC(5, 5);
// test 1: both NULL
texs_init(canvas, img);
tex_blit(&canvas, &img, NULL, NULL);
TEX_SET_FOR_EACH(target, (x < 3 && y < 3) ? COLOR_RG(100+x, 100+y) : COLOR_RG(x, y));
TEST_ASSERT(tex_equal(canvas, target));
// test 2: centered
texs_init(canvas, img);
tex_blit(&canvas, &img, NULL, &RECT_XYWH(1, 1, 3, 3));
TEX_SET_FOR_EACH(target, color2(x, y));
TEST_ASSERT(tex_equal(canvas, target));
// test 3: centered and dst cut off in x dir
texs_init(canvas, img);
tex_blit(&canvas, &img, NULL, &RECT_XYWH(1, 1, 2, 3));
TEX_SET_FOR_EACH(target, color3(x, y));
TEST_ASSERT(tex_equal(canvas, target));
// test 4: src cut off
texs_init(canvas, img);
tex_blit(&canvas, &img, &RECT_XYWH(1, 2, 2, 1), &RECT_XYWH(2, 3, 3, 3));
TEX_SET_FOR_EACH(target, color4(x, y));
TEST_ASSERT(tex_equal(canvas, target));
// test 4.1: src overflow bottom right
texs_init(canvas, img);
tex_blit(&canvas, &img, &RECT_XYWH(1, 2, 5, 5), &RECT_XYWH(2, 3, 3, 3));
TEX_SET_FOR_EACH(target, color4(x, y));
TEST_ASSERT(tex_equal(canvas, target));
// test 5: dst underflow left
texs_init(canvas, img);
tex_blit(&canvas, &img, NULL, &RECT_XYWH(-1, 2, 3, 3));
TEX_SET_FOR_EACH(target, color5(x, y));
TEST_ASSERT(tex_equal(canvas, target));
// test 6: dst underflow left and top
texs_init(canvas, img);
tex_blit(&canvas, &img, NULL, &RECT_XYWH(-2, -1, 10, 10));
TEX_SET_FOR_EACH(target, color6(x, y));
TEST_ASSERT(tex_equal(canvas, target));
}
int main() {
test_fill_region();
test_fill_region_view();
test_blit();
return 0;
}