The objective is speed.
The GrArea is not available on ELKS, so instead the EmuGrArea is used in nxjpeg. GrArea draws generic rectangles of raw pixels, while GrDrawIndexedSpanBuffer draws pre-quantized palette-index rows more efficiently by collapsing them into horizontal color runs.
This is a very experimental move of EmuGrArea to server side of Nano-X. It should reside in src/server/srvdraw.c.
#include "srvdraw.h"
#include "device.h"
#include "devfont.h"
#include "devdraw.h"
#include "serv.h"
/* Draws a block of indexed pixels by grouping consecutive pixels
* of the same color into horizontal runs, then drawing each run
* in one operation (faster than per-pixel drawing).
*/
void srv_DrawIndexedSpanBuffer(GR_CLIENT *cl, GR_DRAW_INDEXED_SPAN_BUFFER_REQ *req)
{
GR_WINDOW *wp = GsFindWindow(req->wid);
if (!wp) return;
/* read raw data buffer sent by client */
const unsigned char *buf = (const unsigned char *)GsReadData(req->pitch * req->h);
if (!buf) return;
int x = req->x;
int y = req->y;
int w = req->w;
int h = req->h;
int pitch = req->pitch;
/* Loop through scanlines */
for (int iy = 0; iy < h; ++iy) {
const unsigned char *row = buf + iy * pitch;
int run_start = 0;
unsigned char run_idx = row[0];
/* Scan through each pixel to detect runs */
for (int ix = 1; ix < w; ++ix) {
if (row[ix] != run_idx) {
GdSetForegroundColorIndex(run_idx);
GdLine(x + run_start, y + iy,
x + ix - 1, y + iy,
wp->output);
run_start = ix;
run_idx = row[ix];
}
}
/* Draw final run */
GdSetForegroundColorIndex(run_idx);
GdLine(x + run_start, y + iy,
x + w - 1, y + iy,
wp->output);
}
/* Update window region */
GsExposeArea(wp, x, y, w, h);
}
The objective is speed.
The GrArea is not available on ELKS, so instead the EmuGrArea is used in nxjpeg. GrArea draws generic rectangles of raw pixels, while GrDrawIndexedSpanBuffer draws pre-quantized palette-index rows more efficiently by collapsing them into horizontal color runs.
This is a very experimental move of EmuGrArea to server side of Nano-X. It should reside in src/server/srvdraw.c.