nv04-nv40: move 2d blit/fill code into pipe driver

This commit is contained in:
Ben Skeggs 2009-02-05 18:19:32 +10:00
parent 13393736db
commit ff8dff017e
27 changed files with 623 additions and 652 deletions

View file

@ -50,7 +50,7 @@ struct nouveau_winsys {
uint32_t (*notifier_status)(struct nouveau_notifier *, int id);
uint32_t (*notifier_retval)(struct nouveau_notifier *, int id);
int (*notifier_wait)(struct nouveau_notifier *, int id,
int status, float timeout);
int status, double timeout);
int (*surface_copy)(struct nouveau_winsys *, struct pipe_surface *,
unsigned, unsigned, struct pipe_surface *,

View file

@ -4,6 +4,7 @@ include $(TOP)/configs/current
LIBNAME = nv04
DRIVER_SOURCES = \
nv04_surface_2d.c \
nv04_clear.c \
nv04_context.c \
nv04_fragprog.c \

View file

@ -149,10 +149,19 @@ nv04_screen_destroy(struct pipe_screen *pscreen)
nvws->notifier_free(&screen->sync);
nvws->grobj_free(&screen->fahrenheit);
nv04_surface_2d_takedown(&screen->eng2d);
FREE(pscreen);
}
static struct pipe_buffer *
nv04_surface_buffer(struct pipe_surface *surf)
{
struct nv04_miptree *mt = (struct nv04_miptree *)surf->texture;
return mt->buffer;
}
struct pipe_screen *
nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
{
@ -181,6 +190,10 @@ nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
return NULL;
}
/* 2D engine setup */
screen->eng2d = nv04_surface_2d_init(nvws);
screen->eng2d->buf = nv04_surface_buffer;
/* 3D object */
ret = nvws->grobj_alloc(nvws, fahrenheit_class, &screen->fahrenheit);
if (ret) {

View file

@ -2,6 +2,7 @@
#define __NV04_SCREEN_H__
#include "pipe/p_screen.h"
#include "nv04_surface_2d.h"
struct nv04_screen {
struct pipe_screen pipe;
@ -10,6 +11,7 @@ struct nv04_screen {
unsigned chipset;
/* HW graphics objects */
struct nv04_surface_2d *eng2d;
struct nouveau_grobj *fahrenheit;
struct nouveau_grobj *context_surfaces_3d;
struct nouveau_notifier *sync;

View file

@ -39,10 +39,17 @@ nv04_surface_copy(struct pipe_context *pipe, boolean do_flip,
unsigned width, unsigned height)
{
struct nv04_context *nv04 = nv04_context(pipe);
struct nouveau_winsys *nvws = nv04->nvws;
struct nv04_surface_2d *eng2d = nv04->screen->eng2d;
nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
width, height);
if (do_flip) {
desty += height;
while (height--) {
eng2d->copy(eng2d, dest, destx, desty--, src,
srcx, srcy++, width, 1);
}
}
eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
}
static void
@ -51,9 +58,9 @@ nv04_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
unsigned height, unsigned value)
{
struct nv04_context *nv04 = nv04_context(pipe);
struct nouveau_winsys *nvws = nv04->nvws;
struct nv04_surface_2d *eng2d = nv04->screen->eng2d;
nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
eng2d->fill(eng2d, dest, destx, desty, width, height, value);
}
void

View file

@ -0,0 +1,449 @@
#include "pipe/p_context.h"
#include "pipe/p_format.h"
#include "util/u_memory.h"
#include "nouveau/nouveau_winsys.h"
#include "nouveau/nouveau_util.h"
#include "nv04_surface_2d.h"
static INLINE int
nv04_surface_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
case PIPE_FORMAT_R16_SNORM:
case PIPE_FORMAT_R5G6B5_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
case PIPE_FORMAT_X8R8G8B8_UNORM:
case PIPE_FORMAT_A8R8G8B8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
case PIPE_FORMAT_Z24S8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
default:
return -1;
}
}
static INLINE int
nv04_rect_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A8_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
case PIPE_FORMAT_R5G6B5_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_Z24S8_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
default:
return -1;
}
}
static INLINE int
nv04_scaled_image_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A1R5G5B5_UNORM:
return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
case PIPE_FORMAT_A8R8G8B8_UNORM:
return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
case PIPE_FORMAT_X8R8G8B8_UNORM:
return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
case PIPE_FORMAT_R5G6B5_UNORM:
case PIPE_FORMAT_R16_SNORM:
return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
default:
return -1;
}
}
static INLINE unsigned
nv04_swizzle_bits(unsigned x, unsigned y)
{
unsigned u = (x & 0x001) << 0 |
(x & 0x002) << 1 |
(x & 0x004) << 2 |
(x & 0x008) << 3 |
(x & 0x010) << 4 |
(x & 0x020) << 5 |
(x & 0x040) << 6 |
(x & 0x080) << 7 |
(x & 0x100) << 8 |
(x & 0x200) << 9 |
(x & 0x400) << 10 |
(x & 0x800) << 11;
unsigned v = (y & 0x001) << 1 |
(y & 0x002) << 2 |
(y & 0x004) << 3 |
(y & 0x008) << 4 |
(y & 0x010) << 5 |
(y & 0x020) << 6 |
(y & 0x040) << 7 |
(y & 0x080) << 8 |
(y & 0x100) << 9 |
(y & 0x200) << 10 |
(y & 0x400) << 11 |
(y & 0x800) << 12;
return v | u;
}
static int
nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx,
struct pipe_surface *dst, int dx, int dy,
struct pipe_surface *src, int sx, int sy,
int w, int h)
{
struct nouveau_channel *chan = ctx->nvws->channel;
struct nouveau_grobj *swzsurf = ctx->swzsurf;
struct nouveau_grobj *sifm = ctx->sifm;
struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src));
struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst));
const unsigned max_w = 1024;
const unsigned max_h = 1024;
const unsigned sub_w = w > max_w ? max_w : w;
const unsigned sub_h = h > max_h ? max_h : h;
unsigned cx = 0;
unsigned cy = 0;
/* POT or GTFO */
assert(!(w & (w - 1)) && !(h & (h - 1)));
BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
OUT_RELOCo(chan, dst_bo,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
OUT_RING (chan, nv04_surface_format(dst->format) |
log2i(w) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT |
log2i(h) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT);
BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
OUT_RELOCo(chan, src_bo,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
OUT_RING (chan, swzsurf->handle);
for (cy = 0; cy < h; cy += sub_h) {
for (cx = 0; cx < w; cx += sub_w) {
BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1);
OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(cx, cy) *
dst->block.size, NOUVEAU_BO_GART |
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
OUT_RING (chan, nv04_scaled_image_format(src->format));
OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
OUT_RING (chan, 0);
OUT_RING (chan, sub_h << 16 | sub_w);
OUT_RING (chan, 0);
OUT_RING (chan, sub_h << 16 | sub_w);
OUT_RING (chan, 1 << 20);
OUT_RING (chan, 1 << 20);
BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
OUT_RING (chan, sub_h << 16 | sub_w);
OUT_RING (chan, src->stride |
NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
OUT_RELOCl(chan, src_bo, src->offset + cy * src->stride +
cx * src->block.size, NOUVEAU_BO_GART |
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RING (chan, 0);
}
}
return 0;
}
static int
nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx,
struct pipe_surface *dst, int dx, int dy,
struct pipe_surface *src, int sx, int sy, int w, int h)
{
struct nouveau_channel *chan = ctx->nvws->channel;
struct nouveau_grobj *m2mf = ctx->m2mf;
struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src));
struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst));
unsigned dst_offset, src_offset;
dst_offset = dst->offset + (dy * dst->stride) + (dx * dst->block.size);
src_offset = src->offset + (sy * src->stride) + (sx * src->block.size);
WAIT_RING (chan, 3 + ((h / 2047) + 1) * 9);
BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
OUT_RELOCo(chan, src_bo,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, dst_bo,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
while (h) {
int count = (h > 2047) ? 2047 : h;
BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
OUT_RELOCl(chan, src_bo, src_offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
OUT_RELOCl(chan, dst_bo, dst_offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
OUT_RING (chan, src->stride);
OUT_RING (chan, dst->stride);
OUT_RING (chan, w * src->block.size);
OUT_RING (chan, count);
OUT_RING (chan, 0x0101);
OUT_RING (chan, 0);
h -= count;
src_offset += src->stride * count;
dst_offset += dst->stride * count;
}
return 0;
}
static int
nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
int dx, int dy, struct pipe_surface *src, int sx, int sy,
int w, int h)
{
struct nouveau_channel *chan = ctx->nvws->channel;
struct nouveau_grobj *surf2d = ctx->surf2d;
struct nouveau_grobj *blit = ctx->blit;
struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src));
struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst));
int format;
format = nv04_surface_format(dst->format);
if (format < 0)
return 1;
WAIT_RING (chan, 12);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(chan, src_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (chan, format);
OUT_RING (chan, (dst->stride << 16) | src->stride);
OUT_RELOCl(chan, src_bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, blit, 0x0300, 3);
OUT_RING (chan, (sy << 16) | sx);
OUT_RING (chan, (dy << 16) | dx);
OUT_RING (chan, ( h << 16) | w);
return 0;
}
static void
nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
int dx, int dy, struct pipe_surface *src, int sx, int sy,
int w, int h)
{
int src_linear = src->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR;
int dst_linear = dst->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR;
assert(src->format == dst->format);
/* Setup transfer to swizzle the texture to vram if needed */
/* FIXME/TODO: check proper limits of this operation */
if (src_linear ^ dst_linear) {
nv04_surface_copy_swizzle(ctx, dst, dx, dy, src, sx, sy, w, h);
return;
}
/* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
* to NV_MEMORY_TO_MEMORY_FORMAT in this case.
*/
if ((src->offset & 63) || (dst->offset & 63)) {
nv04_surface_copy_m2mf(ctx, dst, dx, dy, src, sx, sy, w, h);
return;
}
nv04_surface_copy_blit(ctx, dst, dx, dy, src, sx, sy, w, h);
}
static void
nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
int dx, int dy, int w, int h, unsigned value)
{
struct nouveau_channel *chan = ctx->nvws->channel;
struct nouveau_grobj *surf2d = ctx->surf2d;
struct nouveau_grobj *rect = ctx->rect;
struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst));
int cs2d_format, gdirect_format;
cs2d_format = nv04_surface_format(dst->format);
assert(cs2d_format >= 0);
gdirect_format = nv04_surface_format(dst->format);
assert(gdirect_format >= 0);
WAIT_RING (chan, 16);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (chan, cs2d_format);
OUT_RING (chan, (dst->stride << 16) | dst->stride);
OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
OUT_RING (chan, gdirect_format);
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
OUT_RING (chan, value);
BEGIN_RING(chan, rect,
NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
OUT_RING (chan, (dx << 16) | dy);
OUT_RING (chan, ( w << 16) | h);
}
void
nv04_surface_2d_takedown(struct nv04_surface_2d **pctx)
{
struct nv04_surface_2d *ctx;
if (!pctx || !*pctx)
return;
ctx = *pctx;
*pctx = NULL;
nouveau_notifier_free(&ctx->ntfy);
nouveau_grobj_free(&ctx->m2mf);
nouveau_grobj_free(&ctx->surf2d);
nouveau_grobj_free(&ctx->swzsurf);
nouveau_grobj_free(&ctx->rect);
nouveau_grobj_free(&ctx->blit);
nouveau_grobj_free(&ctx->sifm);
FREE(ctx);
}
struct nv04_surface_2d *
nv04_surface_2d_init(struct nouveau_winsys *nvws)
{
struct nv04_surface_2d *ctx = CALLOC_STRUCT(nv04_surface_2d);
struct nouveau_channel *chan = nvws->channel;
unsigned handle = 0x88000000, class;
int ret;
if (!ctx)
return NULL;
ret = nouveau_notifier_alloc(chan, handle++, 1, &ctx->ntfy);
if (ret) {
nv04_surface_2d_takedown(&ctx);
return NULL;
}
ret = nouveau_grobj_alloc(chan, handle++, 0x0039, &ctx->m2mf);
if (ret) {
nv04_surface_2d_takedown(&ctx);
return NULL;
}
BEGIN_RING(chan, ctx->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
OUT_RING (chan, ctx->ntfy->handle);
if (chan->device->chipset < 0x10)
class = NV04_CONTEXT_SURFACES_2D;
else
class = NV10_CONTEXT_SURFACES_2D;
ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->surf2d);
if (ret) {
nv04_surface_2d_takedown(&ctx);
return NULL;
}
BEGIN_RING(chan, ctx->surf2d,
NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RING (chan, chan->vram->handle);
OUT_RING (chan, chan->vram->handle);
if (chan->device->chipset < 0x10)
class = NV04_IMAGE_BLIT;
else
class = NV12_IMAGE_BLIT;
ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->blit);
if (ret) {
nv04_surface_2d_takedown(&ctx);
return NULL;
}
BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
OUT_RING (chan, ctx->ntfy->handle);
BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_SURFACE, 1);
OUT_RING (chan, ctx->surf2d->handle);
BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_OPERATION, 1);
OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY);
ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT,
&ctx->rect);
if (ret) {
nv04_surface_2d_takedown(&ctx);
return NULL;
}
BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
OUT_RING (chan, ctx->ntfy->handle);
BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
OUT_RING (chan, ctx->ntfy->handle);
BEGIN_RING(chan, ctx->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
BEGIN_RING(chan, ctx->rect,
NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
switch (chan->device->chipset & 0xf0) {
case 0x00:
case 0x10:
class = NV04_SWIZZLED_SURFACE;
break;
case 0x20:
class = NV20_SWIZZLED_SURFACE;
break;
case 0x30:
class = NV30_SWIZZLED_SURFACE;
break;
case 0x40:
case 0x60:
class = NV40_SWIZZLED_SURFACE;
break;
default:
/* Famous last words: this really can't happen.. */
assert(0);
break;
}
ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->swzsurf);
if (ret) {
nv04_surface_2d_takedown(&ctx);
return NULL;
}
if (chan->device->chipset < 0x10) {
class = NV04_SCALED_IMAGE_FROM_MEMORY;
} else
if (chan->device->chipset < 0x40) {
class = NV10_SCALED_IMAGE_FROM_MEMORY;
} else {
class = NV40_SCALED_IMAGE_FROM_MEMORY;
}
ret = nouveau_grobj_alloc(chan, handle++, class, &ctx->sifm);
if (ret) {
nv04_surface_2d_takedown(&ctx);
return NULL;
}
ctx->nvws = nvws;
ctx->copy = nv04_surface_copy;
ctx->fill = nv04_surface_fill;
return ctx;
}

