DVX_GUI/dvx/dvxComp.c

176 lines
5 KiB
C

// dvx_comp.c — Layer 3: Dirty rectangle compositor for DV/X GUI (optimized)
#include "dvxComp.h"
#include "platform/dvxPlatform.h"
#include <string.h>
#define DIRTY_MERGE_GAP 4
// ============================================================
// Prototypes
// ============================================================
static inline bool rectsOverlapOrAdjacent(const RectT *a, const RectT *b, int32_t gap);
static inline void rectUnion(const RectT *a, const RectT *b, RectT *result);
// ============================================================
// dirtyListAdd
// ============================================================
void dirtyListAdd(DirtyListT *dl, int32_t x, int32_t y, int32_t w, int32_t h) {
if (__builtin_expect(w <= 0 || h <= 0, 0)) {
return;
}
if (__builtin_expect(dl->count >= MAX_DIRTY_RECTS, 0)) {
dirtyListMerge(dl);
if (dl->count >= MAX_DIRTY_RECTS) {
RectT merged = dl->rects[0];
for (int32_t i = 1; i < dl->count; i++) {
rectUnion(&merged, &dl->rects[i], &merged);
}
RectT newRect = {x, y, w, h};
rectUnion(&merged, &newRect, &merged);
dl->rects[0] = merged;
dl->count = 1;
return;
}
}
dl->rects[dl->count].x = x;
dl->rects[dl->count].y = y;
dl->rects[dl->count].w = w;
dl->rects[dl->count].h = h;
dl->count++;
}
// ============================================================
// dirtyListClear
// ============================================================
void dirtyListClear(DirtyListT *dl) {
dl->count = 0;
}
// ============================================================
// dirtyListInit
// ============================================================
void dirtyListInit(DirtyListT *dl) {
dl->count = 0;
}
// ============================================================
// dirtyListMerge
// ============================================================
void dirtyListMerge(DirtyListT *dl) {
if (dl->count <= 1) {
return;
}
// O(N²) with bounded restarts: for each rect, try to merge it
// into an earlier rect. When a merge succeeds the merged rect
// may now overlap others, so restart the inner scan — but cap
// restarts per slot to avoid O(N³) pathological cascades.
for (int32_t i = 0; i < dl->count; i++) {
int32_t restarts = 0;
bool merged = true;
while (merged && restarts < 3) {
merged = false;
for (int32_t j = i + 1; j < dl->count; j++) {
if (rectsOverlapOrAdjacent(&dl->rects[i], &dl->rects[j], DIRTY_MERGE_GAP)) {
rectUnion(&dl->rects[i], &dl->rects[j], &dl->rects[i]);
dl->rects[j] = dl->rects[dl->count - 1];
dl->count--;
j--;
merged = true;
}
}
restarts++;
}
}
}
// ============================================================
// flushRect
// ============================================================
void flushRect(DisplayT *d, const RectT *r) {
platformFlushRect(d, r);
}
// ============================================================
// rectIntersect
// ============================================================
bool rectIntersect(const RectT *a, const RectT *b, RectT *result) {
int32_t ix1 = a->x > b->x ? a->x : b->x;
int32_t iy1 = a->y > b->y ? a->y : b->y;
int32_t ix2 = (a->x + a->w) < (b->x + b->w) ? (a->x + a->w) : (b->x + b->w);
int32_t iy2 = (a->y + a->h) < (b->y + b->h) ? (a->y + a->h) : (b->y + b->h);
if (__builtin_expect(ix1 >= ix2 || iy1 >= iy2, 0)) {
return false;
}
result->x = ix1;
result->y = iy1;
result->w = ix2 - ix1;
result->h = iy2 - iy1;
return true;
}
// ============================================================
// rectIsEmpty
// ============================================================
bool rectIsEmpty(const RectT *r) {
return (r->w <= 0 || r->h <= 0);
}
// ============================================================
// rectsOverlapOrAdjacent
// ============================================================
static inline bool rectsOverlapOrAdjacent(const RectT *a, const RectT *b, int32_t gap) {
if (a->x + a->w + gap < b->x) { return false; }
if (b->x + b->w + gap < a->x) { return false; }
if (a->y + a->h + gap < b->y) { return false; }
if (b->y + b->h + gap < a->y) { return false; }
return true;
}
// ============================================================
// rectUnion
// ============================================================
static inline void rectUnion(const RectT *a, const RectT *b, RectT *result) {
int32_t x1 = a->x < b->x ? a->x : b->x;
int32_t y1 = a->y < b->y ? a->y : b->y;
int32_t x2 = (a->x + a->w) > (b->x + b->w) ? (a->x + a->w) : (b->x + b->w);
int32_t y2 = (a->y + a->h) > (b->y + b->h) ? (a->y + a->h) : (b->y + b->h);
result->x = x1;
result->y = y1;
result->w = x2 - x1;
result->h = y2 - y1;
}