static void gpu_blit(struct igt_fb *dst_fb, struct igt_fb *src_fb) { drm_intel_bo *dst_bo; drm_intel_bo *src_bo; int bpp; igt_assert(dst_fb->drm_format == src_fb->drm_format); igt_assert(src_fb->drm_format == DRM_FORMAT_RGB565 || igt_drm_format_to_bpp(src_fb->drm_format) != 16); bpp = igt_drm_format_to_bpp(src_fb->drm_format); dst_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "destination", dst_fb->gem_handle); igt_assert(dst_bo); src_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "source", src_fb->gem_handle); igt_assert(src_bo); intel_blt_copy(batch, src_bo, 0, 0, src_fb->width * bpp / 8, dst_bo, 0, 0, dst_fb->width * bpp / 8, src_fb->width, src_fb->height, bpp); intel_batchbuffer_flush(batch); gem_quiescent_gpu(drm_fd); drm_intel_bo_unreference(src_bo); drm_intel_bo_unreference(dst_bo); }
/** * igt_create_fb_with_bo_size: * @fd: open i915 drm file descriptor * @width: width of the framebuffer in pixel * @height: height of the framebuffer in pixel * @format: drm fourcc pixel format code * @tiling: tiling layout of the framebuffer (as framebuffer modifier) * @fb: pointer to an #igt_fb structure * @bo_size: size of the backing bo (0 for minimum needed size) * * This function allocates a gem buffer object suitable to back a framebuffer * with the requested properties and then wraps it up in a drm framebuffer * object of the requested size. All metadata is stored in @fb. * * The backing storage of the framebuffer is filled with all zeros, i.e. black * for rgb pixel formats. * * Returns: * The kms id of the created framebuffer. */ unsigned int igt_create_fb_with_bo_size(int fd, int width, int height, uint32_t format, uint64_t tiling, struct igt_fb *fb, unsigned bo_size) { uint32_t fb_id; int bpp; memset(fb, 0, sizeof(*fb)); bpp = igt_drm_format_to_bpp(format); igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d], tiling=0x%"PRIx64", size=%d)\n", __func__, width, height, format, bpp, tiling, bo_size); do_or_die(create_bo_for_fb(fd, width, height, bpp, tiling, bo_size, &fb->gem_handle, &fb->size, &fb->stride)); igt_debug("%s(handle=%d, pitch=%d)\n", __func__, fb->gem_handle, fb->stride); if (tiling != LOCAL_DRM_FORMAT_MOD_NONE && tiling != LOCAL_I915_FORMAT_MOD_X_TILED) { do_or_die(__kms_addfb(fd, fb->gem_handle, width, height, fb->stride, format, tiling, LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id)); } else { uint32_t handles[4]; uint32_t pitches[4]; uint32_t offsets[4]; memset(handles, 0, sizeof(handles)); memset(pitches, 0, sizeof(pitches)); memset(offsets, 0, sizeof(offsets)); handles[0] = fb->gem_handle; pitches[0] = fb->stride; do_or_die(drmModeAddFB2(fd, width, height, format, handles, pitches, offsets, &fb_id, 0)); } fb->width = width; fb->height = height; fb->tiling = tiling; fb->drm_format = format; fb->fb_id = fb_id; return fb_id; }
static void create_cairo_surface__blit(int fd, struct igt_fb *fb) { struct fb_blit_upload *blit; cairo_format_t cairo_format; unsigned int obj_tiling = fb_mod_to_obj_tiling(fb->tiling); 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; /* Copy fb content to linear BO */ gem_set_domain(fd, blit->linear.handle, I915_GEM_DOMAIN_GTT, 0); igt_blitter_fast_copy__raw(fd, fb->gem_handle, fb->stride, obj_tiling, 0, 0, /* src_x, src_y */ fb->width, fb->height, blit->linear.handle, blit->linear.stride, I915_TILING_NONE, 0, 0 /* dst_x, dst_y */); gem_sync(fd, blit->linear.handle); gem_set_domain(fd, blit->linear.handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); /* Setup cairo context */ blit->linear.map = gem_mmap__cpu(fd, blit->linear.handle, 0, blit->linear.size, PROT_READ | PROT_WRITE); 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); }