diff options
Diffstat (limited to 'src/vcr.c')
-rw-r--r-- | src/vcr.c | 115 |
1 files changed, 92 insertions, 23 deletions
@@ -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. |