mesa: s/CALLOC/calloc/
[mesa.git] / src / mesa / drivers / dri / intel / intel_regions.c
index 67142a131620ddbdb00600fc2ce4f86412e6f834..9bf9c668da50b9f3217feb7d8c8a271c0f0a34b2 100644 (file)
@@ -108,8 +108,9 @@ debug_backtrace(void)
 
 /* XXX: Thread safety?
  */
-GLubyte *
-intel_region_map(struct intel_context *intel, struct intel_region *region)
+void *
+intel_region_map(struct intel_context *intel, struct intel_region *region,
+                 GLbitfield mode)
 {
    /* We have the region->map_refcount controlling mapping of the BO because
     * in software fallbacks we may end up mapping the same buffer multiple
@@ -122,17 +123,26 @@ intel_region_map(struct intel_context *intel, struct intel_region *region)
     * flush is only needed on first map of the buffer.
     */
 
+   if (unlikely(INTEL_DEBUG & DEBUG_PERF)) {
+      if (drm_intel_bo_busy(region->bo)) {
+         perf_debug("Mapping a busy BO, causing a stall on the GPU.\n");
+      }
+   }
+
    _DBG("%s %p\n", __FUNCTION__, region);
-   if (!region->map_refcount++) {
+   if (!region->map_refcount) {
       intel_flush(&intel->ctx);
 
       if (region->tiling != I915_TILING_NONE)
         drm_intel_gem_bo_map_gtt(region->bo);
       else
-        drm_intel_bo_map(region->bo, GL_TRUE);
+        drm_intel_bo_map(region->bo, true);
 
       region->map = region->bo->virtual;
-      ++intel->num_mapped_regions;
+   }
+   if (region->map) {
+      intel->num_mapped_regions++;
+      region->map_refcount++;
    }
 
    return region->map;
@@ -183,7 +193,7 @@ struct intel_region *
 intel_region_alloc(struct intel_screen *screen,
                   uint32_t tiling,
                    GLuint cpp, GLuint width, GLuint height,
-                  GLboolean expect_accelerated_upload)
+                  bool expect_accelerated_upload)
 {
    drm_intel_bo *buffer;
    unsigned long flags = 0;
@@ -209,12 +219,12 @@ intel_region_alloc(struct intel_screen *screen,
    return region;
 }
 
-GLboolean
+bool
 intel_region_flink(struct intel_region *region, uint32_t *name)
 {
    if (region->name == 0) {
       if (drm_intel_bo_flink(region->bo, &region->name))
-        return GL_FALSE;
+        return false;
       
       _mesa_HashInsert(region->screen->named_regions,
                       region->name, region);
@@ -222,7 +232,7 @@ intel_region_flink(struct intel_region *region, uint32_t *name)
 
    *name = region->name;
 
-   return GL_TRUE;
+   return true;
 }
 
 struct intel_region *
@@ -356,7 +366,7 @@ _mesa_copy_rect(GLubyte * dst,
 /* Copy rectangular sub-regions. Need better logic about when to
  * push buffers into AGP - will currently do so whenever possible.
  */
-GLboolean
+bool
 intel_region_copy(struct intel_context *intel,
                   struct intel_region *dst,
                   GLuint dst_offset,
@@ -364,7 +374,7 @@ intel_region_copy(struct intel_context *intel,
                   struct intel_region *src,
                   GLuint src_offset,
                   GLuint srcx, GLuint srcy, GLuint width, GLuint height,
-                 GLboolean flip,
+                 bool flip,
                  GLenum logicop)
 {
    uint32_t src_pitch = src->pitch;
@@ -372,7 +382,7 @@ intel_region_copy(struct intel_context *intel,
    _DBG("%s\n", __FUNCTION__);
 
    if (intel == NULL)
-      return GL_FALSE;
+      return false;
 
    assert(src->cpp == dst->cpp);
 
@@ -386,3 +396,59 @@ intel_region_copy(struct intel_context *intel,
                            srcx, srcy, dstx, dsty, width, height,
                            logicop);
 }
+
+/**
+ * This function computes masks that may be used to select the bits of the X
+ * and Y coordinates that indicate the offset within a tile.  If the region is
+ * untiled, the masks are set to 0.
+ */
+void
+intel_region_get_tile_masks(struct intel_region *region,
+                            uint32_t *mask_x, uint32_t *mask_y)
+{
+   int cpp = region->cpp;
+
+   switch (region->tiling) {
+   default:
+      assert(false);
+   case I915_TILING_NONE:
+      *mask_x = *mask_y = 0;
+      break;
+   case I915_TILING_X:
+      *mask_x = 512 / cpp - 1;
+      *mask_y = 7;
+      break;
+   case I915_TILING_Y:
+      *mask_x = 128 / cpp - 1;
+      *mask_y = 31;
+      break;
+   }
+}
+
+/**
+ * Compute the offset (in bytes) from the start of the region to the given x
+ * and y coordinate.  For tiled regions, caller must ensure that x and y are
+ * multiples of the tile size.
+ */
+uint32_t
+intel_region_get_aligned_offset(struct intel_region *region, uint32_t x,
+                                uint32_t y)
+{
+   int cpp = region->cpp;
+   uint32_t pitch = region->pitch * cpp;
+
+   switch (region->tiling) {
+   default:
+      assert(false);
+   case I915_TILING_NONE:
+      return y * pitch + x * cpp;
+   case I915_TILING_X:
+      assert((x % (512 / cpp)) == 0);
+      assert((y % 8) == 0);
+      return y * pitch + x / (512 / cpp) * 4096;
+   case I915_TILING_Y:
+      assert((x % (128 / cpp)) == 0);
+      assert((y % 32) == 0);
+      return y * pitch + x / (128 / cpp) * 4096;
+   }
+}