View file

@ -0,0 +1,29 @@
#ifndef __NV04_SURFACE_2D_H__
#define __NV04_SURFACE_2D_H__
struct nv04_surface_2d {
struct nouveau_winsys *nvws;
struct nouveau_notifier *ntfy;
struct nouveau_grobj *surf2d;
struct nouveau_grobj *swzsurf;
struct nouveau_grobj *m2mf;
struct nouveau_grobj *rect;
struct nouveau_grobj *blit;
struct nouveau_grobj *sifm;
struct pipe_buffer *(*buf)(struct pipe_surface *);
void (*copy)(struct nv04_surface_2d *, struct pipe_surface *dst,
int dx, int dy, struct pipe_surface *src, int sx, int sy,
int w, int h);
void (*fill)(struct nv04_surface_2d *, struct pipe_surface *dst,
int dx, int dy, int w, int h, unsigned value);
};
struct nv04_surface_2d *
nv04_surface_2d_init(struct nouveau_winsys *nvws);
void
nv04_surface_2d_takedown(struct nv04_surface_2d **);
#endif

View file

@ -152,6 +152,14 @@ nv10_screen_destroy(struct pipe_screen *pscreen)
FREE(pscreen);
}
static struct pipe_buffer *
nv10_surface_buffer(struct pipe_surface *surf)
{
struct nv10_miptree *mt = (struct nv10_miptree *)surf->texture;
return mt->buffer;
}
struct pipe_screen *
nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
{
@ -164,6 +172,10 @@ nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
return NULL;
screen->nvws = nvws;
/* 2D engine setup */
screen->eng2d = nv04_surface_2d_init(nvws);
screen->eng2d->buf = nv10_surface_buffer;
/* 3D object */
if (chipset>=0x20)
celsius_class=NV11TCL;

View file

@ -2,6 +2,7 @@
#define __NV10_SCREEN_H__
#include "pipe/p_screen.h"
#include "nv04/nv04_surface_2d.h"
struct nv10_screen {
struct pipe_screen pipe;
@ -9,6 +10,7 @@ struct nv10_screen {
struct nouveau_winsys *nvws;
/* HW graphics objects */
struct nv04_surface_2d *eng2d;
struct nouveau_grobj *celsius;
struct nouveau_notifier *sync;
};

View file

@ -39,10 +39,17 @@ nv10_surface_copy(struct pipe_context *pipe, boolean do_flip,
unsigned width, unsigned height)
{
struct nv10_context *nv10 = nv10_context(pipe);
struct nouveau_winsys *nvws = nv10->nvws;
struct nv04_surface_2d *eng2d = nv10->screen->eng2d;
nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
width, height);
if (do_flip) {
desty += height;
while (height--) {
eng2d->copy(eng2d, dest, destx, desty--, src,
srcx, srcy++, width, 1);
}
}
eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
}
static void
@ -51,9 +58,9 @@ nv10_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
unsigned height, unsigned value)
{
struct nv10_context *nv10 = nv10_context(pipe);
struct nouveau_winsys *nvws = nv10->nvws;
struct nv04_surface_2d *eng2d = nv10->screen->eng2d;
nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
eng2d->fill(eng2d, dest, destx, desty, width, height, value);
}
void

