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
 
29
#include "i915_reg.h"
30
#include "i915_context.h"
31
#include "i915_batch.h"
32
#include "i915_debug.h"
33
#include "i915_fpc.h"
34
#include "i915_resource.h"
35
 
36
#include "pipe/p_context.h"
37
#include "pipe/p_defines.h"
38
#include "pipe/p_format.h"
39
 
40
#include "util/u_format.h"
41
#include "util/u_math.h"
42
#include "util/u_memory.h"
43
 
44
struct i915_tracked_hw_state {
45
   const char *name;
46
   void (*validate)(struct i915_context *, unsigned *batch_space);
47
   void (*emit)(struct i915_context *);
48
   unsigned dirty, batch_space;
49
};
50
 
51
 
52
static void
53
validate_flush(struct i915_context *i915, unsigned *batch_space)
54
{
55
   *batch_space = i915->flush_dirty ? 1 : 0;
56
}
57
 
58
static void
59
emit_flush(struct i915_context *i915)
60
{
61
   /* Cache handling is very cheap atm. State handling can request to flushes:
62
    * - I915_FLUSH_CACHE which is a flush everything request and
63
    * - I915_PIPELINE_FLUSH which is specifically for the draw_offset flush.
64
    * Because the cache handling is so dumb, no explicit "invalidate map cache".
65
    * Also, the first is a strict superset of the latter, so the following logic
66
    * works. */
67
   if (i915->flush_dirty & I915_FLUSH_CACHE)
68
      OUT_BATCH(MI_FLUSH | FLUSH_MAP_CACHE);
69
   else if (i915->flush_dirty & I915_PIPELINE_FLUSH)
70
      OUT_BATCH(MI_FLUSH | INHIBIT_FLUSH_RENDER_CACHE);
71
}
72
 
73
uint32_t invariant_state[] = {
74
   _3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 |
75
             AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0,
76
 
77
   _3DSTATE_DFLT_DIFFUSE_CMD, 0,
78
 
79
   _3DSTATE_DFLT_SPEC_CMD, 0,
80
 
81
   _3DSTATE_DFLT_Z_CMD, 0,
82
 
83
   _3DSTATE_COORD_SET_BINDINGS |
84
             CSB_TCB(0, 0) |
85
             CSB_TCB(1, 1) |
86
             CSB_TCB(2, 2) |
87
             CSB_TCB(3, 3) |
88
             CSB_TCB(4, 4) |
89
             CSB_TCB(5, 5) |
90
             CSB_TCB(6, 6) |
91
             CSB_TCB(7, 7),
92
 
93
   _3DSTATE_RASTER_RULES_CMD |
94
             ENABLE_POINT_RASTER_RULE |
95
             OGL_POINT_RASTER_RULE |
96
             ENABLE_LINE_STRIP_PROVOKE_VRTX |
97
             ENABLE_TRI_FAN_PROVOKE_VRTX |
98
             LINE_STRIP_PROVOKE_VRTX(1) |
99
             TRI_FAN_PROVOKE_VRTX(2) |
100
             ENABLE_TEXKILL_3D_4D |
101
             TEXKILL_4D,
102
 
103
   _3DSTATE_DEPTH_SUBRECT_DISABLE,
104
 
105
   /* disable indirect state for now
106
    */
107
   _3DSTATE_LOAD_INDIRECT | 0, 0};
108
 
109
static void
110
emit_invariant(struct i915_context *i915)
111
{
112
   i915_winsys_batchbuffer_write(i915->batch, invariant_state,
113
                                 Elements(invariant_state)*sizeof(uint32_t));
114
}
115
 
116
static void
117
validate_immediate(struct i915_context *i915, unsigned *batch_space)
118
{
119
   unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 |
120
                     1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
121
                     1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
122
                     1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) &
123
                    i915->immediate_dirty;
124
 
125
   if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0) && i915->vbo)
126
      i915->validation_buffers[i915->num_validation_buffers++] = i915->vbo;
127
 
128
   *batch_space = 1 + util_bitcount(dirty);
129
}
130
 
