Browse Source

nv50: move 2d blit/fill code into pipe driver

tags/mesa_20090313
Ben Skeggs 16 years ago
parent
commit
13393736db

+ 24
- 0
src/gallium/drivers/nv50/nv50_screen.c View File

@@ -173,6 +173,14 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
return NULL;
screen->nvws = nvws;

/* 2D object */
ret = nvws->grobj_alloc(nvws, NV50_2D, &screen->eng2d);
if (ret) {
NOUVEAU_ERR("Error creating 2D object: %d\n", ret);
nv50_screen_destroy(&screen->pipe);
return NULL;
}

/* 3D object */
if ((chipset & 0xf0) != 0x50 && (chipset & 0xf0) != 0x80) {
NOUVEAU_ERR("Not a G8x chipset\n");
@@ -218,6 +226,22 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
return NULL;
}

/* Static 2D init */
so = so_new(64, 0);
so_method(so, screen->eng2d, NV50_2D_DMA_NOTIFY, 4);
so_data (so, screen->sync->handle);
so_data (so, screen->nvws->channel->vram->handle);
so_data (so, screen->nvws->channel->vram->handle);
so_data (so, screen->nvws->channel->vram->handle);
so_method(so, screen->eng2d, NV50_2D_OPERATION, 1);
so_data (so, NV50_2D_OPERATION_SRCCOPY);
so_method(so, screen->eng2d, 0x0290, 1);
so_data (so, 0);
so_method(so, screen->eng2d, 0x0888, 1);
so_data (so, 1);
so_emit(nvws, so);
so_ref(NULL, &so);

/* Static tesla init */
so = so_new(256, 20);


+ 1
- 0
src/gallium/drivers/nv50/nv50_screen.h View File

@@ -11,6 +11,7 @@ struct nv50_screen {
unsigned cur_pctx;

struct nouveau_grobj *tesla;
struct nouveau_grobj *eng2d;
struct nouveau_notifier *sync;

struct pipe_buffer *constbuf;

+ 145
- 7
src/gallium/drivers/nv50/nv50_surface.c View File

@@ -20,6 +20,9 @@
* SOFTWARE.
*/

#define __NOUVEAU_PUSH_H__
#include <stdint.h>
#include "nouveau/nouveau_pushbuf.h"
#include "nv50_context.h"
#include "pipe/p_defines.h"
#include "pipe/internal/p_winsys_screen.h"
@@ -27,6 +30,118 @@

#include "util/u_tile.h"

static INLINE int
nv50_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_Z24S8_UNORM:
return NV50_2D_DST_FORMAT_32BPP;
case PIPE_FORMAT_X8R8G8B8_UNORM:
return NV50_2D_DST_FORMAT_24BPP;
case PIPE_FORMAT_R5G6B5_UNORM:
return NV50_2D_DST_FORMAT_16BPP;
case PIPE_FORMAT_A8_UNORM:
return NV50_2D_DST_FORMAT_8BPP;
default:
return -1;
}
}

static int
nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
{
struct nouveau_channel *chan = screen->nvws->channel;
struct nouveau_grobj *eng2d = screen->eng2d;
struct nouveau_bo *bo;
int format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);
bo = screen->nvws->get_bo(nv50_miptree(ps->texture)->buffer);
if (!bo)
return 1;

format = nv50_format(ps->format);
if (format < 0)
return 1;
if (!bo->tiled) {
BEGIN_RING(chan, eng2d, mthd, 2);
OUT_RING (chan, format);
OUT_RING (chan, 1);
BEGIN_RING(chan, eng2d, mthd + 0x14, 5);
OUT_RING (chan, ps->stride);
OUT_RING (chan, ps->width);
OUT_RING (chan, ps->height);
OUT_RELOCh(chan, bo, ps->offset, flags);
OUT_RELOCl(chan, bo, ps->offset, flags);
} else {
BEGIN_RING(chan, eng2d, mthd, 5);
OUT_RING (chan, format);
OUT_RING (chan, 0);
OUT_RING (chan, 0);
OUT_RING (chan, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
OUT_RING (chan, ps->width);
OUT_RING (chan, ps->height);
OUT_RELOCh(chan, bo, ps->offset, flags);
OUT_RELOCl(chan, bo, ps->offset, flags);
}
#if 0
if (dst) {
BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
OUT_RING (chan, 0);
OUT_RING (chan, 0);
OUT_RING (chan, surf->width);
OUT_RING (chan, surf->height);
}
#endif
return 0;
}

