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 **************************************************************************/
34 #include "intel_screen.h"
35 #include "intel_batchbuffer.h"
36 #include "intel_ioctl.h"
38 #include "i915_context.h"
41 /* A large amount of state doesn't need to be uploaded.
43 #define ACTIVE (I915_UPLOAD_PROGRAM | \
44 I915_UPLOAD_STIPPLE | \
46 I915_UPLOAD_BUFFERS | \
49 #define SET_STATE( i915, STATE ) \
51 i915->current->emitted &= ~ACTIVE; \
52 i915->current = &i915->STATE; \
53 i915->current->emitted &= ~ACTIVE; \
56 /* Operations where the 3D engine is decoupled temporarily from the
57 * current GL state and used for other purposes than simply rendering
60 static void set_initial_state( i915ContextPtr i915
)
62 memcpy(&i915
->meta
, &i915
->initial
, sizeof(i915
->meta
) );
63 i915
->meta
.active
= ACTIVE
;
64 i915
->meta
.emitted
= 0;
68 static void set_no_depth_stencil_write( i915ContextPtr i915
)
70 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
72 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] &= ~(S5_STENCIL_TEST_ENABLE
|
73 S5_STENCIL_WRITE_ENABLE
);
75 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
77 i915
->meta
.Ctx
[I915_CTXREG_LIS6
] &= ~(S6_DEPTH_TEST_ENABLE
|
78 S6_DEPTH_WRITE_ENABLE
);
80 i915
->meta
.emitted
&= ~I915_UPLOAD_CTX
;
83 /* Set stencil unit to replace always with the reference value.
85 static void set_stencil_replace( i915ContextPtr i915
,
89 GLuint op
= STENCILOP_REPLACE
;
90 GLuint func
= COMPAREFUNC_ALWAYS
;
92 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
94 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |= (S5_STENCIL_TEST_ENABLE
|
95 S5_STENCIL_WRITE_ENABLE
);
98 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
100 i915
->meta
.Ctx
[I915_CTXREG_LIS6
] &= ~(S6_DEPTH_TEST_ENABLE
|
101 S6_DEPTH_WRITE_ENABLE
);
104 /* ctx->Driver.StencilMask( ctx, s_mask )
106 i915
->meta
.Ctx
[I915_CTXREG_STATE4
] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK
;
108 i915
->meta
.Ctx
[I915_CTXREG_STATE4
] |= (ENABLE_STENCIL_WRITE_MASK
|
109 STENCIL_WRITE_MASK(s_mask
));
112 /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
114 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] &= ~(S5_STENCIL_FAIL_MASK
|
115 S5_STENCIL_PASS_Z_FAIL_MASK
|
116 S5_STENCIL_PASS_Z_PASS_MASK
);
118 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |= ((op
<< S5_STENCIL_FAIL_SHIFT
) |
119 (op
<< S5_STENCIL_PASS_Z_FAIL_SHIFT
) |
120 (op
<< S5_STENCIL_PASS_Z_PASS_SHIFT
));
123 /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_ref, ~0 )
125 i915
->meta
.Ctx
[I915_CTXREG_STATE4
] &= ~MODE4_ENABLE_STENCIL_TEST_MASK
;
126 i915
->meta
.Ctx
[I915_CTXREG_STATE4
] |= (ENABLE_STENCIL_TEST_MASK
|
127 STENCIL_TEST_MASK(0xff));
129 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] &= ~(S5_STENCIL_REF_MASK
|
130 S5_STENCIL_TEST_FUNC_MASK
);
132 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |= ((s_clear
<< S5_STENCIL_REF_SHIFT
) |
133 (func
<< S5_STENCIL_TEST_FUNC_SHIFT
));
136 i915
->meta
.emitted
&= ~I915_UPLOAD_CTX
;
140 static void set_color_mask( i915ContextPtr i915
, GLboolean state
)
142 const GLuint mask
= (S5_WRITEDISABLE_RED
|
143 S5_WRITEDISABLE_GREEN
|
144 S5_WRITEDISABLE_BLUE
|
145 S5_WRITEDISABLE_ALPHA
);
147 /* Copy colormask state from "regular" hw context.
150 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] &= ~mask
;
151 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |=
152 (i915
->state
.Ctx
[I915_CTXREG_LIS5
] & mask
);
155 i915
->meta
.Ctx
[I915_CTXREG_LIS5
] |= mask
;
157 i915
->meta
.emitted
&= ~I915_UPLOAD_CTX
;
163 #define REG( type, nr ) (((type)<<5)|(nr))
165 #define REG_R(x) REG(REG_TYPE_R, x)
166 #define REG_T(x) REG(REG_TYPE_T, x)
167 #define REG_CONST(x) REG(REG_TYPE_CONST, x)
168 #define REG_S(x) REG(REG_TYPE_S, x)
169 #define REG_OC REG(REG_TYPE_OC, 0)
170 #define REG_OD REG(REG_TYPE_OD, 0)
171 #define REG_U(x) REG(REG_TYPE_U, x)
173 #define REG_T_DIFFUSE REG(REG_TYPE_T, T_DIFFUSE)
174 #define REG_T_SPECULAR REG(REG_TYPE_T, T_SPECULAR)
175 #define REG_T_FOG_W REG(REG_TYPE_T, T_FOG_W)
176 #define REG_T_TEX(x) REG(REG_TYPE_T, x)
179 #define A0_DEST_REG( reg ) ( (reg) << A0_DEST_NR_SHIFT )
180 #define A0_SRC0_REG( reg ) ( (reg) << A0_SRC0_NR_SHIFT )
181 #define A1_SRC1_REG( reg ) ( (reg) << A1_SRC1_NR_SHIFT )
182 #define A1_SRC2_REG( reg ) ( (reg) << A1_SRC2_NR_SHIFT )
183 #define A2_SRC2_REG( reg ) ( (reg) << A2_SRC2_NR_SHIFT )
184 #define D0_DECL_REG( reg ) ( (reg) << D0_NR_SHIFT )
185 #define T0_DEST_REG( reg ) ( (reg) << T0_DEST_NR_SHIFT )
187 #define T0_SAMPLER( unit ) ((unit)<<T0_SAMPLER_NR_SHIFT)
189 #define T1_ADDRESS_REG( type, nr ) (((type)<<T1_ADDRESS_REG_TYPE_SHIFT)| \
190 ((nr)<<T1_ADDRESS_REG_NR_SHIFT))
193 #define A1_SRC0_XYZW ((SRC_X << A1_SRC0_CHANNEL_X_SHIFT) | \
194 (SRC_Y << A1_SRC0_CHANNEL_Y_SHIFT) | \
195 (SRC_Z << A1_SRC0_CHANNEL_Z_SHIFT) | \
196 (SRC_W << A1_SRC0_CHANNEL_W_SHIFT))
198 #define A1_SRC1_XY ((SRC_X << A1_SRC1_CHANNEL_X_SHIFT) | \
199 (SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT))
201 #define A2_SRC1_ZW ((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) | \
202 (SRC_W << A2_SRC1_CHANNEL_W_SHIFT))
204 #define A2_SRC2_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \
205 (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \
206 (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \
207 (SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
213 static void set_no_texture( i915ContextPtr i915
)
215 static const GLuint prog
[] = {
216 _3DSTATE_PIXEL_SHADER_PROGRAM
,
218 /* Declare incoming diffuse color:
221 D0_DECL_REG( REG_T_DIFFUSE
) |
226 /* output-color = mov(t_diffuse)
229 A0_DEST_REG( REG_OC
) |
230 A0_DEST_CHANNEL_ALL
|
231 A0_SRC0_REG( REG_T_DIFFUSE
)),
237 memcpy( i915
->meta
.Program
, prog
, sizeof(prog
) );
238 i915
->meta
.ProgramSize
= sizeof(prog
) / sizeof(*prog
);
239 i915
->meta
.Program
[0] |= i915
->meta
.ProgramSize
- 2;
240 i915
->meta
.emitted
&= ~I915_UPLOAD_PROGRAM
;
244 static void enable_texture_blend_replace( i915ContextPtr i915
)
246 static const GLuint prog
[] = {
247 _3DSTATE_PIXEL_SHADER_PROGRAM
,
249 /* Declare the sampler:
252 D0_DECL_REG( REG_S(0) ) |
258 /* Declare the interpolated texture coordinate:
261 D0_DECL_REG( REG_T_TEX(0) ) |
266 /* output-color = texld(sample0, texcoord0)
269 T0_DEST_REG( REG_OC
) |
271 T1_ADDRESS_REG(REG_TYPE_T
, 0),
275 memcpy( i915
->meta
.Program
, prog
, sizeof(prog
) );
276 i915
->meta
.ProgramSize
= sizeof(prog
) / sizeof(*prog
);
277 i915
->meta
.Program
[0] |= i915
->meta
.ProgramSize
- 2;
278 i915
->meta
.emitted
&= ~I915_UPLOAD_PROGRAM
;
285 /* Set up an arbitary piece of memory as a rectangular texture
286 * (including the front or back buffer).
288 static void set_tex_rect_source( i915ContextPtr i915
,
293 GLuint textureFormat
)
297 GLuint
*state
= i915
->meta
.Tex
[0];
299 pitch
*= i915
->intel
.intelScreen
->cpp
;
301 /* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
302 /* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
304 state
[I915_TEXREG_MS2
] = offset
;
305 state
[I915_TEXREG_MS3
] = (((height
- 1) << MS3_HEIGHT_SHIFT
) |
306 ((width
- 1) << MS3_WIDTH_SHIFT
) |
310 state
[I915_TEXREG_MS4
] = ((((pitch
/ 4) - 1) << MS4_PITCH_SHIFT
) |
311 MS4_CUBE_FACE_ENA_MASK
|
312 ((((numLevels
-1) * 4)) << MS4_MAX_LOD_SHIFT
));
314 state
[I915_TEXREG_SS2
] = ((FILTER_NEAREST
<< SS2_MIN_FILTER_SHIFT
) |
315 (MIPFILTER_NONE
<< SS2_MIP_FILTER_SHIFT
) |
316 (FILTER_NEAREST
<< SS2_MAG_FILTER_SHIFT
));
317 state
[I915_TEXREG_SS3
] = ((TEXCOORDMODE_WRAP
<< SS3_TCX_ADDR_MODE_SHIFT
) |
318 (TEXCOORDMODE_WRAP
<< SS3_TCY_ADDR_MODE_SHIFT
) |
319 (TEXCOORDMODE_WRAP
<< SS3_TCZ_ADDR_MODE_SHIFT
) |
320 (unit
<<SS3_TEXTUREMAP_INDEX_SHIFT
));
322 state
[I915_TEXREG_SS4
] = 0;
324 i915
->meta
.emitted
&= ~I915_UPLOAD_TEX(0);
328 /* Select between front and back draw buffers.
330 static void set_draw_offset( i915ContextPtr i915
,
333 i915
->meta
.Buffer
[I915_DESTREG_CBUFADDR2
] = offset
;
334 i915
->meta
.emitted
&= ~I915_UPLOAD_BUFFERS
;
337 /* Setup an arbitary draw format, useful for targeting texture or agp
340 static void set_draw_format( i915ContextPtr i915
,
344 i915
->meta
.Buffer
[I915_DESTREG_DV1
] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
345 DSTORG_VERT_BIAS(0x8) | /* .5 */
348 TEX_DEFAULT_COLOR_OGL
|
351 i915
->meta
.emitted
&= ~I915_UPLOAD_BUFFERS
;
352 /* fprintf(stderr, "%s: DV1: %x\n", */
353 /* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
356 static void set_vertex_format( i915ContextPtr i915
)
358 i915
->meta
.Ctx
[I915_CTXREG_LIS2
] =
359 (S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D
) |
360 S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT
) |
361 S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT
) |
362 S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT
) |
363 S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT
) |
364 S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT
) |
365 S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT
) |
366 S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT
));
368 i915
->meta
.Ctx
[I915_CTXREG_LIS4
] &= ~S4_VFMT_MASK
;
370 i915
->meta
.Ctx
[I915_CTXREG_LIS4
] |=
375 i915
->meta
.emitted
&= ~I915_UPLOAD_CTX
;
380 static void draw_quad(i915ContextPtr i915
,
381 GLfloat x0
, GLfloat x1
,
382 GLfloat y0
, GLfloat y1
,
383 GLubyte red
, GLubyte green
,
384 GLubyte blue
, GLubyte alpha
,
385 GLfloat s0
, GLfloat s1
,
386 GLfloat t0
, GLfloat t1
)
388 GLuint vertex_size
= 8;
389 GLuint
*vb
= intelEmitInlinePrimitiveLocked( &i915
->intel
,
397 fprintf(stderr
, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
399 x0
,y0
,x1
,y1
,red
,green
,blue
,alpha
,s0
,t0
,s1
,t1
);
402 /* initial vertex, left bottom */
407 tmp
.v
.color
.red
= red
;
408 tmp
.v
.color
.green
= green
;
409 tmp
.v
.color
.blue
= blue
;
410 tmp
.v
.color
.alpha
= alpha
;
411 tmp
.v
.specular
.red
= 0;
412 tmp
.v
.specular
.green
= 0;
413 tmp
.v
.specular
.blue
= 0;
414 tmp
.v
.specular
.alpha
= 0;
418 for (i
= 0 ; i
< vertex_size
; i
++)
425 for (i
= 0 ; i
< vertex_size
; i
++)
432 for (i
= 0 ; i
< vertex_size
; i
++)
439 for (i
= 0 ; i
< vertex_size
; i
++)
444 i915ClearWithTris(intelContextPtr intel
, GLbitfield mask
,
446 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
448 i915ContextPtr i915
= I915_CONTEXT( intel
);
449 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
450 intelScreenPrivate
*screen
= intel
->intelScreen
;
453 SET_STATE( i915
, meta
);
454 set_initial_state( i915
);
455 set_no_texture( i915
);
456 set_vertex_format( i915
);
458 LOCK_HARDWARE(intel
);
472 /* Don't do any clipping to screen - these are window coordinates.
473 * The active cliprects will be applied as for any other geometry.
476 if (mask
& DD_FRONT_LEFT_BIT
) {
477 set_no_depth_stencil_write( i915
);
478 set_color_mask( i915
, GL_TRUE
);
479 set_draw_offset( i915
, screen
->frontOffset
);
481 draw_quad(i915
, x0
, x1
, y0
, y1
,
482 intel
->clear_red
, intel
->clear_green
,
483 intel
->clear_blue
, intel
->clear_alpha
,
487 if(mask
& DD_BACK_LEFT_BIT
) {
488 set_no_depth_stencil_write( i915
);
489 set_color_mask( i915
, GL_TRUE
);
490 set_draw_offset( i915
, screen
->backOffset
);
492 draw_quad(i915
, x0
, x1
, y0
, y1
,
493 intel
->clear_red
, intel
->clear_green
,
494 intel
->clear_blue
, intel
->clear_alpha
,
498 if(mask
& DD_STENCIL_BIT
) {
499 set_stencil_replace( i915
,
500 intel
->ctx
.Stencil
.WriteMask
[0],
501 intel
->ctx
.Stencil
.Clear
);
503 set_color_mask( i915
, GL_FALSE
);
504 set_draw_offset( i915
, screen
->frontOffset
); /* could be either? */
506 draw_quad( i915
, x0
, x1
, y0
, y1
, 0, 0, 0, 0, 0, 0, 0, 0 );
509 UNLOCK_HARDWARE(intel
);
511 SET_STATE( i915
, state
);