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
 Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3
 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4
 develop this 3D driver.
5
 
6
 Permission is hereby granted, free of charge, to any person obtaining
7
 a 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, sublicense, 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
16
 portions of the Software.
17
 
18
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22
 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 
26
 **********************************************************************/
27
 /*
28
  * Authors:
29
  *   Keith Whitwell 
30
  */
31
 
32
 
33
#include "main/glheader.h"
34
#include "main/macros.h"
35
#include "main/enums.h"
36
#include "program/program.h"
37
 
38
#include "intel_batchbuffer.h"
39
 
40
#include "brw_defines.h"
41
#include "brw_context.h"
42
#include "brw_eu.h"
43
#include "brw_clip.h"
44
 
45
 
46
 
47
 
48
struct brw_reg get_tmp( struct brw_clip_compile *c )
49
{
50
   struct brw_reg tmp = brw_vec4_grf(c->last_tmp, 0);
51
 
52
   if (++c->last_tmp > c->prog_data.total_grf)
53
      c->prog_data.total_grf = c->last_tmp;
54
 
55
   return tmp;
56
}
57
 
58
static void release_tmp( struct brw_clip_compile *c, struct brw_reg tmp )
59
{
60
   if (tmp.nr == c->last_tmp-1)
61
      c->last_tmp--;
62
}
63
 
64
 
65
static struct brw_reg make_plane_ud(GLuint x, GLuint y, GLuint z, GLuint w)
66
{
67
   return brw_imm_ud((w<<24) | (z<<16) | (y<<8) | x);
68
}
69
 
70
 
71
void brw_clip_init_planes( struct brw_clip_compile *c )
72
{
73
   struct brw_compile *p = &c->func;
74
 
75
   if (!c->key.nr_userclip) {
76
      brw_MOV(p, get_element_ud(c->reg.fixed_planes, 0), make_plane_ud( 0,    0, 0xff, 1));
77
      brw_MOV(p, get_element_ud(c->reg.fixed_planes, 1), make_plane_ud( 0,    0,    1, 1));
78
      brw_MOV(p, get_element_ud(c->reg.fixed_planes, 2), make_plane_ud( 0, 0xff,    0, 1));
79
      brw_MOV(p, get_element_ud(c->reg.fixed_planes, 3), make_plane_ud( 0,    1,    0, 1));
80
      brw_MOV(p, get_element_ud(c->reg.fixed_planes, 4), make_plane_ud(0xff,  0,    0, 1));
81
      brw_MOV(p, get_element_ud(c->reg.fixed_planes, 5), make_plane_ud( 1,    0,    0, 1));
82
   }
83
}
84
 
85
 
86
 
87
#define W 3
88
 
89
/* Project 'pos' to screen space (or back again), overwrite with results:
90
 */
91
void brw_clip_project_position(struct brw_clip_compile *c, struct brw_reg pos )
92
{
93
   struct brw_compile *p = &c->func;
94
 
95
   /* calc rhw
96
    */
97
   brw_math_invert(p, get_element(pos, W), get_element(pos, W));
98
 
99
   /* value.xyz *= value.rhw
100
    */
101
   brw_set_access_mode(p, BRW_ALIGN_16);
102
   brw_MUL(p, brw_writemask(pos, WRITEMASK_XYZ), pos, brw_swizzle1(pos, W));
103
   brw_set_access_mode(p, BRW_ALIGN_1);
104
}
105
 
106
 
107
static void brw_clip_project_vertex( struct brw_clip_compile *c,
108
				     struct brw_indirect vert_addr )
109
{
110
   struct brw_compile *p = &c->func;
111
   struct brw_reg tmp = get_tmp(c);
112
   GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
113
   GLuint ndc_offset = brw_varying_to_offset(&c->vue_map,
114
                                             BRW_VARYING_SLOT_NDC);
115
 
116
   /* Fixup position.  Extract from the original vertex and re-project
117
    * to screen space:
118
    */
119
   brw_MOV(p, tmp, deref_4f(vert_addr, hpos_offset));
120
   brw_clip_project_position(c, tmp);
121
   brw_MOV(p, deref_4f(vert_addr, ndc_offset), tmp);
122
 
123
   release_tmp(c, tmp);
124
}
125
 
126
 
127
 
128
 
129
/* Interpolate between two vertices and put the result into a0.0.
130
 * Increment a0.0 accordingly.
131
 */
132
void brw_clip_interp_vertex( struct brw_clip_compile *c,
133
			     struct brw_indirect dest_ptr,
134
			     struct brw_indirect v0_ptr, /* from */
135
			     struct brw_indirect v1_ptr, /* to */
136
			     struct brw_reg t0,
137
			     bool force_edgeflag)
