X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fnv50%2Fnv50_surface.c;h=8db3b6d344dd804ba0ff73926b3b0fd7cb4a6e24;hb=1a92c71a66dd9d785906cdb78c107e63dcf48672;hp=5bf97d3a6bfcfe91a061a7a7df4faeddce070164;hpb=c789bd376f09c3b61617aeef6f5adbba2c541178;p=mesa.git diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index 5bf97d3a6bf..8db3b6d344d 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -20,91 +20,170 @@ * SOFTWARE. */ +#define __NOUVEAU_PUSH_H__ +#include +#include "nouveau/nouveau_pushbuf.h" #include "nv50_context.h" #include "pipe/p_defines.h" -#include "pipe/p_winsys.h" +#include "pipe/internal/p_winsys_screen.h" #include "pipe/p_inlines.h" #include "util/u_tile.h" -static void -nv50_surface_copy(struct pipe_context *pipe, boolean flip, - struct pipe_surface *dest, unsigned destx, unsigned desty, - struct pipe_surface *src, unsigned srcx, unsigned srcy, - unsigned width, unsigned height) +static INLINE int +nv50_format(enum pipe_format format) { - struct nv50_context *nv50 = (struct nv50_context *)pipe; - struct nouveau_winsys *nvws = nv50->screen->nvws; - - if (flip) { - desty += height; - while (height--) { - nvws->surface_copy(nvws, dest, destx, desty--, src, - srcx, srcy++, width, 1); - } - } else { - nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy, - width, height); + 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 void -nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, - unsigned destx, unsigned desty, unsigned width, - unsigned height, unsigned value) +static int +nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst) { - struct nv50_context *nv50 = (struct nv50_context *)pipe; - struct nouveau_winsys *nvws = nv50->screen->nvws; - - nvws->surface_fill(nvws, dest, destx, desty, width, height, value); + struct nv50_miptree *mt = nv50_miptree(ps->texture); + struct nouveau_channel *chan = screen->eng2d->channel; + struct nouveau_grobj *eng2d = screen->eng2d; + struct nouveau_bo *bo = nv50_miptree(ps->texture)->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); + + format = nv50_format(ps->format); + if (format < 0) + return 1; + + if (!bo->tile_flags) { + BEGIN_RING(chan, eng2d, mthd, 2); + OUT_RING (chan, format); + OUT_RING (chan, 1); + BEGIN_RING(chan, eng2d, mthd + 0x14, 5); + OUT_RING (chan, mt->level[0].pitch); + 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, bo->tile_mode << 4); + 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 void * -nv50_surface_map(struct pipe_screen *screen, struct pipe_surface *ps, - unsigned flags ) +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_winsys *nvws = nv50_screen(screen)->nvws; - struct pipe_winsys *ws = screen->winsys; - struct nv50_surface *s = nv50_surface(ps); - struct nv50_surface m = *s; - void *map; - - if (!s->untiled) { - s->untiled = ws->buffer_create(ws, 0, 0, ps->buffer->size); - - m.base.buffer = s->untiled; - nvws->surface_copy(nvws, &m.base, 0, 0, &s->base, 0, 0, - ps->width, ps->height); - } - - /* Map original tiled surface to disallow it being validated while - * untiled mirror is mapped. - */ - ws->buffer_map(ws, ps->buffer, flags); - - map = ws->buffer_map(ws, s->untiled, flags); - if (!map) - return NULL; - - return map; + struct nouveau_channel *chan = screen->eng2d->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_unmap(struct pipe_screen *pscreen, struct pipe_surface *ps) +nv50_surface_copy(struct pipe_context *pipe, + struct pipe_surface *dest, unsigned destx, unsigned desty, + struct pipe_surface *src, unsigned srcx, unsigned srcy, + unsigned width, unsigned height) { - struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws; - struct pipe_winsys *ws = pscreen->winsys; - struct nv50_surface *s = nv50_surface(ps); - struct nv50_surface m = *s; + struct nv50_context *nv50 = (struct nv50_context *)pipe; + struct nv50_screen *screen = nv50->screen; - ws->buffer_unmap(ws, s->untiled); - ws->buffer_unmap(ws, ps->buffer); + assert(src->format == dest->format); - m.base.buffer = s->untiled; - nvws->surface_copy(nvws, &s->base, 0, 0, &m.base, 0, 0, - ps->width, ps->height); + nv50_surface_do_copy(screen, dest, destx, desty, src, srcx, + srcy, width, height); +} - pipe_buffer_reference(pscreen, &s->untiled, NULL); +static void +nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, + unsigned destx, unsigned desty, unsigned width, + unsigned height, unsigned value) +{ + struct nv50_context *nv50 = (struct nv50_context *)pipe; + struct nv50_screen *screen = nv50->screen; + struct nouveau_channel *chan = screen->eng2d->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; + + 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); } void @@ -114,10 +193,4 @@ nv50_init_surface_functions(struct nv50_context *nv50) nv50->pipe.surface_fill = nv50_surface_fill; } -void -nv50_surface_init_screen_functions(struct pipe_screen *pscreen) -{ - pscreen->surface_map = nv50_surface_map; - pscreen->surface_unmap = nv50_surface_unmap; -}