summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2009-01-07 13:32:57 +1100
committerBen Skeggs <skeggsb@gmail.com>2009-01-07 13:55:48 +1100
commitbbb22bc420d65a367f1ee3cf87773e6b778214fb (patch)
tree52ad6090fe4693492dea78695e52d5d5b5a9ad83
parentb71b21604ce4022108621e3096f74433dcd1fcfd (diff)
nv50/exa: make sure tesla_scratch usage is tracked
Because we were emitting this once during init, and never again, the bufmgr thought the buffer was unused and kicked it out in low memory situtations. This caused everything we keep there to get corrupted, and made the engine very unhappy! This commit causes PrepareComposite() to be repeated after a flush, not sure how much of an impact this'll have (hopefully minimal). After everything's working nicely this may be reworked to have a less severe reemit.
-rw-r--r--src/nv50_exa.c51
-rw-r--r--src/nv_type.h8
2 files changed, 59 insertions, 0 deletions
diff --git a/src/nv50_exa.c b/src/nv50_exa.c
index 5528d7f..71ce07c 100644
--- a/src/nv50_exa.c
+++ b/src/nv50_exa.c
@@ -449,11 +449,21 @@ NV50EXATexture(PixmapPtr ppix, PicturePtr ppict, unsigned unit)
{
NV50EXA_LOCALS(ppix);
struct nouveau_pixmap *tex = nouveau_pixmap(ppix);
+ const unsigned tic_tsc_flags = NOUVEAU_BO_RD | NOUVEAU_BO_VRAM;
+ const unsigned cb_flags = NOUVEAU_BO_WR | NOUVEAU_BO_VRAM;
/*XXX: Scanout buffer not tiled, someone needs to figure it out */
if (!tex->bo->tiled)
NOUVEAU_FALLBACK("pixmap is scanout buffer\n");
+ BEGIN_RING(chan, tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
+ OUT_RELOCh(chan, pNv->tesla_scratch, TIC_OFFSET, tic_tsc_flags);
+ OUT_RELOCl(chan, pNv->tesla_scratch, TIC_OFFSET, tic_tsc_flags);
+ OUT_RING (chan, 0x00000800);
+ BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ OUT_RELOCh(chan, pNv->tesla_scratch, TIC_OFFSET, cb_flags);
+ OUT_RELOCl(chan, pNv->tesla_scratch, TIC_OFFSET, cb_flags);
+ OUT_RING (chan, (CB_TIC << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
OUT_RING (chan, CB_TIC | ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT));
BEGIN_RING(chan, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 8);
@@ -511,6 +521,14 @@ NV50EXATexture(PixmapPtr ppix, PicturePtr ppict, unsigned unit)
OUT_RING (chan, 0x03000000);
OUT_RELOCh(chan, tex->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ BEGIN_RING(chan, tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
+ OUT_RELOCh(chan, pNv->tesla_scratch, TSC_OFFSET, tic_tsc_flags);
+ OUT_RELOCl(chan, pNv->tesla_scratch, TSC_OFFSET, tic_tsc_flags);
+ OUT_RING (chan, 0x00000000);
+ BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ OUT_RELOCh(chan, pNv->tesla_scratch, TSC_OFFSET, cb_flags);
+ OUT_RELOCl(chan, pNv->tesla_scratch, TSC_OFFSET, cb_flags);
+ OUT_RING (chan, (CB_TSC << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
OUT_RING (chan, CB_TSC | ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT));
BEGIN_RING(chan, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 8);
@@ -645,13 +663,28 @@ NV50EXACheckComposite(int op,
return TRUE;
}
+static void
+NV50EXAState3DReEmit(struct nouveau_channel *chan)
+{
+ NVPtr pNv = chan->user_private;
+
+ NV50EXAPrepareComposite(pNv->composite_op, pNv->src_picture,
+ pNv->mask_picture, pNv->dst_picture,
+ pNv->src_pixmap, pNv->mask_pixmap,
+ pNv->dst_pixmap);
+}
+
Bool
NV50EXAPrepareComposite(int op,
PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict,
PixmapPtr pspix, PixmapPtr pmpix, PixmapPtr pdpix)
{
NV50EXA_LOCALS(pspix);
+ const unsigned shd_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
+ /* Make sure there's enough room for 3D state setup, and to
+ * at least fit one Composite() call.
+ */
RING_SPACE(chan, 100);
BEGIN_RING(chan, eng2d, 0x0110, 1);
@@ -663,6 +696,13 @@ NV50EXAPrepareComposite(int op,
NV50EXABlend(pdpix, pdpict, op, pmpict && pmpict->componentAlpha &&
PICT_FORMAT_RGB(pmpict->format));
+ BEGIN_RING(chan, tesla, NV50TCL_VP_ADDRESS_HIGH, 2);
+ OUT_RELOCh(chan, pNv->tesla_scratch, PVP_OFFSET, shd_flags);
+ OUT_RELOCl(chan, pNv->tesla_scratch, PVP_OFFSET, shd_flags);
+ BEGIN_RING(chan, tesla, NV50TCL_FP_ADDRESS_HIGH, 2);
+ OUT_RELOCh(chan, pNv->tesla_scratch, PFP_OFFSET, shd_flags);
+ OUT_RELOCl(chan, pNv->tesla_scratch, PFP_OFFSET, shd_flags);
+
if (pmpict) {
if (!NV50EXATexture(pspix, pspict, 0))
NOUVEAU_FALLBACK("src picture invalid\n");
@@ -704,6 +744,14 @@ NV50EXAPrepareComposite(int op,
BEGIN_RING(chan, tesla, 0x1458, 1);
OUT_RING (chan, 0x203);
+ chan->flush_notify = NV50EXAState3DReEmit;
+ pNv->composite_op = op;
+ pNv->src_pixmap = pspix;
+ pNv->mask_pixmap = pmpix;
+ pNv->dst_pixmap = pdpix;
+ pNv->src_picture = pspict;
+ pNv->mask_picture = pmpict;
+ pNv->dst_picture = pdpict;
return TRUE;
}
@@ -736,6 +784,8 @@ NV50EXAComposite(PixmapPtr pdpix, int sx, int sy, int mx, int my,
float sX0, sX1, sX2, sX3, sY0, sY1, sY2, sY3;
unsigned dX0 = dx, dX1 = dx + w, dY0 = dy, dY1 = dy + h;
+ RING_SPACE(chan, 6 + 7*4);
+
NV50EXATransform(state->unit[0].transform, sx, sy,
state->unit[0].width, state->unit[0].height,
&sX0, &sY0);
@@ -788,5 +838,6 @@ NV50EXADoneComposite(PixmapPtr pdpix)
{
NV50EXA_LOCALS(pdpix);
+ chan->flush_notify = NULL;
}
diff --git a/src/nv_type.h b/src/nv_type.h
index b642a23..0802a34 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -528,6 +528,14 @@ typedef struct _NVRec {
struct nouveau_bo *tesla_scratch;
struct nouveau_bo *shader_mem;
struct nouveau_bo *xv_filtertable_mem;
+
+ int composite_op;
+ PixmapPtr src_pixmap;
+ PixmapPtr mask_pixmap;
+ PixmapPtr dst_pixmap;
+ PicturePtr src_picture;
+ PicturePtr mask_picture;
+ PicturePtr dst_picture;
} NVRec;
#define NVPTR(p) ((NVPtr)((p)->driverPrivate))