View file

@ -152,6 +152,14 @@ nv20_screen_destroy(struct pipe_screen *pscreen)
FREE(pscreen);
}
static struct pipe_buffer *
nv20_surface_buffer(struct pipe_surface *surf)
{
struct nv20_miptree *mt = (struct nv20_miptree *)surf->texture;
return mt->buffer;
}
struct pipe_screen *
nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
{
@ -164,6 +172,10 @@ nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
return NULL;
screen->nvws = nvws;
/* 2D engine setup */
screen->eng2d = nv04_surface_2d_init(nvws);
screen->eng2d->buf = nv20_surface_buffer;
/* 3D object */
if (chipset >= 0x25)
kelvin_class = NV25TCL;

View file

@ -2,6 +2,7 @@
#define __NV20_SCREEN_H__
#include "pipe/p_screen.h"
#include "nv04/nv04_surface_2d.h"
struct nv20_screen {
struct pipe_screen pipe;
@ -9,6 +10,7 @@ struct nv20_screen {
struct nouveau_winsys *nvws;
/* HW graphics objects */
struct nv04_surface_2d *eng2d;
struct nouveau_grobj *kelvin;
struct nouveau_notifier *sync;
};

View file

@ -39,10 +39,17 @@ nv20_surface_copy(struct pipe_context *pipe, boolean do_flip,
unsigned width, unsigned height)
{
struct nv20_context *nv20 = nv20_context(pipe);
struct nouveau_winsys *nvws = nv20->nvws;
struct nv04_surface_2d *eng2d = nv20->screen->eng2d;
nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
width, height);
if (do_flip) {
desty += height;
while (height--) {
eng2d->copy(eng2d, dest, destx, desty--, src,
srcx, srcy++, width, 1);
}
}
eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
}
static void
@ -51,9 +58,9 @@ nv20_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
unsigned height, unsigned value)
{
struct nv20_context *nv20 = nv20_context(pipe);
struct nouveau_winsys *nvws = nv20->nvws;
struct nv04_surface_2d *eng2d = nv20->screen->eng2d;
nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
eng2d->fill(eng2d, dest, destx, desty, width, height, value);
}
void

