1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
/*
* gxr
* Copyright 2018 Collabora Ltd.
* Author: Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
* SPDX-License-Identifier: MIT
*/
#include "cairo_content.h"
#include <glib/gprintf.h>
#include <gxr.h>
#define WIDTH 1000
#define HEIGHT 1000
#define STRIDE (WIDTH * 4)
static struct timespec last_time;
static unsigned frames_without_time_update = 60;
static gchar fps_str [50];
static void
update_fps (struct timespec* now)
{
struct timespec diff;
gxr_time_substract (now, &last_time, &diff);
double diff_s = gxr_time_to_double_secs (&diff);
double diff_ms = diff_s * SEC_IN_MSEC_D;
double fps = SEC_IN_MSEC_D / diff_ms;
g_sprintf (fps_str, "FPS %.2f (%.2fms)", fps, diff_ms);
frames_without_time_update = 0;
}
static cairo_surface_t*
create_cairo_surface (unsigned char *image)
{
struct timespec now;
if (clock_gettime (CLOCK_REALTIME, &now) != 0)
{
g_printerr ("Could not read system clock\n");
return NULL;
}
double now_secs = gxr_time_to_double_secs (&now);
cairo_surface_t *surface =
cairo_image_surface_create_for_data (image,
CAIRO_FORMAT_ARGB32,
WIDTH, HEIGHT,
STRIDE);
cairo_t *cr = cairo_create (surface);
cairo_set_source_rgba (cr, 0, 0, 0, 0);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
draw_rotated_quad (cr, WIDTH, now_secs);
if (frames_without_time_update > 60)
update_fps (&now);
else
frames_without_time_update++;
last_time.tv_sec = now.tv_sec;
last_time.tv_nsec = now.tv_nsec;
draw_fps (cr, WIDTH, fps_str);
cairo_destroy (cr);
return surface;
}
static gboolean
input_callback (gpointer data)
{
GxrOverlay *overlay = (GxrOverlay*) data;
gxr_overlay_poll_event (overlay);
return TRUE;
}
struct RenderContext
{
GulkanClient *uploader;
GxrOverlay *overlay;
GulkanTexture *texture;
};
static gboolean
render_callback (gpointer data)
{
struct RenderContext *context = (struct RenderContext*) data;
/* render frame */
unsigned char image[STRIDE*HEIGHT];
cairo_surface_t* surface = create_cairo_surface (image);
if (surface == NULL) {
g_printerr ("Could not create cairo surface.\n");
return FALSE;
}
GulkanClient *client = GULKAN_CLIENT (context->uploader);
if (context->texture == NULL)
context->texture =
gulkan_texture_new_from_cairo_surface (client, surface,
VK_FORMAT_R8G8B8A8_UNORM,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
else
gulkan_texture_upload_cairo_surface (context->texture, surface,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
cairo_surface_destroy (surface);
gxr_overlay_submit_texture (context->overlay, context->texture);
return TRUE;
}
static void
_press_cb (GxrOverlay *overlay,
GdkEventButton *event,
gpointer data)
{
(void) overlay;
g_print ("press: %d %f %f (%d)\n",
event->button, event->x, event->y, event->time);
GMainLoop *loop = (GMainLoop*) data;
g_main_loop_quit (loop);
}
static void
_destroy_cb (GxrOverlay *overlay,
gpointer data)
{
(void) overlay;
g_print ("destroy\n");
GMainLoop *loop = (GMainLoop*) data;
g_main_loop_quit (loop);
}
static int
test_overlay ()
{
GMainLoop *loop;
loop = g_main_loop_new (NULL, FALSE);
struct RenderContext render_context;
render_context.texture = NULL;
GxrContext *context = gxr_context_new (GXR_APP_OVERLAY, "Overlay Cairo", 1);
if (!context)
return -1;
/* create cairo overlay */
GxrOverlay *overlay = gxr_overlay_new (context, "examples.cairo");
if (overlay == NULL)
{
g_printerr ("Overlay unavailable.\n");
return -1;
}
gxr_overlay_set_mouse_scale (overlay, (float) WIDTH, (float) HEIGHT);
if (!gxr_overlay_show (overlay))
return -1;
g_signal_connect (overlay, "button-press-event", (GCallback) _press_cb, loop);
g_signal_connect (overlay, "destroy", (GCallback) _destroy_cb, loop);
render_context.overlay = overlay;
render_context.uploader = gxr_context_get_gulkan (context);
g_timeout_add (20, input_callback, overlay);
g_timeout_add (11, render_callback, &render_context); // sync to 90 hz
g_main_loop_run (loop);
g_main_loop_unref (loop);
g_object_unref (overlay);
g_object_unref (render_context.texture);
g_object_unref (context);
return 0;
}
int main () {
return test_overlay ();
}
|