summaryrefslogtreecommitdiff
path: root/src/intel_uxa.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-08-25 12:56:43 +0100
committerOwain G. Ainsworth <oga@openbsd.org>2010-09-12 04:52:11 +0100
commit56f3afcc7b7b11b7eeabe197176a74892449221d (patch)
tree630c02bdcb8958e9f7b09e66603429342a561f4d /src/intel_uxa.c
parentde486ee8e4295d5d827692b26c5c12b7a26c9d01 (diff)
Enable a shadow buffer and disable GPU acceleration.
An attempt to workaround the incoherency in gen2 chipsets, we avoid using dynamic reallocation as much as possible. The first step is to disable allocation of pixmaps using GEM and simply create them in system memory without a backing buffer object. This forces all rendering to use S/W fallbacks. The second step is to allocate a shadow front buffer and assign that to the Screen pixmap. This ensure that the front buffer remains in the GTT and pinned for scanout. The shadow buffer will be rendered to in the normal fashion via the Screen pixmap, and be marked dirty. In the block handler, the dirty shadow buffer is then blitted (using the GPU) over the front buffer. This should completely avoid having to move pages around in the GTT and avoid incurring the wrath of those early chipsets. Secondly, performance should be reasonable as we avoid the ping-pong caused by the small aperture and weak GPU forcing software fallbacks. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Owain G. Ainsworth <oga@openbsd.org> (cherry-picked from commit 2b96c18165d713cd6781dbf217ec33e11cc961bc) Also pulled in the following commit: commit ae160d7fbfc79e78dad8702efcc55d9c0c25ff67 Author: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri Sep 10 13:19:12 2010 +0100 shadow: Simply modify the Screen pixmap header This is a slightly less risky strategy than having to remember to update all pointers to the old Screen pixmap. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/intel_uxa.c')
-rw-r--r--src/intel_uxa.c216
1 files changed, 202 insertions, 14 deletions
diff --git a/src/intel_uxa.c b/src/intel_uxa.c
index 4f7ab3f9..aed5d548 100644
--- a/src/intel_uxa.c
+++ b/src/intel_uxa.c
@@ -675,9 +675,6 @@ static void intel_uxa_finish_access(PixmapPtr pixmap)
struct intel_pixmap *priv = intel_get_pixmap_private(pixmap);
dri_bo *bo = priv->bo;
- if (bo == intel->front_buffer)
- intel->need_sync = TRUE;
-
if (priv->tiling || bo->size <= intel->max_gtt_map_size)
drm_intel_gem_bo_unmap_gtt(bo);
else
@@ -879,14 +876,196 @@ static Bool intel_uxa_get_image(PixmapPtr pixmap,
scratch->drawable.pScreen->DestroyPixmap(scratch);
return ret;
+}
+
+static dri_bo *
+intel_shadow_create_bo(intel_screen_private *intel,
+ int16_t x1, int16_t y1,
+ int16_t x2, int16_t y2,
+ int *pitch)
+{
+ int w = x2 - x1, h = y2 - y1;
+ int size = h * w * intel->cpp;
+ dri_bo *bo;
+
+ bo = drm_intel_bo_alloc(intel->bufmgr, "shadow", size, 0);
+ if (bo && drm_intel_gem_bo_map_gtt(bo) == 0) {
+ char *dst = bo->virtual;
+ char *src = intel->shadow_buffer;
+ int src_pitch = intel->shadow_stride;
+ int row_length = w * intel->cpp;
+ int num_rows = h;
+ src += y1 * src_pitch + x1 * intel->cpp;
+ do {
+ memcpy (dst, src, row_length);
+ src += src_pitch;
+ dst += row_length;
+ } while (--num_rows);
+ drm_intel_gem_bo_unmap_gtt(bo);
+ }
+
+ *pitch = w * intel->cpp;
+ return bo;
+}
+
+static void
+intel_shadow_blt(intel_screen_private *intel)
+{
+ ScrnInfoPtr scrn = intel->scrn;
+ unsigned int dst_pitch;
+ uint32_t blt, br13;
+ RegionPtr region;
+ BoxPtr box;
+ int n;
+
+ dst_pitch = intel->front_pitch;
+
+ blt = XY_SRC_COPY_BLT_CMD;
+ if (intel->cpp == 4)
+ blt |= (XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+
+ if (IS_I965G(intel)) {
+ if (intel->front_tiling) {
+ dst_pitch >>= 2;
+ blt |= XY_SRC_COPY_BLT_DST_TILED;
+ }
+ }
+
+ br13 = ROP_S << 16 | dst_pitch;
+ switch (intel->cpp) {
+ default:
+ case 4: br13 |= 1 << 25; /* RGB8888 */
+ case 2: br13 |= 1 << 24; /* RGB565 */
+ case 1: break;
+ }
+
+ region = DamageRegion(intel->shadow_damage);
+ box = REGION_RECTS(region);
+ n = REGION_NUM_RECTS(region);
+ while (n--) {
+ int pitch;
+ dri_bo *bo;
+ int offset;
+
+ if (IS_I8XX(intel)) {
+ bo = intel->shadow_buffer;
+ offset = box->x1 | box->y1 << 16;
+ pitch = intel->shadow_stride;
+ } else {
+ bo = intel_shadow_create_bo(intel,
+ box->x1, box->y1,
+ box->x2, box->y2,
+ &pitch);
+ if (bo == NULL)
+ return;
+
+ offset = 0;
+ }
+
+ BEGIN_BATCH(8);
+ OUT_BATCH(blt);
+ OUT_BATCH(br13);
+ OUT_BATCH(box->y1 << 16 | box->x1);
+ OUT_BATCH(box->y2 << 16 | box->x2);
+ OUT_RELOC_FENCED(intel->front_buffer,
+ I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER,
+ 0);
+ OUT_BATCH(offset);
+ OUT_BATCH(pitch);
+ OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, 0, 0);
+
+ ADVANCE_BATCH();
+
+ if (bo != intel->shadow_buffer)
+ drm_intel_bo_unreference(bo);
+ box++;
+ }
+}
+
+static void intel_shadow_create(struct intel_screen_private *intel)
+{
+ ScrnInfoPtr scrn = intel->scrn;
+ ScreenPtr screen = scrn->pScreen;
+ PixmapPtr pixmap;
+ int stride;
+
+ pixmap = screen->GetScreenPixmap(screen);
+ if (IS_I8XX(intel)) {
+ dri_bo *bo;
+ int size;
+
+ /* Reduce the incoherency worries for gen2
+ * by only allocating a static shadow, at about 2-3x
+ * performance cost for forcing rendering to uncached memory.
+ */
+ if (intel->shadow_buffer) {
+ drm_intel_gem_bo_unmap_gtt(intel->shadow_buffer);
+ drm_intel_bo_unreference(intel->shadow_buffer);
+ intel->shadow_buffer = NULL;
+ }
+
+ stride = ALIGN(scrn->virtualX * intel->cpp, 4);
+ size = stride * scrn->virtualY;
+ bo = drm_intel_bo_alloc(intel->bufmgr,
+ "shadow", size,
+ 0);
+ if (bo && drm_intel_gem_bo_map_gtt(bo) == 0) {
+ screen->ModifyPixmapHeader(pixmap,
+ scrn->virtualX,
+ scrn->virtualY,
+ -1, -1,
+ stride,
+ bo->virtual);
+ intel->shadow_buffer = bo;
+ }
+ } else {
+ void *buffer;
+
+ stride = intel->cpp*scrn->virtualX;
+ buffer = malloc(stride * scrn->virtualY);
+
+ if (buffer && screen->ModifyPixmapHeader(pixmap,
+ scrn->virtualX,
+ scrn->virtualY,
+ -1, -1,
+ stride,
+ buffer)) {
+ if (intel->shadow_buffer)
+ free(intel->shadow_buffer);
+
+ intel->shadow_buffer = buffer;
+ } else
+ stride = intel->shadow_stride;
+ }
+ if (!intel->shadow_damage) {
+ intel->shadow_damage = DamageCreate(NULL, NULL,
+ DamageReportNone,
+ TRUE,
+ screen,
+ intel);
+ DamageRegister(&pixmap->drawable, intel->shadow_damage);
+ DamageSetReportAfterOp(intel->shadow_damage, TRUE);
+ }
+
+ scrn->displayWidth = stride / intel->cpp;
+ intel->shadow_stride = stride;
}
void intel_uxa_block_handler(intel_screen_private *intel)
{
- if (intel->need_sync) {
- dri_bo_wait_rendering(intel->front_buffer);
- intel->need_sync = FALSE;
+ if (intel->shadow_damage &&
+ pixman_region_not_empty(DamageRegion(intel->shadow_damage))) {
+ intel_shadow_blt(intel);
+ /* Emit a flush of the rendering cache, or on the 965
+ * and beyond rendering results may not hit the
+ * framebuffer until significantly later.
+ */
+ intel_batch_submit(intel->scrn, TRUE);
+
+ DamageEmpty(intel->shadow_damage);
}
}
@@ -1034,17 +1213,27 @@ static Bool intel_uxa_destroy_pixmap(PixmapPtr pixmap)
return TRUE;
}
-
void intel_uxa_create_screen_resources(ScreenPtr screen)
{
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- dri_bo *bo = intel->front_buffer;
- if (bo != NULL) {
- PixmapPtr pixmap = screen->GetScreenPixmap(screen);
- intel_set_pixmap_bo(pixmap, bo);
- intel_get_pixmap_private(pixmap)->busy = 1;
+ if (intel->use_shadow) {
+ intel_shadow_create(intel);
+ } else {
+ dri_bo *bo = intel->front_buffer;
+ if (bo != NULL) {
+ PixmapPtr pixmap = screen->GetScreenPixmap(screen);
+ intel_set_pixmap_bo(pixmap, bo);
+ intel_get_pixmap_private(pixmap)->busy = 1;
+ screen->ModifyPixmapHeader(pixmap,
+ scrn->virtualX,
+ scrn->virtualY,
+ -1, -1,
+ intel->front_pitch,
+ NULL);
+ }
+ scrn->displayWidth = intel->front_pitch / intel->cpp;
}
}
@@ -1120,8 +1309,6 @@ Bool intel_uxa_init(ScreenPtr screen)
memset(intel->uxa_driver, 0, sizeof(*intel->uxa_driver));
- intel->force_fallback = FALSE;
-
intel->bufferOffset = 0;
intel->uxa_driver->uxa_major = 1;
intel->uxa_driver->uxa_minor = 0;
@@ -1195,6 +1382,7 @@ Bool intel_uxa_init(ScreenPtr screen)
}
uxa_set_fallback_debug(screen, intel->fallback_debug);
+ uxa_set_force_fallback(screen, intel->force_fallback);
return TRUE;
}