r600g: Move fetch shader register setup to r600_state.c / evergreen_state.c.
[mesa.git] / src / gallium / drivers / nv50 / nv50_context.c
1 /*
2 * Copyright 2010 Christoph Bumiller
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "draw/draw_context.h"
24 #include "pipe/p_defines.h"
25
26 #include "nv50_context.h"
27 #include "nv50_screen.h"
28 #include "nv50_resource.h"
29
30 #include "nouveau/nouveau_reloc.h"
31
32 static void
33 nv50_flush(struct pipe_context *pipe,
34 struct pipe_fence_handle **fence)
35 {
36 struct nouveau_screen *screen = &nv50_context(pipe)->screen->base;
37
38 if (fence)
39 nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
40
41 /* Try to emit before firing to avoid having to flush again right after
42 * in case we have to wait on this fence.
43 */
44 nouveau_fence_emit(screen->fence.current);
45
46 FIRE_RING(screen->channel);
47 }
48
49 void
50 nv50_default_flush_notify(struct nouveau_channel *chan)
51 {
52 struct nv50_context *nv50 = chan->user_private;
53
54 if (!nv50)
55 return;
56
57 nouveau_fence_update(&nv50->screen->base, TRUE);
58 nouveau_fence_next(&nv50->screen->base);
59 }
60
61 static void
62 nv50_context_unreference_resources(struct nv50_context *nv50)
63 {
64 unsigned s, i;
65
66 for (i = 0; i < NV50_BUFCTX_COUNT; ++i)
67 nv50_bufctx_reset(nv50, i);
68
69 for (i = 0; i < nv50->num_vtxbufs; ++i)
70 pipe_resource_reference(&nv50->vtxbuf[i].buffer, NULL);
71
72 pipe_resource_reference(&nv50->idxbuf.buffer, NULL);
73
74 for (s = 0; s < 3; ++s) {
75 for (i = 0; i < nv50->num_textures[s]; ++i)
76 pipe_sampler_view_reference(&nv50->textures[s][i], NULL);
77
78 for (i = 0; i < 16; ++i)
79 pipe_resource_reference(&nv50->constbuf[s][i], NULL);
80 }
81 }
82
83 static void
84 nv50_destroy(struct pipe_context *pipe)
85 {
86 struct nv50_context *nv50 = nv50_context(pipe);
87
88 nv50_context_unreference_resources(nv50);
89
90 draw_destroy(nv50->draw);
91
92 if (nv50->screen->cur_ctx == nv50) {
93 nv50->screen->base.channel->user_private = NULL;
94 nv50->screen->cur_ctx = NULL;
95 }
96
97 FREE(nv50);
98 }
99
100 struct pipe_context *
101 nv50_create(struct pipe_screen *pscreen, void *priv)
102 {
103 struct pipe_winsys *pipe_winsys = pscreen->winsys;
104 struct nv50_screen *screen = nv50_screen(pscreen);
105 struct nv50_context *nv50;
106 struct pipe_context *pipe;
107
108 nv50 = CALLOC_STRUCT(nv50_context);
109 if (!nv50)
110 return NULL;
111 pipe = &nv50->base.pipe;
112
113 nv50->screen = screen;
114 nv50->base.screen = &screen->base;
115 nv50->base.copy_data = nv50_m2mf_copy_linear;
116 nv50->base.push_data = nv50_sifc_linear_u8;
117
118 pipe->winsys = pipe_winsys;
119 pipe->screen = pscreen;
120 pipe->priv = priv;
121
122 pipe->destroy = nv50_destroy;
123
124 pipe->draw_vbo = nv50_draw_vbo;
125 pipe->clear = nv50_clear;
126
127 pipe->flush = nv50_flush;
128
129 if (!screen->cur_ctx)
130 screen->cur_ctx = nv50;
131 screen->base.channel->user_private = nv50;
132 screen->base.channel->flush_notify = nv50_default_flush_notify;
133
134 nv50_init_query_functions(nv50);
135 nv50_init_surface_functions(nv50);
136 nv50_init_state_functions(nv50);
137 nv50_init_resource_functions(pipe);
138
139 nv50->draw = draw_create(pipe);
140 assert(nv50->draw);
141 draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
142
143 return pipe;
144 }
145
146 struct resident {
147 struct nv04_resource *res;
148 uint32_t flags;
149 };
150
151 void
152 nv50_bufctx_add_resident(struct nv50_context *nv50, int ctx,
153 struct nv04_resource *resource, uint32_t flags)
154 {
155 struct resident rsd = { resource, flags };
156
157 if (!resource->bo)
158 return;
159
160 /* We don't need to reference the resource here, it will be referenced
161 * in the context/state, and bufctx will be reset when state changes.
162 */
163 util_dynarray_append(&nv50->residents[ctx], struct resident, rsd);
164 }
165
166 void
167 nv50_bufctx_del_resident(struct nv50_context *nv50, int ctx,
168 struct nv04_resource *resource)
169 {
170 struct resident *rsd, *top;
171 unsigned i;
172
173 for (i = 0; i < nv50->residents[ctx].size / sizeof(struct resident); ++i) {
174 rsd = util_dynarray_element(&nv50->residents[ctx], struct resident, i);
175
176 if (rsd->res == resource) {
177 top = util_dynarray_pop_ptr(&nv50->residents[ctx], struct resident);
178 if (rsd != top)
179 *rsd = *top;
180 break;
181 }
182 }
183 }
184
185 void
186 nv50_bufctx_emit_relocs(struct nv50_context *nv50)
187 {
188 struct resident *rsd;
189 struct util_dynarray *array;
190 unsigned ctx, i, n;
191
192 for (ctx = 0; ctx < NV50_BUFCTX_COUNT; ++ctx) {
193 array = &nv50->residents[ctx];
194
195 n = array->size / sizeof(struct resident);
196 MARK_RING(nv50->screen->base.channel, n, n);
197 for (i = 0; i < n; ++i) {
198 rsd = util_dynarray_element(array, struct resident, i);
199
200 nv50_resource_validate(rsd->res, rsd->flags);
201 }
202 }
203
204 nv50_screen_make_buffers_resident(nv50->screen);
205 }