1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/* Authors:
29bf215546Sopenharmony_ci *  Brian Paul
30bf215546Sopenharmony_ci */
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "util/u_inlines.h"
33bf215546Sopenharmony_ci#include "util/u_memory.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "draw/draw_context.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "lp_context.h"
38bf215546Sopenharmony_ci#include "lp_screen.h"
39bf215546Sopenharmony_ci#include "lp_state.h"
40bf215546Sopenharmony_ci#include "lp_debug.h"
41bf215546Sopenharmony_ci#include "frontend/sw_winsys.h"
42bf215546Sopenharmony_ci#include "lp_flush.h"
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_cistatic void *
46bf215546Sopenharmony_cillvmpipe_create_sampler_state(struct pipe_context *pipe,
47bf215546Sopenharmony_ci                              const struct pipe_sampler_state *sampler)
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci   struct pipe_sampler_state *state = mem_dup(sampler, sizeof *sampler);
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   if (LP_PERF & PERF_NO_MIP_LINEAR) {
52bf215546Sopenharmony_ci      if (state->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
53bf215546Sopenharmony_ci	 state->min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
54bf215546Sopenharmony_ci   }
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci   if (LP_PERF & PERF_NO_MIPMAPS)
57bf215546Sopenharmony_ci      state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci   if (LP_PERF & PERF_NO_LINEAR) {
60bf215546Sopenharmony_ci      state->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
61bf215546Sopenharmony_ci      state->min_img_filter = PIPE_TEX_FILTER_NEAREST;
62bf215546Sopenharmony_ci   }
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   return state;
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_cistatic void
69bf215546Sopenharmony_cillvmpipe_bind_sampler_states(struct pipe_context *pipe,
70bf215546Sopenharmony_ci                             enum pipe_shader_type shader,
71bf215546Sopenharmony_ci                             unsigned start,
72bf215546Sopenharmony_ci                             unsigned num,
73bf215546Sopenharmony_ci                             void **samplers)
74bf215546Sopenharmony_ci{
75bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
76bf215546Sopenharmony_ci   unsigned i;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   assert(shader < PIPE_SHADER_TYPES);
79bf215546Sopenharmony_ci   assert(start + num <= ARRAY_SIZE(llvmpipe->samplers[shader]));
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   draw_flush(llvmpipe->draw);
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   /* set the new samplers */
84bf215546Sopenharmony_ci   for (i = 0; i < num; i++) {
85bf215546Sopenharmony_ci      void *sampler = NULL;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci      if (samplers && samplers[i])
88bf215546Sopenharmony_ci	 sampler = samplers[i];
89bf215546Sopenharmony_ci      llvmpipe->samplers[shader][start + i] = sampler;
90bf215546Sopenharmony_ci   }
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   /* find highest non-null samplers[] entry */
93bf215546Sopenharmony_ci   {
94bf215546Sopenharmony_ci      unsigned j = MAX2(llvmpipe->num_samplers[shader], start + num);
95bf215546Sopenharmony_ci      while (j > 0 && llvmpipe->samplers[shader][j - 1] == NULL)
96bf215546Sopenharmony_ci         j--;
97bf215546Sopenharmony_ci      llvmpipe->num_samplers[shader] = j;
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   if (shader == PIPE_SHADER_VERTEX ||
101bf215546Sopenharmony_ci       shader == PIPE_SHADER_GEOMETRY ||
102bf215546Sopenharmony_ci       shader == PIPE_SHADER_TESS_CTRL ||
103bf215546Sopenharmony_ci       shader == PIPE_SHADER_TESS_EVAL) {
104bf215546Sopenharmony_ci      draw_set_samplers(llvmpipe->draw,
105bf215546Sopenharmony_ci                        shader,
106bf215546Sopenharmony_ci                        llvmpipe->samplers[shader],
107bf215546Sopenharmony_ci                        llvmpipe->num_samplers[shader]);
108bf215546Sopenharmony_ci   }
109bf215546Sopenharmony_ci   else if (shader == PIPE_SHADER_COMPUTE) {
110bf215546Sopenharmony_ci      llvmpipe->cs_dirty |= LP_CSNEW_SAMPLER;
111bf215546Sopenharmony_ci   } else {
112bf215546Sopenharmony_ci      llvmpipe->dirty |= LP_NEW_SAMPLER;
113bf215546Sopenharmony_ci   }
114bf215546Sopenharmony_ci}
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_cistatic void
118bf215546Sopenharmony_cillvmpipe_set_sampler_views(struct pipe_context *pipe,
119bf215546Sopenharmony_ci                           enum pipe_shader_type shader,
120bf215546Sopenharmony_ci                           unsigned start,
121bf215546Sopenharmony_ci                           unsigned num,
122bf215546Sopenharmony_ci                           unsigned unbind_num_trailing_slots,
123bf215546Sopenharmony_ci                           bool take_ownership,
124bf215546Sopenharmony_ci                           struct pipe_sampler_view **views)
125bf215546Sopenharmony_ci{
126bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
127bf215546Sopenharmony_ci   uint i;
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   assert(shader < PIPE_SHADER_TYPES);
132bf215546Sopenharmony_ci   assert(start + num <= ARRAY_SIZE(llvmpipe->sampler_views[shader]));
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   draw_flush(llvmpipe->draw);
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   /* set the new sampler views */
137bf215546Sopenharmony_ci   for (i = 0; i < num; i++) {
138bf215546Sopenharmony_ci      struct pipe_sampler_view *view = NULL;
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci      if (views && views[i])
141bf215546Sopenharmony_ci	 view = views[i];
142bf215546Sopenharmony_ci      /*
143bf215546Sopenharmony_ci       * Warn if someone tries to set a view created in a different context
144bf215546Sopenharmony_ci       * (which is why we need the hack above in the first place).
145bf215546Sopenharmony_ci       * An assert would be better but st/mesa relies on it...
146bf215546Sopenharmony_ci       */
147bf215546Sopenharmony_ci      if (view && view->context != pipe) {
148bf215546Sopenharmony_ci         debug_printf("Illegal setting of sampler_view %d created in another "
149bf215546Sopenharmony_ci                      "context\n", i);
150bf215546Sopenharmony_ci      }
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci      if (view)
153bf215546Sopenharmony_ci         llvmpipe_flush_resource(pipe, view->texture, 0, true, false, false, "sampler_view");
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci      if (take_ownership) {
156bf215546Sopenharmony_ci         pipe_sampler_view_reference(&llvmpipe->sampler_views[shader][start + i],
157bf215546Sopenharmony_ci                                     NULL);
158bf215546Sopenharmony_ci         llvmpipe->sampler_views[shader][start + i] = view;
159bf215546Sopenharmony_ci      } else {
160bf215546Sopenharmony_ci         pipe_sampler_view_reference(&llvmpipe->sampler_views[shader][start + i],
161bf215546Sopenharmony_ci                                     view);
162bf215546Sopenharmony_ci      }
163bf215546Sopenharmony_ci   }
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   for (; i < num + unbind_num_trailing_slots; i++) {
166bf215546Sopenharmony_ci      pipe_sampler_view_reference(&llvmpipe->sampler_views[shader][start + i],
167bf215546Sopenharmony_ci                                  NULL);
168bf215546Sopenharmony_ci   }
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   /* find highest non-null sampler_views[] entry */
171bf215546Sopenharmony_ci   {
172bf215546Sopenharmony_ci      unsigned j = MAX2(llvmpipe->num_sampler_views[shader], start + num);
173bf215546Sopenharmony_ci      while (j > 0 && llvmpipe->sampler_views[shader][j - 1] == NULL)
174bf215546Sopenharmony_ci         j--;
175bf215546Sopenharmony_ci      llvmpipe->num_sampler_views[shader] = j;
176bf215546Sopenharmony_ci   }
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   if (shader == PIPE_SHADER_VERTEX ||
179bf215546Sopenharmony_ci       shader == PIPE_SHADER_GEOMETRY ||
180bf215546Sopenharmony_ci       shader == PIPE_SHADER_TESS_CTRL ||
181bf215546Sopenharmony_ci       shader == PIPE_SHADER_TESS_EVAL) {
182bf215546Sopenharmony_ci      draw_set_sampler_views(llvmpipe->draw,
183bf215546Sopenharmony_ci                             shader,
184bf215546Sopenharmony_ci                             llvmpipe->sampler_views[shader],
185bf215546Sopenharmony_ci                             llvmpipe->num_sampler_views[shader]);
186bf215546Sopenharmony_ci   }
187bf215546Sopenharmony_ci   else if (shader == PIPE_SHADER_COMPUTE) {
188bf215546Sopenharmony_ci      llvmpipe->cs_dirty |= LP_CSNEW_SAMPLER_VIEW;
189bf215546Sopenharmony_ci   }
190bf215546Sopenharmony_ci   else if (shader == PIPE_SHADER_FRAGMENT) {
191bf215546Sopenharmony_ci      llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW;
192bf215546Sopenharmony_ci      lp_setup_set_fragment_sampler_views(llvmpipe->setup,
193bf215546Sopenharmony_ci                                          llvmpipe->num_sampler_views[PIPE_SHADER_FRAGMENT],
194bf215546Sopenharmony_ci                                          llvmpipe->sampler_views[PIPE_SHADER_FRAGMENT]);
195bf215546Sopenharmony_ci   }
196bf215546Sopenharmony_ci}
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_cistatic struct pipe_sampler_view *
200bf215546Sopenharmony_cillvmpipe_create_sampler_view(struct pipe_context *pipe,
201bf215546Sopenharmony_ci                            struct pipe_resource *texture,
202bf215546Sopenharmony_ci                            const struct pipe_sampler_view *templ)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
205bf215546Sopenharmony_ci   /*
206bf215546Sopenharmony_ci    * XXX: bind flags from OpenGL state tracker are notoriously unreliable.
207bf215546Sopenharmony_ci    * This looks unfixable, so fix the bind flags instead when it happens.
208bf215546Sopenharmony_ci    */
209bf215546Sopenharmony_ci   if (!(texture->bind & PIPE_BIND_SAMPLER_VIEW)) {
210bf215546Sopenharmony_ci      debug_printf("Illegal sampler view creation without bind flag\n");
211bf215546Sopenharmony_ci      texture->bind |= PIPE_BIND_SAMPLER_VIEW;
212bf215546Sopenharmony_ci   }
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci   if (view) {
215bf215546Sopenharmony_ci      *view = *templ;
216bf215546Sopenharmony_ci      view->reference.count = 1;
217bf215546Sopenharmony_ci      view->texture = NULL;
218bf215546Sopenharmony_ci      pipe_resource_reference(&view->texture, texture);
219bf215546Sopenharmony_ci      view->context = pipe;
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci#ifdef DEBUG
222bf215546Sopenharmony_ci     /*
223bf215546Sopenharmony_ci      * This is possibly too lenient, but the primary reason is just
224bf215546Sopenharmony_ci      * to catch gallium frontends which forget to initialize this, so
225bf215546Sopenharmony_ci      * it only catches clearly impossible view targets.
226bf215546Sopenharmony_ci      */
227bf215546Sopenharmony_ci      if (view->target != texture->target) {
228bf215546Sopenharmony_ci         if (view->target == PIPE_TEXTURE_1D)
229bf215546Sopenharmony_ci            assert(texture->target == PIPE_TEXTURE_1D_ARRAY);
230bf215546Sopenharmony_ci         else if (view->target == PIPE_TEXTURE_1D_ARRAY)
231bf215546Sopenharmony_ci            assert(texture->target == PIPE_TEXTURE_1D);
232bf215546Sopenharmony_ci         else if (view->target == PIPE_TEXTURE_2D)
233bf215546Sopenharmony_ci            assert(texture->target == PIPE_TEXTURE_2D_ARRAY ||
234bf215546Sopenharmony_ci                   texture->target == PIPE_TEXTURE_3D ||
235bf215546Sopenharmony_ci                   texture->target == PIPE_TEXTURE_CUBE ||
236bf215546Sopenharmony_ci                   texture->target == PIPE_TEXTURE_CUBE_ARRAY);
237bf215546Sopenharmony_ci         else if (view->target == PIPE_TEXTURE_2D_ARRAY)
238bf215546Sopenharmony_ci            assert(texture->target == PIPE_TEXTURE_2D ||
239bf215546Sopenharmony_ci                   texture->target == PIPE_TEXTURE_CUBE ||
240bf215546Sopenharmony_ci                   texture->target == PIPE_TEXTURE_CUBE_ARRAY);
241bf215546Sopenharmony_ci         else if (view->target == PIPE_TEXTURE_CUBE)
242bf215546Sopenharmony_ci            assert(texture->target == PIPE_TEXTURE_CUBE_ARRAY ||
243bf215546Sopenharmony_ci                   texture->target == PIPE_TEXTURE_2D_ARRAY);
244bf215546Sopenharmony_ci         else if (view->target == PIPE_TEXTURE_CUBE_ARRAY)
245bf215546Sopenharmony_ci            assert(texture->target == PIPE_TEXTURE_CUBE ||
246bf215546Sopenharmony_ci                   texture->target == PIPE_TEXTURE_2D_ARRAY);
247bf215546Sopenharmony_ci         else
248bf215546Sopenharmony_ci            assert(0);
249bf215546Sopenharmony_ci      }
250bf215546Sopenharmony_ci#endif
251bf215546Sopenharmony_ci   }
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci   return view;
254bf215546Sopenharmony_ci}
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_cistatic void
258bf215546Sopenharmony_cillvmpipe_sampler_view_destroy(struct pipe_context *pipe,
259bf215546Sopenharmony_ci                              struct pipe_sampler_view *view)
260bf215546Sopenharmony_ci{
261bf215546Sopenharmony_ci   pipe_resource_reference(&view->texture, NULL);
262bf215546Sopenharmony_ci   FREE(view);
263bf215546Sopenharmony_ci}
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_cistatic void
267bf215546Sopenharmony_cillvmpipe_delete_sampler_state(struct pipe_context *pipe,
268bf215546Sopenharmony_ci                              void *sampler)
269bf215546Sopenharmony_ci{
270bf215546Sopenharmony_ci   FREE( sampler );
271bf215546Sopenharmony_ci}
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_cistatic void
275bf215546Sopenharmony_ciprepare_shader_sampling(
276bf215546Sopenharmony_ci   struct llvmpipe_context *lp,
277bf215546Sopenharmony_ci   unsigned num,
278bf215546Sopenharmony_ci   struct pipe_sampler_view **views,
279bf215546Sopenharmony_ci   enum pipe_shader_type shader_type)
280bf215546Sopenharmony_ci{
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   unsigned i;
283bf215546Sopenharmony_ci   uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
284bf215546Sopenharmony_ci   uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
285bf215546Sopenharmony_ci   uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
286bf215546Sopenharmony_ci   const void *addr;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
289bf215546Sopenharmony_ci   if (!num)
290bf215546Sopenharmony_ci      return;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   for (i = 0; i < num; i++) {
293bf215546Sopenharmony_ci      struct pipe_sampler_view *view = i < num ? views[i] : NULL;
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci      if (view) {
296bf215546Sopenharmony_ci         struct pipe_resource *tex = view->texture;
297bf215546Sopenharmony_ci         struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex);
298bf215546Sopenharmony_ci         unsigned width0 = tex->width0;
299bf215546Sopenharmony_ci         unsigned num_layers = tex->depth0;
300bf215546Sopenharmony_ci         unsigned first_level = 0;
301bf215546Sopenharmony_ci         unsigned last_level = 0;
302bf215546Sopenharmony_ci         unsigned sample_stride = 0;
303bf215546Sopenharmony_ci         unsigned num_samples = tex->nr_samples;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci         if (!lp_tex->dt) {
306bf215546Sopenharmony_ci            /* regular texture - setup array of mipmap level offsets */
307bf215546Sopenharmony_ci            struct pipe_resource *res = view->texture;
308bf215546Sopenharmony_ci            int j;
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci            if (llvmpipe_resource_is_texture(res)) {
311bf215546Sopenharmony_ci               first_level = view->u.tex.first_level;
312bf215546Sopenharmony_ci               last_level = view->u.tex.last_level;
313bf215546Sopenharmony_ci               assert(first_level <= last_level);
314bf215546Sopenharmony_ci               assert(last_level <= res->last_level);
315bf215546Sopenharmony_ci               addr = lp_tex->tex_data;
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci               sample_stride = lp_tex->sample_stride;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci               for (j = first_level; j <= last_level; j++) {
320bf215546Sopenharmony_ci                  mip_offsets[j] = lp_tex->mip_offsets[j];
321bf215546Sopenharmony_ci                  row_stride[j] = lp_tex->row_stride[j];
322bf215546Sopenharmony_ci                  img_stride[j] = lp_tex->img_stride[j];
323bf215546Sopenharmony_ci               }
324bf215546Sopenharmony_ci               if (tex->target == PIPE_TEXTURE_1D_ARRAY ||
325bf215546Sopenharmony_ci                   tex->target == PIPE_TEXTURE_2D_ARRAY ||
326bf215546Sopenharmony_ci                   tex->target == PIPE_TEXTURE_CUBE ||
327bf215546Sopenharmony_ci                   tex->target == PIPE_TEXTURE_CUBE_ARRAY) {
328bf215546Sopenharmony_ci                  num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1;
329bf215546Sopenharmony_ci                  for (j = first_level; j <= last_level; j++) {
330bf215546Sopenharmony_ci                     mip_offsets[j] += view->u.tex.first_layer *
331bf215546Sopenharmony_ci                                       lp_tex->img_stride[j];
332bf215546Sopenharmony_ci                  }
333bf215546Sopenharmony_ci                  if (view->target == PIPE_TEXTURE_CUBE ||
334bf215546Sopenharmony_ci                      view->target == PIPE_TEXTURE_CUBE_ARRAY) {
335bf215546Sopenharmony_ci                     assert(num_layers % 6 == 0);
336bf215546Sopenharmony_ci                  }
337bf215546Sopenharmony_ci                  assert(view->u.tex.first_layer <= view->u.tex.last_layer);
338bf215546Sopenharmony_ci                  assert(view->u.tex.last_layer < res->array_size);
339bf215546Sopenharmony_ci               }
340bf215546Sopenharmony_ci            }
341bf215546Sopenharmony_ci            else {
342bf215546Sopenharmony_ci               unsigned view_blocksize = util_format_get_blocksize(view->format);
343bf215546Sopenharmony_ci               addr = lp_tex->data;
344bf215546Sopenharmony_ci               /* probably don't really need to fill that out */
345bf215546Sopenharmony_ci               mip_offsets[0] = 0;
346bf215546Sopenharmony_ci               row_stride[0] = 0;
347bf215546Sopenharmony_ci               img_stride[0] = 0;
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci               /* everything specified in number of elements here. */
350bf215546Sopenharmony_ci               width0 = view->u.buf.size / view_blocksize;
351bf215546Sopenharmony_ci               addr = (uint8_t *)addr + view->u.buf.offset;
352bf215546Sopenharmony_ci               assert(view->u.buf.offset + view->u.buf.size <= res->width0);
353bf215546Sopenharmony_ci            }
354bf215546Sopenharmony_ci         }
355bf215546Sopenharmony_ci         else {
356bf215546Sopenharmony_ci            /* display target texture/surface */
357bf215546Sopenharmony_ci            addr = llvmpipe_resource_map(tex, 0, 0, LP_TEX_USAGE_READ);
358bf215546Sopenharmony_ci            row_stride[0] = lp_tex->row_stride[0];
359bf215546Sopenharmony_ci            img_stride[0] = lp_tex->img_stride[0];
360bf215546Sopenharmony_ci            mip_offsets[0] = 0;
361bf215546Sopenharmony_ci            assert(addr);
362bf215546Sopenharmony_ci         }
363bf215546Sopenharmony_ci         draw_set_mapped_texture(lp->draw,
364bf215546Sopenharmony_ci                                 shader_type,
365bf215546Sopenharmony_ci                                 i,
366bf215546Sopenharmony_ci                                 width0, tex->height0, num_layers,
367bf215546Sopenharmony_ci                                 first_level, last_level,
368bf215546Sopenharmony_ci                                 num_samples, sample_stride,
369bf215546Sopenharmony_ci                                 addr,
370bf215546Sopenharmony_ci                                 row_stride, img_stride, mip_offsets);
371bf215546Sopenharmony_ci      }
372bf215546Sopenharmony_ci   }
373bf215546Sopenharmony_ci}
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci/**
377bf215546Sopenharmony_ci * Called whenever we're about to draw (no dirty flag, FIXME?).
378bf215546Sopenharmony_ci */
379bf215546Sopenharmony_civoid
380bf215546Sopenharmony_cillvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
381bf215546Sopenharmony_ci                                 unsigned num,
382bf215546Sopenharmony_ci                                 struct pipe_sampler_view **views)
383bf215546Sopenharmony_ci{
384bf215546Sopenharmony_ci   prepare_shader_sampling(lp, num, views, PIPE_SHADER_VERTEX);
385bf215546Sopenharmony_ci}
386bf215546Sopenharmony_ci
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci/**
389bf215546Sopenharmony_ci * Called whenever we're about to draw (no dirty flag, FIXME?).
390bf215546Sopenharmony_ci */
391bf215546Sopenharmony_civoid
392bf215546Sopenharmony_cillvmpipe_prepare_geometry_sampling(struct llvmpipe_context *lp,
393bf215546Sopenharmony_ci                                   unsigned num,
394bf215546Sopenharmony_ci                                   struct pipe_sampler_view **views)
395bf215546Sopenharmony_ci{
396bf215546Sopenharmony_ci   prepare_shader_sampling(lp, num, views, PIPE_SHADER_GEOMETRY);
397bf215546Sopenharmony_ci}
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci/**
400bf215546Sopenharmony_ci * Called whenever we're about to draw (no dirty flag, FIXME?).
401bf215546Sopenharmony_ci */
402bf215546Sopenharmony_civoid
403bf215546Sopenharmony_cillvmpipe_prepare_tess_ctrl_sampling(struct llvmpipe_context *lp,
404bf215546Sopenharmony_ci				    unsigned num,
405bf215546Sopenharmony_ci				    struct pipe_sampler_view **views)
406bf215546Sopenharmony_ci{
407bf215546Sopenharmony_ci   prepare_shader_sampling(lp, num, views, PIPE_SHADER_TESS_CTRL);
408bf215546Sopenharmony_ci}
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci/**
411bf215546Sopenharmony_ci * Called whenever we're about to draw (no dirty flag, FIXME?).
412bf215546Sopenharmony_ci */
413bf215546Sopenharmony_civoid
414bf215546Sopenharmony_cillvmpipe_prepare_tess_eval_sampling(struct llvmpipe_context *lp,
415bf215546Sopenharmony_ci				    unsigned num,
416bf215546Sopenharmony_ci				    struct pipe_sampler_view **views)
417bf215546Sopenharmony_ci{
418bf215546Sopenharmony_ci   prepare_shader_sampling(lp, num, views, PIPE_SHADER_TESS_EVAL);
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_civoid
422bf215546Sopenharmony_cillvmpipe_cleanup_stage_sampling(struct llvmpipe_context *ctx,
423bf215546Sopenharmony_ci                                enum pipe_shader_type stage)
424bf215546Sopenharmony_ci{
425bf215546Sopenharmony_ci   unsigned num, i;
426bf215546Sopenharmony_ci   struct pipe_sampler_view **views;
427bf215546Sopenharmony_ci   assert(ctx);
428bf215546Sopenharmony_ci   assert(stage < ARRAY_SIZE(ctx->num_sampler_views));
429bf215546Sopenharmony_ci   assert(stage < ARRAY_SIZE(ctx->sampler_views));
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci   num = ctx->num_sampler_views[stage];
432bf215546Sopenharmony_ci   views = ctx->sampler_views[stage];
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   for (i = 0; i < num; i++) {
437bf215546Sopenharmony_ci      struct pipe_sampler_view *view = views[i];
438bf215546Sopenharmony_ci      if (view) {
439bf215546Sopenharmony_ci         struct pipe_resource *tex = view->texture;
440bf215546Sopenharmony_ci         if (tex)
441bf215546Sopenharmony_ci            llvmpipe_resource_unmap(tex, 0, 0);
442bf215546Sopenharmony_ci      }
443bf215546Sopenharmony_ci   }
444bf215546Sopenharmony_ci}
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_cistatic void
447bf215546Sopenharmony_ciprepare_shader_images(
448bf215546Sopenharmony_ci   struct llvmpipe_context *lp,
449bf215546Sopenharmony_ci   unsigned num,
450bf215546Sopenharmony_ci   struct pipe_image_view *views,
451bf215546Sopenharmony_ci   enum pipe_shader_type shader_type)
452bf215546Sopenharmony_ci{
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci   unsigned i;
455bf215546Sopenharmony_ci   uint32_t row_stride;
456bf215546Sopenharmony_ci   uint32_t img_stride;
457bf215546Sopenharmony_ci   uint32_t sample_stride;
458bf215546Sopenharmony_ci   const void *addr;
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
461bf215546Sopenharmony_ci   if (!num)
462bf215546Sopenharmony_ci      return;
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_ci   for (i = 0; i < num; i++) {
465bf215546Sopenharmony_ci      struct pipe_image_view *view = i < num ? &views[i] : NULL;
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci      if (view) {
468bf215546Sopenharmony_ci         struct pipe_resource *img = view->resource;
469bf215546Sopenharmony_ci         struct llvmpipe_resource *lp_img = llvmpipe_resource(img);
470bf215546Sopenharmony_ci         if (!img)
471bf215546Sopenharmony_ci            continue;
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci         unsigned width = img->width0;
474bf215546Sopenharmony_ci         unsigned height = img->height0;
475bf215546Sopenharmony_ci         unsigned num_layers = img->depth0;
476bf215546Sopenharmony_ci         unsigned num_samples = img->nr_samples;
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci         const uint32_t bw = util_format_get_blockwidth(view->resource->format);
479bf215546Sopenharmony_ci         const uint32_t bh = util_format_get_blockheight(view->resource->format);
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_ci         width = DIV_ROUND_UP(width, bw);
482bf215546Sopenharmony_ci         height = DIV_ROUND_UP(height, bh);
483bf215546Sopenharmony_ci         width = u_minify(width, view->u.tex.level);
484bf215546Sopenharmony_ci         height = u_minify(height, view->u.tex.level);
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci         if (!lp_img->dt) {
487bf215546Sopenharmony_ci            /* regular texture - setup array of mipmap level offsets */
488bf215546Sopenharmony_ci            struct pipe_resource *res = view->resource;
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci            if (llvmpipe_resource_is_texture(res)) {
491bf215546Sopenharmony_ci               uint32_t mip_offset = lp_img->mip_offsets[view->u.tex.level];
492bf215546Sopenharmony_ci               addr = lp_img->tex_data;
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci               if (img->target == PIPE_TEXTURE_1D_ARRAY ||
495bf215546Sopenharmony_ci                   img->target == PIPE_TEXTURE_2D_ARRAY ||
496bf215546Sopenharmony_ci                   img->target == PIPE_TEXTURE_3D ||
497bf215546Sopenharmony_ci                   img->target == PIPE_TEXTURE_CUBE ||
498bf215546Sopenharmony_ci                   img->target == PIPE_TEXTURE_CUBE_ARRAY) {
499bf215546Sopenharmony_ci                  num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1;
500bf215546Sopenharmony_ci                  assert(view->u.tex.first_layer <= view->u.tex.last_layer);
501bf215546Sopenharmony_ci                  mip_offset += view->u.tex.first_layer * lp_img->img_stride[view->u.tex.level];
502bf215546Sopenharmony_ci               }
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci               row_stride = lp_img->row_stride[view->u.tex.level];
505bf215546Sopenharmony_ci               img_stride = lp_img->img_stride[view->u.tex.level];
506bf215546Sopenharmony_ci               sample_stride = lp_img->sample_stride;
507bf215546Sopenharmony_ci               addr = (uint8_t *)addr + mip_offset;
508bf215546Sopenharmony_ci            }
509bf215546Sopenharmony_ci            else {
510bf215546Sopenharmony_ci               unsigned view_blocksize = util_format_get_blocksize(view->format);
511bf215546Sopenharmony_ci               addr = lp_img->data;
512bf215546Sopenharmony_ci               /* probably don't really need to fill that out */
513bf215546Sopenharmony_ci               row_stride = 0;
514bf215546Sopenharmony_ci               img_stride = 0;
515bf215546Sopenharmony_ci               sample_stride = 0;
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_ci               /* everything specified in number of elements here. */
518bf215546Sopenharmony_ci               width = view->u.buf.size / view_blocksize;
519bf215546Sopenharmony_ci               addr = (uint8_t *)addr + view->u.buf.offset;
520bf215546Sopenharmony_ci               assert(view->u.buf.offset + view->u.buf.size <= res->width0);
521bf215546Sopenharmony_ci            }
522bf215546Sopenharmony_ci         }
523bf215546Sopenharmony_ci         else {
524bf215546Sopenharmony_ci            /* display target texture/surface */
525bf215546Sopenharmony_ci            addr = llvmpipe_resource_map(img, 0, 0, LP_TEX_USAGE_READ);
526bf215546Sopenharmony_ci            row_stride = lp_img->row_stride[0];
527bf215546Sopenharmony_ci            img_stride = lp_img->img_stride[0];
528bf215546Sopenharmony_ci            sample_stride = 0;
529bf215546Sopenharmony_ci            assert(addr);
530bf215546Sopenharmony_ci         }
531bf215546Sopenharmony_ci         draw_set_mapped_image(lp->draw,
532bf215546Sopenharmony_ci                               shader_type,
533bf215546Sopenharmony_ci                               i,
534bf215546Sopenharmony_ci                               width, height, num_layers,
535bf215546Sopenharmony_ci                               addr,
536bf215546Sopenharmony_ci                               row_stride, img_stride,
537bf215546Sopenharmony_ci                               num_samples, sample_stride);
538bf215546Sopenharmony_ci      }
539bf215546Sopenharmony_ci   }
540bf215546Sopenharmony_ci}
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ci/**
544bf215546Sopenharmony_ci * Called whenever we're about to draw (no dirty flag, FIXME?).
545bf215546Sopenharmony_ci */
546bf215546Sopenharmony_civoid
547bf215546Sopenharmony_cillvmpipe_prepare_vertex_images(struct llvmpipe_context *lp,
548bf215546Sopenharmony_ci                               unsigned num,
549bf215546Sopenharmony_ci                               struct pipe_image_view *views)
550bf215546Sopenharmony_ci{
551bf215546Sopenharmony_ci   prepare_shader_images(lp, num, views, PIPE_SHADER_VERTEX);
552bf215546Sopenharmony_ci}
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci/**
556bf215546Sopenharmony_ci * Called whenever we're about to draw (no dirty flag, FIXME?).
557bf215546Sopenharmony_ci */
558bf215546Sopenharmony_civoid
559bf215546Sopenharmony_cillvmpipe_prepare_geometry_images(struct llvmpipe_context *lp,
560bf215546Sopenharmony_ci                                 unsigned num,
561bf215546Sopenharmony_ci                                 struct pipe_image_view *views)
562bf215546Sopenharmony_ci{
563bf215546Sopenharmony_ci   prepare_shader_images(lp, num, views, PIPE_SHADER_GEOMETRY);
564bf215546Sopenharmony_ci}
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci/**
567bf215546Sopenharmony_ci * Called whenever we're about to draw (no dirty flag, FIXME?).
568bf215546Sopenharmony_ci */
569bf215546Sopenharmony_civoid
570bf215546Sopenharmony_cillvmpipe_prepare_tess_ctrl_images(struct llvmpipe_context *lp,
571bf215546Sopenharmony_ci                                  unsigned num,
572bf215546Sopenharmony_ci                                  struct pipe_image_view *views)
573bf215546Sopenharmony_ci{
574bf215546Sopenharmony_ci   prepare_shader_images(lp, num, views, PIPE_SHADER_TESS_CTRL);
575bf215546Sopenharmony_ci}
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci/**
578bf215546Sopenharmony_ci * Called whenever we're about to draw (no dirty flag, FIXME?).
579bf215546Sopenharmony_ci */
580bf215546Sopenharmony_civoid
581bf215546Sopenharmony_cillvmpipe_prepare_tess_eval_images(struct llvmpipe_context *lp,
582bf215546Sopenharmony_ci                                  unsigned num,
583bf215546Sopenharmony_ci                                  struct pipe_image_view *views)
584bf215546Sopenharmony_ci{
585bf215546Sopenharmony_ci   prepare_shader_images(lp, num, views, PIPE_SHADER_TESS_EVAL);
586bf215546Sopenharmony_ci}
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_civoid
589bf215546Sopenharmony_cillvmpipe_cleanup_stage_images(struct llvmpipe_context *ctx,
590bf215546Sopenharmony_ci                              enum pipe_shader_type stage)
591bf215546Sopenharmony_ci{
592bf215546Sopenharmony_ci   unsigned num, i;
593bf215546Sopenharmony_ci   struct pipe_image_view *views;
594bf215546Sopenharmony_ci   assert(ctx);
595bf215546Sopenharmony_ci   assert(stage < ARRAY_SIZE(ctx->num_images));
596bf215546Sopenharmony_ci   assert(stage < ARRAY_SIZE(ctx->images));
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   num = ctx->num_images[stage];
599bf215546Sopenharmony_ci   views = ctx->images[stage];
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci   assert(num <= LP_MAX_TGSI_SHADER_IMAGES);
602bf215546Sopenharmony_ci
603bf215546Sopenharmony_ci   for (i = 0; i < num; i++) {
604bf215546Sopenharmony_ci      struct pipe_image_view *view = &views[i];
605bf215546Sopenharmony_ci      assert(view);
606bf215546Sopenharmony_ci      struct pipe_resource *img = view->resource;
607bf215546Sopenharmony_ci      if (img)
608bf215546Sopenharmony_ci         llvmpipe_resource_unmap(img, 0, 0);
609bf215546Sopenharmony_ci   }
610bf215546Sopenharmony_ci}
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_civoid
613bf215546Sopenharmony_cillvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe)
614bf215546Sopenharmony_ci{
615bf215546Sopenharmony_ci   llvmpipe->pipe.create_sampler_state = llvmpipe_create_sampler_state;
616bf215546Sopenharmony_ci
617bf215546Sopenharmony_ci   llvmpipe->pipe.bind_sampler_states = llvmpipe_bind_sampler_states;
618bf215546Sopenharmony_ci   llvmpipe->pipe.create_sampler_view = llvmpipe_create_sampler_view;
619bf215546Sopenharmony_ci   llvmpipe->pipe.set_sampler_views = llvmpipe_set_sampler_views;
620bf215546Sopenharmony_ci   llvmpipe->pipe.sampler_view_destroy = llvmpipe_sampler_view_destroy;
621bf215546Sopenharmony_ci   llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state;
622bf215546Sopenharmony_ci}
623