View file

@ -220,6 +220,14 @@ nv30_screen_destroy(struct pipe_screen *pscreen)
FREE(pscreen);
}
static struct pipe_buffer *
nv30_surface_buffer(struct pipe_surface *surf)
{
struct nv30_miptree *mt = (struct nv30_miptree *)surf->texture;
return mt->buffer;
}
struct pipe_screen *
nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
{
@ -233,6 +241,10 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
return NULL;
screen->nvws = nvws;
/* 2D engine setup */
screen->eng2d = nv04_surface_2d_init(nvws);
screen->eng2d->buf = nv30_surface_buffer;
/* 3D object */
switch (chipset & 0xf0) {
case 0x30:

View file

@ -2,6 +2,7 @@
#define __NV30_SCREEN_H__
#include "pipe/p_screen.h"
#include "nv04/nv04_surface_2d.h"
struct nv30_screen {
struct pipe_screen pipe;
@ -11,6 +12,7 @@ struct nv30_screen {
unsigned cur_pctx;
/* HW graphics objects */
struct nv04_surface_2d *eng2d;
struct nouveau_grobj *rankine;
struct nouveau_notifier *sync;

View file

@ -30,7 +30,6 @@
#include "pipe/p_defines.h"
#include "pipe/internal/p_winsys_screen.h"
#include "pipe/p_inlines.h"
#include "util/u_tile.h"
static void
@ -40,22 +39,17 @@ nv30_surface_copy(struct pipe_context *pipe, boolean do_flip,
unsigned width, unsigned height)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nouveau_winsys *nvws = nv30->nvws;
struct nv04_surface_2d *eng2d = nv30->screen->eng2d;
if (do_flip) {
/*XXX: This dodgyness will do for now for correctness. But,
* need to investigate whether the 2D engine is able to
* manage a flip (perhaps SIFM?), if not, use the 3D engine
*/
desty += height;
while (height--) {
nvws->surface_copy(nvws, dest, destx, desty--, src,
srcx, srcy++, width, 1);
eng2d->copy(eng2d, dest, destx, desty--, src,
srcx, srcy++, width, 1);
}
} else {
nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
width, height);
}
eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
}
static void
@ -64,9 +58,9 @@ nv30_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
unsigned height, unsigned value)
{
struct nv30_context *nv30 = nv30_context(pipe);
struct nouveau_winsys *nvws = nv30->nvws;
struct nv04_surface_2d *eng2d = nv30->screen->eng2d;
nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
eng2d->fill(eng2d, dest, destx, desty, width, height, value);
}
void

View file

@ -230,6 +230,14 @@ nv40_screen_destroy(struct pipe_screen *pscreen)
FREE(pscreen);
}
static struct pipe_buffer *
nv40_surface_buffer(struct pipe_surface *surf)
{
struct nv40_miptree *mt = (struct nv40_miptree *)surf->texture;
return mt->buffer;
}
struct pipe_screen *
nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
{
@ -243,6 +251,10 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
return NULL;
screen->nvws = nvws;
/* 2D engine setup */
screen->eng2d = nv04_surface_2d_init(nvws);
screen->eng2d->buf = nv40_surface_buffer;
/* 3D object */
switch (chipset & 0xf0) {
case 0x40:

View file

@ -2,6 +2,7 @@
#define __NV40_SCREEN_H__
#include "pipe/p_screen.h"
#include "nv04/nv04_surface_2d.h"
struct nv40_screen {
struct pipe_screen pipe;
@ -11,6 +12,7 @@ struct nv40_screen {
unsigned cur_pctx;
/* HW graphics objects */
struct nv04_surface_2d *eng2d;
struct nouveau_grobj *curie;
struct nouveau_notifier *sync;

View file

@ -30,7 +30,6 @@
#include "pipe/p_defines.h"
#include "pipe/internal/p_winsys_screen.h"
#include "pipe/p_inlines.h"
#include "util/u_tile.h"
static void
@ -40,22 +39,17 @@ nv40_surface_copy(struct pipe_context *pipe, boolean do_flip,
unsigned width, unsigned height)
{
struct nv40_context *nv40 = nv40_context(pipe);
struct nouveau_winsys *nvws = nv40->nvws;
struct nv04_surface_2d *eng2d = nv40->screen->eng2d;
if (do_flip) {
/*XXX: This dodgyness will do for now for correctness. But,
* need to investigate whether the 2D engine is able to
* manage a flip (perhaps SIFM?), if not, use the 3D engine
*/
desty += height;
while (height--) {
nvws->surface_copy(nvws, dest, destx, desty--, src,
srcx, srcy++, width, 1);
eng2d->copy(eng2d, dest, destx, desty--, src,
srcx, srcy++, width, 1);
}
} else {
nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
width, height);
}
eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height);
}
static void
@ -64,9 +58,9 @@ nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
unsigned height, unsigned value)
{
struct nv40_context *nv40 = nv40_context(pipe);
struct nouveau_winsys *nvws = nv40->nvws;
struct nv04_surface_2d *eng2d = nv40->screen->eng2d;
nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
eng2d->fill(eng2d, dest, destx, desty, width, height, value);
}
void

View file

@ -9,9 +9,7 @@ C_SOURCES = \
nouveau_screen.c \
nouveau_winsys.c \
nouveau_winsys_pipe.c \
nouveau_winsys_softpipe.c \
nv04_surface.c
nouveau_winsys_softpipe.c
include ./Makefile.template

View file

@ -11,16 +11,6 @@
static void
nouveau_channel_context_destroy(struct nouveau_channel_context *nvc)
{
nouveau_grobj_free(&nvc->NvCtxSurf2D);
nouveau_grobj_free(&nvc->NvImageBlit);
nouveau_grobj_free(&nvc->NvGdiRect);
nouveau_grobj_free(&nvc->NvM2MF);
nouveau_grobj_free(&nvc->Nv2D);
nouveau_grobj_free(&nvc->NvSwzSurf);
nouveau_grobj_free(&nvc->NvSIFM);
nouveau_notifier_free(&nvc->sync_notifier);
nouveau_channel_free(&nvc->channel);
FREE(nvc);
@ -43,32 +33,7 @@ nouveau_channel_context_create(struct nouveau_device *dev)
return NULL;
}
nvc->next_handle = 0x88000000;
if ((ret = nouveau_notifier_alloc(nvc->channel, nvc->next_handle++, 1,
&nvc->sync_notifier))) {
NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret);
nouveau_channel_context_destroy(nvc);
return NULL;
}
switch (dev->chipset & 0xf0) {
case 0x50:
case 0x80:
case 0x90:
/* pipe driver does this */
break;
default:
ret = nouveau_surface_channel_create_nv04(nvc);
break;
}
if (ret) {
NOUVEAU_ERR("Error initialising surface objects: %d\n", ret);
nouveau_channel_context_destroy(nvc);
return NULL;
}
nvc->next_handle = 0x77000000;
return nvc;
}
@ -164,18 +129,6 @@ nouveau_context_init(struct nouveau_screen *nv_screen,
}
/* Create pipe */
switch (dev->chipset & 0xf0) {
case 0x50:
case 0x80:
case 0x90:
/* pipe driver does this */
break;
default:
if (nouveau_surface_init_nv04(nv))
return 1;
break;
}
if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
struct pipe_screen *pscreen;

