* Older hardware can't scanout Y-tiled formats. Newer devices can, and
* report this functionality via format modifiers.
*/
- for (i = 0; i < drv->backend->combos.size; i++) {
- combo = &drv->backend->combos.data[i];
+ for (i = 0; i < drv->combos.size; i++) {
+ combo = &drv->combos.data[i];
if (combo->format != item->format)
continue;
drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE);
+ render_flags &= ~BO_USE_RENDERSCRIPT;
render_flags &= ~BO_USE_SW_WRITE_OFTEN;
render_flags &= ~BO_USE_SW_READ_OFTEN;
render_flags &= ~BO_USE_LINEAR;
+ texture_flags &= ~BO_USE_RENDERSCRIPT;
texture_flags &= ~BO_USE_SW_WRITE_OFTEN;
texture_flags &= ~BO_USE_SW_READ_OFTEN;
texture_flags &= ~BO_USE_LINEAR;
break;
}
+ /*
+ * The alignment calculated above is based on the full size luma plane and to have chroma
+ * planes properly aligned with subsampled formats, we need to multiply luma alignment by
+ * subsampling factor.
+ */
+ switch (bo->format) {
+ case DRM_FORMAT_YVU420_ANDROID:
+ case DRM_FORMAT_YVU420:
+ horizontal_alignment *= 2;
+ /* Fall through */
+ case DRM_FORMAT_NV12:
+ vertical_alignment *= 2;
+ break;
+ }
+
+ /*
+ * For multi-planar formats we must be aligned to 16
+ */
+ if (bo->num_planes > 1)
+ vertical_alignment = MAX(vertical_alignment, 16);
+
*aligned_height = ALIGN(bo->height, vertical_alignment);
if (i915->gen > 3) {
*stride = ALIGN(*stride, horizontal_alignment);
return ret;
/*
- * Align the Y plane to 128 bytes so the chroma planes would be aligned
- * to 64 byte boundaries. This is an Intel HW requirement.
- */
- if (format == DRM_FORMAT_YVU420)
- stride = ALIGN(stride, 128);
-
- /*
- * HAL_PIXEL_FORMAT_YV12 requires that the buffer's height not be aligned.
+ * HAL_PIXEL_FORMAT_YV12 requires the buffer height not be aligned, but we need to keep
+ * total size as with aligned height to ensure enough padding space after each plane to
+ * satisfy GPU alignment requirements.
+ *
+ * We do it by first calling drv_bo_from_format() with aligned height and
+ * DRM_FORMAT_YVU420, which allows height alignment, saving the total size it calculates
+ * and then calling it again with requested parameters.
+ *
+ * This relies on the fact that i965 driver uses separate surfaces for each plane and
+ * contents of padding bytes is not affected, as it is only used to satisfy GPU cache
+ * requests.
+ *
+ * This is enforced by Mesa in src/intel/isl/isl_gen8.c, inside
+ * isl_gen8_choose_image_alignment_el(), which is used for GEN9 and GEN8.
*/
- if (format == DRM_FORMAT_YVU420_ANDROID)
- height = bo->height;
-
- drv_bo_from_format(bo, stride, height, format);
+ if (format == DRM_FORMAT_YVU420_ANDROID) {
+ uint32_t unaligned_height = bo->height;
+ size_t total_size;
+
+ drv_bo_from_format(bo, stride, height, DRM_FORMAT_YVU420);
+ total_size = bo->total_size;
+ drv_bo_from_format(bo, stride, unaligned_height, format);
+ bo->total_size = total_size;
+ } else {
+ drv_bo_from_format(bo, stride, height, format);
+ }
/*
* Quoting Mesa ISL library:
return addr;
}
-static int i915_bo_unmap(struct bo *bo, struct map_info *data)
+static int i915_bo_flush(struct bo *bo, struct map_info *data)
{
struct i915_device *i915 = bo->drv->priv;
if (!i915->has_llc && bo->tiling == I915_TILING_NONE)
i915_clflush(data->addr, data->length);
- return munmap(data->addr, data->length);
+ return 0;
}
static uint32_t i915_resolve_format(uint32_t format, uint64_t usage)
.bo_destroy = drv_gem_bo_destroy,
.bo_import = i915_bo_import,
.bo_map = i915_bo_map,
- .bo_unmap = i915_bo_unmap,
+ .bo_unmap = drv_bo_munmap,
+ .bo_flush = i915_bo_flush,
.resolve_format = i915_resolve_format,
};