summaryrefslogtreecommitdiff
path: root/lib/igt_fb.c
diff options
context:
space:
mode:
authorDamien Lespiau <damien.lespiau@intel.com>2015-03-03 14:11:04 +0000
committerDamien Lespiau <damien.lespiau@intel.com>2015-03-12 14:24:18 +0000
commitff451a6d439f76ddc51cc0a374f086ace4dab680 (patch)
tree7accce113a0e2ab5fa1fd5b5723d728580216590 /lib/igt_fb.c
parenteb93c1b33ef6eebe53646003e951e54a3e68bc5e (diff)
lib: Allow the creation of Ys/Yf tiled FBs
There's no fencing for those tiling layouts, so we create a linear bo for cairo to play with, and when cairo is finished with it, we do a fast copy blit to the fb BO with its final tiling. v2: Move to correct domain after CPU is done with the object (-EINVAL). (Tvrtko Ursulin) Correct arguments passed in to framebuffer creation (segfault). (Tvrtko Ursulin) Pass zero stride to kernel as it expects for Yf&Ys. (Tvrtko Ursulin) v3: Rebase for gem_mmap__cpu changes. (Tvrtko Ursulin) v4: Rebase for addfb2.5. (Tvrtko Ursulin) Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Diffstat (limited to 'lib/igt_fb.c')
-rw-r--r--lib/igt_fb.c109
1 files changed, 106 insertions, 3 deletions
diff --git a/lib/igt_fb.c b/lib/igt_fb.c
index c54907e6..5c92fac8 100644
--- a/lib/igt_fb.c
+++ b/lib/igt_fb.c
@@ -112,7 +112,7 @@ static int create_bo_for_fb(int fd, int width, int height, int bpp,
bo_size = size;
gem_handle = gem_create(fd, bo_size);
- if (tiling != LOCAL_DRM_FORMAT_MOD_NONE)
+ if (tiling == LOCAL_I915_FORMAT_MOD_X_TILED)
ret = __gem_set_tiling(fd, gem_handle, I915_TILING_X, stride);
*stride_ret = stride;
@@ -629,6 +629,104 @@ static cairo_format_t drm_format_to_cairo(uint32_t drm_format)
drm_format, igt_format_str(drm_format));
}
+struct fb_blit_upload {
+ int fd;
+ struct igt_fb *fb;
+ struct {
+ uint32_t handle;
+ unsigned size, stride;
+ uint8_t *map;
+ } linear;
+};
+
+static void destroy_cairo_surface__blit(void *arg)
+{
+ struct fb_blit_upload *blit = arg;
+ struct igt_fb *fb = blit->fb;
+ unsigned int obj_tiling = I915_TILING_NONE;
+
+ munmap(blit->linear.map, blit->linear.size);
+ fb->cairo_surface = NULL;
+
+ gem_set_domain(blit->fd, blit->linear.handle,
+ I915_GEM_DOMAIN_GTT, 0);
+
+ switch (fb->tiling) {
+ case LOCAL_I915_FORMAT_MOD_X_TILED:
+ obj_tiling = I915_TILING_X;
+ break;
+ case LOCAL_I915_FORMAT_MOD_Y_TILED:
+ obj_tiling = I915_TILING_Y;
+ break;
+ case LOCAL_I915_FORMAT_MOD_Yf_TILED:
+ obj_tiling = I915_TILING_Yf;
+ break;
+ }
+
+ igt_blitter_fast_copy__raw(blit->fd,
+ blit->linear.handle,
+ blit->linear.stride,
+ I915_TILING_NONE,
+ 0, 0, /* src_x, src_y */
+ fb->width, fb->height,
+ fb->gem_handle,
+ fb->stride,
+ obj_tiling,
+ 0, 0 /* dst_x, dst_y */);
+
+ gem_sync(blit->fd, blit->linear.handle);
+ gem_close(blit->fd, blit->linear.handle);
+
+ free(blit);
+}
+
+static void create_cairo_surface__blit(int fd, struct igt_fb *fb)
+{
+ struct fb_blit_upload *blit;
+ cairo_format_t cairo_format;
+ int bpp, ret;
+
+ blit = malloc(sizeof(*blit));
+ igt_assert(blit);
+
+ /*
+ * We create a linear BO that we'll map for the CPU to write to (using
+ * cairo). This linear bo will be then blitted to its final
+ * destination, tiling it at the same time.
+ */
+ bpp = igt_drm_format_to_bpp(fb->drm_format);
+ ret = create_bo_for_fb(fd, fb->width, fb->height, bpp,
+ LOCAL_DRM_FORMAT_MOD_NONE, 0,
+ &blit->linear.handle,
+ &blit->linear.size,
+ &blit->linear.stride);
+
+ igt_assert(ret == 0);
+
+ blit->fd = fd;
+ blit->fb = fb;
+ blit->linear.map = gem_mmap__cpu(fd,
+ blit->linear.handle,
+ 0,
+ blit->linear.size,
+ PROT_READ | PROT_WRITE);
+ igt_assert(blit->linear.map);
+
+ gem_set_domain(fd, blit->linear.handle,
+ I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+
+ cairo_format = drm_format_to_cairo(fb->drm_format);
+ fb->cairo_surface =
+ cairo_image_surface_create_for_data(blit->linear.map,
+ cairo_format,
+ fb->width, fb->height,
+ blit->linear.stride);
+
+ cairo_surface_set_user_data(fb->cairo_surface,
+ (cairo_user_data_key_t *)create_cairo_surface__blit,
+ blit, destroy_cairo_surface__blit);
+}
+
static void destroy_cairo_surface__gtt(void *arg)
{
struct igt_fb *fb = arg;
@@ -651,8 +749,13 @@ static void create_cairo_surface__gtt(int fd, struct igt_fb *fb)
static cairo_surface_t *get_cairo_surface(int fd, struct igt_fb *fb)
{
- if (fb->cairo_surface == NULL)
- create_cairo_surface__gtt(fd, fb);
+ if (fb->cairo_surface == NULL) {
+ if (fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED ||
+ fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED)
+ create_cairo_surface__blit(fd, fb);
+ else
+ create_cairo_surface__gtt(fd, fb);
+ }
gem_set_domain(fd, fb->gem_handle,
I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);