From f7edafe7752c7545deb43e2b253735b7abd4b7cd Mon Sep 17 00:00:00 2001 From: EliteTK Date: Mon, 17 Nov 2014 00:42:00 +0000 Subject: xcb_gol.c: xcb_gol_macro.c: new --- xcb_gol.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 xcb_gol.c (limited to 'xcb_gol.c') diff --git a/xcb_gol.c b/xcb_gol.c new file mode 100644 index 0000000..71beeb0 --- /dev/null +++ b/xcb_gol.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2014 Tomasz Kramkowski + * + * This program is free software. It is licensed under version 3 of the + * GNU General Public License. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see [http://www.gnu.org/licenses/]. + */ +#include +#include +#include +#include +#include +#include + +#define BOARD_WIDTH 500 +#define BOARD_HEIGHT 500 + +#define PIXEL 1 + +#define WIDTH (BOARD_WIDTH * PIXEL) +#define HEIGHT (BOARD_HEIGHT * PIXEL) + +typedef struct gol_t { + uint32_t width, height; + bool *buffers[2]; + uint8_t front; +} Gol; + +Gol *gol_new(unsigned const int width, unsigned const int height) +{ + Gol *gol = malloc(sizeof(Gol)); + gol->width = width; + gol->height = height; + gol->front = 0; + gol->buffers[0] = malloc(width * height * sizeof(bool)); + gol->buffers[1] = malloc(width * height * sizeof(bool)); + return gol; +} + +void gol_del(Gol *gol) +{ + free(gol->buffers[0]); + free(gol->buffers[1]); + free(gol); +} + +void gol_random(Gol *const gol, unsigned const int seed) +{ + srand(seed); + for (uint32_t i = 0; i < gol->width * gol->height; i++) + gol->buffers[gol->front][i] = rand() < 0.5 * ((double)RAND_MAX + 1.0); +} + +static inline uint32_t gol_clamp(const int32_t pos, const int32_t max) { + return pos < 0 ? pos + max : pos % max; +} + +static inline bool *gol_resolve(const Gol *const gol, const uint8_t buffer, const int32_t x, const int32_t y) +{ + return gol->buffers[buffer] + gol_clamp(x, gol->width) + + gol_clamp(y, gol->height) * gol->width; +} + +static inline bool *gol_resolve_f(const Gol *const gol, const int32_t x, const int32_t y) +{ + return gol_resolve(gol, gol->front, x, y); +} + +static inline bool *gol_resolve_b(const Gol *const gol, const int32_t x, const int32_t y) +{ + return gol_resolve(gol, !gol->front, x, y); +} + +static uint8_t gol_neighbours(Gol *const gol, const uint32_t x, const uint32_t y) +{ + uint8_t neighbours = 0; + for (int8_t dx = -1; dx <= 1; dx++) + for (int8_t dy = -1; dy <= 1; dy++) + if (!(dx == 0 && dy == 0) && *gol_resolve_f(gol, x + dx, y + dy)) + neighbours++; + return neighbours; +} + +void gol_simulate(Gol *const gol) +{ + for (uint32_t x = 0; x < gol->width; x++) + for (uint32_t y = 0; y < gol->height; y++) { + uint8_t neighbours = gol_neighbours(gol, x, y); + if (*gol_resolve_f(gol, x, y)){ + if (neighbours < 2) + *gol_resolve_b(gol, x, y) = 0; + else if (neighbours <= 3) + *gol_resolve_b(gol, x, y) = 1; + else + *gol_resolve_b(gol, x, y) = 0; + } else { + if (neighbours == 3) + *gol_resolve_b(gol, x, y) = 1; + else + *gol_resolve_b(gol, x, y) = 0; + } + } + + gol->front = !gol->front; +} + +int main(int argc, char **argv) +{ + xcb_connection_t *connection = xcb_connect(NULL, NULL); + + xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; + + uint32_t mask = XCB_CW_BACK_PIXEL; + uint32_t values[] = {screen->black_pixel}; + + xcb_drawable_t window = xcb_generate_id(connection); + xcb_create_window(connection, + 24, + window, + screen->root, + 0, 0, + WIDTH, HEIGHT, + 1, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + mask, values); + + xcb_pixmap_t pixmap = xcb_generate_id(connection); + xcb_create_pixmap(connection, + 24, + pixmap, + window, + WIDTH, HEIGHT); + + uint8_t *img = malloc(WIDTH * HEIGHT * 4); + xcb_image_t *image = xcb_image_create(WIDTH, HEIGHT, + XCB_IMAGE_FORMAT_Z_PIXMAP, + 8, 24, 32, + 0, + XCB_IMAGE_ORDER_MSB_FIRST, + XCB_IMAGE_ORDER_LSB_FIRST, + img, + WIDTH * HEIGHT * 4, + img); + + mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; + values[0] = screen->black_pixel; + values[1] = 0xFFFFFF; + + xcb_gcontext_t gc = xcb_generate_id(connection); + xcb_create_gc(connection, + gc, + pixmap, + mask, values); + + xcb_image_put(connection, pixmap, gc, image, 0, 0, 0); + + xcb_map_window(connection, window); + xcb_flush(connection); + + uint8_t value = 0; + + uint32_t *limg; + + Gol *gol = gol_new(BOARD_WIDTH, BOARD_HEIGHT); + gol_random(gol, time(NULL)); + + while (1) { + limg = (uint32_t *)image->data; + + for (int i = 0; i < gol->width * gol->height; i++) + *(limg++) = gol->buffers[gol->front][i] ? 0x00FFFF00 : 0x00000000; + + xcb_image_put(connection, pixmap, gc, image, 0, 0, 0); + + xcb_copy_area(connection, + pixmap, + window, + gc, + 0, 0, + 0, 0, + WIDTH, HEIGHT); + xcb_flush(connection); + value++; + + gol_simulate(gol); + } + return 0; +} -- cgit v1.2.3-54-g00ecf