2
* Copyright © 2013 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 3 as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
19
#include "mir_toolkit/mir_client_library.h"
24
#define __USE_BSD 1 /* for usleep() */
25
#include <unistd.h> /* sleep() */
28
#define BYTES_PER_PIXEL(f) ((f) == mir_pixel_format_bgr_888 ? 3 : 4)
29
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
36
static volatile sig_atomic_t running = 1;
38
static void shutdown(int signum)
43
printf("Signal %d received. Good night.\n", signum);
47
static void blend(uint32_t *dest, uint32_t src, int alpha_shift)
49
uint8_t *d = (uint8_t*)dest;
50
uint8_t *s = (uint8_t*)&src;
51
uint32_t src_alpha = (uint32_t)(src >> alpha_shift) & 0xff;
52
uint32_t dest_alpha = 0xff - src_alpha;
55
for (i = 0; i < 4; i++)
60
((uint32_t)d[i] * dest_alpha) +
61
((uint32_t)s[i] * src_alpha)
62
) >> 8 /* Close enough, and faster than /255 */
66
*dest |= (0xff << alpha_shift); /* Restore alpha 1.0 in the destination */
69
static void put_pixels(void *where, int count, MirPixelFormat format,
77
* We are blending in software, so can pretend that
78
* mir_pixel_format_abgr_8888 == mir_pixel_format_xbgr_8888
79
* mir_pixel_format_argb_8888 == mir_pixel_format_xrgb_8888
83
case mir_pixel_format_abgr_8888:
84
case mir_pixel_format_xbgr_8888:
87
(uint32_t)color->a << 24 |
88
(uint32_t)color->b << 16 |
89
(uint32_t)color->g << 8 |
92
case mir_pixel_format_argb_8888:
93
case mir_pixel_format_xrgb_8888:
96
(uint32_t)color->a << 24 |
97
(uint32_t)color->r << 16 |
98
(uint32_t)color->g << 8 |
101
case mir_pixel_format_bgr_888:
102
for (n = 0; n < count; n++)
104
uint8_t *p = (uint8_t*)where + n * 3;
116
if (alpha_shift >= 0 && color->a < 255)
118
for (n = 0; n < count; n++)
119
blend((uint32_t*)where + n, pixel, alpha_shift);
123
for (n = 0; n < count; n++)
124
((uint32_t*)where)[n] = pixel;
128
static void clear_region(const MirGraphicsRegion *region, const Color *color)
131
char *row = region->vaddr;
133
for (y = 0; y < region->height; y++)
135
put_pixels(row, region->width, region->pixel_format, color);
136
row += region->stride;
140
static void draw_box(const MirGraphicsRegion *region, int x, int y, int size,
143
if (x >= 0 && y >= 0 && x+size < region->width && y+size < region->height)
146
char *row = region->vaddr +
147
(y * region->stride) +
148
(x * BYTES_PER_PIXEL(region->pixel_format));
150
for (j = 0; j < size; j++)
152
put_pixels(row, size, region->pixel_format, color);
153
row += region->stride;
158
static void copy_region(const MirGraphicsRegion *dest,
159
const MirGraphicsRegion *src)
161
int height = MIN(src->height, dest->height);
162
int width = MIN(src->width, dest->width);
164
const char *srcrow = src->vaddr;
165
char *destrow = dest->vaddr;
166
int copy = width * BYTES_PER_PIXEL(dest->pixel_format);
168
for (y = 0; y < height; y++)
170
memcpy(destrow, srcrow, copy);
171
srcrow += src->stride;
172
destrow += dest->stride;
176
static void redraw(MirSurface *surface, const MirGraphicsRegion *canvas)
178
MirGraphicsRegion backbuffer;
180
mir_surface_get_graphics_region(surface, &backbuffer);
181
copy_region(&backbuffer, canvas);
182
mir_surface_swap_buffers_sync(surface);
185
int main(int argc, char *argv[])
188
MirSurfaceParameters parm;
190
MirGraphicsRegion canvas;
192
unsigned int const pf_size = 32;
193
MirPixelFormat formats[pf_size];
194
unsigned int valid_formats;
195
int sleep_usec = 50000;
201
if (sscanf(argv[1], "%d", &rate) == 1 && rate > 0)
203
sleep_usec = 1000000 / rate;
207
fprintf(stderr, "Usage: %s [repeat rate in Hz]\n"
208
"Default repeat rate is %d\n",
209
argv[0], 1000000 / sleep_usec);
215
conn = mir_connect_sync(NULL, argv[0]);
216
if (!mir_connection_is_valid(conn))
218
fprintf(stderr, "Could not connect to a display server.\n");
222
parm.buffer_usage = mir_buffer_usage_software;
223
parm.output_id = mir_display_output_id_invalid;
225
mir_connection_get_available_surface_formats(conn, formats, pf_size,
228
parm.pixel_format = mir_pixel_format_invalid;
229
for (f = 0; f < valid_formats; f++)
231
if (BYTES_PER_PIXEL(formats[f]) == 4)
233
parm.pixel_format = formats[f];
238
if (parm.pixel_format == mir_pixel_format_invalid)
240
fprintf(stderr, "Could not find a fast 32-bit pixel format\n");
241
mir_connection_release(conn);
245
parm.name = "Progress Bars";
249
surf = mir_connection_create_surface_sync(conn, &parm);
252
canvas.width = parm.width;
253
canvas.height = parm.height;
254
canvas.stride = canvas.width * BYTES_PER_PIXEL(parm.pixel_format);
255
canvas.pixel_format = parm.pixel_format;
256
canvas.vaddr = (char*)malloc(canvas.stride * canvas.height);
258
if (canvas.vaddr != NULL)
262
signal(SIGINT, shutdown);
263
signal(SIGTERM, shutdown);
267
static const Color background = {0, 0, 255, 255};
268
static const Color foreground = {255, 255, 255, 255};
269
static const int width = 8;
270
static const int space = 1;
271
const int grid = width + 2 * space;
272
const int row = parm.width / grid;
273
const int square = row * row;
274
const int x = (t % row) * grid + space;
275
const int y = (t / row) * grid + space;
278
clear_region(&canvas, &background);
280
t = (t + 1) % square;
282
draw_box(&canvas, x, y, width, &foreground);
284
redraw(surf, &canvas);
292
fprintf(stderr, "Failed to malloc canvas\n");
295
mir_surface_release_sync(surf);
299
fprintf(stderr, "mir_connection_create_surface_sync failed\n");
302
mir_connection_release(conn);