static int
nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
int dx, int dy, struct pipe_surface *src, int sx, int sy,
int w, int h)
{
struct nouveau_channel *chan = screen->nvws->channel;
struct nouveau_grobj *eng2d = screen->eng2d;
int ret;

WAIT_RING (chan, 32);

ret = nv50_surface_set(screen, dst, 1);
if (ret)
return ret;

ret = nv50_surface_set(screen, src, 0);
if (ret)
return ret;

BEGIN_RING(chan, eng2d, 0x088c, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4);
OUT_RING (chan, dx);
OUT_RING (chan, dy);
OUT_RING (chan, w);
OUT_RING (chan, h);
BEGIN_RING(chan, eng2d, 0x08c0, 4);
OUT_RING (chan, 0);
OUT_RING (chan, 1);
OUT_RING (chan, 0);
OUT_RING (chan, 1);
BEGIN_RING(chan, eng2d, 0x08d0, 4);
OUT_RING (chan, 0);
OUT_RING (chan, sx);
OUT_RING (chan, 0);
OUT_RING (chan, sy);

return 0;
}

static void
nv50_surface_copy(struct pipe_context *pipe, boolean flip,
struct pipe_surface *dest, unsigned destx, unsigned desty,
@@ -34,17 +149,19 @@ nv50_surface_copy(struct pipe_context *pipe, boolean flip,
unsigned width, unsigned height)
{
struct nv50_context *nv50 = (struct nv50_context *)pipe;
struct nouveau_winsys *nvws = nv50->screen->nvws;
struct nv50_screen *screen = nv50->screen;

assert(src->format == dest->format);

if (flip) {
desty += height;
while (height--) {
nvws->surface_copy(nvws, dest, destx, desty--, src,
srcx, srcy++, width, 1);
nv50_surface_do_copy(screen, dest, destx, desty--, src,
srcx, srcy++, width, 1);
}
} else {
nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
width, height);
nv50_surface_do_copy(screen, dest, destx, desty, src, srcx,
srcy, width, height);
}
}

@@ -54,9 +171,30 @@ nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
unsigned height, unsigned value)
{
struct nv50_context *nv50 = (struct nv50_context *)pipe;
struct nouveau_winsys *nvws = nv50->screen->nvws;
struct nv50_screen *screen = nv50->screen;
struct nouveau_channel *chan = screen->nvws->channel;
struct nouveau_grobj *eng2d = screen->eng2d;
int format, ret;

format = nv50_format(dest->format);
if (format < 0)
return;

WAIT_RING (chan, 32);

ret = nv50_surface_set(screen, dest, 1);
if (ret)
return;

nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
BEGIN_RING(chan, eng2d, 0x0580, 3);
OUT_RING (chan, 4);
OUT_RING (chan, format);
OUT_RING (chan, value);
BEGIN_RING(chan, eng2d, NV50_2D_RECT_X1, 4);
OUT_RING (chan, destx);
OUT_RING (chan, desty);
OUT_RING (chan, width);
OUT_RING (chan, height);
}

static void *

+ 1
- 2
src/gallium/winsys/drm/nouveau/common/Makefile View File

@@ -10,8 +10,7 @@ C_SOURCES = \
nouveau_winsys.c \
nouveau_winsys_pipe.c \
nouveau_winsys_softpipe.c \
nv04_surface.c \
nv50_surface.c
nv04_surface.c


include ./Makefile.template

+ 2
- 3
src/gallium/winsys/drm/nouveau/common/nouveau_context.c View File

@@ -56,7 +56,7 @@ nouveau_channel_context_create(struct nouveau_device *dev)
case 0x50:
case 0x80:
case 0x90:
ret = nouveau_surface_channel_create_nv50(nvc);
/* pipe driver does this */
break;
default:
ret = nouveau_surface_channel_create_nv04(nvc);
@@ -168,8 +168,7 @@ nouveau_context_init(struct nouveau_screen *nv_screen,
case 0x50:
case 0x80:
case 0x90:
if (nouveau_surface_init_nv50(nv))
return 1;
/* pipe driver does this */
break;
default:
if (nouveau_surface_init_nv04(nv))

+ 0
- 3
src/gallium/winsys/drm/nouveau/common/nouveau_context.h View File

@@ -78,10 +78,7 @@ extern void UNLOCK_HARDWARE(struct nouveau_context *);

extern int
nouveau_surface_channel_create_nv04(struct nouveau_channel_context *);
extern int
nouveau_surface_channel_create_nv50(struct nouveau_channel_context *);
extern int nouveau_surface_init_nv04(struct nouveau_context *);
extern int nouveau_surface_init_nv50(struct nouveau_context *);

extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int);
extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *);

+ 0
- 193
src/gallium/winsys/drm/nouveau/common/nv50_surface.c View File

@@ -1,193 +0,0 @@
#include "pipe/p_context.h"
#include "pipe/p_format.h"

#include "nouveau_context.h"

static INLINE int
nv50_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_Z24S8_UNORM:
return NV50_2D_DST_FORMAT_32BPP;
case PIPE_FORMAT_X8R8G8B8_UNORM:
return NV50_2D_DST_FORMAT_24BPP;
case PIPE_FORMAT_R5G6B5_UNORM:
return NV50_2D_DST_FORMAT_16BPP;
case PIPE_FORMAT_A8_UNORM:
return NV50_2D_DST_FORMAT_8BPP;
default:
return -1;
}
}

