summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv50/nv50_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_context.c')
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c180
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);
}