summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--platform/wavelet3d/host_sw/demo.c423
-rw-r--r--platform/wavelet3d/host_sw/gfx_boot.c1
-rw-r--r--platform/wavelet3d/host_sw/main.c4
-rw-r--r--platform/wavelet3d/host_sw/mod.mk5
-rw-r--r--platform/wavelet3d/host_sw/vdc.c54
-rw-r--r--platform/wavelet3d/host_sw/vdc.h6
-rw-r--r--platform/wavelet3d/host_sw/vdc_rayas.c100
-rw-r--r--platform/wavelet3d/main.cpp2
8 files changed, 591 insertions, 4 deletions
diff --git a/platform/wavelet3d/host_sw/demo.c b/platform/wavelet3d/host_sw/demo.c
new file mode 100644
index 0000000..32e8e0e
--- /dev/null
+++ b/platform/wavelet3d/host_sw/demo.c
@@ -0,0 +1,423 @@
+#define MOD_NAME "demo"
+
+#include <math.h>
+#include <string.h>
+
+#include "log.h"
+
+#define W 640
+#define H 480
+
+#define FB_BASE ((void *)0x1d000000)
+
+typedef float mat4[4][4];
+typedef float vec4[4];
+
+typedef struct vec2i
+{
+ int x, y;
+} vec2i;
+
+typedef struct vertex
+{
+ vec4 pos;
+ vec2i grid;
+ vec4 color;
+} vertex;
+
+static mat4 mvp;
+static unsigned short z_buff[1024 * H];
+
+static inline int min(int x, int y)
+{
+ return x < y ? x : y;
+}
+
+static inline int max(int x, int y)
+{
+ return x > y ? x : y;
+}
+
+void mat_vec(mat4 *a, vec4 *b, vec4 *out)
+{
+ vec4 v;
+ for (int i = 0; i < 4; ++i) {
+ v[i] = 0.0;
+ for (int k = 0; k < 4; ++k)
+ v[i] += (*a)[i][k] * (*b)[k];
+ }
+
+ memcpy(out, v, sizeof v);
+}
+
+void mat_mat(mat4 *a, mat4 *b, mat4 *out)
+{
+ mat4 c;
+ for (int i = 0; i < 4; ++i)
+ for (int j = 0; j < 4; ++j) {
+ c[i][j] = 0.0;
+ for (int k = 0; k < 4; ++k)
+ c[i][j] += (*a)[i][k] * (*b)[k][j];
+ }
+
+ memcpy(out, c, sizeof c);
+}
+
+void mat_translate(float x, float y, float z, mat4 *out)
+{
+ mat4 m =
+ {
+ {1, 0, 0, x},
+ {0, 1, 0, y},
+ {0, 0, 1, z},
+ {0, 0, 0, 1},
+ };
+
+ memcpy(out, m, sizeof m);
+};
+
+void mat_scale(float x, float y, float z, mat4 *out)
+{
+ mat4 m =
+ {
+ {x, 0, 0, 0},
+ {0, y, 0, 0},
+ {0, 0, z, 0},
+ {0, 0, 0, 1},
+ };
+
+ memcpy(out, m, sizeof m);
+}
+
+void mat_rotate(float x, float y, float z, float angle, mat4 *out)
+{
+ float xx = x * x, yy = y * y, zz = z * z;
+ float mag = sqrt(xx + yy + zz);
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+ angle = angle * M_PI / 180;
+ float c = cosf(angle), s = sinf(angle);
+
+ mat4 m =
+ {
+ {x * x * (1 - c) + c, x * y * (1 - c) - z * s, x * z * (1 - c) + y * s, 0},
+ {y * x * (1 - c) + z * s, y * y * (1 - c) + c, y * z * (1 - c) - x * s, 0},
+ {x * z * (1 - c) - y * s, y * z * (1 - c) + x * s, z * z * (1 - c) + c, 0},
+ {0, 0, 0, 1},
+ };
+
+ memcpy(out, m, sizeof m);
+}
+
+void mat_frustum(float left, float right, float bottom, float top, float near, float far, mat4 *out)
+{
+ // https://docs.gl/gl3/glFrustum
+
+ float l = left, r = right, b = bottom, t = top, n = near, f = far;
+
+ mat4 m =
+ {
+ {2 * n / (r - l), 0, (r + l) / (r - l), 0},
+ {0, 2 * n / (t - b), (t + b) / (t - b), 0},
+ {0, 0, -(f + n) / (f - n), -2 * f * n / (f - n)},
+ {0, 0, -1 , 0},
+ };
+
+ memcpy(out, m, sizeof m);
+}
+
+void fixed(vec4 *p, vec2i *out)
+{
+ out->x = (int)ldexpf((*p)[0] / (*p)[3], 13);
+ out->y = (int)ldexpf((*p)[1] / (*p)[3], 13);
+}
+
+void edge_fn(vec2i *p, vec2i *q, int sx, int sy, int *base_x, int *base_y, int *add_x, int *add_y)
+{
+ // https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/rasterization-stage.html
+ int a = p->y - q->y, b = -(p->x - q->x);
+ int r = (sx - q->x) * a + (sy - q->y) * b;
+
+ *base_x = r;
+ *base_y = r;
+ *add_x = a;
+ *add_y = b;
+}
+
+void bounding(vec2i *p0, vec2i *p1, vec2i *p2, int *minx, int *miny, int *maxx, int *maxy)
+{
+ *minx = max(min(p0->x, min(p1->x, p2->x)), (-W / 2) << 4);
+ *maxx = min(max(p0->x, max(p1->x, p2->x)), ( W / 2) << 4);
+ *miny = max(min(p0->y, min(p1->y, p2->y)), (-H / 2) << 4);
+ *maxy = min(max(p0->y, max(p1->y, p2->y)), ( H / 2) << 4);
+}
+
+unsigned char clamp_color(float color)
+{
+ color = ldexpf(color, 8);
+ if (color < 0.0)
+ return 0;
+ else if (color >= 256.0)
+ return 255;
+
+ return (unsigned char)(int)color;
+}
+
+float area(vec2i *a, vec2i *b, vec2i *c)
+{
+ float a_x = a->x;
+ float a_y = a->y;
+ float b_x = b->x;
+ float b_y = b->y;
+ float c_x = c->x;
+ float c_y = c->y;
+
+
+ return (a_x * (b_y - c_y) + b_x * (c_y - a_y) + c_x * (a_y - b_y)) / 2;
+}
+
+void raster(vertex *v0, vertex *v1, vertex *v2)
+{
+ // https://math.stackexchange.com/questions/1324179/how-to-tell-if-3-connected-points-are-connected-clockwise-or-counter-clockwise
+
+ int A = v1->grid.x * v0->grid.y + v2->grid.x * v1->grid.y + v0->grid.x * v2->grid.y;
+ int B = v0->grid.x * v1->grid.y + v1->grid.x * v2->grid.y + v2->grid.x * v0->grid.y;
+
+ if (A > B) {
+ vertex *tmp = v2;
+ v2 = v1;
+ v1 = tmp;
+ }
+
+ vec2i *p0 = &v0->grid;
+ vec2i *p1 = &v1->grid;
+ vec2i *p2 = &v2->grid;
+
+ int msaa = 0; //TODO
+
+ int minx, miny, maxx, maxy;
+ bounding(p0, p1, p2, &minx, &miny, &maxx, &maxy);
+
+ int sx = minx / 16 * 16, sy = miny / 16 * 16;
+
+ int base_x_a, base_y_a, add_x_a, add_y_a;
+ edge_fn(p0, p1, sx, sy, &base_x_a, &base_y_a, &add_x_a, &add_y_a);
+
+ int base_x_b, base_y_b, add_x_b, add_y_b;
+ edge_fn(p1, p2, sx, sy, &base_x_b, &base_y_b, &add_x_b, &add_y_b);
+
+ int base_x_c, base_y_c, add_x_c, add_y_c;
+ edge_fn(p2, p0, sx, sy, &base_x_c, &base_y_c, &add_x_c, &add_y_c);
+
+ int int_x_a = add_x_a << 4;
+ int int_x_b = add_x_b << 4;
+ int int_x_c = add_x_c << 4;
+ int int_y_a = add_y_a << 4;
+ int int_y_b = add_y_b << 4;
+ int int_y_c = add_y_c << 4;
+
+ for (int x = minx / 16 * 16; x < maxx + 16; x += 16) {
+ for (int y = miny / 16 * 16; y < maxy + 16; y += 16) {
+ int count = 0;
+
+ if (base_y_a >= 0 && base_y_b >= 0 && base_y_c >= 0)
+ ++count;
+
+ base_y_a += int_y_a;
+ base_y_b += int_y_b;
+ base_y_c += int_y_c;
+
+ if (!count > 0)
+ continue;
+
+ int yield_x = x >> 4, yield_y = y >> 4, yield_c = msaa ? count : 3;
+ if (!(-W / 2 <= yield_x && yield_x < W / 2 && -H / 2 <= yield_y && yield_y < H / 2))
+ continue;
+
+ yield_x += W / 2;
+ yield_y = H / 2 - yield_y - 1;
+
+ vec2i p = {.x = x, .y = y};
+ // https://stackoverflow.com/questions/24441631/how-exactly-does-opengl-do-perspectively-correct-linear-interpolation
+ float b0 = area(&p, p1, p2) / v0->pos[3];
+ float b1 = area(p0, &p, p2) / v1->pos[3];
+ float b2 = area(p0, p1, &p) / v2->pos[3];
+
+ float b_sum = b0 + b1 + b2;
+ b0 /= b_sum;
+ b1 /= b_sum;
+ b2 /= b_sum;
+
+ float z = v0->pos[2] * b0 + v1->pos[2] * b1 + v2->pos[2] * b2;
+ if (z < -1.0 || z >= 1.0)
+ continue;
+
+ unsigned short z_int = (unsigned short)(int)ldexpf(1.0 + z, 16 - 1);
+ unsigned short *z_cell = &z_buff[yield_y * 1024 + yield_x];
+
+ if (*z_cell > z_int)
+ continue;
+
+ *z_cell = z_int;
+
+ unsigned char r = clamp_color(v0->color[0] * b0 + v1->color[0] * b1 + v2->color[0] * b2);
+ unsigned char g = clamp_color(v0->color[1] * b0 + v1->color[1] * b1 + v2->color[1] * b2);
+ unsigned char b = clamp_color(v0->color[2] * b0 + v1->color[2] * b1 + v2->color[2] * b2);
+
+ volatile unsigned char *ptr =
+ (unsigned char *)FB_BASE
+ + yield_y * 2048
+ + yield_x * 3;
+
+ *ptr++ = b;
+ *ptr++ = g;
+ *ptr++ = r;
+ }
+
+ base_x_a += int_x_a;
+ base_x_b += int_x_b;
+ base_x_c += int_x_c;
+
+ base_y_a = base_x_a;
+ base_y_b = base_x_b;
+ base_y_c = base_x_c;
+ }
+}
+
+void persp_div(vec4 *pos)
+{
+ float w_inv = 1.0f / (*pos)[3];
+ (*pos)[0] = (*pos)[0] * w_inv;
+ (*pos)[1] = (*pos)[1] * w_inv;
+ (*pos)[2] = (*pos)[2] * w_inv;
+ (*pos)[3] = w_inv;
+}
+
+void tri
+(
+ float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ float x3, float y3, float z3
+)
+{
+ vertex v0 = {.pos = {x1, y1, z1, 1.0}, .color = {1.0, 0.0, 0.0, 0.0}};
+ vertex v1 = {.pos = {x2, y2, z2, 1.0}, .color = {0.0, 1.0, 0.0, 0.0}};
+ vertex v2 = {.pos = {x3, y3, z3, 1.0}, .color = {0.0, 0.0, 1.0, 0.0}};
+
+ mat_vec(&mvp, &v0.pos, &v0.pos);
+ mat_vec(&mvp, &v1.pos, &v1.pos);
+ mat_vec(&mvp, &v2.pos, &v2.pos);
+
+ persp_div(&v0.pos);
+ persp_div(&v1.pos);
+ persp_div(&v2.pos);
+
+ fixed(&v0.pos, &v0.grid);
+ fixed(&v1.pos, &v1.grid);
+ fixed(&v2.pos, &v2.grid);
+
+ raster(&v0, &v1, &v2);
+}
+
+// v2-v3 debe ser una diagonal, sino no sirve
+void quad
+(
+ float x1, float y1, float z1,
+ float x2, float y2, float z2,
+ float x3, float y3, float z3,
+ float x4, float y4, float z4
+)
+{
+ tri(x2, y2, z2, x1, y1, z1, x3, y3, z3);
+ tri(x2, y2, z2, x4, y4, z4, x3, y3, z3);
+}
+
+void demo(void)
+{
+ //memset(FB_BASE, 0, 2048 * H);
+ //memset(z_buff, 0, sizeof z_buff);
+
+ float a = -50;
+ float f = 1;
+ float w = 1;
+
+ mat4 trans_z, trans_center, rot, scal;
+ mat_translate(0, 0, -5, &trans_z);
+ mat_rotate(1, 1, 1, a, &rot);
+ mat_translate(-0.5, -0.5, -0.5, &trans_center);
+ mat_scale(f, f, f, &scal);
+
+ // https://stackoverflow.com/questions/16398463/getting-coordinates-for-glfrustum
+ float fov = 120;
+ float back = 1000.0;
+ float front = 1.0;
+ float aspect = 1.0;
+
+ // transform from horizontal fov to vertical fov
+ fov = ldexpf(atanf(tanf(fov * M_PI_2 / 180) / aspect), 1);
+
+ float tangent = tanf(fov / 2.0f); // tangent of half vertical fov
+ float height = front * tangent; // half height of near plane
+ float width = height * aspect; // half width of near plane
+
+ // Escalar, luego rotar, luego frustum
+ mat_frustum(-width, width, -height, height, front, back, &mvp);
+ mat_mat(&mvp, &trans_z, &mvp);
+ mat_mat(&mvp, &rot, &mvp);
+ mat_mat(&mvp, &trans_center, &mvp);
+ mat_mat(&mvp, &scal, &mvp);
+
+ for (int i = 0; i < 4; ++i)
+ for (int j = 0; j < 4; ++j)
+ log("mvp[%d][%d] = %f", i, j, mvp[i][j]);
+
+ quad
+ (
+ 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 1.0, 0.0
+ );
+
+ quad
+ (
+ 0.0, 0.0, 1.0,
+ 0.0, 1.0, 1.0,
+ 1.0, 0.0, 1.0,
+ 1.0, 1.0, 1.0
+ );
+
+ quad
+ (
+ 0.0, 0.0, 1.0,
+ 0.0, 1.0, 1.0,
+ 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0
+ );
+
+ quad
+ (
+ 1.0, 0.0, 1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 1.0, 0.0
+ );
+
+ quad
+ (
+ 0.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 1.0
+ );
+
+ quad
+ (
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 1.0,
+ 1.0, 1.0, 0.0,
+ 1.0, 1.0, 1.0
+ );
+}
diff --git a/platform/wavelet3d/host_sw/gfx_boot.c b/platform/wavelet3d/host_sw/gfx_boot.c
index 2a7071f..69335ef 100644
--- a/platform/wavelet3d/host_sw/gfx_boot.c
+++ b/platform/wavelet3d/host_sw/gfx_boot.c
@@ -40,7 +40,6 @@ enum gfx_probe_result gfx_probe(void)
switch (hostif_rev) {
case 0:
- log("scheduler is in bootloader rom");
return GFX_PROBE_BOOTROM;
case 1:
diff --git a/platform/wavelet3d/host_sw/main.c b/platform/wavelet3d/host_sw/main.c
index 7513c4c..5df035e 100644
--- a/platform/wavelet3d/host_sw/main.c
+++ b/platform/wavelet3d/host_sw/main.c
@@ -1,7 +1,11 @@
#include "init.h"
+#include "vdc.h"
int main()
{
+ void demo(void);
+ demo();
+ vdc_init();
init();
return 0;
}
diff --git a/platform/wavelet3d/host_sw/mod.mk b/platform/wavelet3d/host_sw/mod.mk
index 2563f9e..8ca7dbd 100644
--- a/platform/wavelet3d/host_sw/mod.mk
+++ b/platform/wavelet3d/host_sw/mod.mk
@@ -7,8 +7,9 @@ define core/w3d_host_sw
$(this)/obj_deps := picolibc/picolibc.specs
- $(this)/cc_files := main.c gfx_boot.c init.c sgdma.c
- $(this)/cc_flags = -g -march=rv32imafc -mabi=ilp32f --specs=$$(obj)/picolibc/picolibc.specs
+ $(this)/cc_files := demo.c main.c gfx_boot.c init.c sgdma.c vdc.c
+ $(this)/cc_flags = $$(if $$(enable_opt),-O3 -ffast-math) -g -march=rv32imafc \
+ -mabi=ilp32f --specs=$$(obj)/picolibc/picolibc.specs
$(this)/ld_extra := gfx_fw_payload.o
$(this)/ld_flags := --oslib=semihost
$(this)/ld_binary := w3d_host_flash
diff --git a/platform/wavelet3d/host_sw/vdc.c b/platform/wavelet3d/host_sw/vdc.c
new file mode 100644
index 0000000..f31f0db
--- /dev/null
+++ b/platform/wavelet3d/host_sw/vdc.c
@@ -0,0 +1,54 @@
+#define MOD_NAME "vdc"
+
+#include "log.h"
+#include "vdc.h"
+
+struct vdc_ctrl
+{
+ unsigned dacen : 1;
+ unsigned dacon : 1;
+ unsigned doublebuff : 1;
+ unsigned rsvd3 : 29;
+};
+
+struct vdc_geometry
+{
+ unsigned lines : 16;
+ unsigned length : 16;
+};
+
+struct vdc_stream
+{
+ unsigned hstride : 16;
+ unsigned rsvd16 : 16;
+};
+
+struct vdc_fb
+{
+ unsigned rsvd0 : 2;
+ unsigned addr : 30;
+};
+
+#define VDC_BASE 0x24000000
+#define VDC_CTRL (*(volatile struct vdc_ctrl *) (VDC_BASE + 0x00))
+#define VDC_GEOMETRY (*(volatile struct vdc_geometry *)(VDC_BASE + 0x04))
+#define VDC_STREAM (*(volatile struct vdc_stream *) (VDC_BASE + 0x08))
+#define VDC_FRONT (*(volatile struct vdc_fb *) (VDC_BASE + 0x0c))
+#define VDC_BACK (*(volatile struct vdc_fb *) (VDC_BASE + 0x10))
+#define VDC_RETIRE (*(volatile struct vdc_fb *) (VDC_BASE + 0x14))
+
+#define FB_BASE ((void *)0x1d000000)
+
+void vdc_init(void)
+{
+ log("fb init, vdc_on=%u", VDC_CTRL.dacon);
+
+ log("fb done");
+
+ VDC_FRONT = (struct vdc_fb){ .addr = (unsigned)FB_BASE >> 2, .rsvd0 = 0, };
+ VDC_STREAM = (struct vdc_stream){ .hstride = 512, .rsvd16 = 0, };
+ VDC_GEOMETRY = (struct vdc_geometry){ .length = 479, .lines = 479, };
+ VDC_CTRL = (struct vdc_ctrl){ .dacen = 1, .dacon = 0, .doublebuff = 0, };
+
+ log("init done, vdc_on=%u", VDC_CTRL.dacon);
+}
diff --git a/platform/wavelet3d/host_sw/vdc.h b/platform/wavelet3d/host_sw/vdc.h
new file mode 100644
index 0000000..eb5867a
--- /dev/null
+++ b/platform/wavelet3d/host_sw/vdc.h
@@ -0,0 +1,6 @@
+#ifndef VDC_H
+#define VDC_H
+
+void vdc_init(void);
+
+#endif
diff --git a/platform/wavelet3d/host_sw/vdc_rayas.c b/platform/wavelet3d/host_sw/vdc_rayas.c
new file mode 100644
index 0000000..5a583b6
--- /dev/null
+++ b/platform/wavelet3d/host_sw/vdc_rayas.c
@@ -0,0 +1,100 @@
+#define MOD_NAME "vdc"
+
+#include "log.h"
+#include "vdc.h"
+
+struct vdc_ctrl
+{
+ unsigned dacen : 1;
+ unsigned dacon : 1;
+ unsigned doublebuff : 1;
+ unsigned rsvd3 : 29;
+};
+
+struct vdc_geometry
+{
+ unsigned lines : 16;
+ unsigned length : 16;
+};
+
+struct vdc_stream
+{
+ unsigned hstride : 16;
+ unsigned rsvd16 : 16;
+};
+
+struct vdc_fb
+{
+ unsigned rsvd0 : 2;
+ unsigned addr : 30;
+};
+
+#define VDC_BASE 0x24000000
+#define VDC_CTRL (*(volatile struct vdc_ctrl *) (VDC_BASE + 0x00))
+#define VDC_GEOMETRY (*(volatile struct vdc_geometry *)(VDC_BASE + 0x04))
+#define VDC_STREAM (*(volatile struct vdc_stream *) (VDC_BASE + 0x08))
+#define VDC_FRONT (*(volatile struct vdc_fb *) (VDC_BASE + 0x0c))
+#define VDC_BACK (*(volatile struct vdc_fb *) (VDC_BASE + 0x10))
+#define VDC_RETIRE (*(volatile struct vdc_fb *) (VDC_BASE + 0x14))
+
+#define FB_BASE ((void *)0x1d000000)
+
+void vdc_init(void)
+{
+ log("fb init, vdc_on=%u", VDC_CTRL.dacon);
+
+ unsigned r[] = { 0x00ff0000, 0x0000ff00, 0xff0000ff };
+ unsigned g[] = { 0x0000ff00, 0xff0000ff, 0x00ff0000 };
+ unsigned b[] = { 0xff0000ff, 0x00ff0000, 0x0000ff00 };
+
+ unsigned *p = (unsigned *)FB_BASE;
+
+ for (unsigned n = 0; n < 120; ++n) {
+ unsigned *porig = p;
+ for (unsigned i = 0; i < 480; i += 3, p += 3) {
+ p[0] = r[0];
+ p[1] = r[1];
+ p[2] = r[2];
+ }
+ p = porig + 512;
+ }
+
+ for (unsigned n = 0; n < 120; ++n) {
+ unsigned *porig = p;
+ for (unsigned i = 0; i < 480; i += 3, p += 3) {
+ p[0] = g[0];
+ p[1] = g[1];
+ p[2] = g[2];
+ }
+ p = porig + 512;
+ }
+
+ for (unsigned n = 0; n < 120; ++n) {
+ unsigned *porig = p;
+ for (unsigned i = 0; i < 480; i += 3, p += 3) {
+ p[0] = b[0];
+ p[1] = b[1];
+ p[2] = b[2];
+ }
+ p = porig + 512;
+ }
+
+ for (unsigned n = 0; n < 120; ++n) {
+ unsigned *porig = p;
+ for (unsigned i = 0; i < 480; i += 3, p += 3) {
+ p[0] = r[0];
+ p[1] = r[1];
+ p[2] = r[2];
+ }
+ p = porig + 512;
+ }
+
+ log("fb done");
+
+ VDC_FRONT = (struct vdc_fb){ .addr = (unsigned)FB_BASE >> 2, .rsvd0 = 0, };
+ VDC_STREAM = (struct vdc_stream){ .hstride = 512, .rsvd16 = 0, };
+ VDC_GEOMETRY = (struct vdc_geometry){ .length = 479, .lines = 479, };
+ VDC_CTRL = (struct vdc_ctrl){ .dacen = 1, .dacon = 0, .doublebuff = 0, };
+
+ log("init done, vdc_on=%u", VDC_CTRL.dacon);
+}
diff --git a/platform/wavelet3d/main.cpp b/platform/wavelet3d/main.cpp
index a94fa4f..f70b03c 100644
--- a/platform/wavelet3d/main.cpp
+++ b/platform/wavelet3d/main.cpp
@@ -256,7 +256,7 @@ int main(int argc, char **argv)
texture = ::SDL_CreateTexture
(
- renderer, SDL_PIXELFORMAT_ARGB32, SDL_TEXTUREACCESS_STREAMING, 640, 480
+ renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, 640, 480
);
}