i965: Allocate tile aligned height
[mesa.git] / src / mesa / drivers / dri / i965 / intel_screen.c
index 5de6f18b84f12d283f7484b8e7f7ef0a96e99f21..96f30168127acac0909714a21bd179c1b30d7376 100644 (file)
@@ -294,10 +294,14 @@ static struct intel_image_format intel_image_formats[] = {
 static const struct {
    uint32_t tiling;
    uint64_t modifier;
+   unsigned height_align;
 } tiling_modifier_map[] = {
-   { .tiling = I915_TILING_NONE, .modifier = DRM_FORMAT_MOD_LINEAR },
-   { .tiling = I915_TILING_X, .modifier = I915_FORMAT_MOD_X_TILED },
-   { .tiling = I915_TILING_Y, .modifier = I915_FORMAT_MOD_Y_TILED },
+   { .tiling = I915_TILING_NONE, .modifier = DRM_FORMAT_MOD_LINEAR,
+     .height_align = 1 },
+   { .tiling = I915_TILING_X, .modifier = I915_FORMAT_MOD_X_TILED,
+     .height_align = 8 },
+   { .tiling = I915_TILING_Y, .modifier = I915_FORMAT_MOD_Y_TILED,
+     .height_align = 32 },
 };
 
 static uint32_t
@@ -326,6 +330,19 @@ tiling_to_modifier(uint32_t tiling)
    unreachable("tiling_to_modifier received unknown tiling mode");
 }
 
