mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-25 23:10:23 +01:00
nv04-nv40: move 2d blit/fill code into pipe driver
This commit is contained in:
parent
13393736db
commit
ff8dff017e
27 changed files with 623 additions and 652 deletions
|
|
@ -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 *,
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
449
src/gallium/drivers/nv04/nv04_surface_2d.c
Normal file
449
src/gallium/drivers/nv04/nv04_surface_2d.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
29
src/gallium/drivers/nv04/nv04_surface_2d.h
Normal file
29
src/gallium/drivers/nv04/nv04_surface_2d.h
Normal 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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue