summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-07-26 10:37:04 +1000
committerDave Airlie <airlied@redhat.com>2012-09-03 12:28:29 +1000
commit6705d8237aca90964449e4dbee97b4f62b87c28b (patch)
treeed10f61099cc352b170c69a2e7f95299e8f905cf
parent69827126abdfa289417b55fe7db8ae0535037185 (diff)
intel: add pixmap tracking and scanout support. (v2)
This adds support for pixmap tracking and scanout of alternate pixmaps. v2: do dirty updates after uxa block handler, check if kernel can flush vmap for us so we don't have to. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/intel.h9
-rw-r--r--src/intel_display.c60
-rw-r--r--src/intel_driver.c60
3 files changed, 125 insertions, 4 deletions
diff --git a/src/intel.h b/src/intel.h
index 0b57aafa..5b0c5df7 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -80,6 +80,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define MONITOR_EDID_COMPLETE_RAWDATA EDID_COMPLETE_RAWDATA
#endif
+#if XF86_CRTC_VERSION >= 5
+#define INTEL_PIXMAP_SHARING 1
+#endif
+
struct intel_pixmap {
dri_bo *bo;
@@ -347,8 +351,13 @@ typedef struct intel_screen_private {
struct udev_monitor *uevent_monitor;
InputHandlerProc uevent_handler;
#endif
+ Bool has_prime_vmap_flush;
} intel_screen_private;
+#ifndef I915_PARAM_HAS_PRIME_VMAP_FLUSH
+#define I915_PARAM_HAS_PRIME_VMAP_FLUSH 21
+#endif
+
enum {
DEBUG_FLUSH_BATCHES = 0x1,
DEBUG_FLUSH_CACHES = 0x2,
diff --git a/src/intel_display.c b/src/intel_display.c
index 6dfc8e63..4bc8a7b4 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -86,6 +86,8 @@ struct intel_crtc {
uint32_t rotate_fb_id;
xf86CrtcPtr crtc;
struct list link;
+ PixmapPtr scanout_pixmap;
+ uint32_t scanout_fb_id;
};
struct intel_property {
@@ -378,6 +380,7 @@ intel_crtc_apply(xf86CrtcPtr crtc)
ScrnInfoPtr scrn = crtc->scrn;
struct intel_crtc *intel_crtc = crtc->driver_private;
struct intel_mode *mode = intel_crtc->mode;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
uint32_t *output_ids;
int output_count = 0;
@@ -401,13 +404,15 @@ intel_crtc_apply(xf86CrtcPtr crtc)
output_count++;
}
+ if (!intel_crtc->scanout_fb_id) {
#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
- if (!xf86CrtcRotate(crtc, mode, rotation))
- goto done;
+ if (!xf86CrtcRotate(crtc, mode, rotation))
+ goto done;
#else
- if (!xf86CrtcRotate(crtc))
- goto done;
+ if (!xf86CrtcRotate(crtc))
+ goto done;
#endif
+ }
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
@@ -421,6 +426,10 @@ intel_crtc_apply(xf86CrtcPtr crtc)
fb_id = intel_crtc->rotate_fb_id;
x = 0;
y = 0;
+ } else if (intel_crtc->scanout_fb_id && intel_crtc->scanout_pixmap->drawable.width >= crtc->mode.HDisplay && intel_crtc->scanout_pixmap->drawable.height >= crtc->mode.VDisplay) {
+ fb_id = intel_crtc->scanout_fb_id;
+ x = 0;
+ y = 0;
}
ret = drmModeSetCrtc(mode->fd, crtc_id(intel_crtc),
fb_id, x, y, output_ids, output_count,
@@ -684,6 +693,42 @@ intel_crtc_destroy(xf86CrtcPtr crtc)
crtc->driver_private = NULL;
}
+#ifdef INTEL_PIXMAP_SHARING
+static Bool
+intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
+{
+ struct intel_crtc *intel_crtc = crtc->driver_private;
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ dri_bo *bo;
+ int ret;
+
+ if (ppix == intel_crtc->scanout_pixmap)
+ return TRUE;
+
+ if (!ppix) {
+ intel_crtc->scanout_pixmap = NULL;
+ if (intel_crtc->scanout_fb_id) {
+ drmModeRmFB(intel->drmSubFD, intel_crtc->scanout_fb_id);
+ intel_crtc->scanout_fb_id = 0;
+ }
+ return TRUE;
+ }
+
+ bo = intel_get_pixmap_bo(ppix);
+ if (intel->front_buffer) {
+ ErrorF("have front buffer\n");
+ }
+
+ intel_crtc->scanout_pixmap = ppix;
+ ret = drmModeAddFB(intel->drmSubFD, ppix->drawable.width,
+ ppix->drawable.height, ppix->drawable.depth,
+ ppix->drawable.bitsPerPixel, ppix->devKind,
+ bo->handle, &intel_crtc->scanout_fb_id);
+ return TRUE;
+}
+#endif
+
static const xf86CrtcFuncsRec intel_crtc_funcs = {
.dpms = intel_crtc_dpms,
.set_mode_major = intel_crtc_set_mode_major,
@@ -697,6 +742,9 @@ static const xf86CrtcFuncsRec intel_crtc_funcs = {
.shadow_destroy = intel_crtc_shadow_destroy,
.gamma_set = intel_crtc_gamma_set,
.destroy = intel_crtc_destroy,
+#ifdef INTEL_PIXMAP_SHARING
+ .set_scanout_pixmap = intel_set_scanout_pixmap,
+#endif
};
static void
@@ -1662,6 +1710,10 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
for (i = 0; i < mode->mode_res->count_connectors; i++)
intel_output_init(scrn, mode, i);
+#ifdef INTEL_PIXMAP_SHARING
+ xf86ProviderSetup(scrn, NULL, "Intel");
+#endif
+
xf86InitialConfiguration(scrn, TRUE);
mode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
diff --git a/src/intel_driver.c b/src/intel_driver.c
index 76d56d92..65fecfce 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -385,6 +385,11 @@ static Bool has_relaxed_fencing(struct intel_screen_private *intel)
return drm_has_boolean_param(intel, I915_PARAM_HAS_RELAXED_FENCING);
}
+static Bool has_prime_vmap_flush(struct intel_screen_private *intel)
+{
+ return drm_has_boolean_param(intel, I915_PARAM_HAS_PRIME_VMAP_FLUSH);
+}
+
static Bool can_accelerate_blt(struct intel_screen_private *intel)
{
if (INTEL_INFO(intel)->gen == -1)
@@ -545,6 +550,8 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
intel->has_kernel_flush = has_kernel_flush(intel);
+ intel->has_prime_vmap_flush = has_prime_vmap_flush(intel);
+
intel->has_relaxed_fencing =
xf86ReturnOptValBool(intel->Options,
OPTION_RELAXED_FENCING,
@@ -645,6 +652,51 @@ void IntelEmitInvarientState(ScrnInfoPtr scrn)
I915EmitInvarientState(scrn);
}
+#ifdef INTEL_PIXMAP_SHARING
+static Bool
+redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ RegionRec pixregion;
+ int was_blocked;
+
+ PixmapRegionInit(&pixregion, dirty->slave_dst->master_pixmap);
+
+ PixmapSyncDirtyHelper(dirty, &pixregion);
+ intel_batch_submit(scrn);
+ if (!intel->has_prime_vmap_flush) {
+ drm_intel_bo *bo = intel_get_pixmap_bo(dirty->slave_dst->master_pixmap);
+ was_blocked = xf86BlockSIGIO();
+ drm_intel_bo_map(bo, FALSE);
+ drm_intel_bo_unmap(bo);
+ xf86UnblockSIGIO(was_blocked);
+ }
+ DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
+ RegionUninit(&pixregion);
+ return 0;
+}
+
+static void
+intel_dirty_update(ScreenPtr screen)
+{
+ RegionPtr region;
+ PixmapDirtyUpdatePtr ent;
+
+ if (xorg_list_is_empty(&screen->pixmap_dirty_list))
+ return;
+
+ ErrorF("list is not empty\n");
+ xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
+ region = DamageRegion(ent->damage);
+ if (RegionNotEmpty(region)) {
+ redisplay_dirty(screen, ent);
+ DamageEmpty(ent->damage);
+ }
+ }
+}
+#endif
+
static void
I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
{
@@ -661,6 +713,9 @@ I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
intel_uxa_block_handler(intel);
intel_video_block_handler(intel);
+#ifdef INTEL_PIXMAP_SHARING
+ intel_dirty_update(screen);
+#endif
}
static Bool
@@ -906,6 +961,11 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL)
intel->BlockHandler = screen->BlockHandler;
screen->BlockHandler = I830BlockHandler;
+#ifdef INTEL_PIXMAP_SHARING
+ screen->StartPixmapTracking = PixmapStartDirtyTracking;
+ screen->StopPixmapTracking = PixmapStopDirtyTracking;
+#endif
+
if (!AddCallback(&FlushCallback, intel_flush_callback, scrn))
return FALSE;