Author: mesyeti <mesyeti@mesyeti.uk>
software backend working
source/backend.c | 4 ++ source/backend.h | 4 ++ source/backends/glLegacy.c | 6 +++ source/backends/soft.c | 65 +++++++++++++++++++++++++++++++++------ source/backends/stub.c | 6 +++ source/buffer.c | 16 +++++++++ source/buffer.h | 2 + source/screen.c | 2 +
diff --git a/source/backend.c b/source/backend.c
index 76f3f9d00ff9be9198b0eff97fff14e628709d0c..8032163580e267eb658649cc6ffff739cd683faf 100644
--- a/source/backend.c
+++ b/source/backend.c
@@ -30,6 +30,10 @@ void Backend_OnWindowResize(void) {
backend.onWindowResize();
}
+void Backend_OnScreenUpdate(void) {
+ backend.onScreenUpdate();
+}
+
void Backend_Render(void) {
backend.render();
}
diff --git a/source/backend.h b/source/backend.h
index fc69e3fce90219a92a5c6be18ab26ae3d6193460..24f308eb6f688dd333512fcf97389b06491373af 100644
--- a/source/backend.h
+++ b/source/backend.h
@@ -18,12 +18,15 @@
typedef void Texture;
typedef struct {
+ const char* name;
+
void (*init)(bool beforeWindow);
void (*free)(void);
Texture* (*loadTexture)(uint8_t* data, int w, int h, int aW, int aH, int ch);
void (*freeTexture)(Texture* texture);
Vec2 (*getTextureSize)(Texture* texture);
void (*onWindowResize)(void);
+ void (*onScreenUpdate)(void);
void (*render)(void);
} Backend;
@@ -34,6 +37,7 @@ Texture* Backend_LoadTexture(uint8_t* data, int w, int h, int aW, int aH, int ch);
void Backend_FreeTexture(Texture* texture);
Vec2 Backend_GetTextureSize(Texture* texture);
void Backend_OnWindowResize(void);
+void Backend_OnScreenUpdate(void);
void Backend_Render(void);
#endif
diff --git a/source/backends/glLegacy.c b/source/backends/glLegacy.c
index 67ccb46c3fefa8f4b716368a9a19a98a37d4cbbc..fbe2fa44f816f7d9bf023818d9bd738ae61bc24b 100644
--- a/source/backends/glLegacy.c
+++ b/source/backends/glLegacy.c
@@ -223,18 +223,24 @@ static void OnWindowResize(void) {
}
+static void OnScreenUpdate(void) {
+
+}
+
static void Render(void) {
}
Backend Backend_GLLegacy(void) {
return (Backend) {
+ .name = "gl 1.1",
.init = &Init,
.free = &Free,
.loadTexture = &LoadTexture,
.freeTexture = &FreeTexture,
.getTextureSize = &GetTextureSize,
.onWindowResize = &OnWindowResize,
+ .onScreenUpdate = &OnScreenUpdate,
.render = &Render
};
}
diff --git a/source/backends/soft.c b/source/backends/soft.c
index bb7573138c565991bc5596f62c30381e6ea07ab2..d86549c1fbdd90362ceb6b42cd455f76f6f87f22 100644
--- a/source/backends/soft.c
+++ b/source/backends/soft.c
@@ -1,4 +1,5 @@
#include <stdio.h>
+#include <assert.h>
#include "../log.h"
#include "../mem.h"
#include "../font.h"
@@ -22,6 +23,8 @@ BTexture textures[32];
uint32_t* buffer;
int bufferW;
int bufferH;
+ bool* changes;
+ bool redraw;
// SDL stuff
SDL_Renderer* renderer;
@@ -30,12 +33,27 @@ } State;
static State state;
+static uint32_t ColourToPixel(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
+ return r | (g << 8) | (b << 16) | (a << 24);
+ //return r + (rand() % 20) | (g + (rand() % 20) << 8) | (b + (rand() % 20) << 16) | (a << 24);
+}
+
static void DrawPixel(int x, int y, uint32_t colour) {
if ((x < 0) || (y < 0) || (y >= state.bufferH) || (x >= state.bufferW)) return;
state.buffer[(y * state.bufferW) + x] = colour;
}
+static uint8_t Component(uint32_t colour, uint8_t comp) {
+ switch (comp) {
+ case 0: return colour & 0x000000FF; // red
+ case 1: return (colour & 0x0000FF00) >> 8; // green
+ case 2: return (colour & 0x00FF0000) >> 16; // blue
+ case 3: return (colour & 0xFF000000) >> 24; // alpha
+ default: assert(0);
+ }
+}
+
static void Init(bool beforeWindow) {
if (beforeWindow) return;
@@ -64,6 +82,8 @@
state.buffer = SafeMalloc(video.windows[0].width * video.windows[0].height * sizeof(uint32_t));
state.bufferW = video.windows[0].width;
state.bufferH = video.windows[0].height;
+
+ state.changes = NULL;
}
static void Free(void) {
@@ -77,11 +97,6 @@ free(state.buffer);
SDL_DestroyTexture(state.texture);
SDL_DestroyRenderer(state.renderer);
-}
-
-static uint32_t ColourToPixel(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
- return r | (g << 8) | (b << 16) | (a << 24);
- //return r + (rand() % 20) | (g + (rand() % 20) << 8) | (b + (rand() % 20) << 16) | (a << 24);
}
static Texture* LoadTexture(uint8_t* data, int w, int h, int aW, int aH, int ch) {
@@ -122,6 +137,18 @@ static void OnWindowResize(void) {
}
+static void OnScreenUpdate(void) {
+ if (!state.changes) {
+ free(state.changes);
+ }
+
+ size_t size = screen.buffer.width * screen.buffer.height * sizeof(bool);
+ state.changes = SafeMalloc(size);
+ memset(state.changes, 0, size);
+
+ state.redraw = true;
+}
+
static void FillRect(int x, int y, int w, int h, Colour colour) {
for (int iy = 0; iy < h; ++ iy) {
for (int ix = 0; ix < w; ++ ix) {
@@ -140,15 +167,21 @@
int sx = ix + src.x;
int sy = iy + src.y;
- // DrawPixel(ix + x, iy + y, texture->pixels[(sy * texture->width) + sx]);
- DrawPixel(ix + x, iy + y, texture->pixels[(sy * texture->width) + sx]);
+ uint32_t srcPix = texture->pixels[(sy * texture->aWidth) + sx];
+ uint8_t alpha = Component(srcPix, 3);
+
+ if (alpha == 0) continue;
+
+ DrawPixel(ix + x, iy + y, srcPix);
}
}
}
static void Render(void) {
- for (int i = 0; i < state.bufferW * state.bufferH; ++ i) {
- state.buffer[i] = ColourToPixel(theme.bg.r, theme.bg.g, theme.bg.b, 255);
+ if (state.redraw) {
+ for (int i = 0; i < state.bufferW * state.bufferH; ++ i) {
+ state.buffer[i] = ColourToPixel(theme.bg.r, theme.bg.g, theme.bg.b, 255);
+ }
}
int cw;
@@ -157,6 +190,10 @@ Font_CharSize(&screen.font, &cw, &ch);
for (int y = 0; y < screen.buffer.height; ++ y) {
for (int x = 0; x < screen.buffer.width; ++ x) {
+ if (!state.changes[(y * screen.buffer.width) + x] && !state.redraw) continue;
+
+ state.changes[(y * screen.buffer.width) + x] = false;
+
int cx = x * cw;
int cy = y * ch;
@@ -166,10 +203,12 @@ ColourRGB fg = Screen_GetColour(true, cell->fgMode, cell->fg);
ColourRGB bg = Screen_GetColour(false, cell->bgMode, cell->bg);
FillRect(cx, cy, cw, ch, (Colour) {bg.r, bg.g, bg.b, 255});
+
+ if ((cell->ch == ' ') || (cell->ch == 0)) continue;
Rect src;
- src.x = ((int) (ch % 16)) * cw;
- src.y = ((int) (ch / 16)) * ch;
+ src.x = ((int) (cell->ch % 16)) * cw;
+ src.y = ((int) (cell->ch / 16)) * ch;
src.w = cw;
src.h = ch;
@@ -177,6 +216,8 @@ Blit((BTexture*) screen.font.v.bm.texture, cx, cy, src, (Colour) {fg.r, fg.g, fg.b, 255});
}
}
+ state.redraw = false;
+
SDL_RenderClear(state.renderer);
SDL_UpdateTexture(state.texture, NULL, state.buffer, state.bufferW * 4);
SDL_RenderCopy(state.renderer, state.texture, NULL, NULL);
@@ -185,12 +226,14 @@ }
Backend Backend_Soft(void) {
return (Backend) {
+ .name = "soft",
.init = &Init,
.free = &Free,
.loadTexture = &LoadTexture,
.freeTexture = &FreeTexture,
.getTextureSize = &GetTextureSize,
.onWindowResize = &OnWindowResize,
+ .onScreenUpdate = &OnScreenUpdate,
.render = &Render
};
}
diff --git a/source/backends/stub.c b/source/backends/stub.c
index 6d7dfe19e8f2b7b5174ed71d944f0d5eec673443..c8d879b1779adaf28cd4bcda1032f4f7c126fd54 100644
--- a/source/backends/stub.c
+++ b/source/backends/stub.c
@@ -33,18 +33,24 @@ static void OnWindowResize(void) {
}
+static void OnScreenUpdate(void) {
+
+}
+
static void Render(void) {
}
Backend Backend_Stub(void) {
return (Backend) {
+ .name = "stub",
.init = &Init,
.free = &Free,
.loadTexture = &LoadTexture,
.freeTexture = &FreeTexture,
.getTextureSize = &GetTextureSize,
.onWindowResize = &OnWindowResize,
+ .onScreenUpdate = &OnScreenUpdate,
.render = &Render
};
}
diff --git a/source/buffer.c b/source/buffer.c
index 1fc8b68cc668162f9601bf50683997a6bad6d475..c6c1619e38bc0833c636f912368ce6735eec1caf 100644
--- a/source/buffer.c
+++ b/source/buffer.c
@@ -16,7 +16,7 @@ Buffer ret;
ret.buf = SafeMalloc(width * height * sizeof(BufCell));
for (int i = 0; i < width * height; ++ i) {
- ret.buf[i] = FromChar('a');
+ ret.buf[i] = FromChar(0);
}
ret.width = width;
@@ -39,3 +39,17 @@ if ((x < 0) || (y < 0) || (x >= buf->width) || (y >= buf->height)) return NULL;
return &buf->buf[(y * buf->width) + x];
}
+
+void Buffer_Blit(Buffer* dest, Buffer* src, int x, int y, Rect clip) {
+ for (int iy = 0; iy < clip.h; ++ iy) {
+ for (int ix = 0; ix < clip.w; ++ ix) {
+ if ((clip.x + ix >= src->width) || (clip.y + iy >= src->height)) continue;
+
+ int sx = ix + clip.x;
+ int sy = iy + clip.y;
+
+ BufCell* cell = Buffer_Get(src, sx, sy);
+ *Buffer_Get(dest, x + ix, y + iy) = *cell;
+ }
+ }
+}
diff --git a/source/buffer.h b/source/buffer.h
index 6ef2d01260d3b857d75017dbfd9e00d19bb1b2e7..7ae1a1806cc0970c593c5c536a19d8d3b07a29c4 100644
--- a/source/buffer.h
+++ b/source/buffer.h
@@ -2,6 +2,7 @@ #ifndef YT_BUFFER_H
#define YT_BUFFER_H
#include "char.h"
+#include "types.h"
#include "video.h"
enum {
@@ -34,5 +35,6 @@ Buffer Buffer_New(int width, int height);
void Buffer_Free(Buffer* buf);
void Buffer_WriteChar(Buffer* buf, UChar ch, int x, int y);
BufCell* Buffer_Get(Buffer* buf, int x, int y);
+void Buffer_Blit(Buffer* dest, Buffer* src, int x, int y, Rect clip);
#endif
diff --git a/source/screen.c b/source/screen.c
index 91ff0e30648f3712ead9f7bf7521dd38c23617a7..271ac94133b21efb3794d6b992d1b265c83a392f 100644
--- a/source/screen.c
+++ b/source/screen.c
@@ -25,6 +25,8 @@ int ch;
Font_CharSize(&screen.font, &cw, &ch);
screen.buffer = Buffer_New(video.windows[0].width / cw, video.windows[0].height / ch);
+
+ Backend_OnScreenUpdate();
}
void Screen_Free(void) {