Add Intel i915GM support, and these extensions.
[mesa.git] / src / mesa / drivers / dri / i915 / i915_metaops.c
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 #include "glheader.h"
29 #include "enums.h"
30 #include "mtypes.h"
31 #include "macros.h"
32 #include "utils.h"
33
34 #include "intel_screen.h"
35 #include "intel_batchbuffer.h"
36 #include "intel_ioctl.h"
37
38 #include "i915_context.h"
39 #include "i915_reg.h"
40
41 /* A large amount of state doesn't need to be uploaded.
42 */
43 #define ACTIVE (I915_UPLOAD_PROGRAM | \
44 I915_UPLOAD_STIPPLE | \
45 I915_UPLOAD_CTX | \
46 I915_UPLOAD_BUFFERS | \
47 I915_UPLOAD_TEX(0))
48
49 #define SET_STATE( i915, STATE ) \
50 do { \
51 i915->current->emitted &= ~ACTIVE; \
52 i915->current = &i915->STATE; \
53 i915->current->emitted &= ~ACTIVE; \
54 } while (0)
55
56 /* Operations where the 3D engine is decoupled temporarily from the
57 * current GL state and used for other purposes than simply rendering
58 * incoming triangles.
59 */
60 static void set_initial_state( i915ContextPtr i915 )
61 {
62 memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
63 i915->meta.active = ACTIVE;
64 i915->meta.emitted = 0;
65 }
66
67
68 static void set_no_depth_stencil_write( i915ContextPtr i915 )
69 {
70 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
71 */
72 i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
73 S5_STENCIL_WRITE_ENABLE);
74
75 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
76 */
77 i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
78 S6_DEPTH_WRITE_ENABLE);
79
80 i915->meta.emitted &= ~I915_UPLOAD_CTX;
81 }
82
83 /* Set stencil unit to replace always with the reference value.
84 */
85 static void set_stencil_replace( i915ContextPtr i915,
86 GLuint s_mask,
87 GLuint s_clear)
88 {
89 GLuint op = STENCILOP_REPLACE;
90 GLuint func = COMPAREFUNC_ALWAYS;
91
92 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
93 */
94 i915->meta.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
95 S5_STENCIL_WRITE_ENABLE);
96
97
98 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
99 */
100 i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
101 S6_DEPTH_WRITE_ENABLE);
102
103
104 /* ctx->Driver.StencilMask( ctx, s_mask )
105 */
106 i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
107
108 i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
109 STENCIL_WRITE_MASK(s_mask));
110
111
112 /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
113 */
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);
117
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));
121
122
123 /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_ref, ~0 )
124 */
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));
128
129 i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
130 S5_STENCIL_TEST_FUNC_MASK);
131
132 i915->meta.Ctx[I915_CTXREG_LIS5] |= ((s_clear << S5_STENCIL_REF_SHIFT) |
133 (func << S5_STENCIL_TEST_FUNC_SHIFT));
134
135
136 i915->meta.emitted &= ~I915_UPLOAD_CTX;
137 }
138
139
140 static void set_color_mask( i915ContextPtr i915, GLboolean state )
141 {
142 const GLuint mask = (S5_WRITEDISABLE_RED |
143 S5_WRITEDISABLE_GREEN |
144 S5_WRITEDISABLE_BLUE |
145 S5_WRITEDISABLE_ALPHA);
146
147 /* Copy colormask state from "regular" hw context.
148 */
149 if (state) {
150 i915->meta.Ctx[I915_CTXREG_LIS5] &= ~mask;
151 i915->meta.Ctx[I915_CTXREG_LIS5] |=
152 (i915->state.Ctx[I915_CTXREG_LIS5] & mask);
153 }
154 else
155 i915->meta.Ctx[I915_CTXREG_LIS5] |= mask;
156
157 i915->meta.emitted &= ~I915_UPLOAD_CTX;
158 }
159
160
161
162
163 #define REG( type, nr ) (((type)<<5)|(nr))
164
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)
172
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)
177
178
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 )
186
187 #define T0_SAMPLER( unit ) ((unit)<<T0_SAMPLER_NR_SHIFT)
188
189 #define T1_ADDRESS_REG( type, nr ) (((type)<<T1_ADDRESS_REG_TYPE_SHIFT)| \
190 ((nr)<<T1_ADDRESS_REG_NR_SHIFT))
191
192
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))
197
198 #define A1_SRC1_XY ((SRC_X << A1_SRC1_CHANNEL_X_SHIFT) | \
199 (SRC_Y << A1_SRC1_CHANNEL_Y_SHIFT))
200
201 #define A2_SRC1_ZW ((SRC_Z << A2_SRC1_CHANNEL_Z_SHIFT) | \
202 (SRC_W << A2_SRC1_CHANNEL_W_SHIFT))
203
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))
208
209
210
211
212
213 static void set_no_texture( i915ContextPtr i915 )
214 {
215 static const GLuint prog[] = {
216 _3DSTATE_PIXEL_SHADER_PROGRAM,
217
218 /* Declare incoming diffuse color:
219 */
220 (D0_DCL |
221 D0_DECL_REG( REG_T_DIFFUSE ) |
222 D0_CHANNEL_ALL),
223 D1_MBZ,
224 D2_MBZ,
225
226 /* output-color = mov(t_diffuse)
227 */
228 (A0_MOV |
229 A0_DEST_REG( REG_OC ) |
230 A0_DEST_CHANNEL_ALL |
231 A0_SRC0_REG( REG_T_DIFFUSE )),
232 (A1_SRC0_XYZW),
233 0,
234 };
235
236
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;
241 }
242
243 #if 0
244 static void enable_texture_blend_replace( i915ContextPtr i915 )
245 {
246 static const GLuint prog[] = {
247 _3DSTATE_PIXEL_SHADER_PROGRAM,
248
249 /* Declare the sampler:
250 */
251 (D0_DCL |
252 D0_DECL_REG( REG_S(0) ) |
253 D0_SAMPLE_TYPE_2D |
254 D0_CHANNEL_NONE),
255 D1_MBZ,
256 D2_MBZ,
257
258 /* Declare the interpolated texture coordinate:
259 */
260 (D0_DCL |
261 D0_DECL_REG( REG_T_TEX(0) ) |
262 D0_CHANNEL_ALL),
263 D1_MBZ,
264 D2_MBZ,
265
266 /* output-color = texld(sample0, texcoord0)
267 */
268 (T0_TEXLD |
269 T0_DEST_REG( REG_OC ) |
270 T0_SAMPLER( 0 )),
271 T1_ADDRESS_REG(REG_TYPE_T, 0),
272 T2_MBZ
273 };
274
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;
279 }
280
281
282
283
284
285 /* Set up an arbitary piece of memory as a rectangular texture
286 * (including the front or back buffer).
287 */
288 static void set_tex_rect_source( i915ContextPtr i915,
289 GLuint offset,
290 GLuint width,
291 GLuint height,
292 GLuint pitch,
293 GLuint textureFormat )
294 {
295 GLuint unit = 0;
296 GLint numLevels = 1;
297 GLuint *state = i915->meta.Tex[0];
298
299 pitch *= i915->intel.intelScreen->cpp;
300
301 /* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
302 /* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
303
304 state[I915_TEXREG_MS2] = offset;
305 state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) |
306 ((width - 1) << MS3_WIDTH_SHIFT) |
307 textureFormat |
308 MS3_USE_FENCE_REGS);
309
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));
313
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));
321
322 state[I915_TEXREG_SS4] = 0;
323
324 i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
325 }
326 #endif
327
328 /* Select between front and back draw buffers.
329 */
330 static void set_draw_offset( i915ContextPtr i915,
331 GLuint offset )
332 {
333 i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset;
334 i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
335 }
336
337 #if 0
338 /* Setup an arbitary draw format, useful for targeting texture or agp
339 * memory.
340 */
341 static void set_draw_format( i915ContextPtr i915,
342 GLuint format,
343 GLuint depth_format)
344 {
345 i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
346 DSTORG_VERT_BIAS(0x8) | /* .5 */
347 format |
348 LOD_PRECLAMP_OGL |
349 TEX_DEFAULT_COLOR_OGL |
350 depth_format);
351
352 i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
353 /* fprintf(stderr, "%s: DV1: %x\n", */
354 /* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
355 }
356 #endif
357
358 static void set_vertex_format( i915ContextPtr i915 )
359 {
360 i915->meta.Ctx[I915_CTXREG_LIS2] =
361 (S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
362 S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
363 S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) |
364 S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) |
365 S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) |
366 S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) |
367 S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) |
368 S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT));
369
370 i915->meta.Ctx[I915_CTXREG_LIS4] &= ~S4_VFMT_MASK;
371
372 i915->meta.Ctx[I915_CTXREG_LIS4] |=
373 (S4_VFMT_COLOR |
374 S4_VFMT_SPEC_FOG |
375 S4_VFMT_XYZW);
376
377 i915->meta.emitted &= ~I915_UPLOAD_CTX;
378
379 }
380
381
382 static void draw_quad(i915ContextPtr i915,
383 GLfloat x0, GLfloat x1,
384 GLfloat y0, GLfloat y1,
385 GLubyte red, GLubyte green,
386 GLubyte blue, GLubyte alpha,
387 GLfloat s0, GLfloat s1,
388 GLfloat t0, GLfloat t1 )
389 {
390 GLuint vertex_size = 8;
391 GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
392 PRIM3D_TRIFAN,
393 4 * vertex_size,
394 vertex_size );
395 intelVertex tmp;
396 int i;
397
398 if (0)
399 fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
400 __FUNCTION__,
401 x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1);
402
403
404 /* initial vertex, left bottom */
405 tmp.v.x = x0;
406 tmp.v.y = y0;
407 tmp.v.z = 1.0;
408 tmp.v.w = 1.0;
409 tmp.v.color.red = red;
410 tmp.v.color.green = green;
411 tmp.v.color.blue = blue;
412 tmp.v.color.alpha = alpha;
413 tmp.v.specular.red = 0;
414 tmp.v.specular.green = 0;
415 tmp.v.specular.blue = 0;
416 tmp.v.specular.alpha = 0;
417 tmp.v.u0 = s0;
418 tmp.v.v0 = t0;
419
420 for (i = 0 ; i < vertex_size ; i++)
421 vb[i] = tmp.ui[i];
422
423 /* right bottom */
424 vb += vertex_size;
425 tmp.v.x = x1;
426 tmp.v.u0 = s1;
427 for (i = 0 ; i < vertex_size ; i++)
428 vb[i] = tmp.ui[i];
429
430 /* right top */
431 vb += vertex_size;
432 tmp.v.y = y1;
433 tmp.v.v0 = t1;
434 for (i = 0 ; i < vertex_size ; i++)
435 vb[i] = tmp.ui[i];
436
437 /* left top */
438 vb += vertex_size;
439 tmp.v.x = x0;
440 tmp.v.u0 = s0;
441 for (i = 0 ; i < vertex_size ; i++)
442 vb[i] = tmp.ui[i];
443 }
444
445 void
446 i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
447 GLboolean all,
448 GLint cx, GLint cy, GLint cw, GLint ch)
449 {
450 i915ContextPtr i915 = I915_CONTEXT( intel );
451 __DRIdrawablePrivate *dPriv = intel->driDrawable;
452 intelScreenPrivate *screen = intel->intelScreen;
453 int x0, y0, x1, y1;
454
455 SET_STATE( i915, meta );
456 set_initial_state( i915 );
457 set_no_texture( i915 );
458 set_vertex_format( i915 );
459
460 LOCK_HARDWARE(intel);
461
462 if(!all) {
463 x0 = cx;
464 y0 = cy;
465 x1 = x0 + cw;
466 y1 = y0 + ch;
467 } else {
468 x0 = 0;
469 y0 = 0;
470 x1 = x0 + dPriv->w;
471 y1 = y0 + dPriv->h;
472 }
473
474 /* Don't do any clipping to screen - these are window coordinates.
475 * The active cliprects will be applied as for any other geometry.
476 */
477
478 if (mask & DD_FRONT_LEFT_BIT) {
479 set_no_depth_stencil_write( i915 );
480 set_color_mask( i915, GL_TRUE );
481 set_draw_offset( i915, screen->frontOffset );
482
483 draw_quad(i915, x0, x1, y0, y1,
484 intel->clear_red, intel->clear_green,
485 intel->clear_blue, intel->clear_alpha,
486 0, 0, 0, 0);
487 }
488
489 if(mask & DD_BACK_LEFT_BIT) {
490 set_no_depth_stencil_write( i915 );
491 set_color_mask( i915, GL_TRUE );
492 set_draw_offset( i915, screen->backOffset );
493
494 draw_quad(i915, x0, x1, y0, y1,
495 intel->clear_red, intel->clear_green,
496 intel->clear_blue, intel->clear_alpha,
497 0, 0, 0, 0);
498 }
499
500 if(mask & DD_STENCIL_BIT) {
501 set_stencil_replace( i915,
502 intel->ctx.Stencil.WriteMask[0],
503 intel->ctx.Stencil.Clear);
504
505 set_color_mask( i915, GL_FALSE );
506 set_draw_offset( i915, screen->frontOffset ); /* could be either? */
507
508 draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
509 }
510
511 UNLOCK_HARDWARE(intel);
512
513 SET_STATE( i915, state );
514 }
515
516