1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
36 #include "tnl/t_context.h"
37 #include "tnl/t_vertex.h"
39 #include "intel_batchbuffer.h"
42 #include "i915_context.h"
44 static void i915_render_start( intelContextPtr intel
)
46 GLcontext
*ctx
= &intel
->ctx
;
47 i915ContextPtr i915
= I915_CONTEXT(intel
);
49 if (ctx
->FragmentProgram
._Active
)
50 i915ValidateFragmentProgram( i915
);
52 assert(!ctx
->_MaintainTexEnvProgram
);
53 i915ValidateTextureProgram( i915
);
58 static void i915_reduced_primitive_state( intelContextPtr intel
,
61 i915ContextPtr i915
= I915_CONTEXT(intel
);
62 GLuint st1
= i915
->state
.Stipple
[I915_STPREG_ST1
];
68 if (intel
->ctx
.Polygon
.StippleFlag
&&
78 i915
->intel
.reduced_primitive
= rprim
;
80 if (st1
!= i915
->state
.Stipple
[I915_STPREG_ST1
]) {
81 I915_STATECHANGE(i915
, I915_UPLOAD_STIPPLE
);
82 i915
->state
.Stipple
[I915_STPREG_ST1
] = st1
;
87 /* Pull apart the vertex format registers and figure out how large a
88 * vertex is supposed to be.
90 static GLboolean
i915_check_vertex_size( intelContextPtr intel
,
93 i915ContextPtr i915
= I915_CONTEXT(intel
);
94 int lis2
= i915
->current
->Ctx
[I915_CTXREG_LIS2
];
95 int lis4
= i915
->current
->Ctx
[I915_CTXREG_LIS4
];
98 switch (lis4
& S4_VFMT_XYZW_MASK
) {
99 case S4_VFMT_XY
: sz
= 2; break;
100 case S4_VFMT_XYZ
: sz
= 3; break;
101 case S4_VFMT_XYW
: sz
= 3; break;
102 case S4_VFMT_XYZW
: sz
= 4; break;
104 fprintf(stderr
, "no xyzw specified\n");
108 if (lis4
& S4_VFMT_SPEC_FOG
) sz
++;
109 if (lis4
& S4_VFMT_COLOR
) sz
++;
110 if (lis4
& S4_VFMT_DEPTH_OFFSET
) sz
++;
111 if (lis4
& S4_VFMT_POINT_WIDTH
) sz
++;
112 if (lis4
& S4_VFMT_FOG_PARAM
) sz
++;
114 for (i
= 0 ; i
< 8 ; i
++) {
115 switch (lis2
& S2_TEXCOORD_FMT0_MASK
) {
116 case TEXCOORDFMT_2D
: sz
+= 2; break;
117 case TEXCOORDFMT_3D
: sz
+= 3; break;
118 case TEXCOORDFMT_4D
: sz
+= 4; break;
119 case TEXCOORDFMT_1D
: sz
+= 1; break;
120 case TEXCOORDFMT_2D_16
: sz
+= 1; break;
121 case TEXCOORDFMT_4D_16
: sz
+= 2; break;
122 case TEXCOORDFMT_NOT_PRESENT
: break;
124 fprintf(stderr
, "bad texcoord fmt %d\n", i
);
127 lis2
>>= S2_TEXCOORD_FMT1_SHIFT
;
131 fprintf(stderr
, "vertex size mismatch %d/%d\n", sz
, expected
);
133 return sz
== expected
;
137 static void i915_emit_invarient_state( intelContextPtr intel
)
143 OUT_BATCH(_3DSTATE_AA_CMD
|
144 AA_LINE_ECAAR_WIDTH_ENABLE
|
145 AA_LINE_ECAAR_WIDTH_1_0
|
146 AA_LINE_REGION_WIDTH_ENABLE
|
147 AA_LINE_REGION_WIDTH_1_0
);
149 OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD
);
152 OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD
);
155 OUT_BATCH(_3DSTATE_DFLT_Z_CMD
);
158 /* Don't support texture crossbar yet */
159 OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS
|
169 OUT_BATCH(_3DSTATE_RASTER_RULES_CMD
|
170 ENABLE_POINT_RASTER_RULE
|
171 OGL_POINT_RASTER_RULE
|
172 ENABLE_LINE_STRIP_PROVOKE_VRTX
|
173 ENABLE_TRI_FAN_PROVOKE_VRTX
|
174 LINE_STRIP_PROVOKE_VRTX(1) |
175 TRI_FAN_PROVOKE_VRTX(2) |
176 ENABLE_TEXKILL_3D_4D
|
179 /* Need to initialize this to zero.
181 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1
|
187 OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD
|
188 DISABLE_SCISSOR_RECT
);
190 OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD
);
194 OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE
);
196 OUT_BATCH(_3DSTATE_LOAD_INDIRECT
| 0); /* disable indirect state */
200 /* Don't support twosided stencil yet */
201 OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS
|
202 BFO_ENABLE_STENCIL_TWO_SIDE
|
209 #define emit( intel, state, size ) \
212 BEGIN_BATCH( (size) / sizeof(GLuint)); \
213 for (k = 0 ; k < (size) / sizeof(GLuint) ; k++) \
214 OUT_BATCH((state)[k]); \
218 static GLuint
get_dirty( struct i915_hw_state
*state
)
222 /* Workaround the multitex hang - if one texture unit state is
223 * modified, emit all texture units.
225 dirty
= state
->active
& ~state
->emitted
;
226 if (dirty
& I915_UPLOAD_TEX_ALL
)
227 state
->emitted
&= ~I915_UPLOAD_TEX_ALL
;
228 dirty
= state
->active
& ~state
->emitted
;
234 static GLuint
get_state_size( struct i915_hw_state
*state
)
236 GLuint dirty
= get_dirty(state
);
240 if (dirty
& I915_UPLOAD_INVARIENT
)
241 sz
+= 20 * sizeof(int);
243 if (dirty
& I915_UPLOAD_CTX
)
244 sz
+= sizeof(state
->Ctx
);
246 if (dirty
& I915_UPLOAD_BUFFERS
)
247 sz
+= sizeof(state
->Buffer
);
249 if (dirty
& I915_UPLOAD_STIPPLE
)
250 sz
+= sizeof(state
->Stipple
);
252 if (dirty
& I915_UPLOAD_FOG
)
253 sz
+= sizeof(state
->Fog
);
255 if (dirty
& I915_UPLOAD_TEX_ALL
) {
257 for (i
= 0; i
< I915_TEX_UNITS
; i
++)
258 if (dirty
& I915_UPLOAD_TEX(i
))
261 sz
+= (2+nr
*3) * sizeof(GLuint
) * 2;
264 if (dirty
& I915_UPLOAD_CONSTANTS
)
265 sz
+= state
->ConstantSize
* sizeof(GLuint
);
267 if (dirty
& I915_UPLOAD_PROGRAM
)
268 sz
+= state
->ProgramSize
* sizeof(GLuint
);
274 /* Push the state into the sarea and/or texture memory.
276 static void i915_emit_state( intelContextPtr intel
)
278 i915ContextPtr i915
= I915_CONTEXT(intel
);
279 struct i915_hw_state
*state
= i915
->current
;
281 GLuint dirty
= get_dirty(state
);
282 GLuint counter
= intel
->batch
.counter
;
285 if (intel
->batch
.space
< get_state_size(state
)) {
286 intelFlushBatch(intel
, GL_TRUE
);
287 dirty
= get_dirty(state
);
288 counter
= intel
->batch
.counter
;
292 fprintf(stderr
, "%s dirty: %x\n", __FUNCTION__
, dirty
);
294 if (dirty
& I915_UPLOAD_INVARIENT
) {
295 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_INVARIENT:\n");
296 i915_emit_invarient_state( intel
);
299 if (dirty
& I915_UPLOAD_CTX
) {
300 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_CTX:\n");
301 emit( i915
, state
->Ctx
, sizeof(state
->Ctx
) );
304 if (dirty
& I915_UPLOAD_BUFFERS
) {
305 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_BUFFERS:\n");
306 emit( i915
, state
->Buffer
, sizeof(state
->Buffer
) );
309 if (dirty
& I915_UPLOAD_STIPPLE
) {
310 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_STIPPLE:\n");
311 emit( i915
, state
->Stipple
, sizeof(state
->Stipple
) );
314 if (dirty
& I915_UPLOAD_FOG
) {
315 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_FOG:\n");
316 emit( i915
, state
->Fog
, sizeof(state
->Fog
) );
319 /* Combine all the dirty texture state into a single command to
320 * avoid lockups on I915 hardware.
322 if (dirty
& I915_UPLOAD_TEX_ALL
) {
325 for (i
= 0; i
< I915_TEX_UNITS
; i
++)
326 if (dirty
& I915_UPLOAD_TEX(i
))
330 OUT_BATCH(_3DSTATE_MAP_STATE
| (3*nr
));
331 OUT_BATCH((dirty
& I915_UPLOAD_TEX_ALL
) >> I915_UPLOAD_TEX_0_SHIFT
);
332 for (i
= 0 ; i
< I915_TEX_UNITS
; i
++)
333 if (dirty
& I915_UPLOAD_TEX(i
)) {
334 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_MS2
]);
335 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_MS3
]);
336 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_MS4
]);
341 OUT_BATCH(_3DSTATE_SAMPLER_STATE
| (3*nr
));
342 OUT_BATCH((dirty
& I915_UPLOAD_TEX_ALL
) >> I915_UPLOAD_TEX_0_SHIFT
);
343 for (i
= 0 ; i
< I915_TEX_UNITS
; i
++)
344 if (dirty
& I915_UPLOAD_TEX(i
)) {
345 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_SS2
]);
346 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_SS3
]);
347 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_SS4
]);
352 if (dirty
& I915_UPLOAD_CONSTANTS
) {
353 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_CONSTANTS:\n");
354 emit( i915
, state
->Constant
, state
->ConstantSize
* sizeof(GLuint
) );
357 if (dirty
& I915_UPLOAD_PROGRAM
) {
358 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_PROGRAM:\n");
360 assert((state
->Program
[0] & 0x1ff)+2 == state
->ProgramSize
);
362 emit( i915
, state
->Program
, state
->ProgramSize
* sizeof(GLuint
) );
364 i915_disassemble_program( state
->Program
, state
->ProgramSize
);
367 state
->emitted
|= dirty
;
368 intel
->batch
.last_emit_state
= counter
;
369 assert(counter
== intel
->batch
.counter
);
372 static void i915_destroy_context( intelContextPtr intel
)
374 _tnl_free_vertices(&intel
->ctx
);
379 * Set the color buffer drawing region.
382 i915_set_color_region( intelContextPtr intel
, const intelRegion
*region
)
384 i915ContextPtr i915
= I915_CONTEXT(intel
);
385 I915_STATECHANGE( i915
, I915_UPLOAD_BUFFERS
);
386 i915
->state
.Buffer
[I915_DESTREG_CBUFADDR1
] =
387 (BUF_3D_ID_COLOR_BACK
| BUF_3D_PITCH(region
->pitch
) | BUF_3D_USE_FENCE
);
388 i915
->state
.Buffer
[I915_DESTREG_CBUFADDR2
] = region
->offset
;
393 * specify the z-buffer/stencil region
396 i915_set_z_region( intelContextPtr intel
, const intelRegion
*region
)
398 i915ContextPtr i915
= I915_CONTEXT(intel
);
399 I915_STATECHANGE( i915
, I915_UPLOAD_BUFFERS
);
400 i915
->state
.Buffer
[I915_DESTREG_DBUFADDR1
] =
401 (BUF_3D_ID_DEPTH
| BUF_3D_PITCH(region
->pitch
) | BUF_3D_USE_FENCE
);
402 i915
->state
.Buffer
[I915_DESTREG_DBUFADDR2
] = region
->offset
;
407 * Set both the color and Z/stencil drawing regions.
408 * Similar to two previous functions, but don't use I915_STATECHANGE()
411 i915_update_color_z_regions(intelContextPtr intel
,
412 const intelRegion
*colorRegion
,
413 const intelRegion
*depthRegion
)
415 i915ContextPtr i915
= I915_CONTEXT(intel
);
417 i915
->state
.Buffer
[I915_DESTREG_CBUFADDR1
] =
418 (BUF_3D_ID_COLOR_BACK
| BUF_3D_PITCH(colorRegion
->pitch
) | BUF_3D_USE_FENCE
);
419 i915
->state
.Buffer
[I915_DESTREG_CBUFADDR2
] = colorRegion
->offset
;
421 i915
->state
.Buffer
[I915_DESTREG_DBUFADDR1
] =
423 BUF_3D_PITCH(depthRegion
->pitch
) | /* pitch in bytes */
425 i915
->state
.Buffer
[I915_DESTREG_DBUFADDR2
] = depthRegion
->offset
;
429 static void i915_lost_hardware( intelContextPtr intel
)
431 I915_CONTEXT(intel
)->state
.emitted
= 0;
434 static void i915_emit_flush( intelContextPtr intel
)
439 OUT_BATCH( MI_FLUSH
| FLUSH_MAP_CACHE
| FLUSH_RENDER_CACHE
);
445 void i915InitVtbl( i915ContextPtr i915
)
447 i915
->intel
.vtbl
.alloc_tex_obj
= i915AllocTexObj
;
448 i915
->intel
.vtbl
.check_vertex_size
= i915_check_vertex_size
;
449 i915
->intel
.vtbl
.clear_with_tris
= i915ClearWithTris
;
450 i915
->intel
.vtbl
.rotate_window
= i915RotateWindow
;
451 i915
->intel
.vtbl
.destroy
= i915_destroy_context
;
452 i915
->intel
.vtbl
.emit_state
= i915_emit_state
;
453 i915
->intel
.vtbl
.lost_hardware
= i915_lost_hardware
;
454 i915
->intel
.vtbl
.reduced_primitive_state
= i915_reduced_primitive_state
;
455 i915
->intel
.vtbl
.render_start
= i915_render_start
;
456 i915
->intel
.vtbl
.set_color_region
= i915_set_color_region
;
457 i915
->intel
.vtbl
.set_z_region
= i915_set_z_region
;
458 i915
->intel
.vtbl
.update_color_z_regions
= i915_update_color_z_regions
;
459 i915
->intel
.vtbl
.update_texture_state
= i915UpdateTextureState
;
460 i915
->intel
.vtbl
.emit_flush
= i915_emit_flush
;