From 84cc07dc89c0ebce4ad55b4b3684d4420a202683 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 29 Feb 2008 15:03:57 +1100 Subject: nouveau: implement pipe_screen Untested on NV3x/NV5x. Quite possibly broken. --- src/gallium/drivers/nv40/nv40_screen.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/gallium/drivers/nv40/nv40_screen.h (limited to 'src/gallium/drivers/nv40/nv40_screen.h') diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h new file mode 100644 index 00000000000..b30a6c5ad57 --- /dev/null +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -0,0 +1,20 @@ +#ifndef __NV40_SCREEN_H__ +#define __NV40_SCREEN_H__ + +#include "pipe/p_screen.h" + +struct nv40_screen { + struct pipe_screen pipe; + unsigned chipset; +}; + +static INLINE struct nv40_screen * +nv40_screen(struct pipe_screen *screen) +{ + return (struct nv40_screen *)screen; +} + +extern struct pipe_screen * +nv40_screen_create(struct pipe_winsys *winsys, unsigned chipset); + +#endif -- cgit v1.2.3 From baaae562f02563c5966b857c61b3eae7341950e3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 29 Feb 2008 22:54:40 +1100 Subject: nouveau: hand nouveau_winsys in with pipe_screen init --- src/gallium/drivers/nouveau/nouveau_winsys.h | 15 +++++++++------ src/gallium/drivers/nv30/nv30_context.c | 3 ++- src/gallium/drivers/nv30/nv30_screen.c | 4 +++- src/gallium/drivers/nv30/nv30_screen.h | 5 ++--- src/gallium/drivers/nv40/nv40_context.c | 3 ++- src/gallium/drivers/nv40/nv40_screen.c | 4 +++- src/gallium/drivers/nv40/nv40_screen.h | 5 ++--- src/gallium/drivers/nv50/nv50_context.c | 3 ++- src/gallium/drivers/nv50/nv50_screen.c | 4 +++- src/gallium/drivers/nv50/nv50_screen.h | 5 ++--- src/gallium/winsys/dri/nouveau/nouveau_winsys.c | 8 ++++---- 11 files changed, 34 insertions(+), 25 deletions(-) (limited to 'src/gallium/drivers/nv40/nv40_screen.h') diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index 98d95e94a58..11ca7e80ddb 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -50,21 +50,24 @@ struct nouveau_winsys { }; extern struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, unsigned chipset); +nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, + unsigned chipset); extern struct pipe_context * -nv30_create(struct pipe_screen *, struct nouveau_winsys *); +nv30_create(struct pipe_screen *); extern struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, unsigned chipset); +nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, + unsigned chipset); extern struct pipe_context * -nv40_create(struct pipe_screen *, struct nouveau_winsys *); +nv40_create(struct pipe_screen *); extern struct pipe_screen * -nv50_screen_create(struct pipe_winsys *ws, unsigned chipset); +nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, + unsigned chipset); extern struct pipe_context * -nv50_create(struct pipe_screen *, struct nouveau_winsys *); +nv50_create(struct pipe_screen *); #endif diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c index b8452e23b16..522fb132269 100644 --- a/src/gallium/drivers/nv30/nv30_context.c +++ b/src/gallium/drivers/nv30/nv30_context.c @@ -265,9 +265,10 @@ nv30_init_hwctx(struct nv30_context *nv30, int rankine_class) #define NV35TCL_CHIPSET_3X_MASK 0x000001e0 struct pipe_context * -nv30_create(struct pipe_screen *screen, struct nouveau_winsys *nvws) +nv30_create(struct pipe_screen *screen) { struct pipe_winsys *pipe_winsys = screen->winsys; + struct nouveau_winsys *nvws = nv30_screen(screen)->nvws; unsigned chipset = nv30_screen(screen)->chipset; struct nv30_context *nv30; int rankine_class = 0, ret; diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 6d64025528f..39f2ac1af5c 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -125,7 +125,8 @@ nv30_screen_destroy(struct pipe_screen *screen) } struct pipe_screen * -nv30_screen_create(struct pipe_winsys *winsys, unsigned chipset) +nv30_screen_create(struct pipe_winsys *winsys, struct nouveau_winsys *nvws, + unsigned chipset) { struct nv30_screen *nv30screen = CALLOC_STRUCT(nv30_screen); @@ -133,6 +134,7 @@ nv30_screen_create(struct pipe_winsys *winsys, unsigned chipset) return NULL; nv30screen->chipset = chipset; + nv30screen->nvws = nvws; nv30screen->screen.winsys = winsys; diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h index e55242fbf7f..f878f81e11f 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -5,6 +5,8 @@ struct nv30_screen { struct pipe_screen screen; + + struct nouveau_winsys *nvws; unsigned chipset; }; @@ -14,7 +16,4 @@ nv30_screen(struct pipe_screen *screen) return (struct nv30_screen *)screen; } -extern struct pipe_screen * -nv30_screen_create(struct pipe_winsys *winsys, unsigned chipset); - #endif diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c index a7f64c6e9e5..679c2ddc6b5 100644 --- a/src/gallium/drivers/nv40/nv40_context.c +++ b/src/gallium/drivers/nv40/nv40_context.c @@ -196,11 +196,12 @@ nv40_destroy(struct pipe_context *pipe) } struct pipe_context * -nv40_create(struct pipe_screen *pscreen, struct nouveau_winsys *nvws) +nv40_create(struct pipe_screen *pscreen) { struct pipe_winsys *ws = pscreen->winsys; struct nv40_context *nv40; unsigned chipset = nv40_screen(pscreen)->chipset; + struct nouveau_winsys *nvws = nv40_screen(pscreen)->nvws; nv40 = CALLOC(1, sizeof(struct nv40_context)); if (!nv40) diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 1941598c641..66e84b68908 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -125,7 +125,8 @@ nv40_screen_destroy(struct pipe_screen *pscreen) } struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, unsigned chipset) +nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws, + unsigned chipset) { struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); @@ -133,6 +134,7 @@ nv40_screen_create(struct pipe_winsys *ws, unsigned chipset) return NULL; screen->chipset = chipset; + screen->nvws = nvws; screen->pipe.winsys = ws; screen->pipe.destroy = nv40_screen_destroy; diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index b30a6c5ad57..88b8fed26cf 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -5,6 +5,8 @@ struct nv40_screen { struct pipe_screen pipe; + + struct nouveau_winsys *nvws; unsigned chipset; }; @@ -14,7 +16,4 @@ nv40_screen(struct pipe_screen *screen) return (struct nv40_screen *)screen; } -extern struct pipe_screen * -nv40_screen_create(struct pipe_winsys *winsys, unsigned chipset); - #endif diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 98022809a6c..e5054e34f6b 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -56,9 +56,10 @@ nv50_init_hwctx(struct nv50_context *nv50, int tesla_class) #define GRCLASS5097_CHIPSETS 0x00000000 #define GRCLASS8297_CHIPSETS 0x00000010 struct pipe_context * -nv50_create(struct pipe_screen *pscreen, struct nouveau_winsys *nvws) +nv50_create(struct pipe_screen *pscreen) { struct pipe_winsys *pipe_winsys = pscreen->winsys; + struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws; unsigned chipset = nv50_screen(pscreen)->chipset; struct nv50_context *nv50; int tesla_class, ret; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 8bf82eb0bc0..f091779e3b0 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -90,7 +90,8 @@ nv50_screen_destroy(struct pipe_screen *pscreen) } struct pipe_screen * -nv50_screen_create(struct pipe_winsys *ws, unsigned chipset) +nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws, + unsigned chipset) { struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen); @@ -98,6 +99,7 @@ nv50_screen_create(struct pipe_winsys *ws, unsigned chipset) return NULL; screen->chipset = chipset; + screen->nvws = nvws; screen->pipe.winsys = ws; diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 45ebbb8051b..d664816a031 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -5,6 +5,8 @@ struct nv50_screen { struct pipe_screen pipe; + + struct nouveau_winsys *nvws; unsigned chipset; }; @@ -14,7 +16,4 @@ nv50_screen(struct pipe_screen *screen) return (struct nv50_screen *)screen; } -extern struct pipe_screen * -nv50_screen_create(struct pipe_winsys *winsys, unsigned chipset); - #endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c index 1d758e29e75..529f5771812 100644 --- a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c +++ b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c @@ -73,9 +73,9 @@ nouveau_pipe_create(struct nouveau_context *nv) { struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys); struct pipe_screen *(*hws_create)(struct pipe_winsys *, + struct nouveau_winsys *, unsigned chipset); - struct pipe_context *(*hw_create)(struct pipe_screen *, - struct nouveau_winsys *); + struct pipe_context *(*hw_create)(struct pipe_screen *); struct pipe_winsys *ws; struct pipe_screen *pscreen; @@ -126,7 +126,7 @@ nouveau_pipe_create(struct nouveau_context *nv) nvws->surface_fill = nouveau_pipe_surface_fill; ws = nouveau_create_pipe_winsys(nv); - pscreen = hws_create(ws, nv->chipset); - return hw_create(pscreen, nvws); + pscreen = hws_create(ws, nvws, nv->chipset); + return hw_create(pscreen); } -- cgit v1.2.3 From 17f6db9d0197657cd753249ef60355c6fd983032 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 29 Feb 2008 23:08:01 +1100 Subject: nv40: move "channel context" stuff into nv40_screen --- src/gallium/drivers/nv40/nv40_context.c | 168 +------------------------ src/gallium/drivers/nv40/nv40_context.h | 29 +---- src/gallium/drivers/nv40/nv40_fragprog.c | 4 +- src/gallium/drivers/nv40/nv40_fragtex.c | 6 +- src/gallium/drivers/nv40/nv40_query.c | 10 +- src/gallium/drivers/nv40/nv40_screen.c | 128 ++++++++++++++++++- src/gallium/drivers/nv40/nv40_screen.h | 15 +++ src/gallium/drivers/nv40/nv40_state.c | 16 +-- src/gallium/drivers/nv40/nv40_state_blend.c | 2 +- src/gallium/drivers/nv40/nv40_state_emit.c | 4 +- src/gallium/drivers/nv40/nv40_state_fb.c | 34 ++--- src/gallium/drivers/nv40/nv40_state_scissor.c | 2 +- src/gallium/drivers/nv40/nv40_state_stipple.c | 2 +- src/gallium/drivers/nv40/nv40_state_viewport.c | 2 +- src/gallium/drivers/nv40/nv40_vbo.c | 10 +- src/gallium/drivers/nv40/nv40_vertprog.c | 8 +- 16 files changed, 203 insertions(+), 237 deletions(-) (limited to 'src/gallium/drivers/nv40/nv40_screen.h') diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c index 679c2ddc6b5..084829ce281 100644 --- a/src/gallium/drivers/nv40/nv40_context.c +++ b/src/gallium/drivers/nv40/nv40_context.c @@ -6,10 +6,6 @@ #include "nv40_context.h" #include "nv40_screen.h" -#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf -#define NV4X_GRCLASS4497_CHIPSETS 0x00005450 -#define NV6X_GRCLASS4497_CHIPSETS 0x00000088 - static void nv40_flush(struct pipe_context *pipe, unsigned flags) { @@ -24,7 +20,7 @@ nv40_flush(struct pipe_context *pipe, unsigned flags) } if (flags & PIPE_FLUSH_WAIT) { - nvws->notifier_reset(nv40->hw->sync, 0); + nvws->notifier_reset(nv40->screen->sync, 0); BEGIN_RING(curie, 0x104, 1); OUT_RING (0); BEGIN_RING(curie, 0x100, 1); @@ -34,149 +30,7 @@ nv40_flush(struct pipe_context *pipe, unsigned flags) FIRE_RING(); if (flags & PIPE_FLUSH_WAIT) - nvws->notifier_wait(nv40->hw->sync, 0, 0, 2000); -} - -static void -nv40_channel_takedown(struct nv40_channel_context *cnv40) -{ - struct nouveau_winsys *nvws = cnv40->nvws; - - nvws->res_free(&cnv40->vp_exec_heap); - nvws->res_free(&cnv40->vp_data_heap); - nvws->res_free(&cnv40->query_heap); - nvws->notifier_free(&cnv40->query); - nvws->notifier_free(&cnv40->sync); - nvws->grobj_free(&cnv40->curie); - free(cnv40); -} - -static struct nv40_channel_context * -nv40_channel_init(struct pipe_winsys *ws, struct nouveau_winsys *nvws, - unsigned chipset) -{ - struct nv40_channel_context *cnv40 = NULL; - struct nouveau_stateobj *so; - unsigned curie_class = 0; - int ret; - - switch (chipset & 0xf0) { - case 0x40: - if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f))) - curie_class = NV40TCL; - else - if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) - curie_class = NV44TCL; - break; - case 0x60: - if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) - curie_class = NV44TCL; - break; - default: - break; - } - - if (!curie_class) { - NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset); - return NULL; - } - - cnv40 = CALLOC(1, sizeof(struct nv40_channel_context)); - if (!cnv40) - return NULL; - cnv40->chipset = chipset; - cnv40->nvws = nvws; - - /* Notifier for sync purposes */ - ret = nvws->notifier_alloc(nvws, 1, &cnv40->sync); - if (ret) { - NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv40_channel_takedown(cnv40); - return NULL; - } - - /* Query objects */ - ret = nvws->notifier_alloc(nvws, 32, &cnv40->query); - if (ret) { - NOUVEAU_ERR("Error initialising query objects: %d\n", ret); - nv40_channel_takedown(cnv40); - return NULL; - } - - ret = nvws->res_init(&cnv40->query_heap, 0, 32); - if (ret) { - NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); - nv40_channel_takedown(cnv40); - return NULL; - } - - /* Vtxprog resources */ - if (nvws->res_init(&cnv40->vp_exec_heap, 0, 512) || - nvws->res_init(&cnv40->vp_data_heap, 0, 256)) { - nv40_channel_takedown(cnv40); - return NULL; - } - - /* 3D object */ - ret = nvws->grobj_alloc(nvws, curie_class, &cnv40->curie); - if (ret) { - NOUVEAU_ERR("Error creating 3D object: %d\n", ret); - return FALSE; - } - - /* Static curie initialisation */ - so = so_new(128, 0); - so_method(so, cnv40->curie, NV40TCL_DMA_NOTIFY, 1); - so_data (so, cnv40->sync->handle); - so_method(so, cnv40->curie, NV40TCL_DMA_TEXTURE0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->gart->handle); - so_method(so, cnv40->curie, NV40TCL_DMA_COLOR1, 1); - so_data (so, nvws->channel->vram->handle); - so_method(so, cnv40->curie, NV40TCL_DMA_COLOR0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->vram->handle); - so_method(so, cnv40->curie, NV40TCL_DMA_VTXBUF0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->gart->handle); - so_method(so, cnv40->curie, NV40TCL_DMA_FENCE, 2); - so_data (so, 0); - so_data (so, cnv40->query->handle); - so_method(so, cnv40->curie, NV40TCL_DMA_UNK01AC, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->vram->handle); - so_method(so, cnv40->curie, NV40TCL_DMA_COLOR2, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->vram->handle); - - so_method(so, cnv40->curie, 0x1ea4, 3); - so_data (so, 0x00000010); - so_data (so, 0x01000100); - so_data (so, 0xff800006); - - /* vtxprog output routing */ - so_method(so, cnv40->curie, 0x1fc4, 1); - so_data (so, 0x06144321); - so_method(so, cnv40->curie, 0x1fc8, 2); - so_data (so, 0xedcba987); - so_data (so, 0x00000021); - so_method(so, cnv40->curie, 0x1fd0, 1); - so_data (so, 0x00171615); - so_method(so, cnv40->curie, 0x1fd4, 1); - so_data (so, 0x001b1a19); - - so_method(so, cnv40->curie, 0x1ef8, 1); - so_data (so, 0x0020ffff); - so_method(so, cnv40->curie, 0x1d64, 1); - so_data (so, 0x00d30000); - so_method(so, cnv40->curie, 0x1e94, 1); - so_data (so, 0x00000001); - - so_emit(nvws, so); - so_ref(NULL, &so); - nvws->push_flush(nvws->channel, 0); - - return cnv40; + nvws->notifier_wait(nv40->screen->sync, 0, 0, 2000); } static void @@ -186,32 +40,22 @@ nv40_destroy(struct pipe_context *pipe) if (nv40->draw) draw_destroy(nv40->draw); - - if (nv40->hw) { - if (--nv40->hw->refcount == 0) - nv40_channel_takedown(nv40->hw); - } - free(nv40); } struct pipe_context * nv40_create(struct pipe_screen *pscreen) { + struct nv40_screen *screen = nv40_screen(pscreen); struct pipe_winsys *ws = pscreen->winsys; struct nv40_context *nv40; - unsigned chipset = nv40_screen(pscreen)->chipset; - struct nouveau_winsys *nvws = nv40_screen(pscreen)->nvws; + unsigned chipset = screen->chipset; + struct nouveau_winsys *nvws = screen->nvws; nv40 = CALLOC(1, sizeof(struct nv40_context)); if (!nv40) return NULL; - - nv40->hw = nv40_channel_init(ws, nvws, chipset); - if (!nv40->hw) { - nv40_destroy(&nv40->pipe); - return NULL; - } + nv40->screen = screen; nv40->chipset = chipset; nv40->nvws = nvws; diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index 3ddfbd43f60..3b669594dc3 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -11,7 +11,7 @@ #include "nouveau/nouveau_gldefs.h" #define NOUVEAU_PUSH_CONTEXT(ctx) \ - struct nv40_channel_context *ctx = nv40->hw + struct nv40_screen *ctx = nv40->screen #include "nouveau/nouveau_push.h" #include "nouveau/nouveau_stateobj.h" @@ -59,6 +59,8 @@ enum nv40_state_index { NV40_STATE_MAX = 33 }; +#include "nv40_screen.h" + #define NV40_NEW_BLEND (1 << 0) #define NV40_NEW_RAST (1 << 1) #define NV40_NEW_ZSA (1 << 2) @@ -76,28 +78,6 @@ enum nv40_state_index { #define NV40_FALLBACK_TNL (1 << 0) #define NV40_FALLBACK_RAST (1 << 1) -struct nv40_channel_context { - struct nouveau_winsys *nvws; - unsigned refcount; - - unsigned chipset; - - /* HW graphics objects */ - struct nouveau_grobj *curie; - struct nouveau_notifier *sync; - - /* Query object resources */ - struct nouveau_notifier *query; - struct nouveau_resource *query_heap; - - /* Vtxprog resources */ - struct nouveau_resource *vp_exec_heap; - struct nouveau_resource *vp_data_heap; - - /* Current 3D state of channel */ - struct nouveau_stateobj *state[NV40_STATE_MAX]; -}; - struct nv40_rasterizer_state { struct pipe_rasterizer_state pipe; struct nouveau_stateobj *so; @@ -125,9 +105,10 @@ struct nv40_state { struct nv40_context { struct pipe_context pipe; + struct nouveau_winsys *nvws; + struct nv40_screen *screen; - struct nv40_channel_context *hw; struct draw_context *draw; int chipset; diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c index 2a8abb32a30..3c4ea7e99ed 100644 --- a/src/gallium/drivers/nv40/nv40_fragprog.c +++ b/src/gallium/drivers/nv40/nv40_fragprog.c @@ -810,11 +810,11 @@ nv40_fragprog_validate(struct nv40_context *nv40) nv40_fragprog_upload(nv40, fp); so = so_new(4, 1); - so_method(so, nv40->hw->curie, NV40TCL_FP_ADDRESS, 1); + so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1); so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, NV40TCL_FP_ADDRESS_DMA0, NV40TCL_FP_ADDRESS_DMA1); - so_method(so, nv40->hw->curie, NV40TCL_FP_CONTROL, 1); + so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1); so_data (so, fp->fp_control); so_ref(so, &fp->so); diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nv40/nv40_fragtex.c index 6be8378c087..436f954ceca 100644 --- a/src/gallium/drivers/nv40/nv40_fragtex.c +++ b/src/gallium/drivers/nv40/nv40_fragtex.c @@ -106,7 +106,7 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit) txs = tf->swizzle; so = so_new(16, 2); - so_method(so, nv40->hw->curie, NV40TCL_TEX_OFFSET(unit), 8); + so_method(so, nv40->screen->curie, NV40TCL_TEX_OFFSET(unit), 8); so_reloc (so, nv40mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); so_reloc (so, nv40mt->buffer, txf, tex_flags | NOUVEAU_BO_OR, NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1); @@ -117,7 +117,7 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit) so_data (so, (pt->width[0] << NV40TCL_TEX_SIZE0_W_SHIFT) | pt->height[0]); so_data (so, ps->bcol); - so_method(so, nv40->hw->curie, NV40TCL_TEX_SIZE1(unit), 1); + so_method(so, nv40->screen->curie, NV40TCL_TEX_SIZE1(unit), 1); so_data (so, (pt->depth[0] << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp); return so; @@ -137,7 +137,7 @@ nv40_fragtex_validate(struct nv40_context *nv40) samplers &= ~(1 << unit); so = so_new(2, 0); - so_method(so, nv40->hw->curie, NV40TCL_TEX_ENABLE(unit), 1); + so_method(so, nv40->screen->curie, NV40TCL_TEX_ENABLE(unit), 1); so_data (so, 0); so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]); state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit)); diff --git a/src/gallium/drivers/nv40/nv40_query.c b/src/gallium/drivers/nv40/nv40_query.c index 8bca2788b93..03178456246 100644 --- a/src/gallium/drivers/nv40/nv40_query.c +++ b/src/gallium/drivers/nv40/nv40_query.c @@ -45,9 +45,9 @@ nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq) assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); - if (nv40->nvws->res_alloc(nv40->hw->query_heap, 1, NULL, &q->object)) + if (nv40->nvws->res_alloc(nv40->screen->query_heap, 1, NULL, &q->object)) assert(0); - nv40->nvws->notifier_reset(nv40->hw->query, q->object->start); + nv40->nvws->notifier_reset(nv40->screen->query, q->object->start); BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1); OUT_RING (1); @@ -82,17 +82,17 @@ nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq, if (!q->ready) { unsigned status; - status = nvws->notifier_status(nv40->hw->query, + status = nvws->notifier_status(nv40->screen->query, q->object->start); if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { if (wait == FALSE) return FALSE; - nvws->notifier_wait(nv40->hw->query, q->object->start, + nvws->notifier_wait(nv40->screen->query, q->object->start, NV_NOTIFY_STATE_STATUS_COMPLETED, 0); } - q->result = nvws->notifier_retval(nv40->hw->query, + q->result = nvws->notifier_retval(nv40->screen->query, q->object->start); q->ready = TRUE; nvws->res_free(&q->object); diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 66e84b68908..268ca83ce0d 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -4,6 +4,10 @@ #include "nv40_context.h" #include "nv40_screen.h" +#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf +#define NV4X_GRCLASS4497_CHIPSETS 0x00005450 +#define NV6X_GRCLASS4497_CHIPSETS 0x00000088 + static const char * nv40_screen_get_name(struct pipe_screen *pscreen) { @@ -121,6 +125,16 @@ nv40_screen_surface_format_supported(struct pipe_screen *pscreen, static void nv40_screen_destroy(struct pipe_screen *pscreen) { + struct nv40_screen *screen = nv40_screen(pscreen); + struct nouveau_winsys *nvws = screen->nvws; + + nvws->res_free(&screen->vp_exec_heap); + nvws->res_free(&screen->vp_data_heap); + nvws->res_free(&screen->query_heap); + nvws->notifier_free(&screen->query); + nvws->notifier_free(&screen->sync); + nvws->grobj_free(&screen->curie); + FREE(pscreen); } @@ -129,13 +143,125 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws, unsigned chipset) { struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); + struct nouveau_stateobj *so; + unsigned curie_class; + int ret; if (!screen) return NULL; - screen->chipset = chipset; screen->nvws = nvws; + /* 3D object */ + switch (chipset & 0xf0) { + case 0x40: + if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f))) + curie_class = NV40TCL; + else + if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) + curie_class = NV44TCL; + break; + case 0x60: + if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) + curie_class = NV44TCL; + break; + default: + break; + } + + if (!curie_class) { + NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset); + return NULL; + } + + ret = nvws->grobj_alloc(nvws, curie_class, &screen->curie); + if (ret) { + NOUVEAU_ERR("Error creating 3D object: %d\n", ret); + return FALSE; + } + + /* Notifier for sync purposes */ + ret = nvws->notifier_alloc(nvws, 1, &screen->sync); + if (ret) { + NOUVEAU_ERR("Error creating notifier object: %d\n", ret); + nv40_screen_destroy(&screen->pipe); + return NULL; + } + + /* Query objects */ + ret = nvws->notifier_alloc(nvws, 32, &screen->query); + if (ret) { + NOUVEAU_ERR("Error initialising query objects: %d\n", ret); + nv40_screen_destroy(&screen->pipe); + return NULL; + } + + ret = nvws->res_init(&screen->query_heap, 0, 32); + if (ret) { + NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); + nv40_screen_destroy(&screen->pipe); + return NULL; + } + + /* Vtxprog resources */ + if (nvws->res_init(&screen->vp_exec_heap, 0, 512) || + nvws->res_init(&screen->vp_data_heap, 0, 256)) { + nv40_screen_destroy(&screen->pipe); + return NULL; + } + + /* Static curie initialisation */ + so = so_new(128, 0); + so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1); + so_data (so, screen->sync->handle); + so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2); + so_data (so, nvws->channel->vram->handle); + so_data (so, nvws->channel->gart->handle); + so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1); + so_data (so, nvws->channel->vram->handle); + so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2); + so_data (so, nvws->channel->vram->handle); + so_data (so, nvws->channel->vram->handle); + so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2); + so_data (so, nvws->channel->vram->handle); + so_data (so, nvws->channel->gart->handle); + so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2); + so_data (so, 0); + so_data (so, screen->query->handle); + so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2); + so_data (so, nvws->channel->vram->handle); + so_data (so, nvws->channel->vram->handle); + so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2); + so_data (so, nvws->channel->vram->handle); + so_data (so, nvws->channel->vram->handle); + + so_method(so, screen->curie, 0x1ea4, 3); + so_data (so, 0x00000010); + so_data (so, 0x01000100); + so_data (so, 0xff800006); + + /* vtxprog output routing */ + so_method(so, screen->curie, 0x1fc4, 1); + so_data (so, 0x06144321); + so_method(so, screen->curie, 0x1fc8, 2); + so_data (so, 0xedcba987); + so_data (so, 0x00000021); + so_method(so, screen->curie, 0x1fd0, 1); + so_data (so, 0x00171615); + so_method(so, screen->curie, 0x1fd4, 1); + so_data (so, 0x001b1a19); + + so_method(so, screen->curie, 0x1ef8, 1); + so_data (so, 0x0020ffff); + so_method(so, screen->curie, 0x1d64, 1); + so_data (so, 0x00d30000); + so_method(so, screen->curie, 0x1e94, 1); + so_data (so, 0x00000001); + + so_emit(nvws, so); + so_ref(NULL, &so); + nvws->push_flush(nvws->channel, 0); + screen->pipe.winsys = ws; screen->pipe.destroy = nv40_screen_destroy; diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index 88b8fed26cf..9f9668dbb6b 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -8,6 +8,21 @@ struct nv40_screen { struct nouveau_winsys *nvws; unsigned chipset; + + /* HW graphics objects */ + struct nouveau_grobj *curie; + struct nouveau_notifier *sync; + + /* Query object resources */ + struct nouveau_notifier *query; + struct nouveau_resource *query_heap; + + /* Vtxprog resources */ + struct nouveau_resource *vp_exec_heap; + struct nouveau_resource *vp_data_heap; + + /* Current 3D state of channel */ + struct nouveau_stateobj *state[NV40_STATE_MAX]; }; static INLINE struct nv40_screen * diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c index 24335fbc44d..caa2f9df0c6 100644 --- a/src/gallium/drivers/nv40/nv40_state.c +++ b/src/gallium/drivers/nv40/nv40_state.c @@ -10,7 +10,7 @@ nv40_blend_state_create(struct pipe_context *pipe, const struct pipe_blend_state *cso) { struct nv40_context *nv40 = nv40_context(pipe); - struct nouveau_grobj *curie = nv40->hw->curie; + struct nouveau_grobj *curie = nv40->screen->curie; struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso)); struct nouveau_stateobj *so = so_new(16, 0); @@ -286,7 +286,7 @@ nv40_rasterizer_state_create(struct pipe_context *pipe, struct nv40_context *nv40 = nv40_context(pipe); struct nv40_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); struct nouveau_stateobj *so = so_new(32, 0); - struct nouveau_grobj *curie = nv40->hw->curie; + struct nouveau_grobj *curie = nv40->screen->curie; /*XXX: ignored: * light_twoside @@ -420,18 +420,18 @@ nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe, struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); struct nouveau_stateobj *so = so_new(32, 0); - so_method(so, nv40->hw->curie, NV40TCL_DEPTH_FUNC, 3); + so_method(so, nv40->screen->curie, NV40TCL_DEPTH_FUNC, 3); so_data (so, nvgl_comparison_op(cso->depth.func)); so_data (so, cso->depth.writemask ? 1 : 0); so_data (so, cso->depth.enabled ? 1 : 0); - so_method(so, nv40->hw->curie, NV40TCL_ALPHA_TEST_ENABLE, 3); + so_method(so, nv40->screen->curie, NV40TCL_ALPHA_TEST_ENABLE, 3); so_data (so, cso->alpha.enabled ? 1 : 0); so_data (so, nvgl_comparison_op(cso->alpha.func)); so_data (so, float_to_ubyte(cso->alpha.ref)); if (cso->stencil[0].enabled) { - so_method(so, nv40->hw->curie, NV40TCL_STENCIL_FRONT_ENABLE, 8); + so_method(so, nv40->screen->curie, NV40TCL_STENCIL_FRONT_ENABLE, 8); so_data (so, cso->stencil[0].enabled ? 1 : 0); so_data (so, cso->stencil[0].write_mask); so_data (so, nvgl_comparison_op(cso->stencil[0].func)); @@ -441,12 +441,12 @@ nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe, so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); } else { - so_method(so, nv40->hw->curie, NV40TCL_STENCIL_FRONT_ENABLE, 1); + so_method(so, nv40->screen->curie, NV40TCL_STENCIL_FRONT_ENABLE, 1); so_data (so, 0); } if (cso->stencil[1].enabled) { - so_method(so, nv40->hw->curie, NV40TCL_STENCIL_BACK_ENABLE, 8); + so_method(so, nv40->screen->curie, NV40TCL_STENCIL_BACK_ENABLE, 8); so_data (so, cso->stencil[1].enabled ? 1 : 0); so_data (so, cso->stencil[1].write_mask); so_data (so, nvgl_comparison_op(cso->stencil[1].func)); @@ -456,7 +456,7 @@ nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe, so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); } else { - so_method(so, nv40->hw->curie, NV40TCL_STENCIL_BACK_ENABLE, 1); + so_method(so, nv40->screen->curie, NV40TCL_STENCIL_BACK_ENABLE, 1); so_data (so, 0); } diff --git a/src/gallium/drivers/nv40/nv40_state_blend.c b/src/gallium/drivers/nv40/nv40_state_blend.c index dd09830aa3d..95e6d7394f4 100644 --- a/src/gallium/drivers/nv40/nv40_state_blend.c +++ b/src/gallium/drivers/nv40/nv40_state_blend.c @@ -21,7 +21,7 @@ nv40_state_blend_colour_validate(struct nv40_context *nv40) struct nouveau_stateobj *so = so_new(2, 0); struct pipe_blend_color *bcol = &nv40->blend_colour; - so_method(so, nv40->hw->curie, NV40TCL_BLEND_COLOR, 1); + so_method(so, nv40->screen->curie, NV40TCL_BLEND_COLOR, 1); so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) | (float_to_ubyte(bcol->color[0]) << 16) | (float_to_ubyte(bcol->color[1]) << 8) | diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c index bb2ce0f7221..221503617c3 100644 --- a/src/gallium/drivers/nv40/nv40_state_emit.c +++ b/src/gallium/drivers/nv40/nv40_state_emit.c @@ -67,8 +67,8 @@ nv40_state_emit(struct nv40_context *nv40) while (state->dirty) { unsigned idx = ffsll(state->dirty) - 1; - so_ref (state->hw[idx], &nv40->hw->state[idx]); - so_emit(nv40->nvws, nv40->hw->state[idx]); + so_ref (state->hw[idx], &nv40->screen->state[idx]); + so_emit(nv40->nvws, nv40->screen->state[idx]); state->dirty &= ~(1ULL << idx); } diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c index 3d0ab920030..71795ab1824 100644 --- a/src/gallium/drivers/nv40/nv40_state_fb.c +++ b/src/gallium/drivers/nv40/nv40_state_fb.c @@ -72,73 +72,73 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) } if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) { - so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR0, 1); + so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR0, 1); so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); - so_method(so, nv40->hw->curie, NV40TCL_COLOR0_PITCH, 2); + so_method(so, nv40->screen->curie, NV40TCL_COLOR0_PITCH, 2); so_data (so, rt[0]->pitch * rt[0]->cpp); so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) { - so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR1, 1); + so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR1, 1); so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); - so_method(so, nv40->hw->curie, NV40TCL_COLOR1_OFFSET, 2); + so_method(so, nv40->screen->curie, NV40TCL_COLOR1_OFFSET, 2); so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); so_data (so, rt[1]->pitch * rt[1]->cpp); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { - so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR2, 1); + so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR2, 1); so_reloc (so, rt[2]->buffer, 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); - so_method(so, nv40->hw->curie, NV40TCL_COLOR2_OFFSET, 1); + so_method(so, nv40->screen->curie, NV40TCL_COLOR2_OFFSET, 1); so_reloc (so, rt[2]->buffer, rt[2]->offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_method(so, nv40->hw->curie, NV40TCL_COLOR2_PITCH, 1); + so_method(so, nv40->screen->curie, NV40TCL_COLOR2_PITCH, 1); so_data (so, rt[2]->pitch * rt[2]->cpp); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { - so_method(so, nv40->hw->curie, NV40TCL_DMA_COLOR3, 1); + so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR3, 1); so_reloc (so, rt[3]->buffer, 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); - so_method(so, nv40->hw->curie, NV40TCL_COLOR3_OFFSET, 1); + so_method(so, nv40->screen->curie, NV40TCL_COLOR3_OFFSET, 1); so_reloc (so, rt[3]->buffer, rt[3]->offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_method(so, nv40->hw->curie, NV40TCL_COLOR3_PITCH, 1); + so_method(so, nv40->screen->curie, NV40TCL_COLOR3_PITCH, 1); so_data (so, rt[3]->pitch * rt[3]->cpp); } if (zeta_format) { - so_method(so, nv40->hw->curie, NV40TCL_DMA_ZETA, 1); + so_method(so, nv40->screen->curie, NV40TCL_DMA_ZETA, 1); so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR, nv40->nvws->channel->vram->handle, nv40->nvws->channel->gart->handle); - so_method(so, nv40->hw->curie, NV40TCL_ZETA_OFFSET, 1); + so_method(so, nv40->screen->curie, NV40TCL_ZETA_OFFSET, 1); so_reloc (so, zeta->buffer, zeta->offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_method(so, nv40->hw->curie, NV40TCL_ZETA_PITCH, 1); + so_method(so, nv40->screen->curie, NV40TCL_ZETA_PITCH, 1); so_data (so, zeta->pitch * zeta->cpp); } - so_method(so, nv40->hw->curie, NV40TCL_RT_ENABLE, 1); + so_method(so, nv40->screen->curie, NV40TCL_RT_ENABLE, 1); so_data (so, rt_enable); - so_method(so, nv40->hw->curie, NV40TCL_RT_HORIZ, 3); + so_method(so, nv40->screen->curie, NV40TCL_RT_HORIZ, 3); so_data (so, (w << 16) | 0); so_data (so, (h << 16) | 0); so_data (so, rt_format); - so_method(so, nv40->hw->curie, NV40TCL_VIEWPORT_HORIZ, 2); + so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_HORIZ, 2); so_data (so, (w << 16) | 0); so_data (so, (h << 16) | 0); - so_method(so, nv40->hw->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2); + so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2); so_data (so, ((w - 1) << 16) | 0); so_data (so, ((h - 1) << 16) | 0); diff --git a/src/gallium/drivers/nv40/nv40_state_scissor.c b/src/gallium/drivers/nv40/nv40_state_scissor.c index 09ffc49f965..9e9eadc5116 100644 --- a/src/gallium/drivers/nv40/nv40_state_scissor.c +++ b/src/gallium/drivers/nv40/nv40_state_scissor.c @@ -12,7 +12,7 @@ nv40_state_scissor_validate(struct nv40_context *nv40) return FALSE; so = so_new(3, 0); - so_method(so, nv40->hw->curie, NV40TCL_SCISSOR_HORIZ, 2); + so_method(so, nv40->screen->curie, NV40TCL_SCISSOR_HORIZ, 2); if (rast->scissor) { so_data (so, ((s->maxx - s->minx) << 16) | s->minx); so_data (so, ((s->maxy - s->miny) << 16) | s->miny); diff --git a/src/gallium/drivers/nv40/nv40_state_stipple.c b/src/gallium/drivers/nv40/nv40_state_stipple.c index 001c396d747..b51024ad9b2 100644 --- a/src/gallium/drivers/nv40/nv40_state_stipple.c +++ b/src/gallium/drivers/nv40/nv40_state_stipple.c @@ -4,7 +4,7 @@ static boolean nv40_state_stipple_validate(struct nv40_context *nv40) { struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe; - struct nouveau_grobj *curie = nv40->hw->curie; + struct nouveau_grobj *curie = nv40->screen->curie; struct nouveau_stateobj *so; if (nv40->state.hw[NV40_STATE_STIPPLE] && diff --git a/src/gallium/drivers/nv40/nv40_state_viewport.c b/src/gallium/drivers/nv40/nv40_state_viewport.c index 9616be5052a..3a325339072 100644 --- a/src/gallium/drivers/nv40/nv40_state_viewport.c +++ b/src/gallium/drivers/nv40/nv40_state_viewport.c @@ -6,7 +6,7 @@ nv40_state_viewport_validate(struct nv40_context *nv40) struct nouveau_stateobj *so = so_new(9, 0); struct pipe_viewport_state *vpt = &nv40->viewport; - so_method(so, nv40->hw->curie, NV40TCL_VIEWPORT_TRANSLATE_X, 8); + so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_TRANSLATE_X, 8); so_data (so, fui(vpt->translate[0])); so_data (so, fui(vpt->translate[1])); so_data (so, fui(vpt->translate[2])); diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c index 1653ebf2a7e..bedc8c6d4ef 100644 --- a/src/gallium/drivers/nv40/nv40_vbo.c +++ b/src/gallium/drivers/nv40/nv40_vbo.c @@ -52,7 +52,7 @@ nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib, } /* No support for 8bit indices, no support at all on 0x4497 chips */ - if (nv40->hw->curie->grclass == NV44TCL || ib_size == 1) + if (nv40->screen->curie->grclass == NV44TCL || ib_size == 1) return FALSE; switch (ib_size) { @@ -365,9 +365,9 @@ nv40_vbo_validate(struct nv40_context *nv40) num_hw++; vtxbuf = so_new(20, 18); - so_method(vtxbuf, nv40->hw->curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw); + so_method(vtxbuf, nv40->screen->curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw); vtxfmt = so_new(17, 0); - so_method(vtxfmt, nv40->hw->curie, NV40TCL_VTXFMT(0), num_hw); + so_method(vtxfmt, nv40->screen->curie, NV40TCL_VTXFMT(0), num_hw); inputs = vp->ir; for (hw = 0; hw < num_hw; hw++) { @@ -399,13 +399,13 @@ nv40_vbo_validate(struct nv40_context *nv40) } if (ib) { - so_method(vtxbuf, nv40->hw->curie, NV40TCL_IDXBUF_ADDRESS, 2); + so_method(vtxbuf, nv40->screen->curie, NV40TCL_IDXBUF_ADDRESS, 2); so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR, 0, NV40TCL_IDXBUF_FORMAT_DMA1); } - so_method(vtxbuf, nv40->hw->curie, 0x1710, 1); + so_method(vtxbuf, nv40->screen->curie, 0x1710, 1); so_data (vtxbuf, 0); so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]); diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c index d3ed57b1998..5b7a343e55d 100644 --- a/src/gallium/drivers/nv40/nv40_vertprog.c +++ b/src/gallium/drivers/nv40/nv40_vertprog.c @@ -655,7 +655,7 @@ nv40_vertprog_validate(struct nv40_context *nv40) check_gpu_resources: /* Allocate hw vtxprog exec slots */ if (!vp->exec) { - struct nouveau_resource *heap = nv40->hw->vp_exec_heap; + struct nouveau_resource *heap = nv40->screen->vp_exec_heap; struct nouveau_stateobj *so; uint vplen = vp->nr_insns; @@ -672,9 +672,9 @@ check_gpu_resources: } so = so_new(5, 0); - so_method(so, nv40->hw->curie, NV40TCL_VP_START_FROM_ID, 1); + so_method(so, nv40->screen->curie, NV40TCL_VP_START_FROM_ID, 1); so_data (so, vp->exec->start); - so_method(so, nv40->hw->curie, NV40TCL_VP_ATTRIB_EN, 2); + so_method(so, nv40->screen->curie, NV40TCL_VP_ATTRIB_EN, 2); so_data (so, vp->ir); so_data (so, vp->or); so_ref(so, &vp->so); @@ -684,7 +684,7 @@ check_gpu_resources: /* Allocate hw vtxprog const slots */ if (vp->nr_consts && !vp->data) { - struct nouveau_resource *heap = nv40->hw->vp_data_heap; + struct nouveau_resource *heap = nv40->screen->vp_data_heap; if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) { while (heap->next && heap->size < vp->nr_consts) { -- cgit v1.2.3 From b560ed2444383b9634786fe742b8cb6f5cdfc781 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 2 Mar 2008 14:56:42 +1100 Subject: nouveau: enable multi-context/single-channel support for nv40 --- src/gallium/drivers/nouveau/nouveau_winsys.h | 6 +-- src/gallium/drivers/nv30/nv30_context.c | 2 +- src/gallium/drivers/nv40/nv40_context.c | 3 +- src/gallium/drivers/nv40/nv40_context.h | 1 + src/gallium/drivers/nv40/nv40_screen.h | 2 + src/gallium/drivers/nv40/nv40_state_emit.c | 10 ++++ src/gallium/drivers/nv50/nv50_context.c | 2 +- src/gallium/winsys/dri/nouveau/nouveau_context.c | 63 +++++++++++++++++++++--- src/gallium/winsys/dri/nouveau/nouveau_context.h | 8 +++ src/gallium/winsys/dri/nouveau/nouveau_screen.h | 2 + src/gallium/winsys/dri/nouveau/nouveau_winsys.c | 10 ++-- 11 files changed, 94 insertions(+), 15 deletions(-) (limited to 'src/gallium/drivers/nv40/nv40_screen.h') diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index 11ca7e80ddb..44c8bb919bb 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -54,20 +54,20 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, unsigned chipset); extern struct pipe_context * -nv30_create(struct pipe_screen *); +nv30_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, unsigned chipset); extern struct pipe_context * -nv40_create(struct pipe_screen *); +nv40_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, unsigned chipset); extern struct pipe_context * -nv50_create(struct pipe_screen *); +nv50_create(struct pipe_screen *, unsigned pctx_id); #endif diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c index 522fb132269..28d3f057cc4 100644 --- a/src/gallium/drivers/nv30/nv30_context.c +++ b/src/gallium/drivers/nv30/nv30_context.c @@ -265,7 +265,7 @@ nv30_init_hwctx(struct nv30_context *nv30, int rankine_class) #define NV35TCL_CHIPSET_3X_MASK 0x000001e0 struct pipe_context * -nv30_create(struct pipe_screen *screen) +nv30_create(struct pipe_screen *screen, unsigned pctx_id) { struct pipe_winsys *pipe_winsys = screen->winsys; struct nouveau_winsys *nvws = nv30_screen(screen)->nvws; diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c index 084829ce281..203c843a013 100644 --- a/src/gallium/drivers/nv40/nv40_context.c +++ b/src/gallium/drivers/nv40/nv40_context.c @@ -44,7 +44,7 @@ nv40_destroy(struct pipe_context *pipe) } struct pipe_context * -nv40_create(struct pipe_screen *pscreen) +nv40_create(struct pipe_screen *pscreen, unsigned pctx_id) { struct nv40_screen *screen = nv40_screen(pscreen); struct pipe_winsys *ws = pscreen->winsys; @@ -56,6 +56,7 @@ nv40_create(struct pipe_screen *pscreen) if (!nv40) return NULL; nv40->screen = screen; + nv40->pctx_id = pctx_id; nv40->chipset = chipset; nv40->nvws = nvws; diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index 3b669594dc3..e118776306b 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -108,6 +108,7 @@ struct nv40_context { struct nouveau_winsys *nvws; struct nv40_screen *screen; + unsigned pctx_id; struct draw_context *draw; diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index 9f9668dbb6b..3ea78aadfd9 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -9,6 +9,8 @@ struct nv40_screen { struct nouveau_winsys *nvws; unsigned chipset; + unsigned cur_pctx; + /* HW graphics objects */ struct nouveau_grobj *curie; struct nouveau_notifier *sync; diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c index 221503617c3..a95e2472e2b 100644 --- a/src/gallium/drivers/nv40/nv40_state_emit.c +++ b/src/gallium/drivers/nv40/nv40_state_emit.c @@ -62,8 +62,18 @@ static void nv40_state_emit(struct nv40_context *nv40) { struct nv40_state *state = &nv40->state; + struct nv40_screen *screen = nv40->screen; unsigned i, samplers; + if (nv40->pctx_id != screen->cur_pctx) { + for (i = 0; i < NV40_STATE_MAX; i++) { + if (screen->state[i] != state->hw[i] && state->hw[i]) + state->dirty |= (1ULL << i); + } + + screen->cur_pctx = nv40->pctx_id; + } + while (state->dirty) { unsigned idx = ffsll(state->dirty) - 1; diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index e5054e34f6b..c937b8de6d4 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -56,7 +56,7 @@ nv50_init_hwctx(struct nv50_context *nv50, int tesla_class) #define GRCLASS5097_CHIPSETS 0x00000000 #define GRCLASS8297_CHIPSETS 0x00000010 struct pipe_context * -nv50_create(struct pipe_screen *pscreen) +nv50_create(struct pipe_screen *pscreen, unsigned pctx_id) { struct pipe_winsys *pipe_winsys = pscreen->winsys; struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws; diff --git a/src/gallium/winsys/dri/nouveau/nouveau_context.c b/src/gallium/winsys/dri/nouveau/nouveau_context.c index 7915afae226..dc852c9f498 100644 --- a/src/gallium/winsys/dri/nouveau/nouveau_context.c +++ b/src/gallium/winsys/dri/nouveau/nouveau_context.c @@ -4,6 +4,7 @@ #include "utils.h" #include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" #include "pipe/p_defines.h" #include "pipe/p_context.h" @@ -101,7 +102,8 @@ nouveau_context_create(const __GLcontextModes *glVis, struct nouveau_device_priv *nvdev; struct pipe_context *pipe = NULL; struct st_context *st_share = NULL; - int ret; + struct nouveau_channel_context *nvc = NULL; + int i, ret; if (sharedContextPrivate) { st_share = ((struct nouveau_context *)sharedContextPrivate)->st; @@ -163,12 +165,56 @@ nouveau_context_create(const __GLcontextModes *glVis, nv->frontbuffer = fb_surf; } - nv->nvc = nouveau_channel_context_create(&nvdev->base, nv->chipset); - if (!nv->nvc) { - NOUVEAU_ERR("Failed initialising GPU channel context\n"); - return GL_FALSE; + /* Attempt to share a single channel between multiple contexts from + * a single process. + */ + nvc = nv_screen->nvc; + if (!nvc && st_share) { + struct nouveau_context *snv = st_share->pipe->priv; + if (snv) { + nvc = snv->nvc; + } + } + + /*XXX: temporary - disable multi-context/single-channel on non-NV4x */ + switch (nv->chipset & 0xf0) { + case 0x40: + case 0x60: + break; + default: + nvc = NULL; + break; + } + + if (!nvc) { + nvc = nouveau_channel_context_create(&nvdev->base, nv->chipset); + if (!nvc) { + NOUVEAU_ERR("Failed initialising GPU context\n"); + return GL_FALSE; + } + nv_screen->nvc = nvc; + } + + nvc->refcount++; + nv->nvc = nvc; + + /* Find a free slot for a pipe context, allocate a new one if needed */ + nv->pctx_id = -1; + for (i = 0; i < nvc->nr_pctx; i++) { + if (nvc->pctx[i] == NULL) { + nv->pctx_id = i; + break; + } } + if (nv->pctx_id < 0) { + nv->pctx_id = nvc->nr_pctx++; + nvc->pctx = + realloc(nvc->pctx, + sizeof(struct pipe_context *) * nvc->nr_pctx); + } + + /* Create pipe */ if (nv->chipset < 0x50) ret = nouveau_surface_init_nv04(nv); else @@ -201,13 +247,18 @@ void nouveau_context_destroy(__DRIcontextPrivate *driContextPriv) { struct nouveau_context *nv = driContextPriv->driverPrivate; + struct nouveau_channel_context *nvc = nv->nvc; assert(nv); st_flush(nv->st, PIPE_FLUSH_WAIT); st_destroy_context(nv->st); - nouveau_channel_context_destroy(nv->nvc); + if (nv->pctx_id >= 0) { + nvc->pctx[nv->pctx_id] = NULL; + if (--nvc->refcount <= 0) + nouveau_channel_context_destroy(nvc); + } free(nv); } diff --git a/src/gallium/winsys/dri/nouveau/nouveau_context.h b/src/gallium/winsys/dri/nouveau/nouveau_context.h index 736c8d8bef3..92f551855a4 100644 --- a/src/gallium/winsys/dri/nouveau/nouveau_context.h +++ b/src/gallium/winsys/dri/nouveau/nouveau_context.h @@ -14,6 +14,13 @@ struct nouveau_framebuffer { }; struct nouveau_channel_context { + struct pipe_screen *pscreen; + int refcount; + + unsigned cur_pctx; + unsigned nr_pctx; + struct pipe_context **pctx; + unsigned chipset; struct nouveau_channel *channel; @@ -51,6 +58,7 @@ struct nouveau_context { /* Hardware context */ struct nouveau_channel_context *nvc; + int pctx_id; /* pipe_surface accel */ struct pipe_surface *surf_src, *surf_dst; diff --git a/src/gallium/winsys/dri/nouveau/nouveau_screen.h b/src/gallium/winsys/dri/nouveau/nouveau_screen.h index 019823bd44d..e9da2026904 100644 --- a/src/gallium/winsys/dri/nouveau/nouveau_screen.h +++ b/src/gallium/winsys/dri/nouveau/nouveau_screen.h @@ -14,6 +14,8 @@ struct nouveau_screen { uint32_t front_pitch; uint32_t front_cpp; uint32_t front_height; + + void *nvc; }; #endif diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c index 50d7549b1b7..87619bdcfb4 100644 --- a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c +++ b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c @@ -70,11 +70,12 @@ nouveau_pipe_emit_reloc(struct nouveau_channel *chan, void *ptr, struct pipe_context * nouveau_pipe_create(struct nouveau_context *nv) { + struct nouveau_channel_context *nvc = nv->nvc; struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys); struct pipe_screen *(*hws_create)(struct pipe_winsys *, struct nouveau_winsys *, unsigned chipset); - struct pipe_context *(*hw_create)(struct pipe_screen *); + struct pipe_context *(*hw_create)(struct pipe_screen *, unsigned); struct pipe_winsys *ws; struct pipe_screen *pscreen; @@ -125,7 +126,10 @@ nouveau_pipe_create(struct nouveau_context *nv) nvws->surface_fill = nouveau_pipe_surface_fill; ws = nouveau_create_pipe_winsys(nv); - pscreen = hws_create(ws, nvws, nv->chipset); - return hw_create(pscreen); + + if (!nvc->pscreen) + nvc->pscreen = hws_create(ws, nvws, nv->chipset); + nvc->pctx[nv->pctx_id] = hw_create(nvc->pscreen, nv->pctx_id); + return nvc->pctx[nv->pctx_id]; } -- cgit v1.2.3 From 1ef08564d2a201a422db772a6bb23d1129888304 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 13 May 2008 12:16:35 +1000 Subject: nouveau: remove chipset fields in all nv pipe driver context/screen structs. --- src/gallium/drivers/nouveau/nouveau_winsys.h | 13 +++++-------- src/gallium/drivers/nv10/nv10_context.c | 2 -- src/gallium/drivers/nv10/nv10_context.h | 2 -- src/gallium/drivers/nv10/nv10_screen.c | 8 ++++---- src/gallium/drivers/nv10/nv10_screen.h | 1 - src/gallium/drivers/nv30/nv30_context.c | 2 -- src/gallium/drivers/nv30/nv30_context.h | 2 -- src/gallium/drivers/nv30/nv30_screen.c | 8 ++++---- src/gallium/drivers/nv30/nv30_screen.h | 1 - src/gallium/drivers/nv40/nv40_context.c | 2 -- src/gallium/drivers/nv40/nv40_context.h | 2 -- src/gallium/drivers/nv40/nv40_screen.c | 8 ++++---- src/gallium/drivers/nv40/nv40_screen.h | 1 - src/gallium/drivers/nv50/nv50_screen.c | 8 ++++---- src/gallium/drivers/nv50/nv50_screen.h | 1 - src/gallium/winsys/dri/nouveau/nouveau_winsys.c | 5 ++--- 16 files changed, 23 insertions(+), 43 deletions(-) (limited to 'src/gallium/drivers/nv40/nv40_screen.h') diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index fbde7adc6ad..07a41dcf4a1 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -8,6 +8,7 @@ #include "nouveau/nouveau_bo.h" #include "nouveau/nouveau_channel.h" #include "nouveau/nouveau_class.h" +#include "nouveau/nouveau_device.h" #include "nouveau/nouveau_grobj.h" #include "nouveau/nouveau_notifier.h" #include "nouveau/nouveau_resource.h" @@ -56,29 +57,25 @@ struct nouveau_winsys { }; extern struct pipe_screen * -nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, - unsigned chipset); +nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); extern struct pipe_context * nv10_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, - unsigned chipset); +nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); extern struct pipe_context * nv30_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, - unsigned chipset); +nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); extern struct pipe_context * nv40_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * -nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *, - unsigned chipset); +nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); extern struct pipe_context * nv50_create(struct pipe_screen *, unsigned pctx_id); diff --git a/src/gallium/drivers/nv10/nv10_context.c b/src/gallium/drivers/nv10/nv10_context.c index a25c082a5d1..79253f8a2b3 100644 --- a/src/gallium/drivers/nv10/nv10_context.c +++ b/src/gallium/drivers/nv10/nv10_context.c @@ -264,7 +264,6 @@ nv10_create(struct pipe_screen *pscreen, unsigned pctx_id) struct nv10_screen *screen = nv10_screen(pscreen); struct pipe_winsys *ws = pscreen->winsys; struct nv10_context *nv10; - unsigned chipset = screen->chipset; struct nouveau_winsys *nvws = screen->nvws; nv10 = CALLOC(1, sizeof(struct nv10_context)); @@ -273,7 +272,6 @@ nv10_create(struct pipe_screen *pscreen, unsigned pctx_id) nv10->screen = screen; nv10->pctx_id = pctx_id; - nv10->chipset = chipset; nv10->nvws = nvws; nv10->pipe.winsys = ws; diff --git a/src/gallium/drivers/nv10/nv10_context.h b/src/gallium/drivers/nv10/nv10_context.h index 1b794c18724..433d04dc2a8 100644 --- a/src/gallium/drivers/nv10/nv10_context.h +++ b/src/gallium/drivers/nv10/nv10_context.h @@ -43,8 +43,6 @@ struct nv10_context { struct draw_context *draw; - int chipset; - uint32_t dirty; struct nv10_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c index cf6b2fac84e..fad96058b8e 100644 --- a/src/gallium/drivers/nv10/nv10_screen.c +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -8,9 +8,10 @@ static const char * nv10_screen_get_name(struct pipe_screen *screen) { struct nv10_screen *nv10screen = nv10_screen(screen); + struct nouveau_device *dev = nv10screen->nvws->channel->device; static char buffer[128]; - snprintf(buffer, sizeof(buffer), "NV%02X", nv10screen->chipset); + snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); return buffer; } @@ -129,16 +130,15 @@ nv10_screen_destroy(struct pipe_screen *pscreen) } struct pipe_screen * -nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws, - unsigned chipset) +nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) { struct nv10_screen *screen = CALLOC_STRUCT(nv10_screen); unsigned celsius_class; + unsigned chipset = nvws->channel->device->chipset; int ret; if (!screen) return NULL; - screen->chipset = chipset; screen->nvws = nvws; /* 3D object */ diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h index 4192fe11ef4..3f8750a13f7 100644 --- a/src/gallium/drivers/nv10/nv10_screen.h +++ b/src/gallium/drivers/nv10/nv10_screen.h @@ -7,7 +7,6 @@ struct nv10_screen { struct pipe_screen pipe; struct nouveau_winsys *nvws; - unsigned chipset; /* HW graphics objects */ struct nouveau_grobj *celsius; diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c index 4b0892971ec..7a2fee78751 100644 --- a/src/gallium/drivers/nv30/nv30_context.c +++ b/src/gallium/drivers/nv30/nv30_context.c @@ -44,7 +44,6 @@ nv30_create(struct pipe_screen *pscreen, unsigned pctx_id) struct nv30_screen *screen = nv30_screen(pscreen); struct pipe_winsys *ws = pscreen->winsys; struct nv30_context *nv30; - unsigned chipset = screen->chipset; struct nouveau_winsys *nvws = screen->nvws; nv30 = CALLOC(1, sizeof(struct nv30_context)); @@ -53,7 +52,6 @@ nv30_create(struct pipe_screen *pscreen, unsigned pctx_id) nv30->screen = screen; nv30->pctx_id = pctx_id; - nv30->chipset = chipset; nv30->nvws = nvws; nv30->pipe.winsys = ws; diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h index 1a016405e62..f49450f82d9 100644 --- a/src/gallium/drivers/nv30/nv30_context.h +++ b/src/gallium/drivers/nv30/nv30_context.h @@ -85,8 +85,6 @@ struct nv30_context { struct draw_context *draw; - int chipset; - uint32_t dirty; struct nv30_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 1de45079043..9b0ac55ff88 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -12,9 +12,10 @@ static const char * nv30_screen_get_name(struct pipe_screen *pscreen) { struct nv30_screen *screen = nv30_screen(pscreen); + struct nouveau_device *dev = screen->nvws->channel->device; static char buffer[128]; - snprintf(buffer, sizeof(buffer), "NV%02X", screen->chipset); + snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); return buffer; } @@ -140,17 +141,16 @@ nv30_screen_destroy(struct pipe_screen *pscreen) } struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws, - unsigned chipset) +nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) { struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen); struct nouveau_stateobj *so; unsigned rankine_class = 0; + unsigned chipset = nvws->channel->device->chipset; int ret, i; if (!screen) return NULL; - screen->chipset = chipset; screen->nvws = nvws; /* 3D object */ diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h index 56f8776a173..816ece94c4a 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -7,7 +7,6 @@ struct nv30_screen { struct pipe_screen pipe; struct nouveau_winsys *nvws; - unsigned chipset; /* HW graphics objects */ struct nouveau_grobj *rankine; diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c index f9c93f7a2d7..d9d9accea8d 100644 --- a/src/gallium/drivers/nv40/nv40_context.c +++ b/src/gallium/drivers/nv40/nv40_context.c @@ -38,7 +38,6 @@ nv40_create(struct pipe_screen *pscreen, unsigned pctx_id) struct nv40_screen *screen = nv40_screen(pscreen); struct pipe_winsys *ws = pscreen->winsys; struct nv40_context *nv40; - unsigned chipset = screen->chipset; struct nouveau_winsys *nvws = screen->nvws; nv40 = CALLOC(1, sizeof(struct nv40_context)); @@ -47,7 +46,6 @@ nv40_create(struct pipe_screen *pscreen, unsigned pctx_id) nv40->screen = screen; nv40->pctx_id = pctx_id; - nv40->chipset = chipset; nv40->nvws = nvws; nv40->pipe.winsys = ws; diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index 24e8cd23379..77b3da0ab91 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -111,8 +111,6 @@ struct nv40_context { struct draw_context *draw; - int chipset; - /* HW state derived from pipe states */ struct nv40_state state; struct { diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 7f68539a85c..1bf0931e4d9 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -12,9 +12,10 @@ static const char * nv40_screen_get_name(struct pipe_screen *pscreen) { struct nv40_screen *screen = nv40_screen(pscreen); + struct nouveau_device *dev = screen->nvws->channel->device; static char buffer[128]; - snprintf(buffer, sizeof(buffer), "NV%02X", screen->chipset); + snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); return buffer; } @@ -149,17 +150,16 @@ nv40_screen_destroy(struct pipe_screen *pscreen) } struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws, - unsigned chipset) +nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) { struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); struct nouveau_stateobj *so; unsigned curie_class; + unsigned chipset = nvws->channel->device; int ret; if (!screen) return NULL; - screen->chipset = chipset; screen->nvws = nvws; /* 3D object */ diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index 3ea78aadfd9..c04a1275a00 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -7,7 +7,6 @@ struct nv40_screen { struct pipe_screen pipe; struct nouveau_winsys *nvws; - unsigned chipset; unsigned cur_pctx; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index e4ca72c7171..d069639dc48 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -45,9 +45,10 @@ static const char * nv50_screen_get_name(struct pipe_screen *pscreen) { struct nv50_screen *screen = nv50_screen(pscreen); + struct nouveau_device *dev = screen->nvws->channel->device; static char buffer[128]; - snprintf(buffer, sizeof(buffer), "NV%02X", screen->chipset); + snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); return buffer; } @@ -123,17 +124,16 @@ nv50_screen_destroy(struct pipe_screen *pscreen) } struct pipe_screen * -nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws, - unsigned chipset) +nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) { struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen); struct nouveau_stateobj *so; unsigned tesla_class = 0, ret; + unsigned chipset = nvws->channel->device->chipset; int i; if (!screen) return NULL; - screen->chipset = chipset; screen->nvws = nvws; /* 3D object */ diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 6e4120d6693..5a2732e37f4 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -7,7 +7,6 @@ struct nv50_screen { struct pipe_screen pipe; struct nouveau_winsys *nvws; - unsigned chipset; unsigned cur_pctx; diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c index 635fd478a94..5eabbc88939 100644 --- a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c +++ b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c @@ -91,8 +91,7 @@ nouveau_pipe_create(struct nouveau_context *nv) struct nouveau_channel_context *nvc = nv->nvc; struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys); struct pipe_screen *(*hws_create)(struct pipe_winsys *, - struct nouveau_winsys *, - unsigned chipset); + struct nouveau_winsys *); struct pipe_context *(*hw_create)(struct pipe_screen *, unsigned); struct pipe_winsys *ws; unsigned chipset = nv->nv_screen->device->chipset; @@ -152,7 +151,7 @@ nouveau_pipe_create(struct nouveau_context *nv) ws = nouveau_create_pipe_winsys(nv); if (!nvc->pscreen) - nvc->pscreen = hws_create(ws, nvws, chipset); + nvc->pscreen = hws_create(ws, nvws); nvc->pctx[nv->pctx_id] = hw_create(nvc->pscreen, nv->pctx_id); return nvc->pctx[nv->pctx_id]; } -- cgit v1.2.3 From ff8dff017e537c6db4c86aad43e92b768cb187e4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 5 Feb 2009 18:19:32 +1000 Subject: nv04-nv40: move 2d blit/fill code into pipe driver --- src/gallium/drivers/nouveau/nouveau_winsys.h | 2 +- src/gallium/drivers/nv04/Makefile | 1 + src/gallium/drivers/nv04/nv04_screen.c | 13 + src/gallium/drivers/nv04/nv04_screen.h | 2 + src/gallium/drivers/nv04/nv04_surface.c | 17 +- src/gallium/drivers/nv04/nv04_surface_2d.c | 449 ++++++++++++++++++++ src/gallium/drivers/nv04/nv04_surface_2d.h | 29 ++ src/gallium/drivers/nv10/nv10_screen.c | 12 + src/gallium/drivers/nv10/nv10_screen.h | 2 + src/gallium/drivers/nv10/nv10_surface.c | 17 +- src/gallium/drivers/nv20/nv20_screen.c | 12 + src/gallium/drivers/nv20/nv20_screen.h | 2 + src/gallium/drivers/nv20/nv20_surface.c | 17 +- src/gallium/drivers/nv30/nv30_screen.c | 12 + src/gallium/drivers/nv30/nv30_screen.h | 2 + src/gallium/drivers/nv30/nv30_surface.c | 20 +- src/gallium/drivers/nv40/nv40_screen.c | 12 + src/gallium/drivers/nv40/nv40_screen.h | 2 + src/gallium/drivers/nv40/nv40_surface.c | 20 +- src/gallium/winsys/drm/nouveau/common/Makefile | 4 +- .../winsys/drm/nouveau/common/nouveau_context.c | 49 +-- .../winsys/drm/nouveau/common/nouveau_context.h | 33 +- .../winsys/drm/nouveau/common/nouveau_winsys.c | 32 +- .../drm/nouveau/common/nouveau_winsys_pipe.c | 6 +- .../drm/nouveau/common/nouveau_winsys_pipe.h | 11 +- .../winsys/drm/nouveau/common/nv04_surface.c | 458 --------------------- .../winsys/drm/nouveau/dri/nouveau_swapbuffers.c | 43 +- 27 files changed, 625 insertions(+), 654 deletions(-) create mode 100644 src/gallium/drivers/nv04/nv04_surface_2d.c create mode 100644 src/gallium/drivers/nv04/nv04_surface_2d.h delete mode 100644 src/gallium/winsys/drm/nouveau/common/nv04_surface.c (limited to 'src/gallium/drivers/nv40/nv40_screen.h') diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index 99f8e08201c..b86c4b93388 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 5ea51a2f420..4ed62dae95d 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 e5e3d4772aa..9ef38bc244c 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 99a49cdf7a9..540aec907bf 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 0d0983f9d4c..1d11f53f2a1 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 00000000000..75295831511 --- /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 00000000000..21b8f869606 --- /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 2f945a193cc..f417b06c944 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 3f8750a13f7..60102a369a9 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 78fd7b42dac..1093dfd62ed 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 c9171fa1781..5f2b7b4f71f 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 8f2f2e341db..bf2f2c0d9fb 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 9b4c028eae6..a79974ce5e4 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 9738436dc47..2bc83f815b3 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 b7ddc2a9594..b11e470f949 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 806131dcc95..b46b6123cf7 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 41d342d27d2..a2b124d2289 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 c04a1275a00..4500aa0e5cc 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 aa51d040519..68bbfce448b 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 4cd315e2895..c6dd6dd7f99 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 7be3e94d492..d6ae0827cd7 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 66883e85fec..02d2745680c 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 ef7e8aac54a..b6199f8e6db 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c +++ b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c @@ -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); 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 c17d8a05e60..881df985563 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 b041a77e38b..1eb80434789 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 214c8437826..00000000000 --- 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 450c981ca44..58cb6f7265c 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); -- cgit v1.2.3