diff options
27 files changed, 625 insertions, 654 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index 99f8e08201..b86c4b9338 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -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 *, diff --git a/src/gallium/drivers/nv04/Makefile b/src/gallium/drivers/nv04/Makefile index 5ea51a2f42..4ed62dae95 100644 --- a/src/gallium/drivers/nv04/Makefile +++ b/src/gallium/drivers/nv04/Makefile @@ -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 \ diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c index e5e3d4772a..9ef38bc244 100644 --- a/src/gallium/drivers/nv04/nv04_screen.c +++ b/src/gallium/drivers/nv04/nv04_screen.c @@ -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) { diff --git a/src/gallium/drivers/nv04/nv04_screen.h b/src/gallium/drivers/nv04/nv04_screen.h index 99a49cdf7a..540aec907b 100644 --- a/src/gallium/drivers/nv04/nv04_screen.h +++ b/src/gallium/drivers/nv04/nv04_screen.h @@ -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; diff --git a/src/gallium/drivers/nv04/nv04_surface.c b/src/gallium/drivers/nv04/nv04_surface.c index 0d0983f9d4..1d11f53f2a 100644 --- a/src/gallium/drivers/nv04/nv04_surface.c +++ b/src/gallium/drivers/nv04/nv04_surface.c @@ -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 diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nv04/nv04_surface_2d.c new file mode 100644 index 0000000000..7529583151 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_surface_2d.c @@ -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; +} + + diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.h b/src/gallium/drivers/nv04/nv04_surface_2d.h new file mode 100644 index 0000000000..21b8f86960 --- /dev/null +++ b/src/gallium/drivers/nv04/nv04_surface_2d.h @@ -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 diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c index 2f945a193c..f417b06c94 100644 --- a/src/gallium/drivers/nv10/nv10_screen.c +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -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; diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h index 3f8750a13f..60102a369a 100644 --- a/src/gallium/drivers/nv10/nv10_screen.h +++ b/src/gallium/drivers/nv10/nv10_screen.h @@ -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; }; diff --git a/src/gallium/drivers/nv10/nv10_surface.c b/src/gallium/drivers/nv10/nv10_surface.c index 78fd7b42da..1093dfd62e 100644 --- a/src/gallium/drivers/nv10/nv10_surface.c +++ b/src/gallium/drivers/nv10/nv10_surface.c @@ -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 diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c index c9171fa178..5f2b7b4f71 100644 --- a/src/gallium/drivers/nv20/nv20_screen.c +++ b/src/gallium/drivers/nv20/nv20_screen.c @@ -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; diff --git a/src/gallium/drivers/nv20/nv20_screen.h b/src/gallium/drivers/nv20/nv20_screen.h index 8f2f2e341d..bf2f2c0d9f 100644 --- a/src/gallium/drivers/nv20/nv20_screen.h +++ b/src/gallium/drivers/nv20/nv20_screen.h @@ -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; }; diff --git a/src/gallium/drivers/nv20/nv20_surface.c b/src/gallium/drivers/nv20/nv20_surface.c index 9b4c028eae..a79974ce5e 100644 --- a/src/gallium/drivers/nv20/nv20_surface.c +++ b/src/gallium/drivers/nv20/nv20_surface.c @@ -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 diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 9738436dc4..2bc83f815b 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -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: diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h index b7ddc2a959..b11e470f94 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -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; diff --git a/src/gallium/drivers/nv30/nv30_surface.c b/src/gallium/drivers/nv30/nv30_surface.c index 806131dcc9..b46b6123cf 100644 --- a/src/gallium/drivers/nv30/nv30_surface.c +++ b/src/gallium/drivers/nv30/nv30_surface.c @@ -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 diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 41d342d27d..a2b124d228 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -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: diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index c04a1275a0..4500aa0e5c 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -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; diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c index aa51d04051..68bbfce448 100644 --- a/src/gallium/drivers/nv40/nv40_surface.c +++ b/src/gallium/drivers/nv40/nv40_surface.c @@ -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 diff --git a/src/gallium/winsys/drm/nouveau/common/Makefile b/src/gallium/winsys/drm/nouveau/common/Makefile index 4cd315e289..c6dd6dd7f9 100644 --- a/src/gallium/winsys/drm/nouveau/common/Makefile +++ b/src/gallium/winsys/drm/nouveau/common/Makefile @@ -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 diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_context.c b/src/gallium/winsys/drm/nouveau/common/nouveau_context.c index 7be3e94d49..d6ae0827cd 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_context.c +++ b/src/gallium/winsys/drm/nouveau/common/nouveau_context.c @@ -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; diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_context.h b/src/gallium/winsys/drm/nouveau/common/nouveau_context.h index 66883e85fe..02d2745680 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_context.h +++ b/src/gallium/winsys/drm/nouveau/common/nouveau_context.h @@ -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 *); diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c index ef7e8aac54..b6199f8e6d 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c +++ b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c @@ -36,36 +36,11 @@ nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass, } 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); diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c index c17d8a05e6..881df98556 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c +++ b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c @@ -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); } diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.h b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.h index b041a77e38..1eb8043478 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.h +++ b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.h @@ -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 { diff --git a/src/gallium/winsys/drm/nouveau/common/nv04_surface.c b/src/gallium/winsys/drm/nouveau/common/nv04_surface.c deleted file mode 100644 index 214c843782..0000000000 --- a/src/gallium/winsys/drm/nouveau/common/nv04_surface.c +++ /dev/null @@ -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; -} - diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c index 450c981ca4..58cb6f7265 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c @@ -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; - - 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); - } + 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); } FIRE_RING(nv->base.nvc->channel); |