~dandrader/mir/cross-compile-parallel

« back to all changes in this revision

Viewing changes to examples/progressbar.c

  • Committer: Daniel van Vugt
  • Date: 2013-08-28 03:41:48 UTC
  • mfrom: (1026 trunk)
  • mto: This revision was merged to the branch mainline in revision 1040.
  • Revision ID: daniel.van.vugt@canonical.com-20130828034148-3rie198rwv3qmnhz
Merge latest lp:mir

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2013 Canonical Ltd.
 
3
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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/>.
 
15
 *
 
16
 * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
 
17
 */
 
18
 
 
19
#include "mir_toolkit/mir_client_library.h"
 
20
#include <stdio.h>
 
21
#include <signal.h>
 
22
#include <stdint.h>
 
23
#include <stdlib.h>
 
24
#define __USE_BSD 1  /* for usleep() */
 
25
#include <unistd.h>  /* sleep() */
 
26
#include <string.h>
 
27
 
 
28
#define BYTES_PER_PIXEL(f) ((f) == mir_pixel_format_bgr_888 ? 3 : 4)
 
29
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
 
30
 
 
31
typedef struct
 
32
{
 
33
    uint8_t r, g, b, a;
 
34
} Color;
 
35
 
 
36
static volatile sig_atomic_t running = 1;
 
37
 
 
38
static void shutdown(int signum)
 
39
{
 
40
    if (running)
 
41
    {
 
42
        running = 0;
 
43
        printf("Signal %d received. Good night.\n", signum);
 
44
    }
 
45
}
 
46
 
 
47
static void blend(uint32_t *dest, uint32_t src, int alpha_shift)
 
48
{
 
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;
 
53
    int i;
 
54
 
 
55
    for (i = 0; i < 4; i++)
 
56
    {
 
57
        d[i] = (uint8_t)
 
58
               (
 
59
                   (
 
60
                       ((uint32_t)d[i] * dest_alpha) +
 
61
                       ((uint32_t)s[i] * src_alpha)
 
62
                   ) >> 8   /* Close enough, and faster than /255 */
 
63
               );
 
64
    }
 
65
 
 
66
    *dest |= (0xff << alpha_shift); /* Restore alpha 1.0 in the destination */
 
67
}
 
68
 
 
69
static void put_pixels(void *where, int count, MirPixelFormat format,
 
70
                       const Color *color)
 
71
{
 
72
    uint32_t pixel = 0;
 
73
    int alpha_shift = -1;
 
74
    int n;
 
75
 
 
76
    /*
 
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
 
80
     */
 
81
    switch (format)
 
82
    {
 
83
    case mir_pixel_format_abgr_8888:
 
84
    case mir_pixel_format_xbgr_8888:
 
85
        alpha_shift = 24;
 
86
        pixel = 
 
87
            (uint32_t)color->a << 24 |
 
88
            (uint32_t)color->b << 16 |
 
89
            (uint32_t)color->g << 8  |
 
90
            (uint32_t)color->r;
 
91
        break;
 
92
    case mir_pixel_format_argb_8888:
 
93
    case mir_pixel_format_xrgb_8888:
 
94
        alpha_shift = 24;
 
95
        pixel = 
 
96
            (uint32_t)color->a << 24 |
 
97
            (uint32_t)color->r << 16 |
 
98
            (uint32_t)color->g << 8  |
 
99
            (uint32_t)color->b;
 
100
        break;
 
101
    case mir_pixel_format_bgr_888:
 
102
        for (n = 0; n < count; n++)
 
103
        {
 
104
            uint8_t *p = (uint8_t*)where + n * 3;
 
105
            p[0] = color->b;
 
106
            p[1] = color->g;
 
107
            p[2] = color->r;
 
108
        }
 
109
        count = 0;
 
110
        break;
 
111
    default:
 
112
        count = 0;
 
113
        break;
 
114
    }
 
115
 
 
116
    if (alpha_shift >= 0 && color->a < 255)
 
117
    {
 
118
        for (n = 0; n < count; n++)
 
119
            blend((uint32_t*)where + n, pixel, alpha_shift);
 
120
    }
 
121
    else
 
122
    {
 
123
        for (n = 0; n < count; n++)
 
124
            ((uint32_t*)where)[n] = pixel;
 
125
    }
 
126
}
 
127
 
 
128
static void clear_region(const MirGraphicsRegion *region, const Color *color)
 
129
{
 
130
    int y;
 
131
    char *row = region->vaddr;
 
132
 
 
133
    for (y = 0; y < region->height; y++)
 
134
    {
 
135
        put_pixels(row, region->width, region->pixel_format, color);
 
136
        row += region->stride;
 
137
    }
 
138
}
 
139
 
 
140
static void draw_box(const MirGraphicsRegion *region, int x, int y, int size,
 
141
                     const Color *color)
 
142
{
 
143
    if (x >= 0 && y >= 0 && x+size < region->width && y+size < region->height)
 
144
    {
 
145
        int j;
 
146
        char *row = region->vaddr +
 
147
                    (y * region->stride) +
 
148
                    (x * BYTES_PER_PIXEL(region->pixel_format));
 
149
    
 
150
        for (j = 0; j < size; j++)
 
151
        {
 
152
            put_pixels(row, size, region->pixel_format, color);
 
153
            row += region->stride;
 
154
        }
 
155
    }
 
156
}
 
