summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2014-01-30 12:11:00 -0800
committerKeith Packard <keithp@keithp.com>2014-01-30 12:11:00 -0800
commit739c624630154b422d7f5e4ae92f93df42fa35b9 (patch)
tree19bab22b07540ef45da62a0128c847e2b583be79
parente8828fa0513e666fa7246cd213001c51d7957e0e (diff)
present demo: support multiple pixmaps
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--present.c146
1 files changed, 119 insertions, 27 deletions
diff --git a/present.c b/present.c
index f992f6d..a67893b 100644
--- a/present.c
+++ b/present.c
@@ -18,11 +18,15 @@
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
#include <time.h>
#include <sys/mman.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <xcb/present.h>
+#include <xcb/xfixes.h>
+#include <xcb/sync.h>
#define INIT_WIDTH 500
#define INIT_HEIGHT 500
@@ -34,9 +38,14 @@ xcb_screen_t *screen;
xcb_gc_t gc;
xcb_present_event_t present_event;
xcb_window_t window;
-xcb_pixmap_t pixmap;
+xcb_xfixes_region_t update;
+#define NPIXMAP 3
+xcb_pixmap_t pixmap[NPIXMAP];
+bool busy[NPIXMAP];
xcb_generic_event_t *event;
xcb_generic_error_t *error;
+xcb_sync_fence_t wait_fence;
+int using_fence;
const xcb_query_extension_reply_t *present_extension;
uint32_t window_mask;
uint32_t window_values[5];
@@ -49,29 +58,54 @@ int x;
int x_inc = 30;
uint64_t msc;
uint64_t target_msc;
+int interval = 0;
+uint32_t serial;
+uint32_t options = 0; // XCB_PRESENT_OPTION_ASYNC;
-static void make_pixmap(void)
+static void make_pixmap(int i)
{
xcb_create_pixmap(c,
24,
- (pixmap = xcb_generate_id(c)),
+ (pixmap[i] = xcb_generate_id(c)),
window,
width,
height);
}
+static void make_update(void)
+{
+ return;
+ xcb_rectangle_t rect = { .x = 0, .y = 0, .width = width, .height = height };
+
+ xcb_xfixes_create_region(c,
+ (update = xcb_generate_id(c)),
+ 1,
+ &rect);
+}
+
static void discard_pixmap(void)
{
- if (pixmap) {
- xcb_free_pixmap (c, pixmap);
- pixmap = 0;
+ int i;
+ for (i = 0; i < NPIXMAP; i++) {
+ if (pixmap[i]) {
+ xcb_free_pixmap (c, pixmap[i]);
+ pixmap[i] = 0;
+ }
+ }
+
+ if (update) {
+ xcb_xfixes_destroy_region(c, update);
+ update = 0;
}
}
-static void draw(void)
+static void draw(int i)
{
- if (!pixmap)
- make_pixmap();
+ if (!pixmap[i])
+ make_pixmap(i);
+
+ if (!update)
+ make_update();
gc_mask = XCB_GC_FOREGROUND;
gc_values[0] = 0xffffffff;
@@ -80,7 +114,7 @@ static void draw(void)
rectangle.y = 0;
rectangle.width = width;
rectangle.height = height;
- xcb_poly_fill_rectangle(c, pixmap, gc, 1, &rectangle);
+ xcb_poly_fill_rectangle(c, pixmap[i], gc, 1, &rectangle);
gc_mask = XCB_GC_FOREGROUND;
gc_values[0] = 0x0;
@@ -90,7 +124,7 @@ static void draw(void)
rectangle.y = 0;
rectangle.width = 60;
rectangle.height = height;
- xcb_poly_fill_rectangle(c, pixmap, gc, 1, &rectangle);
+ xcb_poly_fill_rectangle(c, pixmap[i], gc, 1, &rectangle);
x += x_inc;
if (x_inc > 0) {
@@ -104,20 +138,20 @@ static void draw(void)
#define None 0
-static void show(void)
+static void show(int i)
{
xcb_present_pixmap (c,
window,
- pixmap,
- 0,
- None,
+ pixmap[i],
+ i,
None,
+ update,
0,
0,
None,
+ using_fence ? wait_fence : None,
None,
- None,
- 0,
+ options,
target_msc,
0,
0,
@@ -126,6 +160,9 @@ static void show(void)
}
int frame_count;
+int skip_count;
+int copy_count;
+int flip_count;
uint32_t start_time;
uint32_t end_time;
@@ -139,10 +176,16 @@ millis(void)
static void frame(void)
{
- draw();
- target_msc = msc + 1;
- show();
- ++frame_count;
+ int p;
+
+ for (p = 0; p < NPIXMAP; p++) {
+ if (!busy[p]) {
+ busy[p] = true;
+ draw(p);
+ target_msc += interval;
+ show(p);
+ }
+ }
}
int
@@ -155,9 +198,11 @@ main (int argc, char **argv)
}
screen = xcb_aux_get_screen(c, screen_num);
+ (void) xcb_xfixes_query_version(c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
+
window_mask = XCB_CW_BACK_PIXEL|XCB_CW_EVENT_MASK;
window_values[0] = 0xffffff;
- window_values[1] = XCB_EVENT_MASK_EXPOSURE;
+ window_values[1] = XCB_EVENT_MASK_EXPOSURE|XCB_EVENT_MASK_KEY_PRESS;
width = INIT_WIDTH;
height = INIT_HEIGHT;
@@ -181,6 +226,11 @@ main (int argc, char **argv)
0, /* mask */
NULL); /* values */
+ xcb_sync_create_fence(c,
+ window,
+ (wait_fence = xcb_generate_id(c)),
+ 0);
+
xcb_present_select_input(c,
(present_event = xcb_generate_id(c)),
window,
@@ -191,10 +241,10 @@ main (int argc, char **argv)
present_extension = xcb_get_extension_data(c, &xcb_present_id);
start_time = millis();
- draw();
+ draw(0);
xcb_map_window(c, window);
- show();
+ show(0);
xcb_present_notify_msc(c, window, 0, 0, 5 * 60, 0);
printf ("mapped\n");
@@ -207,6 +257,21 @@ main (int argc, char **argv)
switch (event->response_type) {
case XCB_EXPOSE:
break;
+ case XCB_KEY_PRESS:
+ switch (++using_fence) {
+ case 1:
+ printf ("wait fence\n");
+ break;
+ case 2:
+ printf ("trigger fence\n");
+ xcb_sync_trigger_fence(c, wait_fence);
+ break;
+ case 3:
+ printf ("no fence\n");
+ xcb_sync_reset_fence(c, wait_fence);
+ using_fence = 0;
+ }
+ break;
case 0:
error = (xcb_generic_error_t *) event;
printf ("error %d major %d minor %d\n",
@@ -229,25 +294,52 @@ main (int argc, char **argv)
}
case XCB_PRESENT_COMPLETE_NOTIFY: {
xcb_present_complete_notify_event_t *ce = (void *) event;
+// printf ("kind %d mode %d\n", ce->kind, ce->mode);
if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) {
int64_t diff = ce->msc - target_msc;
if (diff< 0)
diff = -diff;
- if (diff)
+ if (diff && interval)
printf ("target %lld actual %lld\n", target_msc, ce->msc);
+ ++frame_count;
+ switch (ce->mode) {
+ case XCB_PRESENT_COMPLETE_MODE_COPY:
+ ++copy_count;
+ break;
+ case XCB_PRESENT_COMPLETE_MODE_SKIP:
+ ++skip_count;
+ break;
+ case XCB_PRESENT_COMPLETE_MODE_FLIP:
+ ++flip_count;
+ break;
+ }
msc = ce->msc;
- frame();
+ target_msc = msc + interval;
+ if (interval)
+ frame();
} else {
xcb_present_notify_msc(c, window, 0, 0, 5 * 60, 0);
end_time = millis();
double seconds = (end_time - start_time) / 1000.0;
- printf ("%5d frames in %8.3f seconds. frame rate: %f\n", frame_count, seconds, (double) frame_count / ((double) (end_time - start_time) / 1000.0));
+ printf ("%5d frames in %8.3f seconds. frame rate: %f copy %d skip %d flip %d\n",
+ frame_count, seconds, (double) frame_count / ((double) (end_time - start_time) / 1000.0),
+ copy_count, skip_count, flip_count);
frame_count = 0;
+ copy_count = 0;
+ skip_count = 0;
+ flip_count = 0;
start_time = millis();
}
break;
}
+ case XCB_PRESENT_IDLE_NOTIFY: {
+ xcb_present_idle_notify_event_t *ie = (void *) event;
+ busy[ie->serial] = false;
+ if (!interval)
+ frame();
+ break;
+ }
}
}
break;