Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4
 * All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice (including the
15
 * next paragraph) shall be included in all copies or substantial portions
16
 * of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 **************************************************************************/
27
 
28
/* Authors:
29
 *  Brian Paul
30
 */
31
 
32
#include "util/u_inlines.h"
33
#include "util/u_memory.h"
34
 
35
#include "draw/draw_context.h"
36
 
37
#include "lp_context.h"
38
#include "lp_screen.h"
39
#include "lp_state.h"
40
#include "lp_debug.h"
41
#include "state_tracker/sw_winsys.h"
42
 
43
 
44
static void *
45
llvmpipe_create_sampler_state(struct pipe_context *pipe,
46
                              const struct pipe_sampler_state *sampler)
47
{
48
   struct pipe_sampler_state *state = mem_dup(sampler, sizeof *sampler);
49
 
50
   if (LP_PERF & PERF_NO_MIP_LINEAR) {
51
      if (state->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
52
	 state->min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
53
   }
54
 
55
   if (LP_PERF & PERF_NO_MIPMAPS)
56
      state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
57
 
58
   if (LP_PERF & PERF_NO_LINEAR) {
59
      state->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
60
      state->min_img_filter = PIPE_TEX_FILTER_NEAREST;
61
   }
62
 
63
   return state;
64
}
65
 
66
 
67
static void
68
llvmpipe_bind_sampler_states(struct pipe_context *pipe,
69
                             unsigned shader,
70
                             unsigned start,
71
                             unsigned num,
72
                             void **samplers)
73
{
74
   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
75
   unsigned i;
76
 
77
   assert(shader < PIPE_SHADER_TYPES);
78
   assert(start + num <= Elements(llvmpipe->samplers[shader]));
79
 
80
   /* Check for no-op */
81
   if (start + num <= llvmpipe->num_samplers[shader] &&
82
       !memcmp(llvmpipe->samplers[shader] + start, samplers,
83
               num * sizeof(void *))) {
84
      return;
85
   }
86
 
87
   draw_flush(llvmpipe->draw);
88
 
89
   /* set the new samplers */
90
   for (i = 0; i < num; i++) {
91
      llvmpipe->samplers[shader][start + i] = samplers[i];
92
   }
93
 
94
   /* find highest non-null samplers[] entry */
95
   {
96
      unsigned j = MAX2(llvmpipe->num_samplers[shader], start + num);
97
      while (j > 0 && llvmpipe->samplers[shader][j - 1] == NULL)
98
         j--;
99
      llvmpipe->num_samplers[shader] = j;
100
   }
101
 
102
   if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
103
      draw_set_samplers(llvmpipe->draw,
104
                        shader,
105
                        llvmpipe->samplers[shader],
106
                        llvmpipe->num_samplers[shader]);
107
   }
108
 
109
   llvmpipe->dirty |= LP_NEW_SAMPLER;
110
}
111
 
112
 
113
static void
114
llvmpipe_bind_fragment_sampler_states(struct pipe_context *pipe,
115
                                      unsigned num, void **samplers)
116
{
117
   llvmpipe_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, num, samplers);
118
}
119
 
120
 
121
static void
122
llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
123
                                    unsigned num, void **samplers)
124
{
125
   llvmpipe_bind_sampler_states(pipe, PIPE_SHADER_VERTEX, 0, num, samplers);
126
}
127
 
128
 
129
static void
130
llvmpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
131
                                      unsigned num, void **samplers)
132
{
133
   llvmpipe_bind_sampler_states(pipe, PIPE_SHADER_GEOMETRY, 0, num, samplers);
134
}
135
 
136
static void
137
llvmpipe_set_sampler_views(struct pipe_context *pipe,
138
                           unsigned shader,
139
                           unsigned start,
140
                           unsigned num,
141
                           struct pipe_sampler_view **views)
142
{
143
   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
144
   uint i;
145
 
146
   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
147
 
148
   assert(shader < PIPE_SHADER_TYPES);
149
   assert(start + num <= Elements(llvmpipe->sampler_views[shader]));
150
 
151
   /* Check for no-op */
152
   if (start + num <= llvmpipe->num_sampler_views[shader] &&
153
       !memcmp(llvmpipe->sampler_views[shader] + start, views,
154
               num * sizeof(struct pipe_sampler_view *))) {
155
      return;
156
   }
157
 
158
   draw_flush(llvmpipe->draw);
159
 
160
   /* set the new sampler views */
161
   for (i = 0; i < num; i++) {
162
      pipe_sampler_view_reference(&llvmpipe->sampler_views[shader][start + i],
163
                                  views[i]);
164
   }
165
 
166
   /* find highest non-null sampler_views[] entry */
167
   {
168
      unsigned j = MAX2(llvmpipe->num_sampler_views[shader], start + num);
169
      while (j > 0 && llvmpipe->sampler_views[shader][j - 1] == NULL)
170
         j--;
171
      llvmpipe->num_sampler_views[shader] = j;
172
   }
173
 
174
   if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
175
      draw_set_sampler_views(llvmpipe->draw,
176
                             shader,
177
                             llvmpipe->sampler_views[shader],
178
                             llvmpipe->num_sampler_views[shader]);
179
   }
