dbb33f26955f7aed7eedfaea901926fc0d23b231
[mesa.git] / src / gallium / drivers / i915simple / i915_state.c
1 /**************************************************************************
2 *
3 * Copyright 2007 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 /* Authors: Keith Whitwell <keith@tungstengraphics.com>
29 */
30
31
32 #include "draw/draw_context.h"
33 #include "pipe/p_winsys.h"
34 #include "pipe/p_util.h"
35 #include "pipe/p_inlines.h"
36 #include "tgsi/util/tgsi_parse.h"
37
38 #include "i915_context.h"
39 #include "i915_reg.h"
40 #include "i915_state.h"
41 #include "i915_state_inlines.h"
42 #include "i915_fpc.h"
43
44 /* The i915 (and related graphics cores) do not support GL_CLAMP. The
45 * Intel drivers for "other operating systems" implement GL_CLAMP as
46 * GL_CLAMP_TO_EDGE, so the same is done here.
47 */
48 static unsigned
49 translate_wrap_mode(unsigned wrap)
50 {
51 switch (wrap) {
52 case PIPE_TEX_WRAP_REPEAT:
53 return TEXCOORDMODE_WRAP;
54 case PIPE_TEX_WRAP_CLAMP:
55 return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
56 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
57 return TEXCOORDMODE_CLAMP_EDGE;
58 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
59 return TEXCOORDMODE_CLAMP_BORDER;
60 // case PIPE_TEX_WRAP_MIRRORED_REPEAT:
61 // return TEXCOORDMODE_MIRROR;
62 default:
63 return TEXCOORDMODE_WRAP;
64 }
65 }
66
67 static unsigned translate_img_filter( unsigned filter )
68 {
69 switch (filter) {
70 case PIPE_TEX_FILTER_NEAREST:
71 return FILTER_NEAREST;
72 case PIPE_TEX_FILTER_LINEAR:
73 return FILTER_LINEAR;
74 case PIPE_TEX_FILTER_ANISO:
75 return FILTER_ANISOTROPIC;
76 default:
77 assert(0);
78 return FILTER_NEAREST;
79 }
80 }
81
82 static unsigned translate_mip_filter( unsigned filter )
83 {
84 switch (filter) {
85 case PIPE_TEX_MIPFILTER_NONE:
86 return MIPFILTER_NONE;
87 case PIPE_TEX_MIPFILTER_NEAREST:
88 return MIPFILTER_NEAREST;
89 case PIPE_TEX_MIPFILTER_LINEAR:
90 return MIPFILTER_LINEAR;
91 default:
92 assert(0);
93 return MIPFILTER_NONE;
94 }
95 }
96
97
98 /* None of this state is actually used for anything yet.
99 */
100 static void *
101 i915_create_blend_state(struct pipe_context *pipe,
102 const struct pipe_blend_state *blend)
103 {
104 struct i915_blend_state *cso_data = CALLOC_STRUCT( i915_blend_state );
105
106 {
107 unsigned eqRGB = blend->rgb_func;
108 unsigned srcRGB = blend->rgb_src_factor;
109 unsigned dstRGB = blend->rgb_dst_factor;
110
111 unsigned eqA = blend->alpha_func;
112 unsigned srcA = blend->alpha_src_factor;
113 unsigned dstA = blend->alpha_dst_factor;
114
115 /* Special handling for MIN/MAX filter modes handled at
116 * state_tracker level.
117 */
118
119 if (srcA != srcRGB ||
120 dstA != dstRGB ||
121 eqA != eqRGB) {
122
123 cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
124 IAB_MODIFY_ENABLE |
125 IAB_ENABLE |
126 IAB_MODIFY_FUNC |
127 IAB_MODIFY_SRC_FACTOR |
128 IAB_MODIFY_DST_FACTOR |
129 SRC_ABLND_FACT(i915_translate_blend_factor(srcA)) |
130 DST_ABLND_FACT(i915_translate_blend_factor(dstA)) |
131 (i915_translate_blend_func(eqA) << IAB_FUNC_SHIFT));
132 }
133 else {
134 cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
135 IAB_MODIFY_ENABLE |
136 0);
137 }
138 }
139
140 cso_data->modes4 |= (_3DSTATE_MODES_4_CMD |
141 ENABLE_LOGIC_OP_FUNC |
142 LOGIC_OP_FUNC(i915_translate_logic_op(blend->logicop_func)));
143
144 if (blend->logicop_enable)
145 cso_data->LIS5 |= S5_LOGICOP_ENABLE;
146
147 if (blend->dither)
148 cso_data->LIS5 |= S5_COLOR_DITHER_ENABLE;
149
150 if ((blend->colormask & PIPE_MASK_R) == 0)
151 cso_data->LIS5 |= S5_WRITEDISABLE_RED;
152
153 if ((blend->colormask & PIPE_MASK_G) == 0)
154 cso_data->LIS5 |= S5_WRITEDISABLE_GREEN;
155
156 if ((blend->colormask & PIPE_MASK_B) == 0)
157 cso_data->LIS5 |= S5_WRITEDISABLE_BLUE;
158
159 if ((blend->colormask & PIPE_MASK_A) == 0)
160 cso_data->LIS5 |= S5_WRITEDISABLE_ALPHA;
161
162 if (blend->blend_enable) {
163 unsigned funcRGB = blend->rgb_func;
164 unsigned srcRGB = blend->rgb_src_factor;
165 unsigned dstRGB = blend->rgb_dst_factor;
166
167 cso_data->LIS6 |= (S6_CBUF_BLEND_ENABLE |
168 SRC_BLND_FACT(i915_translate_blend_factor(srcRGB)) |
169 DST_BLND_FACT(i915_translate_blend_factor(dstRGB)) |
170 (i915_translate_blend_func(funcRGB) << S6_CBUF_BLEND_FUNC_SHIFT));
171 }
172
173 return cso_data;
174 }
175
176 static void i915_bind_blend_state(struct pipe_context *pipe,
177 void *blend)
178 {
179 struct i915_context *i915 = i915_context(pipe);
180 draw_flush(i915->draw);
181
182 i915->blend = (struct i915_blend_state*)blend;
183
184 i915->dirty |= I915_NEW_BLEND;
185 }
186
187
188 static void i915_delete_blend_state(struct pipe_context *pipe, void *blend)
189 {
190 FREE(blend);
191 }
192
193 static void i915_set_blend_color( struct pipe_context *pipe,
194 const struct pipe_blend_color *blend_color )
195 {
196 struct i915_context *i915 = i915_context(pipe);
197 draw_flush(i915->draw);
198
199 i915->blend_color = *blend_color;
200
201 i915->dirty |= I915_NEW_BLEND;
202 }
203
204 static void *
205 i915_create_sampler_state(struct pipe_context *pipe,
206 const struct pipe_sampler_state *sampler)
207 {
208 struct i915_sampler_state *cso = CALLOC_STRUCT( i915_sampler_state );
209 const unsigned ws = sampler->wrap_s;
210 const unsigned wt = sampler->wrap_t;
211 const unsigned wr = sampler->wrap_r;
212 unsigned minFilt, magFilt;
213 unsigned mipFilt;
214
215 cso->templ = sampler;
216
217 mipFilt = translate_mip_filter(sampler->min_mip_filter);
218 minFilt = translate_img_filter( sampler->min_img_filter );
219 magFilt = translate_img_filter( sampler->mag_img_filter );
220
221 if (sampler->max_anisotropy > 2.0) {
222 cso->state[0] |= SS2_MAX_ANISO_4;
223 }
224
225 {
226 int b = (int) (sampler->lod_bias * 16.0);
227 b = CLAMP(b, -256, 255);
228 cso->state[0] |= ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
229 }
230
231 /* Shadow:
232 */
233 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE)
234 {
235 cso->state[0] |= (SS2_SHADOW_ENABLE |
236 i915_translate_compare_func(sampler->compare_func));
237
238 minFilt = FILTER_4X4_FLAT;
239 magFilt = FILTER_4X4_FLAT;
240 }
241
242 cso->state[0] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
243 (mipFilt << SS2_MIP_FILTER_SHIFT) |
244 (magFilt << SS2_MAG_FILTER_SHIFT));
245
246 cso->state[1] |=
247 ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
248 (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
249 (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
250
251 if (sampler->normalized_coords)
252 cso->state[1] |= SS3_NORMALIZED_COORDS;
253
254 {
255 int minlod = (int) (16.0 * sampler->min_lod);
256 int maxlod = (int) (16.0 * sampler->max_lod);
257 minlod = CLAMP(minlod, 0, 16 * 11);
258 maxlod = CLAMP(maxlod, 0, 16 * 11);
259
260 if (minlod > maxlod)
261 maxlod = minlod;
262
263 cso->minlod = minlod;
264 cso->maxlod = maxlod;
265 }
266
267 {
268 ubyte r = float_to_ubyte(sampler->border_color[0]);
269 ubyte g = float_to_ubyte(sampler->border_color[1]);
270 ubyte b = float_to_ubyte(sampler->border_color[2]);
271 ubyte a = float_to_ubyte(sampler->border_color[3]);
272 cso->state[2] = I915PACKCOLOR8888(r, g, b, a);
273 }
274 return cso;
275 }
276
277 static void i915_bind_sampler_states(struct pipe_context *pipe,
278 unsigned num, void **sampler)
279 {
280 struct i915_context *i915 = i915_context(pipe);
281 unsigned i;
282
283 assert(num <= PIPE_MAX_SAMPLERS);
284
285 /* Check for no-op */
286 if (num == i915->num_samplers &&
287 !memcmp(i915->sampler, sampler, num * sizeof(void *)))
288 return;
289
290 draw_flush(i915->draw);
291
292 for (i = 0; i < num; ++i)
293 i915->sampler[i] = sampler[i];
294 for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
295 i915->sampler[i] = NULL;
296
297 i915->num_samplers = num;
298
299 i915->dirty |= I915_NEW_SAMPLER;
300 }
301
302 static void i915_delete_sampler_state(struct pipe_context *pipe,
303 void *sampler)
304 {
305 FREE(sampler);
306 }
307
308
309 /** XXX move someday? Or consolidate all these simple state setters
310 * into one file.
311 */
312
313 static void *
314 i915_create_depth_stencil_state(struct pipe_context *pipe,
315 const struct pipe_depth_stencil_alpha_state *depth_stencil)
316 {
317 struct i915_depth_stencil_state *cso = CALLOC_STRUCT( i915_depth_stencil_state );
318
319 {
320 int testmask = depth_stencil->stencil[0].value_mask & 0xff;
321 int writemask = depth_stencil->stencil[0].write_mask & 0xff;
322
323 cso->stencil_modes4 |= (_3DSTATE_MODES_4_CMD |
324 ENABLE_STENCIL_TEST_MASK |
325 STENCIL_TEST_MASK(testmask) |
326 ENABLE_STENCIL_WRITE_MASK |
327 STENCIL_WRITE_MASK(writemask));
328 }
329
330 if (depth_stencil->stencil[0].enabled) {
331 int test = i915_translate_compare_func(depth_stencil->stencil[0].func);
332 int fop = i915_translate_stencil_op(depth_stencil->stencil[0].fail_op);
333 int dfop = i915_translate_stencil_op(depth_stencil->stencil[0].zfail_op);
334 int dpop = i915_translate_stencil_op(depth_stencil->stencil[0].zpass_op);
335 int ref = depth_stencil->stencil[0].ref_value & 0xff;
336
337 cso->stencil_LIS5 |= (S5_STENCIL_TEST_ENABLE |
338 S5_STENCIL_WRITE_ENABLE |
339 (ref << S5_STENCIL_REF_SHIFT) |
340 (test << S5_STENCIL_TEST_FUNC_SHIFT) |
341 (fop << S5_STENCIL_FAIL_SHIFT) |
342 (dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
343 (dpop << S5_STENCIL_PASS_Z_PASS_SHIFT));
344 }
345
346 if (depth_stencil->stencil[1].enabled) {
347 int test = i915_translate_compare_func(depth_stencil->stencil[1].func);
348 int fop = i915_translate_stencil_op(depth_stencil->stencil[1].fail_op);
349 int dfop = i915_translate_stencil_op(depth_stencil->stencil[1].zfail_op);
350 int dpop = i915_translate_stencil_op(depth_stencil->stencil[1].zpass_op);
351 int ref = depth_stencil->stencil[1].ref_value & 0xff;
352 int tmask = depth_stencil->stencil[1].value_mask & 0xff;
353 int wmask = depth_stencil->stencil[1].write_mask & 0xff;
354
355 cso->bfo[0] = (_3DSTATE_BACKFACE_STENCIL_OPS |
356 BFO_ENABLE_STENCIL_FUNCS |
357 BFO_ENABLE_STENCIL_TWO_SIDE |
358 BFO_ENABLE_STENCIL_REF |
359 BFO_STENCIL_TWO_SIDE |
360 (ref << BFO_STENCIL_REF_SHIFT) |
361 (test << BFO_STENCIL_TEST_SHIFT) |
362 (fop << BFO_STENCIL_FAIL_SHIFT) |
363 (dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
364 (dpop << BFO_STENCIL_PASS_Z_PASS_SHIFT));
365
366 cso->bfo[1] = (_3DSTATE_BACKFACE_STENCIL_MASKS |
367 BFM_ENABLE_STENCIL_TEST_MASK |
368 BFM_ENABLE_STENCIL_WRITE_MASK |
369 (tmask << BFM_STENCIL_TEST_MASK_SHIFT) |
370 (wmask << BFM_STENCIL_WRITE_MASK_SHIFT));
371 }
372 else {
373 /* This actually disables two-side stencil: The bit set is a
374 * modify-enable bit to indicate we are changing the two-side
375 * setting. Then there is a symbolic zero to show that we are
376 * setting the flag to zero/off.
377 */
378 cso->bfo[0] = (_3DSTATE_BACKFACE_STENCIL_OPS |
379 BFO_ENABLE_STENCIL_TWO_SIDE |
380 0);
381 cso->bfo[1] = 0;
382 }
383
384 if (depth_stencil->depth.enabled) {
385 int func = i915_translate_compare_func(depth_stencil->depth.func);
386
387 cso->depth_LIS6 |= (S6_DEPTH_TEST_ENABLE |
388 (func << S6_DEPTH_TEST_FUNC_SHIFT));
389
390 if (depth_stencil->depth.writemask)
391 cso->depth_LIS6 |= S6_DEPTH_WRITE_ENABLE;
392 }
393
394 if (depth_stencil->alpha.enabled) {
395 int test = i915_translate_compare_func(depth_stencil->alpha.func);
396 ubyte refByte = float_to_ubyte(depth_stencil->alpha.ref);
397
398 cso->depth_LIS6 |= (S6_ALPHA_TEST_ENABLE |
399 (test << S6_ALPHA_TEST_FUNC_SHIFT) |
400 (((unsigned) refByte) << S6_ALPHA_REF_SHIFT));
401 }
402
403 return cso;
404 }
405
406 static void i915_bind_depth_stencil_state(struct pipe_context *pipe,
407 void *depth_stencil)
408 {
409 struct i915_context *i915 = i915_context(pipe);
410 draw_flush(i915->draw);
411
412 i915->depth_stencil = (const struct i915_depth_stencil_state *)depth_stencil;
413
414 i915->dirty |= I915_NEW_DEPTH_STENCIL;
415 }
416
417 static void i915_delete_depth_stencil_state(struct pipe_context *pipe,
418 void *depth_stencil)
419 {
420 FREE(depth_stencil);
421 }
422
423
424 static void i915_set_scissor_state( struct pipe_context *pipe,
425 const struct pipe_scissor_state *scissor )
426 {
427 struct i915_context *i915 = i915_context(pipe);
428 draw_flush(i915->draw);
429
430 memcpy( &i915->scissor, scissor, sizeof(*scissor) );
431 i915->dirty |= I915_NEW_SCISSOR;
432 }
433
434
435 static void i915_set_polygon_stipple( struct pipe_context *pipe,
436 const struct pipe_poly_stipple *stipple )
437 {
438 }
439
440
441
442 static void *
443 i915_create_fs_state(struct pipe_context *pipe,
444 const struct pipe_shader_state *templ)
445 {
446 struct i915_context *i915 = i915_context(pipe);
447 struct i915_fragment_shader *ifs = CALLOC_STRUCT(i915_fragment_shader);
448 if (!ifs)
449 return NULL;
450
451 ifs->state.tokens = tgsi_dup_tokens(templ->tokens);
452
453 tgsi_scan_shader(templ->tokens, &ifs->info);
454
455 /* The shader's compiled to i915 instructions here */
456 i915_translate_fragment_program(i915, ifs);
457
458 return ifs;
459 }
460
461 static void
462 i915_bind_fs_state(struct pipe_context *pipe, void *shader)
463 {
464 struct i915_context *i915 = i915_context(pipe);
465 draw_flush(i915->draw);
466
467 i915->fs = (struct i915_fragment_shader*) shader;
468
469 i915->dirty |= I915_NEW_FS;
470 }
471
472 static
473 void i915_delete_fs_state(struct pipe_context *pipe, void *shader)
474 {
475 struct i915_fragment_shader *ifs = (struct i915_fragment_shader *) shader;
476
477 if (ifs->program)
478 FREE(ifs->program);
479 ifs->program_len = 0;
480
481 FREE((struct tgsi_token *)ifs->state.tokens);
482
483 FREE(ifs);
484 }
485
486
487 static void *
488 i915_create_vs_state(struct pipe_context *pipe,
489 const struct pipe_shader_state *templ)
490 {
491 struct i915_context *i915 = i915_context(pipe);
492
493 /* just pass-through to draw module */
494 return draw_create_vertex_shader(i915->draw, templ);
495 }
496
497 static void i915_bind_vs_state(struct pipe_context *pipe, void *shader)
498 {
499 struct i915_context *i915 = i915_context(pipe);
500
501 /* just pass-through to draw module */
502 draw_bind_vertex_shader(i915->draw, (struct draw_vertex_shader *) shader);
503
504 i915->dirty |= I915_NEW_VS;
505 }
506
507 static void i915_delete_vs_state(struct pipe_context *pipe, void *shader)
508 {
509 struct i915_context *i915 = i915_context(pipe);
510
511 /* just pass-through to draw module */
512 draw_delete_vertex_shader(i915->draw, (struct draw_vertex_shader *) shader);
513 }
514
515 static void i915_set_constant_buffer(struct pipe_context *pipe,
516 uint shader, uint index,
517 const struct pipe_constant_buffer *buf)
518 {
519 struct i915_context *i915 = i915_context(pipe);
520 struct pipe_winsys *ws = pipe->winsys;
521 draw_flush(i915->draw);
522
523 assert(shader < PIPE_SHADER_TYPES);
524 assert(index == 0);
525
526 /* Make a copy of shader constants.
527 * During fragment program translation we may add additional
528 * constants to the array.
529 *
530 * We want to consider the situation where some user constants
531 * (ex: a material color) may change frequently but the shader program
532 * stays the same. In that case we should only be updating the first
533 * N constants, leaving any extras from shader translation alone.
534 */
535 if (buf) {
536 void *mapped;
537 if (buf->size &&
538 (mapped = ws->buffer_map(ws, buf->buffer,
539 PIPE_BUFFER_USAGE_CPU_READ))) {
540 memcpy(i915->current.constants[shader], mapped, buf->size);
541 ws->buffer_unmap(ws, buf->buffer);
542 i915->current.num_user_constants[shader]
543 = buf->size / (4 * sizeof(float));
544 }
545 else {
546 i915->current.num_user_constants[shader] = 0;
547 }
548 }
549
550 i915->dirty |= I915_NEW_CONSTANTS;
551 }
552
553
554 static void i915_set_sampler_textures(struct pipe_context *pipe,
555 unsigned num,
556 struct pipe_texture **texture)
557 {
558 struct i915_context *i915 = i915_context(pipe);
559 uint i;
560
561 assert(num <= PIPE_MAX_SAMPLERS);
562
563 /* Check for no-op */
564 if (num == i915->num_textures &&
565 !memcmp(i915->texture, texture, num * sizeof(struct pipe_texture *)))
566 return;
567
568 /* Fixes wrong texture in texobj with VBUF */
569 draw_flush(i915->draw);
570
571 for (i = 0; i < num; i++)
572 pipe_texture_reference((struct pipe_texture **) &i915->texture[i],
573 texture[i]);
574
575 for (i = num; i < i915->num_textures; i++)
576 pipe_texture_reference((struct pipe_texture **) &i915->texture[i],
577 NULL);
578
579 i915->num_textures = num;
580
581 i915->dirty |= I915_NEW_TEXTURE;
582 }
583
584
585
586 static void i915_set_framebuffer_state(struct pipe_context *pipe,
587 const struct pipe_framebuffer_state *fb)
588 {
589 struct i915_context *i915 = i915_context(pipe);
590 draw_flush(i915->draw);
591
592 i915->framebuffer = *fb; /* struct copy */
593
594 i915->dirty |= I915_NEW_FRAMEBUFFER;
595 }
596
597
598
599 static void i915_set_clip_state( struct pipe_context *pipe,
600 const struct pipe_clip_state *clip )
601 {
602 struct i915_context *i915 = i915_context(pipe);
603 draw_flush(i915->draw);
604
605 draw_set_clip_state(i915->draw, clip);
606
607 i915->dirty |= I915_NEW_CLIP;
608 }
609
610
611
612 /* Called when driver state tracker notices changes to the viewport
613 * matrix:
614 */
615 static void i915_set_viewport_state( struct pipe_context *pipe,
616 const struct pipe_viewport_state *viewport )
617 {
618 struct i915_context *i915 = i915_context(pipe);
619
620 i915->viewport = *viewport; /* struct copy */
621
622 /* pass the viewport info to the draw module */
623 draw_set_viewport_state(i915->draw, &i915->viewport);
624
625 i915->dirty |= I915_NEW_VIEWPORT;
626 }
627
628
629 static void *
630 i915_create_rasterizer_state(struct pipe_context *pipe,
631 const struct pipe_rasterizer_state *rasterizer)
632 {
633 struct i915_rasterizer_state *cso = CALLOC_STRUCT( i915_rasterizer_state );
634
635 cso->templ = rasterizer;
636 cso->color_interp = rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
637 cso->light_twoside = rasterizer->light_twoside;
638 cso->ds[0].u = _3DSTATE_DEPTH_OFFSET_SCALE;
639 cso->ds[1].f = rasterizer->offset_scale;
640 if (rasterizer->poly_stipple_enable) {
641 cso->st |= ST1_ENABLE;
642 }
643
644 if (rasterizer->scissor)
645 cso->sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT;
646 else
647 cso->sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT;
648
649 switch (rasterizer->cull_mode) {
650 case PIPE_WINDING_NONE:
651 cso->LIS4 |= S4_CULLMODE_NONE;
652 break;
653 case PIPE_WINDING_CW:
654 cso->LIS4 |= S4_CULLMODE_CW;
655 break;
656 case PIPE_WINDING_CCW:
657 cso->LIS4 |= S4_CULLMODE_CCW;
658 break;
659 case PIPE_WINDING_BOTH:
660 cso->LIS4 |= S4_CULLMODE_BOTH;
661 break;
662 }
663
664 {
665 int line_width = CLAMP((int)(rasterizer->line_width * 2), 1, 0xf);
666
667 cso->LIS4 |= line_width << S4_LINE_WIDTH_SHIFT;
668
669 if (rasterizer->line_smooth)
670 cso->LIS4 |= S4_LINE_ANTIALIAS_ENABLE;
671 }
672
673 {
674 int point_size = CLAMP((int) rasterizer->point_size, 1, 0xff);
675
676 cso->LIS4 |= point_size << S4_POINT_WIDTH_SHIFT;
677 }
678
679 if (rasterizer->flatshade) {
680 cso->LIS4 |= (S4_FLATSHADE_ALPHA |
681 S4_FLATSHADE_COLOR |
682 S4_FLATSHADE_SPECULAR);
683 }
684
685 cso->LIS7 = fui( rasterizer->offset_units );
686
687
688 return cso;
689 }
690
691 static void i915_bind_rasterizer_state( struct pipe_context *pipe,
692 void *raster )
693 {
694 struct i915_context *i915 = i915_context(pipe);
695
696 i915->rasterizer = (struct i915_rasterizer_state *)raster;
697
698 /* pass-through to draw module */
699 draw_set_rasterizer_state(i915->draw,
700 (i915->rasterizer ? i915->rasterizer->templ : NULL));
701
702 i915->dirty |= I915_NEW_RASTERIZER;
703 }
704
705 static void i915_delete_rasterizer_state(struct pipe_context *pipe,
706 void *raster)
707 {
708 FREE(raster);
709 }
710
711 static void i915_set_vertex_buffers(struct pipe_context *pipe,
712 unsigned count,
713 const struct pipe_vertex_buffer *buffers)
714 {
715 struct i915_context *i915 = i915_context(pipe);
716 /* Because we change state before the draw_set_vertex_buffers call
717 * we need a flush here, just to be sure.
718 */
719 draw_flush(i915->draw);
720
721 memcpy(i915->vertex_buffer, buffers, count * sizeof(buffers[0]));
722 i915->num_vertex_buffers = count;
723
724 /* pass-through to draw module */
725 draw_set_vertex_buffers(i915->draw, count, buffers);
726 }
727
728 static void i915_set_vertex_elements(struct pipe_context *pipe,
729 unsigned count,
730 const struct pipe_vertex_element *elements)
731 {
732 struct i915_context *i915 = i915_context(pipe);
733 /* Because we change state before the draw_set_vertex_buffers call
734 * we need a flush here, just to be sure.
735 */
736 draw_flush(i915->draw);
737
738 i915->num_vertex_elements = count;
739 /* pass-through to draw module */
740 draw_set_vertex_elements(i915->draw, count, elements);
741 }
742
743
744 static void i915_set_edgeflags(struct pipe_context *pipe,
745 const unsigned *bitfield)
746 {
747 /* TODO do something here */
748 }
749
750 void
751 i915_init_state_functions( struct i915_context *i915 )
752 {
753 i915->pipe.set_edgeflags = i915_set_edgeflags;
754 i915->pipe.create_blend_state = i915_create_blend_state;
755 i915->pipe.bind_blend_state = i915_bind_blend_state;
756 i915->pipe.delete_blend_state = i915_delete_blend_state;
757
758 i915->pipe.create_sampler_state = i915_create_sampler_state;
759 i915->pipe.bind_sampler_states = i915_bind_sampler_states;
760 i915->pipe.delete_sampler_state = i915_delete_sampler_state;
761
762 i915->pipe.create_depth_stencil_alpha_state = i915_create_depth_stencil_state;
763 i915->pipe.bind_depth_stencil_alpha_state = i915_bind_depth_stencil_state;
764 i915->pipe.delete_depth_stencil_alpha_state = i915_delete_depth_stencil_state;
765
766 i915->pipe.create_rasterizer_state = i915_create_rasterizer_state;
767 i915->pipe.bind_rasterizer_state = i915_bind_rasterizer_state;
768 i915->pipe.delete_rasterizer_state = i915_delete_rasterizer_state;
769 i915->pipe.create_fs_state = i915_create_fs_state;
770 i915->pipe.bind_fs_state = i915_bind_fs_state;
771 i915->pipe.delete_fs_state = i915_delete_fs_state;
772 i915->pipe.create_vs_state = i915_create_vs_state;
773 i915->pipe.bind_vs_state = i915_bind_vs_state;
774 i915->pipe.delete_vs_state = i915_delete_vs_state;
775
776 i915->pipe.set_blend_color = i915_set_blend_color;
777 i915->pipe.set_clip_state = i915_set_clip_state;
778 i915->pipe.set_constant_buffer = i915_set_constant_buffer;
779 i915->pipe.set_framebuffer_state = i915_set_framebuffer_state;
780
781 i915->pipe.set_polygon_stipple = i915_set_polygon_stipple;
782 i915->pipe.set_scissor_state = i915_set_scissor_state;
783 i915->pipe.set_sampler_textures = i915_set_sampler_textures;
784 i915->pipe.set_viewport_state = i915_set_viewport_state;
785 i915->pipe.set_vertex_buffers = i915_set_vertex_buffers;
786 i915->pipe.set_vertex_elements = i915_set_vertex_elements;
787 }