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 i915ValidateTextureProgram( i915
);
56 static void i915_reduced_primitive_state( intelContextPtr intel
,
59 i915ContextPtr i915
= I915_CONTEXT(intel
);
60 GLuint st1
= i915
->state
.Stipple
[I915_STPREG_ST1
];
66 if (intel
->ctx
.Polygon
.StippleFlag
&&
76 i915
->intel
.reduced_primitive
= rprim
;
78 if (st1
!= i915
->state
.Stipple
[I915_STPREG_ST1
]) {
79 I915_STATECHANGE(i915
, I915_UPLOAD_STIPPLE
);
80 i915
->state
.Stipple
[I915_STPREG_ST1
] = st1
;
85 /* Pull apart the vertex format registers and figure out how large a
86 * vertex is supposed to be.
88 static GLboolean
i915_check_vertex_size( intelContextPtr intel
,
91 i915ContextPtr i915
= I915_CONTEXT(intel
);
92 int lis2
= i915
->current
->Ctx
[I915_CTXREG_LIS2
];
93 int lis4
= i915
->current
->Ctx
[I915_CTXREG_LIS4
];
96 switch (lis4
& S4_VFMT_XYZW_MASK
) {
97 case S4_VFMT_XY
: sz
= 2; break;
98 case S4_VFMT_XYZ
: sz
= 3; break;
99 case S4_VFMT_XYW
: sz
= 3; break;
100 case S4_VFMT_XYZW
: sz
= 4; break;
102 fprintf(stderr
, "no xyzw specified\n");
106 if (lis4
& S4_VFMT_SPEC_FOG
) sz
++;
107 if (lis4
& S4_VFMT_COLOR
) sz
++;
108 if (lis4
& S4_VFMT_DEPTH_OFFSET
) sz
++;
109 if (lis4
& S4_VFMT_POINT_WIDTH
) sz
++;
110 if (lis4
& S4_VFMT_FOG_PARAM
) sz
++;
112 for (i
= 0 ; i
< 8 ; i
++) {
113 switch (lis2
& S2_TEXCOORD_FMT0_MASK
) {
114 case TEXCOORDFMT_2D
: sz
+= 2; break;
115 case TEXCOORDFMT_3D
: sz
+= 3; break;
116 case TEXCOORDFMT_4D
: sz
+= 4; break;
117 case TEXCOORDFMT_1D
: sz
+= 1; break;
118 case TEXCOORDFMT_2D_16
: sz
+= 1; break;
119 case TEXCOORDFMT_4D_16
: sz
+= 2; break;
120 case TEXCOORDFMT_NOT_PRESENT
: break;
122 fprintf(stderr
, "bad texcoord fmt %d\n", i
);
125 lis2
>>= S2_TEXCOORD_FMT1_SHIFT
;
129 fprintf(stderr
, "vertex size mismatch %d/%d\n", sz
, expected
);
131 return sz
== expected
;
135 static void i915_emit_invarient_state( intelContextPtr intel
)
141 OUT_BATCH(_3DSTATE_AA_CMD
|
142 AA_LINE_ECAAR_WIDTH_ENABLE
|
143 AA_LINE_ECAAR_WIDTH_1_0
|
144 AA_LINE_REGION_WIDTH_ENABLE
|
145 AA_LINE_REGION_WIDTH_1_0
);
147 OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD
);
150 OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD
);
153 OUT_BATCH(_3DSTATE_DFLT_Z_CMD
);
156 /* Don't support texture crossbar yet */
157 OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS
|
167 OUT_BATCH(_3DSTATE_RASTER_RULES_CMD
|
168 ENABLE_POINT_RASTER_RULE
|
169 OGL_POINT_RASTER_RULE
|
170 ENABLE_LINE_STRIP_PROVOKE_VRTX
|
171 ENABLE_TRI_FAN_PROVOKE_VRTX
|
172 LINE_STRIP_PROVOKE_VRTX(1) |
173 TRI_FAN_PROVOKE_VRTX(2) |
174 ENABLE_TEXKILL_3D_4D
|
177 /* Need to initialize this to zero.
179 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1
|
185 OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD
|
186 DISABLE_SCISSOR_RECT
);
188 OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD
);
192 OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE
);
194 OUT_BATCH(_3DSTATE_LOAD_INDIRECT
| 0); /* disable indirect state */
198 /* Don't support twosided stencil yet */
199 OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS
|
200 BFO_ENABLE_STENCIL_TWO_SIDE
|
207 #define emit( intel, state, size ) \
210 BEGIN_BATCH( (size) / sizeof(GLuint)); \
211 for (k = 0 ; k < (size) / sizeof(GLuint) ; k++) \
212 OUT_BATCH((state)[k]); \
216 static GLuint
get_dirty( struct i915_hw_state
*state
)
220 /* Workaround the multitex hang - if one texture unit state is
221 * modified, emit all texture units.
223 dirty
= state
->active
& ~state
->emitted
;
224 if (dirty
& I915_UPLOAD_TEX_ALL
)
225 state
->emitted
&= ~I915_UPLOAD_TEX_ALL
;
226 dirty
= state
->active
& ~state
->emitted
;
232 static GLuint
get_state_size( struct i915_hw_state
*state
)
234 GLuint dirty
= get_dirty(state
);
238 if (dirty
& I915_UPLOAD_CTX
)
239 sz
+= sizeof(state
->Ctx
);
241 if (dirty
& I915_UPLOAD_BUFFERS
)
242 sz
+= sizeof(state
->Buffer
);
244 if (dirty
& I915_UPLOAD_STIPPLE
)
245 sz
+= sizeof(state
->Stipple
);
247 if (dirty
& I915_UPLOAD_FOG
)
248 sz
+= sizeof(state
->Fog
);
250 if (dirty
& I915_UPLOAD_TEX_ALL
) {
252 for (i
= 0; i
< I915_TEX_UNITS
; i
++)
253 if (dirty
& I915_UPLOAD_TEX(i
))
256 sz
+= (2+nr
*3) * sizeof(GLuint
) * 2;
259 if (dirty
& I915_UPLOAD_CONSTANTS
)
260 sz
+= state
->ConstantSize
* sizeof(GLuint
);
262 if (dirty
& I915_UPLOAD_PROGRAM
)
263 sz
+= state
->ProgramSize
* sizeof(GLuint
);
269 /* Push the state into the sarea and/or texture memory.
271 static void i915_emit_state( intelContextPtr intel
)
273 i915ContextPtr i915
= I915_CONTEXT(intel
);
274 struct i915_hw_state
*state
= i915
->current
;
276 GLuint dirty
= get_dirty(state
);
277 GLuint counter
= intel
->batch
.counter
;
280 if (intel
->batch
.space
< get_state_size(state
)) {
281 intelFlushBatch(intel
, GL_TRUE
);
282 dirty
= get_dirty(state
);
283 counter
= intel
->batch
.counter
;
287 fprintf(stderr
, "%s dirty: %x\n", __FUNCTION__
, dirty
);
289 if (dirty
& I915_UPLOAD_CTX
) {
290 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_CTX:\n");
291 emit( i915
, state
->Ctx
, sizeof(state
->Ctx
) );
294 if (dirty
& I915_UPLOAD_BUFFERS
) {
295 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_BUFFERS:\n");
296 emit( i915
, state
->Buffer
, sizeof(state
->Buffer
) );
299 if (dirty
& I915_UPLOAD_STIPPLE
) {
300 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_STIPPLE:\n");
301 emit( i915
, state
->Stipple
, sizeof(state
->Stipple
) );
304 if (dirty
& I915_UPLOAD_FOG
) {
305 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_FOG:\n");
306 emit( i915
, state
->Fog
, sizeof(state
->Fog
) );
309 /* Combine all the dirty texture state into a single command to
310 * avoid lockups on I915 hardware.
312 if (dirty
& I915_UPLOAD_TEX_ALL
) {
315 for (i
= 0; i
< I915_TEX_UNITS
; i
++)
316 if (dirty
& I915_UPLOAD_TEX(i
))
320 OUT_BATCH(_3DSTATE_MAP_STATE
| (3*nr
));
321 OUT_BATCH((dirty
& I915_UPLOAD_TEX_ALL
) >> I915_UPLOAD_TEX_0_SHIFT
);
322 for (i
= 0 ; i
< I915_TEX_UNITS
; i
++)
323 if (dirty
& I915_UPLOAD_TEX(i
)) {
324 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_MS2
]);
325 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_MS3
]);
326 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_MS4
]);
331 OUT_BATCH(_3DSTATE_SAMPLER_STATE
| (3*nr
));
332 OUT_BATCH((dirty
& I915_UPLOAD_TEX_ALL
) >> I915_UPLOAD_TEX_0_SHIFT
);
333 for (i
= 0 ; i
< I915_TEX_UNITS
; i
++)
334 if (dirty
& I915_UPLOAD_TEX(i
)) {
335 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_SS2
]);
336 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_SS3
]);
337 OUT_BATCH(state
->Tex
[i
][I915_TEXREG_SS4
]);
342 if (dirty
& I915_UPLOAD_CONSTANTS
) {
343 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_CONSTANTS:\n");
344 emit( i915
, state
->Constant
, state
->ConstantSize
* sizeof(GLuint
) );
347 if (dirty
& I915_UPLOAD_PROGRAM
) {
348 if (VERBOSE
) fprintf(stderr
, "I915_UPLOAD_PROGRAM:\n");
350 assert((state
->Program
[0] & 0x1ff)+2 == state
->ProgramSize
);
352 emit( i915
, state
->Program
, state
->ProgramSize
* sizeof(GLuint
) );
354 i915_disassemble_program( state
->Program
, state
->ProgramSize
);
357 state
->emitted
|= dirty
;
358 intel
->batch
.last_emit_state
= counter
;
359 assert(counter
== intel
->batch
.counter
);
362 static void i915_destroy_context( intelContextPtr intel
)
364 _tnl_free_vertices(&intel
->ctx
);
369 * Set the color buffer drawing region.
372 i915_set_color_region( intelContextPtr intel
, const intelRegion
*region
)
374 i915ContextPtr i915
= I915_CONTEXT(intel
);
375 I915_STATECHANGE( i915
, I915_UPLOAD_BUFFERS
);
376 i915
->state
.Buffer
[I915_DESTREG_CBUFADDR1
] =
377 (BUF_3D_ID_COLOR_BACK
| BUF_3D_PITCH(region
->pitch
) | BUF_3D_USE_FENCE
);
378 i915
->state
.Buffer
[I915_DESTREG_CBUFADDR2
] = region
->offset
;
383 * specify the z-buffer/stencil region
386 i915_set_z_region( intelContextPtr intel
, const intelRegion
*region
)
388 i915ContextPtr i915
= I915_CONTEXT(intel
);
389 I915_STATECHANGE( i915
, I915_UPLOAD_BUFFERS
);
390 i915
->state
.Buffer
[I915_DESTREG_DBUFADDR1
] =
391 (BUF_3D_ID_DEPTH
| BUF_3D_PITCH(region
->pitch
) | BUF_3D_USE_FENCE
);
392 i915
->state
.Buffer
[I915_DESTREG_DBUFADDR2
] = region
->offset
;
397 * Set both the color and Z/stencil drawing regions.
398 * Similar to two previous functions, but don't use I915_STATECHANGE()
401 i915_update_color_z_regions(intelContextPtr intel
,
402 const intelRegion
*colorRegion
,
403 const intelRegion
*depthRegion
)
405 i915ContextPtr i915
= I915_CONTEXT(intel
);
407 i915
->state
.Buffer
[I915_DESTREG_CBUFADDR1
] =
408 (BUF_3D_ID_COLOR_BACK
| BUF_3D_PITCH(colorRegion
->pitch
) | BUF_3D_USE_FENCE
);
409 i915
->state
.Buffer
[I915_DESTREG_CBUFADDR2
] = colorRegion
->offset
;
411 i915
->state
.Buffer
[I915_DESTREG_DBUFADDR1
] =
413 BUF_3D_PITCH(depthRegion
->pitch
) | /* pitch in bytes */
415 i915
->state
.Buffer
[I915_DESTREG_DBUFADDR2
] = depthRegion
->offset
;
419 static void i915_lost_hardware( intelContextPtr intel
)
421 I915_CONTEXT(intel
)->state
.emitted
= 0;
424 static void i915_emit_flush( intelContextPtr intel
)
429 OUT_BATCH( MI_FLUSH
| FLUSH_MAP_CACHE
| FLUSH_RENDER_CACHE
);
435 void i915InitVtbl( i915ContextPtr i915
)
437 i915
->intel
.vtbl
.alloc_tex_obj
= i915AllocTexObj
;
438 i915
->intel
.vtbl
.check_vertex_size
= i915_check_vertex_size
;
439 i915
->intel
.vtbl
.clear_with_tris
= i915ClearWithTris
;
440 i915
->intel
.vtbl
.rotate_window
= i915RotateWindow
;
441 i915
->intel
.vtbl
.destroy
= i915_destroy_context
;
442 i915
->intel
.vtbl
.emit_invarient_state
= i915_emit_invarient_state
;
443 i915
->intel
.vtbl
.emit_state
= i915_emit_state
;
444 i915
->intel
.vtbl
.lost_hardware
= i915_lost_hardware
;
445 i915
->intel
.vtbl
.reduced_primitive_state
= i915_reduced_primitive_state
;
446 i915
->intel
.vtbl
.render_start
= i915_render_start
;
447 i915
->intel
.vtbl
.set_color_region
= i915_set_color_region
;
448 i915
->intel
.vtbl
.set_z_region
= i915_set_z_region
;
449 i915
->intel
.vtbl
.update_color_z_regions
= i915_update_color_z_regions
;
450 i915
->intel
.vtbl
.update_texture_state
= i915UpdateTextureState
;
451 i915
->intel
.vtbl
.emit_flush
= i915_emit_flush
;