180
 
181
   llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW;
182
}
183
 
184
 
185
static void
186
llvmpipe_set_fragment_sampler_views(struct pipe_context *pipe,
187
                                    unsigned num,
188
                                    struct pipe_sampler_view **views)
189
{
190
   llvmpipe_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num, views);
191
}
192
 
193
 
194
static void
195
llvmpipe_set_vertex_sampler_views(struct pipe_context *pipe,
196
                                  unsigned num,
197
                                  struct pipe_sampler_view **views)
198
{
199
   llvmpipe_set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, num, views);
200
}
201
 
202
 
203
static void
204
llvmpipe_set_geometry_sampler_views(struct pipe_context *pipe,
205
                                    unsigned num,
206
                                    struct pipe_sampler_view **views)
207
{
208
   llvmpipe_set_sampler_views(pipe, PIPE_SHADER_GEOMETRY, 0, num, views);
209
}
210
 
211
static struct pipe_sampler_view *
212
llvmpipe_create_sampler_view(struct pipe_context *pipe,
213
                            struct pipe_resource *texture,
214
                            const struct pipe_sampler_view *templ)
215
{
216
   struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
217
   /*
218
    * XXX we REALLY want to see the correct bind flag here but the OpenGL
219
    * state tracker can't guarantee that at least for texture buffer objects.
220
    */
221
   if (!(texture->bind & PIPE_BIND_SAMPLER_VIEW))
222
      debug_printf("Illegal sampler view creation without bind flag\n");
223
 
224
   if (view) {
225
      *view = *templ;
226
      view->reference.count = 1;
227
      view->texture = NULL;
228
      pipe_resource_reference(&view->texture, texture);
229
      view->context = pipe;
230
   }
231
 
232
   return view;
233
}
234
 
235
 
236
static void
237
llvmpipe_sampler_view_destroy(struct pipe_context *pipe,
238
                              struct pipe_sampler_view *view)
239
{
240
   pipe_resource_reference(&view->texture, NULL);
241
   FREE(view);
242
}
243
 
244
 
245
static void
246
llvmpipe_delete_sampler_state(struct pipe_context *pipe,
247
                              void *sampler)
248
{
249
   FREE( sampler );
250
}
251
 
252
 
253
static void
254
prepare_shader_sampling(
255
   struct llvmpipe_context *lp,
256
   unsigned num,
257
   struct pipe_sampler_view **views,
258
   unsigned shader_type,
259
   struct pipe_resource *mapped_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS])
