diff --git a/src/lib/internal.h b/src/lib/internal.h index b4cef3902..8ab95341c 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -401,6 +401,9 @@ struct blitset { #include "blitset.h" +void reset_stats(ncstats* stats); +void summarize_stats(notcurses* nc); + void sigwinch_handler(int signo); void init_lang(notcurses* nc); // nc may be NULL, only used for logging @@ -854,7 +857,7 @@ ALLOC char* ncplane_vprintf_prep(const char* format, va_list ap); int ncvisual_blit(struct ncvisual* ncv, int rows, int cols, ncplane* n, const struct blitset* bset, int placey, int placex, int begy, int begx, - int leny, int lenx, bool blendcolors); + int leny, int lenx, unsigned blendcolors); void nclog(const char* fmt, ...); @@ -1069,6 +1072,7 @@ pool_blit_direct(egcpool* pool, nccell* c, const char* gcluster, int bytes, int return -1; } c->width = cols; + cell_set_pixels(c, 0); if(bytes <= 4){ c->gcluster = 0; memcpy(&c->gcluster, gcluster, bytes); @@ -1208,7 +1212,7 @@ API const struct blitset* lookup_blitset(const tinfo* tcache, ncblitter_e setid, static inline int rgba_blit_dispatch(ncplane* nc, const struct blitset* bset, int placey, int placex, int linesize, const void* data, int begy, - int begx, int leny, int lenx, bool blendcolors){ + int begx, int leny, int lenx, unsigned blendcolors){ return bset->blit(nc, placey, placex, linesize, data, begy, begx, leny, lenx, blendcolors); } @@ -1237,7 +1241,7 @@ typedef struct ncvisual_implementation { int (*visual_blit)(struct ncvisual* ncv, int rows, int cols, ncplane* n, const struct blitset* bset, int placey, int placex, int begy, int begx, int leny, int lenx, - bool blendcolors); + unsigned blendcolors); struct ncvisual* (*visual_create)(void); struct ncvisual* (*visual_from_file)(const char* fname); // ncv constructors other than ncvisual_from_file() need to set up the diff --git a/src/lib/kitty.c b/src/lib/kitty.c index 83a9823b6..83b94229f 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -76,6 +76,7 @@ int kitty_blit_inner(ncplane* nc, int placey, int placex, int linesize, free(buf); return -1; } + cell_set_pixels(c, 1); free(buf); return 1; } diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 62eb09838..a3ab69a8e 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -707,84 +707,6 @@ int ncplane_genocide(ncplane *ncp){ return ret; } -static void -reset_stats(ncstats* stats){ - uint64_t fbbytes = stats->fbbytes; - unsigned planes = stats->planes; - memset(stats, 0, sizeof(*stats)); - stats->render_min_ns = 1ull << 62u; - stats->render_min_bytes = 1ull << 62u; - stats->raster_min_ns = 1ull << 62u; - stats->writeout_min_ns = 1ull << 62u; - stats->fbbytes = fbbytes; - stats->planes = planes; -} - -void notcurses_stats(notcurses* nc, ncstats* stats){ - pthread_mutex_lock(&nc->statlock); - memcpy(stats, &nc->stats, sizeof(*stats)); - pthread_mutex_unlock(&nc->statlock); -} - -ncstats* notcurses_stats_alloc(const notcurses* nc __attribute__ ((unused))){ - return malloc(sizeof(ncstats)); -} - -void notcurses_stats_reset(notcurses* nc, ncstats* stats){ - pthread_mutex_lock(&nc->statlock); - if(stats){ - memcpy(stats, &nc->stats, sizeof(*stats)); - } - // add the stats to the stashed stats, so that we can show true totals on - // shutdown in the closing banner - ncstats* stash = &nc->stashed_stats; - if(nc->stats.render_min_ns < stash->render_min_ns){ - stash->render_min_ns = nc->stats.render_min_ns; - } - if(nc->stats.render_min_bytes < stash->render_min_bytes){ - stash->render_min_bytes = nc->stats.render_min_bytes; - } - if(nc->stats.raster_min_ns < stash->raster_min_ns){ - stash->raster_min_ns = nc->stats.raster_min_ns; - } - if(nc->stats.writeout_min_ns < stash->writeout_min_ns){ - stash->writeout_min_ns = nc->stats.writeout_min_ns; - } - if(nc->stats.render_max_ns > stash->render_max_ns){ - stash->render_max_ns = nc->stats.render_max_ns; - } - if(nc->stats.render_max_bytes > stash->render_max_bytes){ - stash->render_max_bytes = nc->stats.render_max_bytes; - } - if(nc->stats.raster_max_ns > stash->raster_max_ns){ - stash->raster_max_ns = nc->stats.raster_max_ns; - } - if(nc->stats.writeout_max_ns > stash->writeout_max_ns){ - stash->writeout_max_ns = nc->stats.writeout_max_ns; - } - stash->writeout_ns += nc->stats.writeout_ns; - stash->raster_ns += nc->stats.raster_ns; - stash->render_ns += nc->stats.render_ns; - stash->render_bytes += nc->stats.render_bytes; - stash->failed_renders += nc->stats.failed_renders; - stash->failed_writeouts += nc->stats.failed_writeouts; - stash->renders += nc->stats.renders; - stash->writeouts += nc->stats.writeouts; - stash->cellelisions += nc->stats.cellelisions; - stash->cellemissions += nc->stats.cellemissions; - stash->fgelisions += nc->stats.fgelisions; - stash->fgemissions += nc->stats.fgemissions; - stash->bgelisions += nc->stats.bgelisions; - stash->bgemissions += nc->stats.bgemissions; - stash->defaultelisions += nc->stats.defaultelisions; - stash->defaultemissions += nc->stats.defaultemissions; - stash->refreshes = nc->stats.refreshes; - stash->fbbytes = nc->stats.fbbytes; - stash->planes = nc->stats.planes; - reset_stats(&nc->stats); - pthread_mutex_unlock(&nc->statlock); -} - // only invoked without suppress banners flag. prints various warnings based on // the environment / terminal definition. static void @@ -1222,67 +1144,7 @@ int notcurses_stop(notcurses* nc){ // get any current stats loaded into stash_stats notcurses_stats_reset(nc, NULL); if(!nc->suppress_banner){ - const ncstats *stats = &nc->stashed_stats; - if(stats->renders){ - char totalbuf[BPREFIXSTRLEN + 1]; - char minbuf[BPREFIXSTRLEN + 1]; - char maxbuf[BPREFIXSTRLEN + 1]; - char avgbuf[BPREFIXSTRLEN + 1]; - qprefix(stats->render_ns, NANOSECS_IN_SEC, totalbuf, 0); - qprefix(stats->render_min_ns, NANOSECS_IN_SEC, minbuf, 0); - qprefix(stats->render_max_ns, NANOSECS_IN_SEC, maxbuf, 0); - qprefix(stats->render_ns / stats->renders, NANOSECS_IN_SEC, avgbuf, 0); - fprintf(stderr, "\n%ju render%s, %ss (%ss min, %ss avg, %ss max)\n", - stats->renders, stats->renders == 1 ? "" : "s", - totalbuf, minbuf, avgbuf, maxbuf); - qprefix(stats->raster_ns, NANOSECS_IN_SEC, totalbuf, 0); - qprefix(stats->raster_min_ns, NANOSECS_IN_SEC, minbuf, 0); - qprefix(stats->raster_max_ns, NANOSECS_IN_SEC, maxbuf, 0); - qprefix(stats->raster_ns / stats->writeouts, NANOSECS_IN_SEC, avgbuf, 0); - fprintf(stderr, "%ju raster%s, %ss (%ss min, %ss avg, %ss max)\n", - stats->writeouts, stats->writeouts == 1 ? "" : "s", - totalbuf, minbuf, avgbuf, maxbuf); - qprefix(stats->writeout_ns, NANOSECS_IN_SEC, totalbuf, 0); - qprefix(stats->writeout_min_ns, NANOSECS_IN_SEC, minbuf, 0); - qprefix(stats->writeout_max_ns, NANOSECS_IN_SEC, maxbuf, 0); - qprefix(stats->writeouts ? stats->writeout_ns / stats->writeouts : 0, - NANOSECS_IN_SEC, avgbuf, 0); - fprintf(stderr, "%ju write%s, %ss (%ss min, %ss avg, %ss max)\n", - stats->writeouts, stats->writeouts == 1 ? "" : "s", - totalbuf, minbuf, avgbuf, maxbuf); - bprefix(stats->render_bytes, 1, totalbuf, 1), - bprefix(stats->render_min_bytes, 1, minbuf, 1), - bprefix(stats->renders ? stats->render_bytes / stats->renders : 0, 1, avgbuf, 1); - bprefix(stats->render_max_bytes, 1, maxbuf, 1), - fprintf(stderr, "%sB (%sB min, %sB avg, %sB max)\n", - totalbuf, minbuf, avgbuf, maxbuf); - } - if(stats->renders || stats->failed_renders){ - fprintf(stderr, "%ju failed render%s, %ju failed write%s, %ju refresh%s\n", - stats->failed_renders, - stats->failed_renders == 1 ? "" : "s", - stats->failed_writeouts, - stats->failed_writeouts == 1 ? "" : "s", - stats->refreshes, - stats->refreshes == 1 ? "" : "es"); - fprintf(stderr, "RGB emits:elides: def %ju:%ju fg %ju:%ju bg %ju:%ju\n", - stats->defaultemissions, - stats->defaultelisions, - stats->fgemissions, - stats->fgelisions, - stats->bgemissions, - stats->bgelisions); - fprintf(stderr, "Cell emits:elides: %ju/%ju (%.2f%%) %.2f%% %.2f%% %.2f%%\n", - stats->cellemissions, stats->cellelisions, - (stats->cellemissions + stats->cellelisions) == 0 ? 0 : - (stats->cellelisions * 100.0) / (stats->cellemissions + stats->cellelisions), - (stats->defaultemissions + stats->defaultelisions) == 0 ? 0 : - (stats->defaultelisions * 100.0) / (stats->defaultemissions + stats->defaultelisions), - (stats->fgemissions + stats->fgelisions) == 0 ? 0 : - (stats->fgelisions * 100.0) / (stats->fgemissions + stats->fgelisions), - (stats->bgemissions + stats->bgelisions) == 0 ? 0 : - (stats->bgelisions * 100.0) / (stats->bgemissions + stats->bgelisions)); - } + summarize_stats(nc); } del_curterm(cur_term); ret |= pthread_mutex_destroy(&nc->statlock); diff --git a/src/lib/sixel.c b/src/lib/sixel.c index b289bae80..601839627 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -251,6 +251,7 @@ int sixel_blit_inner(ncplane* nc, int placey, int placex, int lenx, free(buf); return -1; } + cell_set_pixels(c, 1); free(buf); return 1; } diff --git a/src/lib/stats.c b/src/lib/stats.c new file mode 100644 index 000000000..239a0feee --- /dev/null +++ b/src/lib/stats.c @@ -0,0 +1,142 @@ +#include "internal.h" + +void reset_stats(ncstats* stats){ + uint64_t fbbytes = stats->fbbytes; + unsigned planes = stats->planes; + memset(stats, 0, sizeof(*stats)); + stats->render_min_ns = 1ull << 62u; + stats->render_min_bytes = 1ull << 62u; + stats->raster_min_ns = 1ull << 62u; + stats->writeout_min_ns = 1ull << 62u; + stats->fbbytes = fbbytes; + stats->planes = planes; +} + +void notcurses_stats(notcurses* nc, ncstats* stats){ + pthread_mutex_lock(&nc->statlock); + memcpy(stats, &nc->stats, sizeof(*stats)); + pthread_mutex_unlock(&nc->statlock); +} + +ncstats* notcurses_stats_alloc(const notcurses* nc __attribute__ ((unused))){ + return malloc(sizeof(ncstats)); +} + +void notcurses_stats_reset(notcurses* nc, ncstats* stats){ + pthread_mutex_lock(&nc->statlock); + if(stats){ + memcpy(stats, &nc->stats, sizeof(*stats)); + } + // add the stats to the stashed stats, so that we can show true totals on + // shutdown in the closing banner + ncstats* stash = &nc->stashed_stats; + if(nc->stats.render_min_ns < stash->render_min_ns){ + stash->render_min_ns = nc->stats.render_min_ns; + } + if(nc->stats.render_min_bytes < stash->render_min_bytes){ + stash->render_min_bytes = nc->stats.render_min_bytes; + } + if(nc->stats.raster_min_ns < stash->raster_min_ns){ + stash->raster_min_ns = nc->stats.raster_min_ns; + } + if(nc->stats.writeout_min_ns < stash->writeout_min_ns){ + stash->writeout_min_ns = nc->stats.writeout_min_ns; + } + if(nc->stats.render_max_ns > stash->render_max_ns){ + stash->render_max_ns = nc->stats.render_max_ns; + } + if(nc->stats.render_max_bytes > stash->render_max_bytes){ + stash->render_max_bytes = nc->stats.render_max_bytes; + } + if(nc->stats.raster_max_ns > stash->raster_max_ns){ + stash->raster_max_ns = nc->stats.raster_max_ns; + } + if(nc->stats.writeout_max_ns > stash->writeout_max_ns){ + stash->writeout_max_ns = nc->stats.writeout_max_ns; + } + stash->writeout_ns += nc->stats.writeout_ns; + stash->raster_ns += nc->stats.raster_ns; + stash->render_ns += nc->stats.render_ns; + stash->render_bytes += nc->stats.render_bytes; + stash->failed_renders += nc->stats.failed_renders; + stash->failed_writeouts += nc->stats.failed_writeouts; + stash->renders += nc->stats.renders; + stash->writeouts += nc->stats.writeouts; + stash->cellelisions += nc->stats.cellelisions; + stash->cellemissions += nc->stats.cellemissions; + stash->fgelisions += nc->stats.fgelisions; + stash->fgemissions += nc->stats.fgemissions; + stash->bgelisions += nc->stats.bgelisions; + stash->bgemissions += nc->stats.bgemissions; + stash->defaultelisions += nc->stats.defaultelisions; + stash->defaultemissions += nc->stats.defaultemissions; + stash->refreshes = nc->stats.refreshes; + stash->fbbytes = nc->stats.fbbytes; + stash->planes = nc->stats.planes; + reset_stats(&nc->stats); + pthread_mutex_unlock(&nc->statlock); +} + +void summarize_stats(notcurses* nc){ + const ncstats *stats = &nc->stashed_stats; + if(stats->renders){ + char totalbuf[BPREFIXSTRLEN + 1]; + char minbuf[BPREFIXSTRLEN + 1]; + char maxbuf[BPREFIXSTRLEN + 1]; + char avgbuf[BPREFIXSTRLEN + 1]; + qprefix(stats->render_ns, NANOSECS_IN_SEC, totalbuf, 0); + qprefix(stats->render_min_ns, NANOSECS_IN_SEC, minbuf, 0); + qprefix(stats->render_max_ns, NANOSECS_IN_SEC, maxbuf, 0); + qprefix(stats->render_ns / stats->renders, NANOSECS_IN_SEC, avgbuf, 0); + fprintf(stderr, "\n%ju render%s, %ss (%ss min, %ss avg, %ss max)\n", + stats->renders, stats->renders == 1 ? "" : "s", + totalbuf, minbuf, avgbuf, maxbuf); + qprefix(stats->raster_ns, NANOSECS_IN_SEC, totalbuf, 0); + qprefix(stats->raster_min_ns, NANOSECS_IN_SEC, minbuf, 0); + qprefix(stats->raster_max_ns, NANOSECS_IN_SEC, maxbuf, 0); + qprefix(stats->raster_ns / stats->writeouts, NANOSECS_IN_SEC, avgbuf, 0); + fprintf(stderr, "%ju raster%s, %ss (%ss min, %ss avg, %ss max)\n", + stats->writeouts, stats->writeouts == 1 ? "" : "s", + totalbuf, minbuf, avgbuf, maxbuf); + qprefix(stats->writeout_ns, NANOSECS_IN_SEC, totalbuf, 0); + qprefix(stats->writeout_min_ns, NANOSECS_IN_SEC, minbuf, 0); + qprefix(stats->writeout_max_ns, NANOSECS_IN_SEC, maxbuf, 0); + qprefix(stats->writeouts ? stats->writeout_ns / stats->writeouts : 0, + NANOSECS_IN_SEC, avgbuf, 0); + fprintf(stderr, "%ju write%s, %ss (%ss min, %ss avg, %ss max)\n", + stats->writeouts, stats->writeouts == 1 ? "" : "s", + totalbuf, minbuf, avgbuf, maxbuf); + bprefix(stats->render_bytes, 1, totalbuf, 1), + bprefix(stats->render_min_bytes, 1, minbuf, 1), + bprefix(stats->renders ? stats->render_bytes / stats->renders : 0, 1, avgbuf, 1); + bprefix(stats->render_max_bytes, 1, maxbuf, 1), + fprintf(stderr, "%sB (%sB min, %sB avg, %sB max)\n", + totalbuf, minbuf, avgbuf, maxbuf); + } + if(stats->renders || stats->failed_renders){ + fprintf(stderr, "%ju failed render%s, %ju failed write%s, %ju refresh%s\n", + stats->failed_renders, + stats->failed_renders == 1 ? "" : "s", + stats->failed_writeouts, + stats->failed_writeouts == 1 ? "" : "s", + stats->refreshes, + stats->refreshes == 1 ? "" : "es"); + fprintf(stderr, "RGB emits:elides: def %ju:%ju fg %ju:%ju bg %ju:%ju\n", + stats->defaultemissions, + stats->defaultelisions, + stats->fgemissions, + stats->fgelisions, + stats->bgemissions, + stats->bgelisions); + fprintf(stderr, "Cell emits:elides: %ju/%ju (%.2f%%) %.2f%% %.2f%% %.2f%%\n", + stats->cellemissions, stats->cellelisions, + (stats->cellemissions + stats->cellelisions) == 0 ? 0 : + (stats->cellelisions * 100.0) / (stats->cellemissions + stats->cellelisions), + (stats->defaultemissions + stats->defaultelisions) == 0 ? 0 : + (stats->defaultelisions * 100.0) / (stats->defaultemissions + stats->defaultelisions), + (stats->fgemissions + stats->fgelisions) == 0 ? 0 : + (stats->fgelisions * 100.0) / (stats->fgemissions + stats->fgelisions), + (stats->bgemissions + stats->bgelisions) == 0 ? 0 : + (stats->bgelisions * 100.0) / (stats->bgemissions + stats->bgelisions)); + } +} diff --git a/src/lib/visual.cpp b/src/lib/visual.cpp index 8e2d33d1d..990944051 100644 --- a/src/lib/visual.cpp +++ b/src/lib/visual.cpp @@ -16,7 +16,7 @@ auto ncvisual_decode(ncvisual* nc) -> int { auto ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n, const struct blitset* bset, int placey, int placex, int begy, int begx, int leny, int lenx, - bool blendcolors) -> int { + unsigned blendcolors) -> int { int ret = -1; if(visual_implementation){ if(visual_implementation->visual_blit(ncv, rows, cols, n, bset, placey, placex, @@ -523,7 +523,7 @@ auto ncvisual_render_pixels(tinfo* tcache, ncvisual* ncv, const blitset* bset, if(scaling == NCSCALE_SCALE || scaling == NCSCALE_SCALE_HIRES){ scale_visual(ncv, &disprows, &dispcols); } -//fprintf(stderr, "blit: %dx%d <- %dx%d:%d+%d of %d/%d stride %u @%dx%d %p\n", disprows, dispcols, begy, begx, leny, lenx, ncv->rows, ncv->cols, ncv->rowstride, placey, placex, ncv->data); +//fprintf(stderr, "pblit: %dx%d <- %dx%d of %d/%d stride %u @%dx%d %p %u\n", disprows, dispcols, begy, begx, ncv->rows, ncv->cols, ncv->rowstride, placey, placex, ncv->data, ncplane_notcurses(stdn)->tcache.cellpixx); if(ncvisual_blit(ncv, disprows, dispcols, n, bset, placey, placex, begy, begx, disprows, dispcols, ncplane_notcurses(stdn)->tcache.cellpixx)){ diff --git a/src/media/ffmpeg.cpp b/src/media/ffmpeg.cpp index 4b7f62a45..67cd4db51 100644 --- a/src/media/ffmpeg.cpp +++ b/src/media/ffmpeg.cpp @@ -469,7 +469,7 @@ int ffmpeg_decode_loop(ncvisual* ncv){ int ffmpeg_blit(ncvisual* ncv, int rows, int cols, ncplane* n, const struct blitset* bset, int placey, int placex, - int begy, int begx, int leny, int lenx, bool blendcolors) { + int begy, int begx, int leny, int lenx, unsigned blendcolors) { const AVFrame* inframe = ncv->details->oframe ? ncv->details->oframe : ncv->details->frame; //fprintf(stderr, "inframe: %p oframe: %p frame: %p\n", inframe, ncv->details->oframe, ncv->details->frame); void* data = nullptr; diff --git a/src/media/oiio.cpp b/src/media/oiio.cpp index 70e6c20b1..4e27f07e5 100644 --- a/src/media/oiio.cpp +++ b/src/media/oiio.cpp @@ -150,7 +150,7 @@ int oiio_resize(ncvisual* nc, int rows, int cols) { int oiio_blit(struct ncvisual* ncv, int rows, int cols, ncplane* n, const struct blitset* bset, int placey, int placex, int begy, int begx, - int leny, int lenx, bool blendcolors) { + int leny, int lenx, unsigned blendcolors) { //fprintf(stderr, "%d/%d -> %d/%d on the resize\n", ncv->rows, ncv->cols, rows, cols); void* data = nullptr; int stride = 0;