Mir

Merge lp:~vanvugt/mir/16bpp into lp:mir

Proposed by Daniel van Vugt
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 2751
Proposed branch: lp:~vanvugt/mir/16bpp
Merge into: lp:mir
Diff against target: 1191 lines (+556/-130)
24 files modified
examples/eglapp.c (+50/-23)
examples/image_renderer.cpp (+1/-0)
examples/multiwin.c (+73/-21)
include/common/mir_toolkit/common.h (+39/-15)
playground/demo-shell/typo/typo_glcache.cpp (+1/-0)
src/platform/graphics/pixel_format_utils.cpp (+59/-36)
src/platforms/android/server/android_buffer_allocator.cpp (+2/-1)
src/platforms/android/server/android_format_conversion-inl.h (+6/-2)
src/platforms/mesa/server/common/buffer_allocator.cpp (+23/-17)
src/platforms/mesa/server/common/buffer_allocator.h (+0/-1)
src/platforms/mesa/server/common/gbm_buffer.cpp (+42/-0)
src/platforms/mesa/server/common/shm_buffer.cpp (+76/-4)
src/platforms/mesa/server/common/shm_buffer.h (+2/-0)
src/utils/screencast.cpp (+8/-0)
tests/include/mir/test/doubles/mock_gbm.h (+3/-0)
tests/include/mir/test/doubles/mock_gl.h (+1/-0)
tests/mir_test_doubles/mock_gbm.cpp (+9/-0)
tests/mir_test_doubles/mock_gl.cpp (+6/-0)
tests/unit-tests/graphics/android/test_android_buffer_allocator.cpp (+11/-1)
tests/unit-tests/graphics/android/test_pixel_format.cpp (+6/-3)
tests/unit-tests/graphics/mesa/common/test_buffer_allocator.cpp (+2/-0)
tests/unit-tests/graphics/mesa/common/test_shm_buffer.cpp (+110/-6)
tests/unit-tests/graphics/test_graphics_platform.cpp (+2/-0)
tests/unit-tests/graphics/test_pixel_format_utils.cpp (+24/-0)
To merge this branch: bzr merge lp:~vanvugt/mir/16bpp
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Kevin DuBois (community) Approve
Robert Carr (community) Approve
Review via email: mp+264246@code.launchpad.net

Commit message

