2 * Copyright © 2013,2014 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Daniel Vetter <daniel.vetter@ffwll.ch>
25 * Damien Lespiau <damien.lespiau@intel.com>
34 #include "ioctl_wrappers.h"
38 * @short_description: Framebuffer handling and drawing library
39 * @title: i-g-t framebuffer
42 * This library contains helper functions for handling kms framebuffer objects
43 * using #igt_fb structures to track all the metadata. igt_create_fb() creates
44 * a basic framebufffer and igt_remove_fb() cleans everything up again.
46 * It also supports drawing using the cairo library and provides some simplified
47 * helper functions to easily draw test patterns. The main function to create a
48 * cairo drawing context for a framebuffer object is igt_get_cairo_ctx().
50 * Finally it also pulls in the drm fourcc headers and provides some helper
51 * functions to work with these pixel format codes.
54 /* drm fourcc/cairo format maps */
55 #define DF(did, cid, _bpp, _depth) \
56 { DRM_FORMAT_##did, CAIRO_FORMAT_##cid, # did, _bpp, _depth }
57 static struct format_desc_struct {
59 cairo_format_t cairo_id;
64 DF(RGB565, RGB16_565, 16, 16),
65 DF(RGB888, INVALID, 24, 24),
66 DF(XRGB8888, RGB24, 32, 24),
67 DF(XRGB2101010, RGB30, 32, 30),
68 DF(ARGB8888, ARGB32, 32, 32),
72 #define for_each_format(f) \
73 for (f = format_desc; f - format_desc < ARRAY_SIZE(format_desc); f++)
76 /* helpers to create nice-looking framebuffers */
77 static int create_bo_for_fb(int fd, int width, int height, int bpp,
78 bool tiled, uint32_t *gem_handle_ret,
79 unsigned *size_ret, unsigned *stride_ret,
89 /* Round the tiling up to the next power-of-two and the
90 * region up to the next pot fence size so that this works
93 * This can still fail if the framebuffer is too large to
94 * be tiled. But then that failure is expected.
98 for (stride = 512; stride < v; stride *= 2)
102 for (size = 1024*1024; size < v; size *= 2)
105 /* Scan-out has a 64 byte alignment restriction */
106 stride = (width * (bpp / 8) + 63) & ~63;
107 size = stride * height;
112 gem_handle = gem_create(fd, bo_size);
115 ret = __gem_set_tiling(fd, gem_handle, I915_TILING_X, stride);
117 *stride_ret = stride;
119 *gem_handle_ret = gem_handle;
126 * @cr: cairo drawing context
127 * @x: pixel x-coordination of the fill rectangle
128 * @y: pixel y-coordination of the fill rectangle
129 * @w: width of the fill rectangle
130 * @h: height of the fill rectangle
131 * @r: red value to use as fill color
132 * @g: gree value to use as fill color
133 * @b: blue value to use as fill color
135 * This functions draws a solid rectangle with the given color using the drawing
138 void igt_paint_color(cairo_t *cr, int x, int y, int w, int h,
139 double r, double g, double b)
141 cairo_rectangle(cr, x, y, w, h);
142 cairo_set_source_rgb(cr, r, g, b);
147 * igt_paint_color_alpha:
148 * @cr: cairo drawing context
149 * @x: pixel x-coordination of the fill rectangle
150 * @y: pixel y-coordination of the fill rectangle
151 * @w: width of the fill rectangle
152 * @h: height of the fill rectangle
153 * @r: red value to use as fill color
154 * @g: gree value to use as fill color
155 * @b: blue value to use as fill color
156 * @a: alpha value to use as fill color
158 * This functions draws a rectangle with the given color and alpha values using
159 * the drawing context @cr.
161 void igt_paint_color_alpha(cairo_t *cr, int x, int y, int w, int h,
162 double r, double g, double b, double a)
164 cairo_rectangle(cr, x, y, w, h);
165 cairo_set_source_rgba(cr, r, g, b, a);
170 * igt_paint_color_gradient:
171 * @cr: cairo drawing context
172 * @x: pixel x-coordination of the fill rectangle
173 * @y: pixel y-coordination of the fill rectangle
174 * @w: width of the fill rectangle
175 * @h: height of the fill rectangle
176 * @r: red value to use as fill color
177 * @g: gree value to use as fill color
178 * @b: blue value to use as fill color
180 * This functions draws a gradient into the rectangle which fades in from black
181 * to the given values using the drawing context @cr.
184 igt_paint_color_gradient(cairo_t *cr, int x, int y, int w, int h,
187 cairo_pattern_t *pat;
189 pat = cairo_pattern_create_linear(x, y, x + w, y + h);
190 cairo_pattern_add_color_stop_rgba(pat, 1, 0, 0, 0, 1);
191 cairo_pattern_add_color_stop_rgba(pat, 0, r, g, b, 1);
193 cairo_rectangle(cr, x, y, w, h);
194 cairo_set_source(cr, pat);
196 cairo_pattern_destroy(pat);
200 paint_test_patterns(cairo_t *cr, int width, int height)
202 double gr_height, gr_width;
206 gr_width = width * 0.75;
207 gr_height = height * 0.08;
208 x = (width / 2) - (gr_width / 2);
210 igt_paint_color_gradient(cr, x, y, gr_width, gr_height, 1, 0, 0);
213 igt_paint_color_gradient(cr, x, y, gr_width, gr_height, 0, 1, 0);
216 igt_paint_color_gradient(cr, x, y, gr_width, gr_height, 0, 0, 1);
219 igt_paint_color_gradient(cr, x, y, gr_width, gr_height, 1, 1, 1);
223 * igt_cairo_printf_line:
224 * @cr: cairo drawing context
225 * @align: text alignment
226 * @yspacing: additional y-direction feed after this line
227 * @fmt: format string
228 * @...: optional arguments used in the format string
230 * This is a little helper to draw text onto framebuffers. All the initial setup
231 * (like setting the font size and the moving to the starting position) still
232 * needs to be done manually with explicit cairo calls on @cr.
235 * The width of the drawn text.
237 int igt_cairo_printf_line(cairo_t *cr, enum igt_text_align align,
238 double yspacing, const char *fmt, ...)
240 double x, y, xofs, yofs;
241 cairo_text_extents_t extents;
247 ret = vasprintf(&text, fmt, ap);
248 igt_assert(ret >= 0);
251 cairo_text_extents(cr, text, &extents);
254 if (align & align_right)
255 xofs = -extents.width;
256 else if (align & align_hcenter)
257 xofs = -extents.width / 2;
259 if (align & align_top)
260 yofs = extents.height;
261 else if (align & align_vcenter)
262 yofs = extents.height / 2;
264 cairo_get_current_point(cr, &x, &y);
266 cairo_rel_move_to(cr, xofs, yofs);
268 cairo_text_path(cr, text);
269 cairo_set_source_rgb(cr, 0, 0, 0);
270 cairo_stroke_preserve(cr);
271 cairo_set_source_rgb(cr, 1, 1, 1);
274 cairo_move_to(cr, x, y + extents.height + yspacing);
278 return extents.width;
282 paint_marker(cairo_t *cr, int x, int y)
284 enum igt_text_align align;
287 cairo_move_to(cr, x, y - 20);
288 cairo_line_to(cr, x, y + 20);
289 cairo_move_to(cr, x - 20, y);
290 cairo_line_to(cr, x + 20, y);
291 cairo_new_sub_path(cr);
292 cairo_arc(cr, x, y, 10, 0, M_PI * 2);
293 cairo_set_line_width(cr, 4);
294 cairo_set_source_rgb(cr, 0, 0, 0);
295 cairo_stroke_preserve(cr);
296 cairo_set_source_rgb(cr, 1, 1, 1);
297 cairo_set_line_width(cr, 2);
301 align = x ? align_right : align_left;
304 align |= y ? align_bottom : align_top;
306 cairo_move_to(cr, x + xoff, y + yoff);
307 cairo_set_font_size(cr, 18);
308 igt_cairo_printf_line(cr, align, 0, "(%d, %d)", x, y);
312 * igt_paint_test_pattern:
313 * @cr: cairo drawing context
314 * @width: width of the visible area
315 * @height: height of the visible area
317 * This functions draws an entire set of test patterns for the given visible
318 * area using the drawing context @cr. This is useful for manual visual
319 * inspection of displayed framebuffers.
321 * The test patterns include
322 * - corner markers to check for over/underscan and
323 * - a set of color and b/w gradients.
325 void igt_paint_test_pattern(cairo_t *cr, int width, int height)
327 paint_test_patterns(cr, width, height);
329 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
331 /* Paint corner markers */
332 paint_marker(cr, 0, 0);
333 paint_marker(cr, width, 0);
334 paint_marker(cr, 0, height);
335 paint_marker(cr, width, height);
337 igt_assert(!cairo_status(cr));
342 * @cr: cairo drawing context
343 * @filename: filename of the png image to draw
344 * @dst_x: pixel x-coordination of the destination rectangle
345 * @dst_y: pixel y-coordination of the destination rectangle
346 * @dst_width: width of the destination rectangle
347 * @dst_height: height of the destination rectangle
349 * This function can be used to draw a scaled version of the supplied png image.
350 * This is currently only used by the CR-code based testing in the "testdisplay"
353 void igt_paint_image(cairo_t *cr, const char *filename,
354 int dst_x, int dst_y, int dst_width, int dst_height)
356 cairo_surface_t *image;
357 int img_width, img_height;
358 double scale_x, scale_y;
360 image = cairo_image_surface_create_from_png(filename);
361 igt_assert(cairo_surface_status(image) == CAIRO_STATUS_SUCCESS);
363 img_width = cairo_image_surface_get_width(image);
364 img_height = cairo_image_surface_get_height(image);
366 scale_x = (double)dst_width / img_width;
367 scale_y = (double)dst_height / img_height;
371 cairo_translate(cr, dst_x, dst_y);
372 cairo_scale(cr, scale_x, scale_y);
373 cairo_set_source_surface(cr, image, 0, 0);
376 cairo_surface_destroy(image);
382 * igt_create_fb_with_bo_size:
383 * @fd: open i915 drm file descriptor
384 * @width: width of the framebuffer in pixel
385 * @height: height of the framebuffer in pixel
386 * @format: drm fourcc pixel format code
387 * @tiled: X-tiled or linear framebuffer
388 * @fb: pointer to an #igt_fb structure
389 * @bo_size: size of the backing bo (0 for minimum needed size)
391 * This function allocates a gem buffer object suitable to back a framebuffer
392 * with the requested properties and then wraps it up in a drm framebuffer
393 * object of the requested size. All metadata is stored in @fb.
395 * The backing storage of the framebuffer is filled with all zeros, i.e. black
396 * for rgb pixel formats.
399 * The kms id of the created framebuffer on success or a negative error code on
402 unsigned int igt_create_fb_with_bo_size(int fd, int width, int height,
403 uint32_t format, bool tiled,
404 struct igt_fb *fb, unsigned bo_size)
413 memset(fb, 0, sizeof(*fb));
415 bpp = igt_drm_format_to_bpp(format);
416 ret = create_bo_for_fb(fd, width, height, bpp, tiled, &fb->gem_handle,
417 &fb->size, &fb->stride, bo_size);
421 memset(handles, 0, sizeof(handles));
422 handles[0] = fb->gem_handle;
423 memset(pitches, 0, sizeof(pitches));
424 pitches[0] = fb->stride;
425 memset(offsets, 0, sizeof(offsets));
426 if (drmModeAddFB2(fd, width, height, format, handles, pitches,
427 offsets, &fb_id, 0) < 0) {
428 gem_close(fd, fb->gem_handle);
436 fb->drm_format = format;
444 * @fd: open i915 drm file descriptor
445 * @width: width of the framebuffer in pixel
446 * @height: height of the framebuffer in pixel
447 * @format: drm fourcc pixel format code
448 * @tiled: X-tiled or linear framebuffer
449 * @fb: pointer to an #igt_fb structure
451 * This function allocates a gem buffer object suitable to back a framebuffer
452 * with the requested properties and then wraps it up in a drm framebuffer
453 * object. All metadata is stored in @fb.
455 * The backing storage of the framebuffer is filled with all zeros, i.e. black
456 * for rgb pixel formats.
459 * The kms id of the created framebuffer on success or a negative error code on
462 unsigned int igt_create_fb(int fd, int width, int height, uint32_t format,
463 bool tiled, struct igt_fb *fb)
465 return igt_create_fb_with_bo_size(fd, width, height, format, tiled, fb, 0);
469 * igt_create_color_fb:
470 * @fd: open i915 drm file descriptor
471 * @width: width of the framebuffer in pixel
472 * @height: height of the framebuffer in pixel
473 * @format: drm fourcc pixel format code
474 * @tiled: X-tiled or linear framebuffer
475 * @r: red value to use as fill color
476 * @g: gree value to use as fill color
477 * @b: blue value to use as fill color
478 * @fb: pointer to an #igt_fb structure
480 * This function allocates a gem buffer object suitable to back a framebuffer
481 * with the requested properties and then wraps it up in a drm framebuffer
482 * object. All metadata is stored in @fb.
484 * Compared to igt_create_fb() this function also fills the entire framebuffer
485 * with the given color, which is useful for some simple pipe crc based tests.
488 * The kms id of the created framebuffer on success or a negative error code on
491 unsigned int igt_create_color_fb(int fd, int width, int height,
492 uint32_t format, bool tiled,
493 double r, double g, double b,
494 struct igt_fb *fb /* out */)
499 fb_id = igt_create_fb(fd, width, height, format, tiled, fb);
502 cr = igt_get_cairo_ctx(fd, fb);
503 igt_paint_color(cr, 0, 0, width, height, r, g, b);
504 igt_assert(cairo_status(cr) == 0);
510 static cairo_format_t drm_format_to_cairo(uint32_t drm_format)
512 struct format_desc_struct *f;
515 if (f->drm_id == drm_format)
521 static void destroy_cairo_surface__gtt(void *arg)
523 struct igt_fb *fb = arg;
524 munmap(cairo_image_surface_get_data(fb->cairo_surface), fb->size);
527 static void create_cairo_surface__gtt(int fd, struct igt_fb *fb)
530 cairo_image_surface_create_for_data(gem_mmap(fd, fb->gem_handle, fb->size, PROT_READ | PROT_WRITE),
531 drm_format_to_cairo(fb->drm_format),
532 fb->width, fb->height, fb->stride);
534 cairo_surface_set_user_data(fb->cairo_surface,
535 (cairo_user_data_key_t *)create_cairo_surface__gtt,
536 fb, destroy_cairo_surface__gtt);
539 static cairo_surface_t *get_cairo_surface(int fd, struct igt_fb *fb)
541 if (fb->cairo_surface == NULL)
542 create_cairo_surface__gtt(fd, fb);
544 gem_set_domain(fd, fb->gem_handle,
545 I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
547 igt_assert(cairo_surface_status(fb->cairo_surface) == CAIRO_STATUS_SUCCESS);
548 return cairo_surface_reference(fb->cairo_surface);
553 * @fd: open i915 drm file descriptor
554 * @fb: pointer to an #igt_fb structure
556 * This initializes a cairo surface for @fb and then allocates a drawing context
557 * for it. The return cairo drawing context should be released by calling
558 * cairo_destroy(). This also sets a default font for drawing text on
562 * The created cairo drawing context.
564 cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb)
566 cairo_surface_t *surface;
569 surface = get_cairo_surface(fd, fb);
570 cr = cairo_create(surface);
571 cairo_surface_destroy(surface);
572 igt_assert(cairo_status(cr) == CAIRO_STATUS_SUCCESS);
574 cairo_select_font_face(cr, "Helvetica", CAIRO_FONT_SLANT_NORMAL,
575 CAIRO_FONT_WEIGHT_NORMAL);
576 igt_assert(cairo_status(cr) == CAIRO_STATUS_SUCCESS);
582 * igt_write_fb_to_png:
583 * @fd: open i915 drm file descriptor
584 * @fb: pointer to an #igt_fb structure
585 * @filename: target name for the png image
587 * This function stores the contents of the supplied framebuffer into a png
588 * image stored at @filename.
590 void igt_write_fb_to_png(int fd, struct igt_fb *fb, const char *filename)
592 cairo_surface_t *surface;
593 cairo_status_t status;
595 surface = get_cairo_surface(fd, fb);
596 status = cairo_surface_write_to_png(surface, filename);
597 cairo_surface_destroy(surface);
599 igt_assert(status == CAIRO_STATUS_SUCCESS);
604 * @fd: open i915 drm file descriptor
605 * @fb: pointer to an #igt_fb structure
607 * This function releases all resources allocated in igt_create_fb() for @fb.
608 * Note that if this framebuffer is still in use on a primary plane the kernel
609 * will disable the corresponding crtc.
611 void igt_remove_fb(int fd, struct igt_fb *fb)
613 cairo_surface_destroy(fb->cairo_surface);
614 do_or_die(drmModeRmFB(fd, fb->fb_id));
615 gem_close(fd, fb->gem_handle);
619 * igt_bpp_depth_to_drm_format:
620 * @bpp: desired bits per pixel
621 * @depth: desired depth
624 * The rgb drm fourcc pixel format code corresponding to the given @bpp and
625 * @depth values. Fails hard if no match was found.
627 uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth)
629 struct format_desc_struct *f;
632 if (f->bpp == bpp && f->depth == depth)
639 * igt_drm_format_to_bpp:
640 * @drm_format: drm fourcc pixel format code
643 * The bits per pixel for the given drm fourcc pixel format code. Fails hard if
644 * no match was found.
646 uint32_t igt_drm_format_to_bpp(uint32_t drm_format)
648 struct format_desc_struct *f;
651 if (f->drm_id == drm_format)
659 * @drm_format: drm fourcc pixel format code
662 * Human-readable fourcc pixel format code for @drm_format or "invalid" no match
665 const char *igt_format_str(uint32_t drm_format)
667 struct format_desc_struct *f;
670 if (f->drm_id == drm_format)
677 * igt_get_all_formats:
678 * @formats: pointer to pointer to store the allocated formats array
679 * @format_count: pointer to integer to store the size of the allocated array
681 * This functions returns an array of all the drm fourcc codes supported by this
682 * library. The caller must free the allocated array again with free().
684 void igt_get_all_formats(const uint32_t **formats, int *format_count)
686 static uint32_t *drm_formats;
689 struct format_desc_struct *f;
692 drm_formats = calloc(ARRAY_SIZE(format_desc),
693 sizeof(*drm_formats));
694 format = &drm_formats[0];
696 *format++ = f->drm_id;
699 *formats = drm_formats;
700 *format_count = ARRAY_SIZE(format_desc);