diff options
author | Bad Diode <bd@badd10de.dev> | 2021-09-08 14:52:24 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-09-08 14:52:24 +0200 |
commit | e98ffd3a32cff5d367d360be9ebe2d1e1a416054 (patch) | |
tree | 6159609637ab5c532df66762c4167c09c4192004 | |
parent | 7654bb013814d7cf317f7dfd69238abe6dc30ef1 (diff) | |
download | uxnrpi-e98ffd3a32cff5d367d360be9ebe2d1e1a416054.tar.gz uxnrpi-e98ffd3a32cff5d367d360be9ebe2d1e1a416054.zip |
Add dirty lines and redraw optimization to ppu
-rw-r--r-- | src/main.c | 12 | ||||
-rw-r--r-- | src/ppu.c | 40 |
2 files changed, 42 insertions, 10 deletions
@@ -44,6 +44,10 @@ docolors(Device *d) { | |||
44 | for(size_t i = 4; i < 16; ++i) { | 44 | for(size_t i = 4; i < 16; ++i) { |
45 | palette[i] = palette[i / 4]; | 45 | palette[i] = palette[i / 4]; |
46 | } | 46 | } |
47 | |||
48 | // Redraw the screen if we change the color palette. | ||
49 | reqdraw = 1; | ||
50 | redraw_screen(); | ||
47 | } | 51 | } |
48 | 52 | ||
49 | void | 53 | void |
@@ -74,6 +78,7 @@ screen_talk(Device *d, u8 b0, u8 w) { | |||
74 | Uint16 y = mempeek16(d->dat, 0xa); | 78 | Uint16 y = mempeek16(d->dat, 0xa); |
75 | Uint8 layer = d->dat[0xe] >> 4 & 0x1; | 79 | Uint8 layer = d->dat[0xe] >> 4 & 0x1; |
76 | ppu_pixel(&ppu, layer, x, y, d->dat[0xe] & 0x3); | 80 | ppu_pixel(&ppu, layer, x, y, d->dat[0xe] & 0x3); |
81 | reqdraw = 1; | ||
77 | } else if(w && b0 == 0xf) { | 82 | } else if(w && b0 == 0xf) { |
78 | Uint16 x = mempeek16(d->dat, 0x8); | 83 | Uint16 x = mempeek16(d->dat, 0x8); |
79 | Uint16 y = mempeek16(d->dat, 0xa); | 84 | Uint16 y = mempeek16(d->dat, 0xa); |
@@ -83,6 +88,7 @@ screen_talk(Device *d, u8 b0, u8 w) { | |||
83 | ppu_2bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] >> 0x4 & 0x1, d->dat[0xf] >> 0x5 & 0x1); | 88 | ppu_2bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] >> 0x4 & 0x1, d->dat[0xf] >> 0x5 & 0x1); |
84 | else | 89 | else |
85 | ppu_1bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] >> 0x4 & 0x1, d->dat[0xf] >> 0x5 & 0x1); | 90 | ppu_1bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] >> 0x4 & 0x1, d->dat[0xf] >> 0x5 & 0x1); |
91 | reqdraw = 1; | ||
86 | } | 92 | } |
87 | } | 93 | } |
88 | 94 | ||
@@ -153,10 +159,6 @@ void main(void) { | |||
153 | uxn_eval(&u, mempeek16(devscreen->dat, 0)); | 159 | uxn_eval(&u, mempeek16(devscreen->dat, 0)); |
154 | 160 | ||
155 | // Blit ppu.pixels to the framebuffer. | 161 | // Blit ppu.pixels to the framebuffer. |
156 | // NOTE: This is very inefficient, we likely want to keep track of the | 162 | blit_framebuffer(&ppu); |
157 | // lines/tiles that have changed and only copy those. | ||
158 | for (size_t i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT; i++) { | ||
159 | framebuffer[i] = palette[ppu.pixels[i]]; | ||
160 | } | ||
161 | } | 163 | } |
162 | } | 164 | } |
@@ -15,13 +15,15 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
15 | WITH REGARD TO THIS SOFTWARE. | 15 | WITH REGARD TO THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define SCREEN_WIDTH 64 * 8 / 2 | 18 | #define SCREEN_WIDTH 64 * 8 |
19 | #define SCREEN_HEIGHT 40 * 8 / 2 | 19 | #define SCREEN_HEIGHT 40 * 8 |
20 | 20 | ||
21 | static u32 *framebuffer = 0; | 21 | static u32 *framebuffer = 0; |
22 | 22 | ||
23 | static u32 palette[16]; | 23 | static u32 palette[16] = {0}; |
24 | static u8 pixels_buf[SCREEN_WIDTH * SCREEN_HEIGHT]; | 24 | static u8 pixels_buf[SCREEN_WIDTH * SCREEN_HEIGHT] = {0}; |
25 | static u8 dirty_lines[SCREEN_HEIGHT] = {0}; | ||
26 | static u8 reqdraw = 0; | ||
25 | 27 | ||
26 | static Uint8 blending[5][16] = { | 28 | static Uint8 blending[5][16] = { |
27 | {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, | 29 | {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0}, |
@@ -37,8 +39,8 @@ ppu_pixel(Ppu *p, Uint8 layer, Uint16 x, Uint16 y, Uint8 color) | |||
37 | Uint8 *pixel = &p->pixels[idx], shift = layer * 2; | 39 | Uint8 *pixel = &p->pixels[idx], shift = layer * 2; |
38 | if(x < p->width && y < p->height) { | 40 | if(x < p->width && y < p->height) { |
39 | *pixel = (*pixel & ~(0x3 << shift)) | (color << shift); | 41 | *pixel = (*pixel & ~(0x3 << shift)) | (color << shift); |
40 | // framebuffer[idx] = palette[*pixel]; | ||
41 | } | 42 | } |
43 | dirty_lines[y] |= 1; | ||
42 | } | 44 | } |
43 | 45 | ||
44 | void | 46 | void |
@@ -75,6 +77,13 @@ ppu_2bpp(Ppu *p, Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Ui | |||
75 | } | 77 | } |
76 | } | 78 | } |
77 | 79 | ||
80 | void | ||
81 | redraw_screen(void) { | ||
82 | for (size_t j = 0; j < SCREEN_HEIGHT; j++) { | ||
83 | dirty_lines[j] |= 1; | ||
84 | } | ||
85 | } | ||
86 | |||
78 | int | 87 | int |
79 | ppu_init(Ppu *p, Uint8 hor, Uint8 ver) { | 88 | ppu_init(Ppu *p, Uint8 hor, Uint8 ver) { |
80 | p->width = 8 * hor; | 89 | p->width = 8 * hor; |
@@ -135,5 +144,26 @@ ppu_init(Ppu *p, Uint8 hor, Uint8 ver) { | |||
135 | palette[2] = 0x007777ff; | 144 | palette[2] = 0x007777ff; |
136 | palette[3] = 0x00ff7777; | 145 | palette[3] = 0x00ff7777; |
137 | 146 | ||
147 | // Make sure we perform an initial screen drawing. | ||
148 | reqdraw = 1; | ||
149 | redraw_screen(); | ||
150 | |||
138 | return 1; | 151 | return 1; |
139 | } | 152 | } |
153 | |||
154 | void | ||
155 | blit_framebuffer(Ppu *p) { | ||
156 | if (reqdraw == 0) { | ||
157 | return; | ||
158 | } | ||
159 | for (size_t j = 0; j < SCREEN_HEIGHT; j++) { | ||
160 | if (dirty_lines[j] == 1) { | ||
161 | for (size_t i = 0; i < SCREEN_WIDTH; i++) { | ||
162 | size_t idx = i + j * SCREEN_WIDTH; | ||
163 | framebuffer[idx] = palette[p->pixels[idx]]; | ||
164 | } | ||
165 | } | ||
166 | dirty_lines[j] = 0; | ||
167 | } | ||
168 | reqdraw = 0; | ||
169 | } | ||