Message ID | 1430536299-17547-2-git-send-email-chandra.konduru@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 2 May 2015 at 04:11, Chandra Konduru <chandra.konduru@intel.com> wrote: > From: chandra konduru <chandra.konduru@intel.com> > > This patch adds necessary prep work for nv12 testcase: > - updated fb allocation functions to handle NV12 format > - igt helper function to return png image size > - igt helper function to calculate start of uv in a given NV12 buffer > - igt helper function to map buffer for host access > - populates fb->...[4] parameters for NV12 > - igt helper function to convert RGB data to NV12 > - updated drm_format to bpp to handle NV12 > - updated fast copy blit function to deal NV12 subplanes > - made an update to kms_render testcase due to above changes Could you split these changes into seperate patches? The igt_get_image_size function would be especially useful separately as you have suggest that it should be used to fix kms_plane_scaling image loading issue. > > Signed-off-by: chandra konduru <chandra.konduru@intel.com> > --- > lib/igt_fb.c | 316 +++++++++++++++++++++++++++++++++++++++++++++--- > lib/igt_fb.h | 9 +- > lib/intel_batchbuffer.c | 16 ++- > lib/intel_batchbuffer.h | 3 +- > lib/intel_reg.h | 1 + > lib/ioctl_wrappers.c | 10 +- > lib/ioctl_wrappers.h | 2 +- > tests/kms_render.c | 4 +- > 8 files changed, 334 insertions(+), 27 deletions(-) > > diff --git a/lib/igt_fb.c b/lib/igt_fb.c > index cc4b8ee..dedee9e 100644 > --- a/lib/igt_fb.c > +++ b/lib/igt_fb.c > @@ -74,7 +74,7 @@ static struct format_desc_struct { > > > /* helpers to create nice-looking framebuffers */ > -static int create_bo_for_fb(int fd, int width, int height, int bpp, > +static int create_bo_for_fb(int fd, int width, int height, int bpp, int bpp2, > uint64_t tiling, unsigned bo_size, > uint32_t *gem_handle_ret, > unsigned *size_ret, > @@ -99,13 +99,17 @@ static int create_bo_for_fb(int fd, int width, int height, int bpp, > for (stride = 512; stride < v; stride *= 2) > ; > > - v = stride * height; > + /* planar formats height is 1.5x */ > + v = stride * (bpp2 ? (height * 3) / 2 : height); > + > for (size = 1024*1024; size < v; size *= 2) > ; > } else { > /* Scan-out has a 64 byte alignment restriction */ > stride = (width * (bpp / 8) + 63) & ~63; > - size = stride * height; > + > + /* planar formats height is 1.5x */ > + size = stride * (bpp2 ? (height * 3) / 2 : height); > } > > if (bo_size == 0) > @@ -393,6 +397,75 @@ void igt_paint_image(cairo_t *cr, const char *filename, > } > > /** > + * igt_get_image_size: > + * @filename: filename of the png image > + * @width: width of the image > + * @height: height of the image > + * > + * This function returns @width and @height of the png image in @filename, > + * which is loaded from the package data directory. > + */ > +void > +igt_get_image_size(const char *filename, int *width, int *height) > +{ > + cairo_surface_t *image; > + FILE* f; > + > + f = igt_fopen_data(filename); > + > + image = cairo_image_surface_create_from_png_stream(&stdio_read_func, f); > + igt_assert(cairo_surface_status(image) == CAIRO_STATUS_SUCCESS); > + > + *width = cairo_image_surface_get_width(image); > + *height = cairo_image_surface_get_height(image); > + > + cairo_surface_destroy(image); > + > + fclose(f); > +} > + > + > +/** > + * igt_fb_calc_uv: > + * @fb: pointer to an #igt_fb structure > + * > + * This function calculates UV offset in bytes and UV starting line number > + * for requested NV12 @fb. > + */ > +void > +igt_fb_calc_uv(struct igt_fb *fb) > +{ > + if (fb->drm_format != DRM_FORMAT_NV12) > + return; > + > + switch (fb->tiling) { > + case LOCAL_DRM_FORMAT_MOD_NONE: > + fb->uv_y_start = fb->height; > + break; > + case LOCAL_I915_FORMAT_MOD_X_TILED: > + fb->uv_y_start = fb->height; > + break; > + case LOCAL_I915_FORMAT_MOD_Y_TILED: > + fb->uv_y_start = fb->height; > + break; > + case LOCAL_I915_FORMAT_MOD_Yf_TILED: > + /* tile-Yf requires uv to start on a new tile row */ > + if (fb->height % 64) > + fb->uv_y_start = (fb->height + 63) & ~63; > + else > + fb->uv_y_start = fb->height; > + break; > + default: > + igt_assert(0); > + } > + > + fb->uv_offset = fb->uv_y_start * fb->stride; > + > + /* assert that fb has enough lines to hold y and uv sub-planes */ > + igt_assert(fb->size / fb->stride >= fb->uv_y_start + fb->height / 2); > +} > + > +/** > * igt_create_fb_with_bo_size: > * @fd: open i915 drm file descriptor > * @width: width of the framebuffer in pixel > @@ -418,24 +491,32 @@ igt_create_fb_with_bo_size(int fd, int width, int height, > struct igt_fb *fb, unsigned bo_size) > { > uint32_t fb_id; > - int bpp; > + int bpp, bpp2; > > memset(fb, 0, sizeof(*fb)); > > - bpp = igt_drm_format_to_bpp(format); > + bpp = igt_drm_format_to_bpp(format, 0); > + bpp2 = igt_drm_format_to_bpp(format, 1); > > - 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, > + igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d, %d], tiling=0x%"PRIx64", size=%d\n", > + __func__, width, height, format, bpp, bpp2, tiling, bo_size); > + do_or_die(create_bo_for_fb(fd, width, height, bpp, bpp2, tiling, bo_size, > &fb->gem_handle, &fb->size, &fb->stride)); > > igt_debug("%s(handle=%d, pitch=%d)\n", > __func__, fb->gem_handle, fb->stride); > > + fb->width = width; > + fb->height = height; > + fb->tiling = tiling; > + fb->drm_format = format; > + > + igt_fb_calc_uv(fb); > + > 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, > + fb->stride, format, tiling, fb->uv_offset, > LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id)); > } else { > uint32_t handles[4]; > @@ -449,21 +530,213 @@ igt_create_fb_with_bo_size(int fd, int width, int height, > handles[0] = fb->gem_handle; > pitches[0] = fb->stride; > > + if (format == DRM_FORMAT_NV12) { > + handles[1] = fb->gem_handle; > + pitches[1] = fb->stride; > + offsets[1] = fb->uv_offset; > + } > + > 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; > } > > /** > + * igt_fb_gem_mmap: > + * @fd: open i915 drm file descriptor > + * @fb: pointer to an #igt_fb structure > + * > + * This function memory maps gem buffer for cpu access and saves mmap pointer > + * in @fb. > + */ > +void > +igt_fb_gem_mmap(int fd, struct igt_fb *fb) > +{ > + if (!fb->mmap_gtt) > + fb->mmap_gtt = gem_mmap__gtt(fd, fb->gem_handle, fb->size, > + PROT_READ | PROT_WRITE); > + igt_assert(fb->mmap_gtt); > +} > + > +/** > + * igt_fb_csc_xrgb_to_nv12: > + * @fd: open i915 drm file descriptor > + * @width: width of the framebuffer to be converted > + * @height: height of the framebuffer to be converted > + * @dst: pointer to an #igt_fb structure holding destination framebuffer > + * @src: pointer to an #igt_fb structure holding source framebuffer > + * > + * This function converts source framebuffer into destination framebuffer > + * format. It also mmaps the underlying gem buffer if it isn't mmaped > + * before. > + * > + * For now: > + * - it expects both src and dst fbs are same size and tiling > + */ > +void > +igt_fb_csc_xrgb_to_nv12(int fd, struct igt_fb *dst_fb, struct igt_fb *src_fb) > +{ > + unsigned char *nv12; > + unsigned char *xrgb; > + unsigned char y, v, u; > + float yf, vf, uf; > + unsigned char r, g, b; > + int i, j; > + int xrgb_pos; > + int y_pos; > + int uv_pos; > + int uv_base; > + unsigned int obj_tiling; > + struct igt_fb *temp_src_fb, *temp_dst_fb; > + struct igt_fb fb1, fb2; > + int temp_src_id, temp_dst_id; > + > + igt_assert(dst_fb); > + igt_assert(src_fb); > + igt_assert(dst_fb->width == src_fb->width); > + igt_assert(dst_fb->height == src_fb->height); > + igt_assert(src_fb->tiling == dst_fb->tiling); > + > + igt_assert(src_fb->drm_format == DRM_FORMAT_XRGB8888); > + igt_assert(dst_fb->drm_format == DRM_FORMAT_NV12); > + > + /* > + * Steps: Not the best approach but gets job done for igt > + * (1) create linear temp_src, temp_dst > + * (2) fast blit src --> temp src > + * (3) gem map temp_src, temp_dst > + * (4) host conversion & copy from temp src --> temp dst > + * (5) fast blit temp dst --> dst > + * (6) free temp fbs > + * > + * For Linear/X: > + * perform 3 & 4 only > + * For Y/Yf: > + * perform all steps > + */ > + > + if (src_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || > + src_fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) { > + > + temp_src_fb = &fb1; > + temp_dst_fb = &fb2; > + > + /* (1) create linear temp_src, temp_dst */ > + temp_src_id = igt_create_fb(fd, > + src_fb->width, src_fb->height, > + src_fb->drm_format, > + LOCAL_DRM_FORMAT_MOD_NONE, > + temp_src_fb); > + igt_assert(temp_src_id); > + > + temp_dst_id = igt_create_fb(fd, > + dst_fb->width, dst_fb->height, > + dst_fb->drm_format, > + LOCAL_DRM_FORMAT_MOD_NONE, > + temp_dst_fb); > + igt_assert(temp_dst_id); > + > + if (src_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED) > + obj_tiling = I915_TILING_Y; > + else > + obj_tiling = I915_TILING_Yf; > + > + /* (2) fast blit src --> temp src */ > + igt_blitter_fast_copy__raw(fd, > + src_fb->gem_handle, > + src_fb->stride, > + obj_tiling, > + 0, 0, > + temp_src_fb->width, temp_src_fb->height, > + igt_drm_format_to_bpp(temp_src_fb->drm_format, 0), > + temp_src_fb->gem_handle, > + temp_src_fb->stride, > + I915_TILING_NONE, > + 0, 0); > + } else { > + temp_src_fb = src_fb; > + temp_dst_fb = dst_fb; > + } > + > + /* (3) gem map temp_src, temp_dst */ > + igt_fb_gem_mmap(fd, temp_src_fb); > + igt_fb_gem_mmap(fd, temp_dst_fb); > + > + /* (4) host conversion & copy from temp src --> temp dst */ > + xrgb = (unsigned char *) temp_src_fb->mmap_gtt; > + nv12 = (unsigned char *) temp_dst_fb->mmap_gtt; > + uv_base = temp_dst_fb->stride * temp_dst_fb->height; > + > + for (i = 0; i < temp_src_fb->height; i++) { > + xrgb_pos = i * temp_src_fb->stride; > + y_pos = i * temp_dst_fb->stride; > + uv_pos = temp_dst_fb->stride * i / 2; > + for (j = 0; j < temp_src_fb->width; j++) { > + b = xrgb[xrgb_pos++]; > + g = xrgb[xrgb_pos++]; > + r = xrgb[xrgb_pos++]; > + xrgb_pos++; > + > + /* use floats for intermediate calcs, to get better results */ > + yf = (0.257 * r) + (0.504 * g) + (0.098 * b) + 16; > + uf = -(0.148 * r) - (0.291 * g) + (0.439 * b) + 128; > + vf = (0.439 * r) - (0.368 * g) - (0.071 * b) + 128; > + > + y = (unsigned char) yf; > + u = (unsigned char) uf; > + v = (unsigned char) vf; > + > + nv12[y_pos++] = y; > + > + if (!(j % 2) && !(i % 2)) { > + nv12[uv_base + uv_pos++] = u; > + nv12[uv_base + uv_pos++] = v; > + } > + } > + } > + > + /* (5) fast blit temp dst --> dst */ > + if (dst_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || > + dst_fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) { > + > + /* blit y-plane */ > + igt_blitter_fast_copy__raw(fd, > + temp_dst_fb->gem_handle, > + temp_dst_fb->stride, > + I915_TILING_NONE, > + 0, 0, > + dst_fb->width, dst_fb->height, > + igt_drm_format_to_bpp(dst_fb->drm_format, 0), > + dst_fb->gem_handle, > + dst_fb->stride, > + obj_tiling, > + 0, 0); > + > + /* blit uv-plane */ > + igt_blitter_fast_copy__raw(fd, > + temp_dst_fb->gem_handle, > + temp_dst_fb->stride, > + I915_TILING_NONE, > + 0, temp_dst_fb->uv_y_start, > + dst_fb->width, dst_fb->height, > + igt_drm_format_to_bpp(dst_fb->drm_format, 1), > + dst_fb->gem_handle, > + dst_fb->stride, > + obj_tiling, > + 0, dst_fb->uv_y_start); > + > + /* (6) free temp fbs */ > + igt_remove_fb(fd, temp_src_fb); > + igt_remove_fb(fd, temp_dst_fb); > + } > +} > + > +/** > * igt_create_fb: > * @fd: open i915 drm file descriptor > * @width: width of the framebuffer in pixel > @@ -686,6 +959,7 @@ static void destroy_cairo_surface__blit(void *arg) > I915_TILING_NONE, > 0, 0, /* src_x, src_y */ > fb->width, fb->height, > + 0, > fb->gem_handle, > fb->stride, > obj_tiling, > @@ -712,8 +986,8 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb) > * 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, > + bpp = igt_drm_format_to_bpp(fb->drm_format, 0); > + ret = create_bo_for_fb(fd, fb->width, fb->height, bpp, 0, > LOCAL_DRM_FORMAT_MOD_NONE, 0, > &blit->linear.handle, > &blit->linear.size, > @@ -734,6 +1008,7 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb) > obj_tiling, > 0, 0, /* src_x, src_y */ > fb->width, fb->height, > + bpp, > blit->linear.handle, > blit->linear.stride, > I915_TILING_NONE, > @@ -893,15 +1168,24 @@ uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth) > /** > * igt_drm_format_to_bpp: > * @drm_format: drm fourcc pixel format code > + * @plane: plane id > * > * Returns: > * The bits per pixel for the given drm fourcc pixel format code. Fails hard if > * no match was found. > */ > -uint32_t igt_drm_format_to_bpp(uint32_t drm_format) > +uint32_t igt_drm_format_to_bpp(uint32_t drm_format, int plane) > { > struct format_desc_struct *f; > > + if (drm_format == DRM_FORMAT_NV12 && plane == 0) > + return 8; > + if (drm_format == DRM_FORMAT_NV12 && plane == 1) > + return 16; > + > + if (plane) > + return 0; > + > for_each_format(f) > if (f->drm_id == drm_format) > return f->bpp; > diff --git a/lib/igt_fb.h b/lib/igt_fb.h > index a07acd2..9e227e8 100644 > --- a/lib/igt_fb.h > +++ b/lib/igt_fb.h > @@ -54,10 +54,13 @@ struct igt_fb { > uint64_t tiling; > unsigned size; > cairo_surface_t *cairo_surface; > + void *mmap_gtt; > uint32_t src_x; > uint32_t src_y; > uint32_t src_w; > uint32_t src_h; > + uint32_t uv_y_start; > + uint32_t uv_offset; > }; > > enum igt_text_align { > @@ -82,6 +85,9 @@ unsigned int igt_create_color_fb(int fd, int width, int height, > unsigned int igt_create_stereo_fb(int drm_fd, drmModeModeInfo *mode, > uint32_t format, uint64_t tiling); > void igt_remove_fb(int fd, struct igt_fb *fb); > +void igt_fb_gem_mmap(int fd, struct igt_fb *fb); > +void igt_fb_csc_xrgb_to_nv12(int fd, struct igt_fb *dst, struct igt_fb *src); > +void igt_fb_calc_uv(struct igt_fb *fb); > > /* cairo-based painting */ > cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb); > @@ -98,10 +104,11 @@ void igt_write_fb_to_png(int fd, struct igt_fb *fb, const char *filename); > int igt_cairo_printf_line(cairo_t *cr, enum igt_text_align align, > double yspacing, const char *fmt, ...) > __attribute__((format (printf, 4, 5))); > +void igt_get_image_size(const char *filename, int *width, int *height); > > /* helpers to handle drm fourcc codes */ > uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth); > -uint32_t igt_drm_format_to_bpp(uint32_t drm_format); > +uint32_t igt_drm_format_to_bpp(uint32_t drm_format, int plane); > const char *igt_format_str(uint32_t drm_format); > void igt_get_all_formats(const uint32_t **formats, int *format_count); > > diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c > index 8b68e52..a2cd6ab 100644 > --- a/lib/intel_batchbuffer.c > +++ b/lib/intel_batchbuffer.c > @@ -518,7 +518,7 @@ static uint32_t fast_copy_dword0(unsigned int src_tiling, > } > > static uint32_t fast_copy_dword1(unsigned int src_tiling, > - unsigned int dst_tiling) > + unsigned int dst_tiling, uint32_t color_depth) > { > uint32_t dword1 = 0; > > @@ -527,7 +527,10 @@ static uint32_t fast_copy_dword1(unsigned int src_tiling, > if (dst_tiling == I915_TILING_Yf) > dword1 |= XY_FAST_COPY_DST_TILING_Yf; > > - dword1 |= XY_FAST_COPY_COLOR_DEPTH_32; > + if (color_depth == 8) > + dword1 |= XY_FAST_COPY_COLOR_DEPTH_8; > + else > + dword1 |= XY_FAST_COPY_COLOR_DEPTH_32; > > return dword1; > } > @@ -585,6 +588,7 @@ static void exec_blit(int fd, > * @src_y: Y coordinate of the source region to copy > * @width: Width of the region to copy > * @height: Height of the region to copy > + * @color_depth: Color depth of the buffer > * @dst_handle: GEM handle of the source buffer > * @dst_stride: Stride (in bytes) of the destination buffer > * @dst_tiling: Tiling mode of the destination buffer > @@ -602,6 +606,7 @@ void igt_blitter_fast_copy__raw(int fd, > > /* size */ > unsigned int width, unsigned int height, > + uint32_t color_depth, > > /* dst */ > uint32_t dst_handle, > @@ -620,7 +625,7 @@ void igt_blitter_fast_copy__raw(int fd, > src_pitch = fast_copy_pitch(src_stride, src_tiling); > dst_pitch = fast_copy_pitch(dst_stride, dst_tiling); > dword0 = fast_copy_dword0(src_tiling, dst_tiling); > - dword1 = fast_copy_dword1(src_tiling, dst_tiling); > + dword1 = fast_copy_dword1(src_tiling, dst_tiling, color_depth); > > #define CHECK_RANGE(x) ((x) >= 0 && (x) < (1 << 15)) > assert(CHECK_RANGE(src_x) && CHECK_RANGE(src_y) && > @@ -670,6 +675,7 @@ void igt_blitter_fast_copy__raw(int fd, > * @src_y: source pixel y-coordination > * @width: width of the copied rectangle > * @height: height of the copied rectangle > + * @color_depth: Color depth of the buffer > * @dst: destination i-g-t buffer object > * @dst_x: destination pixel x-coordination > * @dst_y: destination pixel y-coordination > @@ -680,7 +686,7 @@ void igt_blitter_fast_copy__raw(int fd, > */ > void igt_blitter_fast_copy(struct intel_batchbuffer *batch, > struct igt_buf *src, unsigned src_x, unsigned src_y, > - unsigned width, unsigned height, > + unsigned width, unsigned height, uint32_t color_depth, > struct igt_buf *dst, unsigned dst_x, unsigned dst_y) > { > uint32_t src_pitch, dst_pitch; > @@ -689,7 +695,7 @@ void igt_blitter_fast_copy(struct intel_batchbuffer *batch, > src_pitch = fast_copy_pitch(src->stride, src->tiling); > dst_pitch = fast_copy_pitch(dst->stride, src->tiling); > dword0 = fast_copy_dword0(src->tiling, dst->tiling); > - dword1 = fast_copy_dword1(src->tiling, dst->tiling); > + dword1 = fast_copy_dword1(src->tiling, dst->tiling, color_depth); > > #define CHECK_RANGE(x) ((x) >= 0 && (x) < (1 << 15)) > assert(CHECK_RANGE(src_x) && CHECK_RANGE(src_y) && > diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h > index 62c8396..0e0feed 100644 > --- a/lib/intel_batchbuffer.h > +++ b/lib/intel_batchbuffer.h > @@ -226,7 +226,7 @@ unsigned igt_buf_height(struct igt_buf *buf); > > void igt_blitter_fast_copy(struct intel_batchbuffer *batch, > struct igt_buf *src, unsigned src_x, unsigned src_y, > - unsigned width, unsigned height, > + unsigned width, unsigned height, uint32_t color_depth, > struct igt_buf *dst, unsigned dst_x, unsigned dst_y); > > void igt_blitter_fast_copy__raw(int fd, > @@ -238,6 +238,7 @@ void igt_blitter_fast_copy__raw(int fd, > > /* size */ > unsigned int width, unsigned int height, > + uint32_t color_depth, > > /* dst */ > uint32_t dst_handle, > diff --git a/lib/intel_reg.h b/lib/intel_reg.h > index 0ffa803..9f3de7a 100644 > --- a/lib/intel_reg.h > +++ b/lib/intel_reg.h > @@ -2530,6 +2530,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. > /* dword 1 */ > #define XY_FAST_COPY_SRC_TILING_Yf (1 << 31) > #define XY_FAST_COPY_DST_TILING_Yf (1 << 30) > +#define XY_FAST_COPY_COLOR_DEPTH_8 (0 << 24) > #define XY_FAST_COPY_COLOR_DEPTH_32 (3 << 24) > > #define MI_STORE_DWORD_IMM ((0x20<<23)|2) > diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c > index a269d0f..93717a0 100644 > --- a/lib/ioctl_wrappers.c > +++ b/lib/ioctl_wrappers.c > @@ -54,6 +54,7 @@ > #include "intel_chipset.h" > #include "intel_io.h" > #include "igt_debugfs.h" > +#include "igt_fb.h" > #include "config.h" > > #include "ioctl_wrappers.h" > @@ -1221,7 +1222,7 @@ void igt_require_fb_modifiers(int fd) > > int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height, > uint32_t stride, uint32_t pixel_format, uint64_t modifier, > - uint32_t flags, uint32_t *buf_id) > + uint32_t uv_offset, uint32_t flags, uint32_t *buf_id) > { > struct local_drm_mode_fb_cmd2 f; > int ret; > @@ -1238,6 +1239,13 @@ int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height, > f.pitches[0] = stride; > f.modifier[0] = modifier; > > + if (pixel_format == DRM_FORMAT_NV12) { > + f.handles[1] = handle; > + f.pitches[1] = stride; > + f.offsets[1] = uv_offset; > + f.modifier[1] = modifier; > + } > + > ret = drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f); > > *buf_id = f.fb_id; > diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h > index bc5d4bd..3d93a5e 100644 > --- a/lib/ioctl_wrappers.h > +++ b/lib/ioctl_wrappers.h > @@ -175,6 +175,6 @@ void igt_require_fb_modifiers(int fd); > */ > int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height, > uint32_t stride, uint32_t pixel_format, uint64_t modifier, > - uint32_t flags, uint32_t *buf_id); > + uint32_t uv_offset, uint32_t flags, uint32_t *buf_id); > > #endif /* IOCTL_WRAPPERS_H */ > diff --git a/tests/kms_render.c b/tests/kms_render.c > index 1759eaa..4a7aaec 100644 > --- a/tests/kms_render.c > +++ b/tests/kms_render.c > @@ -78,8 +78,8 @@ static void gpu_blit(struct igt_fb *dst_fb, struct igt_fb *src_fb) > > 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); > + igt_drm_format_to_bpp(src_fb->drm_format, 0) != 16); > + bpp = igt_drm_format_to_bpp(src_fb->drm_format, 0); > dst_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "destination", > dst_fb->gem_handle); > igt_assert(dst_bo); > -- > 1.9.1 >
diff --git a/lib/igt_fb.c b/lib/igt_fb.c index cc4b8ee..dedee9e 100644 --- a/lib/igt_fb.c +++ b/lib/igt_fb.c @@ -74,7 +74,7 @@ static struct format_desc_struct { /* helpers to create nice-looking framebuffers */ -static int create_bo_for_fb(int fd, int width, int height, int bpp, +static int create_bo_for_fb(int fd, int width, int height, int bpp, int bpp2, uint64_t tiling, unsigned bo_size, uint32_t *gem_handle_ret, unsigned *size_ret, @@ -99,13 +99,17 @@ static int create_bo_for_fb(int fd, int width, int height, int bpp, for (stride = 512; stride < v; stride *= 2) ; - v = stride * height; + /* planar formats height is 1.5x */ + v = stride * (bpp2 ? (height * 3) / 2 : height); + for (size = 1024*1024; size < v; size *= 2) ; } else { /* Scan-out has a 64 byte alignment restriction */ stride = (width * (bpp / 8) + 63) & ~63; - size = stride * height; + + /* planar formats height is 1.5x */ + size = stride * (bpp2 ? (height * 3) / 2 : height); } if (bo_size == 0) @@ -393,6 +397,75 @@ void igt_paint_image(cairo_t *cr, const char *filename, } /** + * igt_get_image_size: + * @filename: filename of the png image + * @width: width of the image + * @height: height of the image + * + * This function returns @width and @height of the png image in @filename, + * which is loaded from the package data directory. + */ +void +igt_get_image_size(const char *filename, int *width, int *height) +{ + cairo_surface_t *image; + FILE* f; + + f = igt_fopen_data(filename); + + image = cairo_image_surface_create_from_png_stream(&stdio_read_func, f); + igt_assert(cairo_surface_status(image) == CAIRO_STATUS_SUCCESS); + + *width = cairo_image_surface_get_width(image); + *height = cairo_image_surface_get_height(image); + + cairo_surface_destroy(image); + + fclose(f); +} + + +/** + * igt_fb_calc_uv: + * @fb: pointer to an #igt_fb structure + * + * This function calculates UV offset in bytes and UV starting line number + * for requested NV12 @fb. + */ +void +igt_fb_calc_uv(struct igt_fb *fb) +{ + if (fb->drm_format != DRM_FORMAT_NV12) + return; + + switch (fb->tiling) { + case LOCAL_DRM_FORMAT_MOD_NONE: + fb->uv_y_start = fb->height; + break; + case LOCAL_I915_FORMAT_MOD_X_TILED: + fb->uv_y_start = fb->height; + break; + case LOCAL_I915_FORMAT_MOD_Y_TILED: + fb->uv_y_start = fb->height; + break; + case LOCAL_I915_FORMAT_MOD_Yf_TILED: + /* tile-Yf requires uv to start on a new tile row */ + if (fb->height % 64) + fb->uv_y_start = (fb->height + 63) & ~63; + else + fb->uv_y_start = fb->height; + break; + default: + igt_assert(0); + } + + fb->uv_offset = fb->uv_y_start * fb->stride; + + /* assert that fb has enough lines to hold y and uv sub-planes */ + igt_assert(fb->size / fb->stride >= fb->uv_y_start + fb->height / 2); +} + +/** * igt_create_fb_with_bo_size: * @fd: open i915 drm file descriptor * @width: width of the framebuffer in pixel @@ -418,24 +491,32 @@ igt_create_fb_with_bo_size(int fd, int width, int height, struct igt_fb *fb, unsigned bo_size) { uint32_t fb_id; - int bpp; + int bpp, bpp2; memset(fb, 0, sizeof(*fb)); - bpp = igt_drm_format_to_bpp(format); + bpp = igt_drm_format_to_bpp(format, 0); + bpp2 = igt_drm_format_to_bpp(format, 1); - 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, + igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d, %d], tiling=0x%"PRIx64", size=%d\n", + __func__, width, height, format, bpp, bpp2, tiling, bo_size); + do_or_die(create_bo_for_fb(fd, width, height, bpp, bpp2, tiling, bo_size, &fb->gem_handle, &fb->size, &fb->stride)); igt_debug("%s(handle=%d, pitch=%d)\n", __func__, fb->gem_handle, fb->stride); + fb->width = width; + fb->height = height; + fb->tiling = tiling; + fb->drm_format = format; + + igt_fb_calc_uv(fb); + 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, + fb->stride, format, tiling, fb->uv_offset, LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id)); } else { uint32_t handles[4]; @@ -449,21 +530,213 @@ igt_create_fb_with_bo_size(int fd, int width, int height, handles[0] = fb->gem_handle; pitches[0] = fb->stride; + if (format == DRM_FORMAT_NV12) { + handles[1] = fb->gem_handle; + pitches[1] = fb->stride; + offsets[1] = fb->uv_offset; + } + 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; } /** + * igt_fb_gem_mmap: + * @fd: open i915 drm file descriptor + * @fb: pointer to an #igt_fb structure + * + * This function memory maps gem buffer for cpu access and saves mmap pointer + * in @fb. + */ +void +igt_fb_gem_mmap(int fd, struct igt_fb *fb) +{ + if (!fb->mmap_gtt) + fb->mmap_gtt = gem_mmap__gtt(fd, fb->gem_handle, fb->size, + PROT_READ | PROT_WRITE); + igt_assert(fb->mmap_gtt); +} + +/** + * igt_fb_csc_xrgb_to_nv12: + * @fd: open i915 drm file descriptor + * @width: width of the framebuffer to be converted + * @height: height of the framebuffer to be converted + * @dst: pointer to an #igt_fb structure holding destination framebuffer + * @src: pointer to an #igt_fb structure holding source framebuffer + * + * This function converts source framebuffer into destination framebuffer + * format. It also mmaps the underlying gem buffer if it isn't mmaped + * before. + * + * For now: + * - it expects both src and dst fbs are same size and tiling + */ +void +igt_fb_csc_xrgb_to_nv12(int fd, struct igt_fb *dst_fb, struct igt_fb *src_fb) +{ + unsigned char *nv12; + unsigned char *xrgb; + unsigned char y, v, u; + float yf, vf, uf; + unsigned char r, g, b; + int i, j; + int xrgb_pos; + int y_pos; + int uv_pos; + int uv_base; + unsigned int obj_tiling; + struct igt_fb *temp_src_fb, *temp_dst_fb; + struct igt_fb fb1, fb2; + int temp_src_id, temp_dst_id; + + igt_assert(dst_fb); + igt_assert(src_fb); + igt_assert(dst_fb->width == src_fb->width); + igt_assert(dst_fb->height == src_fb->height); + igt_assert(src_fb->tiling == dst_fb->tiling); + + igt_assert(src_fb->drm_format == DRM_FORMAT_XRGB8888); + igt_assert(dst_fb->drm_format == DRM_FORMAT_NV12); + + /* + * Steps: Not the best approach but gets job done for igt + * (1) create linear temp_src, temp_dst + * (2) fast blit src --> temp src + * (3) gem map temp_src, temp_dst + * (4) host conversion & copy from temp src --> temp dst + * (5) fast blit temp dst --> dst + * (6) free temp fbs + * + * For Linear/X: + * perform 3 & 4 only + * For Y/Yf: + * perform all steps + */ + + if (src_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || + src_fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) { + + temp_src_fb = &fb1; + temp_dst_fb = &fb2; + + /* (1) create linear temp_src, temp_dst */ + temp_src_id = igt_create_fb(fd, + src_fb->width, src_fb->height, + src_fb->drm_format, + LOCAL_DRM_FORMAT_MOD_NONE, + temp_src_fb); + igt_assert(temp_src_id); + + temp_dst_id = igt_create_fb(fd, + dst_fb->width, dst_fb->height, + dst_fb->drm_format, + LOCAL_DRM_FORMAT_MOD_NONE, + temp_dst_fb); + igt_assert(temp_dst_id); + + if (src_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED) + obj_tiling = I915_TILING_Y; + else + obj_tiling = I915_TILING_Yf; + + /* (2) fast blit src --> temp src */ + igt_blitter_fast_copy__raw(fd, + src_fb->gem_handle, + src_fb->stride, + obj_tiling, + 0, 0, + temp_src_fb->width, temp_src_fb->height, + igt_drm_format_to_bpp(temp_src_fb->drm_format, 0), + temp_src_fb->gem_handle, + temp_src_fb->stride, + I915_TILING_NONE, + 0, 0); + } else { + temp_src_fb = src_fb; + temp_dst_fb = dst_fb; + } + + /* (3) gem map temp_src, temp_dst */ + igt_fb_gem_mmap(fd, temp_src_fb); + igt_fb_gem_mmap(fd, temp_dst_fb); + + /* (4) host conversion & copy from temp src --> temp dst */ + xrgb = (unsigned char *) temp_src_fb->mmap_gtt; + nv12 = (unsigned char *) temp_dst_fb->mmap_gtt; + uv_base = temp_dst_fb->stride * temp_dst_fb->height; + + for (i = 0; i < temp_src_fb->height; i++) { + xrgb_pos = i * temp_src_fb->stride; + y_pos = i * temp_dst_fb->stride; + uv_pos = temp_dst_fb->stride * i / 2; + for (j = 0; j < temp_src_fb->width; j++) { + b = xrgb[xrgb_pos++]; + g = xrgb[xrgb_pos++]; + r = xrgb[xrgb_pos++]; + xrgb_pos++; + + /* use floats for intermediate calcs, to get better results */ + yf = (0.257 * r) + (0.504 * g) + (0.098 * b) + 16; + uf = -(0.148 * r) - (0.291 * g) + (0.439 * b) + 128; + vf = (0.439 * r) - (0.368 * g) - (0.071 * b) + 128; + + y = (unsigned char) yf; + u = (unsigned char) uf; + v = (unsigned char) vf; + + nv12[y_pos++] = y; + + if (!(j % 2) && !(i % 2)) { + nv12[uv_base + uv_pos++] = u; + nv12[uv_base + uv_pos++] = v; + } + } + } + + /* (5) fast blit temp dst --> dst */ + if (dst_fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || + dst_fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) { + + /* blit y-plane */ + igt_blitter_fast_copy__raw(fd, + temp_dst_fb->gem_handle, + temp_dst_fb->stride, + I915_TILING_NONE, + 0, 0, + dst_fb->width, dst_fb->height, + igt_drm_format_to_bpp(dst_fb->drm_format, 0), + dst_fb->gem_handle, + dst_fb->stride, + obj_tiling, + 0, 0); + + /* blit uv-plane */ + igt_blitter_fast_copy__raw(fd, + temp_dst_fb->gem_handle, + temp_dst_fb->stride, + I915_TILING_NONE, + 0, temp_dst_fb->uv_y_start, + dst_fb->width, dst_fb->height, + igt_drm_format_to_bpp(dst_fb->drm_format, 1), + dst_fb->gem_handle, + dst_fb->stride, + obj_tiling, + 0, dst_fb->uv_y_start); + + /* (6) free temp fbs */ + igt_remove_fb(fd, temp_src_fb); + igt_remove_fb(fd, temp_dst_fb); + } +} + +/** * igt_create_fb: * @fd: open i915 drm file descriptor * @width: width of the framebuffer in pixel @@ -686,6 +959,7 @@ static void destroy_cairo_surface__blit(void *arg) I915_TILING_NONE, 0, 0, /* src_x, src_y */ fb->width, fb->height, + 0, fb->gem_handle, fb->stride, obj_tiling, @@ -712,8 +986,8 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb) * 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, + bpp = igt_drm_format_to_bpp(fb->drm_format, 0); + ret = create_bo_for_fb(fd, fb->width, fb->height, bpp, 0, LOCAL_DRM_FORMAT_MOD_NONE, 0, &blit->linear.handle, &blit->linear.size, @@ -734,6 +1008,7 @@ static void create_cairo_surface__blit(int fd, struct igt_fb *fb) obj_tiling, 0, 0, /* src_x, src_y */ fb->width, fb->height, + bpp, blit->linear.handle, blit->linear.stride, I915_TILING_NONE, @@ -893,15 +1168,24 @@ uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth) /** * igt_drm_format_to_bpp: * @drm_format: drm fourcc pixel format code + * @plane: plane id * * Returns: * The bits per pixel for the given drm fourcc pixel format code. Fails hard if * no match was found. */ -uint32_t igt_drm_format_to_bpp(uint32_t drm_format) +uint32_t igt_drm_format_to_bpp(uint32_t drm_format, int plane) { struct format_desc_struct *f; + if (drm_format == DRM_FORMAT_NV12 && plane == 0) + return 8; + if (drm_format == DRM_FORMAT_NV12 && plane == 1) + return 16; + + if (plane) + return 0; + for_each_format(f) if (f->drm_id == drm_format) return f->bpp; diff --git a/lib/igt_fb.h b/lib/igt_fb.h index a07acd2..9e227e8 100644 --- a/lib/igt_fb.h +++ b/lib/igt_fb.h @@ -54,10 +54,13 @@ struct igt_fb { uint64_t tiling; unsigned size; cairo_surface_t *cairo_surface; + void *mmap_gtt; uint32_t src_x; uint32_t src_y; uint32_t src_w; uint32_t src_h; + uint32_t uv_y_start; + uint32_t uv_offset; }; enum igt_text_align { @@ -82,6 +85,9 @@ unsigned int igt_create_color_fb(int fd, int width, int height, unsigned int igt_create_stereo_fb(int drm_fd, drmModeModeInfo *mode, uint32_t format, uint64_t tiling); void igt_remove_fb(int fd, struct igt_fb *fb); +void igt_fb_gem_mmap(int fd, struct igt_fb *fb); +void igt_fb_csc_xrgb_to_nv12(int fd, struct igt_fb *dst, struct igt_fb *src); +void igt_fb_calc_uv(struct igt_fb *fb); /* cairo-based painting */ cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb); @@ -98,10 +104,11 @@ void igt_write_fb_to_png(int fd, struct igt_fb *fb, const char *filename); int igt_cairo_printf_line(cairo_t *cr, enum igt_text_align align, double yspacing, const char *fmt, ...) __attribute__((format (printf, 4, 5))); +void igt_get_image_size(const char *filename, int *width, int *height); /* helpers to handle drm fourcc codes */ uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth); -uint32_t igt_drm_format_to_bpp(uint32_t drm_format); +uint32_t igt_drm_format_to_bpp(uint32_t drm_format, int plane); const char *igt_format_str(uint32_t drm_format); void igt_get_all_formats(const uint32_t **formats, int *format_count); diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c index 8b68e52..a2cd6ab 100644 --- a/lib/intel_batchbuffer.c +++ b/lib/intel_batchbuffer.c @@ -518,7 +518,7 @@ static uint32_t fast_copy_dword0(unsigned int src_tiling, } static uint32_t fast_copy_dword1(unsigned int src_tiling, - unsigned int dst_tiling) + unsigned int dst_tiling, uint32_t color_depth) { uint32_t dword1 = 0; @@ -527,7 +527,10 @@ static uint32_t fast_copy_dword1(unsigned int src_tiling, if (dst_tiling == I915_TILING_Yf) dword1 |= XY_FAST_COPY_DST_TILING_Yf; - dword1 |= XY_FAST_COPY_COLOR_DEPTH_32; + if (color_depth == 8) + dword1 |= XY_FAST_COPY_COLOR_DEPTH_8; + else + dword1 |= XY_FAST_COPY_COLOR_DEPTH_32; return dword1; } @@ -585,6 +588,7 @@ static void exec_blit(int fd, * @src_y: Y coordinate of the source region to copy * @width: Width of the region to copy * @height: Height of the region to copy + * @color_depth: Color depth of the buffer * @dst_handle: GEM handle of the source buffer * @dst_stride: Stride (in bytes) of the destination buffer * @dst_tiling: Tiling mode of the destination buffer @@ -602,6 +606,7 @@ void igt_blitter_fast_copy__raw(int fd, /* size */ unsigned int width, unsigned int height, + uint32_t color_depth, /* dst */ uint32_t dst_handle, @@ -620,7 +625,7 @@ void igt_blitter_fast_copy__raw(int fd, src_pitch = fast_copy_pitch(src_stride, src_tiling); dst_pitch = fast_copy_pitch(dst_stride, dst_tiling); dword0 = fast_copy_dword0(src_tiling, dst_tiling); - dword1 = fast_copy_dword1(src_tiling, dst_tiling); + dword1 = fast_copy_dword1(src_tiling, dst_tiling, color_depth); #define CHECK_RANGE(x) ((x) >= 0 && (x) < (1 << 15)) assert(CHECK_RANGE(src_x) && CHECK_RANGE(src_y) && @@ -670,6 +675,7 @@ void igt_blitter_fast_copy__raw(int fd, * @src_y: source pixel y-coordination * @width: width of the copied rectangle * @height: height of the copied rectangle + * @color_depth: Color depth of the buffer * @dst: destination i-g-t buffer object * @dst_x: destination pixel x-coordination * @dst_y: destination pixel y-coordination @@ -680,7 +686,7 @@ void igt_blitter_fast_copy__raw(int fd, */ void igt_blitter_fast_copy(struct intel_batchbuffer *batch, struct igt_buf *src, unsigned src_x, unsigned src_y, - unsigned width, unsigned height, + unsigned width, unsigned height, uint32_t color_depth, struct igt_buf *dst, unsigned dst_x, unsigned dst_y) { uint32_t src_pitch, dst_pitch; @@ -689,7 +695,7 @@ void igt_blitter_fast_copy(struct intel_batchbuffer *batch, src_pitch = fast_copy_pitch(src->stride, src->tiling); dst_pitch = fast_copy_pitch(dst->stride, src->tiling); dword0 = fast_copy_dword0(src->tiling, dst->tiling); - dword1 = fast_copy_dword1(src->tiling, dst->tiling); + dword1 = fast_copy_dword1(src->tiling, dst->tiling, color_depth); #define CHECK_RANGE(x) ((x) >= 0 && (x) < (1 << 15)) assert(CHECK_RANGE(src_x) && CHECK_RANGE(src_y) && diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h index 62c8396..0e0feed 100644 --- a/lib/intel_batchbuffer.h +++ b/lib/intel_batchbuffer.h @@ -226,7 +226,7 @@ unsigned igt_buf_height(struct igt_buf *buf); void igt_blitter_fast_copy(struct intel_batchbuffer *batch, struct igt_buf *src, unsigned src_x, unsigned src_y, - unsigned width, unsigned height, + unsigned width, unsigned height, uint32_t color_depth, struct igt_buf *dst, unsigned dst_x, unsigned dst_y); void igt_blitter_fast_copy__raw(int fd, @@ -238,6 +238,7 @@ void igt_blitter_fast_copy__raw(int fd, /* size */ unsigned int width, unsigned int height, + uint32_t color_depth, /* dst */ uint32_t dst_handle, diff --git a/lib/intel_reg.h b/lib/intel_reg.h index 0ffa803..9f3de7a 100644 --- a/lib/intel_reg.h +++ b/lib/intel_reg.h @@ -2530,6 +2530,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* dword 1 */ #define XY_FAST_COPY_SRC_TILING_Yf (1 << 31) #define XY_FAST_COPY_DST_TILING_Yf (1 << 30) +#define XY_FAST_COPY_COLOR_DEPTH_8 (0 << 24) #define XY_FAST_COPY_COLOR_DEPTH_32 (3 << 24) #define MI_STORE_DWORD_IMM ((0x20<<23)|2) diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c index a269d0f..93717a0 100644 --- a/lib/ioctl_wrappers.c +++ b/lib/ioctl_wrappers.c @@ -54,6 +54,7 @@ #include "intel_chipset.h" #include "intel_io.h" #include "igt_debugfs.h" +#include "igt_fb.h" #include "config.h" #include "ioctl_wrappers.h" @@ -1221,7 +1222,7 @@ void igt_require_fb_modifiers(int fd) int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height, uint32_t stride, uint32_t pixel_format, uint64_t modifier, - uint32_t flags, uint32_t *buf_id) + uint32_t uv_offset, uint32_t flags, uint32_t *buf_id) { struct local_drm_mode_fb_cmd2 f; int ret; @@ -1238,6 +1239,13 @@ int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height, f.pitches[0] = stride; f.modifier[0] = modifier; + if (pixel_format == DRM_FORMAT_NV12) { + f.handles[1] = handle; + f.pitches[1] = stride; + f.offsets[1] = uv_offset; + f.modifier[1] = modifier; + } + ret = drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f); *buf_id = f.fb_id; diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h index bc5d4bd..3d93a5e 100644 --- a/lib/ioctl_wrappers.h +++ b/lib/ioctl_wrappers.h @@ -175,6 +175,6 @@ void igt_require_fb_modifiers(int fd); */ int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height, uint32_t stride, uint32_t pixel_format, uint64_t modifier, - uint32_t flags, uint32_t *buf_id); + uint32_t uv_offset, uint32_t flags, uint32_t *buf_id); #endif /* IOCTL_WRAPPERS_H */ diff --git a/tests/kms_render.c b/tests/kms_render.c index 1759eaa..4a7aaec 100644 --- a/tests/kms_render.c +++ b/tests/kms_render.c @@ -78,8 +78,8 @@ static void gpu_blit(struct igt_fb *dst_fb, struct igt_fb *src_fb) 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); + igt_drm_format_to_bpp(src_fb->drm_format, 0) != 16); + bpp = igt_drm_format_to_bpp(src_fb->drm_format, 0); dst_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "destination", dst_fb->gem_handle); igt_assert(dst_bo);