View file

@ -21,22 +21,7 @@ struct nouveau_channel_context {
struct pipe_context **pctx;
struct nouveau_channel *channel;
struct nouveau_notifier *sync_notifier;
/* Common */
struct nouveau_grobj *NvM2MF;
/* NV04-NV40 */
struct nouveau_grobj *NvCtxSurf2D;
struct nouveau_grobj *NvSwzSurf;
struct nouveau_grobj *NvImageBlit;
struct nouveau_grobj *NvGdiRect;
struct nouveau_grobj *NvSIFM;
/* G80 */
struct nouveau_grobj *Nv2D;
uint32_t next_handle;
uint32_t next_sequence;
unsigned next_handle;
};
struct nouveau_context {
@ -53,18 +38,6 @@ struct nouveau_context {
/* Hardware context */
struct nouveau_channel_context *nvc;
int pctx_id;
/* pipe_surface accel */
struct pipe_surface *surf_src, *surf_dst;
unsigned surf_src_offset, surf_dst_offset;
int (*surface_copy_prep)(struct nouveau_context *,
struct pipe_surface *dst,
struct pipe_surface *src);
void (*surface_copy)(struct nouveau_context *, unsigned dx, unsigned dy,
unsigned sx, unsigned sy, unsigned w, unsigned h);
void (*surface_copy_done)(struct nouveau_context *);
int (*surface_fill)(struct nouveau_context *, struct pipe_surface *,
unsigned, unsigned, unsigned, unsigned, unsigned);
};
extern int nouveau_context_init(struct nouveau_screen *nv_screen,
@ -76,10 +49,6 @@ extern void nouveau_context_cleanup(struct nouveau_context *nv);
extern void LOCK_HARDWARE(struct nouveau_context *);
extern void UNLOCK_HARDWARE(struct nouveau_context *);
extern int
nouveau_surface_channel_create_nv04(struct nouveau_channel_context *);
extern int nouveau_surface_init_nv04(struct nouveau_context *);
extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int);
extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *);

View file

