[Nouveau] [PATCH 3/3] nv50: support frontbuffer fallbacks
Maarten Maathuis
madman2003 at gmail.com
Thu Feb 12 14:56:32 PST 2009
---
src/nouveau_exa.c | 36 +++++++++++++++
src/nv50_shadow_damage.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++
src/nv_proto.h | 1 +
3 files changed, 145 insertions(+), 0 deletions(-)
diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index c4cafb0..b6ae8ca 100644
--- a/src/nouveau_exa.c
+++ b/src/nouveau_exa.c
@@ -308,6 +308,36 @@ nouveau_exa_pixmap_unmap(PixmapPtr ppix)
}
static Bool
+nouveau_exa_prepare_access(PixmapPtr ppix, int index)
+{
+ ScreenPtr pScreen = ppix->drawable.pScreen;
+ NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]);
+
+ if (ppix == pScreen->GetScreenPixmap(pScreen)) {
+ nouveau_bo_map(pNv->scanout, NOUVEAU_BO_RDWR);
+ ppix->devPrivate.ptr = pNv->scanout->map;
+ } else if (nouveau_exa_pixmap_is_tiled(ppix)) {
+ return false; /* force migration */
+ }
+
+ return true;
+}
+
+static void
+nouveau_exa_finish_access(PixmapPtr ppix, int index)
+{
+ ScreenPtr pScreen = ppix->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
+
+ if (ppix == pScreen->GetScreenPixmap(pScreen)) {
+ ppix->devPrivate.ptr = NULL;
+ nouveau_bo_unmap(pNv->scanout);
+ nv50_shadow_damage_frontbuffer_fallback(pScrn);
+ }
+}
+
+static Bool
nouveau_exa_download_from_screen(PixmapPtr pspix, int x, int y, int w, int h,
char *dst, int dst_pitch)
{
@@ -447,6 +477,12 @@ nouveau_exa_init(ScreenPtr pScreen)
exa->maxY = 2048;
}
+ /* Needed for frontbuffer fallbacks (to ensure it accesses the linear fb). */
+ if (pNv->Architecture >= NV_ARCH_50) {
+ exa->PrepareAccess = nouveau_exa_prepare_access;
+ exa->FinishAccess = nouveau_exa_finish_access;
+ }
+
exa->MarkSync = nouveau_exa_mark_sync;
exa->WaitMarker = nouveau_exa_wait_marker;
diff --git a/src/nv50_shadow_damage.c b/src/nv50_shadow_damage.c
index 9d1a8cb..a48cfb2 100644
--- a/src/nv50_shadow_damage.c
+++ b/src/nv50_shadow_damage.c
@@ -29,6 +29,7 @@
*/
#include "nv_include.h"
+#include "damagestr.h"
/* When driver allocated pixmaps are used we can easily fold this back into exa code. */
static void nv50_shadow_damage_blit(PixmapPtr ppix, RegionPtr pRegion)
@@ -115,6 +116,91 @@ static void nv50_shadow_damage_blit(PixmapPtr ppix, RegionPtr pRegion)
}
}
+/* For frontbuffer fallbacks. */
+static void nv50_shadow_damage_blit_back(PixmapPtr ppix, RegionPtr pRegion)
+{
+ ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
+ struct nouveau_channel *chan = pNv->chan;
+ struct nouveau_grobj *eng2d = pNv->Nv2D;
+ uint32_t fmt;
+ BoxPtr pbox;
+ int nbox;
+
+ pbox = REGION_RECTS(pRegion);
+ nbox = REGION_NUM_RECTS(pRegion);
+ if (!nbox)
+ return;
+
+ /* flush_notify is not needed, we check for all the ring space in advance. */
+ WAIT_RING (chan, 26 + nbox * 13);
+
+ switch (ppix->drawable.depth) {
+ case 8 : fmt = NV50_2D_SRC_FORMAT_8BPP; break;
+ case 15: fmt = NV50_2D_SRC_FORMAT_15BPP; break;
+ case 16: fmt = NV50_2D_SRC_FORMAT_16BPP; break;
+ case 24: fmt = NV50_2D_SRC_FORMAT_24BPP; break;
+ case 32: fmt = NV50_2D_SRC_FORMAT_32BPP; break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unknown surface format for bpp=%d\n",
+ ppix->drawable.depth);
+ return;
+ }
+
+ /* untiled source */
+ BEGIN_RING(chan, eng2d, NV50_2D_SRC_FORMAT, 2);
+ OUT_RING (chan, fmt);
+ OUT_RING (chan, 1);
+ BEGIN_RING(chan, eng2d, NV50_2D_SRC_PITCH, 5);
+ OUT_RING (chan, NOUVEAU_ALIGN(pScrn->virtualX, 64) *
+ (pScrn->bitsPerPixel >> 3));
+ OUT_RING (chan, ppix->drawable.width);
+ OUT_RING (chan, ppix->drawable.height);
+ OUT_RELOCh(chan, pNv->scanout, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(chan, pNv->scanout, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ /* tiled destination */
+ BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 5);
+ OUT_RING (chan, fmt);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0);
+
+ BEGIN_RING(chan, eng2d, NV50_2D_DST_WIDTH, 4);
+ OUT_RING (chan, ppix->drawable.width);
+ OUT_RING (chan, ppix->drawable.height);
+ OUT_PIXMAPh(chan, ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_PIXMAPl(chan, ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, ppix->drawable.width);
+ OUT_RING (chan, ppix->drawable.height);
+ BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
+ OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY);
+
+ while (nbox--) {
+ BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 12);
+ OUT_RING (chan, pbox->x1);
+ OUT_RING (chan, pbox->y1);
+ OUT_RING (chan, pbox->x2 - pbox->x1);
+ OUT_RING (chan, pbox->y2 - pbox->y1);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, 1);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, pbox->x1);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, pbox->y1);
+
+ pbox++;
+ }
+}
+
static void nv50_shadow_damage_report(DamagePtr pDamage, RegionPtr pRegion, void *closure)
{
PixmapPtr ppix = closure;
@@ -122,6 +208,28 @@ static void nv50_shadow_damage_report(DamagePtr pDamage, RegionPtr pRegion, void
nv50_shadow_damage_blit(ppix, pRegion);
}
+void nv50_shadow_damage_frontbuffer_fallback(ScrnInfoPtr pScrn)
+{
+ NVPtr pNv = NVPTR(pScrn);
+ ScreenPtr pScreen = pScrn->pScreen;
+ PixmapPtr ppix = NULL;
+ DamagePtr pDamage = pNv->screen_damage;
+
+ if (pNv->Architecture < NV_ARCH_50)
+ return;
+
+ ppix = pScreen->GetScreenPixmap(pScreen);
+ if (!ppix) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "No screen pixmap.\n");
+ return;
+ }
+
+ /* Pending damage reflects the rendering currently being done. */
+ /* When exa calls finish access, damage hasn't flushed it yet. */
+ nv50_shadow_damage_blit_back(ppix, &pDamage->pendingDamage);
+}
+
static void nv50_shadow_damage_destroy(DamagePtr pDamage, void *closure)
{
PixmapPtr ppix = closure;
diff --git a/src/nv_proto.h b/src/nv_proto.h
index f39c294..f73770d 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -278,6 +278,7 @@ int nv50_xv_port_attribute_get(ScrnInfoPtr, Atom, INT32 *, pointer);
/* nv50_shadow_damage.c */
bool nv50_shadow_damage_create(ScrnInfoPtr pScrn);
+void nv50_shadow_damage_frontbuffer_fallback(ScrnInfoPtr pScrn);
/* To support EXA 2.0, 2.1 has this in the header */
#ifndef exaMoveInPixmap
--
1.6.1.2
More information about the Nouveau
mailing list