- Only for sufficiently new xserver's and exa_driver_pixmaps.
---
src/nouveau_exa.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++--
src/nv_driver.c | 51 +++++++++++--
src/nv_proto.h | 4 +
src/nv_type.h | 12 +++-
4 files changed, 267 insertions(+), 17 deletions(-)
diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index 93fc3c5..074a226 100644
--- a/src/nouveau_exa.c
+++ b/src/nouveau_exa.c
@@ -259,7 +259,11 @@ nouveau_exa_mark_sync(ScreenPtr pScreen)
static void
nouveau_exa_wait_marker(ScreenPtr pScreen, int marker)
{
- NVSync(xf86Screens[pScreen->myNum]);
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
+
+ if (!pNv->exa_driver_pixmaps)
+ NVSync(xf86Screens[pScreen->myNum]);
}
static Bool
@@ -351,17 +355,16 @@ nouveau_exa_modify_pixmap_header(PixmapPtr ppix, int
width, int height,
if (!nvpix->bo && nvpix->size) {
uint32_t cpp = ppix->drawable.bitsPerPixel >> 3;
- /* At some point we should just keep 1bpp pixmaps in sysram */
uint32_t flags = NOUVEAU_BO_VRAM;
int ret;
if (pNv->Architecture >= NV_ARCH_50 && cpp) {
- uint32_t aw = (width + 7) & ~7;
- uint32_t ah = (height + 7) & ~7;
+ uint32_t ah = (height + 3) & ~3;
flags |= NOUVEAU_BO_TILED;
- devkind = ((aw * cpp) + 63) & ~63;
+ /* This allignment is very important. */
+ devkind = (width * cpp + 63) & ~63;
nvpix->size = devkind * ah;
}
@@ -390,8 +393,11 @@ nouveau_exa_pixmap_is_tiled(PixmapPtr ppix)
NVPtr pNv = NVPTR(pScrn);
if (pNv->exa_driver_pixmaps) {
- if (!nouveau_pixmap_bo(ppix)->tiled)
+ if (!nouveau_pixmap_bo(ppix))
+ return false;
+ if (nouveau_pixmap_bo(ppix)->tiled == 0)
return false;
+ return true;
} else
if (pNv->Architecture < NV_ARCH_50 ||
exaGetPixmapOffset(ppix) < pNv->EXADriverPtr->offScreenBase)
@@ -403,10 +409,12 @@ nouveau_exa_pixmap_is_tiled(PixmapPtr ppix)
static void *
nouveau_exa_pixmap_map(PixmapPtr ppix)
{
+ ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
unsigned delta = nouveau_pixmap_offset(ppix);
- if (bo->tiled) {
+ if (!pNv->wfb_enabled && bo->tiled) {
struct nouveau_pixmap *nvpix = nouveau_pixmap(ppix);
nvpix->linear = xcalloc(1, ppix->devKind * ppix->drawable.height);
@@ -426,9 +434,11 @@ nouveau_exa_pixmap_map(PixmapPtr ppix)
static void
nouveau_exa_pixmap_unmap(PixmapPtr ppix)
{
+ ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
- if (bo->tiled) {
+ if (!pNv->wfb_enabled && bo->tiled) {
struct nouveau_pixmap *nvpix = nouveau_pixmap(ppix);
NVAccelUploadM2MF(ppix, 0, 0, ppix->drawable.width,
@@ -674,3 +684,194 @@ nouveau_exa_init(ScreenPtr pScreen)
pNv->EXADriverPtr = exa;
return TRUE;
}
+
+/* WFB functions. */
+
+static FbBits
+nouveau_exa_wfb_read_memory_linear(const void *src, int size)
+{
+ FbBits bits = 0;
+
+ memcpy(&bits, src, size);
+
+ return bits;
+}
+
+static void
+nouveau_exa_wfb_write_memory_linear(void *dst, FbBits value, int size)
+{
+ memcpy(dst, &value, size);
+}
+
+#define TILE_PITCH 32
+#define TILE_HEIGHT 4
+#define SUBTILE_PITCH 8
+#define SUBTILE_HEIGHT 2
+
+#define LINEAR_PITCH (pPixmap->devKind)
+#define NUM_TILES_WIDTH (LINEAR_PITCH/TILE_PITCH)
+
+static NVPtr last_wfb_pNv = NULL;
+
+/* Note, we can only expose one read and write function, the linear versions
are for internal consumption. */
+static FbBits
+nouveau_exa_wfb_read_memory(const void *src, int size)
+{
+ int i, line_x, line_y, tile_x, tile_y, subtile_x, subtile_y;
+ unsigned long offset = (unsigned long) src, subpixel_offset;
+ PixmapPtr pPixmap = NULL;
+ FbBits bits = 0;
+ void *new_src;
+
+ if (!last_wfb_pNv)
+ return nouveau_exa_wfb_read_memory_linear(src, size);
+
+ /* Find the right pixmap. */
+ for (i = 0; i < 6; i++)
+ if (offset >= last_wfb_pNv->wfb_pixmaps[i].start && offset <
last_wfb_pNv->wfb_pixmaps[i].end) {
+ pPixmap = last_wfb_pNv->wfb_pixmaps[i].ppix;
+ break;
+ }
+
+ if (!pPixmap || !last_wfb_pNv->wfb_pixmaps[i].tiled)
+ return nouveau_exa_wfb_read_memory_linear(src, size);
+
+ /* Now comes the decoding. */
+ offset -= (unsigned long) pPixmap->devPrivate.ptr;
+ /* Assuming dword alligned offsets. */
+ subpixel_offset = offset & ((pPixmap->drawable.bitsPerPixel >> 3)
- 1);
+ offset &= ~((pPixmap->drawable.bitsPerPixel >> 3) - 1);
+
+ /* Determine the coordinate first. */
+ line_y = offset/LINEAR_PITCH;
+ line_x = offset - line_y * LINEAR_PITCH;
+ tile_x = line_x/TILE_PITCH;
+ tile_y = line_y/TILE_HEIGHT;
+ subtile_x = (line_x - tile_x * TILE_PITCH)/SUBTILE_PITCH;
+ subtile_y = (line_y - tile_y * TILE_HEIGHT)/SUBTILE_HEIGHT;
+
+ new_src = pPixmap->devPrivate.ptr +
+ (((tile_y * NUM_TILES_WIDTH) + tile_x) * (TILE_HEIGHT * TILE_PITCH)) +
+ (((subtile_y * (TILE_PITCH/SUBTILE_PITCH)) + subtile_x) * (SUBTILE_HEIGHT *
SUBTILE_PITCH)) +
+ ((line_y - tile_y * TILE_HEIGHT - subtile_y * SUBTILE_HEIGHT) *
SUBTILE_PITCH) +
+ (line_x - tile_x * TILE_PITCH - subtile_x * SUBTILE_PITCH) +
+ subpixel_offset;
+
+ memcpy(&bits, new_src, size);
+
+ return bits;
+}
+
+static void
+nouveau_exa_wfb_write_memory(void *dst, FbBits value, int size)
+{
+ int i, line_x, line_y, tile_x, tile_y, subtile_x, subtile_y;
+ unsigned long offset = (unsigned long) dst, subpixel_offset;
+ PixmapPtr pPixmap = NULL;
+ void *new_dst;
+
+ if (!last_wfb_pNv) {
+ nouveau_exa_wfb_write_memory_linear(dst, value, size);
+ return;
+ }
+
+ /* Find the right pixmap. */
+ for (i = 0; i < 6; i++)
+ if (offset >= last_wfb_pNv->wfb_pixmaps[i].start && offset <
last_wfb_pNv->wfb_pixmaps[i].end) {
+ pPixmap = last_wfb_pNv->wfb_pixmaps[i].ppix;
+ break;
+ }
+
+ if (!pPixmap || !last_wfb_pNv->wfb_pixmaps[i].tiled) {
+ nouveau_exa_wfb_write_memory_linear(dst, value, size);
+ return;
+ }
+
+ /* Now comes the decoding. */
+ offset -= (unsigned long) pPixmap->devPrivate.ptr;
+ /* Assuming dword alligned offsets. */
+ subpixel_offset = offset & ((pPixmap->drawable.bitsPerPixel >> 3)
- 1);
+ offset &= ~((pPixmap->drawable.bitsPerPixel >> 3) - 1);
+
+ /* Determine the coordinate first. */
+ line_y = offset/LINEAR_PITCH;
+ line_x = offset - line_y * LINEAR_PITCH;
+ tile_x = line_x/TILE_PITCH;
+ tile_y = line_y/TILE_HEIGHT;
+ subtile_x = (line_x - tile_x * TILE_PITCH)/SUBTILE_PITCH;
+ subtile_y = (line_y - tile_y * TILE_HEIGHT)/SUBTILE_HEIGHT;
+
+ new_dst = pPixmap->devPrivate.ptr +
+ (((tile_y * NUM_TILES_WIDTH) + tile_x) * (TILE_HEIGHT * TILE_PITCH)) +
+ (((subtile_y * (TILE_PITCH/SUBTILE_PITCH)) + subtile_x) * (SUBTILE_HEIGHT *
SUBTILE_PITCH)) +
+ ((line_y - tile_y * TILE_HEIGHT - subtile_y * SUBTILE_HEIGHT) *
SUBTILE_PITCH) +
+ (line_x - tile_x * TILE_PITCH - subtile_x * SUBTILE_PITCH) +
+ subpixel_offset;
+
+ memcpy(new_dst, &value, size);
+}
+
+void
+nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
+ WriteMemoryProcPtr *pWrite,
+ DrawablePtr pDraw)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
+ PixmapPtr pPixmap;
+
+ if (!pRead || !pWrite)
+ return;
+
+ pPixmap = NVGetDrawablePixmap(pDraw);
+ if (!pPixmap)
+ return;
+
+ int i;
+ for (i = 0; i < 6; i++)
+ if (!pNv->wfb_pixmaps[i].used)
+ break;
+
+ if (i == 6) {
+ ErrorF("More than 10 wraps are setup, what the hell is going
on?\n");
+ *pRead = NULL;
+ *pWrite = NULL;
+ return;
+ }
+
+ /* We will get a pointer, somewhere in the range of this pixmap. */
+ /* Based on linear representation ofcource. */
+ pNv->wfb_pixmaps[i].ppix = pPixmap;
+ pNv->wfb_pixmaps[i].start = (unsigned long) pPixmap->devPrivate.ptr;
+ pNv->wfb_pixmaps[i].end = pNv->wfb_pixmaps[i].start +
exaGetPixmapPitch(pPixmap) * ((pPixmap->drawable.height + 3) & ~3);
+ pNv->wfb_pixmaps[i].used = true;
+ pNv->wfb_pixmaps[i].tiled = nouveau_exa_pixmap_is_tiled(pPixmap);
+
+ *pRead = nouveau_exa_wfb_read_memory;
+ *pWrite = nouveau_exa_wfb_write_memory;
+
+ last_wfb_pNv = pNv;
+}
+
+void
+nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum];
+ NVPtr pNv = NVPTR(pScrn);
+ PixmapPtr pPixmap;
+ int i;
+
+ pPixmap = NVGetDrawablePixmap(pDraw);
+ if (!pPixmap)
+ return;
+
+ for (i = 0; i < 6; i++)
+ if (pNv->wfb_pixmaps[i].ppix == pPixmap) {
+ pNv->wfb_pixmaps[i].ppix = NULL;
+ pNv->wfb_pixmaps[i].start = 0;
+ pNv->wfb_pixmaps[i].end = 0;
+ pNv->wfb_pixmaps[i].used = false;
+ pNv->wfb_pixmaps[i].tiled = false;
+ break;
+ }
+}
diff --git a/src/nv_driver.c b/src/nv_driver.c
index d7e8025..4c6b691 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -157,6 +157,12 @@ static const char *fbSymbols[] = {
NULL
};
+static const char *wfbSymbols[] = {
+ "wfbPictureInit",
+ "wfbScreenInit",
+ NULL
+};
+
static const char *exaSymbols[] = {
"exaDriverInit",
"exaOffscreenInit",
@@ -285,7 +291,7 @@ nouveauSetup(pointer module, pointer opts, int *errmaj, int
*errmin)
* Tell the loader about symbols from other modules that this module
* might refer to.
*/
- LoaderRefSymLists(vgahwSymbols, exaSymbols, fbSymbols,
+ LoaderRefSymLists(vgahwSymbols, exaSymbols, fbSymbols, wfbSymbols,
ramdacSymbols, shadowSymbols, drmSymbols,
i2cSymbols, ddcSymbols, vbeSymbols,
int10Symbols, NULL);
@@ -1510,10 +1516,22 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
* section.
*/
- if (xf86LoadSubModule(pScrn, "fb") == NULL)
- NVPreInitFail("\n");
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0)
+ if (!pNv->NoAccel && pNv->exa_driver_pixmaps &&
pNv->Architecture == NV_ARCH_50) {
+ pNv->wfb_enabled = true;
+ if (xf86LoadSubModule(pScrn, "wfb") == NULL)
+ NVPreInitFail("\n");
- xf86LoaderReqSymLists(fbSymbols, NULL);
+ xf86LoaderReqSymLists(wfbSymbols, NULL);
+ } else
+#endif
+ {
+ pNv->wfb_enabled = false;
+ if (xf86LoadSubModule(pScrn, "fb") == NULL)
+ NVPreInitFail("\n");
+
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+ }
/* Load EXA if needed */
if (!pNv->NoAccel) {
@@ -2154,9 +2172,19 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
char **argv)
switch (pScrn->bitsPerPixel) {
case 16:
case 32:
- ret = fbScreenInit(pScreen, FBStart, pScrn->virtualX, pScrn->virtualY,
- pScrn->xDpi, pScrn->yDpi,
- displayWidth, pScrn->bitsPerPixel);
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0)
+ if (pNv->wfb_enabled) {
+ ret = wfbScreenInit(pScreen, FBStart, pScrn->virtualX,
pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ displayWidth, pScrn->bitsPerPixel,
+ nouveau_exa_wfb_setup_wrap, nouveau_exa_wfb_finish_wrap);
+ } else
+#endif
+ {
+ ret = fbScreenInit(pScreen, FBStart, pScrn->virtualX,
pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi,
+ displayWidth, pScrn->bitsPerPixel);
+ }
break;
default:
xf86DrvMsg(scrnIndex, X_ERROR,
@@ -2181,7 +2209,14 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
char **argv)
}
}
- fbPictureInit (pScreen, 0, 0);
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0)
+ if (pNv->wfb_enabled) {
+ wfbPictureInit(pScreen, 0, 0);
+ } else
+#endif
+ {
+ fbPictureInit(pScreen, 0, 0);
+ }
xf86SetBlackWhitePixels(pScreen);
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 28605a8..5933ddd 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -65,6 +65,10 @@ void NVTakedownDma(ScrnInfoPtr pScrn);
Bool nouveau_exa_init(ScreenPtr pScreen);
Bool nouveau_exa_pixmap_is_onscreen(PixmapPtr pPixmap);
bool nouveau_exa_pixmap_is_tiled(PixmapPtr ppix);
+void nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
+ WriteMemoryProcPtr *pWrite,
+ DrawablePtr pDraw);
+void nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw);
/* in nv_hw.c */
void NVCalcStateExt(ScrnInfoPtr,struct _riva_hw_state
*,int,int,int,int,int,int);
diff --git a/src/nv_type.h b/src/nv_type.h
index 78a7802..bec4851 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -303,7 +303,8 @@ typedef struct _NVRec {
uint8_t cur_head;
ExaDriverPtr EXADriverPtr;
- Bool exa_driver_pixmaps;
+ Bool exa_driver_pixmaps;
+ bool wfb_enabled;
xf86CursorInfoPtr CursorInfoRec;
ScreenBlockHandlerProcPtr BlockHandler;
CloseScreenProcPtr CloseScreen;
@@ -404,6 +405,15 @@ typedef struct _NVRec {
unsigned point_x, point_y;
unsigned width_in, width_out;
unsigned height_in, height_out;
+
+ /* Wfb related data. */
+ struct {
+ PixmapPtr ppix;
+ bool used;
+ bool tiled;
+ unsigned long start;
+ unsigned long end;
+ } wfb_pixmaps[6];
} NVRec;
#define NVPTR(p) ((NVPtr)((p)->driverPrivate))
--
1.6.2
---
src/nouveau_exa.c | 17 +++++++++++++----
src/nv_type.h | 1 +
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index 074a226..ae6e151 100644
--- a/src/nouveau_exa.c
+++ b/src/nouveau_exa.c
@@ -717,7 +717,9 @@ static NVPtr last_wfb_pNv = NULL;
static FbBits
nouveau_exa_wfb_read_memory(const void *src, int size)
{
- int i, line_x, line_y, tile_x, tile_y, subtile_x, subtile_y;
+ int i;
+ uint32_t tile_x, tile_y, subtile_x, subtile_y;
+ uint64_t line_x, line_y;
unsigned long offset = (unsigned long) src, subpixel_offset;
PixmapPtr pPixmap = NULL;
FbBits bits = 0;
@@ -743,7 +745,8 @@ nouveau_exa_wfb_read_memory(const void *src, int size)
offset &= ~((pPixmap->drawable.bitsPerPixel >> 3) - 1);
/* Determine the coordinate first. */
- line_y = offset/LINEAR_PITCH;
+ /* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
+ line_y = (offset * last_wfb_pNv->wfb_pixmaps[i].multiply_factor) >>
32;
line_x = offset - line_y * LINEAR_PITCH;
tile_x = line_x/TILE_PITCH;
tile_y = line_y/TILE_HEIGHT;
@@ -765,7 +768,9 @@ nouveau_exa_wfb_read_memory(const void *src, int size)
static void
nouveau_exa_wfb_write_memory(void *dst, FbBits value, int size)
{
- int i, line_x, line_y, tile_x, tile_y, subtile_x, subtile_y;
+ int i;
+ uint32_t tile_x, tile_y, subtile_x, subtile_y;
+ uint64_t line_x, line_y;
unsigned long offset = (unsigned long) dst, subpixel_offset;
PixmapPtr pPixmap = NULL;
void *new_dst;
@@ -794,7 +799,8 @@ nouveau_exa_wfb_write_memory(void *dst, FbBits value, int
size)
offset &= ~((pPixmap->drawable.bitsPerPixel >> 3) - 1);
/* Determine the coordinate first. */
- line_y = offset/LINEAR_PITCH;
+ /* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
+ line_y = (offset * last_wfb_pNv->wfb_pixmaps[i].multiply_factor) >>
32;
line_x = offset - line_y * LINEAR_PITCH;
tile_x = line_x/TILE_PITCH;
tile_y = line_y/TILE_HEIGHT;
@@ -846,6 +852,8 @@ nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
pNv->wfb_pixmaps[i].end = pNv->wfb_pixmaps[i].start +
exaGetPixmapPitch(pPixmap) * ((pPixmap->drawable.height + 3) & ~3);
pNv->wfb_pixmaps[i].used = true;
pNv->wfb_pixmaps[i].tiled = nouveau_exa_pixmap_is_tiled(pPixmap);
+ /* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
+ pNv->wfb_pixmaps[i].multiply_factor =
(0xFFFFFFFF/exaGetPixmapPitch(pPixmap)) + 1;
*pRead = nouveau_exa_wfb_read_memory;
*pWrite = nouveau_exa_wfb_write_memory;
@@ -872,6 +880,7 @@ nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw)
pNv->wfb_pixmaps[i].end = 0;
pNv->wfb_pixmaps[i].used = false;
pNv->wfb_pixmaps[i].tiled = false;
+ pNv->wfb_pixmaps[i].multiply_factor = 0;
break;
}
}
diff --git a/src/nv_type.h b/src/nv_type.h
index bec4851..0313415 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -413,6 +413,7 @@ typedef struct _NVRec {
bool tiled;
unsigned long start;
unsigned long end;
+ uint64_t multiply_factor;
} wfb_pixmaps[6];
} NVRec;
--
1.6.2
---
src/nouveau_exa.c | 10 ++++++----
src/nv_type.h | 1 +
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index ae6e151..c44e882 100644
--- a/src/nouveau_exa.c
+++ b/src/nouveau_exa.c
@@ -741,8 +741,8 @@ nouveau_exa_wfb_read_memory(const void *src, int size)
/* Now comes the decoding. */
offset -= (unsigned long) pPixmap->devPrivate.ptr;
/* Assuming dword alligned offsets. */
- subpixel_offset = offset & ((pPixmap->drawable.bitsPerPixel >> 3)
- 1);
- offset &= ~((pPixmap->drawable.bitsPerPixel >> 3) - 1);
+ subpixel_offset = offset & (last_wfb_pNv->wfb_pixmaps[i].cpp - 1);
+ offset &= ~(last_wfb_pNv->wfb_pixmaps[i].cpp - 1);
/* Determine the coordinate first. */
/* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
@@ -795,8 +795,8 @@ nouveau_exa_wfb_write_memory(void *dst, FbBits value, int
size)
/* Now comes the decoding. */
offset -= (unsigned long) pPixmap->devPrivate.ptr;
/* Assuming dword alligned offsets. */
- subpixel_offset = offset & ((pPixmap->drawable.bitsPerPixel >> 3)
- 1);
- offset &= ~((pPixmap->drawable.bitsPerPixel >> 3) - 1);
+ subpixel_offset = offset & (last_wfb_pNv->wfb_pixmaps[i].cpp - 1);
+ offset &= ~(last_wfb_pNv->wfb_pixmaps[i].cpp - 1);
/* Determine the coordinate first. */
/* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
@@ -854,6 +854,7 @@ nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
pNv->wfb_pixmaps[i].tiled = nouveau_exa_pixmap_is_tiled(pPixmap);
/* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
pNv->wfb_pixmaps[i].multiply_factor =
(0xFFFFFFFF/exaGetPixmapPitch(pPixmap)) + 1;
+ pNv->wfb_pixmaps[i].cpp = (pPixmap->drawable.bitsPerPixel >> 3);
*pRead = nouveau_exa_wfb_read_memory;
*pWrite = nouveau_exa_wfb_write_memory;
@@ -881,6 +882,7 @@ nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw)
pNv->wfb_pixmaps[i].used = false;
pNv->wfb_pixmaps[i].tiled = false;
pNv->wfb_pixmaps[i].multiply_factor = 0;
+ pNv->wfb_pixmaps[i].cpp = 0;
break;
}
}
diff --git a/src/nv_type.h b/src/nv_type.h
index 0313415..78ec614 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -414,6 +414,7 @@ typedef struct _NVRec {
unsigned long start;
unsigned long end;
uint64_t multiply_factor;
+ uint8_t cpp;
} wfb_pixmaps[6];
} NVRec;
--
1.6.2
---
src/nouveau_exa.c | 97 +++++++++++++++++++++++++++++-----------------------
src/nv_driver.c | 1 +
src/nv_proto.h | 1 +
src/nv_type.h | 11 ------
4 files changed, 56 insertions(+), 54 deletions(-)
diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index c44e882..2d748e1 100644
--- a/src/nouveau_exa.c
+++ b/src/nouveau_exa.c
@@ -711,7 +711,16 @@ nouveau_exa_wfb_write_memory_linear(void *dst, FbBits
value, int size)
#define LINEAR_PITCH (pPixmap->devKind)
#define NUM_TILES_WIDTH (LINEAR_PITCH/TILE_PITCH)
-static NVPtr last_wfb_pNv = NULL;
+/* Wfb related data. */
+static struct {
+ PixmapPtr ppix;
+ bool used;
+ bool tiled;
+ unsigned long start;
+ unsigned long end;
+ uint64_t multiply_factor;
+ uint8_t cpp;
+} wfb_pixmaps[6];
/* Note, we can only expose one read and write function, the linear versions
are for internal consumption. */
static FbBits
@@ -725,28 +734,25 @@ nouveau_exa_wfb_read_memory(const void *src, int size)
FbBits bits = 0;
void *new_src;
- if (!last_wfb_pNv)
- return nouveau_exa_wfb_read_memory_linear(src, size);
-
/* Find the right pixmap. */
for (i = 0; i < 6; i++)
- if (offset >= last_wfb_pNv->wfb_pixmaps[i].start && offset <
last_wfb_pNv->wfb_pixmaps[i].end) {
- pPixmap = last_wfb_pNv->wfb_pixmaps[i].ppix;
+ if (offset >= wfb_pixmaps[i].start && offset <
wfb_pixmaps[i].end) {
+ pPixmap = wfb_pixmaps[i].ppix;
break;
}
- if (!pPixmap || !last_wfb_pNv->wfb_pixmaps[i].tiled)
+ if (!pPixmap || !wfb_pixmaps[i].tiled)
return nouveau_exa_wfb_read_memory_linear(src, size);
/* Now comes the decoding. */
offset -= (unsigned long) pPixmap->devPrivate.ptr;
/* Assuming dword alligned offsets. */
- subpixel_offset = offset & (last_wfb_pNv->wfb_pixmaps[i].cpp - 1);
- offset &= ~(last_wfb_pNv->wfb_pixmaps[i].cpp - 1);
+ subpixel_offset = offset & (wfb_pixmaps[i].cpp - 1);
+ offset &= ~(wfb_pixmaps[i].cpp - 1);
/* Determine the coordinate first. */
/* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
- line_y = (offset * last_wfb_pNv->wfb_pixmaps[i].multiply_factor) >>
32;
+ line_y = (offset * wfb_pixmaps[i].multiply_factor) >> 32;
line_x = offset - line_y * LINEAR_PITCH;
tile_x = line_x/TILE_PITCH;
tile_y = line_y/TILE_HEIGHT;
@@ -775,19 +781,14 @@ nouveau_exa_wfb_write_memory(void *dst, FbBits value, int
size)
PixmapPtr pPixmap = NULL;
void *new_dst;
- if (!last_wfb_pNv) {
- nouveau_exa_wfb_write_memory_linear(dst, value, size);
- return;
- }
-
/* Find the right pixmap. */
for (i = 0; i < 6; i++)
- if (offset >= last_wfb_pNv->wfb_pixmaps[i].start && offset <
last_wfb_pNv->wfb_pixmaps[i].end) {
- pPixmap = last_wfb_pNv->wfb_pixmaps[i].ppix;
+ if (offset >= wfb_pixmaps[i].start && offset <
wfb_pixmaps[i].end) {
+ pPixmap = wfb_pixmaps[i].ppix;
break;
}
- if (!pPixmap || !last_wfb_pNv->wfb_pixmaps[i].tiled) {
+ if (!pPixmap || !wfb_pixmaps[i].tiled) {
nouveau_exa_wfb_write_memory_linear(dst, value, size);
return;
}
@@ -795,12 +796,12 @@ nouveau_exa_wfb_write_memory(void *dst, FbBits value, int
size)
/* Now comes the decoding. */
offset -= (unsigned long) pPixmap->devPrivate.ptr;
/* Assuming dword alligned offsets. */
- subpixel_offset = offset & (last_wfb_pNv->wfb_pixmaps[i].cpp - 1);
- offset &= ~(last_wfb_pNv->wfb_pixmaps[i].cpp - 1);
+ subpixel_offset = offset & (wfb_pixmaps[i].cpp - 1);
+ offset &= ~(wfb_pixmaps[i].cpp - 1);
/* Determine the coordinate first. */
/* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
- line_y = (offset * last_wfb_pNv->wfb_pixmaps[i].multiply_factor) >>
32;
+ line_y = (offset * wfb_pixmaps[i].multiply_factor) >> 32;
line_x = offset - line_y * LINEAR_PITCH;
tile_x = line_x/TILE_PITCH;
tile_y = line_y/TILE_HEIGHT;
@@ -822,8 +823,6 @@ nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
WriteMemoryProcPtr *pWrite,
DrawablePtr pDraw)
{
- ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum];
- NVPtr pNv = NVPTR(pScrn);
PixmapPtr pPixmap;
if (!pRead || !pWrite)
@@ -835,7 +834,7 @@ nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
int i;
for (i = 0; i < 6; i++)
- if (!pNv->wfb_pixmaps[i].used)
+ if (!wfb_pixmaps[i].used)
break;
if (i == 6) {
@@ -847,26 +846,22 @@ nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
/* We will get a pointer, somewhere in the range of this pixmap. */
/* Based on linear representation ofcource. */
- pNv->wfb_pixmaps[i].ppix = pPixmap;
- pNv->wfb_pixmaps[i].start = (unsigned long) pPixmap->devPrivate.ptr;
- pNv->wfb_pixmaps[i].end = pNv->wfb_pixmaps[i].start +
exaGetPixmapPitch(pPixmap) * ((pPixmap->drawable.height + 3) & ~3);
- pNv->wfb_pixmaps[i].used = true;
- pNv->wfb_pixmaps[i].tiled = nouveau_exa_pixmap_is_tiled(pPixmap);
+ wfb_pixmaps[i].ppix = pPixmap;
+ wfb_pixmaps[i].start = (unsigned long) pPixmap->devPrivate.ptr;
+ wfb_pixmaps[i].end = wfb_pixmaps[i].start + exaGetPixmapPitch(pPixmap) *
((pPixmap->drawable.height + 3) & ~3);
+ wfb_pixmaps[i].used = true;
+ wfb_pixmaps[i].tiled = nouveau_exa_pixmap_is_tiled(pPixmap);
/* Division is too expensive for large numbers, so we precalculate a
multiplication factor. */
- pNv->wfb_pixmaps[i].multiply_factor =
(0xFFFFFFFF/exaGetPixmapPitch(pPixmap)) + 1;
- pNv->wfb_pixmaps[i].cpp = (pPixmap->drawable.bitsPerPixel >> 3);
+ wfb_pixmaps[i].multiply_factor = (0xFFFFFFFF/exaGetPixmapPitch(pPixmap)) + 1;
+ wfb_pixmaps[i].cpp = (pPixmap->drawable.bitsPerPixel >> 3);
*pRead = nouveau_exa_wfb_read_memory;
*pWrite = nouveau_exa_wfb_write_memory;
-
- last_wfb_pNv = pNv;
}
void
nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw)
{
- ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum];
- NVPtr pNv = NVPTR(pScrn);
PixmapPtr pPixmap;
int i;
@@ -875,14 +870,30 @@ nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw)
return;
for (i = 0; i < 6; i++)
- if (pNv->wfb_pixmaps[i].ppix == pPixmap) {
- pNv->wfb_pixmaps[i].ppix = NULL;
- pNv->wfb_pixmaps[i].start = 0;
- pNv->wfb_pixmaps[i].end = 0;
- pNv->wfb_pixmaps[i].used = false;
- pNv->wfb_pixmaps[i].tiled = false;
- pNv->wfb_pixmaps[i].multiply_factor = 0;
- pNv->wfb_pixmaps[i].cpp = 0;
+ if (wfb_pixmaps[i].ppix == pPixmap) {
+ wfb_pixmaps[i].ppix = NULL;
+ wfb_pixmaps[i].start = 0;
+ wfb_pixmaps[i].end = 0;
+ wfb_pixmaps[i].used = false;
+ wfb_pixmaps[i].tiled = false;
+ wfb_pixmaps[i].multiply_factor = 0;
+ wfb_pixmaps[i].cpp = 0;
break;
}
}
+
+void
+nouveau_exa_wfb_init()
+{
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ wfb_pixmaps[i].ppix = NULL;
+ wfb_pixmaps[i].start = 0;
+ wfb_pixmaps[i].end = 0;
+ wfb_pixmaps[i].used = false;
+ wfb_pixmaps[i].tiled = false;
+ wfb_pixmaps[i].multiply_factor = 0;
+ wfb_pixmaps[i].cpp = 0;
+ }
+}
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 4c6b691..d7cdbab 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -1519,6 +1519,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0)
if (!pNv->NoAccel && pNv->exa_driver_pixmaps &&
pNv->Architecture == NV_ARCH_50) {
pNv->wfb_enabled = true;
+ nouveau_exa_wfb_init();
if (xf86LoadSubModule(pScrn, "wfb") == NULL)
NVPreInitFail("\n");
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 5933ddd..472634c 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -69,6 +69,7 @@ void nouveau_exa_wfb_setup_wrap(ReadMemoryProcPtr *pRead,
WriteMemoryProcPtr *pWrite,
DrawablePtr pDraw);
void nouveau_exa_wfb_finish_wrap(DrawablePtr pDraw);
+void nouveau_exa_wfb_init();
/* in nv_hw.c */
void NVCalcStateExt(ScrnInfoPtr,struct _riva_hw_state
*,int,int,int,int,int,int);
diff --git a/src/nv_type.h b/src/nv_type.h
index 78ec614..0cf042a 100644
--- a/src/nv_type.h
+++ b/src/nv_type.h
@@ -405,17 +405,6 @@ typedef struct _NVRec {
unsigned point_x, point_y;
unsigned width_in, width_out;
unsigned height_in, height_out;
-
- /* Wfb related data. */
- struct {
- PixmapPtr ppix;
- bool used;
- bool tiled;
- unsigned long start;
- unsigned long end;
- uint64_t multiply_factor;
- uint8_t cpp;
- } wfb_pixmaps[6];
} NVRec;
#define NVPTR(p) ((NVPtr)((p)->driverPrivate))
--
1.6.2
Maarten Maathuis
2009-Mar-08 14:31 UTC
[Nouveau] [PATCH 5/5] nv50: inline linear wfb functions
---
src/nouveau_exa.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c
index 2d748e1..4b82d21 100644
--- a/src/nouveau_exa.c
+++ b/src/nouveau_exa.c
@@ -687,7 +687,7 @@ nouveau_exa_init(ScreenPtr pScreen)
/* WFB functions. */
-static FbBits
+static inline FbBits
nouveau_exa_wfb_read_memory_linear(const void *src, int size)
{
FbBits bits = 0;
@@ -697,7 +697,7 @@ nouveau_exa_wfb_read_memory_linear(const void *src, int
size)
return bits;
}
-static void
+static inline void
nouveau_exa_wfb_write_memory_linear(void *dst, FbBits value, int size)
{
memcpy(dst, &value, size);
--
1.6.2