summaryrefslogtreecommitdiff
path: root/src/intel_uxa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/intel_uxa.c')
-rw-r--r--src/intel_uxa.c217
1 files changed, 203 insertions, 14 deletions
diff --git a/src/intel_uxa.c b/src/intel_uxa.c
index 1681b708..706d6341 100644
--- a/src/intel_uxa.c
+++ b/src/intel_uxa.c
@@ -688,9 +688,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
@@ -892,14 +889,197 @@ 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_pixmap->devPrivate.ptr;
+ int src_pitch = intel->shadow_pixmap->devKind;
+ 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 (intel->shadow_buffer) {
+ bo = intel->shadow_buffer;
+ offset = box->x1 | box->y1 << 16;
+ pitch = intel->shadow_pixmap->devKind;
+ } 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;
+
+ if (IS_I8XX(intel))
+ pixmap = screen->GetScreenPixmap(screen);
+ else
+ pixmap = intel->shadow_pixmap;
+
+ if (intel->shadow_damage) {
+ DamageUnregister(&pixmap->drawable, intel->shadow_damage);
+ DamageDestroy(intel->shadow_damage);
+ }
+
+ 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 {
+ if (intel->shadow_pixmap)
+ fbDestroyPixmap(intel->shadow_pixmap);
+
+ pixmap = fbCreatePixmap(screen,
+ scrn->virtualX,
+ scrn->virtualY,
+ scrn->depth,
+ 0);
+
+ screen->SetScreenPixmap(pixmap);
+ stride = pixmap->devKind;
+ }
+
+ intel->shadow_pixmap = pixmap;
+ 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;
}
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);
}
}
@@ -1045,17 +1225,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;
}
}
@@ -1131,8 +1321,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;
@@ -1206,6 +1394,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;
}