add missing license texts
[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
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
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 /* Setup an arbitary draw format, useful for targeting texture or agp
338 * memory.
339 */
340 static void set_draw_format( i915ContextPtr i915,
341 GLuint format,
342 GLuint depth_format)
343 {
344 i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
345 DSTORG_VERT_BIAS(0x8) | /* .5 */
346 format |
347 LOD_PRECLAMP_OGL |
348 TEX_DEFAULT_COLOR_OGL |
349 depth_format);
350
351 i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
352 /* fprintf(stderr, "%s: DV1: %x\n", */
353 /* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
354 }
355
356 static void set_vertex_format( i915ContextPtr i915 )
357 {
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));
367
368 i915->meta.Ctx[I915_CTXREG_LIS4] &= ~S4_VFMT_MASK;
369
370 i915->meta.Ctx[I915_CTXREG_LIS4] |=
371 (S4_VFMT_COLOR |
372 S4_VFMT_SPEC_FOG |
373 S4_VFMT_XYZW);
374
375 i915->meta.emitted &= ~I915_UPLOAD_CTX;
376
377 }
378
379
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 )
387 {
388 GLuint vertex_size = 8;
389 GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
390 PRIM3D_TRIFAN,
391 4 * vertex_size,
392 vertex_size );
393 intelVertex tmp;
394 int i;
395
396 if (0)
397 fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
398 __FUNCTION__,
399 x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1);
400
401
402 /* initial vertex, left bottom */
403 tmp.v.x = x0;
404 tmp.v.y = y0;
405 tmp.v.z = 1.0;
406 tmp.v.w = 1.0;
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;
415 tmp.v.u0 = s0;
416 tmp.v.v0 = t0;
417
418 for (i = 0 ; i < vertex_size ; i++)
419 vb[i] = tmp.ui[i];
420
421 /* right bottom */
422 vb += vertex_size;
423 tmp.v.x = x1;
424 tmp.v.u0 = s1;
425 for (i = 0 ; i < vertex_size ; i++)
426 vb[i] = tmp.ui[i];
427
428 /* right top */
429 vb += vertex_size;
430 tmp.v.y = y1;
431 tmp.v.v0 = t1;
432 for (i = 0 ; i < vertex_size ; i++)
433 vb[i] = tmp.ui[i];
434
435 /* left top */
436 vb += vertex_size;
437 tmp.v.x = x0;
438 tmp.v.u0 = s0;
439 for (i = 0 ; i < vertex_size ; i++)
440 vb[i] = tmp.ui[i];
441 }
442
443 void
444 i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
445 GLboolean all,
446 GLint cx, GLint cy, GLint cw, GLint ch)
447 {
448 i915ContextPtr i915 = I915_CONTEXT( intel );
449 __DRIdrawablePrivate *dPriv = intel->driDrawable;
450 intelScreenPrivate *screen = intel->intelScreen;
451 int x0, y0, x1, y1;
452
453 SET_STATE( i915, meta );
454 set_initial_state( i915 );
455 set_no_texture( i915 );
456 set_vertex_format( i915 );
457
458 LOCK_HARDWARE(intel);
459
460 if(!all) {
461 x0 = cx;
462 y0 = cy;
463 x1 = x0 + cw;
464 y1 = y0 + ch;
465 } else {
466 x0 = 0;
467 y0 = 0;
468 x1 = x0 + dPriv->w;
469 y1 = y0 + dPriv->h;
470 }
471
472 /* Don't do any clipping to screen - these are window coordinates.
473 * The active cliprects will be applied as for any other geometry.
474 */
475
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 );
480
481 draw_quad(i915, x0, x1, y0, y1,
482 intel->clear_red, intel->clear_green,
483 intel->clear_blue, intel->clear_alpha,
484 0, 0, 0, 0);
485 }
486
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 );
491
492 draw_quad(i915, x0, x1, y0, y1,
493 intel->clear_red, intel->clear_green,
494 intel->clear_blue, intel->clear_alpha,
495 0, 0, 0, 0);
496 }
497
498 if(mask & DD_STENCIL_BIT) {
499 set_stencil_replace( i915,
500 intel->ctx.Stencil.WriteMask[0],
501 intel->ctx.Stencil.Clear);
502
503 set_color_mask( i915, GL_FALSE );
504 set_draw_offset( i915, screen->frontOffset ); /* could be either? */
505
506 draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
507 }
508
509 UNLOCK_HARDWARE(intel);
510
511 SET_STATE( i915, state );
512 }
513
514