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 2003 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
#include "util/u_inlines.h"
29
#include "util/u_math.h"
30
#include "util/u_memory.h"
31
#include "util/u_pstipple.h"
32
#include "pipe/p_shader_tokens.h"
33
#include "draw/draw_context.h"
34
#include "draw/draw_vertex.h"
35
#include "sp_context.h"
36
#include "sp_screen.h"
37
#include "sp_state.h"
38
#include "sp_texture.h"
39
#include "sp_tex_sample.h"
40
#include "sp_tex_tile_cache.h"
41
 
42
 
43
/**
44
 * Mark the current vertex layout as "invalid".
45
 * We'll validate the vertex layout later, when we start to actually
46
 * render a point or line or tri.
47
 */
48
static void
49
invalidate_vertex_layout(struct softpipe_context *softpipe)
50
{
51
   softpipe->vertex_info.num_attribs =  0;
52
}
53
 
54
 
55
/**
56
 * The vertex info describes how to convert the post-transformed vertices
57
 * (simple float[][4]) used by the 'draw' module into vertices for
58
 * rasterization.
59
 *
60
 * This function validates the vertex layout and returns a pointer to a
61
 * vertex_info object.
62
 */
63
struct vertex_info *
64
softpipe_get_vertex_info(struct softpipe_context *softpipe)
65
{
66
   struct vertex_info *vinfo = &softpipe->vertex_info;
67
 
68
   if (vinfo->num_attribs == 0) {
69
      /* compute vertex layout now */
70
      const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
71
      struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
72
      const uint num = draw_num_shader_outputs(softpipe->draw);
73
      uint i;
74
 
75
      /* Tell draw_vbuf to simply emit the whole post-xform vertex
76
       * as-is.  No longer any need to try and emit draw vertex_header
77
       * info.
78
       */
79
      vinfo_vbuf->num_attribs = 0;
80
      for (i = 0; i < num; i++) {
81
	 draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
82
      }
83
      draw_compute_vertex_size(vinfo_vbuf);
84
 
85
      /*
86
       * Loop over fragment shader inputs, searching for the matching output
87
       * from the vertex shader.
88
       */
89
      vinfo->num_attribs = 0;
90
      for (i = 0; i < fsInfo->num_inputs; i++) {
91
         int src;
92
         enum interp_mode interp = INTERP_LINEAR;
93
 
94
         switch (fsInfo->input_interpolate[i]) {
95
         case TGSI_INTERPOLATE_CONSTANT:
96
            interp = INTERP_CONSTANT;
97
            break;
98
         case TGSI_INTERPOLATE_LINEAR:
99
            interp = INTERP_LINEAR;
100
            break;
101
         case TGSI_INTERPOLATE_PERSPECTIVE:
102
            interp = INTERP_PERSPECTIVE;
103
            break;
104
         case TGSI_INTERPOLATE_COLOR:
105
            assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
106
            break;
107
         default:
108
            assert(0);
109
         }
110
 
111
         switch (fsInfo->input_semantic_name[i]) {
112
         case TGSI_SEMANTIC_POSITION:
113
            interp = INTERP_POS;
114
            break;
115
 
116
         case TGSI_SEMANTIC_COLOR:
117
            if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
118
               if (softpipe->rasterizer->flatshade)
119
                  interp = INTERP_CONSTANT;
120
               else
121
                  interp = INTERP_PERSPECTIVE;
122
            }
123
            break;
124
         }
125
 
126
         /* this includes texcoords and varying vars */
127
         src = draw_find_shader_output(softpipe->draw,
128
                                       fsInfo->input_semantic_name[i],
129
                                       fsInfo->input_semantic_index[i]);
130
	 if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && src == -1)
131
	   /* try and find a bcolor */
132
	   src = draw_find_shader_output(softpipe->draw,
133
					 TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]);
134
 
135
         draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
136
      }
137
 
138
      softpipe->psize_slot = draw_find_shader_output(softpipe->draw,
139
                                                 TGSI_SEMANTIC_PSIZE, 0);
140
      if (softpipe->psize_slot >= 0) {
141
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
142
                               softpipe->psize_slot);
143
      }
144
 
145
      draw_compute_vertex_size(vinfo);
146
   }
147
 
148
   return vinfo;
149
}
150
 
151
 