@ -35,37 +35,12 @@ nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass,
return 0;
}
static int
nouveau_pipe_surface_copy(struct nouveau_winsys *nvws, struct pipe_surface *dst,
unsigned dx, unsigned dy, struct pipe_surface *src,
unsigned sx, unsigned sy, unsigned w, unsigned h)
{
struct nouveau_context *nv = nvws->nv;
if (nv->surface_copy_prep(nv, dst, src))
return 1;
nv->surface_copy(nv, dx, dy, sx, sy, w, h);
nv->surface_copy_done(nv);
return 0;
}
static int
nouveau_pipe_surface_fill(struct nouveau_winsys *nvws, struct pipe_surface *dst,
unsigned dx, unsigned dy, unsigned w, unsigned h,
unsigned value)
{
if (nvws->nv->surface_fill(nvws->nv, dst, dx, dy, w, h, value))
return 1;
return 0;
}
static int
nouveau_pipe_push_reloc(struct nouveau_winsys *nvws, void *ptr,
struct pipe_buffer *buf, uint32_t data,
uint32_t flags, uint32_t vor, uint32_t tor)
{
struct nouveau_bo *bo = ((struct nouveau_pipe_buffer *)buf)->bo;
struct nouveau_bo *bo = nouveau_pipe_buffer(buf)->bo;
return nouveau_pushbuf_emit_reloc(nvws->channel, ptr, bo,
data, flags, vor, tor);
@ -84,7 +59,7 @@ nouveau_pipe_push_flush(struct nouveau_winsys *nvws, unsigned size,
static struct nouveau_bo *
nouveau_pipe_get_bo(struct pipe_buffer *pb)
{
return ((struct nouveau_pipe_buffer *)pb)->bo;
return nouveau_pipe_buffer(pb)->bo;
}
struct pipe_context *
@ -154,9 +129,6 @@ nouveau_pipe_create(struct nouveau_context *nv)
nvws->notifier_retval = nouveau_notifier_return_val;
nvws->notifier_wait = nouveau_notifier_wait_status;
nvws->surface_copy = nouveau_pipe_surface_copy;
nvws->surface_fill = nouveau_pipe_surface_fill;
nvws->get_bo = nouveau_pipe_get_bo;
ws = nouveau_create_pipe_winsys(nv);

View file

@ -103,7 +103,7 @@ nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
static void
nouveau_pipe_bo_del(struct pipe_winsys *ws, struct pipe_buffer *buf)
{
struct nouveau_pipe_buffer *nvbuf = (void *)buf;
struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf);
nouveau_bo_ref(NULL, &nvbuf->bo);
FREE(nvbuf);
@ -113,7 +113,7 @@ static void *
nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
unsigned flags)
{
struct nouveau_pipe_buffer *nvbuf = (void *)buf;
struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf);
uint32_t map_flags = 0;
if (flags & PIPE_BUFFER_USAGE_CPU_READ)
@ -146,7 +146,7 @@ nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
static void
nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
{
struct nouveau_pipe_buffer *nvbuf = (void *)buf;
struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf);
nouveau_bo_unmap(nvbuf->bo);
}

View file

