Browse Source

Implement ximage double buffering

rexim 4 years ago
parent
commit
3f38ce6526
6 changed files with 66 additions and 4 deletions
  1. 4 1
      Makefile
  2. 1 1
      db_none.c
  3. 1 1
      db_pixmap.c
  4. 1 1
      db_xdbe.c
  5. 55 0
      db_ximage.c
  6. 4 0
      main.c

+ 4 - 1
Makefile

@@ -2,7 +2,7 @@ CFLAGS=-Wall -Wextra -std=c11 -pedantic -ggdb
 LIBS=-lX11 -lXext
 
 .PHONY: all
-all: main.none main.xdbe main.pixmap 
+all: main.none main.xdbe main.pixmap main.ximage
 
 main.none: main.c
 	$(CC) $(CFLAGS) -DDB_IMPL=DB_NONE -o main.none main.c $(LIBS)
@@ -12,3 +12,6 @@ main.xdbe: main.c
 
 main.pixmap: main.c
 	$(CC) $(CFLAGS) -DDB_IMPL=DB_PIXMAP -o main.pixmap main.c $(LIBS)
+
+main.ximage: main.c
+	$(CC) $(CFLAGS) -DDB_IMPL=DB_XIMAGE -o main.ximage main.c $(LIBS)

+ 1 - 1
db_none.c

@@ -18,7 +18,7 @@ void db_clear(DB *db)
     XClearArea(db->display, db->window, 0, 0, WIDTH, HEIGHT, False);
 }
 
-void db_fill_rect(DB *db, int x, int y, int w, int h)
+void db_fill_rect(DB *db, int x, int y, unsigned int w, unsigned int h)
 {
     XSetForeground(db->display, db->gc, 0xFF0000);
     XFillRectangle(db->display, db->window, db->gc, x, y, w, h);

+ 1 - 1
db_pixmap.c

@@ -21,7 +21,7 @@ void db_clear(DB *db)
     XFillRectangle(db->display, db->back_buffer, db->gc, 0, 0, WIDTH, HEIGHT);
 }
 
-void db_fill_rect(DB *db, int x, int y, int w, int h)
+void db_fill_rect(DB *db, int x, int y, unsigned int w, unsigned int h)
 {
     XSetForeground(db->display, db->gc, 0xFF0000);
     XFillRectangle(db->display, db->back_buffer, db->gc, x, y, w, h);

+ 1 - 1
db_xdbe.c

@@ -29,7 +29,7 @@ void db_clear(DB *db)
     XFillRectangle(db->display, db->back_buffer, db->gc, 0, 0, WIDTH, HEIGHT);
 }
 
-void db_fill_rect(DB *db, int x, int y, int w, int h)
+void db_fill_rect(DB *db, int x, int y, unsigned int w, unsigned int h)
 {
     XSetForeground(db->display, db->gc, 0xFF0000);
     XFillRectangle(db->display, db->back_buffer, db->gc, x, y, w, h);

+ 55 - 0
db_ximage.c

@@ -0,0 +1,55 @@
+#define DB_IMPL_NAME "XImage"
+
+typedef struct {
+    Display *display;
+    Window window;
+    GC gc;
+    uint32_t *pixels;
+    XImage *image;
+} DB;
+
+void db_init(DB *db, Display *display, Window window)
+{
+    db->display = display;
+    db->window = window;
+    db->gc = XCreateGC(display, window, 0, NULL);
+    db->pixels = malloc(sizeof(uint32_t) * WIDTH * HEIGHT);
+
+    XWindowAttributes wa = {0};
+    XGetWindowAttributes(display, window, &wa);
+
+    db->image = XCreateImage(display,
+                             wa.visual,
+                             wa.depth,
+                             ZPixmap,
+                             0,
+                             (char*) db->pixels,
+                             WIDTH, HEIGHT,
+                             32,
+                             WIDTH * sizeof(uint32_t));
+}
+
+void db_clear(DB *db)
+{
+    memset(db->pixels, 0, sizeof(uint32_t) * WIDTH * HEIGHT);
+}
+
+void db_fill_rect(DB *db, int x0, int y0, unsigned int w, unsigned int h)
+{
+    for (unsigned int dx = 0; dx < w; ++dx) {
+        for (unsigned int dy = 0; dy < h; ++dy) {
+            int x = x0 + dx;
+            int y = y0 + dy;
+
+            if (0 <= x && (unsigned int) x < WIDTH &&
+                    0 <= y && (unsigned int) y < HEIGHT) {
+                db->pixels[y*WIDTH + x] = 0xFF0000;
+            }
+        }
+    }
+}
+
+void db_swap_buffers(DB *db)
+{
+    XPutImage(db->display, db->window, db->gc, db->image, 0, 0, 0, 0, WIDTH, HEIGHT);
+}

+ 4 - 0
main.c

@@ -1,6 +1,8 @@
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
 
 #include <X11/Xlib.h>
 #include <X11/extensions/Xdbe.h>
@@ -24,6 +26,8 @@
 #  include "./db_xdbe.c"
 #elif DB_IMPL == DB_PIXMAP
 #  include "./db_pixmap.c"
+#elif DB_IMPL == DB_XIMAGE
+#  include "./db_ximage.c"
 #else
 #  error "Unsupported Double Buffering approach"
 #endif