summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common.h7
-rw-r--r--src/intel_dri.c225
-rw-r--r--src/intel_driver.c2
-rw-r--r--src/intel_uxa.c20
-rw-r--r--uxa/uxa-glyphs.c7
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,