138
{
139
   struct brw_compile *p = &c->func;
140
   struct brw_reg tmp = get_tmp(c);
141
   GLuint slot;
142
 
143
   /* Just copy the vertex header:
144
    */
145
   /*
146
    * After CLIP stage, only first 256 bits of the VUE are read
147
    * back on Ironlake, so needn't change it
148
    */
149
   brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);
150
 
151
   /* Iterate over each attribute (could be done in pairs?)
152
    */
153
   for (slot = 0; slot < c->vue_map.num_slots; slot++) {
154
      int varying = c->vue_map.slot_to_varying[slot];
155
      GLuint delta = brw_vue_slot_to_offset(slot);
156
 
157
      if (varying == VARYING_SLOT_EDGE) {
158
	 if (force_edgeflag)
159
	    brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));
160
	 else
161
	    brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta));
162
      } else if (varying == VARYING_SLOT_PSIZ ||
163
                 varying == VARYING_SLOT_CLIP_DIST0 ||
164
                 varying == VARYING_SLOT_CLIP_DIST1) {
165
	 /* PSIZ doesn't need interpolation because it isn't used by the
166
          * fragment shader.  CLIP_DIST0 and CLIP_DIST1 don't need
167
          * intepolation because on pre-GEN6, these are just placeholder VUE
168
          * slots that don't perform any action.
169
          */
170
      } else if (varying < VARYING_SLOT_MAX) {
171
	 /* This is a true vertex result (and not a special value for the VUE
172
	  * header), so interpolate:
173
	  *
174
	  *        New = attr0 + t*attr1 - t*attr0
175
	  */
176
	 brw_MUL(p,
177
		 vec4(brw_null_reg()),
178
		 deref_4f(v1_ptr, delta),
179
		 t0);
180
 
181
	 brw_MAC(p,
182
		 tmp,
183
		 negate(deref_4f(v0_ptr, delta)),
184
		 t0);
185
 
186
	 brw_ADD(p,
187
		 deref_4f(dest_ptr, delta),
188
		 deref_4f(v0_ptr, delta),
189
		 tmp);
190
      }
191
   }
192
 
193
   if (c->vue_map.num_slots % 2) {
194
      GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);
195
 
196
      brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));
197
   }
198
 
199
   release_tmp(c, tmp);
200
 
201
   /* Recreate the projected (NDC) coordinate in the new vertex
202
    * header:
203
    */
204
   brw_clip_project_vertex(c, dest_ptr );
205
}
206
 
207
void brw_clip_emit_vue(struct brw_clip_compile *c,
208
		       struct brw_indirect vert,
209
		       bool allocate,
210
		       bool eot,
211
		       GLuint header)
212
{
213
   struct brw_compile *p = &c->func;
214
 
215
   brw_clip_ff_sync(c);
216
 
217
   assert(!(allocate && eot));
218
 
219
   /* Copy the vertex from vertn into m1..mN+1:
220
    */
221
   brw_copy_from_indirect(p, brw_message_reg(1), vert, c->nr_regs);
222
 
223
   /* Overwrite PrimType and PrimStart in the message header, for
224
    * each vertex in turn:
225
    */
226
   brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header));
227
 
228
 
229
   /* Send each vertex as a seperate write to the urb.  This
230
    * is different to the concept in brw_sf_emit.c, where
231
    * subsequent writes are used to build up a single urb
232
    * entry.  Each of these writes instantiates a seperate
233
    * urb entry - (I think... what about 'allocate'?)
234
    */
235
   brw_urb_WRITE(p,
236
		 allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
237
		 0,
238
		 c->reg.R0,
239
		 allocate,
240
		 1,		/* used */
241
		 c->nr_regs + 1, /* msg length */
242
		 allocate ? 1 : 0, /* response_length */
243
		 eot,		/* eot */
244
		 1,		/* writes_complete */
245
		 0,		/* urb offset */
246
		 BRW_URB_SWIZZLE_NONE);
247
}
248
 
249
 
250
 
251
void brw_clip_kill_thread(struct brw_clip_compile *c)
252
{
253
   struct brw_compile *p = &c->func;
254
 
255
   brw_clip_ff_sync(c);
256
   /* Send an empty message to kill the thread and release any
257
    * allocated urb entry:
258
    */
259
   brw_urb_WRITE(p,
260
		 retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
261
		 0,
262
		 c->reg.R0,
263
		 0,		/* allocate */
264
		 0,		/* used */
265
		 1, 		/* msg len */
266
		 0, 		/* response len */
267
		 1, 		/* eot */
268
		 1,		/* writes complete */
269
		 0,
270
		 BRW_URB_SWIZZLE_NONE);
271
}
272
 
