OSDN Git Service

Remove radeonsi from the list of radeon_drivers
[android-x86/external-drm_gralloc.git] / gralloc_drm_intel.c
index 519827f..ad4c136 100644 (file)
 #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;
 
@@ -62,6 +64,7 @@ struct intel_info {
        drm_intel_bo *batch_ibo;
        uint32_t *batch, *cur;
        int capacity, size;
+       int exec_blt;
 };
 
 struct intel_buffer {
@@ -113,6 +116,24 @@ batch_reloc(struct intel_info *info, struct gralloc_drm_bo_t *bo,
 }
 
 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;
@@ -130,7 +151,8 @@ batch_flush(struct intel_info *info)
                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;
@@ -190,10 +212,60 @@ batch_init(struct intel_info *info)
        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;
@@ -201,26 +273,36 @@ static void intel_copy(struct gralloc_drm_drv_t *drv,
        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;
@@ -235,6 +317,14 @@ static void intel_copy(struct gralloc_drm_drv_t *drv,
        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;
@@ -246,7 +336,7 @@ static void intel_copy(struct gralloc_drm_drv_t *drv,
                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;
        }
 
@@ -263,17 +353,33 @@ static void intel_copy(struct gralloc_drm_drv_t *drv,
                }
        }
 
-       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);
@@ -324,7 +430,7 @@ static drm_intel_bo *alloc_ibo(struct intel_info *info,
                        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;
@@ -372,8 +478,8 @@ static drm_intel_bo *alloc_ibo(struct intel_info *info,
                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";
@@ -489,22 +595,13 @@ static void intel_unmap(struct gralloc_drm_drv_t *drv,
                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? */
@@ -522,8 +619,22 @@ static void intel_init_kms_features(struct gralloc_drm_drv_t *drv,
        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;
@@ -545,13 +656,26 @@ static void intel_init_kms_features(struct gralloc_drm_drv_t *drv,
                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)
@@ -589,7 +713,8 @@ struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_intel(int fd)
        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;
 }