diff options
-rw-r--r-- | src/common.h | 7 | ||||
-rw-r--r-- | src/intel_dri.c | 225 | ||||
-rw-r--r-- | src/intel_driver.c | 2 | ||||
-rw-r--r-- | src/intel_uxa.c | 20 | ||||
-rw-r--r-- | uxa/uxa-glyphs.c | 7 |
5 files changed, 198 insertions, 63 deletions
diff --git a/src/common.h b/src/common.h index f7e4923e..6f23cdd8 100644 --- a/src/common.h +++ b/src/common.h @@ -182,9 +182,10 @@ intel_host_bridge (void); * Compare to CREATE_PIXMAP_USAGE_* in the server. */ enum { - INTEL_CREATE_PIXMAP_TILING_X = 0x10000000, - INTEL_CREATE_PIXMAP_TILING_Y, - INTEL_CREATE_PIXMAP_TILING_NONE, + INTEL_CREATE_PIXMAP_TILING_X = 0x10000000, + INTEL_CREATE_PIXMAP_TILING_Y = 0x20000000, + INTEL_CREATE_PIXMAP_TILING_NONE = 0x40000000, + INTEL_CREATE_PIXMAP_DRI2 = 0x80000000, }; #endif /* _INTEL_COMMON_H_ */ diff --git a/src/intel_dri.c b/src/intel_dri.c index 98042722..1527dba1 100644 --- a/src/intel_dri.c +++ b/src/intel_dri.c @@ -58,6 +58,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "windowstr.h" #include "shadow.h" +#include "xaarop.h" + #include "intel.h" #include "i830_reg.h" @@ -68,11 +70,101 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. typedef struct { int refcnt; PixmapPtr pixmap; + DrawablePtr drawable; unsigned int attachment; } I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr; -#if DRI2INFOREC_VERSION < 2 +static PixmapPtr get_front_buffer(DrawablePtr drawable, DrawablePtr *ret) +{ + ScreenPtr screen = drawable->pScreen; + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + intel_screen_private *intel = intel_get_screen_private(scrn); + PixmapPtr pixmap; + + pixmap = get_drawable_pixmap(drawable); + if (pixmap_is_scanout(pixmap)) { + pixmap = fbCreatePixmap(screen, 0, 0, drawable->depth, 0); + if (pixmap) { + screen->ModifyPixmapHeader(pixmap, + drawable->width, + drawable->height, + 0, 0, + intel->front_pitch, + NULL); + intel_set_pixmap_bo(pixmap, intel->front_buffer); + } + } else if (intel_get_pixmap_bo(pixmap)) { + pixmap->refcnt++; + *ret = drawable; + } else + pixmap = NULL; + return pixmap; +} +static PixmapPtr fixup_shadow(DrawablePtr drawable, PixmapPtr pixmap) +{ + ScreenPtr screen = drawable->pScreen; + PixmapPtr old = get_drawable_pixmap(drawable); + struct intel_pixmap *priv = intel_get_pixmap_private(pixmap); + GCPtr gc; + + /* With an active shadow buffer, 2D pixmaps are created in + * system memory and GPU acceleration of 2D render operations + * is *disabled*. As DRI is still enabled, we create hardware + * buffers for the clients, and need to mix this with the + * 2D rendering. So we replace the system pixmap with a GTT + * mapping (with the kernel enforcing coherency between + * CPU and GPU) for 2D and provide the bo so that clients + * can write directly to it (or read from it in the case + * of TextureFromPixmap) using the GPU. + * + * So for a compositor with a GL backend (i.e. compiz) we have + * smooth wobbly windows but incur the cost of uncached 2D rendering, + * however 3D applications (games and clutter) are still fully + * accelerated. + */ + + drm_intel_gem_bo_map_gtt(priv->bo); + + /* Copy the current contents of the pixmap to the bo. */ + gc = GetScratchGC(drawable->depth, screen); + if (gc) { + ValidateGC(&pixmap->drawable, gc); + + screen->ModifyPixmapHeader(pixmap, + drawable->width, + drawable->height, + 0, 0, + priv->stride, + priv->bo->virtual); + + gc->ops->CopyArea(drawable, &pixmap->drawable, + gc, + 0, 0, + drawable->width, + drawable->height, + 0, 0); + FreeScratchGC(gc); + } + + intel_set_pixmap_private(pixmap, NULL); + screen->DestroyPixmap(pixmap); + + /* Redirect 2D rendering to the uncached GTT map of the bo */ + screen->ModifyPixmapHeader(old, + drawable->width, + drawable->height, + 0, 0, + priv->stride, + priv->bo->virtual); + + /* And redirect the pixmap to the new bo (for 3D). */ + intel_set_pixmap_private(old, priv); + old->refcnt++; + return old; +} + +#if DRI2INFOREC_VERSION < 2 static DRI2BufferPtr I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments, int count) @@ -85,6 +177,7 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments, int i; I830DRI2BufferPrivatePtr privates; PixmapPtr pixmap, pDepthPixmap; + DrawablePtr target; buffers = calloc(count, sizeof *buffers); if (buffers == NULL) @@ -97,39 +190,49 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments, pDepthPixmap = NULL; for (i = 0; i < count; i++) { + target = NULL; + pixmap = NULL; if (attachments[i] == DRI2BufferFrontLeft) { - pixmap = get_drawable_pixmap(drawable); - pixmap->refcnt++; + pixmap = get_front_buffer(drawable, &target); } else if (attachments[i] == DRI2BufferStencil && pDepthPixmap) { pixmap = pDepthPixmap; pixmap->refcnt++; - } else { - unsigned int hint = 0; - - switch (attachments[i]) { - case DRI2BufferDepth: - if (SUPPORTS_YTILING(intel)) - hint = INTEL_CREATE_PIXMAP_TILING_Y; - else - hint = INTEL_CREATE_PIXMAP_TILING_X; - break; - case DRI2BufferFakeFrontLeft: - case DRI2BufferFakeFrontRight: - case DRI2BufferBackLeft: - case DRI2BufferBackRight: - hint = INTEL_CREATE_PIXMAP_TILING_X; - break; + } + if (pixmap == NULL) { + unsigned int hint = INTEL_CREATE_PIXMAP_DRI2; + + if (intel->tiling) { + switch (attachments[i]) { + case DRI2BufferDepth: + if (SUPPORTS_YTILING(intel)) + hint |= INTEL_CREATE_PIXMAP_TILING_Y; + else + hint |= INTEL_CREATE_PIXMAP_TILING_X; + break; + case DRI2BufferFakeFrontLeft: + case DRI2BufferFakeFrontRight: + case DRI2BufferBackLeft: + case DRI2BufferBackRight: + hint |= INTEL_CREATE_PIXMAP_TILING_X; + break; + } } - if (!intel->tiling) - hint = 0; - pixmap = screen->CreatePixmap(screen, drawable->width, drawable->height, drawable->depth, hint); + if (pixmap == NULL || + intel_get_pixmap_bo(pixmap) == NULL) + { + if (pixmap) + screen->DestroyPixmap(pixmap); + goto unwind; + } + if (attachment == DRI2BufferFrontLeft) + pixmap = fixup_shadow(drawable, pixmap); } if (attachments[i] == DRI2BufferDepth) @@ -144,6 +247,8 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments, privates[i].pixmap = pixmap; privates[i].attachment = attachments[i]; + privates[i].drawable = target ? target : &pixmap->drawable; + bo = intel_get_pixmap_bo(pixmap); if (bo == NULL || dri_bo_flink(bo, &buffers[i].name) != 0) { /* failed to name buffer */ @@ -193,6 +298,7 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, dri_bo *bo; I830DRI2BufferPrivatePtr privates; PixmapPtr pixmap; + DrawablePtr target = NULL; buffer = calloc(1, sizeof *buffer); if (buffer == NULL) @@ -203,30 +309,25 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, return NULL; } - if (attachment == DRI2BufferFrontLeft) { - pixmap = get_drawable_pixmap(drawable); - pixmap->refcnt++; - } else { - unsigned int hint = 0; - - switch (attachment) { - case DRI2BufferDepth: - case DRI2BufferDepthStencil: - if (SUPPORTS_YTILING(intel)) - hint = INTEL_CREATE_PIXMAP_TILING_Y; - else - hint = INTEL_CREATE_PIXMAP_TILING_X; - break; - case DRI2BufferFakeFrontLeft: - case DRI2BufferFakeFrontRight: - case DRI2BufferBackLeft: - case DRI2BufferBackRight: - hint = INTEL_CREATE_PIXMAP_TILING_X; - break; - } + pixmap = NULL; + if (attachment == DRI2BufferFrontLeft) + pixmap = get_front_buffer(drawable, &target); + if (pixmap == NULL) { + unsigned int hint = INTEL_CREATE_PIXMAP_DRI2; - if (!intel->tiling) - hint = 0; + if (intel->tiling) { + switch (attachment) { + case DRI2BufferDepth: + case DRI2BufferDepthStencil: + if (SUPPORTS_YTILING(intel)) { + hint |= INTEL_CREATE_PIXMAP_TILING_Y; + break; + } + default: + hint |= INTEL_CREATE_PIXMAP_TILING_X; + break; + } + } pixmap = screen->CreatePixmap(screen, drawable->width, @@ -234,12 +335,16 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, (format != 0) ? format : drawable->depth, hint); - if (pixmap == NULL) { + if (pixmap == NULL || intel_get_pixmap_bo(pixmap) == NULL) { + if (pixmap) + screen->DestroyPixmap(pixmap); free(privates); free(buffer); return NULL; } + if (attachment == DRI2BufferFrontLeft) + pixmap = fixup_shadow(drawable, pixmap); } buffer->attachment = attachment; @@ -251,6 +356,7 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment, privates->refcnt = 1; privates->pixmap = pixmap; privates->attachment = attachment; + privates->drawable = target ? target : &pixmap->drawable; bo = intel_get_pixmap_bo(pixmap); if (bo == NULL || dri_bo_flink(bo, &buffer->name) != 0) { @@ -298,11 +404,10 @@ I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion, ScreenPtr screen = drawable->pScreen; ScrnInfoPtr scrn = xf86Screens[screen->myNum]; intel_screen_private *intel = intel_get_screen_private(scrn); - DrawablePtr src = (srcPrivate->attachment == DRI2BufferFrontLeft) - ? drawable : &srcPrivate->pixmap->drawable; - DrawablePtr dst = (dstPrivate->attachment == DRI2BufferFrontLeft) - ? drawable : &dstPrivate->pixmap->drawable; + DrawablePtr src = srcPrivate->drawable; + DrawablePtr dst = dstPrivate->drawable; RegionPtr pCopyClip; + PixmapPtr src_pixmap, dst_pixmap; GCPtr gc; gc = GetScratchGC(dst->depth, screen); @@ -399,12 +504,22 @@ I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion, * that will happen before the client tries to render * again. */ - (*gc->ops->CopyArea) (src, dst, - gc, - 0, 0, - drawable->width, drawable->height, - 0, 0); + /* Re-enable 2D acceleration... */ + src_pixmap = get_drawable_pixmap(src); + src_pixmap->devPrivate.ptr = NULL; + + dst_pixmap = get_drawable_pixmap(dst); + dst_pixmap->devPrivate.ptr = NULL; + + gc->ops->CopyArea(src, dst, gc, + 0, 0, + drawable->width, drawable->height, + 0, 0); FreeScratchGC(gc); + + /* and restore 2D/3D coherency */ + src_pixmap->devPrivate.ptr = intel_get_pixmap_bo(src_pixmap)->virtual; + dst_pixmap->devPrivate.ptr = intel_get_pixmap_bo(dst_pixmap)->virtual; } #if DRI2INFOREC_VERSION >= 4 diff --git a/src/intel_driver.c b/src/intel_driver.c index 43916726..2cd50a10 100644 --- a/src/intel_driver.c +++ b/src/intel_driver.c @@ -575,7 +575,7 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags) if (xf86IsOptionSet(intel->Options, OPTION_SHADOW)) { if (xf86ReturnOptValBool(intel->Options, OPTION_SHADOW, FALSE)) - intel->force_fallback = intel->use_shadow = TRUE; + intel->use_shadow = TRUE; } if (intel->use_shadow) { diff --git a/src/intel_uxa.c b/src/intel_uxa.c index 067994e7..d964a951 100644 --- a/src/intel_uxa.c +++ b/src/intel_uxa.c @@ -731,6 +731,9 @@ static Bool intel_uxa_pixmap_put_image(PixmapPtr pixmap, int stride = intel_pixmap_pitch(pixmap); int ret = FALSE; + if (priv == NULL || priv->bo == NULL) + return FALSE; + if (src_pitch == stride && w == pixmap->drawable.width && priv->tiling == I915_TILING_NONE) { ret = drm_intel_bo_subdata(priv->bo, y * stride, stride * h, src) == 0; } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) { @@ -890,6 +893,11 @@ static Bool intel_uxa_get_image(PixmapPtr pixmap, if (!scratch) return FALSE; + if (!intel_get_pixmap_bo(scratch)) { + screen->DestroyPixmap(scratch); + return FALSE; + } + gc = GetScratchGC(pixmap->drawable.depth, screen); if (!gc) { screen->DestroyPixmap(scratch); @@ -935,7 +943,10 @@ void intel_uxa_block_handler(intel_screen_private *intel) static Bool intel_uxa_pixmap_is_offscreen(PixmapPtr pixmap) { - return intel_get_pixmap_private(pixmap) != NULL; + if (pixmap->devPrivate.ptr) + return FALSE; + + return intel_get_pixmap_bo(pixmap) != NULL; } static PixmapPtr @@ -952,6 +963,9 @@ intel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (depth == 1 || intel->force_fallback) return fbCreatePixmap(screen, w, h, depth, usage); + if (intel->use_shadow && (usage & INTEL_CREATE_PIXMAP_DRI2) == 0) + return fbCreatePixmap(screen, w, h, depth, usage); + if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32) return fbCreatePixmap(screen, w, h, depth, usage); @@ -967,9 +981,9 @@ intel_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, * to be effectively tiled. */ tiling = I915_TILING_X; - if (usage == INTEL_CREATE_PIXMAP_TILING_Y) + if (usage & INTEL_CREATE_PIXMAP_TILING_Y) tiling = I915_TILING_Y; - if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage == INTEL_CREATE_PIXMAP_TILING_NONE) + if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage & INTEL_CREATE_PIXMAP_TILING_NONE) tiling = I915_TILING_NONE; /* if tiling is off force to none */ diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c index ad4f3877..420e8915 100644 --- a/uxa/uxa-glyphs.c +++ b/uxa/uxa-glyphs.c @@ -164,7 +164,12 @@ static Bool uxa_realize_glyph_caches(ScreenPtr pScreen) INTEL_CREATE_PIXMAP_TILING_X); if (!pixmap) goto bail; - assert (uxa_pixmap_is_offscreen(pixmap)); + if (!uxa_pixmap_is_offscreen(pixmap)) { + /* Presume shadow is in-effect */ + pScreen->DestroyPixmap(pixmap); + uxa_unrealize_glyph_caches(pScreen); + return TRUE; + } component_alpha = NeedsComponent(pPictFormat->format); picture = CreatePicture(0, &pixmap->drawable, pPictFormat, |