131
static void
132
emit_immediate(struct i915_context *i915)
133
{
134
   /* remove unwanted bits and S7 */
135
   unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 |
136
                     1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
137
                     1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
138
                     1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) &
139
                    i915->immediate_dirty;
140
   int i, num = util_bitcount(dirty);
141
   assert(num && num <= I915_MAX_IMMEDIATE);
142
 
143
   OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
144
             dirty << 4 | (num - 1));
145
 
146
   if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0)) {
147
      if (i915->vbo)
148
         OUT_RELOC(i915->vbo, I915_USAGE_VERTEX,
149
                   i915->current.immediate[I915_IMMEDIATE_S0]);
150
      else
151
         OUT_BATCH(0);
152
   }
153
 
154
   for (i = 1; i < I915_MAX_IMMEDIATE; i++) {
155
      if (dirty & (1 << i)) {
156
         /* Fixup blend function for A8 dst buffers.
157
          * When we blend to an A8 buffer, the GPU thinks it's a G8 buffer,
158
          * and therefore we need to use the color factor for alphas. */
159
         if ((i == I915_IMMEDIATE_S6) &&
160
             (i915->current.target_fixup_format == PIPE_FORMAT_A8_UNORM)) {
161
            uint32_t imm = i915->current.immediate[i];
162
            uint32_t srcRGB = (imm >> S6_CBUF_SRC_BLEND_FACT_SHIFT) & BLENDFACT_MASK;
163
            if (srcRGB == BLENDFACT_DST_ALPHA)
164
               srcRGB = BLENDFACT_DST_COLR;
165
            else if (srcRGB == BLENDFACT_INV_DST_ALPHA)
166
               srcRGB = BLENDFACT_INV_DST_COLR;
167
            imm &= ~SRC_BLND_FACT(BLENDFACT_MASK);
168
            imm |= SRC_BLND_FACT(srcRGB);
169
            OUT_BATCH(imm);
170
         } else {
171
            OUT_BATCH(i915->current.immediate[i]);
172
         }
173
      }
174
   }
175
}
176
 
177
static void
178
validate_dynamic(struct i915_context *i915, unsigned *batch_space)
179
{
180
   *batch_space = util_bitcount(i915->dynamic_dirty & ((1 << I915_MAX_DYNAMIC) - 1));
181
}
182
 
183
static void
184
emit_dynamic(struct i915_context *i915)
185
{
186
   int i;
187
   for (i = 0; i < I915_MAX_DYNAMIC; i++) {
188
      if (i915->dynamic_dirty & (1 << i))
189
         OUT_BATCH(i915->current.dynamic[i]);
190
   }
191
}
192
 
193
static void
194
validate_static(struct i915_context *i915, unsigned *batch_space)
195
{
196
   *batch_space = 0;
197
 
198
   if (i915->current.cbuf_bo && (i915->static_dirty & I915_DST_BUF_COLOR)) {
199
      i915->validation_buffers[i915->num_validation_buffers++]
200
         = i915->current.cbuf_bo;
201
      *batch_space += 3;
202
   }
203
 
204
   if (i915->current.depth_bo && (i915->static_dirty & I915_DST_BUF_DEPTH)) {
205
      i915->validation_buffers[i915->num_validation_buffers++]
206
         = i915->current.depth_bo;
207
      *batch_space += 3;
208
   }
209
 
210
   if (i915->static_dirty & I915_DST_VARS)
211
      *batch_space += 2;
212
 
213
   if (i915->static_dirty & I915_DST_RECT)
214
      *batch_space += 5;
215
}
216
 
217
static void
218
emit_static(struct i915_context *i915)
219
{
220
   if (i915->current.cbuf_bo && (i915->static_dirty & I915_DST_BUF_COLOR)) {
221
      OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
222
      OUT_BATCH(i915->current.cbuf_flags);
223
      OUT_RELOC(i915->current.cbuf_bo,
224
                I915_USAGE_RENDER,
225
                0);
226
   }
227
 
228
   /* What happens if no zbuf??
229
    */
230
   if (i915->current.depth_bo && (i915->static_dirty & I915_DST_BUF_DEPTH)) {
231
      OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
232
      OUT_BATCH(i915->current.depth_flags);
233
      OUT_RELOC(i915->current.depth_bo,
234
                I915_USAGE_RENDER,
235
                0);
236
   }
237
 
238
   if (i915->static_dirty & I915_DST_VARS) {
239
      OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
240
      OUT_BATCH(i915->current.dst_buf_vars);
241
   }
242
}
243
 
