#define MI_FLUSH_DW (0x26 << 23)
#define MI_WRITE_DIRTY_STATE (1 << 4)
#define MI_INVALIDATE_MAP_CACHE (1 << 0)
-#define XY_SRC_COPY_BLT_CMD ((2 << 29) | (0x53 << 22) | 6)
+#define XY_SRC_COPY_BLT_CMD ((2 << 29) | (0x53 << 22))
#define XY_SRC_COPY_BLT_WRITE_ALPHA (1 << 21)
#define XY_SRC_COPY_BLT_WRITE_RGB (1 << 20)
#define XY_SRC_COPY_BLT_SRC_TILED (1 << 15)
#define XY_SRC_COPY_BLT_DST_TILED (1 << 11)
+#define DEBUG_BLT 0
+
struct intel_info {
struct gralloc_drm_drv_t base;
drm_intel_bo *batch_ibo;
uint32_t *batch, *cur;
int capacity, size;
+ int exec_blt;
};
struct intel_buffer {
}
static int
+batch_reloc64(struct intel_info *info, struct gralloc_drm_bo_t *bo,
+ uint32_t read_domains, uint32_t write_domain)
+{
+ struct intel_buffer *target = (struct intel_buffer *) bo;
+ uint32_t offset = (info->cur - info->batch) * sizeof(info->batch[0]);
+ int ret;
+
+ ret = drm_intel_bo_emit_reloc(info->batch_ibo, offset,
+ target->ibo, 0, read_domains, write_domain);
+ if (!ret) {
+ batch_dword(info, target->ibo->offset64);
+ batch_dword(info, target->ibo->offset64 >> 32);
+ }
+
+ return ret;
+}
+
+static int
batch_flush(struct intel_info *info)
{
int size, ret;
ALOGE("failed to subdata batch");
goto fail;
}
- ret = drm_intel_bo_exec(info->batch_ibo, size, NULL, 0, 0);
+ ret = drm_intel_bo_mrb_exec(info->batch_ibo, size,
+ NULL, 0, 0, info->exec_blt);
if (ret) {
ALOGE("failed to exec batch");
goto fail;
return ret;
}
-static void intel_copy(struct gralloc_drm_drv_t *drv,
+static void intel_resolve_format(struct gralloc_drm_drv_t *drv,
+ struct gralloc_drm_bo_t *bo,
+ uint32_t *pitches, uint32_t *offsets, uint32_t *handles)
+{
+ /*
+ * TODO - should take account hw specific padding, alignment
+ * for camera, video decoder etc.
+ */
+
+ struct intel_buffer *ib = (struct intel_buffer *) bo;
+
+ memset(pitches, 0, 4 * sizeof(uint32_t));
+ memset(offsets, 0, 4 * sizeof(uint32_t));
+ memset(handles, 0, 4 * sizeof(uint32_t));
+
+ pitches[0] = ib->base.handle->stride;
+ handles[0] = ib->base.fb_handle;
+
+ switch(ib->base.handle->format) {
+ case HAL_PIXEL_FORMAT_YV12:
+
+ // U and V stride are half of Y plane
+ pitches[2] = pitches[0]/2;
+ pitches[1] = pitches[0]/2;
+
+ // like I420 but U and V are in reverse order
+ offsets[2] = offsets[0] +
+ pitches[0] * ib->base.handle->height;
+ offsets[1] = offsets[2] +
+ pitches[2] * ib->base.handle->height/2;
+
+ handles[1] = handles[2] = handles[0];
+ break;
+
+ case HAL_PIXEL_FORMAT_DRM_NV12:
+
+ // U and V are interleaved in 2nd plane
+ pitches[1] = pitches[0];
+ offsets[1] = offsets[0] +
+ pitches[0] * ib->base.handle->height;
+
+ handles[1] = handles[0];
+ break;
+ }
+}
+
+
+static void intel_blit(struct gralloc_drm_drv_t *drv,
struct gralloc_drm_bo_t *dst,
struct gralloc_drm_bo_t *src,
- short x1, short y1, short x2, short y2)
+ uint16_t dst_x1, uint16_t dst_y1,
+ uint16_t dst_x2, uint16_t dst_y2,
+ uint16_t src_x1, uint16_t src_y1,
+ uint16_t src_x2, uint16_t src_y2)
{
struct intel_info *info = (struct intel_info *) drv;
struct intel_buffer *dst_ib = (struct intel_buffer *) dst;
drm_intel_bo *bo_table[3];
uint32_t cmd, br13, dst_pitch, src_pitch;
- if (dst->handle->width != src->handle->width ||
- dst->handle->height != src->handle->height ||
- dst->handle->stride != src->handle->stride ||
- dst->handle->format != src->handle->format) {
- ALOGE("copy between incompatible buffers");
+ /*
+ * XY_SRC_COPY_BLT_CMD does not support scaling,
+ * rectangle dimensions much match
+ */
+ if (src_x2 - src_x1 != dst_x2 - dst_x1 ||
+ src_y2 - src_y1 != dst_y2 - dst_y1) {
+ ALOGE("%s, src and dst rect must match", __func__);
return;
}
- if (x1 < 0)
- x1 = 0;
- if (y1 < 0)
- y1 = 0;
- if (x2 > dst->handle->width)
- x2 = dst->handle->width;
- if (y2 > dst->handle->height)
- y2 = dst->handle->height;
+ if (dst->handle->format != src->handle->format) {
+ ALOGE("%s, src and dst format must match", __func__);
+ return;
+ }
- if (x2 <= x1 || y2 <= y1)
+ /* nothing to blit */
+ if (src_x2 <= src_x1 || src_y2 <= src_y1)
return;
+ /* clamp x2, y2 to surface size */
+ if (src_x2 > src->handle->width)
+ src_x2 = src->handle->width;
+ if (src_y2 > src->handle->height)
+ src_y2 = src->handle->height;
+
+ if (dst_x2 > dst->handle->width)
+ dst_x2 = dst->handle->width;
+ if (dst_y2 > dst->handle->height)
+ dst_y2 = dst->handle->height;
+
bo_table[0] = info->batch_ibo;
bo_table[1] = src_ib->ibo;
bo_table[2] = dst_ib->ibo;
dst_pitch = dst->handle->stride;
src_pitch = src->handle->stride;
+ /* Blit pitch must be dword-aligned. Otherwise, the hardware appears to
+ * drop the low bits.
+ */
+ if (src_pitch % 4 != 0 || dst_pitch % 4 != 0) {
+ ALOGE("%s, src and dst pitch must be dword aligned", __func__);
+ return;
+ }
+
switch (gralloc_drm_get_bpp(dst->handle->format)) {
case 1:
break;
cmd |= XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB;
break;
default:
- ALOGE("copy with unsupported format");
+ ALOGE("%s, copy with unsupported format", __func__);
return;
}
}
}
- if (batch_reserve(info, 8))
+ unsigned length = (info->gen >= 80) ? 10 : 8;
+ if (batch_reserve(info, length))
return;
- batch_dword(info, cmd);
- batch_dword(info, br13 | dst_pitch);
- batch_dword(info, (y1 << 16) | x1);
- batch_dword(info, (y2 << 16) | x2);
- batch_reloc(info, dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
- batch_dword(info, (y1 << 16) | x1);
- batch_dword(info, src_pitch);
- batch_reloc(info, src, I915_GEM_DOMAIN_RENDER, 0);
+ ALOGD_IF(DEBUG_BLT, "running batch commands, gen=%d tiling: [%d, %d]. dst=[%d, %d, %d, %d], "
+ "src=[%d, %d, %d, %d], pitch=[%d, %d]",
+ info->gen, dst_ib->tiling, src_ib->tiling,
+ dst_x1, dst_y1, dst_x2, dst_y2,
+ src_x1, src_y1, src_x2, src_y2,
+ dst_pitch, src_pitch);
+
+ batch_dword(info, cmd | (length - 2));
+ batch_dword(info, br13 | (uint16_t)dst_pitch);
+ batch_dword(info, (dst_y1 << 16) | dst_x1);
+ batch_dword(info, (dst_y2 << 16) | dst_x2);
+ if (info->gen >= 80) {
+ batch_reloc64(info, dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+ } else {
+ batch_reloc(info, dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
+ }
+ batch_dword(info, (src_y1 << 16) | src_x1);
+ batch_dword(info, (uint16_t)src_pitch);
+ if (info->gen >= 80) {
+ batch_reloc64(info, src, I915_GEM_DOMAIN_RENDER, 0);
+ } else {
+ batch_reloc(info, src, I915_GEM_DOMAIN_RENDER, 0);
+ }
if (info->gen >= 60) {
batch_reserve(info, 4);
max_stride /= 2;
name = "gralloc-fb";
- aligned_width = (aligned_width + 63) & ~63;
+ aligned_width = ALIGN(aligned_width, 64);
flags = BO_ALLOC_FOR_RENDER;
*tiling = I915_TILING_X;
if (handle->usage & GRALLOC_USAGE_HW_TEXTURE) {
name = "gralloc-texture";
/* see 2D texture layout of DRI drivers */
- aligned_width = (aligned_width + 3) & ~3;
- aligned_height = (aligned_height + 1) & ~1;
+ aligned_width = ALIGN(aligned_width, 4);
+ aligned_height = ALIGN(aligned_height, 2);
}
else {
name = "gralloc-buffer";
drm_intel_bo_unmap(ib->ibo);
}
-#include "dri/intel_chipset.h" /* for IS_965() */
+#include "intel_chipset.h" /* for platform detection macros */
static void intel_init_kms_features(struct gralloc_drm_drv_t *drv,
struct gralloc_drm_t *drm)
{
struct intel_info *info = (struct intel_info *) drv;
struct drm_i915_getparam gp;
- int pageflipping, id;
-
- switch (drm->fb_format) {
- case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_RGB_565:
- break;
- default:
- drm->fb_format = HAL_PIXEL_FORMAT_BGRA_8888;
- break;
- }
+ int pageflipping, id, has_blt;
drm->mode_quirk_vmwgfx = 0;
/* why? */
if (drmCommandWriteRead(drm->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)))
id = 0;
- if (IS_965(id)) {
- if (IS_GEN6(id))
+ memset(&gp, 0, sizeof(gp));
+ gp.param = I915_PARAM_HAS_BLT;
+ gp.value = &has_blt;
+ if (drmCommandWriteRead(drm->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)))
+ has_blt = 0;
+ info->exec_blt = has_blt ? I915_EXEC_BLT : 0;
+
+ /* GEN4, G4X, GEN5, GEN6, GEN7 */
+ if ((IS_9XX(id) || IS_G4X(id)) && !IS_GEN3(id)) {
+ if (IS_GEN9(id))
+ info->gen = 90;
+ else if (IS_GEN8(id))
+ info->gen = 80;
+ else if (IS_GEN7(id))
+ info->gen = 70;
+ else if (IS_GEN6(id))
info->gen = 60;
else if (IS_GEN5(id))
info->gen = 50;
int pipe;
pipe = drm_intel_get_pipe_from_crtc_id(info->bufmgr,
- drm->crtc_id);
+ drm->primary->crtc_id);
drm->swap_interval = (pipe >= 0) ? 1 : 0;
drm->vblank_secondary = (pipe > 0);
}
else {
drm->swap_interval = 0;
}
+
+ switch (drm->primary->fb_format) {
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ if (drm->swap_mode == DRM_SWAP_FLIP)
+ break;
+ /* fall through */
+ default:
+ drm->primary->fb_format = HAL_PIXEL_FORMAT_BGRA_8888;
+ break;
+ }
}
static void intel_destroy(struct gralloc_drm_drv_t *drv)
info->base.free = intel_free;
info->base.map = intel_map;
info->base.unmap = intel_unmap;
- info->base.copy = intel_copy;
+ info->base.blit = intel_blit;
+ info->base.resolve_format = intel_resolve_format;
return &info->base;
}