static int
nv50_surface_set(struct nouveau_context *nv, struct pipe_surface *surf, int dst)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct nouveau_grobj *eng2d = nv->nvc->Nv2D;
struct nouveau_bo *bo = nouveau_buffer(surf)->bo;
int surf_format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);
surf_format = nv50_format(surf->format);
if (surf_format < 0)
return 1;
if (!bo->tiled) {
BEGIN_RING(chan, eng2d, mthd, 2);
OUT_RING (chan, surf_format);
OUT_RING (chan, 1);
BEGIN_RING(chan, eng2d, mthd + 0x14, 5);
OUT_RING (chan, surf->stride);
OUT_RING (chan, surf->width);
OUT_RING (chan, surf->height);
OUT_RELOCh(chan, bo, surf->offset, flags);
OUT_RELOCl(chan, bo, surf->offset, flags);
} else {
BEGIN_RING(chan, eng2d, mthd, 5);
OUT_RING (chan, surf_format);
OUT_RING (chan, 0);
OUT_RING (chan, 0);
OUT_RING (chan, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
OUT_RING (chan, surf->width);
OUT_RING (chan, surf->height);
OUT_RELOCh(chan, bo, surf->offset, flags);
OUT_RELOCl(chan, bo, surf->offset, flags);
}
#if 0
if (dst) {
BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
OUT_RING (chan, 0);
OUT_RING (chan, 0);
OUT_RING (chan, surf->width);
OUT_RING (chan, surf->height);
}
#endif
return 0;
}

static int
nv50_surface_copy_prep(struct nouveau_context *nv,
struct pipe_surface *dst, struct pipe_surface *src)
{
int ret;

assert(src->format == dst->format);

ret = nv50_surface_set(nv, dst, 1);
if (ret)
return ret;

ret = nv50_surface_set(nv, src, 0);
if (ret)
return ret;

return 0;
}

static void
nv50_surface_copy(struct nouveau_context *nv, unsigned dx, unsigned dy,
unsigned sx, unsigned sy, unsigned w, unsigned h)
{
struct nouveau_channel *chan = nv->nvc->channel;
struct nouveau_grobj *eng2d = nv->nvc->Nv2D;

BEGIN_RING(chan, eng2d, 0x088c, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4);
OUT_RING (chan, dx);
OUT_RING (chan, dy);
OUT_RING (chan, w);
OUT_RING (chan, h);
BEGIN_RING(chan, eng2d, 0x08c0, 4);
OUT_RING (chan, 0);
OUT_RING (chan, 1);
OUT_RING (chan, 0);
OUT_RING (chan, 1);
BEGIN_RING(chan, eng2d, 0x08d0, 4);
OUT_RING (chan, 0);
OUT_RING (chan, sx);
OUT_RING (chan, 0);
OUT_RING (chan, sy);
}

static void
nv50_surface_copy_done(struct nouveau_context *nv)
{
FIRE_RING(nv->nvc->channel);
}

static int
nv50_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 *eng2d = nv->nvc->Nv2D;
int rect_format, ret;

rect_format = nv50_format(dst->format);
if (rect_format < 0)
return 1;

ret = nv50_surface_set(nv, dst, 1);
if (ret)
return ret;

BEGIN_RING(chan, eng2d, 0x0580, 3);
OUT_RING (chan, 4);
OUT_RING (chan, rect_format);
OUT_RING (chan, value);

BEGIN_RING(chan, eng2d, NV50_2D_RECT_X1, 4);
OUT_RING (chan, dx);
OUT_RING (chan, dy);
OUT_RING (chan, dx + w);
OUT_RING (chan, dy + h);

FIRE_RING(chan);
return 0;
}

int
nouveau_surface_channel_create_nv50(struct nouveau_channel_context *nvc)
{
struct nouveau_channel *chan = nvc->channel;
struct nouveau_grobj *eng2d = NULL;
int ret;

ret = nouveau_grobj_alloc(chan, nvc->next_handle++, NV50_2D, &eng2d);
if (ret)
return ret;
nvc->Nv2D = eng2d;

BEGIN_RING(chan, eng2d, NV50_2D_DMA_NOTIFY, 4);
OUT_RING (chan, nvc->sync_notifier->handle);
OUT_RING (chan, chan->vram->handle);
OUT_RING (chan, chan->vram->handle);
OUT_RING (chan, chan->vram->handle);
BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY);
BEGIN_RING(chan, eng2d, 0x0290, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, eng2d, 0x0888, 1);
OUT_RING (chan, 1);

return 0;
}

int
nouveau_surface_init_nv50(struct nouveau_context *nv)
{
nv->surface_copy_prep = nv50_surface_copy_prep;
nv->surface_copy = nv50_surface_copy;
nv->surface_copy_done = nv50_surface_copy_done;
nv->surface_fill = nv50_surface_fill;
return 0;
}


+ 30
- 12
src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c View File

@@ -28,18 +28,36 @@ nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
pbox = dPriv->pClipRects;
nbox = dPriv->numClipRects;

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);
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);
}
}

FIRE_RING(nv->base.nvc->channel);

Loading…
Cancel
Save