244
static void
245
validate_map(struct i915_context *i915, unsigned *batch_space)
246
{
247
   const uint enabled = i915->current.sampler_enable_flags;
248
   uint unit;
249
   struct i915_texture *tex;
250
 
251
   *batch_space = i915->current.sampler_enable_nr ?
252
     2 + 3*i915->current.sampler_enable_nr : 0;
253
 
254
   for (unit = 0; unit < I915_TEX_UNITS; unit++) {
255
      if (enabled & (1 << unit)) {
256
         tex = i915_texture(i915->fragment_sampler_views[unit]->texture);
257
         i915->validation_buffers[i915->num_validation_buffers++] = tex->buffer;
258
      }
259
   }
260
}
261
 
262
static void
263
emit_map(struct i915_context *i915)
264
{
265
   const uint nr = i915->current.sampler_enable_nr;
266
   if (nr) {
267
      const uint enabled = i915->current.sampler_enable_flags;
268
      uint unit;
269
      uint count = 0;
270
      OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr));
271
      OUT_BATCH(enabled);
272
      for (unit = 0; unit < I915_TEX_UNITS; unit++) {
273
         if (enabled & (1 << unit)) {
274
            struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture);
275
            struct i915_winsys_buffer *buf = texture->buffer;
276
            assert(buf);
277
 
278
            count++;
279
 
280
            OUT_RELOC(buf, I915_USAGE_SAMPLER, 0);
281
            OUT_BATCH(i915->current.texbuffer[unit][0]); /* MS3 */
282
            OUT_BATCH(i915->current.texbuffer[unit][1]); /* MS4 */
283
         }
284
      }
285
      assert(count == nr);
286
   }
287
}
288
 
289
static void
290
validate_sampler(struct i915_context *i915, unsigned *batch_space)
291
{
292
   *batch_space = i915->current.sampler_enable_nr ?
293
     2 + 3*i915->current.sampler_enable_nr : 0;
294
}
295
 
296
static void
297
emit_sampler(struct i915_context *i915)
298
{
299
   if (i915->current.sampler_enable_nr) {
300
      int i;
301
 
302
      OUT_BATCH( _3DSTATE_SAMPLER_STATE |
303
                 (3 * i915->current.sampler_enable_nr) );
304
 
305
      OUT_BATCH( i915->current.sampler_enable_flags );
306
 
307
      for (i = 0; i < I915_TEX_UNITS; i++) {
308
         if (i915->current.sampler_enable_flags & (1<
309
            OUT_BATCH( i915->current.sampler[i][0] );
310
            OUT_BATCH( i915->current.sampler[i][1] );
311
            OUT_BATCH( i915->current.sampler[i][2] );
312
         }
313
      }
314
   }
315
}
316
 
317
static void
318
validate_constants(struct i915_context *i915, unsigned *batch_space)
319
{
320
   int nr = i915->fs->num_constants ?
321
      2 + 4*i915->fs->num_constants : 0;
322
 
323
   *batch_space = nr;
324
}
325
 
326
static void
327
emit_constants(struct i915_context *i915)
328
{
329
   /* Collate the user-defined constants with the fragment shader's
330
    * immediates according to the constant_flags[] array.
331
    */
332
   const uint nr = i915->fs->num_constants;
333
 
334
   assert(nr < I915_MAX_CONSTANT);
335
   if (nr) {
336
      uint i;
337
 
338
      OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) );
339
      OUT_BATCH((1 << nr) - 1);
340
 
341
      for (i = 0; i < nr; i++) {
342
         const uint *c;
343
         if (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER) {
344
            /* grab user-defined constant */
345
            c = (uint *) i915_buffer(i915->constants[PIPE_SHADER_FRAGMENT])->data;
346
            c += 4 * i;
347
         }
348
         else {
349
            /* emit program constant */
350
            c = (uint *) i915->fs->constants[i];
351
         }
352
#if 0 /* debug */
353
         {
354
            float *f = (float *) c;
355
            printf("Const %2d: %f %f %f %f %s\n", i, f[0], f[1], f[2], f[3],
356
                   (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER
357
                    ? "user" : "immediate"));
358
         }
359
#endif
360
         OUT_BATCH(*c++);
361
         OUT_BATCH(*c++);
362
         OUT_BATCH(*c++);
363
         OUT_BATCH(*c++);
364
      }
365
   }
