1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2010 Christoph Bumiller
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
12bf215546Sopenharmony_ci * all copies or substantial portions of the Software.
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21bf215546Sopenharmony_ci */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include "pipe/p_defines.h"
24bf215546Sopenharmony_ci#include "util/u_framebuffer.h"
25bf215546Sopenharmony_ci#include "util/u_upload_mgr.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "nv50/nv50_context.h"
28bf215546Sopenharmony_ci#include "nv50/nv50_screen.h"
29bf215546Sopenharmony_ci#include "nv50/nv50_resource.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_cistatic void
32bf215546Sopenharmony_cinv50_flush(struct pipe_context *pipe,
33bf215546Sopenharmony_ci           struct pipe_fence_handle **fence,
34bf215546Sopenharmony_ci           unsigned flags)
35bf215546Sopenharmony_ci{
36bf215546Sopenharmony_ci   struct nouveau_context *context = nouveau_context(pipe);
37bf215546Sopenharmony_ci   struct nouveau_screen *screen = context->screen;
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci   if (fence)
40bf215546Sopenharmony_ci      nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci   PUSH_KICK(context->pushbuf);
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci   nouveau_context_update_frame_stats(nouveau_context(pipe));
45bf215546Sopenharmony_ci}
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_cistatic void
48bf215546Sopenharmony_cinv50_texture_barrier(struct pipe_context *pipe, unsigned flags)
49bf215546Sopenharmony_ci{
50bf215546Sopenharmony_ci   struct nouveau_pushbuf *push = nv50_context(pipe)->base.pushbuf;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);
53bf215546Sopenharmony_ci   PUSH_DATA (push, 0);
54bf215546Sopenharmony_ci   BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
55bf215546Sopenharmony_ci   PUSH_DATA (push, 0x20);
56bf215546Sopenharmony_ci}
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_cistatic void
59bf215546Sopenharmony_cinv50_memory_barrier(struct pipe_context *pipe, unsigned flags)
60bf215546Sopenharmony_ci{
61bf215546Sopenharmony_ci   struct nv50_context *nv50 = nv50_context(pipe);
62bf215546Sopenharmony_ci   struct nouveau_pushbuf *push = nv50->base.pushbuf;
63bf215546Sopenharmony_ci   int i, s;
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   if (flags & PIPE_BARRIER_MAPPED_BUFFER) {
66bf215546Sopenharmony_ci      for (i = 0; i < nv50->num_vtxbufs; ++i) {
67bf215546Sopenharmony_ci         if (!nv50->vtxbuf[i].buffer.resource && !nv50->vtxbuf[i].is_user_buffer)
68bf215546Sopenharmony_ci            continue;
69bf215546Sopenharmony_ci         if (nv50->vtxbuf[i].buffer.resource->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
70bf215546Sopenharmony_ci            nv50->base.vbo_dirty = true;
71bf215546Sopenharmony_ci      }
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci      for (s = 0; s < NV50_MAX_3D_SHADER_STAGES && !nv50->cb_dirty; ++s) {
74bf215546Sopenharmony_ci         uint32_t valid = nv50->constbuf_valid[s];
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci         while (valid && !nv50->cb_dirty) {
77bf215546Sopenharmony_ci            const unsigned i = ffs(valid) - 1;
78bf215546Sopenharmony_ci            struct pipe_resource *res;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci            valid &= ~(1 << i);
81bf215546Sopenharmony_ci            if (nv50->constbuf[s][i].user)
82bf215546Sopenharmony_ci               continue;
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci            res = nv50->constbuf[s][i].u.buf;
85bf215546Sopenharmony_ci            if (!res)
86bf215546Sopenharmony_ci               continue;
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci            if (res->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT)
89bf215546Sopenharmony_ci               nv50->cb_dirty = true;
90bf215546Sopenharmony_ci         }
91bf215546Sopenharmony_ci      }
92bf215546Sopenharmony_ci   } else {
93bf215546Sopenharmony_ci      BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);
94bf215546Sopenharmony_ci      PUSH_DATA (push, 0);
95bf215546Sopenharmony_ci   }
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   /* If we're going to texture from a buffer/image written by a shader, we
98bf215546Sopenharmony_ci    * must flush the texture cache.
99bf215546Sopenharmony_ci    */
100bf215546Sopenharmony_ci   if (flags & PIPE_BARRIER_TEXTURE) {
101bf215546Sopenharmony_ci      BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
102bf215546Sopenharmony_ci      PUSH_DATA (push, 0x20);
103bf215546Sopenharmony_ci   }
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
106bf215546Sopenharmony_ci      nv50->cb_dirty = true;
107bf215546Sopenharmony_ci   if (flags & (PIPE_BARRIER_VERTEX_BUFFER | PIPE_BARRIER_INDEX_BUFFER))
108bf215546Sopenharmony_ci      nv50->base.vbo_dirty = true;
109bf215546Sopenharmony_ci}
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_cistatic void
112bf215546Sopenharmony_cinv50_emit_string_marker(struct pipe_context *pipe, const char *str, int len)
113bf215546Sopenharmony_ci{
114bf215546Sopenharmony_ci   struct nouveau_pushbuf *push = nv50_context(pipe)->base.pushbuf;
115bf215546Sopenharmony_ci   int string_words = len / 4;
116bf215546Sopenharmony_ci   int data_words;
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   if (len <= 0)
119bf215546Sopenharmony_ci      return;
120bf215546Sopenharmony_ci   string_words = MIN2(string_words, NV04_PFIFO_MAX_PACKET_LEN);
121bf215546Sopenharmony_ci   if (string_words == NV04_PFIFO_MAX_PACKET_LEN)
122bf215546Sopenharmony_ci      data_words = string_words;
123bf215546Sopenharmony_ci   else
124bf215546Sopenharmony_ci      data_words = string_words + !!(len & 3);
125bf215546Sopenharmony_ci   BEGIN_NI04(push, SUBC_3D(NV04_GRAPH_NOP), data_words);
126bf215546Sopenharmony_ci   if (string_words)
127bf215546Sopenharmony_ci      PUSH_DATAp(push, str, string_words);
128bf215546Sopenharmony_ci   if (string_words != data_words) {
129bf215546Sopenharmony_ci      int data = 0;
130bf215546Sopenharmony_ci      memcpy(&data, &str[string_words * 4], len & 3);
131bf215546Sopenharmony_ci      PUSH_DATA (push, data);
132bf215546Sopenharmony_ci   }
133bf215546Sopenharmony_ci}
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_civoid
136bf215546Sopenharmony_cinv50_default_kick_notify(struct nouveau_pushbuf *push)
137bf215546Sopenharmony_ci{
138bf215546Sopenharmony_ci   struct nv50_screen *screen = push->user_priv;
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   if (screen) {
141bf215546Sopenharmony_ci      nouveau_fence_next(&screen->base);
142bf215546Sopenharmony_ci      nouveau_fence_update(&screen->base, true);
143bf215546Sopenharmony_ci      if (screen->cur_ctx)
144bf215546Sopenharmony_ci         screen->cur_ctx->state.flushed = true;
145bf215546Sopenharmony_ci   }
146bf215546Sopenharmony_ci}
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_cistatic void
149bf215546Sopenharmony_cinv50_context_unreference_resources(struct nv50_context *nv50)
150bf215546Sopenharmony_ci{
151bf215546Sopenharmony_ci   unsigned s, i;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   nouveau_bufctx_del(&nv50->bufctx_3d);
154bf215546Sopenharmony_ci   nouveau_bufctx_del(&nv50->bufctx);
155bf215546Sopenharmony_ci   nouveau_bufctx_del(&nv50->bufctx_cp);
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   util_unreference_framebuffer_state(&nv50->framebuffer);
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   assert(nv50->num_vtxbufs <= PIPE_MAX_ATTRIBS);
160bf215546Sopenharmony_ci   for (i = 0; i < nv50->num_vtxbufs; ++i)
161bf215546Sopenharmony_ci      pipe_vertex_buffer_unreference(&nv50->vtxbuf[i]);
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   for (s = 0; s < NV50_MAX_SHADER_STAGES; ++s) {
164bf215546Sopenharmony_ci      assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS);
165bf215546Sopenharmony_ci      for (i = 0; i < nv50->num_textures[s]; ++i)
166bf215546Sopenharmony_ci         pipe_sampler_view_reference(&nv50->textures[s][i], NULL);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci      for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i)
169bf215546Sopenharmony_ci         if (!nv50->constbuf[s][i].user)
170bf215546Sopenharmony_ci            pipe_resource_reference(&nv50->constbuf[s][i].u.buf, NULL);
171bf215546Sopenharmony_ci   }
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   for (i = 0; i < nv50->global_residents.size / sizeof(struct pipe_resource *);
174bf215546Sopenharmony_ci        ++i) {
175bf215546Sopenharmony_ci      struct pipe_resource **res = util_dynarray_element(
176bf215546Sopenharmony_ci         &nv50->global_residents, struct pipe_resource *, i);
177bf215546Sopenharmony_ci      pipe_resource_reference(res, NULL);
178bf215546Sopenharmony_ci   }
179bf215546Sopenharmony_ci   util_dynarray_fini(&nv50->global_residents);
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_cistatic void
183bf215546Sopenharmony_cinv50_destroy(struct pipe_context *pipe)
184bf215546Sopenharmony_ci{
185bf215546Sopenharmony_ci   struct nv50_context *nv50 = nv50_context(pipe);
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   if (nv50->screen->cur_ctx == nv50) {
188bf215546Sopenharmony_ci      nv50->screen->cur_ctx = NULL;
189bf215546Sopenharmony_ci      /* Save off the state in case another context gets created */
190bf215546Sopenharmony_ci      nv50->screen->save_state = nv50->state;
191bf215546Sopenharmony_ci   }
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   if (nv50->base.pipe.stream_uploader)
194bf215546Sopenharmony_ci      u_upload_destroy(nv50->base.pipe.stream_uploader);
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci   nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL);
197bf215546Sopenharmony_ci   nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel);
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   nv50_context_unreference_resources(nv50);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   FREE(nv50->blit);
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci   nouveau_context_destroy(&nv50->base);
204bf215546Sopenharmony_ci}
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_cistatic int
207bf215546Sopenharmony_cinv50_invalidate_resource_storage(struct nouveau_context *ctx,
208bf215546Sopenharmony_ci                                 struct pipe_resource *res,
209bf215546Sopenharmony_ci                                 int ref)
210bf215546Sopenharmony_ci{
211bf215546Sopenharmony_ci   struct nv50_context *nv50 = nv50_context(&ctx->pipe);
212bf215546Sopenharmony_ci   unsigned bind = res->bind ? res->bind : PIPE_BIND_VERTEX_BUFFER;
213bf215546Sopenharmony_ci   unsigned s, i;
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   if (bind & PIPE_BIND_RENDER_TARGET) {
216bf215546Sopenharmony_ci      assert(nv50->framebuffer.nr_cbufs <= PIPE_MAX_COLOR_BUFS);
217bf215546Sopenharmony_ci      for (i = 0; i < nv50->framebuffer.nr_cbufs; ++i) {
218bf215546Sopenharmony_ci         if (nv50->framebuffer.cbufs[i] &&
219bf215546Sopenharmony_ci             nv50->framebuffer.cbufs[i]->texture == res) {
220bf215546Sopenharmony_ci            nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER;
221bf215546Sopenharmony_ci            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB);
222bf215546Sopenharmony_ci            if (!--ref)
223bf215546Sopenharmony_ci               return ref;
224bf215546Sopenharmony_ci         }
225bf215546Sopenharmony_ci      }
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci   if (bind & PIPE_BIND_DEPTH_STENCIL) {
228bf215546Sopenharmony_ci      if (nv50->framebuffer.zsbuf &&
229bf215546Sopenharmony_ci          nv50->framebuffer.zsbuf->texture == res) {
230bf215546Sopenharmony_ci         nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER;
231bf215546Sopenharmony_ci         nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB);
232bf215546Sopenharmony_ci         if (!--ref)
233bf215546Sopenharmony_ci            return ref;
234bf215546Sopenharmony_ci      }
235bf215546Sopenharmony_ci   }
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci   if (bind & (PIPE_BIND_VERTEX_BUFFER |
238bf215546Sopenharmony_ci               PIPE_BIND_INDEX_BUFFER |
239bf215546Sopenharmony_ci               PIPE_BIND_CONSTANT_BUFFER |
240bf215546Sopenharmony_ci               PIPE_BIND_STREAM_OUTPUT |
241bf215546Sopenharmony_ci               PIPE_BIND_SAMPLER_VIEW)) {
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci      assert(nv50->num_vtxbufs <= PIPE_MAX_ATTRIBS);
244bf215546Sopenharmony_ci      for (i = 0; i < nv50->num_vtxbufs; ++i) {
245bf215546Sopenharmony_ci         if (nv50->vtxbuf[i].buffer.resource == res) {
246bf215546Sopenharmony_ci            nv50->dirty_3d |= NV50_NEW_3D_ARRAYS;
247bf215546Sopenharmony_ci            nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_VERTEX);
248bf215546Sopenharmony_ci            if (!--ref)
249bf215546Sopenharmony_ci               return ref;
250bf215546Sopenharmony_ci         }
251bf215546Sopenharmony_ci      }
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci      for (s = 0; s < NV50_MAX_SHADER_STAGES; ++s) {
254bf215546Sopenharmony_ci      assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS);
255bf215546Sopenharmony_ci      for (i = 0; i < nv50->num_textures[s]; ++i) {
256bf215546Sopenharmony_ci         if (nv50->textures[s][i] &&
257bf215546Sopenharmony_ci             nv50->textures[s][i]->texture == res) {
258bf215546Sopenharmony_ci            if (unlikely(s == NV50_SHADER_STAGE_COMPUTE)) {
259bf215546Sopenharmony_ci               nv50->dirty_cp |= NV50_NEW_CP_TEXTURES;
260bf215546Sopenharmony_ci               nouveau_bufctx_reset(nv50->bufctx_cp, NV50_BIND_CP_TEXTURES);
261bf215546Sopenharmony_ci            } else {
262bf215546Sopenharmony_ci               nv50->dirty_3d |= NV50_NEW_3D_TEXTURES;
263bf215546Sopenharmony_ci               nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_TEXTURES);
264bf215546Sopenharmony_ci            }
265bf215546Sopenharmony_ci            if (!--ref)
266bf215546Sopenharmony_ci               return ref;
267bf215546Sopenharmony_ci         }
268bf215546Sopenharmony_ci      }
269bf215546Sopenharmony_ci      }
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci      for (s = 0; s < NV50_MAX_SHADER_STAGES; ++s) {
272bf215546Sopenharmony_ci      for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i) {
273bf215546Sopenharmony_ci         if (!(nv50->constbuf_valid[s] & (1 << i)))
274bf215546Sopenharmony_ci            continue;
275bf215546Sopenharmony_ci         if (!nv50->constbuf[s][i].user &&
276bf215546Sopenharmony_ci             nv50->constbuf[s][i].u.buf == res) {
277bf215546Sopenharmony_ci            nv50->constbuf_dirty[s] |= 1 << i;
278bf215546Sopenharmony_ci            if (unlikely(s == NV50_SHADER_STAGE_COMPUTE)) {
279bf215546Sopenharmony_ci               nv50->dirty_cp |= NV50_NEW_CP_CONSTBUF;
280bf215546Sopenharmony_ci               nouveau_bufctx_reset(nv50->bufctx_cp, NV50_BIND_CP_CB(i));
281bf215546Sopenharmony_ci            } else {
282bf215546Sopenharmony_ci               nv50->dirty_3d |= NV50_NEW_3D_CONSTBUF;
283bf215546Sopenharmony_ci               nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_CB(s, i));
284bf215546Sopenharmony_ci            }
285bf215546Sopenharmony_ci            if (!--ref)
286bf215546Sopenharmony_ci               return ref;
287bf215546Sopenharmony_ci         }
288bf215546Sopenharmony_ci      }
289bf215546Sopenharmony_ci      }
290bf215546Sopenharmony_ci   }
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   return ref;
293bf215546Sopenharmony_ci}
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_cistatic void
296bf215546Sopenharmony_cinv50_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
297bf215546Sopenharmony_ci                                 float *);
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_cistruct pipe_context *
300bf215546Sopenharmony_cinv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags)
301bf215546Sopenharmony_ci{
302bf215546Sopenharmony_ci   struct nv50_screen *screen = nv50_screen(pscreen);
303bf215546Sopenharmony_ci   struct nv50_context *nv50;
304bf215546Sopenharmony_ci   struct pipe_context *pipe;
305bf215546Sopenharmony_ci   int ret;
306bf215546Sopenharmony_ci   uint32_t flags;
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci   nv50 = CALLOC_STRUCT(nv50_context);
309bf215546Sopenharmony_ci   if (!nv50)
310bf215546Sopenharmony_ci      return NULL;
311bf215546Sopenharmony_ci   pipe = &nv50->base.pipe;
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   if (!nv50_blitctx_create(nv50))
314bf215546Sopenharmony_ci      goto out_err;
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci   nv50->base.pushbuf = screen->base.pushbuf;
317bf215546Sopenharmony_ci   nv50->base.client = screen->base.client;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   ret = nouveau_bufctx_new(nv50->base.client, 2, &nv50->bufctx);
320bf215546Sopenharmony_ci   if (!ret)
321bf215546Sopenharmony_ci      ret = nouveau_bufctx_new(nv50->base.client, NV50_BIND_3D_COUNT,
322bf215546Sopenharmony_ci                               &nv50->bufctx_3d);
323bf215546Sopenharmony_ci   if (!ret)
324bf215546Sopenharmony_ci      ret = nouveau_bufctx_new(nv50->base.client, NV50_BIND_CP_COUNT,
325bf215546Sopenharmony_ci                               &nv50->bufctx_cp);
326bf215546Sopenharmony_ci   if (ret)
327bf215546Sopenharmony_ci      goto out_err;
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   nv50->base.screen    = &screen->base;
330bf215546Sopenharmony_ci   nv50->base.copy_data = nv50_m2mf_copy_linear;
331bf215546Sopenharmony_ci   nv50->base.push_data = nv50_sifc_linear_u8;
332bf215546Sopenharmony_ci   nv50->base.push_cb   = nv50_cb_push;
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   nv50->screen = screen;
335bf215546Sopenharmony_ci   pipe->screen = pscreen;
336bf215546Sopenharmony_ci   pipe->priv = priv;
337bf215546Sopenharmony_ci   pipe->stream_uploader = u_upload_create_default(pipe);
338bf215546Sopenharmony_ci   if (!pipe->stream_uploader)
339bf215546Sopenharmony_ci      goto out_err;
340bf215546Sopenharmony_ci   pipe->const_uploader = pipe->stream_uploader;
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci   pipe->destroy = nv50_destroy;
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   pipe->draw_vbo = nv50_draw_vbo;
345bf215546Sopenharmony_ci   pipe->clear = nv50_clear;
346bf215546Sopenharmony_ci   pipe->launch_grid = nv50_launch_grid;
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci   pipe->flush = nv50_flush;
349bf215546Sopenharmony_ci   pipe->texture_barrier = nv50_texture_barrier;
350bf215546Sopenharmony_ci   pipe->memory_barrier = nv50_memory_barrier;
351bf215546Sopenharmony_ci   pipe->get_sample_position = nv50_context_get_sample_position;
352bf215546Sopenharmony_ci   pipe->emit_string_marker = nv50_emit_string_marker;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   if (!screen->cur_ctx) {
355bf215546Sopenharmony_ci      /* Restore the last context's state here, normally handled during
356bf215546Sopenharmony_ci       * context switch
357bf215546Sopenharmony_ci       */
358bf215546Sopenharmony_ci      nv50->state = screen->save_state;
359bf215546Sopenharmony_ci      screen->cur_ctx = nv50;
360bf215546Sopenharmony_ci      nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx);
361bf215546Sopenharmony_ci   }
362bf215546Sopenharmony_ci   nv50->base.pushbuf->kick_notify = nv50_default_kick_notify;
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci   nouveau_context_init(&nv50->base);
365bf215546Sopenharmony_ci   nv50_init_query_functions(nv50);
366bf215546Sopenharmony_ci   nv50_init_surface_functions(nv50);
367bf215546Sopenharmony_ci   nv50_init_state_functions(nv50);
368bf215546Sopenharmony_ci   nv50_init_resource_functions(pipe);
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci   nv50->base.invalidate_resource_storage = nv50_invalidate_resource_storage;
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   if (screen->base.device->chipset < 0x84 ||
373bf215546Sopenharmony_ci       debug_get_bool_option("NOUVEAU_PMPEG", false)) {
374bf215546Sopenharmony_ci      /* PMPEG */
375bf215546Sopenharmony_ci      nouveau_context_init_vdec(&nv50->base);
376bf215546Sopenharmony_ci   } else if (screen->base.device->chipset < 0x98 ||
377bf215546Sopenharmony_ci              screen->base.device->chipset == 0xa0) {
378bf215546Sopenharmony_ci      /* VP2 */
379bf215546Sopenharmony_ci      pipe->create_video_codec = nv84_create_decoder;
380bf215546Sopenharmony_ci      pipe->create_video_buffer = nv84_video_buffer_create;
381bf215546Sopenharmony_ci   } else {
382bf215546Sopenharmony_ci      /* VP3/4 */
383bf215546Sopenharmony_ci      pipe->create_video_codec = nv98_create_decoder;
384bf215546Sopenharmony_ci      pipe->create_video_buffer = nv98_video_buffer_create;
385bf215546Sopenharmony_ci   }
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci   flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->code);
390bf215546Sopenharmony_ci   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->uniforms);
391bf215546Sopenharmony_ci   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->txc);
392bf215546Sopenharmony_ci   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->stack_bo);
393bf215546Sopenharmony_ci   if (screen->compute) {
394bf215546Sopenharmony_ci      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->code);
395bf215546Sopenharmony_ci      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->uniforms);
396bf215546Sopenharmony_ci      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->txc);
397bf215546Sopenharmony_ci      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->stack_bo);
398bf215546Sopenharmony_ci   }
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci   flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci   BCTX_REFN_bo(nv50->bufctx_3d, 3D_SCREEN, flags, screen->fence.bo);
403bf215546Sopenharmony_ci   BCTX_REFN_bo(nv50->bufctx, FENCE, flags, screen->fence.bo);
404bf215546Sopenharmony_ci   if (screen->compute)
405bf215546Sopenharmony_ci      BCTX_REFN_bo(nv50->bufctx_cp, CP_SCREEN, flags, screen->fence.bo);
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   nv50->base.scratch.bo_size = 2 << 20;
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   util_dynarray_init(&nv50->global_residents, NULL);
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci   // Make sure that the first TSC entry has SRGB conversion bit set, since we
412bf215546Sopenharmony_ci   // use it as a fallback.
413bf215546Sopenharmony_ci   if (!screen->tsc.entries[0])
414bf215546Sopenharmony_ci      nv50_upload_tsc0(nv50);
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci   // And mark samplers as dirty so that the first slot would get bound to the
417bf215546Sopenharmony_ci   // zero entry if it's not otherwise set.
418bf215546Sopenharmony_ci   nv50->dirty_3d |= NV50_NEW_3D_SAMPLERS;
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   return pipe;
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ciout_err:
423bf215546Sopenharmony_ci   if (pipe->stream_uploader)
424bf215546Sopenharmony_ci      u_upload_destroy(pipe->stream_uploader);
425bf215546Sopenharmony_ci   if (nv50->bufctx_3d)
426bf215546Sopenharmony_ci      nouveau_bufctx_del(&nv50->bufctx_3d);
427bf215546Sopenharmony_ci   if (nv50->bufctx_cp)
428bf215546Sopenharmony_ci      nouveau_bufctx_del(&nv50->bufctx_cp);
429bf215546Sopenharmony_ci   if (nv50->bufctx)
430bf215546Sopenharmony_ci      nouveau_bufctx_del(&nv50->bufctx);
431bf215546Sopenharmony_ci   FREE(nv50->blit);
432bf215546Sopenharmony_ci   FREE(nv50);
433bf215546Sopenharmony_ci   return NULL;
434bf215546Sopenharmony_ci}
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_civoid
437bf215546Sopenharmony_cinv50_bufctx_fence(struct nouveau_bufctx *bufctx, bool on_flush)
438bf215546Sopenharmony_ci{
439bf215546Sopenharmony_ci   struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending;
440bf215546Sopenharmony_ci   struct nouveau_list *it;
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci   for (it = list->next; it != list; it = it->next) {
443bf215546Sopenharmony_ci      struct nouveau_bufref *ref = (struct nouveau_bufref *)it;
444bf215546Sopenharmony_ci      struct nv04_resource *res = ref->priv;
445bf215546Sopenharmony_ci      if (res)
446bf215546Sopenharmony_ci         nv50_resource_validate(res, (unsigned)ref->priv_data);
447bf215546Sopenharmony_ci   }
448bf215546Sopenharmony_ci}
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_cistatic void
451bf215546Sopenharmony_cinv50_context_get_sample_position(struct pipe_context *pipe,
452bf215546Sopenharmony_ci                                 unsigned sample_count, unsigned sample_index,
453bf215546Sopenharmony_ci                                 float *xy)
454bf215546Sopenharmony_ci{
455bf215546Sopenharmony_ci   static const uint8_t ms1[1][2] = { { 0x8, 0x8 } };
456bf215546Sopenharmony_ci   static const uint8_t ms2[2][2] = {
457bf215546Sopenharmony_ci      { 0x4, 0x4 }, { 0xc, 0xc } }; /* surface coords (0,0), (1,0) */
458bf215546Sopenharmony_ci   static const uint8_t ms4[4][2] = {
459bf215546Sopenharmony_ci      { 0x6, 0x2 }, { 0xe, 0x6 },   /* (0,0), (1,0) */
460bf215546Sopenharmony_ci      { 0x2, 0xa }, { 0xa, 0xe } }; /* (0,1), (1,1) */
461bf215546Sopenharmony_ci   static const uint8_t ms8[8][2] = {
462bf215546Sopenharmony_ci      { 0x1, 0x7 }, { 0x5, 0x3 },   /* (0,0), (1,0) */
463bf215546Sopenharmony_ci      { 0x3, 0xd }, { 0x7, 0xb },   /* (0,1), (1,1) */
464bf215546Sopenharmony_ci      { 0x9, 0x5 }, { 0xf, 0x1 },   /* (2,0), (3,0) */
465bf215546Sopenharmony_ci      { 0xb, 0xf }, { 0xd, 0x9 } }; /* (2,1), (3,1) */
466bf215546Sopenharmony_ci#if 0
467bf215546Sopenharmony_ci   /* NOTE: there are alternative modes for MS2 and MS8, currently not used */
468bf215546Sopenharmony_ci   static const uint8_t ms8_alt[8][2] = {
469bf215546Sopenharmony_ci      { 0x9, 0x5 }, { 0x7, 0xb },   /* (2,0), (1,1) */
470bf215546Sopenharmony_ci      { 0xd, 0x9 }, { 0x5, 0x3 },   /* (3,1), (1,0) */
471bf215546Sopenharmony_ci      { 0x3, 0xd }, { 0x1, 0x7 },   /* (0,1), (0,0) */
472bf215546Sopenharmony_ci      { 0xb, 0xf }, { 0xf, 0x1 } }; /* (2,1), (3,0) */
473bf215546Sopenharmony_ci#endif
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci   const uint8_t (*ptr)[2];
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci   switch (sample_count) {
478bf215546Sopenharmony_ci   case 0:
479bf215546Sopenharmony_ci   case 1: ptr = ms1; break;
480bf215546Sopenharmony_ci   case 2: ptr = ms2; break;
481bf215546Sopenharmony_ci   case 4: ptr = ms4; break;
482bf215546Sopenharmony_ci   case 8: ptr = ms8; break;
483bf215546Sopenharmony_ci   default:
484bf215546Sopenharmony_ci      assert(0);
485bf215546Sopenharmony_ci      return; /* bad sample count -> undefined locations */
486bf215546Sopenharmony_ci   }
487bf215546Sopenharmony_ci   xy[0] = ptr[sample_index][0] * 0.0625f;
488bf215546Sopenharmony_ci   xy[1] = ptr[sample_index][1] * 0.0625f;
489bf215546Sopenharmony_ci}
490