1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2008 Ben Skeggs
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 "nv50/nv50_context.h"
24bf215546Sopenharmony_ci#include "nv50/nv50_resource.h"
25bf215546Sopenharmony_ci#include "nv50/g80_texture.xml.h"
26bf215546Sopenharmony_ci#include "nv50/g80_defs.xml.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "util/format/u_format.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_cistatic inline uint32_t
31bf215546Sopenharmony_cinv50_tic_swizzle(const struct nv50_format *fmt, unsigned swz, bool tex_int)
32bf215546Sopenharmony_ci{
33bf215546Sopenharmony_ci   switch (swz) {
34bf215546Sopenharmony_ci   case PIPE_SWIZZLE_X  : return fmt->tic.src_x;
35bf215546Sopenharmony_ci   case PIPE_SWIZZLE_Y: return fmt->tic.src_y;
36bf215546Sopenharmony_ci   case PIPE_SWIZZLE_Z : return fmt->tic.src_z;
37bf215546Sopenharmony_ci   case PIPE_SWIZZLE_W: return fmt->tic.src_w;
38bf215546Sopenharmony_ci   case PIPE_SWIZZLE_1:
39bf215546Sopenharmony_ci      return tex_int ? G80_TIC_SOURCE_ONE_INT : G80_TIC_SOURCE_ONE_FLOAT;
40bf215546Sopenharmony_ci   case PIPE_SWIZZLE_0:
41bf215546Sopenharmony_ci   default:
42bf215546Sopenharmony_ci      return G80_TIC_SOURCE_ZERO;
43bf215546Sopenharmony_ci   }
44bf215546Sopenharmony_ci}
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cistruct pipe_sampler_view *
47bf215546Sopenharmony_cinv50_create_sampler_view(struct pipe_context *pipe,
48bf215546Sopenharmony_ci                         struct pipe_resource *res,
49bf215546Sopenharmony_ci                         const struct pipe_sampler_view *templ)
50bf215546Sopenharmony_ci{
51bf215546Sopenharmony_ci   uint32_t flags = 0;
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci   if (templ->target == PIPE_TEXTURE_RECT || templ->target == PIPE_BUFFER)
54bf215546Sopenharmony_ci      flags |= NV50_TEXVIEW_SCALED_COORDS;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   return nv50_create_texture_view(pipe, res, templ, flags);
57bf215546Sopenharmony_ci}
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_cistruct pipe_sampler_view *
60bf215546Sopenharmony_cinv50_create_texture_view(struct pipe_context *pipe,
61bf215546Sopenharmony_ci                         struct pipe_resource *texture,
62bf215546Sopenharmony_ci                         const struct pipe_sampler_view *templ,
63bf215546Sopenharmony_ci                         uint32_t flags)
64bf215546Sopenharmony_ci{
65bf215546Sopenharmony_ci   const uint32_t class_3d = nouveau_context(pipe)->screen->class_3d;
66bf215546Sopenharmony_ci   const struct util_format_description *desc;
67bf215546Sopenharmony_ci   const struct nv50_format *fmt;
68bf215546Sopenharmony_ci   uint64_t addr;
69bf215546Sopenharmony_ci   uint32_t *tic;
70bf215546Sopenharmony_ci   uint32_t swz[4];
71bf215546Sopenharmony_ci   uint32_t depth;
72bf215546Sopenharmony_ci   struct nv50_tic_entry *view;
73bf215546Sopenharmony_ci   struct nv50_miptree *mt = nv50_miptree(texture);
74bf215546Sopenharmony_ci   bool tex_int;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   view = MALLOC_STRUCT(nv50_tic_entry);
77bf215546Sopenharmony_ci   if (!view)
78bf215546Sopenharmony_ci      return NULL;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci   view->pipe = *templ;
81bf215546Sopenharmony_ci   view->pipe.reference.count = 1;
82bf215546Sopenharmony_ci   view->pipe.texture = NULL;
83bf215546Sopenharmony_ci   view->pipe.context = pipe;
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci   view->id = -1;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   pipe_resource_reference(&view->pipe.texture, texture);
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   tic = &view->tic[0];
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   desc = util_format_description(view->pipe.format);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   /* TIC[0] */
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   fmt = &nv50_format_table[view->pipe.format];
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   tex_int = util_format_is_pure_integer(view->pipe.format);
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   swz[0] = nv50_tic_swizzle(fmt, view->pipe.swizzle_r, tex_int);
100bf215546Sopenharmony_ci   swz[1] = nv50_tic_swizzle(fmt, view->pipe.swizzle_g, tex_int);
101bf215546Sopenharmony_ci   swz[2] = nv50_tic_swizzle(fmt, view->pipe.swizzle_b, tex_int);
102bf215546Sopenharmony_ci   swz[3] = nv50_tic_swizzle(fmt, view->pipe.swizzle_a, tex_int);
103bf215546Sopenharmony_ci   tic[0] = (fmt->tic.format << G80_TIC_0_COMPONENTS_SIZES__SHIFT) |
104bf215546Sopenharmony_ci            (fmt->tic.type_r << G80_TIC_0_R_DATA_TYPE__SHIFT) |
105bf215546Sopenharmony_ci            (fmt->tic.type_g << G80_TIC_0_G_DATA_TYPE__SHIFT) |
106bf215546Sopenharmony_ci            (fmt->tic.type_b << G80_TIC_0_B_DATA_TYPE__SHIFT) |
107bf215546Sopenharmony_ci            (fmt->tic.type_a << G80_TIC_0_A_DATA_TYPE__SHIFT) |
108bf215546Sopenharmony_ci            (swz[0] << G80_TIC_0_X_SOURCE__SHIFT) |
109bf215546Sopenharmony_ci            (swz[1] << G80_TIC_0_Y_SOURCE__SHIFT) |
110bf215546Sopenharmony_ci            (swz[2] << G80_TIC_0_Z_SOURCE__SHIFT) |
111bf215546Sopenharmony_ci            (swz[3] << G80_TIC_0_W_SOURCE__SHIFT);
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   addr = mt->base.address;
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   depth = MAX2(mt->base.base.array_size, mt->base.base.depth0);
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   if (mt->base.base.array_size > 1) {
118bf215546Sopenharmony_ci      /* there doesn't seem to be a base layer field in TIC */
119bf215546Sopenharmony_ci      addr += view->pipe.u.tex.first_layer * mt->layer_stride;
120bf215546Sopenharmony_ci      depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1;
121bf215546Sopenharmony_ci   }
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   tic[2] = 0x10001000 | G80_TIC_2_BORDER_SOURCE_COLOR;
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
126bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_SRGB_CONVERSION;
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
129bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_NORMALIZED_COORDS;
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
132bf215546Sopenharmony_ci      if (templ->target == PIPE_BUFFER) {
133bf215546Sopenharmony_ci         addr += view->pipe.u.buf.offset;
134bf215546Sopenharmony_ci         tic[2] |= G80_TIC_2_LAYOUT_PITCH | G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER;
135bf215546Sopenharmony_ci         tic[3] = 0;
136bf215546Sopenharmony_ci         tic[4] = /* width */
137bf215546Sopenharmony_ci            view->pipe.u.buf.size / (desc->block.bits / 8);
138bf215546Sopenharmony_ci         tic[5] = 0;
139bf215546Sopenharmony_ci      } else {
140bf215546Sopenharmony_ci         tic[2] |= G80_TIC_2_LAYOUT_PITCH | G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP;
141bf215546Sopenharmony_ci         tic[3] = mt->level[0].pitch;
142bf215546Sopenharmony_ci         tic[4] = mt->base.base.width0;
143bf215546Sopenharmony_ci         tic[5] = (1 << 16) | (mt->base.base.height0);
144bf215546Sopenharmony_ci      }
145bf215546Sopenharmony_ci      tic[6] =
146bf215546Sopenharmony_ci      tic[7] = 0;
147bf215546Sopenharmony_ci      tic[1] = addr;
148bf215546Sopenharmony_ci      tic[2] |= addr >> 32;
149bf215546Sopenharmony_ci      return &view->pipe;
150bf215546Sopenharmony_ci   }
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   tic[1] = addr;
153bf215546Sopenharmony_ci   tic[2] |= (addr >> 32) & 0xff;
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   tic[2] |=
156bf215546Sopenharmony_ci      ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) |
157bf215546Sopenharmony_ci      ((mt->level[0].tile_mode & 0xf00) << (25 - 8));
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   switch (templ->target) {
160bf215546Sopenharmony_ci   case PIPE_TEXTURE_1D:
161bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D;
162bf215546Sopenharmony_ci      break;
163bf215546Sopenharmony_ci   case PIPE_TEXTURE_2D:
164bf215546Sopenharmony_ci      if (mt->ms_x)
165bf215546Sopenharmony_ci         tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP;
166bf215546Sopenharmony_ci      else
167bf215546Sopenharmony_ci         tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D;
168bf215546Sopenharmony_ci      break;
169bf215546Sopenharmony_ci   case PIPE_TEXTURE_RECT:
170bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP;
171bf215546Sopenharmony_ci      break;
172bf215546Sopenharmony_ci   case PIPE_TEXTURE_3D:
173bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_TEXTURE_TYPE_THREE_D;
174bf215546Sopenharmony_ci      break;
175bf215546Sopenharmony_ci   case PIPE_TEXTURE_CUBE:
176bf215546Sopenharmony_ci      depth /= 6;
177bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_TEXTURE_TYPE_CUBEMAP;
178bf215546Sopenharmony_ci      break;
179bf215546Sopenharmony_ci   case PIPE_TEXTURE_1D_ARRAY:
180bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_ARRAY;
181bf215546Sopenharmony_ci      break;
182bf215546Sopenharmony_ci   case PIPE_TEXTURE_2D_ARRAY:
183bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_ARRAY;
184bf215546Sopenharmony_ci      break;
185bf215546Sopenharmony_ci   case PIPE_TEXTURE_CUBE_ARRAY:
186bf215546Sopenharmony_ci      depth /= 6;
187bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_TEXTURE_TYPE_CUBE_ARRAY;
188bf215546Sopenharmony_ci      break;
189bf215546Sopenharmony_ci   case PIPE_BUFFER:
190bf215546Sopenharmony_ci      assert(0); /* should be linear and handled above ! */
191bf215546Sopenharmony_ci      tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER | G80_TIC_2_LAYOUT_PITCH;
192bf215546Sopenharmony_ci      break;
193bf215546Sopenharmony_ci   default:
194bf215546Sopenharmony_ci      unreachable("unexpected/invalid texture target");
195bf215546Sopenharmony_ci   }
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
202bf215546Sopenharmony_ci   tic[5] |= depth << 16;
203bf215546Sopenharmony_ci   if (class_3d > NV50_3D_CLASS)
204bf215546Sopenharmony_ci      tic[5] |= mt->base.base.last_level << G80_TIC_5_MAP_MIP_LEVEL__SHIFT;
205bf215546Sopenharmony_ci   else
206bf215546Sopenharmony_ci      tic[5] |= view->pipe.u.tex.last_level << G80_TIC_5_MAP_MIP_LEVEL__SHIFT;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci   tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   if (class_3d > NV50_3D_CLASS)
211bf215546Sopenharmony_ci      tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
212bf215546Sopenharmony_ci   else
213bf215546Sopenharmony_ci      tic[7] = 0;
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   if (unlikely(!(tic[2] & G80_TIC_2_NORMALIZED_COORDS)))
216bf215546Sopenharmony_ci      if (mt->base.base.last_level)
217bf215546Sopenharmony_ci         tic[5] &= ~G80_TIC_5_MAP_MIP_LEVEL__MASK;
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   return &view->pipe;
220bf215546Sopenharmony_ci}
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_cistatic void
223bf215546Sopenharmony_cinv50_update_tic(struct nv50_context *nv50, struct nv50_tic_entry *tic,
224bf215546Sopenharmony_ci                struct nv04_resource *res)
225bf215546Sopenharmony_ci{
226bf215546Sopenharmony_ci   uint64_t address = res->address;
227bf215546Sopenharmony_ci   if (res->base.target != PIPE_BUFFER)
228bf215546Sopenharmony_ci      return;
229bf215546Sopenharmony_ci   address += tic->pipe.u.buf.offset;
230bf215546Sopenharmony_ci   if (tic->tic[1] == (uint32_t)address &&
231bf215546Sopenharmony_ci       (tic->tic[2] & 0xff) == address >> 32)
232bf215546Sopenharmony_ci      return;
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci   nv50_screen_tic_unlock(nv50->screen, tic);
235bf215546Sopenharmony_ci   tic->id = -1;
236bf215546Sopenharmony_ci   tic->tic[1] = address;
237bf215546Sopenharmony_ci   tic->tic[2] &= 0xffffff00;
238bf215546Sopenharmony_ci   tic->tic[2] |= address >> 32;
239bf215546Sopenharmony_ci}
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_cibool
242bf215546Sopenharmony_cinv50_validate_tic(struct nv50_context *nv50, int s)
243bf215546Sopenharmony_ci{
244bf215546Sopenharmony_ci   struct nouveau_pushbuf *push = nv50->base.pushbuf;
245bf215546Sopenharmony_ci   struct nouveau_bo *txc = nv50->screen->txc;
246bf215546Sopenharmony_ci   unsigned i;
247bf215546Sopenharmony_ci   bool need_flush = false;
248bf215546Sopenharmony_ci   const bool is_compute_stage = s == NV50_SHADER_STAGE_COMPUTE;
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS);
251bf215546Sopenharmony_ci   for (i = 0; i < nv50->num_textures[s]; ++i) {
252bf215546Sopenharmony_ci      struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
253bf215546Sopenharmony_ci      struct nv04_resource *res;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci      if (!tic) {
256bf215546Sopenharmony_ci         if (unlikely(is_compute_stage))
257bf215546Sopenharmony_ci            BEGIN_NV04(push, NV50_CP(BIND_TIC), 1);
258bf215546Sopenharmony_ci         else
259bf215546Sopenharmony_ci            BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
260bf215546Sopenharmony_ci         PUSH_DATA (push, (i << 1) | 0);
261bf215546Sopenharmony_ci         continue;
262bf215546Sopenharmony_ci      }
263bf215546Sopenharmony_ci      res = &nv50_miptree(tic->pipe.texture)->base;
264bf215546Sopenharmony_ci      nv50_update_tic(nv50, tic, res);
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci      if (tic->id < 0) {
267bf215546Sopenharmony_ci         tic->id = nv50_screen_tic_alloc(nv50->screen, tic);
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);
270bf215546Sopenharmony_ci         PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);
271bf215546Sopenharmony_ci         PUSH_DATA (push, 1);
272bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);
273bf215546Sopenharmony_ci         PUSH_DATA (push, 262144);
274bf215546Sopenharmony_ci         PUSH_DATA (push, 65536);
275bf215546Sopenharmony_ci         PUSH_DATA (push, 1);
276bf215546Sopenharmony_ci         PUSH_DATAh(push, txc->offset);
277bf215546Sopenharmony_ci         PUSH_DATA (push, txc->offset);
278bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);
279bf215546Sopenharmony_ci         PUSH_DATA (push, 0);
280bf215546Sopenharmony_ci         PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);
281bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);
282bf215546Sopenharmony_ci         PUSH_DATA (push, 32);
283bf215546Sopenharmony_ci         PUSH_DATA (push, 1);
284bf215546Sopenharmony_ci         PUSH_DATA (push, 0);
285bf215546Sopenharmony_ci         PUSH_DATA (push, 1);
286bf215546Sopenharmony_ci         PUSH_DATA (push, 0);
287bf215546Sopenharmony_ci         PUSH_DATA (push, 1);
288bf215546Sopenharmony_ci         PUSH_DATA (push, 0);
289bf215546Sopenharmony_ci         PUSH_DATA (push, tic->id * 32);
290bf215546Sopenharmony_ci         PUSH_DATA (push, 0);
291bf215546Sopenharmony_ci         PUSH_DATA (push, 0);
292bf215546Sopenharmony_ci         BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8);
293bf215546Sopenharmony_ci         PUSH_DATAp(push, &tic->tic[0], 8);
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci         need_flush = true;
296bf215546Sopenharmony_ci      } else
297bf215546Sopenharmony_ci      if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
298bf215546Sopenharmony_ci         if (unlikely(is_compute_stage))
299bf215546Sopenharmony_ci            BEGIN_NV04(push, NV50_CP(TEX_CACHE_CTL), 1);
300bf215546Sopenharmony_ci         else
301bf215546Sopenharmony_ci            BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1);
302bf215546Sopenharmony_ci         PUSH_DATA (push, 0x20);
303bf215546Sopenharmony_ci      }
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci      nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci      res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING;
308bf215546Sopenharmony_ci      res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci      if (unlikely(is_compute_stage)) {
311bf215546Sopenharmony_ci         BCTX_REFN(nv50->bufctx_cp, CP_TEXTURES, res, RD);
312bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_CP(BIND_TIC), 1);
313bf215546Sopenharmony_ci      } else {
314bf215546Sopenharmony_ci         BCTX_REFN(nv50->bufctx_3d, 3D_TEXTURES, res, RD);
315bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
316bf215546Sopenharmony_ci      }
317bf215546Sopenharmony_ci      PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1);
318bf215546Sopenharmony_ci   }
319bf215546Sopenharmony_ci   for (; i < nv50->state.num_textures[s]; ++i) {
320bf215546Sopenharmony_ci      if (unlikely(is_compute_stage))
321bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_CP(BIND_TIC), 1);
322bf215546Sopenharmony_ci      else
323bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1);
324bf215546Sopenharmony_ci      PUSH_DATA (push, (i << 1) | 0);
325bf215546Sopenharmony_ci   }
326bf215546Sopenharmony_ci   if (nv50->num_textures[s]) {
327bf215546Sopenharmony_ci      if (unlikely(is_compute_stage))
328bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_CP(CB_ADDR), 1);
329bf215546Sopenharmony_ci      else
330bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
331bf215546Sopenharmony_ci      PUSH_DATA (push, ((NV50_CB_AUX_TEX_MS_OFFSET + 16 * s * 2 * 4) << (8 - 2)) | NV50_CB_AUX);
332bf215546Sopenharmony_ci      if (unlikely(is_compute_stage))
333bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_CP(CB_DATA(0)), nv50->num_textures[s] * 2);
334bf215546Sopenharmony_ci      else
335bf215546Sopenharmony_ci         BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nv50->num_textures[s] * 2);
336bf215546Sopenharmony_ci      for (i = 0; i < nv50->num_textures[s]; i++) {
337bf215546Sopenharmony_ci         struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
338bf215546Sopenharmony_ci         struct nv50_miptree *res;
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci         if (!tic || tic->pipe.target == PIPE_BUFFER) {
341bf215546Sopenharmony_ci            PUSH_DATA (push, 0);
342bf215546Sopenharmony_ci            PUSH_DATA (push, 0);
343bf215546Sopenharmony_ci            continue;
344bf215546Sopenharmony_ci         }
345bf215546Sopenharmony_ci         res = nv50_miptree(tic->pipe.texture);
346bf215546Sopenharmony_ci         PUSH_DATA (push, res->ms_x);
347bf215546Sopenharmony_ci         PUSH_DATA (push, res->ms_y);
348bf215546Sopenharmony_ci      }
349bf215546Sopenharmony_ci   }
350bf215546Sopenharmony_ci   nv50->state.num_textures[s] = nv50->num_textures[s];
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci   return need_flush;
353bf215546Sopenharmony_ci}
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_civoid nv50_validate_textures(struct nv50_context *nv50)
356bf215546Sopenharmony_ci{
357bf215546Sopenharmony_ci   unsigned s;
358bf215546Sopenharmony_ci   bool need_flush = false;
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   for (s = 0; s < NV50_MAX_3D_SHADER_STAGES; ++s)
361bf215546Sopenharmony_ci      need_flush |= nv50_validate_tic(nv50, s);
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci   if (need_flush) {
364bf215546Sopenharmony_ci      BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TIC_FLUSH), 1);
365bf215546Sopenharmony_ci      PUSH_DATA (nv50->base.pushbuf, 0);
366bf215546Sopenharmony_ci   }
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   /* Invalidate all CP textures because they are aliased. */
369bf215546Sopenharmony_ci   nouveau_bufctx_reset(nv50->bufctx_cp, NV50_BIND_CP_TEXTURES);
370bf215546Sopenharmony_ci   nv50->dirty_cp |= NV50_NEW_CP_TEXTURES;
371bf215546Sopenharmony_ci}
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_cibool
374bf215546Sopenharmony_cinv50_validate_tsc(struct nv50_context *nv50, int s)
375bf215546Sopenharmony_ci{
376bf215546Sopenharmony_ci   struct nouveau_pushbuf *push = nv50->base.pushbuf;
377bf215546Sopenharmony_ci   unsigned i;
378bf215546Sopenharmony_ci   bool need_flush = false;
379bf215546Sopenharmony_ci   const bool is_compute_stage = s == NV50_SHADER_STAGE_COMPUTE;
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   assert(nv50->num_samplers[s] <= PIPE_MAX_SAMPLERS);
382bf215546Sopenharmony_ci   for (i = 0; i < nv50->num_samplers[s]; ++i) {
383bf215546Sopenharmony_ci      struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]);
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci      if (!tsc) {
386bf215546Sopenharmony_ci         if (is_compute_stage)
387bf215546Sopenharmony_ci            BEGIN_NV04(push, NV50_CP(BIND_TSC), 1);
388bf215546Sopenharmony_ci         else
389bf215546Sopenharmony_ci            BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
390bf215546Sopenharmony_ci         PUSH_DATA (push, (i << 4) | 0);
391bf215546Sopenharmony_ci         continue;
392bf215546Sopenharmony_ci      }
393bf215546Sopenharmony_ci      nv50->seamless_cube_map = tsc->seamless_cube_map;
394bf215546Sopenharmony_ci      if (tsc->id < 0) {
395bf215546Sopenharmony_ci         tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc);
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci         nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc,
398bf215546Sopenharmony_ci                             65536 + tsc->id * 32,
399bf215546Sopenharmony_ci                             NOUVEAU_BO_VRAM, 32, tsc->tsc);
400bf215546Sopenharmony_ci         need_flush = true;
401bf215546Sopenharmony_ci      }
402bf215546Sopenharmony_ci      nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32);
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci      if (is_compute_stage)
405bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_CP(BIND_TSC), 1);
406bf215546Sopenharmony_ci      else
407bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
408bf215546Sopenharmony_ci      PUSH_DATA (push, (tsc->id << 12) | (i << 4) | 1);
409bf215546Sopenharmony_ci   }
410bf215546Sopenharmony_ci   for (; i < nv50->state.num_samplers[s]; ++i) {
411bf215546Sopenharmony_ci      if (is_compute_stage)
412bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_CP(BIND_TSC), 1);
413bf215546Sopenharmony_ci      else
414bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
415bf215546Sopenharmony_ci      PUSH_DATA (push, (i << 4) | 0);
416bf215546Sopenharmony_ci   }
417bf215546Sopenharmony_ci   nv50->state.num_samplers[s] = nv50->num_samplers[s];
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci   // TXF, in unlinked tsc mode, will always use sampler 0. So we have to
420bf215546Sopenharmony_ci   // ensure that it remains bound. Its contents don't matter, all samplers we
421bf215546Sopenharmony_ci   // ever create have the SRGB_CONVERSION bit set, so as long as the first
422bf215546Sopenharmony_ci   // entry is initialized, we're good to go. This is the only bit that has
423bf215546Sopenharmony_ci   // any effect on what TXF does.
424bf215546Sopenharmony_ci   if (!nv50->samplers[s][0]) {
425bf215546Sopenharmony_ci      if (is_compute_stage)
426bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_CP(BIND_TSC), 1);
427bf215546Sopenharmony_ci      else
428bf215546Sopenharmony_ci         BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1);
429bf215546Sopenharmony_ci      PUSH_DATA (push, 1);
430bf215546Sopenharmony_ci   }
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci   return need_flush;
433bf215546Sopenharmony_ci}
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_civoid nv50_validate_samplers(struct nv50_context *nv50)
436bf215546Sopenharmony_ci{
437bf215546Sopenharmony_ci   unsigned s;
438bf215546Sopenharmony_ci   bool need_flush = false;
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   for (s = 0; s < NV50_MAX_3D_SHADER_STAGES; ++s)
441bf215546Sopenharmony_ci      need_flush |= nv50_validate_tsc(nv50, s);
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci   if (need_flush) {
444bf215546Sopenharmony_ci      BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TSC_FLUSH), 1);
445bf215546Sopenharmony_ci      PUSH_DATA (nv50->base.pushbuf, 0);
446bf215546Sopenharmony_ci   }
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci   /* Invalidate all CP samplers because they are aliased. */
449bf215546Sopenharmony_ci   nv50->dirty_cp |= NV50_NEW_CP_SAMPLERS;
450bf215546Sopenharmony_ci}
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci/* There can be up to 4 different MS levels (1, 2, 4, 8). To simplify the
453bf215546Sopenharmony_ci * shader logic, allow each one to take up 8 offsets.
454bf215546Sopenharmony_ci */
455bf215546Sopenharmony_ci#define COMBINE(x, y) x, y
456bf215546Sopenharmony_ci#define DUMMY 0, 0
457bf215546Sopenharmony_cistatic const uint32_t msaa_sample_xy_offsets[] = {
458bf215546Sopenharmony_ci   /* MS1 */
459bf215546Sopenharmony_ci   COMBINE(0, 0),
460bf215546Sopenharmony_ci   DUMMY,
461bf215546Sopenharmony_ci   DUMMY,
462bf215546Sopenharmony_ci   DUMMY,
463bf215546Sopenharmony_ci   DUMMY,
464bf215546Sopenharmony_ci   DUMMY,
465bf215546Sopenharmony_ci   DUMMY,
466bf215546Sopenharmony_ci   DUMMY,
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci   /* MS2 */
469bf215546Sopenharmony_ci   COMBINE(0, 0),
470bf215546Sopenharmony_ci   COMBINE(1, 0),
471bf215546Sopenharmony_ci   DUMMY,
472bf215546Sopenharmony_ci   DUMMY,
473bf215546Sopenharmony_ci   DUMMY,
474bf215546Sopenharmony_ci   DUMMY,
475bf215546Sopenharmony_ci   DUMMY,
476bf215546Sopenharmony_ci   DUMMY,
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci   /* MS4 */
479bf215546Sopenharmony_ci   COMBINE(0, 0),
480bf215546Sopenharmony_ci   COMBINE(1, 0),
481bf215546Sopenharmony_ci   COMBINE(0, 1),
482bf215546Sopenharmony_ci   COMBINE(1, 1),
483bf215546Sopenharmony_ci   DUMMY,
484bf215546Sopenharmony_ci   DUMMY,
485bf215546Sopenharmony_ci   DUMMY,
486bf215546Sopenharmony_ci   DUMMY,
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci   /* MS8 */
489bf215546Sopenharmony_ci   COMBINE(0, 0),
490bf215546Sopenharmony_ci   COMBINE(1, 0),
491bf215546Sopenharmony_ci   COMBINE(0, 1),
492bf215546Sopenharmony_ci   COMBINE(1, 1),
493bf215546Sopenharmony_ci   COMBINE(2, 0),
494bf215546Sopenharmony_ci   COMBINE(3, 0),
495bf215546Sopenharmony_ci   COMBINE(2, 1),
496bf215546Sopenharmony_ci   COMBINE(3, 1),
497bf215546Sopenharmony_ci};
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_civoid nv50_upload_ms_info(struct nouveau_pushbuf *push)
500bf215546Sopenharmony_ci{
501bf215546Sopenharmony_ci   BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
502bf215546Sopenharmony_ci   PUSH_DATA (push, (NV50_CB_AUX_MS_OFFSET << (8 - 2)) | NV50_CB_AUX);
503bf215546Sopenharmony_ci   BEGIN_NI04(push, NV50_3D(CB_DATA(0)), ARRAY_SIZE(msaa_sample_xy_offsets));
504bf215546Sopenharmony_ci   PUSH_DATAp(push, msaa_sample_xy_offsets, ARRAY_SIZE(msaa_sample_xy_offsets));
505bf215546Sopenharmony_ci}
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_civoid nv50_upload_tsc0(struct nv50_context *nv50)
508bf215546Sopenharmony_ci{
509bf215546Sopenharmony_ci   struct nouveau_pushbuf *push = nv50->base.pushbuf;
510bf215546Sopenharmony_ci   u32 data[8] = { G80_TSC_0_SRGB_CONVERSION };
511bf215546Sopenharmony_ci   nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc,
512bf215546Sopenharmony_ci                       65536 /* + tsc->id * 32 */,
513bf215546Sopenharmony_ci                       NOUVEAU_BO_VRAM, 32, data);
514bf215546Sopenharmony_ci   BEGIN_NV04(push, NV50_3D(TSC_FLUSH), 1);
515bf215546Sopenharmony_ci   PUSH_DATA (push, 0);
516bf215546Sopenharmony_ci}
517