Empty SDL2 example with my array package
authorNick Downing <nick@ndcode.org>
Mon, 18 Apr 2022 12:38:08 +0000 (22:38 +1000)
committerNick Downing <nick@ndcode.org>
Mon, 18 Apr 2022 12:38:08 +0000 (22:38 +1000)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
array.h [new file with mode: 0644]
render.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..104da3d
--- /dev/null
@@ -0,0 +1,2 @@
+*.o
+/render
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..09561ca
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+CFLAGS=-g -O3 -Wall
+
+render: render.o
+       ${CC} -o $@ $< -lSDL2 -lm
+
+render.o: render.c array.h
+
+clean:
+       rm -rf render *.o
diff --git a/array.h b/array.h
new file mode 100644 (file)
index 0000000..70fa0a6
--- /dev/null
+++ b/array.h
@@ -0,0 +1,362 @@
+#ifndef _ARRAY_H
+#define _ARRAY_H
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ALIGN 0x10 
+
+// data is at struct address + header
+// stride array has length n_dims + 1
+// stride[0] is size of the data
+// stride[n_dims] == 1 except if n_dims == 0
+// dimension i has size stride[i] / stride[i + 1], where i < n_dims
+struct array {
+  int header;
+  int n_dims;
+  size_t stride[0];
+};
+
+static inline __attribute__((always_inline)) void *array_new0(void) {
+  struct array *p = aligned_alloc(
+    ALIGN,
+    sizeof(struct array) + sizeof(size_t)
+  );
+  if (p == NULL) {
+    perror("aligned_alloc()");
+    exit(EXIT_FAILURE);
+  }
+
+  p->header =
+    (sizeof(struct array) + sizeof(size_t) + ALIGN - 1) & ~ALIGN;
+  p->n_dims = 0;
+  p->stride[0] = 0;
+  return p;
+}
+
+static inline __attribute__((always_inline)) void *array_new1(size_t dim0) {
+  struct array *p = aligned_alloc(
+    ALIGN,
+    (
+      (sizeof(struct array) + 2 * sizeof(size_t) + ALIGN - 1) & ~ALIGN
+    ) + dim0
+  );
+  if (p == NULL) {
+    perror("aligned_alloc()");
+    exit(EXIT_FAILURE);
+  }
+
+  p->header =
+    (sizeof(struct array) + 2 * sizeof(size_t) + ALIGN - 1) & ~ALIGN;
+  p->n_dims = 1;
+  p->stride[1] = 1;
+  p->stride[0] = dim0;
+  return p;
+}
+
+static inline __attribute__((always_inline)) void *array_new2(size_t dim0, size_t dim1) {
+  struct array *p = aligned_alloc(
+    ALIGN,
+    (
+      (sizeof(struct array) + 3 * sizeof(size_t) + ALIGN - 1) & ~ALIGN
+    ) + dim0 * dim1
+  );
+  if (p == NULL) {
+    perror("aligned_alloc()");
+    exit(EXIT_FAILURE);
+  }
+
+  p->header =
+    (sizeof(struct array) + 3 * sizeof(size_t) + ALIGN - 1) & ~ALIGN;
+  p->n_dims = 2;
+  p->stride[2] = 1;
+  p->stride[1] = dim1;
+  p->stride[0] = dim0 * dim1;
+  return p;
+}
+
+static inline __attribute__((always_inline)) void *array_new3(size_t dim0, size_t dim1, size_t dim2) {
+  struct array *p = aligned_alloc(
+    ALIGN,
+    (
+      (sizeof(struct array) + 4 * sizeof(size_t) + ALIGN - 1) & ~ALIGN
+    ) + dim0 * dim1 * dim2
+  );
+  if (p == NULL) {
+    perror("aligned_alloc()");
+    exit(EXIT_FAILURE);
+  }
+
+  p->header =
+    (sizeof(struct array) + 4 * sizeof(size_t) + ALIGN - 1) & ~ALIGN;
+  p->n_dims = 3;
+  p->stride[3] = 1;
+  p->stride[2] = dim2;
+  p->stride[1] = dim1 * dim2;
+  p->stride[0] = dim0 * p->stride[1];
+  return p;
+}
+
+static inline __attribute__((always_inline)) void *array_new4(size_t dim0, size_t dim1, size_t dim2, size_t dim3) {
+  struct array *p = aligned_alloc(
+    ALIGN,
+    (
+      (sizeof(struct array) + 5 * sizeof(size_t) + ALIGN - 1) & ~ALIGN
+    ) + dim0 * dim1 * dim2 * dim3
+  );
+  if (p == NULL) {
+    perror("aligned_alloc()");
+    exit(EXIT_FAILURE);
+  }
+
+  p->header =
+    (sizeof(struct array) + 5 * sizeof(size_t) + ALIGN - 1) & ~ALIGN;
+  p->n_dims = 3;
+  p->stride[4] = 1;
+  p->stride[3] = dim3;
+  p->stride[2] = dim2 * dim3;
+  p->stride[1] = dim1 * p->stride[2];
+  p->stride[0] = dim0 * p->stride[1];
+  return p;
+}
+
+static inline __attribute__((always_inline)) void array_free(struct array *self) {
+  free(self);
+}
+
+static inline __attribute__((always_inline)) void *array_index0(
+  struct array *self,
+  size_t *size
+) {
+  *size = self->stride[0];
+  return
+    (char *)self +
+    self->header;
+}
+
+static inline __attribute__((always_inline)) void *array_index1(
+  struct array *self,
+  size_t *size,
+  size_t i0
+) {
+  assert(self->n_dims >= 1);
+  *size = self->stride[1];
+  return
+    (char *)self +
+    self->header +
+    i0 * self->stride[1];
+}
+
+static inline __attribute__((always_inline)) void *array_index2(
+  struct array *self,
+  size_t *size,
+  size_t i0,
+  size_t i1
+) {
+  assert(self->n_dims >= 2);
+  *size = self->stride[2];
+  return
+    (char *)self +
+    self->header +
+    i1 * self->stride[2] +
+    i0 * self->stride[1];
+}
+
+static inline __attribute__((always_inline)) void *array_index3(
+  struct array *self,
+  size_t *size,
+  size_t i0,
+  size_t i1,
+  size_t i2
+) {
+  assert(self->n_dims >= 3);
+  *size = self->stride[3];
+  return
+    (char *)self +
+    self->header +
+    i2 * self->stride[3] +
+    i1 * self->stride[2] +
+    i0 * self->stride[1];
+}
+
+static inline __attribute__((always_inline)) void *array_index4(
+  struct array *self,
+  size_t *size,
+  size_t i0,
+  size_t i1,
+  size_t i2,
+  size_t i3
+) {
+  assert(self->n_dims >= 4);
+  *size = self->stride[4];
+  return
+    (char *)self +
+    self->header +
+    i3 * self->stride[4] +
+    i2 * self->stride[3] +
+    i1 * self->stride[2] +
+    i0 * self->stride[1];
+}
+
+static inline __attribute__((always_inline)) void array_get0(
+  struct array *self,
+  void *dest
+) {
+  size_t size;
+  void *p = array_index0(self, &size);
+  memcpy(dest, p, size);
+}
+
+static inline __attribute__((always_inline)) void array_get1(
+  struct array *self,
+  void *dest,
+  size_t i0
+) {
+  size_t size;
+  void *p = array_index1(self, &size, i0);
+  memcpy(dest, p, size);
+}
+
+static inline __attribute__((always_inline)) void array_get2(
+  struct array *self,
+  void *dest,
+  size_t i0,
+  size_t i1
+) {
+  size_t size;
+  void *p = array_index2(self, &size, i0, i1);
+  memcpy(dest, p, size);
+}
+
+static inline __attribute__((always_inline)) void array_get3(
+  struct array *self,
+  void *dest,
+  size_t i0,
+  size_t i1,
+  size_t i2
+) {
+  size_t size;
+  void *p = array_index3(self, &size, i0, i1, i2);
+  memcpy(dest, p, size);
+}
+
+static inline __attribute__((always_inline)) void array_get4(
+  struct array *self,
+  void *dest,
+  size_t i0,
+  size_t i1,
+  size_t i2,
+  size_t i3
+) {
+  size_t size;
+  void *p = array_index4(self, &size, i0, i1, i2, i3);
+  memcpy(dest, p, size);
+}
+
+static inline __attribute__((always_inline)) void array_set0(
+  struct array *self,
+  const void *src
+) {
+  size_t size;
+  void *p = array_index0(self, &size);
+  memcpy(p, src, size);
+}
+
+static inline __attribute__((always_inline)) void array_set1(
+  struct array *self,
+  const void *src,
+  size_t i0
+) {
+  size_t size;
+  void *p = array_index1(self, &size, i0);
+  memcpy(p, src, size);
+}
+
+static inline __attribute__((always_inline)) void array_set2(
+  struct array *self,
+  const void *src,
+  size_t i0,
+  size_t i1
+) {
+  size_t size;
+  void *p = array_index2(self, &size, i0, i1);
+  memcpy(p, src, size);
+}
+
+static inline __attribute__((always_inline)) void array_set3(
+  struct array *self,
+  const void *src,
+  size_t i0,
+  size_t i1,
+  size_t i2
+) {
+  size_t size;
+  void *p = array_index3(self, &size, i0, i1, i2);
+  memcpy(p, src, size);
+}
+
+static inline __attribute__((always_inline)) void array_set4(
+  struct array *self,
+  const void *src,
+  size_t i0,
+  size_t i1,
+  size_t i2,
+  size_t i3
+) {
+  size_t size;
+  void *p = array_index4(self, &size, i0, i1, i2, i3);
+  memcpy(p, src, size);
+}
+
+static inline __attribute__((always_inline)) void array_clear0(
+  struct array *self
+) {
+  size_t size;
+  void *p = array_index0(self, &size);
+  memset(p, 0, size);
+}
+
+static inline __attribute__((always_inline)) void array_clear1(
+  struct array *self,
+  size_t i0
+) {
+  size_t size;
+  void *p = array_index1(self, &size, i0);
+  memset(p, 0, size);
+}
+
+static inline __attribute__((always_inline)) void array_clear2(
+  struct array *self,
+  size_t i0,
+  size_t i1
+) {
+  size_t size;
+  void *p = array_index2(self, &size, i0, i1);
+  memset(p, 0, size);
+}
+
+static inline __attribute__((always_inline)) void array_clear3(
+  struct array *self,
+  size_t i0,
+  size_t i1,
+  size_t i2
+) {
+  size_t size;
+  void *p = array_index3(self, &size, i0, i1, i2);
+  memset(p, 0, size);
+}
+
+static inline __attribute__((always_inline)) void array_clear4(
+  struct array *self,
+  size_t i0,
+  size_t i1,
+  size_t i2,
+  size_t i3
+) {
+  size_t size;
+  void *p = array_index4(self, &size, i0, i1, i2, i3);
+  memset(p, 0, size);
+}
+
+#endif
diff --git a/render.c b/render.c
new file mode 100644 (file)
index 0000000..11ea68d
--- /dev/null
+++ b/render.c
@@ -0,0 +1,85 @@
+#include <stdbool.h>
+#include <stdlib.h>
+#include <SDL2/SDL.h>
+#include "array.h"
+
+#define WINDOW_WIDTH 1024
+#define WINDOW_HEIGHT 768
+
+SDL_Window *window;
+SDL_Renderer *renderer;
+SDL_Surface *window_surface;
+
+int main(void) {
+  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+    fprintf(stderr, "SDL_Init(): %s\n\n", SDL_GetError());
+    exit(EXIT_FAILURE);
+  }
+
+  if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) {
+    fprintf(stderr, "SDL_SetHint(): %s\n", SDL_GetError());
+    exit(EXIT_FAILURE);
+  }
+
+  window = SDL_CreateWindow(
+    "render",
+    SDL_WINDOWPOS_UNDEFINED,
+    SDL_WINDOWPOS_UNDEFINED,
+    WINDOW_WIDTH,
+    WINDOW_HEIGHT,
+    SDL_WINDOW_SHOWN
+  );
+  if (window == NULL) {
+    fprintf(stderr, "SDL_CreateWindow(): %s\n", SDL_GetError());
+    exit(EXIT_FAILURE);
+  }
+
+  window_surface = SDL_GetWindowSurface(window);
+  if (window_surface == NULL) {
+    fprintf(stderr, "SDL_GetWindowSurface(): %s\n", SDL_GetError());
+    exit(EXIT_FAILURE);
+  }
+
+  renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+  if (renderer == NULL) {
+    fprintf(stderr, "SDL_CreateRenderer(): %s\n", SDL_GetError());
+    exit(EXIT_FAILURE);
+  }
+
+  SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xff);
+
+  struct array *a = array_new3(4, 4, sizeof(float));
+  array_clear0(a);
+  for (int i = 0; i < 4; ++i)
+    for (int j = 0; j < i; ++j) {
+      float v = i + j;
+      array_set2(a, &v, i, j);
+    }
+  for (int i = 0; i < 4; ++i) {
+    for (int j = 0; j < 4; ++j) {
+      float v;
+      array_get2(a, &v, i, j);
+      printf("%s%7.3f", j ? ", " : i ? " [" : "[[", v);
+    }
+    printf("%s\n", i < 3 ? "]" : "]]");
+  }
+
+  while (true) {
+    SDL_Event event;
+    while (SDL_PollEvent(&event))
+      switch (event.type) {
+      case SDL_QUIT:
+        goto quit;
+      }
+
+    SDL_RenderClear(renderer);
+    SDL_RenderPresent(renderer);
+    SDL_Delay(1);
+  }
+
+quit:
+  SDL_DestroyRenderer(renderer);
+  SDL_DestroyWindow(window);
+  SDL_Quit();
+  return 0;
+}