@ -10,15 +10,10 @@ struct nouveau_pipe_buffer {
struct nouveau_bo *bo;
};
/* This is so horrible I should be shot - I promise I'll fix it properly
* tomorrow. Just to make the winsys build again however... The TG guys
* don't like to make life easy :)
*/
static inline struct nouveau_pipe_buffer *
nouveau_buffer(struct pipe_surface *ps)
static INLINE struct nouveau_pipe_buffer *
nouveau_pipe_buffer(struct pipe_buffer *buf)
{
return *(struct nouveau_pipe_buffer **)
((void *)ps->texture + sizeof(struct pipe_texture));
return (struct nouveau_pipe_buffer *)buf;
}
struct nouveau_pipe_winsys {

View file

@ -1,458 +0,0 @@
#include "pipe/p_context.h"
#include "pipe/p_format.h"
#include "nouveau_context.h"
static INLINE int log2i(int i)
{
int r = 0;
if (i & 0xffff0000) {
i >>= 16;
r += 16;
}
if (i & 0x0000ff00) {
i >>= 8;
r += 8;
}
if (i & 0x000000f0) {
i >>= 4;
r += 4;
}
if (i & 0x0000000c) {
i >>= 2;
r += 2;
}
if (i & 0x00000002) {
r += 1;
}
return r;
}
static INLINE int
nv04_surface_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
case PIPE_FORMAT_R16_SNORM:
case PIPE_FORMAT_R5G6B5_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
case PIPE_FORMAT_X8R8G8B8_UNORM:
case PIPE_FORMAT_A8R8G8B8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
case PIPE_FORMAT_Z24S8_UNORM:
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
default:
return -1;
}
}
static INLINE int
nv04_rect_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A8_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
case PIPE_FORMAT_R5G6B5_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_Z24S8_UNORM:
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
default:
return -1;
}
}
static INLINE int
nv04_scaled_image_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A1R5G5B5_UNORM:
return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
case PIPE_FORMAT_A8R8G8B8_UNORM:
return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
case PIPE_FORMAT_X8R8G8B8_UNORM:
return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
case PIPE_FORMAT_R5G6B5_UNORM:
case PIPE_FORMAT_R16_SNORM:
return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
default:
return -1;
}
}
static INLINE unsigned
nv04_swizzle_bits(unsigned x, unsigned y)
{
unsigned u = (x & 0x001) << 0 |
(x & 0x002) << 1 |
(x & 0x004) << 2 |
(x & 0x008) << 3 |
(x & 0x010) << 4 |
(x & 0x020) << 5 |
(x & 0x040) << 6 |
(x & 0x080) << 7 |
(x & 0x100) << 8 |
(x & 0x200) << 9 |
(x & 0x400) << 10 |
(x & 0x800) << 11;
unsigned v = (y & 0x001) << 1 |
(y & 0x002) << 2 |
(y & 0x004) << 3 |
(y & 0x008) << 4 |
(y & 0x010) << 5 |
(y & 0x020) << 6 |
(y & 0x040) << 7 |
(y & 0x080) << 8 |
(y & 0x100) << 9 |
(y & 0x200) << 10 |
(y & 0x400) << 11 |
(y & 0x800) << 12;
return v | u;
}
static void
nv04_surface_copy_swizzle(struct nouveau_context *nv, unsigned dx, unsigned dy,
unsigned sx, unsigned sy, unsigned w, unsigned h)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct pipe_surface *dst = nv->surf_dst;
struct pipe_surface *src = nv->surf_src;
const unsigned max_w = 1024;
const unsigned max_h = 1024;
const unsigned sub_w = w > max_w ? max_w : w;
const unsigned sub_h = h > max_h ? max_h : h;
unsigned cx = 0;
unsigned cy = 0;
/* POT or GTFO */
assert(!(w & (w - 1)) && !(h & (h - 1)));
BEGIN_RING(chan, nv->nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
OUT_RELOCo(chan, nouveau_buffer(dst)->bo,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, nv->nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
OUT_RING (chan, nv04_surface_format(dst->format) |
log2i(w) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT |
log2i(h) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT);
BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
OUT_RELOCo(chan, nouveau_buffer(src)->bo,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
OUT_RING (chan, nv->nvc->NvSwzSurf->handle);
for (cy = 0; cy < h; cy += sub_h) {
for (cx = 0; cx < w; cx += sub_w) {
BEGIN_RING(chan, nv->nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_OFFSET, 1);
OUT_RELOCl(chan, nouveau_buffer(dst)->bo,
dst->offset + nv04_swizzle_bits(cx, cy) * dst->block.size,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
OUT_RING (chan, nv04_scaled_image_format(src->format));
OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
OUT_RING (chan, 0);
OUT_RING (chan, sub_h << 16 | sub_w);
OUT_RING (chan, 0);
OUT_RING (chan, sub_h << 16 | sub_w);
OUT_RING (chan, 1 << 20);
OUT_RING (chan, 1 << 20);
BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
OUT_RING (chan, sub_h << 16 | sub_w);
OUT_RING (chan, src->stride |
NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
OUT_RELOCl(chan, nouveau_buffer(src)->bo,
src->offset + cy * src->stride + cx * src->block.size,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RING (chan, 0);
}
}
}
static void
nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy,
unsigned sx, unsigned sy, unsigned w, unsigned h)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct pipe_surface *dst = nv->surf_dst;
struct pipe_surface *src = nv->surf_src;
unsigned dst_offset, src_offset;
dst_offset = dst->offset + (dy * dst->stride) + (dx * dst->block.size);
src_offset = src->offset + (sy * src->stride) + (sx * src->block.size);
while (h) {
int count = (h > 2047) ? 2047 : h;
BEGIN_RING(chan, nv->nvc->NvM2MF,
NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
OUT_RELOCl(chan, nouveau_buffer(src)->bo, src_offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
OUT_RELOCl(chan, nouveau_buffer(dst)->bo, dst_offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
OUT_RING (chan, src->stride);
OUT_RING (chan, dst->stride);
OUT_RING (chan, w * src->block.size);
OUT_RING (chan, count);
OUT_RING (chan, 0x0101);
OUT_RING (chan, 0);
h -= count;
src_offset += src->stride * count;
dst_offset += dst->stride * count;
}
}
static void
nv04_surface_copy_blit(struct nouveau_context *nv, unsigned dx, unsigned dy,
unsigned sx, unsigned sy, unsigned w, unsigned h)
{
struct nouveau_channel *chan = nv->nvc->channel;
BEGIN_RING(chan, nv->nvc->NvImageBlit, 0x0300, 3);
OUT_RING (chan, (sy << 16) | sx);
OUT_RING (chan, (dy << 16) | dx);
OUT_RING (chan, ( h << 16) | w);
}
static int
nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
struct pipe_surface *src)
{
struct nouveau_channel *chan = nv->nvc->channel;
int format;
if (src->format != dst->format)
return 1;
/* Setup transfer to swizzle the texture to vram if needed */
/* FIXME/TODO: check proper limits of this operation */
if (src->texture && dst->texture) {
unsigned int src_linear = src->texture->tex_usage &
NOUVEAU_TEXTURE_USAGE_LINEAR;
unsigned int dst_linear = dst->texture->tex_usage &
NOUVEAU_TEXTURE_USAGE_LINEAR;
if (src_linear ^ dst_linear) {
nv->surface_copy = nv04_surface_copy_swizzle;
nv->surf_dst = dst;
nv->surf_src = src;
return 0;
}
}
/* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
* to NV_MEMORY_TO_MEMORY_FORMAT in this case.
*/
if ((src->offset & 63) || (dst->offset & 63)) {
BEGIN_RING(nv->nvc->channel, nv->nvc->NvM2MF,
NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
OUT_RELOCo(chan, nouveau_buffer(src)->bo,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, nouveau_buffer(dst)->bo,
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
nv->surface_copy = nv04_surface_copy_m2mf;
nv->surf_dst = dst;
nv->surf_src = src;
return 0;
}
if ((format = nv04_surface_format(dst->format)) < 0) {
NOUVEAU_ERR("Bad surface format 0x%x\n", dst->format);
return 1;
}
nv->surface_copy = nv04_surface_copy_blit;
BEGIN_RING(chan, nv->nvc->NvCtxSurf2D,
NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(chan, nouveau_buffer(src)->bo,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, nouveau_buffer(dst)->bo,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, nv->nvc->NvCtxSurf2D,
NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (chan, format);
OUT_RING (chan, (dst->stride << 16) | src->stride);
OUT_RELOCl(chan, nouveau_buffer(src)->bo, src->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(chan, nouveau_buffer(dst)->bo, dst->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
return 0;
}
static void
nv04_surface_copy_done(struct nouveau_context *nv)
{
FIRE_RING(nv->nvc->channel);
}
static int
nv04_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
unsigned dx, unsigned dy, unsigned w, unsigned h,
unsigned value)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct nouveau_grobj *surf2d = nv->nvc->NvCtxSurf2D;
struct nouveau_grobj *rect = nv->nvc->NvGdiRect;
int cs2d_format, gdirect_format;
if ((cs2d_format = nv04_surface_format(dst->format)) < 0) {
NOUVEAU_ERR("Bad format = %d\n", dst->format);
return 1;
}
if ((gdirect_format = nv04_rect_format(dst->format)) < 0) {
NOUVEAU_ERR("Bad format = %d\n", dst->format);
return 1;
}
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(chan, nouveau_buffer(dst)->bo,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCo(chan, nouveau_buffer(dst)->bo,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (chan, cs2d_format);
OUT_RING (chan, (dst->stride << 16) | dst->stride);
OUT_RELOCl(chan, nouveau_buffer(dst)->bo, dst->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(chan, nouveau_buffer(dst)->bo, dst->offset,
NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
OUT_RING (chan, gdirect_format);
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
OUT_RING (chan, value);
BEGIN_RING(chan, rect,
NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
OUT_RING (chan, (dx << 16) | dy);
OUT_RING (chan, ( w << 16) | h);
FIRE_RING(chan);
return 0;
}
int
nouveau_surface_channel_create_nv04(struct nouveau_channel_context *nvc)
{
struct nouveau_channel *chan = nvc->channel;
unsigned chipset = nvc->channel->device->chipset, class;
int ret;
if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, 0x39,
&nvc->NvM2MF))) {
NOUVEAU_ERR("Error creating m2mf object: %d\n", ret);
return 1;
}
BEGIN_RING(chan, nvc->NvM2MF,
NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
OUT_RING (chan, nvc->sync_notifier->handle);
class = chipset < 0x10 ? NV04_CONTEXT_SURFACES_2D :
NV10_CONTEXT_SURFACES_2D;
if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
&nvc->NvCtxSurf2D))) {
NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret);
return 1;
}
BEGIN_RING(chan, nvc->NvCtxSurf2D,
NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RING (chan, nvc->channel->vram->handle);
OUT_RING (chan, nvc->channel->vram->handle);
class = chipset < 0x10 ? NV04_IMAGE_BLIT : NV12_IMAGE_BLIT;
if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
&nvc->NvImageBlit))) {
NOUVEAU_ERR("Error creating blit object: %d\n", ret);
return 1;
}
BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
OUT_RING (chan, nvc->sync_notifier->handle);
BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_SURFACE, 1);
OUT_RING (chan, nvc->NvCtxSurf2D->handle);
BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1);
OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY);
class = NV04_GDI_RECTANGLE_TEXT;
if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
&nvc->NvGdiRect))) {
NOUVEAU_ERR("Error creating rect object: %d\n", ret);
return 1;
}
BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
OUT_RING (chan, nvc->sync_notifier->handle);
BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
OUT_RING (chan, nvc->NvCtxSurf2D->handle);
BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
BEGIN_RING(chan, nvc->NvGdiRect,
NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
switch (chipset & 0xf0) {
case 0x00:
case 0x10:
class = NV04_SWIZZLED_SURFACE;
break;
case 0x20:
class = NV20_SWIZZLED_SURFACE;
break;
case 0x30:
class = NV30_SWIZZLED_SURFACE;
break;
case 0x40:
case 0x60:
class = NV40_SWIZZLED_SURFACE;
break;
default:
/* Famous last words: this really can't happen.. */
assert(0);
break;
}
ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
&nvc->NvSwzSurf);
if (ret) {
NOUVEAU_ERR("Error creating swizzled surface: %d\n", ret);
return 1;
}
if (chipset < 0x10) {
class = NV04_SCALED_IMAGE_FROM_MEMORY;
} else
if (chipset < 0x40) {
class = NV10_SCALED_IMAGE_FROM_MEMORY;
} else {
class = NV40_SCALED_IMAGE_FROM_MEMORY;
}
ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
&nvc->NvSIFM);
if (ret) {
NOUVEAU_ERR("Error creating scaled image object: %d\n", ret);
return 1;
}
return 0;
}
int
nouveau_surface_init_nv04(struct nouveau_context *nv)
{
nv->surface_copy_prep = nv04_surface_copy_prep;
nv->surface_copy = nv04_surface_copy_blit;
nv->surface_copy_done = nv04_surface_copy_done;
nv->surface_fill = nv04_surface_fill;
return 0;
}

