2 * Copyright 2010 Christoph Bumiller
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #include "pipe/p_defines.h"
24 #include "util/u_framebuffer.h"
26 #include "nv50/nv50_context.h"
27 #include "nv50/nv50_screen.h"
28 #include "nv50/nv50_resource.h"
31 nv50_flush(struct pipe_context *pipe,
32 struct pipe_fence_handle **fence,
35 struct nouveau_screen *screen = nouveau_screen(pipe->screen);
38 nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
40 PUSH_KICK(screen->pushbuf);
42 nouveau_context_update_frame_stats(nouveau_context(pipe));
46 nv50_texture_barrier(struct pipe_context *pipe)
48 struct nouveau_pushbuf *push = nv50_context(pipe)->base.pushbuf;
50 BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);
52 BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
53 PUSH_DATA (push, 0x20);
57 nv50_memory_barrier(struct pipe_context *pipe, unsigned flags)
59 struct nv50_context *nv50 = nv50_context(pipe);
62 if (flags & PIPE_BARRIER_MAPPED_BUFFER) {
63 for (i = 0; i < nv50->num_vtxbufs; ++i) {
64 if (!nv50->vtxbuf[i].buffer)
66 if (nv50->vtxbuf[i].buffer->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
67 nv50->base.vbo_dirty = TRUE;
70 if (nv50->idxbuf.buffer &&
71 nv50->idxbuf.buffer->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
72 nv50->base.vbo_dirty = TRUE;
74 for (s = 0; s < 3 && !nv50->cb_dirty; ++s) {
75 uint32_t valid = nv50->constbuf_valid[s];
77 while (valid && !nv50->cb_dirty) {
78 const unsigned i = ffs(valid) - 1;
79 struct pipe_resource *res;
82 if (nv50->constbuf[s][i].user)
85 res = nv50->constbuf[s][i].u.buf;
89 if (res->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
90 nv50->cb_dirty = TRUE;
97 nv50_default_kick_notify(struct nouveau_pushbuf *push)
99 struct nv50_screen *screen = push->user_priv;
102 nouveau_fence_next(&screen->base);
103 nouveau_fence_update(&screen->base, TRUE);
105 screen->cur_ctx->state.flushed = TRUE;
110 nv50_context_unreference_resources(struct nv50_context *nv50)
114 nouveau_bufctx_del(&nv50->bufctx_3d);
115 nouveau_bufctx_del(&nv50->bufctx);
117 util_unreference_framebuffer_state(&nv50->framebuffer);
119 assert(nv50->num_vtxbufs <= PIPE_MAX_ATTRIBS);
120 for (i = 0; i < nv50->num_vtxbufs; ++i)
121 pipe_resource_reference(&nv50->vtxbuf[i].buffer, NULL);
123 pipe_resource_reference(&nv50->idxbuf.buffer, NULL);
125 for (s = 0; s < 3; ++s) {
126 assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS);
127 for (i = 0; i < nv50->num_textures[s]; ++i)
128 pipe_sampler_view_reference(&nv50->textures[s][i], NULL);
130 for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i)
131 if (!nv50->constbuf[s][i].user)
132 pipe_resource_reference(&nv50->constbuf[s][i].u.buf, NULL);
137 nv50_destroy(struct pipe_context *pipe)
139 struct nv50_context *nv50 = nv50_context(pipe);
141 if (nv50_context_screen(nv50)->cur_ctx == nv50)
142 nv50_context_screen(nv50)->cur_ctx = NULL;
143 nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL);
144 nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel);
146 nv50_context_unreference_resources(nv50);
150 nouveau_context_destroy(&nv50->base);
154 nv50_invalidate_resource_storage(struct nouveau_context *ctx,
155 struct pipe_resource *res,
158 struct nv50_context *nv50 = nv50_context(&ctx->pipe);
161 if (res->bind & PIPE_BIND_RENDER_TARGET) {
162 assert(nv50->framebuffer.nr_cbufs <= PIPE_MAX_COLOR_BUFS);
163 for (i = 0; i < nv50->framebuffer.nr_cbufs; ++i) {
164 if (nv50->framebuffer.cbufs[i] &&
165 nv50->framebuffer.cbufs[i]->texture == res) {
166 nv50->dirty |= NV50_NEW_FRAMEBUFFER;
167 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
173 if (res->bind & PIPE_BIND_DEPTH_STENCIL) {
174 if (nv50->framebuffer.zsbuf &&
175 nv50->framebuffer.zsbuf->texture == res) {
176 nv50->dirty |= NV50_NEW_FRAMEBUFFER;
177 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
183 if (res->bind & (PIPE_BIND_VERTEX_BUFFER |
184 PIPE_BIND_INDEX_BUFFER |
185 PIPE_BIND_CONSTANT_BUFFER |
186 PIPE_BIND_STREAM_OUTPUT |
187 PIPE_BIND_SAMPLER_VIEW)) {
189 assert(nv50->num_vtxbufs <= PIPE_MAX_ATTRIBS);
190 for (i = 0; i < nv50->num_vtxbufs; ++i) {
191 if (nv50->vtxbuf[i].buffer == res) {
192 nv50->dirty |= NV50_NEW_ARRAYS;
193 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_VERTEX);
199 if (nv50->idxbuf.buffer == res)
203 for (s = 0; s < 3; ++s) {
204 assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS);
205 for (i = 0; i < nv50->num_textures[s]; ++i) {
206 if (nv50->textures[s][i] &&
207 nv50->textures[s][i]->texture == res) {
208 nv50->dirty |= NV50_NEW_TEXTURES;
209 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES);
216 for (s = 0; s < 3; ++s) {
217 for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i) {
218 if (!(nv50->constbuf_valid[s] & (1 << i)))
220 if (!nv50->constbuf[s][i].user &&
221 nv50->constbuf[s][i].u.buf == res) {
222 nv50->dirty |= NV50_NEW_CONSTBUF;
223 nv50->constbuf_dirty[s] |= 1 << i;
224 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(s, i));
236 nv50_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
239 struct pipe_context *
240 nv50_create(struct pipe_screen *pscreen, void *priv)
242 struct nv50_screen *screen = nv50_screen(pscreen);
243 struct nv50_context *nv50;
244 struct pipe_context *pipe;
248 nv50 = CALLOC_STRUCT(nv50_context);
251 pipe = &nv50->base.pipe;
253 if (!nv50_blitctx_create(nv50))
256 nv50->base.pushbuf = screen->base.pushbuf;
257 nv50->base.client = screen->base.client;
259 ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_COUNT,
262 ret = nouveau_bufctx_new(screen->base.client, 2, &nv50->bufctx);
266 nv50->base.screen = &screen->base;
267 nv50->base.copy_data = nv50_m2mf_copy_linear;
268 nv50->base.push_data = nv50_sifc_linear_u8;
269 /* FIXME: Make it possible to use this again. The problem is that there is
270 * some clever logic in the card that allows for multiple renders to happen
271 * when there are only constbuf changes. However that relies on the
272 * constbuf updates happening to the right constbuf slots. Currently
273 * implementation just makes it go through a separate slot which doesn't
274 * properly update the right constbuf data.
275 nv50->base.push_cb = nv50_cb_push;
278 nv50->screen = screen;
279 pipe->screen = pscreen;
282 pipe->destroy = nv50_destroy;
284 pipe->draw_vbo = nv50_draw_vbo;
285 pipe->clear = nv50_clear;
287 pipe->flush = nv50_flush;
288 pipe->texture_barrier = nv50_texture_barrier;
289 pipe->memory_barrier = nv50_memory_barrier;
290 pipe->get_sample_position = nv50_context_get_sample_position;
292 if (!screen->cur_ctx) {
293 screen->cur_ctx = nv50;
294 nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx);
296 nv50->base.pushbuf->kick_notify = nv50_default_kick_notify;
298 nv50_init_query_functions(nv50);
299 nv50_init_surface_functions(nv50);
300 nv50_init_state_functions(nv50);
301 nv50_init_resource_functions(pipe);
303 nv50->base.invalidate_resource_storage = nv50_invalidate_resource_storage;
305 if (screen->base.device->chipset < 0x84 ||
306 debug_get_bool_option("NOUVEAU_PMPEG", FALSE)) {
308 nouveau_context_init_vdec(&nv50->base);
309 } else if (screen->base.device->chipset < 0x98 ||
310 screen->base.device->chipset == 0xa0) {
312 pipe->create_video_codec = nv84_create_decoder;
313 pipe->create_video_buffer = nv84_video_buffer_create;
316 pipe->create_video_codec = nv98_create_decoder;
317 pipe->create_video_buffer = nv98_video_buffer_create;
320 flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
322 BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->code);
323 BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->uniforms);
324 BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->txc);
325 BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->stack_bo);
327 flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;
329 BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->fence.bo);
330 BCTX_REFN_bo(nv50->bufctx, FENCE, flags, screen->fence.bo);
332 nv50->base.scratch.bo_size = 2 << 20;
338 nouveau_bufctx_del(&nv50->bufctx_3d);
340 nouveau_bufctx_del(&nv50->bufctx);
348 nv50_bufctx_fence(struct nouveau_bufctx *bufctx, boolean on_flush)
350 struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending;
351 struct nouveau_list *it;
353 for (it = list->next; it != list; it = it->next) {
354 struct nouveau_bufref *ref = (struct nouveau_bufref *)it;
355 struct nv04_resource *res = ref->priv;
357 nv50_resource_validate(res, (unsigned)ref->priv_data);
362 nv50_context_get_sample_position(struct pipe_context *pipe,
363 unsigned sample_count, unsigned sample_index,
366 static const uint8_t ms1[1][2] = { { 0x8, 0x8 } };
367 static const uint8_t ms2[2][2] = {
368 { 0x4, 0x4 }, { 0xc, 0xc } }; /* surface coords (0,0), (1,0) */
369 static const uint8_t ms4[4][2] = {
370 { 0x6, 0x2 }, { 0xe, 0x6 }, /* (0,0), (1,0) */
371 { 0x2, 0xa }, { 0xa, 0xe } }; /* (0,1), (1,1) */
372 static const uint8_t ms8[8][2] = {
373 { 0x1, 0x7 }, { 0x5, 0x3 }, /* (0,0), (1,0) */
374 { 0x3, 0xd }, { 0x7, 0xb }, /* (0,1), (1,1) */
375 { 0x9, 0x5 }, { 0xf, 0x1 }, /* (2,0), (3,0) */
376 { 0xb, 0xf }, { 0xd, 0x9 } }; /* (2,1), (3,1) */
378 /* NOTE: there are alternative modes for MS2 and MS8, currently not used */
379 static const uint8_t ms8_alt[8][2] = {
380 { 0x9, 0x5 }, { 0x7, 0xb }, /* (2,0), (1,1) */
381 { 0xd, 0x9 }, { 0x5, 0x3 }, /* (3,1), (1,0) */
382 { 0x3, 0xd }, { 0x1, 0x7 }, /* (0,1), (0,0) */
383 { 0xb, 0xf }, { 0xf, 0x1 } }; /* (2,1), (3,0) */
386 const uint8_t (*ptr)[2];
388 switch (sample_count) {
390 case 1: ptr = ms1; break;
391 case 2: ptr = ms2; break;
392 case 4: ptr = ms4; break;
393 case 8: ptr = ms8; break;
396 return; /* bad sample count -> undefined locations */
398 xy[0] = ptr[sample_index][0] * 0.0625f;
399 xy[1] = ptr[sample_index][1] * 0.0625f;