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>
This commit is contained in:
Damien Lespiau 2015-03-03 14:11:04 +00:00
parent eb93c1b33e
commit ff451a6d43

View File

@ -112,7 +112,7 @@ static int create_bo_for_fb(int fd, int width, int height, int bpp,
bo_size = size; bo_size = size;
gem_handle = gem_create(fd, bo_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); ret = __gem_set_tiling(fd, gem_handle, I915_TILING_X, stride);
*stride_ret = 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)); 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) static void destroy_cairo_surface__gtt(void *arg)
{ {
struct igt_fb *fb = 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) static cairo_surface_t *get_cairo_surface(int fd, struct igt_fb *fb)
{ {
if (fb->cairo_surface == NULL) 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); create_cairo_surface__gtt(fd, fb);
}
gem_set_domain(fd, fb->gem_handle, gem_set_domain(fd, fb->gem_handle,
I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);