aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles <sircharlesaze@gmail.com>2020-05-19 13:22:59 +0200
committerCharles <sircharlesaze@gmail.com>2020-05-19 13:22:59 +0200
commit6a80b1b70ec069b051c0e31aafac6eb596e20261 (patch)
treeedf9856bcd2b4415796a2a49f0232ba830e69560
parentc5008a4e62fb83eb71f5f94f622c01f2d8fe8b6b (diff)
downloadmandelbrot_cpu-6a80b1b70ec069b051c0e31aafac6eb596e20261.tar.gz
mandelbrot_cpu-6a80b1b70ec069b051c0e31aafac6eb596e20261.tar.bz2
mandelbrot_cpu-6a80b1b70ec069b051c0e31aafac6eb596e20261.zip
Back to basic SDL application boilerplate
-rw-r--r--Makefile38
-rw-r--r--graphics.c302
-rw-r--r--header.h88
-rw-r--r--helper.c48
-rw-r--r--inc/config.h9
-rw-r--r--inc/mandel.h55
-rw-r--r--main.c72
-rw-r--r--mandelbrot.c125
-rw-r--r--src/color.c22
-rw-r--r--src/error.c13
-rw-r--r--src/event.c56
-rw-r--r--src/main.c12
-rw-r--r--src/mandelbrot.c22
-rw-r--r--src/state.c34
14 files changed, 245 insertions, 651 deletions
diff --git a/Makefile b/Makefile
index 11997f9..4fae640 100644
--- a/Makefile
+++ b/Makefile
@@ -1,34 +1,40 @@
+RM = rm -f
+
NAME = mandel
+
+SRC_DIR = src
+INC_DIR = inc
+OBJ_DIR = obj
+
CC = gcc
-CCFLAGS = -Wall -Wextra
+OFLAG = -O0
+CCFLAGS = -I$(INC_DIR) -Wall -Wextra $(OFLAG)
LDFLAGS = -lm -lpthread $(shell sdl2-config --libs --cflags)
-HEADER = header.h
-SRC = main.c graphics.c mandelbrot.c helper.c
-OBJ = $(SRC:.c=.o)
+INC = $(shell find $(INC_DIR) -type f -name '*.h')
+SRC = $(shell find $(SRC_DIR) -type f -name '*.c')
+OBJ = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
-RM = rm -f
+all: prebuild $(NAME)
-.PHONY: all
-all: $(NAME)
+prebuild:
+ mkdir -p $(OBJ_DIR)
$(NAME): $(OBJ)
- $(CC) $(LDFLAGS) $(CCFLAGS) -o $@ $(OBJ)
+ $(CC) -o $@ $(OBJ) $(LDFLAGS)
-%.o: %.c $(HEADER)
- $(CC) $(LDFLAGS) $(CCFLAGS) -c -o $@ $<
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(HEADER)
+ $(CC) $(CCFLAGS) -c -o $@ $<
-.PHONY: debug
-debug: CCFLAGS += -g -fsanitize=address
-debug: re
+debug: OFLAG = -g
+debug: all
-.PHONY: clean
clean:
$(RM) $(OBJ)
-.PHONY: fclean
fclean: clean
$(RM) $(NAME)
-.PHONY: re
re: fclean all
+
+.PHONY: all debug clean fclean re
diff --git a/graphics.c b/graphics.c
deleted file mode 100644
index e422071..0000000
--- a/graphics.c
+++ /dev/null
@@ -1,302 +0,0 @@
-#include <stdbool.h>
-#include <pthread.h>
-#include <SDL2/SDL.h>
-#include "header.h"
-
-#define WINDOW_TITLE "Mandelbrot"
-#define WINDOW_X 20
-#define WINDOW_Y 20
-#define REFRESH_RATE 2
-#define MOVE_RATIO 10
-#define ZOOM_RATIO 1.1
-#define REAL_LO(state) (state->center.x - state->real_range / 2)
-#define REAL_HI(state) (state->center.x + state->real_range / 2)
-#define IMAG_LO(state) (state->center.y - state->imag_range / 2)
-#define IMAG_HI(state) (state->center.y + state->imag_range / 2)
-
-#define IN_SET_COLOR 0x050505
-#define PALETTE_START 0x000022
-#define PALETTE_END 0xd62f2f
-/* #define PALETTE_START 0x000000 */
-/* #define PALETTE_END 0xffffff */
-#define SET_DRAW_COLOR(renderer, c) ( \
- SDL_SetRenderDrawColor(renderer, c.rgb.r, c.rgb.g, c.rgb.b, SDL_ALPHA_OPAQUE));
-
-#define RED_MASK 0x0000ff
-#define GREEN_MASK 0x00ff00
-#define BLUE_MASK 0xff0000
-#define PITCH(ch, width) (ch * width)
-
-static void update(GState *state);
-static void event_handler(GState *state);
-static Color *create_palette(Color start, Color end);
-/* static void move_center(GState *state, int motion_x, int motion_y); */
-static void recenter(GState *state, int x, int y);
-static void recenter_x(GState *state, int x);
-static void recenter_y(GState *state, int y);
-static void zoom_in(GState *state, double ratio);
-static void zoom_out(GState *state, double ratio);
-static void destroy_state(GState *state);
-static void error_exit_state(GState *state, const char *msg);
-static void error_exit(const char *msg);
-
-GState *graphics_init(Config *config)
-{
- Color start, end;
-
- if (SDL_Init(SDL_INIT_VIDEO) < 0)
- error_exit("unable to init SDL");
- GState *state = (GState*)malloc(sizeof(GState));
- if (state == NULL)
- error_exit("state allocation failed");
- state->window = SDL_CreateWindow(WINDOW_TITLE, WINDOW_X, WINDOW_Y,
- config->window_w, config->window_h, 0);
- if (state->window == NULL)
- error_exit_state(state, "unable to create window");
- state->renderer = SDL_CreateRenderer(state->window, -1, 0);
- if (state->renderer == NULL)
- error_exit_state(state, "unable to create renderer");
- start.hexcode = PALETTE_START;
- end.hexcode = PALETTE_END;
- state->palette = create_palette(start, end);
- if (state->palette == NULL)
- error_exit_state(state, "unable to create color palette");
- state->canvas = SDL_CreateTexture(
- state->renderer, SDL_PIXELFORMAT_RGBA8888,
- SDL_TEXTUREACCESS_TARGET, config->window_w, config->window_h
- );
- if (state->canvas == NULL)
- error_exit_state(state, "unable to create canvas texture");
- state->running = true;
- state->window_w = config->window_w;
- state->window_h = config->window_h;
- state->real_range = config->real_range;
- state->imag_range = config->imag_range;
- state->center.x = config->center_x;
- state->center.y = config->center_y;
- state->in_set_color.hexcode = IN_SET_COLOR;
- state->moving = false;
- state->changed = true;
- return state;
-}
-
-void graphics_quit(GState *state)
-{
- destroy_state(state);
- SDL_Quit();
-}
-
-void graphics_run(GState *state)
-{
- while (state->running)
- {
- event_handler(state);
- if (state->changed)
- {
- update(state);
- state->changed = false;
- }
- SDL_Delay(REFRESH_RATE);
- }
-}
-
-static void update(GState *state)
-{
- void *pixels = mandelbrot_pixels(REAL_LO(state), REAL_HI(state),
- IMAG_LO(state), IMAG_HI(state),
- state->window_w, state->window_h, state->palette);
- if (pixels == NULL)
- error_exit_state(state, "unable to create pixels");
- SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(
- pixels, state->window_w, state->window_h,
- PIXELS_DEPTH, PITCH(PIXELS_CHANELS, state->window_w),
- RED_MASK, BLUE_MASK, GREEN_MASK, 0
- );
- if (surface == NULL)
- {
- free(pixels);
- error_exit_state(state, "unable to create pixels surface");
- }
- SDL_Texture *texture = SDL_CreateTextureFromSurface(state->renderer, surface);
- free(pixels);
- SDL_FreeSurface(surface);
- if (texture == NULL)
- error_exit_state(state, "unable to create texture");
- SDL_Rect frame;
- if (SDL_QueryTexture(texture, NULL, NULL, &frame.w, &frame.h) != 0)
- {
- SDL_DestroyTexture(texture);
- error_exit_state(state, "unable to load texture");
- }
- frame.x = 0;
- frame.y = 0;
- if (SDL_RenderCopy(state->renderer, texture, NULL, &frame) != 0)
- {
- SDL_DestroyTexture(texture);
- error_exit_state(state, "unable to render texture");
- }
- SDL_RenderPresent(state->renderer);
- SDL_DestroyTexture(texture);
-}
-
-static void event_handler(GState *state)
-{
- SDL_Event e;
- while (SDL_PollEvent(&e))
- {
- switch (e.type)
- {
- case SDL_QUIT:
- state->running = false;
- break;
- case SDL_KEYDOWN:
- switch (e.key.keysym.sym)
- {
- case SDLK_UP:
- case SDLK_k:
- state->center.y -= state->imag_range / MOVE_RATIO;
- break;
- case SDLK_DOWN:
- case SDLK_j:
- state->center.y += state->imag_range / MOVE_RATIO;
- break;
- case SDLK_LEFT:
- case SDLK_h:
- state->center.x -= state->real_range / MOVE_RATIO;
- break;
- case SDLK_RIGHT:
- case SDLK_l:
- state->center.x += state->real_range / MOVE_RATIO;
- break;
- case SDLK_PLUS:
- case SDLK_p:
- zoom_in(state, ZOOM_RATIO);
- break;
- case SDLK_MINUS:
- case SDLK_m:
- zoom_out(state, ZOOM_RATIO);
- break;
- case SDLK_q:
- state->running = false;
- }
- break;
- case SDL_MOUSEWHEEL:
- if (e.wheel.y == -1)
- zoom_in(state, ZOOM_RATIO);
- else if (e.wheel.y == 1)
- zoom_out(state, ZOOM_RATIO);
- break;
- case SDL_MOUSEBUTTONDOWN:
- /* printf("> %d, %d\n", e.button.x, e.button.y); */
- if (e.button.button == SDL_BUTTON_RIGHT)
- recenter(state, e.button.x, e.button.y);
- // TODO
- /* case SDL_MOUSEBUTTONUP: */
- /* if (e.button.button == SDL_BUTTON_LEFT) */
- /* { */
- /* if (!state->moving && e.button.state == SDL_PRESSED) */
- /* state->moving = true; */
- /* else if (state->moving && e.button.state == SDL_RELEASED) */
- /* state->moving = false; */
- /* printf("%d %d\n", state->moving, e.button.state); */
- /* } */
- /* break; */
- /* case SDL_MOUSEMOTION: */
- /* if (state->moving) */
- /* { */
- /* printf("%d, %d\n", e.motion.x, e.motion.y); */
- /* move_center(state, e.motion.xrel, e.motion.yrel); */
- /* printf("%f, %f\n", state->center.x, state->center.y); */
- /* } */
- }
- state->changed = true;
- }
-}
-
- static Color *create_palette(Color start, Color end)
-{
- int red_step = abs(end.rgb.r - start.rgb.r) / MAX_ITERATION;
- int green_step = abs(end.rgb.g - start.rgb.g) / MAX_ITERATION;
- int blue_step = abs(end.rgb.b - start.rgb.b) / MAX_ITERATION;
-
- Color *palette = (Color*)malloc(sizeof(Color) * (MAX_ITERATION + 1));
- if (palette == NULL)
- return NULL;
- for (int i = 0; i < MAX_ITERATION; i++)
- {
- /* palette[i] = helper_HSL_to_RGB(i, 0.6, 1.0); */
- /* printf("%x\n", palette[i].hexcode); */
- palette[i].rgb.r = i * red_step + start.rgb.r;
- palette[i].rgb.g = i * green_step + start.rgb.g;
- palette[i].rgb.b = i * blue_step + start.rgb.b;
- }
- palette[MAX_ITERATION].hexcode = 0x0;
- return palette;
-}
-
-// TODO
-/* static void move_center(GState *state, int motion_x, int motion_y) */
-/* { */
-/* printf("%d, %d\n", motion_x, motion_y); */
-/* if (motion_x != 0) */
-/* state->center.x -= map_range(150 - motion_x, 0, state->window_w, */
-/* REAL_LO(state), REAL_HI(state)); */
-/* if (motion_y != 0) */
-/* state->center.y -= map_range(150 - motion_y, 0, state->window_h, */
-/* IMAG_LO(state), IMAG_HI(state)); */
-/* printf(">> %f, %f\n", state->center.x, state->center.y); */
-/* } */
-
-static void recenter(GState *state, int x, int y)
-{
- recenter_x(state, x);
- recenter_y(state, y);
-}
-
-static void recenter_x(GState *state, int x)
-{
- state->center.x = map_range(x, 0, state->window_w,
- REAL_LO(state), REAL_HI(state));
-}
-
-static void recenter_y(GState *state, int y)
-{
- state->center.y = map_range(y, 0, state->window_w,
- IMAG_LO(state), IMAG_HI(state));
-}
-
-static void zoom_in(GState *state, double ratio)
-{
- state->real_range /= ratio;
- state->imag_range /= ratio;
-}
-
-static void zoom_out(GState *state, double ratio)
-{
- state->real_range *= ratio;
- state->imag_range *= ratio;
-}
-
-static void destroy_state(GState *state)
-{
- if (state == NULL)
- return;
- free(state->palette);
- SDL_DestroyTexture(state->canvas);
- SDL_DestroyRenderer(state->renderer);
- SDL_DestroyWindow(state->window);
- free(state);
-}
-
-static void error_exit_state(GState *state, const char *msg)
-{
- destroy_state(state);
- error_exit(msg);
-}
-
-static void error_exit(const char *msg)
-{
- SDL_Log("ERROR: %s: %s", SDL_GetError(), msg);
- SDL_Quit();
- exit(EXIT_FAILURE);
-}
diff --git a/header.h b/header.h
deleted file mode 100644
index 92b4d83..0000000
--- a/header.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef HEADER_H
-# define HEADER_H
-
-# include <stdbool.h>
-# include <SDL2/SDL.h>
-
-# define MAX_ITERATION 200
-# define ESCAPE_RADIUS 10
-# define ESCAPE_RADIUS_SQUARED (ESCAPE_RADIUS * ESCAPE_RADIUS)
-
-# define PIXELS_CHANELS 3
-# define PIXELS_DEPTH (PIXELS_CHANELS * 8)
-
-typedef uint8_t Byte;
-typedef int ColorHexcode;
-
-typedef union
-{
- ColorHexcode hexcode;
- struct
- {
- Byte b;
- Byte g;
- Byte r;
- } rgb;
-} Color;
-
-typedef struct
-{
- double x;
- double y;
-} Point;
-
-typedef struct
-{
- SDL_Window *window;
- SDL_Renderer *renderer;
- bool running;
- int window_w;
- int window_h;
- Point center;
- double real_range;
- double imag_range;
- Color *palette;
- Color in_set_color;
- bool moving;
- bool changed;
- SDL_Texture *canvas;
-} GState;
-
-typedef struct
-{
- int window_w;
- int window_h;
- double real_range;
- double imag_range;
- double center_x;
- double center_y;
-} Config;
-
-typedef struct
-{
- double real_lo;
- double real_hi;
- double imag_step;
- int width;
- double imag;
- Color *palette;
- uint8_t *row;
-} ThreadArgs;
-
-// mandelbrot.c
-int mandelbrot_in_set(double a, double b);
-void mandelbrot_print(void);
-void *mandelbrot_pixels(double real_lo, double real_hi, double imag_lo,
- double imag_hi, int width, int height, Color *palette);
-
-// graphics.c
-GState *graphics_init(Config *config);
-void graphics_quit(GState *state);
-void graphics_run(GState *state);
-
-// helper.c
-double map_range(double x, double src_lo, double src_hi, double dest_lo, double dest_hi);
-Color helper_HSL_to_RGB(int hue, double saturation, double lightness);
-double double_rand(void);
-
-#endif
diff --git a/helper.c b/helper.c
deleted file mode 100644
index 3e02182..0000000
--- a/helper.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <math.h>
-#include "header.h"
-
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#define MIN3(x, y, z) (MIN(x, MIN(y, z)))
-
-double map_range(double x, double src_lo, double src_hi, double dest_lo, double dest_hi)
-{
- double src_len = src_hi - src_lo;
- double dest_len = dest_hi - dest_lo;
- return (x - src_lo) / src_len * dest_len + dest_lo;
-}
-
-Color helper_HSL_to_RGB(int hue, double saturation, double lightness)
-{
- /* double chroma = (1 - fabs(2 * lightness - 1)) * saturation; */
- /* int hue_p = hue / 60; */
- /* double x = chroma * (1 - abs(hue_p % 2 - 1)); */
- Color color;
-
- /* if (hue == 0) */
- /* { */
- /* color.hexcode = 0x000000; */
- /* return color; */
- /* } */
- /* */
- /* if (hue_p */
-
- double a = saturation * MIN(lightness, 1 - lightness);
- int kn0 = (0 + hue / 30) % 12;
- int kn8 = (8 + hue / 30) % 12;
- int kn4 = (4 + hue / 30) % 12;
- Byte f0 = lightness - a * MAX(MIN3(kn0 - 3, 9 - kn0, 1), -1);
- Byte f8 = lightness - a * MAX(MIN3(kn8 - 3, 9 - kn8, 1), -1);
- Byte f4 = lightness - a * MAX(MIN3(kn4 - 3, 9 - kn4, 1), -1);
-
- color.rgb.r = f0;
- color.rgb.g = f8;
- color.rgb.b = f4;
-
- return color;
-}
-
-double double_rand(void)
-{
- return (double)rand() / RAND_MAX;
-}
diff --git a/inc/config.h b/inc/config.h
new file mode 100644
index 0000000..4085dba
--- /dev/null
+++ b/inc/config.h
@@ -0,0 +1,9 @@
+#ifndef CONFIG_H
+# define CONFIG_H
+
+# define MANDEL_WINDOW_WIDTH 640
+# define MANDEL_WINDOW_HEIGHT 480
+
+# define MANDEL_WINDOW_TITLE "Mandelbrot"
+
+#endif
diff --git a/inc/mandel.h b/inc/mandel.h
new file mode 100644
index 0000000..e6f3e10
--- /dev/null
+++ b/inc/mandel.h
@@ -0,0 +1,55 @@
+#ifndef MANDEL_H
+# define MANDEL_H
+
+# include <stdlib.h>
+# include <stdbool.h>
+# include <math.h>
+# include <SDL2/SDL.h>
+
+#define SDL_CALL(x) do { \
+ SDL_ClearError(); \
+ x; \
+ error_check_sdl(#x, __FILE__, __LINE__); \
+} while (0)
+
+typedef union
+{
+ uint32_t data;
+ struct
+ {
+ uint8_t b;
+ uint8_t g;
+ uint8_t r;
+ };
+} Color;
+
+typedef struct
+{
+ double x;
+ double y;
+} Point;
+
+typedef struct
+{
+ SDL_Window *window;
+ SDL_Renderer *renderer;
+ bool running;
+ SDL_Surface *surface;
+ Color *palette;
+} State;
+
+// mandelbrot.c
+int mandelbrot(double a, double b);
+
+// state.c
+bool state_init(State *state);
+void state_quit(State *state);
+void state_run(State *state);
+
+// event.c
+void event_handle(State *state);
+
+// error.c
+void error_check_sdl(const char *code, const char *filename, int line_num);
+
+#endif
diff --git a/main.c b/main.c
deleted file mode 100644
index 51ac8c9..0000000
--- a/main.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <getopt.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include "header.h"
-
-#define DEFAULT_WINDOW_W 300
-#define DEFAULT_WINDOW_H 300
-#define DEFAULT_CENTER_X 0.0
-#define DEFAULT_CENTER_Y 0.0
-#define DEFAULT_REAL_RANGE 4.0
-#define DEFAULT_IMAG_RANGE 4.0
-
-static void print_help(void);
-
-int main(int argc, char **argv)
-{
- int opt;
- Config config;
- /* Image *image = NULL; */
-
- config.window_w = DEFAULT_WINDOW_W;
- config.window_h = DEFAULT_WINDOW_H;
- config.center_x = DEFAULT_CENTER_X;
- config.center_y = DEFAULT_CENTER_Y;
- config.real_range = DEFAULT_REAL_RANGE;
- config.imag_range = DEFAULT_IMAG_RANGE;
- while ((opt = getopt(argc, argv, "hps:r:c:")) != -1)
- {
- switch (opt)
- {
- case 'p':
- mandelbrot_print();
- exit(EXIT_SUCCESS);
- break;
- /* case 'i': */
- /* image = image_init(); */
- case 'h':
- print_help();
- exit(EXIT_SUCCESS);
- break;
- case 's':
- sscanf(optarg, "%d,%d", &config.window_w, &config.window_h);
- break;
- case 'r':
- sscanf(optarg, "%lf,%lf", &config.real_range, &config.imag_range);
- break;
- case 'c':
- sscanf(optarg, "%lf,%lf", &config.center_x, &config.center_y);
- break;
- case '?':
- default:
- fprintf(stderr, "Try: %s -h for more information", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- }
- /* if (image != NULL) */
- /* { */
- /* */
- /* return EXIT_SUCCESS; */
- /* } */
- GState *gstate = graphics_init(&config);
- graphics_run(gstate);
- graphics_quit(gstate);
- return EXIT_SUCCESS;
-}
-
-static void print_help(void)
-{
- printf("help");
-}
diff --git a/mandelbrot.c b/mandelbrot.c
deleted file mode 100644
index 7017a54..0000000
--- a/mandelbrot.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#include <stdio.h>
-#include <math.h>
-#include <pthread.h>
-#include "header.h"
-
-#define PRINT_REAL_LO -2.0
-#define PRINT_REAL_HI 2.0
-#define PRINT_IMAG_LO -2.0
-#define PRINT_IMAG_HI 2.0
-#define AXIS_DIV 46.0
-#define REAL_AXIS_STEP ((PRINT_REAL_HI - PRINT_REAL_LO) / AXIS_DIV)
-#define IMAG_AXIS_STEP ((PRINT_IMAG_HI - PRINT_IMAG_LO) / AXIS_DIV)
-#define SAMPLES 1
-
-#define IN_CHAR '*'
-#define OUT_CHAR ' '
-
-static void *pixel_row(void *args);
-
-int mandelbrot_in_set(double ca, double cb)
-{
- double zr = ca;
- double zi = cb;
- double zr_square;
- double zi_square;
- int n;
- for (n = 0; n < MAX_ITERATION; n++)
- {
- zi_square = zi * zi;
- zr_square = zr * zr;
- if (zr_square + zi_square > ESCAPE_RADIUS_SQUARED)
- return n;
- /* return n + 5 - clog(ESCAPE_RADIUS) / log(2); */
- zi = 2 * zr * zi;
- zr = zr_square - zi_square;
- zi += cb;
- zr += ca;
- }
- return n;
-}
-
-
-int mandelbrot_in_set_super_sampled(double ca, double cb, double real_step, double imag_step)
-{
- int total = 0;
- for (int i = 0; i < SAMPLES; i++)
- total += mandelbrot_in_set(ca - (double_rand() * real_step) / 2,
- cb - (double_rand() * imag_step) / 2);
- return total / SAMPLES;
-}
-
-void *mandelbrot_pixels(double real_lo, double real_hi, double imag_lo,
- double imag_hi, int width, int height, Color *palette)
-{
- Byte *pixels = (Byte*)malloc(width * height * PIXELS_CHANELS);
- if (pixels == NULL)
- return NULL;
- pthread_t *threads = (pthread_t*)malloc(sizeof(pthread_t) * height);
- if (threads == NULL)
- return NULL;
- for (int y = 0; y < height; y++)
- {
- ThreadArgs *args = (ThreadArgs*)malloc(sizeof(ThreadArgs));
- if (args == NULL)
- return NULL;
- args->real_lo = real_lo;
- args->real_hi = real_hi;
- args->width = width;
- args->imag = map_range((double)y, 0, height, imag_lo, imag_hi);
- args->imag_step = (imag_hi - imag_lo) / (0.5 + (height - 1));
- args->palette = palette;
- args->row = pixels + PIXELS_CHANELS * width * y;
- pthread_create(&threads[y], NULL, pixel_row, args);
- }
- for (int y = 0; y < height; y++)
- pthread_join(threads[y], NULL);
- free(threads);
- return (void*)pixels;
-}
-
-static void *pixel_row(void *void_args)
-{
- ThreadArgs *args = (ThreadArgs*)void_args;
- int iterations;
- double real_step = (args->real_hi - args->real_lo) / (0.5 + (args->width - 1));
- for (int x = 0; x < args->width; x++)
- {
- double a = map_range((double)x, 0, args->width, args->real_lo, args->real_hi);
- if (SAMPLES == 1)
- iterations = mandelbrot_in_set(a, args->imag);
- else
- {
- iterations = mandelbrot_in_set_super_sampled(
- a, args->imag, real_step, args->imag_step);
- }
-
- /* double logBase = 1.0 / log(2.0); */
- /* double logHalfBase = log(0.5) * logBase; */
- /* int color_index = (int)(5 + iterations - logHalfBase */
- /* - log(log(a * a + args->imag * args->imag)) * logBase); */
- Color color = args->palette[iterations];
- int row_index = x * PIXELS_CHANELS;
- args->row[row_index] = color.rgb.r;
- args->row[row_index + 1] = color.rgb.g;
- args->row[row_index + 2] = color.rgb.b;
- }
- free(args);
- return NULL;
-}
-
-void mandelbrot_print(void)
-{
- for (double i = PRINT_IMAG_LO; i < PRINT_IMAG_HI; i += IMAG_AXIS_STEP)
- {
- for (double r = PRINT_REAL_LO; r < PRINT_REAL_HI; r += REAL_AXIS_STEP)
- {
- if (mandelbrot_in_set(r, i) == -1)
- putchar(IN_CHAR);
- else
- putchar(OUT_CHAR);
- putchar(' ');
- }
- putchar('\n');
- }
-}
diff --git a/src/color.c b/src/color.c
new file mode 100644
index 0000000..f758595
--- /dev/null
+++ b/src/color.c
@@ -0,0 +1,22 @@
+#include "mandel.h"
+
+/* static Color *create_palette(Color start, Color end) */
+/* { */
+ /* int red_step = abs(end.rgb.r - start.rgb.r) / MAX_ITERATION; */
+ /* int green_step = abs(end.rgb.g - start.rgb.g) / MAX_ITERATION; */
+ /* int blue_step = abs(end.rgb.b - start.rgb.b) / MAX_ITERATION; */
+ /* */
+ /* Color *palette = (Color*)malloc(sizeof(Color) * (MAX_ITERATION + 1)); */
+ /* if (palette == NULL) */
+ /* return NULL; */
+ /* for (int i = 0; i < MAX_ITERATION; i++) */
+ /* { */
+ /* #<{(| palette[i] = helper_HSL_to_RGB(i, 0.6, 1.0); |)}># */
+ /* #<{(| printf("%x\n", palette[i].hexcode); |)}># */
+ /* palette[i].rgb.r = i * red_step + start.rgb.r; */
+ /* palette[i].rgb.g = i * green_step + start.rgb.g; */
+ /* palette[i].rgb.b = i * blue_step + start.rgb.b; */
+ /* } */
+ /* palette[MAX_ITERATION].hexcode = 0x0; */
+ /* return palette; */
+/* } */
diff --git a/src/error.c b/src/error.c
new file mode 100644
index 0000000..92e3a71
--- /dev/null
+++ b/src/error.c
@@ -0,0 +1,13 @@
+#include "mandel.h"
+
+void error_check_sdl(const char *code, const char *filename, int line_num)
+{
+ const char *err;
+
+ err = SDL_GetError();
+ if (*err == '\0')
+ return ;
+ SDL_Log("[ERROR SDL] %s\n\t(%s) at %s:%d", err, code, filename, line_num);
+ SDL_Quit();
+ exit(EXIT_FAILURE);
+}
diff --git a/src/event.c b/src/event.c
new file mode 100644
index 0000000..d0354eb
--- /dev/null
+++ b/src/event.c
@@ -0,0 +1,56 @@
+#include "mandel.h"
+
+void event_handle(State *state)
+{
+ SDL_Event e;
+
+ while (SDL_PollEvent(&e))
+ {
+ switch (e.type)
+ {
+ case SDL_QUIT:
+ state->running = false;
+ break;
+ case SDL_KEYDOWN:
+ switch (e.key.keysym.sym)
+ {
+ case SDLK_UP:
+ case SDLK_k:
+
+ break;
+ case SDLK_DOWN:
+ case SDLK_j:
+
+ break;
+ case SDLK_LEFT:
+ case SDLK_h:
+
+ break;
+ case SDLK_RIGHT:
+ case SDLK_l:
+
+ break;
+ case SDLK_PLUS:
+ case SDLK_p:
+
+ break;
+ case SDLK_MINUS:
+ case SDLK_m:
+
+ break;
+ case SDLK_q:
+ state->running = false;
+ }
+ break;
+ case SDL_MOUSEWHEEL:
+ if (e.wheel.y == -1)
+ ;
+ else if (e.wheel.y == 1)
+ ;
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ break;
+ }
+ }
+}
+
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..c19d32a
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,12 @@
+#include "mandel.h"
+
+int main(void)
+{
+ State state;
+
+ if (!state_init(&state))
+ return (1);
+ state_run(&state);
+ state_quit(&state);
+ return EXIT_SUCCESS;
+}
diff --git a/src/mandelbrot.c b/src/mandelbrot.c
new file mode 100644
index 0000000..a996b26
--- /dev/null
+++ b/src/mandelbrot.c
@@ -0,0 +1,22 @@
+#include "mandel.h"
+
+int mandelbrot(double ca, double cb)
+{
+ double zr = ca;
+ double zi = cb;
+ double zr_square;
+ double zi_square;
+ int n;
+ for (n = 0; n < 20; n++)
+ {
+ zi_square = zi * zi;
+ zr_square = zr * zr;
+ if (zr_square + zi_square > 4)
+ return n;
+ zi = 2 * zr * zi;
+ zr = zr_square - zi_square;
+ zi += cb;
+ zr += ca;
+ }
+ return n;
+}
diff --git a/src/state.c b/src/state.c
new file mode 100644
index 0000000..ee68b77
--- /dev/null
+++ b/src/state.c
@@ -0,0 +1,34 @@
+#include "config.h"
+#include "mandel.h"
+
+bool state_init(State *state)
+{
+ SDL_CALL(SDL_Init(SDL_INIT_VIDEO));
+ SDL_CALL(state->window = SDL_CreateWindow(
+ MANDEL_WINDOW_TITLE,
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ MANDEL_WINDOW_WIDTH,
+ MANDEL_WINDOW_HEIGHT,
+ 0));
+ SDL_CALL(state->renderer = SDL_CreateRenderer(state->window, -1, 0));
+ state->running = true;
+ return state;
+}
+
+void state_run(State *state)
+{
+ while (state->running)
+ {
+ event_handle(state);
+ }
+}
+
+void state_quit(State *state)
+{
+ /* free(state->palette); */
+ /* SDL_FreeSurface(state->surface); */
+ SDL_DestroyRenderer(state->renderer);
+ SDL_DestroyWindow(state->window);
+ SDL_Quit();
+}