260
{
261
 
262
   unsigned i;
263
   uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
264
   uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
265
   uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
266
   const void *addr;
267
 
268
   assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
269
   if (!num)
270
      return;
271
 
272
   for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
273
      struct pipe_sampler_view *view = i < num ? views[i] : NULL;
274
 
275
      if (view) {
276
         struct pipe_resource *tex = view->texture;
277
         struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex);
278
         unsigned width0 = tex->width0;
279
         unsigned num_layers = tex->depth0;
280
         unsigned first_level = 0;
281
         unsigned last_level = 0;
282
 
283
         /* We're referencing the texture's internal data, so save a
284
          * reference to it.
285
          */
286
         pipe_resource_reference(&mapped_tex[i], tex);
287
 
288
         if (!lp_tex->dt) {
289
            /* regular texture - setup array of mipmap level offsets */
290
            struct pipe_resource *res = view->texture;
291
            int j;
292
            void *mip_ptr;
293
 
294
            if (llvmpipe_resource_is_texture(res)) {
295
               first_level = view->u.tex.first_level;
296
               last_level = view->u.tex.last_level;
297
               assert(first_level <= last_level);
298
               assert(last_level <= res->last_level);
299
 
300
               /* must trigger allocation first before we can get base ptr */
301
               /* XXX this may fail due to OOM ? */
302
               mip_ptr = llvmpipe_get_texture_image_all(lp_tex, view->u.tex.first_level,
303
                                                        LP_TEX_USAGE_READ);
304
               addr = lp_tex->linear_img.data;
305
 
306
               for (j = first_level; j <= last_level; j++) {
307
                  mip_ptr = llvmpipe_get_texture_image_all(lp_tex, j,
308
                                                           LP_TEX_USAGE_READ);
309
                  mip_offsets[j] = (uint8_t *)mip_ptr - (uint8_t *)addr;
310
                  /*
311
                   * could get mip offset directly but need call above to
312
                   * invoke tiled->linear conversion.
313
                   */
314
                  assert(lp_tex->linear_mip_offsets[j] == mip_offsets[j]);
315
                  row_stride[j] = lp_tex->row_stride[j];
316
                  img_stride[j] = lp_tex->img_stride[j];
317
               }
318
               if (res->target == PIPE_TEXTURE_1D_ARRAY ||
319
                   res->target == PIPE_TEXTURE_2D_ARRAY) {
320
                  num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1;
321
                  for (j = first_level; j <= last_level; j++) {
322
                     mip_offsets[j] += view->u.tex.first_layer *
323
                                       lp_tex->img_stride[j];
324
                  }
325
                  assert(view->u.tex.first_layer <= view->u.tex.last_layer);
326
                  assert(view->u.tex.last_layer < res->array_size);
327
               }
328
            }
329
            else {
330
               unsigned view_blocksize = util_format_get_blocksize(view->format);
331
               mip_ptr = lp_tex->data;
332
               addr = mip_ptr;
333
               /* probably don't really need to fill that out */
334
               mip_offsets[0] = 0;
335
               row_stride[0] = 0;
336
               row_stride[0] = 0;
337
 
338
               /* everything specified in number of elements here. */
339
               width0 = view->u.buf.last_element - view->u.buf.first_element + 1;
340
               addr = (uint8_t *)addr + view->u.buf.first_element *
341
                               view_blocksize;
342
               assert(view->u.buf.first_element <= view->u.buf.last_element);
343
               assert(view->u.buf.last_element * view_blocksize < res->width0);
344
            }
345
         }
346
         else {
347
            /* display target texture/surface */
348
            /*
349
             * XXX: Where should this be unmapped?
350
             */
351
            struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen);
352
            struct sw_winsys *winsys = screen->winsys;
353
            addr = winsys->displaytarget_map(winsys, lp_tex->dt,
354
                                                PIPE_TRANSFER_READ);
355
            row_stride[0] = lp_tex->row_stride[0];
356
            img_stride[0] = lp_tex->img_stride[0];
357
            mip_offsets[0] = 0;
358
            assert(addr);
359
         }
360
         draw_set_mapped_texture(lp->draw,
361
                                 shader_type,
362
                                 i,
363
                                 width0, tex->height0, num_layers,
364
                                 first_level, last_level,
365
                                 addr,
366
                                 row_stride, img_stride, mip_offsets);
367
      }
368
   }
369
}
370
 
371
 
372
/**
373
 * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
374
 */
375
void
376
llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
377
                                 unsigned num,
378
                                 struct pipe_sampler_view **views)
379
{
380
   prepare_shader_sampling(lp, num, views, PIPE_SHADER_VERTEX,
381
                           lp->mapped_vs_tex);
382
}
383
 
384
void
385
llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context *ctx)
386
{
387
   unsigned i;
388
   for (i = 0; i < Elements(ctx->mapped_vs_tex); i++) {
389
      pipe_resource_reference(&ctx->mapped_vs_tex[i], NULL);
390
   }
391
}
392
 
393
 
394
/**
395
 * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
396
 */
397
void
398
llvmpipe_prepare_geometry_sampling(struct llvmpipe_context *lp,
399
                                   unsigned num,
400
                                   struct pipe_sampler_view **views)
401
{
402
   prepare_shader_sampling(lp, num, views, PIPE_SHADER_GEOMETRY,
403
                           lp->mapped_gs_tex);
404
}
405
 
406
void
407
llvmpipe_cleanup_geometry_sampling(struct llvmpipe_context *ctx)
408
{
409
   unsigned i;
410
   for (i = 0; i < Elements(ctx->mapped_gs_tex); i++) {
411
      pipe_resource_reference(&ctx->mapped_gs_tex[i], NULL);
412
   }
413
}
414
 
415
void
416
llvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe)
417
{
418
   llvmpipe->pipe.create_sampler_state = llvmpipe_create_sampler_state;
419
 
420
   llvmpipe->pipe.bind_fragment_sampler_states  = llvmpipe_bind_fragment_sampler_states;
421
   llvmpipe->pipe.bind_vertex_sampler_states  = llvmpipe_bind_vertex_sampler_states;
422
   llvmpipe->pipe.bind_geometry_sampler_states  = llvmpipe_bind_geometry_sampler_states;
423
   llvmpipe->pipe.set_fragment_sampler_views = llvmpipe_set_fragment_sampler_views;
424
   llvmpipe->pipe.set_vertex_sampler_views = llvmpipe_set_vertex_sampler_views;
425
   llvmpipe->pipe.set_geometry_sampler_views = llvmpipe_set_geometry_sampler_views;
426
   llvmpipe->pipe.create_sampler_view = llvmpipe_create_sampler_view;
427
   llvmpipe->pipe.sampler_view_destroy = llvmpipe_sampler_view_destroy;
428
   llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state;
429
}