View file

@ -17,6 +17,7 @@ nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
const drm_clip_rect_t *rect)
{
struct nouveau_context_dri *nv = dPriv->driContextPriv->driverPrivate;
struct pipe_context *pipe = nv->base.nvc->pctx[nv->base.pctx_id];
drm_clip_rect_t *pbox;
int nbox, i;
@ -28,36 +29,18 @@ nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
pbox = dPriv->pClipRects;
nbox = dPriv->numClipRects;
if (nv->base.surface_copy_prep) {
nv->base.surface_copy_prep(&nv->base, nv->base.frontbuffer, surf);
for (i = 0; i < nbox; i++, pbox++) {
int sx, sy, dx, dy, w, h;
for (i = 0; i < nbox; i++, pbox++) {
int sx, sy, dx, dy, w, h;
sx = pbox->x1 - dPriv->x;
sy = pbox->y1 - dPriv->y;
dx = pbox->x1;
dy = pbox->y1;
w = pbox->x2 - pbox->x1;
h = pbox->y2 - pbox->y1;
sx = pbox->x1 - dPriv->x;
sy = pbox->y1 - dPriv->y;
dx = pbox->x1;
dy = pbox->y1;
w = pbox->x2 - pbox->x1;
h = pbox->y2 - pbox->y1;
nv->base.surface_copy(&nv->base, dx, dy, sx, sy, w, h);
}
} else {
struct pipe_context *pipe = nv->base.nvc->pctx[nv->base.pctx_id];
for (i = 0; i < nbox; i++, pbox++) {
int sx, sy, dx, dy, w, h;
sx = pbox->x1 - dPriv->x;
sy = pbox->y1 - dPriv->y;
dx = pbox->x1;
dy = pbox->y1;
w = pbox->x2 - pbox->x1;
h = pbox->y2 - pbox->y1;
pipe->surface_copy(pipe, FALSE, nv->base.frontbuffer,
dx, dy, surf, sx, sy, w, h);
}
pipe->surface_copy(pipe, FALSE, nv->base.frontbuffer,
dx, dy, surf, sx, sy, w, h);
}
FIRE_RING(nv->base.nvc->channel);