157
 
 
158
static void copy_region(const MirGraphicsRegion *dest,
 
159
                        const MirGraphicsRegion *src)
 
160
{
 
161
    int height = MIN(src->height, dest->height);
 
162
    int width = MIN(src->width, dest->width);
 
163
    int y;
 
164
    const char *srcrow = src->vaddr;
 
165
    char *destrow = dest->vaddr;
 
166
    int copy = width * BYTES_PER_PIXEL(dest->pixel_format);
 
167
 
 
168
    for (y = 0; y < height; y++)
 
169
    {
 
170
        memcpy(destrow, srcrow, copy);
 
171
        srcrow += src->stride;
 
172
        destrow += dest->stride;
 
173
    }
 
174
}
 
175
 
 
176
static void redraw(MirSurface *surface, const MirGraphicsRegion *canvas)
 
177
{
 
178
    MirGraphicsRegion backbuffer;
 
179
 
 
180
    mir_surface_get_graphics_region(surface, &backbuffer);
 
181
    copy_region(&backbuffer, canvas);
 
182
    mir_surface_swap_buffers_sync(surface);
 
183
}
 
184
 
 
185
int main(int argc, char *argv[])
 
186
{
 
187
    MirConnection *conn;
 
188
    MirSurfaceParameters parm;
 
189
    MirSurface *surf;
 
190
    MirGraphicsRegion canvas;
 
191
    unsigned int f;
 
192
    unsigned int const pf_size = 32;
 
193
    MirPixelFormat formats[pf_size];
 
194
    unsigned int valid_formats;
 
195
    int sleep_usec = 50000;
 
196
 
 
197
    if (argc > 1)
 
198
    {
 
199
        int rate;
 
200
 
 
201
        if (sscanf(argv[1], "%d", &rate) == 1 && rate > 0)
 
202
        {
 
203
            sleep_usec = 1000000 / rate;
 
204
        }
 
205
        else
 
206
        {
 
207
            fprintf(stderr, "Usage: %s [repeat rate in Hz]\n"
 
208
                            "Default repeat rate is %d\n",
 
209
                    argv[0], 1000000 / sleep_usec);
 
210
 
 
211
            return 1;
 
212
        }
 
213
    }
 
214
 
 
215
    conn = mir_connect_sync(NULL, argv[0]);
 
216
    if (!mir_connection_is_valid(conn))
 
217
    {
 
218
        fprintf(stderr, "Could not connect to a display server.\n");
 
219
        return 1;
 
220
    }
 
221
 
 
222
    parm.buffer_usage = mir_buffer_usage_software;
 
223
    parm.output_id = mir_display_output_id_invalid;
 
224
 
 
225
    mir_connection_get_available_surface_formats(conn, formats, pf_size,
 
226
        &valid_formats);
 
227
 
 
228
    parm.pixel_format = mir_pixel_format_invalid;
 
229
    for (f = 0; f < valid_formats; f++)
 
230
    {
 
231
        if (BYTES_PER_PIXEL(formats[f]) == 4)
 
232
        {
 
233
            parm.pixel_format = formats[f];
 
234
            break;
 
235
        }
 
236
    }
 
237
 
 
238
    if (parm.pixel_format == mir_pixel_format_invalid)
 
239
    {
 
240
        fprintf(stderr, "Could not find a fast 32-bit pixel format\n");
 
241
        mir_connection_release(conn);
 
242
        return 1;
 
243
    }
 
244
 
 
245
    parm.name = "Progress Bars";
 
246
    parm.width = 500;
 
247
    parm.height = 500;
 
248
 
 
249
    surf = mir_connection_create_surface_sync(conn, &parm);
 
250
    if (surf != NULL)
 
251
    {
 
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);
 
257
 
 
258
        if (canvas.vaddr != NULL)
 
259
        {
 
260
            int t = 0;
 
261
 
 
262
            signal(SIGINT, shutdown);
 
263
            signal(SIGTERM, shutdown);
 
264
        
 
265
            while (running)
 
266
            {
 
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;
 
276
 
 
277
                if (t % square == 0)
 
278
                    clear_region(&canvas, &background);
 
279
 
 
280
                t = (t + 1) % square;
 
281
 
 
282
                draw_box(&canvas, x, y, width, &foreground);
 
283
 
 
284
                redraw(surf, &canvas);
 
285
                usleep(sleep_usec);
 
286
            }
 
287
 
 
288
            free(canvas.vaddr);
 
289
        }
 
290
        else
 
291
        {
 
292
            fprintf(stderr, "Failed to malloc canvas\n");
 
293
        }
 
294
 
 
295
        mir_surface_release_sync(surf);
 
296
    }
 
297
    else
 
298
    {
 
299
        fprintf(stderr, "mir_connection_create_surface_sync failed\n");
 
300
    }
 
301
 
 
302
    mir_connection_release(conn);
 
303
 
 
304
    return 0;
 
305
}