summaryrefslogtreecommitdiff
path: root/src/i830_memory.c
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-06-06 23:41:23 -0700
committerEric Anholt <eric@anholt.net>2010-06-07 11:15:28 -0700
commitb5c9de10ba3a811f312e622b97ee5e601bd3b74f (patch)
tree075b6547ed465381ee5b19288d352eb7460b03b0 /src/i830_memory.c
parente6acbc763229fd5b5b2cc1d65136404d02ac4655 (diff)
Allocate a correctly sized framebuffer when tiling by using libdrm's support.
When I made libdrm stop overallocating so much memory for the purpose of bo caching, things started scribbling on the bottom of my frontbuffer (and vice versa, leading to GPU hangs). We had the usual mistake of size = tiled_pitch * height instead of size = tiled_pitch * tile_aligned_height.
Diffstat (limited to 'src/i830_memory.c')
-rw-r--r--src/i830_memory.c105
1 files changed, 26 insertions, 79 deletions
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 611b5485..083ddf58 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -163,113 +163,60 @@ i830_check_display_stride(ScrnInfoPtr scrn, int stride, Bool tiling)
return FALSE;
}
-/* Resets the state of the aperture allocator, freeing all memory that had
- * been allocated.
- */
-void i830_reset_allocations(ScrnInfoPtr scrn)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
-
- /* Null out the pointers for all the allocations we just freed. This is
- * kind of gross, but at least it's just one place now.
- */
- drm_intel_bo_unreference(intel->front_buffer);
- intel->front_buffer = NULL;
-}
-
-static Bool IsTileable(ScrnInfoPtr scrn, int pitch)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
-
- if (IS_I965G(intel)) {
- if (pitch / 512 * 512 == pitch && pitch <= KB(128))
- return TRUE;
- else
- return FALSE;
- }
-
- /*
- * Allow tiling for pitches that are a power of 2 multiple of 128 bytes,
- * up to 64 * 128 (= 8192) bytes.
- */
- switch (pitch) {
- case 128:
- case 256:
- if (IS_I945G(intel) || IS_I945GM(intel) || IS_G33CLASS(intel))
- return TRUE;
- else
- return FALSE;
- case 512:
- case KB(1):
- case KB(2):
- case KB(4):
- case KB(8):
- return TRUE;
- default:
- return FALSE;
- }
-}
-
/**
* Allocates a framebuffer for a screen.
*
* Used once for each X screen, so once with RandR 1.2 and twice with classic
* dualhead.
*/
-drm_intel_bo *i830_allocate_framebuffer(ScrnInfoPtr scrn)
+drm_intel_bo *i830_allocate_framebuffer(ScrnInfoPtr scrn,
+ int width, int height, int cpp,
+ unsigned long *out_pitch)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
drm_intel_bo *front_buffer;
- long size, fb_height;
- unsigned int pitch;
- uint32_t tiling_mode, requested_tiling_mode;
- int ret;
-
- /* We'll allocate the fb such that the root window will fit regardless of
- * rotation.
- */
- fb_height = scrn->virtualY;
-
- pitch = scrn->displayWidth * intel->cpp;
- size = ROUND_TO_PAGE(pitch * fb_height);
+ uint32_t tiling_mode;
+ unsigned long pitch;
- if (intel->tiling && IsTileable(scrn, pitch))
+ if (intel->tiling)
tiling_mode = I915_TILING_X;
else
tiling_mode = I915_TILING_NONE;
- if (!i830_check_display_stride(scrn, pitch,
- tiling_mode != I915_TILING_NONE)) {
+ width = i830_pad_drawable_width(width);
+
+ front_buffer = drm_intel_bo_alloc_tiled(intel->bufmgr, "front buffer",
+ width, height, intel->cpp,
+ &tiling_mode, &pitch, 0);
+ if (front_buffer == NULL) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "Front buffer stride %d kB "
- "exceed display limit\n", pitch / 1024);
+ "Failed to allocate framebuffer.\n");
return NULL;
}
- if (tiling_mode != I915_TILING_NONE) {
- /* round to size necessary for the fence register to work */
- size = i830_get_fence_size(intel, size);
- }
-
- front_buffer = drm_intel_bo_alloc(intel->bufmgr, "front buffer",
- size, GTT_PAGE_SIZE);
- if (front_buffer == NULL) {
+ if (!i830_check_display_stride(scrn, pitch,
+ tiling_mode != I915_TILING_NONE)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "Failed to allocate framebuffer.\n");
+ "Front buffer stride %ld kB "
+ "exceeds display limit\n", pitch / 1024);
+ drm_intel_bo_unreference(front_buffer);
return NULL;
}
- requested_tiling_mode = tiling_mode;
- ret = drm_intel_bo_set_tiling(front_buffer, &tiling_mode, pitch);
- if (ret != 0 || tiling_mode != requested_tiling_mode) {
+ if (intel->tiling && tiling_mode != I915_TILING_X) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "Failed to set tiling on frontbuffer: %s\n",
- ret == 0 ? "rejected by kernel" : strerror(-ret));
+ "Failed to set tiling on frontbuffer.\n");
}
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "Allocated new frame buffer %dx%d stride %ld, %s\n",
+ width, height, pitch,
+ tiling_mode == I915_TILING_NONE ? "untiled" : "tiled");
+
drm_intel_bo_disable_reuse(front_buffer);
i830_set_gem_max_sizes(scrn);
+ *out_pitch = pitch;
return front_buffer;
}