bo->sizes[1] = bo->strides[1] * chroma_height + 64;
bo->offsets[0] = bo->offsets[1] = 0;
} else if (format == DRV_FORMAT_XRGB8888 || format == DRV_FORMAT_ARGB8888) {
- bo->strides[0] = drv_stride_from_format(format, width);
+ bo->strides[0] = drv_stride_from_format(format, width, 0);
bo->sizes[0] = height * bo->strides[0];
bo->offsets[0] = 0;
} else {
return 1;
case DRV_FORMAT_NV12:
return 2;
+ case DRV_FORMAT_YVU420:
+ return 3;
}
fprintf(stderr, "drv: UNKNOWN FORMAT %d\n", format);
return 0;
}
-int drv_bpp_from_format(uint32_t format)
+int drv_bpp_from_format(uint32_t format, size_t plane)
{
- switch(format)
+ assert(plane < drv_num_planes_from_format(format));
+
+ switch (format)
{
case DRV_FORMAT_C8:
case DRV_FORMAT_R8:
return 8;
case DRV_FORMAT_NV12:
- return 12;
+ return (plane == 0) ? 8 : 4;
+ case DRV_FORMAT_YVU420:
+ return (plane == 0) ? 8 : 2;
case DRV_FORMAT_RG88:
case DRV_FORMAT_GR88:
return 0;
}
-int drv_stride_from_format(uint32_t format, uint32_t width)
+/*
+ * This function returns the stride for a given format, width and plane.
+ */
+int drv_stride_from_format(uint32_t format, uint32_t width, size_t plane)
{
- /* Only single-plane formats are supported */
- assert(drv_num_planes_from_format(format) == 1);
- return DIV_ROUND_UP(width * drv_bpp_from_format(format), 8);
+ /* Get stride of the first plane */
+ int stride = width * DIV_ROUND_UP(drv_bpp_from_format(format, 0), 8);
+
+ /*
+ * Only downsample for certain multiplanar formats which are not
+ * interleaved and have horizontal subsampling. Only formats supported
+ * by our drivers are listed here -- add more as needed.
+ */
+ if (plane != 0) {
+ switch (format) {
+ case DRV_FORMAT_YVU420:
+ stride = stride / 2;
+ }
+ }
+
+ return stride;
}
int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height,
memset(&create_dumb, 0, sizeof(create_dumb));
create_dumb.height = height;
create_dumb.width = width;
- create_dumb.bpp = drv_bpp_from_format(format);
+ create_dumb.bpp = drv_bpp_from_format(format, 0);
create_dumb.flags = 0;
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
#include "drv.h"
size_t drv_num_planes_from_format(uint32_t format);
-int drv_bpp_from_format(uint32_t format);
-int drv_stride_from_format(uint32_t format, uint32_t width);
+int drv_bpp_from_format(uint32_t format, size_t plane);
+int drv_stride_from_format(uint32_t format, uint32_t width, size_t plane);
int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height,
uint32_t format, uint32_t flags);
int drv_dumb_bo_destroy(struct bo *bo);
uint32_t format, uint32_t flags)
{
struct driver *drv = bo->drv;
- int bpp = drv_stride_from_format(format, 1);
+ int bpp = drv_stride_from_format(format, 1, 0);
struct drm_i915_gem_create gem_create;
struct drm_i915_gem_set_tiling gem_set_tiling;
uint32_t tiling_mode = I915_TILING_NONE;
- size_t size;
+ size_t size, plane;
int ret;
if (flags & (DRV_BO_USE_CURSOR | DRV_BO_USE_LINEAR |
i915_align_dimensions(drv, tiling_mode, &width, &height, bpp);
- bo->strides[0] = width * bpp;
+ switch (format) {
+ case DRV_FORMAT_YVU420:
+ bo->strides[0] = drv_stride_from_format(format, width, 0);
+ bo->strides[1] = bo->strides[2] = drv_stride_from_format(format, width, 1);
+ bo->sizes[0] = height * bo->strides[0];
+ bo->sizes[1] = bo->sizes[2] = (height / 2) * bo->strides[1];
+ bo->offsets[0] = 0;
+ bo->offsets[1] = bo->sizes[0];
+ bo->offsets[2] = bo->offsets[1] + bo->sizes[1];
+ break;
+ default:
+ bo->strides[0] = drv_stride_from_format(format, width, 0);
+ bo->sizes[0] = height * bo->strides[0];
+ bo->offsets[0] = 0;
+ }
if (!i915_verify_dimensions(drv, bo->strides[0], height))
return EINVAL;
+ size = bo->offsets[bo->num_planes - 1] + bo->sizes[bo->num_planes - 1];
+
memset(&gem_create, 0, sizeof(gem_create));
- size = width * height * bpp;
gem_create.size = size;
ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
"(size=%zu)\n", size);
return ret;
}
- bo->handles[0].u32 = gem_create.handle;
- bo->sizes[0] = size;
- bo->offsets[0] = 0;
+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ bo->handles[plane].u32 = gem_create.handle;
memset(&gem_set_tiling, 0, sizeof(gem_set_tiling));
do {
/*HACK: See b/28671744 */
return DRV_FORMAT_XBGR8888;
case DRV_FORMAT_FLEX_YCbCr_420_888:
- /*
- * TODO(gurchetansingh) Implement YV12 with no tiling
- * on Intel. See b/29335168
- */
return DRV_FORMAT_YVU420;
default:
return format;
DRV_BO_USE_SW_READ_OFTEN | DRV_BO_USE_SW_WRITE_OFTEN},
{DRV_FORMAT_GR88, DRV_BO_USE_SCANOUT | DRV_BO_USE_LINEAR |
DRV_BO_USE_SW_READ_OFTEN | DRV_BO_USE_SW_WRITE_OFTEN},
+ {DRV_FORMAT_YVU420, DRV_BO_USE_LINEAR | DRV_BO_USE_SW_READ_OFTEN |
+ DRV_BO_USE_SW_WRITE_OFTEN},
}
};
struct drm_mtk_gem_create gem_create;
int ret;
- bo->strides[0] = drv_stride_from_format(format, width);
+ bo->strides[0] = drv_stride_from_format(format, width, 0);
size = height * bo->strides[0];
memset(&gem_create, 0, sizeof(gem_create));
case DRV_FORMAT_XRGB8888:
case DRV_FORMAT_ARGB8888:
case DRV_FORMAT_ABGR8888:
- bo->strides[0] = drv_stride_from_format(format, width);
+ bo->strides[0] = drv_stride_from_format(format, width, 0);
bo->sizes[0] = height * bo->strides[0];
bo->offsets[0] = 0;
break;
uint32_t *block_height_log2,
uint32_t *stride, uint32_t *size)
{
- int pitch = drv_stride_from_format(format, width);
+ int pitch = drv_stride_from_format(format, width, 0);
/* Align to blocklinear blocks. */
pitch = ALIGN(pitch, NV_BLOCKLINEAR_GOB_WIDTH);
static void compute_layout_linear(int width, int height, int format,
uint32_t *stride, uint32_t *size)
{
- *stride = drv_stride_from_format(format, width);
+ *stride = drv_stride_from_format(format, width, 0);
*size = *stride * height;
}