diff options
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_context.c')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_context.c | 180 |
1 files changed, 130 insertions, 50 deletions
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 4f976161760..912367b8391 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,160 @@ #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) + nouveau_fence_ref(nv50->screen->base.fence.current, + (struct nouveau_fence **)fence); + + 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 (flags & PIPE_FLUSH_TEXTURE_CACHE) { - BEGIN_RING(chan, nv50->screen->tesla, 0x1338, 1); - OUT_RING (chan, 0x20); - } + if (!nv50) + return; - if (flags & PIPE_FLUSH_FRAME) - FIRE_RING(chan); + nouveau_fence_update(&nv50->screen->base, TRUE); + nouveau_fence_next(&nv50->screen->base); } 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); - } - - for (i = 0; i < 64; i++) { - if (!nv50->state.hw[i]) - continue; - so_ref(NULL, &nv50->state.hw[i]); - } + struct nv50_context *nv50 = nv50_context(pipe); - draw_destroy(nv50->draw); + draw_destroy(nv50->draw); - if (nv50->screen->cur_ctx == nv50) - nv50->screen->cur_ctx = NULL; + if (nv50->screen->cur_ctx == nv50) { + nv50->screen->base.channel->user_private = NULL; + 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; + struct pipe_context *pipe; + + nv50 = CALLOC_STRUCT(nv50_context); + if (!nv50) + return NULL; + pipe = &nv50->base.pipe; + + nv50->screen = screen; + nv50->base.screen = &screen->base; + nv50->base.copy_data = nv50_m2mf_copy_linear; + nv50->base.push_data = nv50_sifc_linear_u8; + + pipe->winsys = pipe_winsys; + pipe->screen = pscreen; + pipe->priv = priv; + + pipe->destroy = nv50_destroy; + + pipe->draw_vbo = nv50_draw_vbo; + pipe->clear = nv50_clear; - nv50 = CALLOC_STRUCT(nv50_context); - if (!nv50) - return NULL; - nv50->screen = screen; + pipe->flush = nv50_flush; - nv50->pipe.winsys = pipe_winsys; - nv50->pipe.screen = pscreen; - nv50->pipe.priv = priv; + if (!screen->cur_ctx) + screen->cur_ctx = nv50; + 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(pipe); - nv50->pipe.draw_vbo = nv50_draw_vbo; - nv50->pipe.clear = nv50_clear; + nv50->draw = draw_create(pipe); + assert(nv50->draw); + draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50)); - nv50->pipe.flush = nv50_flush; + return pipe; +} + +struct resident { + struct nv04_resource *res; + uint32_t flags; +}; + +void +nv50_bufctx_add_resident(struct nv50_context *nv50, int ctx, + struct nv04_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 nv04_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); } |