366
}
367
 
368
static void
369
validate_program(struct i915_context *i915, unsigned *batch_space)
370
{
371
   uint additional_size = 0;
372
 
373
   additional_size += i915->current.target_fixup_format ? 3 : 0;
374
 
375
   /* we need more batch space if we want to emulate rgba framebuffers */
376
   *batch_space = i915->fs->decl_len + i915->fs->program_len + additional_size;
377
}
378
 
379
static void
380
emit_program(struct i915_context *i915)
381
{
382
   uint additional_size = 0;
383
   uint i;
384
 
385
   /* count how much additional space we'll need */
386
   validate_program(i915, &additional_size);
387
   additional_size -= i915->fs->decl_len + i915->fs->program_len;
388
 
389
   /* we should always have, at least, a pass-through program */
390
   assert(i915->fs->program_len > 0);
391
 
392
   /* output the declarations */
393
   {
394
      /* first word has the size, we have to adjust that */
395
      uint size = (i915->fs->decl[0]);
396
      size += additional_size;
397
      OUT_BATCH(size);
398
   }
399
 
400
   for (i = 1 ; i < i915->fs->decl_len; i++)
401
      OUT_BATCH(i915->fs->decl[i]);
402
 
403
   /* output the program */
404
   assert(i915->fs->program_len % 3 == 0);
405
   for (i = 0 ; i < i915->fs->program_len; i+=3) {
406
      OUT_BATCH(i915->fs->program[i]);
407
      OUT_BATCH(i915->fs->program[i+1]);
408
      OUT_BATCH(i915->fs->program[i+2]);
409
   }
410
 
411
   /* we emit an additional mov with swizzle to fake RGBA framebuffers */
412
   if (i915->current.target_fixup_format) {
413
      /* mov out_color, out_color.zyxw */
414
      OUT_BATCH(A0_MOV |
415
                (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
416
                A0_DEST_CHANNEL_ALL |
417
                (REG_TYPE_OC << A0_SRC0_TYPE_SHIFT) |
418
                (T_DIFFUSE << A0_SRC0_NR_SHIFT));
419
      OUT_BATCH(i915->current.fixup_swizzle);
420
      OUT_BATCH(0);
421
   }
422
}
423
 
424
static void
425
emit_draw_rect(struct i915_context *i915)
426
{
427
   if (i915->static_dirty & I915_DST_RECT) {
428
      OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
429
      OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS);
430
      OUT_BATCH(i915->current.draw_offset);
431
      OUT_BATCH(i915->current.draw_size);
432
      OUT_BATCH(i915->current.draw_offset);
433
   }
434
}
435
 
