summaryrefslogtreecommitdiff
path: root/src/vcr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vcr.c')
-rw-r--r--src/vcr.c115
1 files changed, 92 insertions, 23 deletions
diff --git a/src/vcr.c b/src/vcr.c
index 18cf301..c9a7c6f 100644
--- a/src/vcr.c
+++ b/src/vcr.c
@@ -76,6 +76,10 @@
#define VCR_USECS_PER_SECOND 1000000
+typedef struct vcr_row_meta_t {
+ vcr_row_palette_t palette;
+} vcr_row_meta_t;
+
/* backend is the root vcr object everything else here derives from,
* for an X backend it encompasses the xserver/display connection.
*/
@@ -135,6 +139,9 @@ typedef struct vcr_t {
int *snowflakes_cnt_ptr; /* pointer to count of snowflaked rows (reset to zero to truncate snowflakes display) */
const unsigned *marker_distance_ptr; /* pointer to marker distance to use (0 disables markers, this is kind of silly but I don't want to add setters everywhere so sharing the instance in vwm_charts_t) */
+ vcr_row_meta_t *meta; /* height / VCR_ROW_HEIGHT elements for per-row metadata */
+ vcr_row_meta_t tmp_meta; /* temp storage for a row's meta */
+
union {
#ifdef USE_XLIB
struct {
@@ -149,9 +156,9 @@ typedef struct vcr_t {
} xlib;
#endif /* USE_XLIB */
struct {
- uint8_t *bits; /* .pitch * height bytes are used to represent the coverage status of up to 4 layers (was 8 until nibbles happened) */
- uint8_t *tmp; /* .pitch * VCR_ROW_HEIGHT bytes for a row's worth of temporary storage */
- int pitch; /* "pitch" of mem surface in bytes, which is half the width rounded up to an even number divisible by two. */
+ uint8_t *bits; /* .pitch * height bytes are used to represent the coverage status of up to 4 layers (was 8 until nibbles happened) */
+ uint8_t *tmp; /* .pitch * VCR_ROW_HEIGHT bytes for a row's worth of temporary storage */
+ int pitch; /* "pitch" of mem surface in bytes, which is half the width rounded up to an even number divisible by two. */
} mem;
};
} vcr_t;
@@ -816,6 +823,7 @@ vcr_t * vcr_free(vcr_t *vcr)
assert(0);
}
+ free(vcr->meta);
free(vcr);
}
@@ -854,6 +862,19 @@ int vcr_resize_visible(vcr_t *vcr, int width, int height)
return 1; /* redraw needed */
}
+ { /* the meta layer isn't backend-specific */
+ vcr_row_meta_t *old = vcr->meta;
+
+ vcr->meta = calloc(height / VCR_ROW_HEIGHT, sizeof(vcr_row_meta_t));
+ if (!vcr->meta)
+ return -ENOMEM;
+
+ if (old) {
+ memcpy(vcr->meta, old, (vcr->height / VCR_ROW_HEIGHT) * sizeof(vcr_row_meta_t));
+ free(old);
+ }
+ }
+
/* we're going outside the current allocation dimensions, so we need to involve the backend
* in _really_ resizing.
*/
@@ -1195,35 +1216,32 @@ void vcr_mark_finish_line(vcr_t *vcr, vcr_layer_t layer, int row)
}
-/* draw a bar at the current phase into the specified layer of t % with a minimum of min_height pixels.
+/* draw a bar at the current phase into the specified layer of height pixels
*
* the only layers supported right now are grapha/graphb
*/
-void vcr_draw_bar(vcr_t *vcr, vcr_layer_t layer, int row, float t, int min_height)
+void vcr_draw_bar(vcr_t *vcr, vcr_layer_t layer, vcr_bar_base_t base, int row, int height)
{
- int height, y = row * VCR_ROW_HEIGHT;
+ int y = row * VCR_ROW_HEIGHT;
assert(vcr);
assert(vcr->backend);
assert(row >= 0);
assert(layer == VCR_LAYER_GRAPHA || layer == VCR_LAYER_GRAPHB);
- assert(min_height >= 0 && min_height < (VCR_ROW_HEIGHT - 1));
+ assert(height >= 0 && height < VCR_ROW_HEIGHT);
if ((row + 1) * VCR_ROW_HEIGHT >= vcr->height)
return;
- height = fabsf(t) * (float)(VCR_ROW_HEIGHT - 1);
-
- if (height < min_height)
- height = min_height;
-
- /* clamp the height to not potentially overflow */
- if (height > (VCR_ROW_HEIGHT - 1))
- height = (VCR_ROW_HEIGHT - 1);
-
- /* negative values project down from the top, positive up from bottom */
- if (t > 0.f)
+ switch (base) {
+ case VCR_BAR_BASE_BOTTOM:
y += VCR_ROW_HEIGHT - height - 1;
+ break;
+ case VCR_BAR_BASE_TOP:
+ break;
+ default:
+ assert(0);
+ }
switch (vcr->backend->type) {
#ifdef USE_XLIB
@@ -1296,6 +1314,11 @@ void vcr_clear_row(vcr_t *vcr, vcr_layer_t layer, int row, int x, int width)
if ((row + 1) * VCR_ROW_HEIGHT >= vcr->height)
return;
+ if (layer == VCR_LAYER_META) {
+ vcr->meta[row] = (vcr_row_meta_t){};
+ return;
+ }
+
switch (vcr->backend->type) {
#ifdef USE_XLIB
case VCR_BACKEND_TYPE_XLIB: {
@@ -1351,6 +1374,20 @@ void vcr_clear_row(vcr_t *vcr, vcr_layer_t layer, int row, int x, int width)
}
+void vcr_set_row_palette(vcr_t *vcr, int row, vcr_row_palette_t palette)
+{
+ assert(vcr);
+ assert(vcr->backend);
+ assert(palette < VCR_ROW_PALETTE_CNT);
+ assert(row >= 0);
+
+ if ((row + 1) * VCR_ROW_HEIGHT >= vcr->height)
+ return;
+
+ vcr->meta[row].palette = palette;
+}
+
+
/* copy what's below a given row up by one row across all the layers */
void vcr_shift_below_row_up_one(vcr_t *vcr, int row)
{
@@ -1363,6 +1400,16 @@ void vcr_shift_below_row_up_one(vcr_t *vcr, int row)
assert(*(vcr->hierarchy_end_ptr) >= row);
+ {
+ vcr_row_meta_t *dest = &vcr->meta[row];
+ vcr_row_meta_t *src = &vcr->meta[(1 + row)];
+ size_t len = ((1 + *(vcr->hierarchy_end_ptr)) - (1 + row)) * sizeof(vcr_row_meta_t);
+
+ assert(*(vcr->hierarchy_end_ptr) >= row);
+
+ memmove(dest, src, len);
+ }
+
switch (vcr->backend->type) {
#ifdef USE_XLIB
case VCR_BACKEND_TYPE_XLIB: {
@@ -1432,6 +1479,14 @@ void vcr_shift_below_row_down_one(vcr_t *vcr, int row)
if (dest_y >= vcr->height)
return;
+ {
+ vcr_row_meta_t *dest = &vcr->meta[row + 1];
+ vcr_row_meta_t *src = &vcr->meta[row];
+ size_t len = ((vcr->height / VCR_ROW_HEIGHT) - (row + 1)) * sizeof(vcr_row_meta_t);
+
+ memmove(dest, src, len);
+ }
+
switch (vcr->backend->type) {
#ifdef USE_XLIB
case VCR_BACKEND_TYPE_XLIB: {
@@ -1599,12 +1654,17 @@ void vcr_stash_row(vcr_t *vcr, vcr_layer_t layer, int row)
{
assert(vcr);
assert(vcr->backend);
- assert(layer == VCR_LAYER_GRAPHA || layer == VCR_LAYER_GRAPHB);
+ assert(layer == VCR_LAYER_GRAPHA || layer == VCR_LAYER_GRAPHB || layer == VCR_LAYER_META);
/* for now we only support stashing graphs */
if ((row + 1) * VCR_ROW_HEIGHT >= vcr->height)
return;
+ if (layer == VCR_LAYER_META) {
+ vcr->tmp_meta = vcr->meta[row];
+ return;
+ }
+
switch (vcr->backend->type) {
#ifdef USE_XLIB
case VCR_BACKEND_TYPE_XLIB: {
@@ -1658,11 +1718,16 @@ void vcr_unstash_row(vcr_t *vcr, vcr_layer_t layer, int row)
{
assert(vcr);
assert(vcr->backend);
- assert(layer == VCR_LAYER_GRAPHA || layer == VCR_LAYER_GRAPHB);
+ assert(layer == VCR_LAYER_GRAPHA || layer == VCR_LAYER_GRAPHB || layer == VCR_LAYER_META);
if ((row + 1) * VCR_ROW_HEIGHT >= vcr->height)
return;
+ if (layer == VCR_LAYER_META) {
+ vcr->meta[row] = vcr->tmp_meta;
+ return;
+ }
+
switch (vcr->backend->type) {
#ifdef USE_XLIB
case VCR_BACKEND_TYPE_XLIB: {
@@ -2253,9 +2318,13 @@ static int vcr_present_mem_to_png(vcr_t *vcr, vcr_dest_t *dest)
marker_distance = *(vcr->marker_distance_ptr);
for (int i = 0; i < n_rows; i++) {
- uint8_t *d = row_pixels;
- uint8_t mask = (0x1 << VCR_LAYER_GRAPHA) | (0x1 << VCR_LAYER_GRAPHB);
- uint8_t odd = ((VCR_ODD << 4 | VCR_ODD) * (i & 0x1));
+ uint8_t *d = row_pixels;
+ uint8_t mask = (0x1 << VCR_LAYER_GRAPHA) | (0x1 << VCR_LAYER_GRAPHB);
+ uint8_t odd = ((VCR_ODD << 4 | VCR_ODD) * (i & 0x1));
+ vcr_row_palette_t row_pal = vcr->meta[i].palette;
+
+ lut[VCR_GRAPHA] = lut[VCR_GRAPHA_ODD] = VCR_LUT_ROWSUB0_A + (row_pal << 1);
+ lut[VCR_GRAPHB] = lut[VCR_GRAPHB_ODD] = VCR_LUT_ROWSUB0_B + (row_pal << 1);
/* The graph layers need to be moved to vcr->phase, since the per-sample updates just draw
* individual graph bars without bothering to move the whole graph layer every sample.
© All Rights Reserved