Browse Source

Upload files to ''

master
bricks 1 year ago
parent
commit
596e0bc785
2 changed files with 342 additions and 0 deletions
  1. +2
    -0
      makefile
  2. +340
    -0
      test.c

+ 2
- 0
makefile View File

@@ -0,0 +1,2 @@
test: test.c
gcc -o test test.c -lxcb -lxcb-util -lcairo -lrt -lxcb-present -lxcb-randr

+ 340
- 0
test.c View File

@@ -0,0 +1,340 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <cairo/cairo.h>
#include <cairo/cairo-xcb.h>
#include <xcb/xcb.h>
#include <xcb/present.h>
#include <xcb/xfixes.h>
#include <xcb/randr.h>

/************************************************************************************************************/
/* _ ********************************************************************************************************/
/************************************************************************************************************/

static void _draw (void);
static void _init_cairo (void);
static void _init_xcb (void);
static void _reset (void);
static void _run (void);

/************************************************************************************************************/
/************************************************************************************************************/
/************************************************************************************************************/

static uint32_t _opt_frame_divider = 1;
static int _opt_async = 0;

static xcb_connection_t *_x_con = NULL;
static xcb_screen_t *_x_scr = NULL;
static xcb_visualtype_t *_x_vis = NULL;
static xcb_special_event_t *_x_sev = NULL;
static xcb_window_t _x_win = 0;
static xcb_pixmap_t _x_pix = 0;

static cairo_surface_t *_c_srf = NULL;
static cairo_t *_c_ctx = NULL;

static int _speed1 = 60;
static int _speed2 = 5;

static double _pos1 = 0;
static double _inc1 = 1;

static double _pos2 = 0;
static double _inc2 = 1;

static long _t_full = 0;
static long _t_paint = 0;
static long _t_xsync = 0;

static double _delay = 0;
static double _fps = 0;
static long _total = 0;

static uint32_t stamp = 0;

/************************************************************************************************************/
/************************************************************************************************************/
/************************************************************************************************************/

int
main(int argc, char **argv)
{
/* options */

int opt;
while ((opt = getopt(argc, argv, "al:")) != -1) {
switch (opt) {

case 'a':
_opt_async = 1;
break;

case 'l':
_opt_frame_divider = (unsigned int)atoi(optarg);
break;
}
}

/* program */

_init_xcb();
_init_cairo();
_run();
_reset();

return 0;
}

/************************************************************************************************************/
/* _ ********************************************************************************************************/
/************************************************************************************************************/