Pixel formats! Add some and fix some.

  * Added support for common 16-bpp pixel formats (LP: #1469673),
  * Added support for software surface (ShmBuffer) compositing in GL
    of every single pixel format except bgr_888 (which OpenGL does not
    support). (LP: #1424909)
  * Fix texture upload alignment that caused corrupt images and/or
    crashes with non-32-bit formats.
  * Enhance some examples to support the new pixel formats, and also to
    allow the user to force a pixel format.
  * Detect supported pixel formats more accurately during surface
    creation. Sadly not in supported_pixel_formats(), yet.
  * Started on (documented but not enabled) support for big endian.

Future work:

  * Move ShmBuffer out of mesa. It should be usable by any driver and
    even Android should benefit from using its wider pixel format
    support than Android native buffers provide right now.
  * Find out why forcing some unsupported pixel formats on mako makes
    the phone reboot instead of providing nice errors.
  * More big endian support.
  * Enhance (or remove) supported_pixel_formats() to take a paremeter
    like intended usage, so that it may give more accurate answers.
  * Fix compositing of those "X instead of A" formats (LP: #1423462)
  * Automatically relate EGLConfig to desired pixel format in
    examples at least.

Tips:

  * To test a working rgb_565 EGL surface on mako (LP: #1460149),
    try this:
      mir_demo_client_egltriangle -e5 -p7

Fixes: LP: #1469673, LP: #1424909
Related but not yet fully fixed: LP: #1423462, LP: #1460149

Description of the change

The scope of this work has already grown beyond expectations. Please forgive all those TODOs and as yet unresolved future work.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

Looks good to me.

+TEST_F(ShmBufferTest, uploads_xrgb_8888_correctly)

These tests seem like good candidates for parameterization.

gbm_buffer.cpp:
Nice candidate for a static table or something

review: Approve
Revision history for this message
Kevin DuBois (kdub) wrote :

Alright by me, although two questions:

l301, What was wrong with the current definition of pixel formats?

1076 +#if __BYTE_ORDER == __LITTLE_ENDIAN
We haven't quite solved hardware-dependent testing problem... maybe we should move these and that "HardwareSanity*" test suite that I ported last week to its own binary?

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I'm trying to keep the diff size down. So only new code gets lookup tables. Existing switch statements remain.

l301: The old description was incomplete (did not address 16/24-bpp formats) and for 3-byte/24-bpp formats was misleadingly wrong. You can see this in that we've had format "bgr_888" for a long time but it apparently never worked. I've augmented it with new format rgb_888 that actually does work, and verified the right colours appear on screen.

You can't entirely get away from endianess switching if you want pixel formats that are addressable as whole uint32's. Either you use our definition, which allows the client to write pixels endian-independently (but requires endian-specific pixel format types), or you use the other traditional definition like OpenGL that describes the byte order as always literal big endian. But that just moves the #ifdef problem out of the display server and into the client code.

Revision history for this message
Kevin DuBois (kdub) wrote :

Eh, so I see the problem, and think that the newer definitions are an improvement, so +1 to that.
I also guess that endianness is hardware-specific (in one sense), but pretty well guarded by the debian architecture definitions... all systems have an endianness, but not all systems have display hardware, so on second thought, seems like a slightly different problem. Anyways, lgtm

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/eglapp.c'
2--- examples/eglapp.c 2015-07-01 09:18:10 +0000
3+++ examples/eglapp.c 2015-07-13 09:10:30 +0000
4@@ -194,6 +194,7 @@
5 EGLContext eglctx;
6 EGLBoolean ok;
7 EGLint swapinterval = 1;
8+ MirPixelFormat pixel_format = mir_pixel_format_invalid;
9 unsigned int output_id = mir_display_output_id_invalid;
10 char *mir_socket = NULL;
11 char const* cursor_name = mir_default_cursor_name;
12@@ -273,6 +274,23 @@
13 *width = 0;
14 *height = 0;
15 break;
16+ case 'p':
17+ {
18+ arg += 2;
19+ if (!arg[0] && i < argc-1)
20+ {
21+ ++i;
22+ arg = argv[i];
23+ }
24+ if (sscanf(arg, "%u", &pixel_format) != 1 ||
25+ pixel_format == mir_pixel_format_invalid ||
26+ pixel_format >= mir_pixel_formats)
27+ {
28+ printf("Invalid pixel format: %s\n", arg);
29+ help = 1;
30+ }
31+ }
32+ break;
33 case 's':
34 {
35 unsigned int w, h;
36@@ -325,6 +343,7 @@
37 " -h Show this help text\n"
38 " -f Force full screen\n"
39 " -o ID Force placement on output monitor ID\n"
40+ " -p pixelformat Force a pixel format (integer)\n"
41 " -n Don't sync to vblank\n"
42 " -m socket Mir server socket\n"
43 " -s WIDTHxHEIGHT Force surface size\n"
44@@ -339,6 +358,36 @@
45 connection = mir_connect_sync(mir_socket, appname);
46 CHECK(mir_connection_is_valid(connection), "Can't get connection");
47
48+ if (pixel_format == mir_pixel_format_invalid)
49+ {
50+ unsigned int format[mir_pixel_formats];
51+ unsigned int nformats;
52+
53+ mir_connection_get_available_surface_formats(connection,
54+ format, mir_pixel_formats, &nformats);
55+
56+ pixel_format = format[0];
57+ for (unsigned int f = 0; f < nformats; f++)
58+ {
59+ const int opaque = (format[f] == mir_pixel_format_xbgr_8888 ||
60+ format[f] == mir_pixel_format_xrgb_8888 ||
61+ format[f] == mir_pixel_format_rgb_565 ||
62+ format[f] == mir_pixel_format_rgb_888 ||
63+ format[f] == mir_pixel_format_bgr_888);
64+
65+ if ((mir_eglapp_background_opacity == 1.0f && opaque) ||
66+ (mir_eglapp_background_opacity < 1.0f && !opaque))
67+ {
68+ pixel_format = format[f];
69+ break;
70+ }
71+ }
72+
73+ printf("Server supports %d of %d surface pixel formats. "
74+ "Using format: %d\n",
75+ nformats, mir_pixel_formats, pixel_format);
76+ }
77+
78 /* eglapps are interested in the screen size, so
79 use mir_connection_create_display_config */
80 MirDisplayConfiguration* display_config =
81@@ -354,27 +403,6 @@
82
83 const MirDisplayMode *mode = &output->modes[output->current_mode];
84
85- unsigned int format[mir_pixel_formats];
86- unsigned int nformats;
87-
88- mir_connection_get_available_surface_formats(connection,
89- format, mir_pixel_formats, &nformats);
90-
91- MirPixelFormat pixel_format = format[0];
92- for (unsigned int f = 0; f < nformats; f++)
93- {
94- const int opaque = (format[f] == mir_pixel_format_xbgr_8888 ||
95- format[f] == mir_pixel_format_xrgb_8888 ||
96- format[f] == mir_pixel_format_bgr_888);
97-
98- if ((mir_eglapp_background_opacity == 1.0f && opaque) ||
99- (mir_eglapp_background_opacity < 1.0f && !opaque))
100- {
101- pixel_format = format[f];
102- break;
103- }
104- }
105-
106 printf("Current active output is %dx%d %+d%+d\n",
107 mode->horizontal_resolution, mode->vertical_resolution,
108 output->position_x, output->position_y);
109@@ -386,13 +414,12 @@
110
111 mir_display_config_destroy(display_config);
112
113- printf("Server supports %d of %d surface pixel formats. Using format: %d\n",
114- nformats, mir_pixel_formats, pixel_format);
115 EGLint attribs[] =
116 {
117 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
118 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
119 EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
120+ // TODO: Improve this to automatically match pixel_format
121 EGL_RED_SIZE, rgb_bits,
122 EGL_GREEN_SIZE, rgb_bits,
123 EGL_BLUE_SIZE, rgb_bits,
124
125=== modified file 'examples/image_renderer.cpp'
126--- examples/image_renderer.cpp 2015-02-22 07:46:25 +0000
127+++ examples/image_renderer.cpp 2015-07-13 09:10:30 +0000
128@@ -157,6 +157,7 @@
129
130 GLenum format = (bytes_per_pixel == 3) ? GL_RGB : GL_RGBA;
131
132+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
133 glTexImage2D(GL_TEXTURE_2D, 0, format,
134 size.width.as_uint32_t(), size.height.as_uint32_t(), 0,
135 format, GL_UNSIGNED_BYTE, pixel_data);
136
137=== modified file 'examples/multiwin.c'
138--- examples/multiwin.c 2015-06-17 05:20:42 +0000
139+++ examples/multiwin.c 2015-07-13 09:10:30 +0000
140@@ -69,6 +69,7 @@
141 break;
142 case mir_pixel_format_xbgr_8888:
143 pixel =
144+ /* Not filling in the X byte is correct but buggy (LP: #1423462) */
145 (uint32_t)color->b << 16 |
146 (uint32_t)color->g << 8 |
147 (uint32_t)color->r;
148@@ -82,10 +83,21 @@
149 break;
150 case mir_pixel_format_xrgb_8888:
151 pixel =
152+ /* Not filling in the X byte is correct but buggy (LP: #1423462) */
153 (uint32_t)color->r << 16 |
154 (uint32_t)color->g << 8 |
155 (uint32_t)color->b;
156 break;
157+ case mir_pixel_format_rgb_888:
158+ for (n = 0; n < count; n++)
159+ {
160+ uint8_t *p = (uint8_t*)where + n * 3;
161+ p[0] = color->r;
162+ p[1] = color->g;
163+ p[2] = color->b;
164+ }
165+ count = 0;
166+ break;
167 case mir_pixel_format_bgr_888:
168 for (n = 0; n < count; n++)
169 {
170@@ -96,6 +108,38 @@
171 }
172 count = 0;
173 break;
174+ case mir_pixel_format_rgb_565:
175+ for (n = 0; n < count; n++)
176+ {
177+ uint16_t *p = (uint16_t*)where + n;
178+ *p = (uint16_t)(color->r >> 3) << 11 |
179+ (uint16_t)(color->g >> 2) << 5 |
180+ (uint16_t)(color->b >> 3);
181+ }
182+ count = 0;
183+ break;
184+ case mir_pixel_format_rgba_5551:
185+ for (n = 0; n < count; n++)
186+ {
187+ uint16_t *p = (uint16_t*)where + n;
188+ *p = (uint16_t)(color->r >> 3) << 11 |
189+ (uint16_t)(color->g >> 3) << 6 |
190+ (uint16_t)(color->b >> 3) << 1 |
191+ (uint16_t)(color->a ? 1 : 0);
192+ }
193+ count = 0;
194+ break;
195+ case mir_pixel_format_rgba_4444:
196+ for (n = 0; n < count; n++)
197+ {
198+ uint16_t *p = (uint16_t*)where + n;
199+ *p = (uint16_t)(color->r >> 4) << 12 |
200+ (uint16_t)(color->g >> 4) << 8 |
201+ (uint16_t)(color->b >> 4) << 4 |
202+ (uint16_t)(color->a >> 4);
203+ }
204+ count = 0;
205+ break;
206 default:
207 count = 0;
208 break;
209@@ -134,11 +178,12 @@
210 MirConnection *conn;
211 Window win[3];
212 unsigned int f;
213+ MirPixelFormat pixel_format = mir_pixel_format_invalid;
214 int alpha = 0x50;
215
216 int arg;
217 opterr = 0;
218- while ((arg = getopt (argc, argv, "hm:a:")) != -1)
219+ while ((arg = getopt (argc, argv, "hm:a:p:")) != -1)
220 {
221 switch (arg)
222 {
223@@ -146,6 +191,10 @@
224 alpha = atoi(optarg);
225 break;
226
227+ case 'p':
228+ pixel_format = (MirPixelFormat)atoi(optarg);
229+ break;
230+
231 case 'm':
232 socket_file = optarg;
233 break;
234@@ -156,8 +205,9 @@
235 puts(argv[0]);
236 puts("Usage:");
237 puts(" -m <Mir server socket>");
238- puts(" -a Alpha for surfaces");
239- puts(" -h: this help text");
240+ puts(" -a Alpha for surfaces");
241+ puts(" -p <N> Force pixel format N");
242+ puts(" -h This help text");
243 return -1;
244 }
245 }
246@@ -169,26 +219,28 @@
247 return 1;
248 }
249
250- unsigned int const pf_size = 32;
251- MirPixelFormat formats[pf_size];
252- unsigned int valid_formats;
253- mir_connection_get_available_surface_formats(conn, formats, pf_size, &valid_formats);
254-
255- MirPixelFormat pixel_format = mir_pixel_format_invalid;
256- for (f = 0; f < valid_formats; f++)
257- {
258- if (formats[f] == mir_pixel_format_abgr_8888 ||
259- formats[f] == mir_pixel_format_argb_8888)
260- {
261- pixel_format = formats[f];
262- break;
263- }
264- }
265 if (pixel_format == mir_pixel_format_invalid)
266 {
267- fprintf(stderr, "Could not find a fast 32-bit pixel format with "
268- "alpha support. Blending won't work!.\n");
269- pixel_format = formats[0];
270+ MirPixelFormat formats[mir_pixel_formats];
271+ unsigned int valid_formats;
272+ mir_connection_get_available_surface_formats(conn, formats,
273+ mir_pixel_formats, &valid_formats);
274+
275+ for (f = 0; f < valid_formats; f++)
276+ {
277+ if (formats[f] == mir_pixel_format_abgr_8888 ||
278+ formats[f] == mir_pixel_format_argb_8888)
279+ {
280+ pixel_format = formats[f];
281+ break;
282+ }
283+ }
284+ if (pixel_format == mir_pixel_format_invalid)
285+ {
286+ fprintf(stderr, "Could not find a fast 32-bit pixel format with "
287+ "alpha support. Blending won't work!.\n");
288+ pixel_format = formats[0];
289+ }
290 }
291
292 MirSurfaceSpec *spec =
293
294=== modified file 'include/common/mir_toolkit/common.h'
295--- include/common/mir_toolkit/common.h 2015-04-28 07:54:10 +0000
296+++ include/common/mir_toolkit/common.h 2015-07-13 09:10:30 +0000
297@@ -114,27 +114,51 @@
298 } MirPromptSessionState;
299
300 /**
301- * The order of components in a format enum matches the
302- * order of the components as they would be written in an
303- * integer representing a pixel value of that format.
304- *
305- * For example, abgr_8888 corresponds to 0xAABBGGRR, which will
306- * end up as R,G,B,A in memory in a little endian system, and
307- * as A,B,G,R in memory in a big endian system.
308+ * 32-bit pixel formats (8888):
309+ * The order of components in the enum matches the order of the components
310+ * as they would be written in an integer representing a pixel value of that
311+ * format. For example; abgr_8888 should be coded as 0xAABBGGRR, which will
312+ * end up as R,G,B,A in memory on a little endian system, and as A,B,G,R on a
313+ * big endian system.
314+ *
315+ * 24-bit pixel formats (888):
316+ * These are in literal byte order, regardless of CPU architecture it's always
317+ * the same. Writing these 3-byte pixels is typically slower than other formats
318+ * but uses less memory than 32-bit and is endian-independent.
319+ *
320+ * 16-bit pixel formats (565/5551/4444):
321+ * Always interpreted as one 16-bit integer per pixel with components in
322+ * high-to-low bit order following the format name. These are the fastest
323+ * formats, however colour quality is visibly lower.
324 */
325 typedef enum MirPixelFormat
326 {
327- mir_pixel_format_invalid,
328- mir_pixel_format_abgr_8888,
329- mir_pixel_format_xbgr_8888,
330- mir_pixel_format_argb_8888,
331- mir_pixel_format_xrgb_8888,
332- mir_pixel_format_bgr_888,
333- mir_pixel_formats
334+ mir_pixel_format_invalid = 0,
335+ mir_pixel_format_abgr_8888 = 1,
336+ mir_pixel_format_xbgr_8888 = 2,
337+ mir_pixel_format_argb_8888 = 3,
338+ mir_pixel_format_xrgb_8888 = 4,
339+ mir_pixel_format_bgr_888 = 5,
340+ mir_pixel_format_rgb_888 = 6,
341+ mir_pixel_format_rgb_565 = 7,
342+ mir_pixel_format_rgba_5551 = 8,
343+ mir_pixel_format_rgba_4444 = 9,
344+ /*
345+ * TODO: Big endian support would require additional formats in order to
346+ * composite software surfaces using OpenGL (GL_RGBA/GL_BGRA_EXT):
347+ * mir_pixel_format_rgb[ax]_8888
348+ * mir_pixel_format_bgr[ax]_8888
349+ */
350+ mir_pixel_formats /* Note: This is always max format + 1 */
351 } MirPixelFormat;
352
353 /* This could be improved... https://bugs.launchpad.net/mir/+bug/1236254 */
354-#define MIR_BYTES_PER_PIXEL(f) (((f) == mir_pixel_format_bgr_888) ? 3 : 4)
355+#define MIR_BYTES_PER_PIXEL(f) ((f) == mir_pixel_format_bgr_888 ? 3 : \
356+ (f) == mir_pixel_format_rgb_888 ? 3 : \
357+ (f) == mir_pixel_format_rgb_565 ? 2 : \
358+ (f) == mir_pixel_format_rgba_5551 ? 2 : \
359+ (f) == mir_pixel_format_rgba_4444 ? 2 : \
360+ 4)
361
362 /** Direction relative to the "natural" orientation of the display */
363 typedef enum MirOrientation
364
365=== modified file 'playground/demo-shell/typo/typo_glcache.cpp'
366--- playground/demo-shell/typo/typo_glcache.cpp 2015-02-19 09:30:02 +0000
367+++ playground/demo-shell/typo/typo_glcache.cpp 2015-07-13 09:10:30 +0000
368@@ -87,6 +87,7 @@
369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
371 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
372+ glPixelStorei(GL_UNPACK_ALIGNMENT, img.align);
373 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA,
374 img.width, img.height, 0, GL_ALPHA,
375 GL_UNSIGNED_BYTE, img.buf);
376
377=== modified file 'src/platform/graphics/pixel_format_utils.cpp'
378--- src/platform/graphics/pixel_format_utils.cpp 2014-01-08 16:07:36 +0000
379+++ src/platform/graphics/pixel_format_utils.cpp 2015-07-13 09:10:30 +0000
380@@ -1,5 +1,5 @@
381 /*
382- * Copyright © 2014 Canonical Ltd.
383+ * Copyright © 2015 Canonical Ltd.
384 *
385 * This program is free software: you can redistribute it and/or modify it
386 * under the terms of the GNU Lesser General Public License version 3,
387@@ -13,42 +13,65 @@
388 * You should have received a copy of the GNU Lesser General Public License
389 * along with this program. If not, see <http://www.gnu.org/licenses/>.
390 *
391- * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
392+ * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com>
393 */
394
395 #include "mir/graphics/pixel_format_utils.h"
396
397-namespace mg = mir::graphics;
398-
399-bool mg::contains_alpha(MirPixelFormat format)
400-{
401- return (format == mir_pixel_format_abgr_8888 ||
402- format == mir_pixel_format_argb_8888);
403-}
404-
405-bool mg::valid_pixel_format(MirPixelFormat format)
406-{
407- return (format > mir_pixel_format_invalid &&
408- format < mir_pixel_formats);
409-}
410-
411-int mg::red_channel_depth(MirPixelFormat format)
412-{
413- return valid_pixel_format(format) ? 8 : 0;
414-}
415-
416-int mg::blue_channel_depth(MirPixelFormat format)
417-{
418- return valid_pixel_format(format) ? 8 : 0;
419-}
420-
421-int mg::green_channel_depth(MirPixelFormat format)
422-{
423- return valid_pixel_format(format) ? 8 : 0;
424-}
425-
426-int mg::alpha_channel_depth(MirPixelFormat format)
427-{
428- return contains_alpha(format) ? 8 : 0;
429-}
430-
431+namespace {
432+
433+const struct
434+{
435+ MirPixelFormat mir_format;
436+ int red_bits, green_bits, blue_bits, alpha_bits;
437+} detail[mir_pixel_formats] =
438+{
439+ {mir_pixel_format_invalid, 0,0,0,0},
440+ {mir_pixel_format_abgr_8888, 8,8,8,8},
441+ {mir_pixel_format_xbgr_8888, 8,8,8,0},
442+ {mir_pixel_format_argb_8888, 8,8,8,8},
443+ {mir_pixel_format_xrgb_8888, 8,8,8,0},
444+ {mir_pixel_format_bgr_888, 8,8,8,0},
445+ {mir_pixel_format_rgb_888, 8,8,8,0},
446+ {mir_pixel_format_rgb_565, 5,6,5,0},
447+ {mir_pixel_format_rgba_5551, 5,5,5,1},
448+ {mir_pixel_format_rgba_4444, 4,4,4,4},
449+};
450+
451+} // anonymous namespace
452+
453+namespace mir { namespace graphics {
454+
455+bool valid_pixel_format(MirPixelFormat f)
456+{
457+ return f > mir_pixel_format_invalid &&
458+ f < mir_pixel_formats &&
459+ detail[f].mir_format == f;
460+}
461+
462+int red_channel_depth(MirPixelFormat f)
463+{
464+ return valid_pixel_format(f) ? detail[f].red_bits : 0;
465+}
466+
467+int green_channel_depth(MirPixelFormat f)
468+{
469+ return valid_pixel_format(f) ? detail[f].green_bits : 0;
470+}
471+
472+int blue_channel_depth(MirPixelFormat f)
473+{
474+ return valid_pixel_format(f) ? detail[f].blue_bits : 0;
475+}
476+
477+int alpha_channel_depth(MirPixelFormat f)
478+{
479+ return valid_pixel_format(f) ? detail[f].alpha_bits : 0;
480+}
481+
482+bool contains_alpha(MirPixelFormat format)
483+{
484+ return alpha_channel_depth(format);
485+}
486+
487+} } // namespace mir::graphics
488
489=== modified file 'src/platforms/android/server/android_buffer_allocator.cpp'
490--- src/platforms/android/server/android_buffer_allocator.cpp 2015-06-17 05:20:42 +0000
491+++ src/platforms/android/server/android_buffer_allocator.cpp 2015-07-13 09:10:30 +0000
492@@ -107,7 +107,8 @@
493 static std::vector<MirPixelFormat> const pixel_formats{
494 mir_pixel_format_abgr_8888,
495 mir_pixel_format_xbgr_8888,
496- mir_pixel_format_bgr_888
497+ mir_pixel_format_rgb_888,
498+ mir_pixel_format_rgb_565
499 };
500
501 return pixel_formats;
502
503=== modified file 'src/platforms/android/server/android_format_conversion-inl.h'
504--- src/platforms/android/server/android_format_conversion-inl.h 2015-02-22 07:46:25 +0000
505+++ src/platforms/android/server/android_format_conversion-inl.h 2015-07-13 09:10:30 +0000
506@@ -41,8 +41,10 @@
507 return HAL_PIXEL_FORMAT_BGRA_8888;
508 case mir_pixel_format_xrgb_8888:
509 return HAL_PIXEL_FORMAT_BGRA_8888;
510- case mir_pixel_format_bgr_888:
511+ case mir_pixel_format_rgb_888:
512 return HAL_PIXEL_FORMAT_RGB_888;
513+ case mir_pixel_format_rgb_565:
514+ return HAL_PIXEL_FORMAT_RGB_565;
515 default:
516 return 0;
517 }
518@@ -59,7 +61,9 @@
519 case HAL_PIXEL_FORMAT_BGRA_8888:
520 return mir_pixel_format_argb_8888;
521 case HAL_PIXEL_FORMAT_RGB_888:
522- return mir_pixel_format_bgr_888;
523+ return mir_pixel_format_rgb_888;
524+ case HAL_PIXEL_FORMAT_RGB_565:
525+ return mir_pixel_format_rgb_565;
526 default:
527 return mir_pixel_format_invalid;
528 }
529
530=== modified file 'src/platforms/mesa/server/common/buffer_allocator.cpp'
531--- src/platforms/mesa/server/common/buffer_allocator.cpp 2015-06-17 05:20:42 +0000
532+++ src/platforms/mesa/server/common/buffer_allocator.cpp 2015-07-13 09:10:30 +0000
533@@ -138,13 +138,6 @@
534
535 uint32_t const gbm_format = mgm::mir_format_to_gbm_format(buffer_properties.format);
536
537- if (!is_pixel_format_supported(buffer_properties.format) ||
538- gbm_format == mgm::invalid_gbm_format)
539- {
540- BOOST_THROW_EXCEPTION(
541- std::runtime_error("Trying to create GBM buffer with unsupported pixel format"));
542- }
543-
544 /*
545 * Bypass is generally only beneficial to hardware buffers where the
546 * blitting happens on the GPU. For software buffers it is slower to blit
547@@ -164,6 +157,12 @@
548 bo_flags |= GBM_BO_USE_SCANOUT;
549 }
550
551+ if (!gbm_device_is_format_supported(device, gbm_format, bo_flags))
552+ {
553+ BOOST_THROW_EXCEPTION(
554+ std::runtime_error("Trying to create GBM buffer with unsupported pixel format"));
555+ }
556+
557 gbm_bo *bo_raw = gbm_bo_create(
558 device,
559 buffer_properties.size.width.as_uint32_t(),
560@@ -189,7 +188,7 @@
561 std::shared_ptr<mg::Buffer> mgm::BufferAllocator::alloc_software_buffer(
562 BufferProperties const& buffer_properties)
563 {
564- if (!is_pixel_format_supported(buffer_properties.format))
565+ if (!ShmBuffer::supports(buffer_properties.format))
566 {
567 BOOST_THROW_EXCEPTION(
568 std::runtime_error(
569@@ -213,6 +212,22 @@
570
571 std::vector<MirPixelFormat> mgm::BufferAllocator::supported_pixel_formats()
572 {
573+ /*
574+ * supported_pixel_formats() is kind of a kludge. The right answer depends
575+ * on whether you're using hardware or software, and it depends on
576+ * the usage type (e.g. scanout). In the future it's also expected to
577+ * depend on the GPU model in use at runtime.
578+ * To be precise, ShmBuffer now supports OpenGL compositing of all
579+ * but one MirPixelFormat (bgr_888). But GBM only supports [AX]RGB.
580+ * So since we don't yet have an adequate API in place to query what the
581+ * intended usage will be, we need to be conservative and report the
582+ * intersection of ShmBuffer and GBM's pixel format support. That is
583+ * just these two. Be aware however you can create a software surface
584+ * with almost any pixel format and it will also work...
585+ * TODO: Convert this to a loop that just queries the intersection of
586+ * gbm_device_is_format_supported and ShmBuffer::supports(), however not
587+ * yet while the former is buggy. (FIXME: LP: #1473901)
588+ */
589 static std::vector<MirPixelFormat> const pixel_formats{
590 mir_pixel_format_argb_8888,
591 mir_pixel_format_xrgb_8888
592@@ -221,15 +236,6 @@
593 return pixel_formats;
594 }
595
596-bool mgm::BufferAllocator::is_pixel_format_supported(MirPixelFormat format)
597-{
598- auto formats = supported_pixel_formats();
599-
600- auto iter = std::find(formats.begin(), formats.end(), format);
601-
602- return iter != formats.end();
603-}
604-
605 std::unique_ptr<mg::Buffer> mgm::BufferAllocator::reconstruct_from(
606 MirBufferPackage* package,
607 MirPixelFormat format)
608
609=== modified file 'src/platforms/mesa/server/common/buffer_allocator.h'
610--- src/platforms/mesa/server/common/buffer_allocator.h 2015-06-17 05:20:42 +0000
611+++ src/platforms/mesa/server/common/buffer_allocator.h 2015-07-13 09:10:30 +0000
612@@ -51,7 +51,6 @@
613 std::vector<MirPixelFormat> supported_pixel_formats();
614
615 private:
616- bool is_pixel_format_supported(MirPixelFormat format);
617 std::shared_ptr<Buffer> alloc_hardware_buffer(
618 graphics::BufferProperties const& buffer_properties);
619 std::shared_ptr<Buffer> alloc_software_buffer(
620
621=== modified file 'src/platforms/mesa/server/common/gbm_buffer.cpp'
622--- src/platforms/mesa/server/common/gbm_buffer.cpp 2015-06-17 05:20:42 +0000
623+++ src/platforms/mesa/server/common/gbm_buffer.cpp 2015-07-13 09:10:30 +0000
624@@ -46,6 +46,27 @@
625 case GBM_FORMAT_XRGB8888:
626 pf = mir_pixel_format_xrgb_8888;
627 break;
628+ case GBM_FORMAT_ABGR8888:
629+ pf = mir_pixel_format_abgr_8888;
630+ break;
631+ case GBM_FORMAT_XBGR8888:
632+ pf = mir_pixel_format_xbgr_8888;
633+ break;
634+ case GBM_FORMAT_BGR888:
635+ pf = mir_pixel_format_bgr_888;
636+ break;
637+ case GBM_FORMAT_RGB888:
638+ pf = mir_pixel_format_rgb_888;
639+ break;
640+ case GBM_FORMAT_RGB565:
641+ pf = mir_pixel_format_rgb_565;
642+ break;
643+ case GBM_FORMAT_RGBA5551:
644+ pf = mir_pixel_format_rgba_5551;
645+ break;
646+ case GBM_FORMAT_RGBA4444:
647+ pf = mir_pixel_format_rgba_4444;
648+ break;
649 default:
650 pf = mir_pixel_format_invalid;
651 break;
652@@ -66,6 +87,27 @@
653 case mir_pixel_format_xrgb_8888:
654 gbm_pf = GBM_FORMAT_XRGB8888;
655 break;
656+ case mir_pixel_format_abgr_8888:
657+ gbm_pf = GBM_FORMAT_ABGR8888;
658+ break;
659+ case mir_pixel_format_xbgr_8888:
660+ gbm_pf = GBM_FORMAT_XBGR8888;
661+ break;
662+ case mir_pixel_format_bgr_888:
663+ gbm_pf = GBM_FORMAT_BGR888;
664+ break;
665+ case mir_pixel_format_rgb_888:
666+ gbm_pf = GBM_FORMAT_RGB888;
667+ break;
668+ case mir_pixel_format_rgb_565:
669+ gbm_pf = GBM_FORMAT_RGB565;
670+ break;
671+ case mir_pixel_format_rgba_5551:
672+ gbm_pf = GBM_FORMAT_RGBA5551;
673+ break;
674+ case mir_pixel_format_rgba_4444:
675+ gbm_pf = GBM_FORMAT_RGBA4444;
676+ break;
677 default:
678 gbm_pf = mgm::invalid_gbm_format;
679 break;
680
681=== modified file 'src/platforms/mesa/server/common/shm_buffer.cpp'
682--- src/platforms/mesa/server/common/shm_buffer.cpp 2015-06-17 05:20:42 +0000
683+++ src/platforms/mesa/server/common/shm_buffer.cpp 2015-07-13 09:10:30 +0000
684@@ -28,10 +28,69 @@
685 #include <stdexcept>
686
687 #include <string.h>
688+#include <endian.h>
689
690 namespace mgm = mir::graphics::mesa;
691 namespace geom = mir::geometry;
692
693+namespace {
694+
695+bool get_gl_pixel_format(MirPixelFormat mir_format,
696+ GLenum& gl_format, GLenum& gl_type)
697+{
698+#if __BYTE_ORDER == __LITTLE_ENDIAN
699+ GLenum const argb = GL_BGRA_EXT;
700+ GLenum const abgr = GL_RGBA;
701+#elif __BYTE_ORDER == __BIG_ENDIAN
702+ // TODO: Big endian support
703+ GLenum const argb = GL_INVALID_ENUM;
704+ GLenum const abgr = GL_INVALID_ENUM;
705+ GLenum const rgba = GL_RGBA;
706+ GLenum const bgra = GL_BGRA_EXT;
707+#endif
708+
709+ static const struct
710+ {
711+ MirPixelFormat mir_format;
712+ GLenum gl_format, gl_type;
713+ } mapping[mir_pixel_formats] =
714+ {
715+ {mir_pixel_format_invalid, GL_INVALID_ENUM, GL_INVALID_ENUM},
716+ {mir_pixel_format_abgr_8888, abgr, GL_UNSIGNED_BYTE},
717+ {mir_pixel_format_xbgr_8888, abgr, GL_UNSIGNED_BYTE},
718+ {mir_pixel_format_argb_8888, argb, GL_UNSIGNED_BYTE},
719+ {mir_pixel_format_xrgb_8888, argb, GL_UNSIGNED_BYTE},
720+ {mir_pixel_format_bgr_888, GL_INVALID_ENUM, GL_INVALID_ENUM},
721+ {mir_pixel_format_rgb_888, GL_RGB, GL_UNSIGNED_BYTE},
722+ {mir_pixel_format_rgb_565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
723+ {mir_pixel_format_rgba_5551, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
724+ {mir_pixel_format_rgba_4444, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
725+ };
726+
727+ if (mir_format > mir_pixel_format_invalid &&
728+ mir_format < mir_pixel_formats &&
729+ mapping[mir_format].mir_format == mir_format) // just a sanity check
730+ {
731+ gl_format = mapping[mir_format].gl_format;
732+ gl_type = mapping[mir_format].gl_type;
733+ }
734+ else
735+ {
736+ gl_format = GL_INVALID_ENUM;
737+ gl_type = GL_INVALID_ENUM;
738+ }
739+
740+ return gl_format != GL_INVALID_ENUM && gl_type != GL_INVALID_ENUM;
741+}
742+
743+} // anonymous namespace
744+
745+bool mgm::ShmBuffer::supports(MirPixelFormat mir_format)
746+{
747+ GLenum gl_format, gl_type;
748+ return get_gl_pixel_format(mir_format, gl_format, gl_type);
749+}
750+
751 mgm::ShmBuffer::ShmBuffer(
752 std::shared_ptr<ShmFile> const& shm_file,
753 geom::Size const& size,
754@@ -65,10 +124,23 @@
755
756 void mgm::ShmBuffer::gl_bind_to_texture()
757 {
758- glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
759- size_.width.as_int(), size_.height.as_int(),
760- 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
761- pixels);
762+ GLenum format, type;
763+
764+ if (get_gl_pixel_format(pixel_format_, format, type))
765+ {
766+ /*
767+ * All existing Mir logic assumes that strides are whole multiples of
768+ * pixels. And OpenGL defaults to expecting strides are multiples of
769+ * 4 bytes. These assumptions used to be compatible when we only had
770+ * 4-byte pixels but now we support 2/3-byte pixels we need to be more
771+ * careful...
772+ */
773+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
774+
775+ glTexImage2D(GL_TEXTURE_2D, 0, format,
776+ size_.width.as_int(), size_.height.as_int(),
777+ 0, format, type, pixels);
778+ }
779 }
780
781 std::shared_ptr<MirNativeBuffer> mgm::ShmBuffer::native_buffer_handle() const
782
783=== modified file 'src/platforms/mesa/server/common/shm_buffer.h'
784--- src/platforms/mesa/server/common/shm_buffer.h 2015-06-17 05:20:42 +0000
785+++ src/platforms/mesa/server/common/shm_buffer.h 2015-07-13 09:10:30 +0000
786@@ -37,6 +37,8 @@
787 class ShmBuffer : public BufferBasic
788 {
789 public:
790+ static bool supports(MirPixelFormat);
791+
792 ShmBuffer(std::shared_ptr<ShmFile> const& shm_file,
793 geometry::Size const& size,
794 MirPixelFormat const& pixel_format);
795
796=== modified file 'src/utils/screencast.cpp'
797--- src/utils/screencast.cpp 2015-06-17 05:20:42 +0000
798+++ src/utils/screencast.cpp 2015-07-13 09:10:30 +0000
799@@ -190,7 +190,15 @@
800 case mir_pixel_format_xrgb_8888:
801 return "BGRX";
802 case mir_pixel_format_bgr_888:
803+ return "BGR";
804+ case mir_pixel_format_rgb_888:
805 return "RGB";
806+ case mir_pixel_format_rgb_565:
807+ return "RGB565";
808+ case mir_pixel_format_rgba_5551:
809+ return "RGBA5551";
810+ case mir_pixel_format_rgba_4444:
811+ return "RGBA4444";
812 default:
813 throw std::logic_error("Invalid pixel format");
814 }
815
816=== modified file 'tests/include/mir/test/doubles/mock_gbm.h'
817--- tests/include/mir/test/doubles/mock_gbm.h 2015-06-17 05:20:42 +0000
818+++ tests/include/mir/test/doubles/mock_gbm.h 2015-07-13 09:10:30 +0000
819@@ -54,6 +54,9 @@
820 MOCK_METHOD1(gbm_create_device, struct gbm_device*(int fd));
821 MOCK_METHOD1(gbm_device_destroy, void(struct gbm_device *gbm));
822 MOCK_METHOD1(gbm_device_get_fd, int(struct gbm_device *gbm));
823+ MOCK_METHOD3(gbm_device_is_format_supported, int(struct gbm_device *gbm,
824+ uint32_t format,
825+ uint32_t usage));
826
827 MOCK_METHOD5(gbm_surface_create, struct gbm_surface*(struct gbm_device *gbm,
828 uint32_t width, uint32_t height,
829
830=== modified file 'tests/include/mir/test/doubles/mock_gl.h'
831--- tests/include/mir/test/doubles/mock_gl.h 2015-02-22 07:46:25 +0000
832+++ tests/include/mir/test/doubles/mock_gl.h 2015-07-13 09:10:30 +0000
833@@ -85,6 +85,7 @@
834 MOCK_METHOD1(glGetString, const GLubyte*(GLenum));
835 MOCK_METHOD2(glGetUniformLocation, GLint(GLuint, const GLchar *));
836 MOCK_METHOD1(glLinkProgram, void(GLuint));
837+ MOCK_METHOD2(glPixelStorei, void(GLenum, GLint));
838 MOCK_METHOD7(glReadPixels,
839 void(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum,
840 GLvoid*));
841
842=== modified file 'tests/mir_test_doubles/mock_gbm.cpp'
843--- tests/mir_test_doubles/mock_gbm.cpp 2015-06-25 03:00:08 +0000
844+++ tests/mir_test_doubles/mock_gbm.cpp 2015-07-13 09:10:30 +0000
845@@ -45,6 +45,9 @@
846 ON_CALL(*this, gbm_create_device(_))
847 .WillByDefault(Return(fake_gbm.device));
848
849+ ON_CALL(*this, gbm_device_is_format_supported(_,_,_))
850+ .WillByDefault(Return(1));
851+
852 ON_CALL(*this, gbm_surface_create(fake_gbm.device,_,_,_,_))
853 .WillByDefault(Return(fake_gbm.surface));
854
855@@ -89,6 +92,12 @@
856 return global_mock->gbm_device_get_fd(gbm);
857 }
858
859+int gbm_device_is_format_supported(struct gbm_device *gbm,
860+ uint32_t format, uint32_t usage)
861+{
862+ return global_mock->gbm_device_is_format_supported(gbm, format, usage);
863+}
864+
865 struct gbm_surface *gbm_surface_create(struct gbm_device *gbm,
866 uint32_t width, uint32_t height,
867 uint32_t format, uint32_t flags)
868
869=== modified file 'tests/mir_test_doubles/mock_gl.cpp'
870--- tests/mir_test_doubles/mock_gl.cpp 2015-06-25 03:00:08 +0000
871+++ tests/mir_test_doubles/mock_gl.cpp 2015-07-13 09:10:30 +0000
872@@ -442,3 +442,9 @@
873 CHECK_GLOBAL_VOID_MOCK();
874 global_mock_gl->glGenerateMipmap(target);
875 }
876+
877+void glPixelStorei(GLenum pname, GLint param)
878+{
879+ CHECK_GLOBAL_VOID_MOCK();
880+ global_mock_gl->glPixelStorei(pname, param);
881+}
882
883=== modified file 'tests/unit-tests/graphics/android/test_android_buffer_allocator.cpp'
884--- tests/unit-tests/graphics/android/test_android_buffer_allocator.cpp 2015-06-25 03:00:08 +0000
885+++ tests/unit-tests/graphics/android/test_android_buffer_allocator.cpp 2015-07-13 09:10:30 +0000
886@@ -73,9 +73,19 @@
887 supported_pixel_formats.end(),
888 mir_pixel_format_bgr_888);
889
890+ auto rgb_888_count = std::count(supported_pixel_formats.begin(),
891+ supported_pixel_formats.end(),
892+ mir_pixel_format_rgb_888);
893+
894+ auto rgb_565_count = std::count(supported_pixel_formats.begin(),
895+ supported_pixel_formats.end(),
896+ mir_pixel_format_rgb_565);
897+
898 EXPECT_EQ(1, abgr_8888_count);
899 EXPECT_EQ(1, xbgr_8888_count);
900- EXPECT_EQ(1, bgr_888_count);
901+ EXPECT_EQ(0, bgr_888_count);
902+ EXPECT_EQ(1, rgb_888_count);
903+ EXPECT_EQ(1, rgb_565_count);
904 }
905
906 TEST_F(AndroidGraphicBufferAllocatorTest, supported_pixel_formats_have_sane_default_in_first_position)
907
908=== modified file 'tests/unit-tests/graphics/android/test_pixel_format.cpp'
909--- tests/unit-tests/graphics/android/test_pixel_format.cpp 2015-02-22 07:46:25 +0000
910+++ tests/unit-tests/graphics/android/test_pixel_format.cpp 2015-07-13 09:10:30 +0000
911@@ -27,9 +27,11 @@
912 EXPECT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mga::to_android_format(mir_pixel_format_abgr_8888));
913 EXPECT_EQ(HAL_PIXEL_FORMAT_RGBX_8888, mga::to_android_format(mir_pixel_format_xbgr_8888));
914 EXPECT_EQ(HAL_PIXEL_FORMAT_BGRA_8888, mga::to_android_format(mir_pixel_format_argb_8888));
915- //note X to A conversion!
916+ // Note X to A conversion! We resolve this during compositing.
917 EXPECT_EQ(HAL_PIXEL_FORMAT_BGRA_8888, mga::to_android_format(mir_pixel_format_xrgb_8888));
918- EXPECT_EQ(HAL_PIXEL_FORMAT_RGB_888, mga::to_android_format(mir_pixel_format_bgr_888));
919+ EXPECT_EQ(HAL_PIXEL_FORMAT_RGB_888, mga::to_android_format(mir_pixel_format_rgb_888));
920+ EXPECT_EQ(0, mga::to_android_format(mir_pixel_format_bgr_888));
921+ EXPECT_EQ(HAL_PIXEL_FORMAT_RGB_565, mga::to_android_format(mir_pixel_format_rgb_565));
922 }
923
924 TEST(PixelFormatConversion, conversion_to_mir_test)
925@@ -37,5 +39,6 @@
926 EXPECT_EQ(mir_pixel_format_abgr_8888, mga::to_mir_format(HAL_PIXEL_FORMAT_RGBA_8888));
927 EXPECT_EQ(mir_pixel_format_xbgr_8888, mga::to_mir_format(HAL_PIXEL_FORMAT_RGBX_8888));
928 EXPECT_EQ(mir_pixel_format_argb_8888, mga::to_mir_format(HAL_PIXEL_FORMAT_BGRA_8888));
929- EXPECT_EQ(mir_pixel_format_bgr_888, mga::to_mir_format(HAL_PIXEL_FORMAT_RGB_888));
930+ EXPECT_EQ(mir_pixel_format_rgb_888, mga::to_mir_format(HAL_PIXEL_FORMAT_RGB_888));
931+ EXPECT_EQ(mir_pixel_format_rgb_565, mga::to_mir_format(HAL_PIXEL_FORMAT_RGB_565));
932 }
933
934=== modified file 'tests/unit-tests/graphics/mesa/common/test_buffer_allocator.cpp'
935--- tests/unit-tests/graphics/mesa/common/test_buffer_allocator.cpp 2015-06-26 08:00:59 +0000
936+++ tests/unit-tests/graphics/mesa/common/test_buffer_allocator.cpp 2015-07-13 09:10:30 +0000
937@@ -277,6 +277,8 @@
938
939 /* We shouldn't try to create a buffer with an unsupported format */
940 EXPECT_CALL(mock_gbm, gbm_bo_create(_,_,_,_,_)).Times(0);
941+ EXPECT_CALL(mock_gbm, gbm_device_is_format_supported(_,_,_))
942+ .WillOnce(Return(0));
943
944 EXPECT_THROW({
945 allocator->alloc_buffer(mg::BufferProperties{size, mir_pixel_format_abgr_8888, usage});
946
947=== modified file 'tests/unit-tests/graphics/mesa/common/test_shm_buffer.cpp'
948--- tests/unit-tests/graphics/mesa/common/test_shm_buffer.cpp 2015-06-26 08:00:59 +0000
949+++ tests/unit-tests/graphics/mesa/common/test_shm_buffer.cpp 2015-07-13 09:10:30 +0000
950@@ -23,11 +23,14 @@
951
952 #include <gtest/gtest.h>
953 #include <gmock/gmock.h>
954+#include <GLES2/gl2ext.h>
955+#include <endian.h>
956
957 namespace mg = mir::graphics;
958 namespace mgm = mir::graphics::mesa;
959 namespace mtd = mir::test::doubles;
960 namespace geom = mir::geometry;
961+using namespace testing;
962
963 namespace
964 {
965@@ -90,12 +93,113 @@
966 EXPECT_FALSE(shm_buffer.native_buffer_handle()->flags & mir_buffer_flag_can_scanout);
967 }
968
969-TEST_F(ShmBufferTest, uploads_pixels_to_texture)
970+TEST_F(ShmBufferTest, cant_upload_bgr_888)
971 {
972- using namespace testing;
973-
974 EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, _,
975- size.width.as_int(), size.height.as_int(),
976- 0, _, _, stub_shm_file->fake_mapping));
977- shm_buffer.gl_bind_to_texture();
978+ size.width.as_int(), size.height.as_int(),
979+ 0, _, _,
980+ stub_shm_file->fake_mapping))
981+ .Times(0);
982+
983+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_bgr_888);
984+ buf.gl_bind_to_texture();
985+}
986+
987+TEST_F(ShmBufferTest, uploads_rgb_888_correctly)
988+{
989+ EXPECT_CALL(mock_gl, glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
990+ EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
991+ size.width.as_int(), size.height.as_int(),
992+ 0, GL_RGB, GL_UNSIGNED_BYTE,
993+ stub_shm_file->fake_mapping));
994+
995+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_rgb_888);
996+ buf.gl_bind_to_texture();
997+}
998+
999+TEST_F(ShmBufferTest, uploads_rgb_565_correctly)
1000+{
1001+ EXPECT_CALL(mock_gl, glPixelStorei(GL_UNPACK_ALIGNMENT,
1002+ AnyOf(Eq(1),Eq(2))));
1003+ EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
1004+ size.width.as_int(), size.height.as_int(),
1005+ 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
1006+ stub_shm_file->fake_mapping));
1007+
1008+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_rgb_565);
1009+ buf.gl_bind_to_texture();
1010+}
1011+
1012+TEST_F(ShmBufferTest, uploads_rgba_5551_correctly)
1013+{
1014+ EXPECT_CALL(mock_gl, glPixelStorei(GL_UNPACK_ALIGNMENT,
1015+ AnyOf(Eq(1),Eq(2))));
1016+ EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1017+ size.width.as_int(), size.height.as_int(),
1018+ 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
1019+ stub_shm_file->fake_mapping));
1020+
1021+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_rgba_5551);
1022+ buf.gl_bind_to_texture();
1023+}
1024+
1025+TEST_F(ShmBufferTest, uploads_rgba_4444_correctly)
1026+{
1027+ EXPECT_CALL(mock_gl, glPixelStorei(GL_UNPACK_ALIGNMENT,
1028+ AnyOf(Eq(1),Eq(2))));
1029+ EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1030+ size.width.as_int(), size.height.as_int(),
1031+ 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4,
1032+ stub_shm_file->fake_mapping));
1033+
1034+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_rgba_4444);
1035+ buf.gl_bind_to_texture();
1036+}
1037+
1038+TEST_F(ShmBufferTest, uploads_xrgb_8888_correctly)
1039+{
1040+#if __BYTE_ORDER == __LITTLE_ENDIAN
1041+ EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1042+ size.width.as_int(), size.height.as_int(),
1043+ 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1044+ stub_shm_file->fake_mapping));
1045+#endif
1046+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_xrgb_8888);
1047+ buf.gl_bind_to_texture();
1048+}
1049+
1050+TEST_F(ShmBufferTest, uploads_argb_8888_correctly)
1051+{
1052+#if __BYTE_ORDER == __LITTLE_ENDIAN
1053+ EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1054+ size.width.as_int(), size.height.as_int(),
1055+ 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1056+ stub_shm_file->fake_mapping));
1057+#endif
1058+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_argb_8888);
1059+ buf.gl_bind_to_texture();
1060+}
1061+
1062+TEST_F(ShmBufferTest, uploads_xbgr_8888_correctly)
1063+{
1064+#if __BYTE_ORDER == __LITTLE_ENDIAN
1065+ EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1066+ size.width.as_int(), size.height.as_int(),
1067+ 0, GL_RGBA, GL_UNSIGNED_BYTE,
1068+ stub_shm_file->fake_mapping));
1069+#endif
1070+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_xbgr_8888);
1071+ buf.gl_bind_to_texture();
1072+}
1073+
1074+TEST_F(ShmBufferTest, uploads_abgr_8888_correctly)
1075+{
1076+#if __BYTE_ORDER == __LITTLE_ENDIAN
1077+ EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
1078+ size.width.as_int(), size.height.as_int(),
1079+ 0, GL_RGBA, GL_UNSIGNED_BYTE,
1080+ stub_shm_file->fake_mapping));
1081+#endif
1082+ mgm::ShmBuffer buf(stub_shm_file, size, mir_pixel_format_abgr_8888);
1083+ buf.gl_bind_to_texture();
1084 }
1085
1086=== modified file 'tests/unit-tests/graphics/test_graphics_platform.cpp'
1087--- tests/unit-tests/graphics/test_graphics_platform.cpp 2015-06-25 21:34:27 +0000
1088+++ tests/unit-tests/graphics/test_graphics_platform.cpp 2015-07-13 09:10:30 +0000
1089@@ -59,6 +59,8 @@
1090 ON_CALL(mock_gbm, gbm_bo_get_height(_))
1091 .WillByDefault(Return(240));
1092
1093+ // FIXME: This format needs to match Mesa's first supported pixel
1094+ // format or tests will fail. The coupling is presently loose.
1095 ON_CALL(mock_gbm, gbm_bo_get_format(_))
1096 .WillByDefault(Return(GBM_FORMAT_ARGB8888));
1097
1098
1099=== modified file 'tests/unit-tests/graphics/test_pixel_format_utils.cpp'
1100--- tests/unit-tests/graphics/test_pixel_format_utils.cpp 2014-01-08 16:07:36 +0000
1101+++ tests/unit-tests/graphics/test_pixel_format_utils.cpp 2015-07-13 09:10:30 +0000
1102@@ -26,10 +26,14 @@
1103 {
1104 EXPECT_FALSE(contains_alpha(mir_pixel_format_xbgr_8888));
1105 EXPECT_FALSE(contains_alpha(mir_pixel_format_bgr_888));
1106+ EXPECT_FALSE(contains_alpha(mir_pixel_format_rgb_888));
1107 EXPECT_FALSE(contains_alpha(mir_pixel_format_xrgb_8888));
1108 EXPECT_FALSE(contains_alpha(mir_pixel_format_xbgr_8888));
1109+ EXPECT_FALSE(contains_alpha(mir_pixel_format_rgb_565));
1110 EXPECT_TRUE(contains_alpha(mir_pixel_format_argb_8888));
1111 EXPECT_TRUE(contains_alpha(mir_pixel_format_abgr_8888));
1112+ EXPECT_TRUE(contains_alpha(mir_pixel_format_rgba_5551));
1113+ EXPECT_TRUE(contains_alpha(mir_pixel_format_rgba_4444));
1114 EXPECT_FALSE(contains_alpha(mir_pixel_format_invalid));
1115 EXPECT_FALSE(contains_alpha(mir_pixel_formats));
1116 }
1117@@ -38,10 +42,14 @@
1118 {
1119 EXPECT_EQ(8, red_channel_depth(mir_pixel_format_xbgr_8888));
1120 EXPECT_EQ(8, red_channel_depth(mir_pixel_format_bgr_888));
1121+ EXPECT_EQ(8, red_channel_depth(mir_pixel_format_rgb_888));
1122 EXPECT_EQ(8, red_channel_depth(mir_pixel_format_xrgb_8888));
1123 EXPECT_EQ(8, red_channel_depth(mir_pixel_format_xbgr_8888));
1124 EXPECT_EQ(8, red_channel_depth(mir_pixel_format_argb_8888));
1125 EXPECT_EQ(8, red_channel_depth(mir_pixel_format_abgr_8888));
1126+ EXPECT_EQ(5, red_channel_depth(mir_pixel_format_rgb_565));
1127+ EXPECT_EQ(5, red_channel_depth(mir_pixel_format_rgba_5551));
1128+ EXPECT_EQ(4, red_channel_depth(mir_pixel_format_rgba_4444));
1129 EXPECT_EQ(0, red_channel_depth(mir_pixel_format_invalid));
1130 EXPECT_EQ(0, red_channel_depth(mir_pixel_formats));
1131 }
1132@@ -50,10 +58,14 @@
1133 {
1134 EXPECT_EQ(8, blue_channel_depth(mir_pixel_format_xbgr_8888));
1135 EXPECT_EQ(8, blue_channel_depth(mir_pixel_format_bgr_888));
1136+ EXPECT_EQ(8, blue_channel_depth(mir_pixel_format_rgb_888));
1137 EXPECT_EQ(8, blue_channel_depth(mir_pixel_format_xrgb_8888));
1138 EXPECT_EQ(8, blue_channel_depth(mir_pixel_format_xbgr_8888));
1139 EXPECT_EQ(8, blue_channel_depth(mir_pixel_format_argb_8888));
1140 EXPECT_EQ(8, blue_channel_depth(mir_pixel_format_abgr_8888));
1141+ EXPECT_EQ(5, blue_channel_depth(mir_pixel_format_rgb_565));
1142+ EXPECT_EQ(5, blue_channel_depth(mir_pixel_format_rgba_5551));
1143+ EXPECT_EQ(4, blue_channel_depth(mir_pixel_format_rgba_4444));
1144 EXPECT_EQ(0, blue_channel_depth(mir_pixel_format_invalid));
1145 EXPECT_EQ(0, blue_channel_depth(mir_pixel_formats));
1146 }
1147@@ -62,10 +74,14 @@
1148 {
1149 EXPECT_EQ(8, green_channel_depth(mir_pixel_format_xbgr_8888));
1150 EXPECT_EQ(8, green_channel_depth(mir_pixel_format_bgr_888));
1151+ EXPECT_EQ(8, green_channel_depth(mir_pixel_format_rgb_888));
1152 EXPECT_EQ(8, green_channel_depth(mir_pixel_format_xrgb_8888));
1153 EXPECT_EQ(8, green_channel_depth(mir_pixel_format_xbgr_8888));
1154 EXPECT_EQ(8, green_channel_depth(mir_pixel_format_argb_8888));
1155 EXPECT_EQ(8, green_channel_depth(mir_pixel_format_abgr_8888));
1156+ EXPECT_EQ(6, green_channel_depth(mir_pixel_format_rgb_565));
1157+ EXPECT_EQ(5, green_channel_depth(mir_pixel_format_rgba_5551));
1158+ EXPECT_EQ(4, green_channel_depth(mir_pixel_format_rgba_4444));
1159 EXPECT_EQ(0, green_channel_depth(mir_pixel_format_invalid));
1160 EXPECT_EQ(0, green_channel_depth(mir_pixel_formats));
1161 }
1162@@ -75,10 +91,14 @@
1163 {
1164 EXPECT_EQ(0, alpha_channel_depth(mir_pixel_format_xbgr_8888));
1165 EXPECT_EQ(0, alpha_channel_depth(mir_pixel_format_bgr_888));
1166+ EXPECT_EQ(0, alpha_channel_depth(mir_pixel_format_rgb_888));
1167 EXPECT_EQ(0, alpha_channel_depth(mir_pixel_format_xrgb_8888));
1168 EXPECT_EQ(0, alpha_channel_depth(mir_pixel_format_xbgr_8888));
1169 EXPECT_EQ(8, alpha_channel_depth(mir_pixel_format_argb_8888));
1170 EXPECT_EQ(8, alpha_channel_depth(mir_pixel_format_abgr_8888));
1171+ EXPECT_EQ(0, alpha_channel_depth(mir_pixel_format_rgb_565));
1172+ EXPECT_EQ(1, alpha_channel_depth(mir_pixel_format_rgba_5551));
1173+ EXPECT_EQ(4, alpha_channel_depth(mir_pixel_format_rgba_4444));
1174 EXPECT_EQ(0, alpha_channel_depth(mir_pixel_format_invalid));
1175 EXPECT_EQ(0, alpha_channel_depth(mir_pixel_formats));
1176 }
1177@@ -87,10 +107,14 @@
1178 {
1179 EXPECT_TRUE(valid_pixel_format(mir_pixel_format_xbgr_8888));
1180 EXPECT_TRUE(valid_pixel_format(mir_pixel_format_bgr_888));
1181+ EXPECT_TRUE(valid_pixel_format(mir_pixel_format_rgb_888));
1182 EXPECT_TRUE(valid_pixel_format(mir_pixel_format_xrgb_8888));
1183 EXPECT_TRUE(valid_pixel_format(mir_pixel_format_xbgr_8888));
1184 EXPECT_TRUE(valid_pixel_format(mir_pixel_format_argb_8888));
1185 EXPECT_TRUE(valid_pixel_format(mir_pixel_format_abgr_8888));
1186+ EXPECT_TRUE(valid_pixel_format(mir_pixel_format_rgb_565));
1187+ EXPECT_TRUE(valid_pixel_format(mir_pixel_format_rgba_5551));
1188+ EXPECT_TRUE(valid_pixel_format(mir_pixel_format_rgba_4444));
1189 EXPECT_FALSE(valid_pixel_format(mir_pixel_format_invalid));
1190 EXPECT_FALSE(valid_pixel_format(mir_pixel_formats));
1191 }

Subscribers

People subscribed via source and target branches