Quellcode durchsuchen

Abstract away different Double Buffering Implementations

rexim vor 4 Jahren
Ursprung
Commit
e4c04f9b03
5 geänderte Dateien mit 97 neuen und 9 gelöschten Zeilen
  1. 1 1
      Makefile
  2. 2 2
      README.md
  3. 27 0
      db_none.c
  4. 44 0
      db_xdbe.c
  5. 23 6
      main.c

+ 1 - 1
Makefile

@@ -2,4 +2,4 @@ CFLAGS=-Wall -Wextra -std=c11 -pedantic -ggdb
 LIBS=-lX11 -lXext
 
 main: main.c
-	$(CC) $(CFLAGS) -o main main.c $(LIBS)
+	$(CC) $(CFLAGS) -DDB_IMPL=0 -o main main.c $(LIBS)

+ 2 - 2
README.md

@@ -3,9 +3,9 @@
 Trying different approaches to Double Buffering in Pure X11 applications on Linux:
 
 - [x] No Double Buffering
-- [ ] Back Buffer in XImage
-- [ ] Back Buffer in Pixmap
 - [ ] [Xdbe](https://www.x.org/releases/X11R7.7/doc/libXext/dbelib.html)
+- [ ] Back Buffer in Pixmap
+- [ ] Back Buffer in XImage
 
 ## Quick Start
 

+ 27 - 0
db_none.c

@@ -0,0 +1,27 @@
+#define DB_IMPL_NAME "None"
+
+typedef struct {
+    Display *display;
+    Window window;
+    GC gc;
+} DB;
+
+void db_init(DB *db, Display *display, Window window)
+{
+    db->display = display;
+    db->window = window;
+    db->gc = XCreateGC(display, window, 0, NULL);
+}
+
+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)
+{
+    XSetForeground(db->display, db->gc, 0xFF0000);
+    XFillRectangle(db->display, db->window, db->gc, x, y, w, h);
+}
+
+#define db_swap_buffers(...)

+ 44 - 0
db_xdbe.c

@@ -0,0 +1,44 @@
+#define DB_IMPL_NAME "Xdbe"
+
+typedef struct {
+    Display *display;
+    Window window;
+    GC gc;
+    XdbeBackBuffer back_buffer;
+} DB;
+
+void db_init(DB *db, Display *display, Window window)
+{
+    int major_version_return, minor_version_return;
+    if(XdbeQueryExtension(display, &major_version_return, &minor_version_return)) {
+        printf("XDBE version %d.%d\n", major_version_return, minor_version_return);
+    } else {
+        fprintf(stderr, "XDBE is not supported!!!1\n");
+        exit(1);
+    }
+
+    db->display = display;
+    db->window = window;
+    db->gc = XCreateGC(display, window, 0, NULL);
+    db->back_buffer = XdbeAllocateBackBufferName(display, window, 0);
+}
+
+void db_clear(DB *db)
+{
+    XSetForeground(db->display, db->gc, 0);
+    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)
+{
+    XSetForeground(db->display, db->gc, 0xFF0000);
+    XFillRectangle(db->display, db->back_buffer, db->gc, x, y, w, h);
+}
+
+void db_swap_buffers(DB *db)
+{
+    XdbeSwapInfo swap_info;
+    swap_info.swap_window = db->window;
+    swap_info.swap_action = 0;
+    XdbeSwapBuffers(db->display, &swap_info, 1);
+}

+ 23 - 6
main.c

@@ -3,6 +3,7 @@
 #include <stdlib.h>
 
 #include <X11/Xlib.h>
+#include <X11/extensions/Xdbe.h>
 
 #include <unistd.h>
 
@@ -12,8 +13,25 @@
 #define RECT_WIDTH 300
 #define RECT_HEIGHT 300
 
+#define DB_NONE   0
+#define DB_XDBE   1
+#define DB_XIMAGE 2
+#define DB_PIXMAP 3
+
+#if DB_IMPL == DB_NONE
+#  include "./db_none.c"
+#elif DB_IMPL == DB_XDBE
+#  include "./db_xdbe.c"
+#else
+#  error "Unsupported Double Buffering approach"
+#endif
+
 int main(void)
 {
+    printf("Double Buffering Implementation: "DB_IMPL_NAME"\n");
+
+    DB db = {0};
+
     Display *display = XOpenDisplay(NULL);
     if (display == NULL) {
         fprintf(stderr, "ERROR: could not open the default display\n");
@@ -29,11 +47,11 @@ int main(void)
                         0,
                         0);
 
+    db_init(&db, display, window);
+
     XWindowAttributes wa = {0};
     XGetWindowAttributes(display, window, &wa);
 
-    GC gc = XCreateGC(display, window, 0, NULL);
-
     Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
     XSetWMProtocols(display, window, &wm_delete_window, 1);
 
@@ -41,8 +59,6 @@ int main(void)
 
     XMapWindow(display, window);
 
-    XSetForeground(display, gc, 0xFF0000);
-
     int rect_x = 10;
     int rect_y = 10;
 
@@ -73,8 +89,9 @@ int main(void)
             }
         }
 
-        XClearArea(display, window, 0, 0, WIDTH, HEIGHT, False);
-        XFillRectangle(display, window, gc, rect_x, rect_y, RECT_WIDTH, RECT_HEIGHT);
+        db_clear(&db);
+        db_fill_rect(&db, rect_x, rect_y, RECT_WIDTH, RECT_HEIGHT);
+        db_swap_buffers(&db);
 
         int rect_nx = rect_x + rect_dx;
         if (rect_nx <= 0 || rect_nx + RECT_WIDTH >= WIDTH) {