diff options
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_context.c')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_context.c | 173 |
1 files changed, 123 insertions, 50 deletions
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 4f976161760..bb6272a4a23 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Ben Skeggs + * Copyright 2010 Christoph Bumiller * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,80 +27,153 @@ #include "nv50_screen.h" #include "nv50_resource.h" +#include "nouveau/nouveau_reloc.h" + static void nv50_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence) + struct pipe_fence_handle **fence) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_channel *chan = nv50->screen->base.channel; + + if (flags & PIPE_FLUSH_TEXTURE_CACHE) { + BEGIN_RING(chan, RING_3D_(NV50_GRAPH_WAIT_FOR_IDLE), 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1); + OUT_RING (chan, 0x20); + } + + if (fence) + nv50_fence_reference((struct nv50_fence **)fence, + nv50->screen->fence.current); + + if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME)) + FIRE_RING(chan); +} + +void +nv50_default_flush_notify(struct nouveau_channel *chan) { - struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->base.channel; + struct nv50_context *nv50 = chan->user_private; + + if (!nv50) + return; - if (flags & PIPE_FLUSH_TEXTURE_CACHE) { - BEGIN_RING(chan, nv50->screen->tesla, 0x1338, 1); - OUT_RING (chan, 0x20); - } + nv50_screen_fence_update(nv50->screen, TRUE); - if (flags & PIPE_FLUSH_FRAME) - FIRE_RING(chan); + nv50_screen_fence_next(nv50->screen); } static void nv50_destroy(struct pipe_context *pipe) { - struct nv50_context *nv50 = nv50_context(pipe); - int i; - - for (i = 0; i < nv50->vtxbuf_nr; i++) { - pipe_resource_reference(&nv50->vtxbuf[i].buffer, NULL); - } + struct nv50_context *nv50 = nv50_context(pipe); - for (i = 0; i < 64; i++) { - if (!nv50->state.hw[i]) - continue; - so_ref(NULL, &nv50->state.hw[i]); - } + draw_destroy(nv50->draw); - draw_destroy(nv50->draw); + if (nv50->screen->cur_ctx == nv50) { + nv50->screen->base.channel->user_private = NULL; + nv50->screen->cur_ctx = NULL; + } - if (nv50->screen->cur_ctx == nv50) - nv50->screen->cur_ctx = NULL; - - FREE(nv50); + FREE(nv50); } - struct pipe_context * nv50_create(struct pipe_screen *pscreen, void *priv) { - struct pipe_winsys *pipe_winsys = pscreen->winsys; - struct nv50_screen *screen = nv50_screen(pscreen); - struct nv50_context *nv50; + struct pipe_winsys *pipe_winsys = pscreen->winsys; + struct nv50_screen *screen = nv50_screen(pscreen); + struct nv50_context *nv50; + + nv50 = CALLOC_STRUCT(nv50_context); + if (!nv50) + return NULL; + nv50->screen = screen; + + nv50->pipe.winsys = pipe_winsys; + nv50->pipe.screen = pscreen; + nv50->pipe.priv = priv; + + nv50->pipe.destroy = nv50_destroy; + + nv50->pipe.draw_vbo = nv50_draw_vbo; + nv50->pipe.clear = nv50_clear; - nv50 = CALLOC_STRUCT(nv50_context); - if (!nv50) - return NULL; - nv50->screen = screen; + nv50->pipe.flush = nv50_flush; - nv50->pipe.winsys = pipe_winsys; - nv50->pipe.screen = pscreen; - nv50->pipe.priv = priv; + screen->base.channel->user_private = nv50; + screen->base.channel->flush_notify = nv50_default_flush_notify; - nv50->pipe.destroy = nv50_destroy; + nv50_init_query_functions(nv50); + nv50_init_surface_functions(nv50); + nv50_init_state_functions(nv50); + nv50_init_resource_functions(&nv50->pipe); - nv50->pipe.draw_vbo = nv50_draw_vbo; - nv50->pipe.clear = nv50_clear; + nv50->draw = draw_create(&nv50->pipe); + assert(nv50->draw); + draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50)); - nv50->pipe.flush = nv50_flush; + return &nv50->pipe; +} + +struct resident { + struct nv50_resource *res; + uint32_t flags; +}; + +void +nv50_bufctx_add_resident(struct nv50_context *nv50, int ctx, + struct nv50_resource *resource, uint32_t flags) +{ + struct resident rsd = { resource, flags }; + + if (!resource->bo) + return; + + /* We don't need to reference the resource here, it will be referenced + * in the context/state, and bufctx will be reset when state changes. + */ + util_dynarray_append(&nv50->residents[ctx], struct resident, rsd); +} + +void +nv50_bufctx_del_resident(struct nv50_context *nv50, int ctx, + struct nv50_resource *resource) +{ + struct resident *rsd, *top; + unsigned i; + + for (i = 0; i < nv50->residents[ctx].size / sizeof(struct resident); ++i) { + rsd = util_dynarray_element(&nv50->residents[ctx], struct resident, i); + + if (rsd->res == resource) { + top = util_dynarray_pop_ptr(&nv50->residents[ctx], struct resident); + if (rsd != top) + *rsd = *top; + break; + } + } +} + +void +nv50_bufctx_emit_relocs(struct nv50_context *nv50) +{ + struct resident *rsd; + struct util_dynarray *array; + unsigned ctx, i, n; - screen->base.channel->user_private = nv50; + for (ctx = 0; ctx < NV50_BUFCTX_COUNT; ++ctx) { + array = &nv50->residents[ctx]; - nv50_init_surface_functions(nv50); - nv50_init_state_functions(nv50); - nv50_init_query_functions(nv50); - nv50_init_resource_functions(&nv50->pipe); + n = array->size / sizeof(struct resident); + MARK_RING(nv50->screen->base.channel, n, n); + for (i = 0; i < n; ++i) { + rsd = util_dynarray_element(array, struct resident, i); - nv50->draw = draw_create(&nv50->pipe); - assert(nv50->draw); - draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50)); + nv50_resource_validate(rsd->res, rsd->flags); + } + } - return &nv50->pipe; + nv50_screen_make_buffers_resident(nv50->screen); } |