273
 
274
 
275
 
276
struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c )
277
{
278
   return brw_address(c->reg.fixed_planes);
279
}
280
 
281
 
282
struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c )
283
{
284
   if (c->key.nr_userclip) {
285
      return brw_imm_uw(16);
286
   }
287
   else {
288
      return brw_imm_uw(4);
289
   }
290
}
291
 
292
 
293
/* If flatshading, distribute color from provoking vertex prior to
294
 * clipping.
295
 */
296
void brw_clip_copy_colors( struct brw_clip_compile *c,
297
			   GLuint to, GLuint from )
298
{
299
   struct brw_compile *p = &c->func;
300
 
301
   if (brw_clip_have_varying(c, VARYING_SLOT_COL0))
302
      brw_MOV(p,
303
	      byte_offset(c->reg.vertex[to],
304
                          brw_varying_to_offset(&c->vue_map,
305
                                                VARYING_SLOT_COL0)),
306
	      byte_offset(c->reg.vertex[from],
307
                          brw_varying_to_offset(&c->vue_map,
308
                                                VARYING_SLOT_COL0)));
309
 
310
   if (brw_clip_have_varying(c, VARYING_SLOT_COL1))
311
      brw_MOV(p,
312
	      byte_offset(c->reg.vertex[to],
313
                          brw_varying_to_offset(&c->vue_map,
314
                                                VARYING_SLOT_COL1)),
315
	      byte_offset(c->reg.vertex[from],
316
                          brw_varying_to_offset(&c->vue_map,
317
                                                VARYING_SLOT_COL1)));
318
 
319
   if (brw_clip_have_varying(c, VARYING_SLOT_BFC0))
320
      brw_MOV(p,
321
	      byte_offset(c->reg.vertex[to],
322
                          brw_varying_to_offset(&c->vue_map,
323
                                                VARYING_SLOT_BFC0)),
324
	      byte_offset(c->reg.vertex[from],
325
                          brw_varying_to_offset(&c->vue_map,
326
                                                VARYING_SLOT_BFC0)));
327
 
328
   if (brw_clip_have_varying(c, VARYING_SLOT_BFC1))
329
      brw_MOV(p,
330
	      byte_offset(c->reg.vertex[to],
331
                          brw_varying_to_offset(&c->vue_map,
332
                                                VARYING_SLOT_BFC1)),
333
	      byte_offset(c->reg.vertex[from],
334
                          brw_varying_to_offset(&c->vue_map,
335
                                                VARYING_SLOT_BFC1)));
336
}
337
 
338
 
339
 
340
void brw_clip_init_clipmask( struct brw_clip_compile *c )
341
{
342
   struct brw_compile *p = &c->func;
343
   struct brw_reg incoming = get_element_ud(c->reg.R0, 2);
344
 
345
   /* Shift so that lowest outcode bit is rightmost:
346
    */
347
   brw_SHR(p, c->reg.planemask, incoming, brw_imm_ud(26));
348
 
349
   if (c->key.nr_userclip) {
350
      struct brw_reg tmp = retype(vec1(get_tmp(c)), BRW_REGISTER_TYPE_UD);
351
 
352
      /* Rearrange userclip outcodes so that they come directly after
353
       * the fixed plane bits.
354
       */
355
      brw_AND(p, tmp, incoming, brw_imm_ud(0x3f<<14));
356
      brw_SHR(p, tmp, tmp, brw_imm_ud(8));
357
      brw_OR(p, c->reg.planemask, c->reg.planemask, tmp);
358
 
359
      release_tmp(c, tmp);
360
   }
361
}
362
 
363
void brw_clip_ff_sync(struct brw_clip_compile *c)
364
{
365
    struct brw_compile *p = &c->func;
366
    struct brw_context *brw = p->brw;
367
 
368
    if (brw->gen == 5) {
369
        brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
370
        brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1));
371
        brw_IF(p, BRW_EXECUTE_1);
372
        {
373
            brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1));
374
            brw_ff_sync(p,
375
			c->reg.R0,
376
			0,
377
			c->reg.R0,
378
			1, /* allocate */
379
			1, /* response length */
380
 
381
        }
382
        brw_ENDIF(p);
383
        brw_set_predicate_control(p, BRW_PREDICATE_NONE);
384
    }
385
}
386
 
387
void brw_clip_init_ff_sync(struct brw_clip_compile *c)
388
{
389
    struct brw_context *brw = c->func.brw;
390
 
391
    if (brw->gen == 5) {
392
	struct brw_compile *p = &c->func;
393
 
394
        brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0));
395
    }
396
}