152
/**
153
 * Called from vbuf module.
154
 *
155
 * Note that there's actually two different vertex layouts in softpipe.
156
 *
157
 * The normal one is computed in softpipe_get_vertex_info() above and is
158
 * used by the point/line/tri "setup" code.
159
 *
160
 * The other one (this one) is only used by the vbuf module (which is
161
 * not normally used by default but used in testing).  For the vbuf module,
162
 * we basically want to pass-through the draw module's vertex layout as-is.
163
 * When the softpipe vbuf code begins drawing, the normal vertex layout
164
 * will come into play again.
165
 */
166
struct vertex_info *
167
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
168
{
169
   (void) softpipe_get_vertex_info(softpipe);
170
   return &softpipe->vertex_info_vbuf;
171
}
172
 
173
 
174
/**
175
 * Recompute cliprect from scissor bounds, scissor enable and surface size.
176
 */
177
static void
178
compute_cliprect(struct softpipe_context *sp)
179
{
180
   /* SP_NEW_FRAMEBUFFER
181
    */
182
   uint surfWidth = sp->framebuffer.width;
183
   uint surfHeight = sp->framebuffer.height;
184
 
185
   /* SP_NEW_RASTERIZER
186
    */
187
   if (sp->rasterizer->scissor) {
188
 
189
      /* SP_NEW_SCISSOR
190
       *
191
       * clip to scissor rect:
192
       */
193
      sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
194
      sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
195
      sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
196
      sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
197
   }
198
   else {
199
      /* clip to surface bounds */
200
      sp->cliprect.minx = 0;
201
      sp->cliprect.miny = 0;
202
      sp->cliprect.maxx = surfWidth;
203
      sp->cliprect.maxy = surfHeight;
204
   }
205
}
206
 
207
 
208
static void
209
set_shader_sampler(struct softpipe_context *softpipe,
210
                   unsigned shader,
211
                   int max_sampler)
212
{
213
   int i;
214
   for (i = 0; i <= max_sampler; i++) {
215
      softpipe->tgsi.sampler[shader]->sp_sampler[i] =
216
         (struct sp_sampler *)(softpipe->samplers[shader][i]);
217
   }
218
}
219
 
220
static void
221
update_tgsi_samplers( struct softpipe_context *softpipe )
222
{
223
   unsigned i, sh;
224
 
225
   set_shader_sampler(softpipe, PIPE_SHADER_VERTEX,
226
                      softpipe->vs->max_sampler);
227
   set_shader_sampler(softpipe, PIPE_SHADER_FRAGMENT,
228
                      softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]);
229
   if (softpipe->gs) {
230
      set_shader_sampler(softpipe, PIPE_SHADER_GEOMETRY,
231
                         softpipe->gs->max_sampler);
232
   }
233
 
234
   /* XXX is this really necessary here??? */
235
   for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
236
      for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
237
         struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[sh][i];
238
         if (tc && tc->texture) {
239
            struct softpipe_resource *spt = softpipe_resource(tc->texture);
240
            if (spt->timestamp != tc->timestamp) {
241
               sp_tex_tile_cache_validate_texture( tc );
242
               /*
243
                 _debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
244
               */
245
               tc->timestamp = spt->timestamp;
246
            }
247
         }
248
      }
249
   }
250
}
251
 
252
 
253
static void
254
update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
255
{
256
   struct sp_fragment_shader_variant_key key;
257
 
258
   memset(&key, 0, sizeof(key));
259
 
260
   if (prim == PIPE_PRIM_TRIANGLES)
261
      key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
262
 
263
   if (softpipe->fs) {
264
      softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
265
                                                      softpipe->fs, &key);
266
 
267
      /* prepare the TGSI interpreter for FS execution */
268
      softpipe->fs_variant->prepare(softpipe->fs_variant,
269
                                    softpipe->fs_machine,
270
                                    (struct tgsi_sampler *) softpipe->
271
                                    tgsi.sampler[PIPE_SHADER_FRAGMENT]);
272
   }
273
   else {
274
      softpipe->fs_variant = NULL;
275
   }
276
 
277
   /* This would be the logical place to pass the fragment shader
278
    * to the draw module.  However, doing this here, during state
279
    * validation, causes problems with the 'draw' module helpers for
280
    * wide/AA/stippled lines.
281
    * In principle, the draw's fragment shader should be per-variant
282
    * but that doesn't work.  So we use a single draw fragment shader
283
    * per fragment shader, not per variant.
284
    */
285
#if 0
286
   if (softpipe->fs_variant) {
287
      draw_bind_fragment_shader(softpipe->draw,
288
                                softpipe->fs_variant->draw_shader);
289
   }