+static unsigned
+get_tiled_height(uint64_t modifier, unsigned height)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(tiling_modifier_map); i++) {
+      if (tiling_modifier_map[i].modifier == modifier)
+         return ALIGN(height, tiling_modifier_map[i].height_align);
+   }
+
+   unreachable("get_tiled_height received unknown tiling mode");
+}
+
 static void
 intel_image_warn_if_unaligned(__DRIimage *image, const char *func)
 {
@@ -608,6 +625,8 @@ intel_create_image_common(__DRIscreen *dri_screen,
    __DRIimage *image;
    struct intel_screen *screen = dri_screen->driverPrivate;
    uint32_t tiling;
+   uint64_t modifier = DRM_FORMAT_MOD_INVALID;
+   unsigned tiled_height;
    int cpp;
 
    /* Callers of this may specify a modifier, or a dri usage, but not both. The
@@ -616,29 +635,30 @@ intel_create_image_common(__DRIscreen *dri_screen,
     */
    assert(!(use && count));
 
-   uint64_t modifier = select_best_modifier(&screen->devinfo, modifiers, count);
-   if (modifier == DRM_FORMAT_MOD_INVALID) {
-      /* User requested specific modifiers, none of which work */
-      if (modifiers)
-         return NULL;
-
-      /* Historically, X-tiled was the default, and so lack of modifier means
-       * X-tiled.
-       */
-      tiling = I915_TILING_X;
-   } else {
-      /* select_best_modifier has found a modifier we support */
-      tiling = modifier_to_tiling(modifier);
-   }
-
    if (use & __DRI_IMAGE_USE_CURSOR) {
       if (width != 64 || height != 64)
         return NULL;
-      tiling = I915_TILING_NONE;
+      modifier = DRM_FORMAT_MOD_LINEAR;
    }
 
    if (use & __DRI_IMAGE_USE_LINEAR)
-      tiling = I915_TILING_NONE;
+      modifier = DRM_FORMAT_MOD_LINEAR;
+
+   if (modifier == DRM_FORMAT_MOD_INVALID) {
+      if (modifiers) {
+         /* User requested specific modifiers */
+         modifier = select_best_modifier(&screen->devinfo, modifiers, count);
+         if (modifier == DRM_FORMAT_MOD_INVALID)
+            return NULL;
+      } else {
+         /* Historically, X-tiled was the default, and so lack of modifier means
+          * X-tiled.
+          */
+         modifier = I915_FORMAT_MOD_X_TILED;
+      }
+   }
+   tiling = modifier_to_tiling(modifier);
+   tiled_height = get_tiled_height(modifier, height);
 
    image = intel_allocate_image(screen, format, loaderPrivate);
    if (image == NULL)
@@ -646,7 +666,7 @@ intel_create_image_common(__DRIscreen *dri_screen,
 
    cpp = _mesa_get_format_bytes(image->format);
    image->bo = brw_bo_alloc_tiled(screen->bufmgr, "image",
-                                  width, height, cpp, tiling,
+                                  width, tiled_height, cpp, tiling,
                                   &image->pitch, 0);
    if (image->bo == NULL) {
       free(image);
@@ -815,6 +835,7 @@ intel_create_image_from_fds(__DRIscreen *dri_screen,
    struct intel_screen *screen = dri_screen->driverPrivate;
    struct intel_image_format *f;
    __DRIimage *image;
+   unsigned tiled_height;
    int i, index;
 
    if (fds == NULL || num_fds < 1)
@@ -844,25 +865,37 @@ intel_create_image_from_fds(__DRIscreen *dri_screen,
    image->pitch = strides[0];
 
    image->planar_format = f;
+
+   image->bo = brw_bo_gem_create_from_prime(screen->bufmgr, fds[0]);
+   if (image->bo == NULL) {
+      free(image);
+      return NULL;
+   }
+
+   image->modifier = tiling_to_modifier(image->bo->tiling_mode);
+   tiled_height = get_tiled_height(image->modifier, height);
+
    int size = 0;
    for (i = 0; i < f->nplanes; i++) {
       index = f->planes[i].buffer_index;
       image->offsets[index] = offsets[index];
       image->strides[index] = strides[index];
 
-      const int plane_height = height >> f->planes[i].height_shift;
+      const int plane_height = tiled_height >> f->planes[i].height_shift;
       const int end = offsets[index] + plane_height * strides[index];
       if (size < end)
          size = end;
    }
 
-   image->bo = brw_bo_gem_create_from_prime(screen->bufmgr,
-                                                  fds[0], size);
-   if (image->bo == NULL) {
+   /* Check that the requested image actually fits within the BO. 'size'
+    * is already relative to the offsets, so we don't need to add that. */
+   if (image->bo->size == 0) {
+      image->bo->size = size;
+   } else if (size > image->bo->size) {
+      brw_bo_unreference(image->bo);
       free(image);
       return NULL;
    }
-   image->modifier = tiling_to_modifier(image->bo->tiling_mode);
 
    if (f->nplanes == 1) {
       image->offset = image->offsets[0];
@@ -1169,12 +1202,11 @@ intelCreateBuffer(__DRIscreen *dri_screen,
    mesa_format rgbFormat;
    unsigned num_samples =
       intel_quantize_num_samples(screen, mesaVis->samples);
-   struct gl_framebuffer *fb;
 
    if (isPixmap)
       return false;
 
-   fb = CALLOC_STRUCT(gl_framebuffer);
+   struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer);
    if (!fb)
       return false;
 
@@ -1201,11 +1233,11 @@ intelCreateBuffer(__DRIscreen *dri_screen,
    }
 
    /* setup the hardware-based renderbuffers */
-   rb = intel_create_renderbuffer(rgbFormat, num_samples);
+   rb = intel_create_winsys_renderbuffer(rgbFormat, num_samples);
    _mesa_attach_and_own_rb(fb, BUFFER_FRONT_LEFT, &rb->Base.Base);
 
    if (mesaVis->doubleBufferMode) {
-      rb = intel_create_renderbuffer(rgbFormat, num_samples);
+      rb = intel_create_winsys_renderbuffer(rgbFormat, num_samples);
       _mesa_attach_and_own_rb(fb, BUFFER_BACK_LEFT, &rb->Base.Base);
    }
 
@@ -1409,6 +1441,7 @@ intel_detect_pipelined_register(struct intel_screen *screen,
    struct brw_bo *results, *bo;
    uint32_t *batch;
    uint32_t offset = 0;
+   void *map;
    bool success = false;
 
    /* Create a zero'ed temporary buffer for reading our results */
@@ -1420,10 +1453,11 @@ intel_detect_pipelined_register(struct intel_screen *screen,
    if (bo == NULL)
       goto err_results;
 
-   if (brw_bo_map(NULL, bo, 1))
+   map = brw_bo_map(NULL, bo, MAP_WRITE);
+   if (!map)
       goto err_batch;
 
-   batch = bo->virtual;
+   batch = map;
 
    /* Write the register. */
    *batch++ = MI_LOAD_REGISTER_IMM | (3 - 2);
@@ -1434,7 +1468,7 @@ intel_detect_pipelined_register(struct intel_screen *screen,
    *batch++ = MI_STORE_REGISTER_MEM | (3 - 2);
    *batch++ = reg;
    struct drm_i915_gem_relocation_entry reloc = {
-      .offset = (char *) batch - (char *) bo->virtual,
+      .offset = (char *) batch - (char *) map,
       .delta = offset * sizeof(uint32_t),
       .target_handle = results->gem_handle,
       .read_domains = I915_GEM_DOMAIN_INSTRUCTION,
@@ -1465,7 +1499,7 @@ intel_detect_pipelined_register(struct intel_screen *screen,
    struct drm_i915_gem_execbuffer2 execbuf = {
       .buffers_ptr = (uintptr_t) exec_objects,
       .buffer_count = 2,
-      .batch_len = ALIGN((char *) batch - (char *) bo->virtual, 8),
+      .batch_len = ALIGN((char *) batch - (char *) map, 8),
       .flags = I915_EXEC_RENDER,
    };
 
@@ -1476,8 +1510,9 @@ intel_detect_pipelined_register(struct intel_screen *screen,
    drmIoctl(dri_screen->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
 
    /* Check whether the value got written. */
-   if (brw_bo_map(NULL, results, false) == 0) {
-      success = *((uint32_t *)results->virtual + offset) == expected_value;
+   void *results_map = brw_bo_map(NULL, results, MAP_READ);
+   if (results_map) {
+      success = *((uint32_t *)results_map + offset) == expected_value;
       brw_bo_unmap(results);
    }