static void
_draw(void)
{
/* background */

cairo_set_source_rgb(_c_ctx, 0.1, 0.1, 0.1);
cairo_rectangle(_c_ctx, 0, 0, 700, 700);
cairo_fill(_c_ctx);

/* big square */

double adv1 = (double)(_speed1 * _t_full) / 1000000.0;
_pos1 += adv1 * _inc1;
while (_pos1 > 600.0 || _pos1 < 0.0) {
if (_pos1 > 600.0) {
_inc1 = -1;
adv1 = _pos1 - 600;
_pos1 = 600;
} else {
_inc1 = 1;
adv1 = -_pos1;
_pos1 = 0;
}
_pos1 += adv1 * _inc1;
}

cairo_set_source_rgb(_c_ctx, 0.8, 0.8, 0.8);
cairo_rectangle(_c_ctx, _pos1, _pos1, 100, 100);
cairo_fill(_c_ctx);

/* small square */

double adv2 = (double)(_speed2 * _t_full) / 1000000.0;
_pos2 += adv2 * _inc2;
while (_pos2 > 80.0 || _pos2 < 0.0) {
if (_pos2 > 80.0) {
_inc2 = -1;
adv2 = _pos2 - 80;
_pos2 = 80;
} else {
_inc2 = 1;
adv2 = -_pos2;
_pos2 = 0;
}
_pos2 += adv2 * _inc2;
}

cairo_set_source_rgb(_c_ctx, 0.3, 0.3, 0.3);
cairo_rectangle(_c_ctx, _pos1 + 80 - _pos2, _pos1 + _pos2, 20, 20);
cairo_fill(_c_ctx);

/* counters */

char str[128];
cairo_set_source_rgb(_c_ctx, 1.0, 1.0, 1.0);

sprintf(str, "fps : %f", _fps);
cairo_move_to(_c_ctx, 25, 555);
cairo_show_text(_c_ctx, str);

sprintf(str, "frame time (µs) : %li", _t_full);
cairo_move_to(_c_ctx, 25, 585);
cairo_show_text(_c_ctx, str);

sprintf(str, "paint time (µs) : %li", _t_paint);
cairo_move_to(_c_ctx, 25, 615);
cairo_show_text(_c_ctx, str);

sprintf(str, "x sync time (µs) : %li", _t_xsync);
cairo_move_to(_c_ctx, 25, 645);
cairo_show_text(_c_ctx, str);

sprintf(str, "total frames : %li", _total);
cairo_move_to(_c_ctx, 25, 675);
cairo_show_text(_c_ctx, str);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

static void
_init_cairo(void)
{
_c_srf = cairo_xcb_surface_create(_x_con, _x_pix, _x_vis, 700, 700);
_c_ctx = cairo_create(_c_srf);

cairo_set_font_size(_c_ctx, 20);
cairo_select_font_face(_c_ctx, "Terminus", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);

cairo_surface_flush(_c_srf);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

static void
_init_xcb(void)
{
/* connection */

_x_con = xcb_connect(NULL, NULL);
_x_scr = xcb_setup_roots_iterator(xcb_get_setup(_x_con)).data;

xcb_visualtype_iterator_t x_vi;
xcb_depth_iterator_t x_di;

x_di = xcb_screen_allowed_depths_iterator(_x_scr);
for (; x_di.rem; xcb_depth_next(&x_di)) {
x_vi = xcb_depth_visuals_iterator(x_di.data);
for (; x_vi.rem; xcb_visualtype_next(&x_vi)) {
if (_x_scr->root_visual == x_vi.data->visual_id) {
_x_vis = x_vi.data;
break;
}
}
}

/* window */

uint32_t mask_vals[2];
mask_vals[0] = _x_scr->black_pixel;
mask_vals[1] = XCB_EVENT_MASK_EXPOSURE;

_x_win = xcb_generate_id(_x_con);
xcb_create_window(
_x_con,
XCB_COPY_FROM_PARENT,
_x_win,
_x_scr->root,
0, 0,
700, 700,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
_x_scr->root_visual,
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
mask_vals);

xcb_map_window(_x_con, _x_win);
xcb_flush(_x_con);

/* pixmap */

_x_pix = xcb_generate_id(_x_con);
xcb_create_pixmap(_x_con, _x_scr->root_depth, _x_pix, _x_win, 700, 700);

/* present extension */

uint32_t id = xcb_generate_id(_x_con);

xcb_present_select_input(
_x_con,
id,
_x_win,
XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);

/* optional setup a special event queue for the present extension */
/* if not done present completion events can still be recoved from the regular */
/* xcb_wait_for_event() queue */

_x_sev = xcb_register_for_special_xge(_x_con, &xcb_present_id, id, &stamp);

/* get frame delay */

xcb_randr_get_screen_info_cookie_t k = xcb_randr_get_screen_info(_x_con, _x_scr->root);
xcb_randr_get_screen_info_reply_t *r = xcb_randr_get_screen_info_reply(_x_con, k, NULL);

_delay = 1000000.0 / (double)r->rate;

free(r);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

static void
_reset(void)
{
cairo_destroy(_c_ctx);
cairo_surface_destroy(_c_srf);

xcb_free_pixmap(_x_con, _x_pix);
xcb_destroy_window(_x_con, _x_win);
xcb_disconnect(_x_con);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

static void
_run(void)
{
xcb_generic_event_t *ev = NULL;

int n = 0;
long t1 = 0;
long t2 = 0;
long t3 = 0;

struct timespec ts = {0};

while (1) {

_total++;

clock_gettime(CLOCK_MONOTONIC, &ts);
t1 = ts.tv_nsec / 1000 + ts.tv_sec * 1000000;

_draw();

clock_gettime(CLOCK_MONOTONIC, &ts);
t2 = ts.tv_nsec / 1000 + ts.tv_sec * 1000000;

xcb_present_pixmap(
_x_con,
_x_win,
_x_pix,
123456,
XCB_XFIXES_REGION_NONE,
XCB_XFIXES_REGION_NONE,
0, 0,
0,
0,
0,
_opt_async ? XCB_PRESENT_OPTION_ASYNC : XCB_PRESENT_OPTION_NONE,
0, _opt_frame_divider, 0,
0,
NULL);
xcb_flush(_x_con);

clock_gettime(CLOCK_MONOTONIC, &ts);
t3 = ts.tv_nsec / 1000 + ts.tv_sec * 1000000;

_t_paint = t2 - t1;
_t_xsync = t3 - t2;

ev = xcb_wait_for_special_event(_x_con, _x_sev);
if (!ev) {
printf("exiting\n");
return;
}

free(ev);

clock_gettime(CLOCK_MONOTONIC, &ts);
_t_full = ts.tv_nsec / 1000 + ts.tv_sec * 1000000 - t1;
_fps = 1000000.0 / (double)_t_full;
}
}

Loading…
Cancel
Save