From 280b3d2a948e965d7af7f017809c27a2b2ee2ce2 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 15 May 2022 22:18:51 +0300 Subject: [PATCH] - fixed C89 compliance issues with the last commit (rlebitmap/minifx) - moved minifx.c under scr, since it's a part - moved src/utils/RleBitmap.* under src/ since src is all about utility stuff anyway. - made filenames DOS 8.3 compatible and lowercase - fixed include malloc.h -> stdlib.h - removed casts from malloc - fixed indentation consistency issues in one file - added new files to the watcom makefile --- GNUmakefile | 2 +- Makefile | 10 +- src/minifx.c | 161 -------------------------- src/rlebmap.c | 309 +++++++++++++++++++++++++++++++++++++++++++++++++ src/rlebmap.h | 66 +++++++++++ src/scr/grise.c | 2 +- src/scr/minifx.c | 169 +++++++++++++++++++++++++++ src/utils/RleBitmap.c | 309 ------------------------------------------------- src/utils/RleBitmap.h | 66 ----------- 9 files changed, 552 insertions(+), 542 deletions(-) delete mode 100644 src/minifx.c create mode 100644 src/rlebmap.c create mode 100644 src/rlebmap.h create mode 100644 src/scr/minifx.c delete mode 100644 src/utils/RleBitmap.c delete mode 100644 src/utils/RleBitmap.h diff --git a/GNUmakefile b/GNUmakefile index ea8082c..767026f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,4 +1,4 @@ -src = $(wildcard src/*.c) $(wildcard src/3dgfx/*.c) $(wildcard src/scr/*.c) $(wildcard src/utils/*.c) \ +src = $(wildcard src/*.c) $(wildcard src/3dgfx/*.c) $(wildcard src/scr/*.c) \ $(wildcard src/glut/*.c) asmsrc = $(wildcard src/*.asm) obj = $(src:.c=.o) $(asmsrc:.asm=.o) diff --git a/Makefile b/Makefile index c862ea9..1f6ab07 100644 --- a/Makefile +++ b/Makefile @@ -9,12 +9,13 @@ srcobj = src/bsptree.obj src/cfgopt.obj src/console.obj src/demo.obj & src/dynarr.obj src/gfxutil.obj src/metasurf.obj src/noise.obj & src/rbtree.obj src/screen.obj src/tinyfps.obj src/treestor.obj & src/image.obj src/ts_text.obj src/util.obj src/util_s.obj src/cpuid.obj & - src/cpuid_s.obj src/darray.obj src/data.obj + src/cpuid_s.obj src/darray.obj src/data.obj src/rlebmap.obj scrobj = src/scr/bump.obj src/scr/fract.obj src/scr/greets.obj & src/scr/grise.obj src/scr/hairball.obj src/scr/infcubes.obj & src/scr/metaball.obj src/scr/plasma.obj src/scr/polytest.obj & src/scr/smoketxt.obj src/scr/thunder.obj src/scr/tilemaze.obj & - src/scr/tunnel.obj src/scr/cybersun.obj src/scr/raytrace.obj src/scr/rt.obj + src/scr/tunnel.obj src/scr/cybersun.obj src/scr/raytrace.obj & + src/scr/rt.obj src/scr/minifx.obj csprobj = cspr/dbgfont.obj cspr/confont.obj incpath = -Isrc -Isrc/dos -Isrc/3dgfx -Ilibs -Ilibs/imago/src -Ilibs/anim/src & @@ -32,12 +33,13 @@ srcobj = src\bsptree.obj src\cfgopt.obj src\console.obj src\demo.obj & src\dynarr.obj src\gfxutil.obj src\metasurf.obj src\noise.obj & src\rbtree.obj src\screen.obj src\tinyfps.obj src\treestor.obj & src\image.obj src\ts_text.obj src\util.obj src\util_s.obj src\cpuid.obj & - src\cpuid_s.obj src\darray.obj src\data.obj + src\cpuid_s.obj src\darray.obj src\data.obj src\rlebmap.obj scrobj = src\scr\bump.obj src\scr\fract.obj src\scr\greets.obj & src\scr\grise.obj src\scr\hairball.obj src\scr\infcubes.obj & src\scr\metaball.obj src\scr\plasma.obj src\scr\polytest.obj & src\scr\smoketxt.obj src\scr\thunder.obj src\scr\tilemaze.obj & - src\scr\tunnel.obj src\scr\cybersun.obj src\scr\raytrace.obj src\scr\rt.obj + src\scr\tunnel.obj src\scr\cybersun.obj src\scr\raytrace.obj & + src\scr\rt.obj src\scr\minifx.obj csprobj = cspr\dbgfont.obj cspr\confont.obj incpath = -Isrc -Isrc\dos -Isrc\3dgfx -Ilibs -Ilibs\imago\src -Ilibs\anim\src & diff --git a/src/minifx.c b/src/minifx.c deleted file mode 100644 index 59a3269..0000000 --- a/src/minifx.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "demo.h" -#include "imago2.h" -#include "screen.h" -#include -#include -#include -#include -#include - -#include - -/* APPROX. 170 FPS Minimum */ - -static int init(void); -static void destroy(void); -static void start(long trans_time); -static void stop(long trans_time); -static void draw(void); - -static void updatePropeller(float t, RleBitmap *rle); - -static unsigned short *backBuffer; - -static unsigned char miniFXBuffer[1024]; - -static long lastFrameTime = 0; - -static struct screen scr = {"minifx", init, destroy, start, 0, draw}; - -struct screen *minifx_screen(void) { - return &scr; -} - -static int init(void) { - /* Allocate back buffer */ - backBuffer = (unsigned short *)calloc(FB_WIDTH * FB_HEIGHT, sizeof(unsigned short)); - - return 0; -} - -static void destroy(void) { - free(backBuffer); - backBuffer = 0; -} - -static void start(long trans_time) { lastFrameTime = time_msec; } - -static void draw(void) { - long lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; - lastFrameTime = time_msec; - - int clearColor = 0x888888; - unsigned short clearColor16 = ((clearColor << 8) & 0xF800) /* R */ - | ((clearColor >> 5) & 0x07E0) /* G */ - | ((clearColor >> 19) & 0x001F); /* B */ - for (int i=0; i= 2; - } - } - - /* Then, encode to rle */ - rleEncode(rle, miniFXBuffer, 32, 32); - - /* Distribute the produced streaks so that they don't produce garbage when interpolated */ - rleDistributeStreaks(rle); -} diff --git a/src/rlebmap.c b/src/rlebmap.c new file mode 100644 index 0000000..de5e168 --- /dev/null +++ b/src/rlebmap.c @@ -0,0 +1,309 @@ +#include +#include +#include "rlebmap.h" + +/* Number of numbers per scanline. Each streak has 2 numbers (start, length) */ +#define RLE_ELEMENTS_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2 + +/* Two RLE_TYPE elements per streak (= start,length) */ +#define RLE_BYTES_PER_SCANLINE RLE_ELEMENTS_PER_SCANLINE * sizeof(RLE_TYPE) + +/* RLE_TYPE count required for storing an RLE of w,h */ +static int rleWorstCaseElementCount(int w, int h) { + /* Allocate an extra worst case for one scanline, which is w/2 streaks = w + * (start,length) elements */ + return h * RLE_ELEMENTS_PER_SCANLINE + w; +} + +/* Byte count of the 'scans' buffer */ +static int rleScansByteCount(RleBitmap *rle) { + return rleWorstCaseElementCount(rle->w, rle->h) * sizeof(RLE_TYPE); +} + +RleBitmap *rleCreate(unsigned int w, unsigned int h) { + RleBitmap *ret = malloc(sizeof(RleBitmap)); + ret->w = w; + ret->h = h; + + /* Allocate scans */ + ret->scans = calloc(rleWorstCaseElementCount(w, h), sizeof(RLE_TYPE)); + + return ret; +} + +void rleDestroy(RleBitmap *b) { + if (!b) + return; + free(b->scans); + free(b); +} + +void rleClear(RleBitmap *rle) { memset(rle->scans, 0, rleScansByteCount(rle)); } + +RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, + unsigned int pixelsH) { + int x = 0; + int y = 0; + int streakActive = 0; + int currentStreakLength = 0; + RLE_TYPE *output = 0; + unsigned char *currentInputPixel = pixels; + + /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */ + if (!rle) + rle = rleCreate(pixelsW, pixelsH); + else + rleClear(rle); /* The following code assumes cleared array */ + + for (y = 0; y < pixelsH; y++) { + /* Go to the beginning of the RLE scan */ + output = rle->scans + y * RLE_ELEMENTS_PER_SCANLINE; + + for (x = 0; x < pixelsW; x++) { + if (*currentInputPixel++) { + if (streakActive) { + if (currentStreakLength >= RLE_MAX_STREAK_LENGTH) { + /* Do not allow streaks of more than max length - + * close current streak */ + *output++ = (RLE_TYPE)currentStreakLength; + + /* Begin new streak at current x */ + *output++ = (RLE_TYPE)x; + currentStreakLength = 0; + } + } else { + /* Begin new streak */ + *output++ = (RLE_TYPE)x; + currentStreakLength = 0; + streakActive = 1; + } + currentStreakLength++; + } else { + if (streakActive) { + /* Close current streak */ + *output++ = (RLE_TYPE)currentStreakLength; + currentStreakLength = 0; + streakActive = 0; + } + } /* End if (current pixel on) */ + } /* End for (all x) */ + + /* We reached the end of the scan - close any active streak */ + if (streakActive) { + *output++ = (RLE_TYPE)currentStreakLength; + } + streakActive = 0; + currentStreakLength = 0; + } /* End for (all scans */ + + return rle; +} + +void rleDistributeStreaks(RleBitmap *rle) { + int scanline = 0; + int halfW = rle->w >> 1; + RLE_TYPE *ptr = 0; + RLE_TYPE tmp = 0; + +#define LAST_STREAK RLE_STREAKS_PER_SCANLINE + + ptr = rle->scans; + for (scanline = 0; scanline < rle->h; scanline++) { + if (ptr[0] >= halfW) { + /* Exchange first with last streak */ + tmp = ptr[0]; + ptr[0] = ptr[LAST_STREAK * 2 - 2]; + ptr[LAST_STREAK * 2 - 2] = tmp; + tmp = ptr[1]; + ptr[1] = ptr[LAST_STREAK * 2 - 1]; + ptr[LAST_STREAK * 2 - 1] = tmp; + } + + ptr += 8; + } +} + +void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + RLE_TYPE *input = rle->scans; + unsigned short *output; + unsigned int *output32; + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline < blitY + rle->h; scanline++) { + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (int)*input++; + streakLength = (int)*input++; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst += dstStride; + } +} + +/* This is madness. We could at least check that we are not interpolating from 0 -> something + * (length). This could remove the need for 'distributeScans' */ +void interpolateScan(RLE_TYPE *output, RLE_TYPE *a, RLE_TYPE *b, float t) { + static int div = 1 << 23; + int ti, i; + + t += 1.0f; + ti = (*((unsigned int *)&t)) & 0x7FFFFF; + + for (i = 0; i < RLE_ELEMENTS_PER_SCANLINE; i++) { + if (*a == 0) { + *output++ = *b++; + a++; + } else { + if (*b == 0) { + *output++ = *a++; + b++; + } else { + *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23; + } + } + } +} + +void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY, float scaleX, float scaleY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned short *output; + unsigned int *output32; + unsigned char *input; + int scanlineCounter = 0; + int scaleXFixed; + static unsigned char scan[512]; + + /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ + int blitH = (int)(rle->h * scaleY + 0.5f); + + /* From this point on, scaleY will be inverted */ + scaleY = 1.0f / scaleY; + + scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline < blitY + blitH; scanline++) { + float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ + unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; + unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; + normalScan -= (int)normalScan; + interpolateScan(scan, scan0, scan1, normalScan); + input = scan; + scanlineCounter++; + + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst += dstStride; + } +} + +void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, + int blitX, int blitY, float scaleX, float scaleY) { + int scanline = 0; + int streakPos = 0; + int streakLength = 0; + int streak = 0; + unsigned short *output; + unsigned int *output32; + unsigned char *input; + int scanlineCounter = 0; + int scaleXFixed; + static unsigned char scan[512]; + + /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ + int blitH = (int)(rle->h * scaleY + 0.5f); + + /* From this point on, scaleY will be inverted */ + scaleY = 1.0f / scaleY; + + scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); + + dst += blitX + blitY * dstStride; + + for (scanline = blitY; scanline > blitY - blitH; scanline--) { + float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ + unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; + unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; + normalScan -= (int)normalScan; + interpolateScan(scan, scan0, scan1, normalScan); + input = scan; + scanlineCounter++; + + if (scanline < 0 || scanline >= dstH) + continue; + for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { + streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; + + if ((streakPos + blitX) <= 0) + continue; + + output = dst + streakPos; + + /* Check if we need to write the first pixel as 16bit */ + if (streakLength % 2) { + *output++ = RLE_FILL_COLOR; + } + + /* Then, write 2 pixels at a time */ + streakLength >>= 1; + output32 = (unsigned int *)output; + while (streakLength--) { + *output32++ = RLE_FILL_COLOR_32; + } + } + + dst -= dstStride; + } +} diff --git a/src/rlebmap.h b/src/rlebmap.h new file mode 100644 index 0000000..3f36b16 --- /dev/null +++ b/src/rlebmap.h @@ -0,0 +1,66 @@ +#ifndef __RLE_BITMAP_H__ +#define __RLE_BITMAP_H__ + +/* Limit streak count per scanline so we can directly jump to specific scanline + */ +#define RLE_STREAKS_PER_SCANLINE 4 + +/* Streaks will not exceed this many pixels. This allows us to optimize with a + * padded framebuffer. If a streak start position happens to lie within + * framebuffer, we will blit it without checking for out of bounds */ +#define RLE_MAX_STREAK_LENGTH 32 + +/* Using the following type for storing start and for storing length in (start, + * length) pairs. */ +#define RLE_TYPE unsigned char + +/* For now, keep a static fill color. We can change this. Not that much about + * speed, but let's keep function definitions more compact. */ +#define RLE_FILL_COLOR 0 + +/* Two entries of RLE_FILL_COLOR (16 bits) packed one after the other. */ +#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR) + +/* For fixed-point arithmetic. Used for scaling. */ +#define RLE_FIXED_BITS 16 + +/* This is a bitmap (image in 1bpp), encoded as streaks of consecutive pixels. + */ +typedef struct { + unsigned int w, h; + + /* Each scan is RLE_BYTES_PER_SCANLINE long and contains pairs of + * (start, length). */ + RLE_TYPE *scans; +} RleBitmap; + +/* Constructor */ +RleBitmap *rleCreate(unsigned int w, unsigned int h); + +/* Destructor */ +void rleDestroy(RleBitmap *rle); + +/* Clears 'rle' to "all transparent" */ +void rleClear(RleBitmap *rle); + +/* Encode 'pixels' into 'rle' and also return it. Pixels are either 0 or 1. This + * will create an RleBitmap of 'h' scanlines. */ +RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, + unsigned int pixelsH); + +/* Rearranges the streaks to make it less frequent that they produce garbege when interpolated */ +void rleDistributeStreaks(RleBitmap *rle); + +/* Blits without scaling */ +void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY); + +/* Scaled blit */ +void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, + int blitY, float scaleX, float scaleY); + +/* Inverted blit (upside down) */ +void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, + int blitX, int blitY, float scaleX, float scaleY); + +#endif // __RLE_BITMAP_H__ diff --git a/src/scr/grise.c b/src/scr/grise.c index 36e9ff9..c4a2e28 100644 --- a/src/scr/grise.c +++ b/src/scr/grise.c @@ -7,7 +7,7 @@ #include #include -#include +#include "rlebmap.h" /* APPROX. 170 FPS Minimum */ diff --git a/src/scr/minifx.c b/src/scr/minifx.c new file mode 100644 index 0000000..84f9c38 --- /dev/null +++ b/src/scr/minifx.c @@ -0,0 +1,169 @@ +#include "demo.h" +#include "imago2.h" +#include "screen.h" +#include +#include +#include +#include +#include + +#include "rlebmap.h" + +/* APPROX. 170 FPS Minimum */ + +static int init(void); +static void destroy(void); +static void start(long trans_time); +static void stop(long trans_time); +static void draw(void); + +static void updatePropeller(float t, RleBitmap *rle); + +static unsigned short *backBuffer; + +static unsigned char miniFXBuffer[1024]; + +static long lastFrameTime = 0; + +static struct screen scr = {"minifx", init, destroy, start, 0, draw}; + +struct screen *minifx_screen(void) { + return &scr; +} + +static int init(void) { + /* Allocate back buffer */ + backBuffer = calloc(FB_WIDTH * FB_HEIGHT, sizeof(unsigned short)); + + return 0; +} + +static void destroy(void) { + free(backBuffer); + backBuffer = 0; +} + +static void start(long trans_time) { lastFrameTime = time_msec; } + +static void draw(void) { + long lastFrameDuration; + int i, stride; + RleBitmap *rle; + int clearColor; + unsigned short clearColor16; + + lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; + lastFrameTime = time_msec; + + clearColor = 0x888888; + clearColor16 = ((clearColor << 8) & 0xF800) /* R */ + | ((clearColor >> 5) & 0x07E0) /* G */ + | ((clearColor >> 19) & 0x001F); /* B */ + + for (i=0; i= 2; + } + } + + /* Then, encode to rle */ + rleEncode(rle, miniFXBuffer, 32, 32); + + /* Distribute the produced streaks so that they don't produce garbage when interpolated */ + rleDistributeStreaks(rle); +} diff --git a/src/utils/RleBitmap.c b/src/utils/RleBitmap.c deleted file mode 100644 index 8c344f2..0000000 --- a/src/utils/RleBitmap.c +++ /dev/null @@ -1,309 +0,0 @@ -#include "RleBitmap.h" -#include -#include - -/* Number of numbers per scanline. Each streak has 2 numbers (start, length) */ -#define RLE_ELEMENTS_PER_SCANLINE RLE_STREAKS_PER_SCANLINE * 2 - -/* Two RLE_TYPE elements per streak (= start,length) */ -#define RLE_BYTES_PER_SCANLINE RLE_ELEMENTS_PER_SCANLINE * sizeof(RLE_TYPE) - -/* RLE_TYPE count required for storing an RLE of w,h */ -static int rleWorstCaseElementCount(int w, int h) { - /* Allocate an extra worst case for one scanline, which is w/2 streaks = w - * (start,length) elements */ - return h * RLE_ELEMENTS_PER_SCANLINE + w; -} - -/* Byte count of the 'scans' buffer */ -static int rleScansByteCount(RleBitmap *rle) { - return rleWorstCaseElementCount(rle->w, rle->h) * sizeof(RLE_TYPE); -} - -RleBitmap *rleCreate(unsigned int w, unsigned int h) { - RleBitmap *ret = (RleBitmap *)malloc(sizeof(RleBitmap)); - ret->w = w; - ret->h = h; - - /* Allocate scans */ - ret->scans = (RLE_TYPE *)calloc(rleWorstCaseElementCount(w, h), sizeof(RLE_TYPE)); - - return ret; -} - -void rleDestroy(RleBitmap *b) { - if (!b) - return; - free(b->scans); - free(b); -} - -void rleClear(RleBitmap *rle) { memset(rle->scans, 0, rleScansByteCount(rle)); } - -RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, - unsigned int pixelsH) { - int x = 0; - int y = 0; - int streakActive = 0; - int currentStreakLength = 0; - RLE_TYPE *output = 0; - unsigned char *currentInputPixel = pixels; - - /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */ - if (!rle) - rle = rleCreate(pixelsW, pixelsH); - else - rleClear(rle); /* The following code assumes cleared array */ - - for (y = 0; y < pixelsH; y++) { - /* Go to the beginning of the RLE scan */ - output = rle->scans + y * RLE_ELEMENTS_PER_SCANLINE; - - for (x = 0; x < pixelsW; x++) { - if (*currentInputPixel++) { - if (streakActive) { - if (currentStreakLength >= RLE_MAX_STREAK_LENGTH) { - /* Do not allow streaks of more than max length - - * close current streak */ - *output++ = (RLE_TYPE)currentStreakLength; - - /* Begin new streak at current x */ - *output++ = (RLE_TYPE)x; - currentStreakLength = 0; - } - } else { - /* Begin new streak */ - *output++ = (RLE_TYPE)x; - currentStreakLength = 0; - streakActive = 1; - } - currentStreakLength++; - } else { - if (streakActive) { - /* Close current streak */ - *output++ = (RLE_TYPE)currentStreakLength; - currentStreakLength = 0; - streakActive = 0; - } - } /* End if (current pixel on) */ - } /* End for (all x) */ - - /* We reached the end of the scan - close any active streak */ - if (streakActive) { - *output++ = (RLE_TYPE)currentStreakLength; - } - streakActive = 0; - currentStreakLength = 0; - } /* End for (all scans */ - - return rle; -} - -void rleDistributeStreaks(RleBitmap *rle) { - int scanline = 0; - int halfW = rle->w >> 1; - RLE_TYPE *ptr = 0; - RLE_TYPE tmp = 0; - -#define LAST_STREAK RLE_STREAKS_PER_SCANLINE - - ptr = rle->scans; - for (scanline = 0; scanline < rle->h; scanline++) { - if (ptr[0] >= halfW) { - /* Exchange first with last streak */ - tmp = ptr[0]; - ptr[0] = ptr[LAST_STREAK * 2 - 2]; - ptr[LAST_STREAK * 2 - 2] = tmp; - tmp = ptr[1]; - ptr[1] = ptr[LAST_STREAK * 2 - 1]; - ptr[LAST_STREAK * 2 - 1] = tmp; - } - - ptr += 8; - } -} - -void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, - int blitY) { - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - RLE_TYPE *input = rle->scans; - unsigned short *output; - unsigned int *output32; - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline < blitY + rle->h; scanline++) { - if (scanline < 0 || scanline >= dstH) - continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (int)*input++; - streakLength = (int)*input++; - - if ((streakPos + blitX) <= 0) - continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int *)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst += dstStride; - } -} - -/* This is madness. We could at least check that we are not interpolating from 0 -> something - * (length). This could remove the need for 'distributeScans' */ -void interpolateScan(RLE_TYPE *output, RLE_TYPE *a, RLE_TYPE *b, float t) { - static int div = 1 << 23; - int ti, i; - - t += 1.0f; - ti = (*((unsigned int *)&t)) & 0x7FFFFF; - - for (i = 0; i < RLE_ELEMENTS_PER_SCANLINE; i++) { - if (*a == 0) { - *output++ = *b++; - a++; - } else { - if (*b == 0) { - *output++ = *a++; - b++; - } else { - *output++ = ((*b++ * ti) + (*a++ * (div - ti))) >> 23; - } - } - } -} - -void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, - int blitY, float scaleX, float scaleY) { - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned short *output; - unsigned int *output32; - unsigned char *input; - int scanlineCounter = 0; - int scaleXFixed; - static unsigned char scan[512]; - - /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ - int blitH = (int)(rle->h * scaleY + 0.5f); - - /* From this point on, scaleY will be inverted */ - scaleY = 1.0f / scaleY; - - scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline < blitY + blitH; scanline++) { - float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ - unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; - unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; - normalScan -= (int)normalScan; - interpolateScan(scan, scan0, scan1, normalScan); - input = scan; - scanlineCounter++; - - if (scanline < 0 || scanline >= dstH) - continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - - if ((streakPos + blitX) <= 0) - continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int *)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst += dstStride; - } -} - -void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, - int blitX, int blitY, float scaleX, float scaleY) { - int scanline = 0; - int streakPos = 0; - int streakLength = 0; - int streak = 0; - unsigned short *output; - unsigned int *output32; - unsigned char *input; - int scanlineCounter = 0; - int scaleXFixed; - static unsigned char scan[512]; - - /*int blitW = (int)(rle->w * scaleX + 0.5f);*/ - int blitH = (int)(rle->h * scaleY + 0.5f); - - /* From this point on, scaleY will be inverted */ - scaleY = 1.0f / scaleY; - - scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f); - - dst += blitX + blitY * dstStride; - - for (scanline = blitY; scanline > blitY - blitH; scanline--) { - float normalScan = scanlineCounter * scaleY; /* ScaleY is inverted */ - unsigned char *scan0 = rle->scans + RLE_BYTES_PER_SCANLINE * (int)normalScan; - unsigned char *scan1 = scan0 + RLE_BYTES_PER_SCANLINE; - normalScan -= (int)normalScan; - interpolateScan(scan, scan0, scan1, normalScan); - input = scan; - scanlineCounter++; - - if (scanline < 0 || scanline >= dstH) - continue; - for (streak = 0; streak < RLE_STREAKS_PER_SCANLINE; streak++) { - streakPos = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - streakLength = (*input++ * scaleXFixed) >> RLE_FIXED_BITS; - - if ((streakPos + blitX) <= 0) - continue; - - output = dst + streakPos; - - /* Check if we need to write the first pixel as 16bit */ - if (streakLength % 2) { - *output++ = RLE_FILL_COLOR; - } - - /* Then, write 2 pixels at a time */ - streakLength >>= 1; - output32 = (unsigned int *)output; - while (streakLength--) { - *output32++ = RLE_FILL_COLOR_32; - } - } - - dst -= dstStride; - } -} diff --git a/src/utils/RleBitmap.h b/src/utils/RleBitmap.h deleted file mode 100644 index 3f36b16..0000000 --- a/src/utils/RleBitmap.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __RLE_BITMAP_H__ -#define __RLE_BITMAP_H__ - -/* Limit streak count per scanline so we can directly jump to specific scanline - */ -#define RLE_STREAKS_PER_SCANLINE 4 - -/* Streaks will not exceed this many pixels. This allows us to optimize with a - * padded framebuffer. If a streak start position happens to lie within - * framebuffer, we will blit it without checking for out of bounds */ -#define RLE_MAX_STREAK_LENGTH 32 - -/* Using the following type for storing start and for storing length in (start, - * length) pairs. */ -#define RLE_TYPE unsigned char - -/* For now, keep a static fill color. We can change this. Not that much about - * speed, but let's keep function definitions more compact. */ -#define RLE_FILL_COLOR 0 - -/* Two entries of RLE_FILL_COLOR (16 bits) packed one after the other. */ -#define RLE_FILL_COLOR_32 ((RLE_FILL_COLOR << 16) | RLE_FILL_COLOR) - -/* For fixed-point arithmetic. Used for scaling. */ -#define RLE_FIXED_BITS 16 - -/* This is a bitmap (image in 1bpp), encoded as streaks of consecutive pixels. - */ -typedef struct { - unsigned int w, h; - - /* Each scan is RLE_BYTES_PER_SCANLINE long and contains pairs of - * (start, length). */ - RLE_TYPE *scans; -} RleBitmap; - -/* Constructor */ -RleBitmap *rleCreate(unsigned int w, unsigned int h); - -/* Destructor */ -void rleDestroy(RleBitmap *rle); - -/* Clears 'rle' to "all transparent" */ -void rleClear(RleBitmap *rle); - -/* Encode 'pixels' into 'rle' and also return it. Pixels are either 0 or 1. This - * will create an RleBitmap of 'h' scanlines. */ -RleBitmap *rleEncode(RleBitmap *rle, unsigned char *pixels, unsigned int pixelsW, - unsigned int pixelsH); - -/* Rearranges the streaks to make it less frequent that they produce garbege when interpolated */ -void rleDistributeStreaks(RleBitmap *rle); - -/* Blits without scaling */ -void rleBlit(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, - int blitY); - -/* Scaled blit */ -void rleBlitScale(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, int blitX, - int blitY, float scaleX, float scaleY); - -/* Inverted blit (upside down) */ -void rleBlitScaleInv(RleBitmap *rle, unsigned short *dst, int dstW, int dstH, int dstStride, - int blitX, int blitY, float scaleX, float scaleY); - -#endif // __RLE_BITMAP_H__ -- 1.7.10.4