436
static boolean
437
i915_validate_state(struct i915_context *i915, unsigned *batch_space)
438
{
439
   unsigned tmp;
440
 
441
   i915->num_validation_buffers = 0;
442
   if (i915->hardware_dirty & I915_HW_INVARIANT)
443
      *batch_space = Elements(invariant_state);
444
   else
445
      *batch_space = 0;
446
 
447
#if 0
448
static int counter_total = 0;
449
#define VALIDATE_ATOM(atom, hw_dirty) \
450
   if (i915->hardware_dirty & hw_dirty) { \
451
      static int counter_##atom = 0;\
452
      validate_##atom(i915, &tmp); \
453
      *batch_space += tmp;\
454
      counter_##atom += tmp;\
455
      counter_total += tmp;\
456
      printf("%s: \t%d/%d \t%2.2f\n",#atom, counter_##atom, counter_total, counter_##atom*100.f/counter_total);}
457
#else
458
#define VALIDATE_ATOM(atom, hw_dirty) \
459
   if (i915->hardware_dirty & hw_dirty) { \
460
      validate_##atom(i915, &tmp); \
461
      *batch_space += tmp; }
462
#endif
463
   VALIDATE_ATOM(flush, I915_HW_FLUSH);
464
   VALIDATE_ATOM(immediate, I915_HW_IMMEDIATE);
465
   VALIDATE_ATOM(dynamic, I915_HW_DYNAMIC);
466
   VALIDATE_ATOM(static, I915_HW_STATIC);
467
   VALIDATE_ATOM(map, I915_HW_MAP);
468
   VALIDATE_ATOM(sampler, I915_HW_SAMPLER);
469
   VALIDATE_ATOM(constants, I915_HW_CONSTANTS);
470
   VALIDATE_ATOM(program, I915_HW_PROGRAM);
471
#undef VALIDATE_ATOM
472
 
473
   if (i915->num_validation_buffers == 0)
474
      return TRUE;
475
 
476
   if (!i915_winsys_validate_buffers(i915->batch, i915->validation_buffers,
477
                                     i915->num_validation_buffers))
478
      return FALSE;
479
 
480
   return TRUE;
481
}
482
 
483
/* Push the state into the sarea and/or texture memory.
484
 */
485
void
486
i915_emit_hardware_state(struct i915_context *i915 )
487
{
488
   unsigned batch_space;
489
   uintptr_t save_ptr;
490
 
491
   assert(i915->dirty == 0);
492
 
493
   if (I915_DBG_ON(DBG_ATOMS))
494
      i915_dump_hardware_dirty(i915, __FUNCTION__);
495
 
496
   if (!i915_validate_state(i915, &batch_space)) {
497
      FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
498
      assert(i915_validate_state(i915, &batch_space));
499
   }
500
 
501
   if(!BEGIN_BATCH(batch_space)) {
502
      FLUSH_BATCH(NULL, I915_FLUSH_ASYNC);
503
      assert(i915_validate_state(i915, &batch_space));
504
      assert(BEGIN_BATCH(batch_space));
505
   }
506
 
507
   save_ptr = (uintptr_t)i915->batch->ptr;
508
 
509
#define EMIT_ATOM(atom, hw_dirty) \
510
   if (i915->hardware_dirty & hw_dirty) \
511
      emit_##atom(i915);
512
   EMIT_ATOM(flush, I915_HW_FLUSH);
513
   EMIT_ATOM(invariant, I915_HW_INVARIANT);
514
   EMIT_ATOM(immediate, I915_HW_IMMEDIATE);
515
   EMIT_ATOM(dynamic, I915_HW_DYNAMIC);
516
   EMIT_ATOM(static, I915_HW_STATIC);
517
   EMIT_ATOM(map, I915_HW_MAP);
518
   EMIT_ATOM(sampler, I915_HW_SAMPLER);
519
   EMIT_ATOM(constants, I915_HW_CONSTANTS);
520
   EMIT_ATOM(program, I915_HW_PROGRAM);
521
   EMIT_ATOM(draw_rect, I915_HW_STATIC);
522
#undef EMIT_ATOM
523
 
524
   I915_DBG(DBG_EMIT, "%s: used %d dwords, %d dwords reserved\n", __FUNCTION__,
525
            ((uintptr_t)i915->batch->ptr - save_ptr) / 4,
526
            batch_space);
527
   assert(((uintptr_t)i915->batch->ptr - save_ptr) / 4 == batch_space);
528
 
529
   i915->hardware_dirty = 0;
530
   i915->immediate_dirty = 0;
531
   i915->dynamic_dirty = 0;
532
   i915->static_dirty = 0;
533
   i915->flush_dirty = 0;
534
}