290
   else {
291
      draw_bind_fragment_shader(softpipe->draw, NULL);
292
   }
293
#endif
294
}
295
 
296
 
297
/**
298
 * This should be called when the polygon stipple pattern changes.
299
 * We create a new texture from the stipple pattern and create a new
300
 * sampler view.
301
 */
302
static void
303
update_polygon_stipple_pattern(struct softpipe_context *softpipe)
304
{
305
   struct pipe_resource *tex;
306
   struct pipe_sampler_view *view;
307
 
308
   tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
309
                                              softpipe->poly_stipple.stipple);
310
   pipe_resource_reference(&softpipe->pstipple.texture, tex);
311
   pipe_resource_reference(&tex, NULL);
312
 
313
   view = util_pstipple_create_sampler_view(&softpipe->pipe,
314
                                            softpipe->pstipple.texture);
315
   pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
316
   pipe_sampler_view_reference(&view, NULL);
317
}
318
 
319
 
320
/**
321
 * Should be called when polygon stipple is enabled/disabled or when
322
 * the fragment shader changes.
323
 * We add/update the fragment sampler and sampler views to sample from
324
 * the polygon stipple texture.  The texture unit that we use depends on
325
 * the fragment shader (we need to use a unit not otherwise used by the
326
 * shader).
327
 */
328
static void
329
update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
330
{
331
   if (prim == PIPE_PRIM_TRIANGLES &&
332
       softpipe->fs_variant->key.polygon_stipple) {
333
      const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
334
 
335
      /* sampler state */
336
      softpipe->samplers[PIPE_SHADER_FRAGMENT][unit] = softpipe->pstipple.sampler;
337
 
338
      /* sampler view state */
339
      softpipe_set_sampler_views(&softpipe->pipe, PIPE_SHADER_FRAGMENT,
340
                                 unit, 1, &softpipe->pstipple.sampler_view);
341
 
342
      softpipe->dirty |= SP_NEW_SAMPLER;
343
   }
344
}
345
 
346
 
347
/* Hopefully this will remain quite simple, otherwise need to pull in
348
 * something like the state tracker mechanism.
349
 */
350
void
351
softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
352
{
353
   struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
354
 
355
   /* Check for updated textures.
356
    */
357
   if (softpipe->tex_timestamp != sp_screen->timestamp) {
358
      softpipe->tex_timestamp = sp_screen->timestamp;
359
      softpipe->dirty |= SP_NEW_TEXTURE;
360
   }
361
 
362
#if DO_PSTIPPLE_IN_HELPER_MODULE
363
   if (softpipe->dirty & SP_NEW_STIPPLE)
364
      /* before updating samplers! */
365
      update_polygon_stipple_pattern(softpipe);
366
#endif
367
 
368
   if (softpipe->dirty & (SP_NEW_RASTERIZER |
369
                          SP_NEW_FS))
370
      update_fragment_shader(softpipe, prim);
371
 
372
#if DO_PSTIPPLE_IN_HELPER_MODULE
373
   if (softpipe->dirty & (SP_NEW_RASTERIZER |
374
                          SP_NEW_STIPPLE |
375
                          SP_NEW_FS))
376
      update_polygon_stipple_enable(softpipe, prim);
377
#endif
378
 
379
   /* TODO: this looks suboptimal */
380
   if (softpipe->dirty & (SP_NEW_SAMPLER |
381
                          SP_NEW_TEXTURE |
382
                          SP_NEW_FS |
383
                          SP_NEW_VS))
384
      update_tgsi_samplers( softpipe );
385
 
386
   if (softpipe->dirty & (SP_NEW_RASTERIZER |
387
                          SP_NEW_FS |
388
                          SP_NEW_VS))
389
      invalidate_vertex_layout( softpipe );
390
 
391
   if (softpipe->dirty & (SP_NEW_SCISSOR |
392
                          SP_NEW_RASTERIZER |
393
                          SP_NEW_FRAMEBUFFER))
394
      compute_cliprect(softpipe);
395
 
396
   if (softpipe->dirty & (SP_NEW_BLEND |
397
                          SP_NEW_DEPTH_STENCIL_ALPHA |
398
                          SP_NEW_FRAMEBUFFER |
399
                          SP_NEW_FS))
400
      sp_build_quad_pipeline(softpipe);
401
 
402
   softpipe->dirty = 0;
403
}