diff options
author | Dave Airlie <airlied@redhat.com> | 2012-07-26 10:37:04 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-09-03 12:28:29 +1000 |
commit | 6705d8237aca90964449e4dbee97b4f62b87c28b (patch) | |
tree | ed10f61099cc352b170c69a2e7f95299e8f905cf /src | |
parent | 69827126abdfa289417b55fe7db8ae0535037185 (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>
Diffstat (limited to 'src')
-rw-r--r-- | src/intel.h | 9 | ||||
-rw-r--r-- | src/intel_display.c | 60 | ||||
-rw-r--r-- | src/intel_driver.c | 60 |
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; |