Merge branch 'master' into autoconf2
[mesa.git] / src / mesa / drivers / dri / i915 / i830_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 #include "intel_regions.h"
38
39 #include "i830_context.h"
40 #include "i830_reg.h"
41
42 /* A large amount of state doesn't need to be uploaded.
43 */
44 #define ACTIVE (I830_UPLOAD_INVARIENT | \
45 I830_UPLOAD_CTX | \
46 I830_UPLOAD_BUFFERS | \
47 I830_UPLOAD_STIPPLE | \
48 I830_UPLOAD_TEXBLEND(0) | \
49 I830_UPLOAD_TEX(0))
50
51
52 #define SET_STATE( i830, STATE ) \
53 do { \
54 i830->current->emitted &= ~ACTIVE; \
55 i830->current = &i830->STATE; \
56 i830->current->emitted &= ~ACTIVE; \
57 } while (0)
58
59
60 static void
61 set_no_stencil_write(struct intel_context *intel)
62 {
63 struct i830_context *i830 = i830_context(&intel->ctx);
64
65 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
66 */
67 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
68 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
69 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
70 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
71
72 i830->meta.emitted &= ~I830_UPLOAD_CTX;
73 }
74
75 static void
76 set_no_depth_write(struct intel_context *intel)
77 {
78 struct i830_context *i830 = i830_context(&intel->ctx);
79
80 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
81 */
82 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
83 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
84 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
85 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
86
87 i830->meta.emitted &= ~I830_UPLOAD_CTX;
88 }
89
90 /* Set depth unit to replace.
91 */
92 static void
93 set_depth_replace(struct intel_context *intel)
94 {
95 struct i830_context *i830 = i830_context(&intel->ctx);
96
97 /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
98 * ctx->Driver.DepthMask( ctx, GL_TRUE )
99 */
100 i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
101 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
102 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST;
103 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE;
104
105 /* ctx->Driver.DepthFunc( ctx, GL_ALWAYS )
106 */
107 i830->meta.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK;
108 i830->meta.Ctx[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC |
109 DEPTH_TEST_FUNC
110 (COMPAREFUNC_ALWAYS));
111
112 i830->meta.emitted &= ~I830_UPLOAD_CTX;
113 }
114
115
116 /* Set stencil unit to replace always with the reference value.
117 */
118 static void
119 set_stencil_replace(struct intel_context *intel,
120 GLuint s_mask, GLuint s_clear)
121 {
122 struct i830_context *i830 = i830_context(&intel->ctx);
123
124 /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
125 */
126 i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
127 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
128
129 /* ctx->Driver.StencilMask( ctx, s_mask )
130 */
131 i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
132 i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
133 STENCIL_WRITE_MASK((s_mask &
134 0xff)));
135
136 /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
137 */
138 i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
139 i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
140 (ENABLE_STENCIL_PARMS |
141 STENCIL_FAIL_OP(STENCILOP_REPLACE) |
142 STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) |
143 STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE));
144
145 /* ctx->Driver.StencilFunc( ctx, GL_ALWAYS, s_clear, ~0 )
146 */
147 i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
148 i830->meta.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
149 STENCIL_TEST_MASK(0xff));
150
151 i830->meta.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK |
152 ENABLE_STENCIL_TEST_FUNC_MASK);
153 i830->meta.Ctx[I830_CTXREG_STENCILTST] |=
154 (ENABLE_STENCIL_REF_VALUE |
155 ENABLE_STENCIL_TEST_FUNC |
156 STENCIL_REF_VALUE((s_clear & 0xff)) |
157 STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS));
158
159
160
161 i830->meta.emitted &= ~I830_UPLOAD_CTX;
162 }
163
164
165 static void
166 set_color_mask(struct intel_context *intel, GLboolean state)
167 {
168 struct i830_context *i830 = i830_context(&intel->ctx);
169
170 const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
171 (1 << WRITEMASK_GREEN_SHIFT) |
172 (1 << WRITEMASK_BLUE_SHIFT) |
173 (1 << WRITEMASK_ALPHA_SHIFT));
174
175 i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~mask;
176
177 if (state) {
178 i830->meta.Ctx[I830_CTXREG_ENABLES_2] |=
179 (i830->state.Ctx[I830_CTXREG_ENABLES_2] & mask);
180 }
181
182 i830->meta.emitted &= ~I830_UPLOAD_CTX;
183 }
184
185 /* Installs a one-stage passthrough texture blend pipeline. Is there
186 * more that can be done to turn off texturing?
187 */
188 static void
189 set_no_texture(struct intel_context *intel)
190 {
191 struct i830_context *i830 = i830_context(&intel->ctx);
192 static const struct gl_tex_env_combine_state comb = {
193 GL_NONE, GL_NONE,
194 {GL_TEXTURE, 0, 0,}, {GL_TEXTURE, 0, 0,},
195 {GL_SRC_COLOR, 0, 0}, {GL_SRC_ALPHA, 0, 0},
196 0, 0, 0, 0
197 };
198
199 i830->meta.TexBlendWordsUsed[0] =
200 i830SetTexEnvCombine(i830, &comb, 0, TEXBLENDARG_TEXEL0,
201 i830->meta.TexBlend[0], NULL);
202
203 i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
204 i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
205 }
206
207 /* Set up a single element blend stage for 'replace' texturing with no
208 * funny ops.
209 */
210 static void
211 set_texture_blend_replace(struct intel_context *intel)
212 {
213 struct i830_context *i830 = i830_context(&intel->ctx);
214 static const struct gl_tex_env_combine_state comb = {
215 GL_REPLACE, GL_REPLACE,
216 {GL_TEXTURE, GL_TEXTURE, GL_TEXTURE,}, {GL_TEXTURE, GL_TEXTURE,
217 GL_TEXTURE,},
218 {GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR}, {GL_SRC_ALPHA, GL_SRC_ALPHA,
219 GL_SRC_ALPHA},
220 0, 0, 1, 1
221 };
222
223 i830->meta.TexBlendWordsUsed[0] =
224 i830SetTexEnvCombine(i830, &comb, 0, TEXBLENDARG_TEXEL0,
225 i830->meta.TexBlend[0], NULL);
226
227 i830->meta.TexBlend[0][0] |= TEXOP_LAST_STAGE;
228 i830->meta.emitted &= ~I830_UPLOAD_TEXBLEND(0);
229
230 /* fprintf(stderr, "%s: TexBlendWordsUsed[0]: %d\n", */
231 /* __FUNCTION__, i830->meta.TexBlendWordsUsed[0]); */
232 }
233
234
235
236 /* Set up an arbitary piece of memory as a rectangular texture
237 * (including the front or back buffer).
238 */
239 static GLboolean
240 set_tex_rect_source(struct intel_context *intel,
241 dri_bo *buffer,
242 GLuint offset,
243 GLuint pitch, GLuint height, GLenum format, GLenum type)
244 {
245 struct i830_context *i830 = i830_context(&intel->ctx);
246 GLuint *setup = i830->meta.Tex[0];
247 GLint numLevels = 1;
248 GLuint textureFormat;
249 GLuint cpp;
250
251 /* A full implementation of this would do the upload through
252 * glTexImage2d, and get all the conversion operations at that
253 * point. We are restricted, but still at least have access to the
254 * fragment program swizzle.
255 */
256 switch (format) {
257 case GL_BGRA:
258 switch (type) {
259 case GL_UNSIGNED_INT_8_8_8_8_REV:
260 case GL_UNSIGNED_BYTE:
261 textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888);
262 cpp = 4;
263 break;
264 default:
265 return GL_FALSE;
266 }
267 break;
268 case GL_RGBA:
269 switch (type) {
270 case GL_UNSIGNED_INT_8_8_8_8_REV:
271 case GL_UNSIGNED_BYTE:
272 textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888);
273 cpp = 4;
274 break;
275 default:
276 return GL_FALSE;
277 }
278 break;
279 case GL_BGR:
280 switch (type) {
281 case GL_UNSIGNED_SHORT_5_6_5_REV:
282 textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
283 cpp = 2;
284 break;
285 default:
286 return GL_FALSE;
287 }
288 break;
289 case GL_RGB:
290 switch (type) {
291 case GL_UNSIGNED_SHORT_5_6_5:
292 textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
293 cpp = 2;
294 break;
295 default:
296 return GL_FALSE;
297 }
298 break;
299
300 default:
301 return GL_FALSE;
302 }
303
304 i830->meta.tex_buffer[0] = buffer;
305 i830->meta.tex_offset[0] = offset;
306
307 setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
308 (LOAD_TEXTURE_MAP0 << 0) | 4);
309 setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
310 ((pitch - 1) << TM0S1_WIDTH_SHIFT) |
311 textureFormat);
312 setup[I830_TEXREG_TM0S2] =
313 (((((pitch * cpp) / 4) -
314 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);
315
316 setup[I830_TEXREG_TM0S3] =
317 ((((numLevels -
318 1) *
319 4) << TM0S3_MIN_MIP_SHIFT) | (FILTER_NEAREST <<
320 TM0S3_MIN_FILTER_SHIFT) |
321 (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT) | (FILTER_NEAREST <<
322 TM0S3_MAG_FILTER_SHIFT));
323
324 setup[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(0));
325
326 setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
327 MAP_UNIT(0) |
328 ENABLE_TEXCOORD_PARAMS |
329 TEXCOORDS_ARE_IN_TEXELUNITS |
330 TEXCOORDTYPE_CARTESIAN |
331 ENABLE_ADDR_V_CNTL |
332 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
333 ENABLE_ADDR_U_CNTL |
334 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
335
336 i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
337 return GL_TRUE;
338 }
339
340
341 static void
342 set_vertex_format(struct intel_context *intel)
343 {
344 struct i830_context *i830 = i830_context(&intel->ctx);
345 i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
346 VFT0_TEX_COUNT(1) |
347 VFT0_DIFFUSE | VFT0_XYZ);
348 i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD |
349 VFT1_TEX0_FMT(TEXCOORDFMT_2D) |
350 VFT1_TEX1_FMT(TEXCOORDFMT_2D) |
351 VFT1_TEX2_FMT(TEXCOORDFMT_2D) |
352 VFT1_TEX3_FMT(TEXCOORDFMT_2D));
353 i830->meta.emitted &= ~I830_UPLOAD_CTX;
354 }
355
356
357 static void
358 meta_import_pixel_state(struct intel_context *intel)
359 {
360 struct i830_context *i830 = i830_context(&intel->ctx);
361
362 i830->meta.Ctx[I830_CTXREG_STATE1] = i830->state.Ctx[I830_CTXREG_STATE1];
363 i830->meta.Ctx[I830_CTXREG_STATE2] = i830->state.Ctx[I830_CTXREG_STATE2];
364 i830->meta.Ctx[I830_CTXREG_STATE3] = i830->state.Ctx[I830_CTXREG_STATE3];
365 i830->meta.Ctx[I830_CTXREG_STATE4] = i830->state.Ctx[I830_CTXREG_STATE4];
366 i830->meta.Ctx[I830_CTXREG_STATE5] = i830->state.Ctx[I830_CTXREG_STATE5];
367 i830->meta.Ctx[I830_CTXREG_IALPHAB] = i830->state.Ctx[I830_CTXREG_IALPHAB];
368 i830->meta.Ctx[I830_CTXREG_STENCILTST] =
369 i830->state.Ctx[I830_CTXREG_STENCILTST];
370 i830->meta.Ctx[I830_CTXREG_ENABLES_1] =
371 i830->state.Ctx[I830_CTXREG_ENABLES_1];
372 i830->meta.Ctx[I830_CTXREG_ENABLES_2] =
373 i830->state.Ctx[I830_CTXREG_ENABLES_2];
374 i830->meta.Ctx[I830_CTXREG_AA] = i830->state.Ctx[I830_CTXREG_AA];
375 i830->meta.Ctx[I830_CTXREG_FOGCOLOR] =
376 i830->state.Ctx[I830_CTXREG_FOGCOLOR];
377 i830->meta.Ctx[I830_CTXREG_BLENDCOLOR0] =
378 i830->state.Ctx[I830_CTXREG_BLENDCOLOR0];
379 i830->meta.Ctx[I830_CTXREG_BLENDCOLOR1] =
380 i830->state.Ctx[I830_CTXREG_BLENDCOLOR1];
381 i830->meta.Ctx[I830_CTXREG_MCSB0] = i830->state.Ctx[I830_CTXREG_MCSB0];
382 i830->meta.Ctx[I830_CTXREG_MCSB1] = i830->state.Ctx[I830_CTXREG_MCSB1];
383
384
385 i830->meta.Ctx[I830_CTXREG_STATE3] &= ~CULLMODE_MASK;
386 i830->meta.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE;
387 i830->meta.emitted &= ~I830_UPLOAD_CTX;
388
389
390 i830->meta.Buffer[I830_DESTREG_SENABLE] =
391 i830->state.Buffer[I830_DESTREG_SENABLE];
392 i830->meta.Buffer[I830_DESTREG_SR1] = i830->state.Buffer[I830_DESTREG_SR1];
393 i830->meta.Buffer[I830_DESTREG_SR2] = i830->state.Buffer[I830_DESTREG_SR2];
394 i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
395 }
396
397
398
399 /* Select between front and back draw buffers.
400 */
401 static void
402 meta_draw_region(struct intel_context *intel,
403 struct intel_region *color_region,
404 struct intel_region *depth_region)
405 {
406 struct i830_context *i830 = i830_context(&intel->ctx);
407
408 i830_state_draw_region(intel, &i830->meta, color_region, depth_region);
409 }
410
411
412 /* Operations where the 3D engine is decoupled temporarily from the
413 * current GL state and used for other purposes than simply rendering
414 * incoming triangles.
415 */
416 static void
417 install_meta_state(struct intel_context *intel)
418 {
419 struct i830_context *i830 = i830_context(&intel->ctx);
420 memcpy(&i830->meta, &i830->initial, sizeof(i830->meta));
421
422 i830->meta.active = ACTIVE;
423 i830->meta.emitted = 0;
424
425 SET_STATE(i830, meta);
426 set_vertex_format(intel);
427 set_no_texture(intel);
428 }
429
430 static void
431 leave_meta_state(struct intel_context *intel)
432 {
433 struct i830_context *i830 = i830_context(&intel->ctx);
434 intel_region_release(&i830->meta.draw_region);
435 intel_region_release(&i830->meta.depth_region);
436 /* intel_region_release(intel, &i830->meta.tex_region[0]); */
437 SET_STATE(i830, state);
438 }
439
440
441
442 void
443 i830InitMetaFuncs(struct i830_context *i830)
444 {
445 i830->intel.vtbl.install_meta_state = install_meta_state;
446 i830->intel.vtbl.leave_meta_state = leave_meta_state;
447 i830->intel.vtbl.meta_no_depth_write = set_no_depth_write;
448 i830->intel.vtbl.meta_no_stencil_write = set_no_stencil_write;
449 i830->intel.vtbl.meta_stencil_replace = set_stencil_replace;
450 i830->intel.vtbl.meta_depth_replace = set_depth_replace;
451 i830->intel.vtbl.meta_color_mask = set_color_mask;
452 i830->intel.vtbl.meta_no_texture = set_no_texture;
453 i830->intel.vtbl.meta_texture_blend_replace = set_texture_blend_replace;
454 i830->intel.vtbl.meta_tex_rect_source = set_tex_rect_source;
455 i830->intel.vtbl.meta_draw_region = meta_draw_region;
456 i830->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state;
457 }