Merge branch 'lp-offset-twoside'
[mesa.git] / src / mesa / drivers / dri / nouveau / nv04_state_raster.c
1 /*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include "nouveau_driver.h"
28 #include "nouveau_context.h"
29 #include "nouveau_util.h"
30 #include "nv_object.xml.h"
31 #include "nv04_3d.xml.h"
32 #include "nv04_driver.h"
33
34 static unsigned
35 get_comparison_op(unsigned op)
36 {
37 switch (op) {
38 case GL_NEVER:
39 return 0x1;
40 case GL_LESS:
41 return 0x2;
42 case GL_EQUAL:
43 return 0x3;
44 case GL_LEQUAL:
45 return 0x4;
46 case GL_GREATER:
47 return 0x5;
48 case GL_NOTEQUAL:
49 return 0x6;
50 case GL_GEQUAL:
51 return 0x7;
52 case GL_ALWAYS:
53 return 0x8;
54 default:
55 assert(0);
56 }
57 }
58
59 static unsigned
60 get_stencil_op(unsigned op)
61 {
62 switch (op) {
63 case GL_KEEP:
64 return 0x1;
65 case GL_ZERO:
66 return 0x2;
67 case GL_REPLACE:
68 return 0x3;
69 case GL_INCR:
70 return 0x4;
71 case GL_DECR:
72 return 0x5;
73 case GL_INVERT:
74 return 0x6;
75 case GL_INCR_WRAP:
76 return 0x7;
77 case GL_DECR_WRAP:
78 return 0x8;
79 default:
80 assert(0);
81 }
82 }
83
84 static unsigned
85 get_texenv_mode(unsigned mode)
86 {
87 switch (mode) {
88 case GL_REPLACE:
89 return 0x1;
90 case GL_DECAL:
91 return 0x3;
92 case GL_MODULATE:
93 return 0x4;
94 default:
95 assert(0);
96 }
97 }
98
99 static unsigned
100 get_blend_func(unsigned func)
101 {
102 switch (func) {
103 case GL_ZERO:
104 return 0x1;
105 case GL_ONE:
106 return 0x2;
107 case GL_SRC_COLOR:
108 return 0x3;
109 case GL_ONE_MINUS_SRC_COLOR:
110 return 0x4;
111 case GL_SRC_ALPHA:
112 return 0x5;
113 case GL_ONE_MINUS_SRC_ALPHA:
114 return 0x6;
115 case GL_DST_ALPHA:
116 return 0x7;
117 case GL_ONE_MINUS_DST_ALPHA:
118 return 0x8;
119 case GL_DST_COLOR:
120 return 0x9;
121 case GL_ONE_MINUS_DST_COLOR:
122 return 0xa;
123 case GL_SRC_ALPHA_SATURATE:
124 return 0xb;
125 default:
126 assert(0);
127 }
128 }
129
130 void
131 nv04_defer_control(struct gl_context *ctx, int emit)
132 {
133 context_dirty(ctx, CONTROL);
134 }
135
136 void
137 nv04_emit_control(struct gl_context *ctx, int emit)
138 {
139 struct nouveau_channel *chan = context_chan(ctx);
140 struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
141
142 if (nv04_mtex_engine(fahrenheit)) {
143 int cull_mode = ctx->Polygon.CullFaceMode;
144 int front_face = ctx->Polygon.FrontFace;
145 uint32_t ctrl0 = 1 << 30 |
146 NV04_MULTITEX_TRIANGLE_CONTROL0_ORIGIN_CORNER;
147 uint32_t ctrl1 = 0, ctrl2 = 0;
148
149 /* Color mask. */
150 if (ctx->Color.ColorMask[0][RCOMP])
151 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE;
152 if (ctx->Color.ColorMask[0][GCOMP])
153 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE;
154 if (ctx->Color.ColorMask[0][BCOMP])
155 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE;
156 if (ctx->Color.ColorMask[0][ACOMP])
157 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE;
158
159 /* Dithering. */
160 if (ctx->Color.DitherFlag)
161 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_DITHER_ENABLE;
162
163 /* Cull mode. */
164 if (!ctx->Polygon.CullFlag)
165 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_NONE;
166 else if (cull_mode == GL_FRONT_AND_BACK)
167 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_BOTH;
168 else
169 ctrl0 |= (cull_mode == GL_FRONT) ^ (front_face == GL_CCW) ?
170 NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CW :
171 NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CCW;
172
173 /* Depth test. */
174 if (ctx->Depth.Test)
175 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE;
176
177 if (ctx->Depth.Mask)
178 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_Z_WRITE;
179
180 ctrl0 |= get_comparison_op(ctx->Depth.Func) << 16;
181
182 /* Alpha test. */
183 if (ctx->Color.AlphaEnabled)
184 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_ENABLE;
185
186 ctrl0 |= get_comparison_op(ctx->Color.AlphaFunc) << 8 |
187 FLOAT_TO_UBYTE(ctx->Color.AlphaRef);
188
189 /* Stencil test. */
190 if (ctx->Stencil.WriteMask[0])
191 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE;
192
193 if (ctx->Stencil.Enabled)
194 ctrl1 |= NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE;
195
196 ctrl1 |= get_comparison_op(ctx->Stencil.Function[0]) << 4 |
197 ctx->Stencil.Ref[0] << 8 |
198 ctx->Stencil.ValueMask[0] << 16 |
199 ctx->Stencil.WriteMask[0] << 24;
200
201 ctrl2 |= get_stencil_op(ctx->Stencil.ZPassFunc[0]) << 8 |
202 get_stencil_op(ctx->Stencil.ZFailFunc[0]) << 4 |
203 get_stencil_op(ctx->Stencil.FailFunc[0]);
204
205 BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_CONTROL0, 3);
206 OUT_RING(chan, ctrl0);
207 OUT_RING(chan, ctrl1);
208 OUT_RING(chan, ctrl2);
209
210 } else {
211 int cull_mode = ctx->Polygon.CullFaceMode;
212 int front_face = ctx->Polygon.FrontFace;
213 uint32_t ctrl = 1 << 30 |
214 NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN_CORNER;
215
216 /* Dithering. */
217 if (ctx->Color.DitherFlag)
218 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE;
219
220 /* Cull mode. */
221 if (!ctx->Polygon.CullFlag)
222 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_NONE;
223 else if (cull_mode == GL_FRONT_AND_BACK)
224 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_BOTH;
225 else
226 ctrl |= (cull_mode == GL_FRONT) ^ (front_face == GL_CCW) ?
227 NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CW :
228 NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CCW;
229
230 /* Depth test. */
231 if (ctx->Depth.Test)
232 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE;
233 if (ctx->Depth.Mask)
234 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE;
235
236 ctrl |= get_comparison_op(ctx->Depth.Func) << 16;
237
238 /* Alpha test. */
239 if (ctx->Color.AlphaEnabled)
240 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE;
241
242 ctrl |= get_comparison_op(ctx->Color.AlphaFunc) << 8 |
243 FLOAT_TO_UBYTE(ctx->Color.AlphaRef);
244
245 BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_CONTROL, 1);
246 OUT_RING(chan, ctrl);
247 }
248 }
249
250 void
251 nv04_defer_blend(struct gl_context *ctx, int emit)
252 {
253 context_dirty(ctx, BLEND);
254 }
255
256 void
257 nv04_emit_blend(struct gl_context *ctx, int emit)
258 {
259 struct nouveau_channel *chan = context_chan(ctx);
260 struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
261
262 if (nv04_mtex_engine(fahrenheit)) {
263 uint32_t blend = 0x2 << 4 |
264 NV04_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE;
265
266 /* Alpha blending. */
267 blend |= get_blend_func(ctx->Color.BlendDstRGB) << 28 |
268 get_blend_func(ctx->Color.BlendSrcRGB) << 24;
269
270 if (ctx->Color.BlendEnabled)
271 blend |= NV04_MULTITEX_TRIANGLE_BLEND_BLEND_ENABLE;
272
273 /* Shade model. */
274 if (ctx->Light.ShadeModel == GL_SMOOTH)
275 blend |= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
276 else
277 blend |= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_FLAT;
278
279 /* Secondary color */
280 if (NEED_SECONDARY_COLOR(ctx))
281 blend |= NV04_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE;
282
283 /* Fog. */
284 if (ctx->Fog.Enabled)
285 blend |= NV04_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE;
286
287 BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_BLEND, 1);
288 OUT_RING(chan, blend);
289
290 BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_FOGCOLOR, 1);
291 OUT_RING(chan, pack_rgba_f(MESA_FORMAT_ARGB8888,
292 ctx->Fog.Color));
293
294 } else {
295 uint32_t blend = 0x2 << 4 |
296 NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE;
297
298 /* Alpha blending. */
299 blend |= get_blend_func(ctx->Color.BlendDstRGB) << 28 |
300 get_blend_func(ctx->Color.BlendSrcRGB) << 24;
301
302 if (ctx->Color.BlendEnabled)
303 blend |= NV04_TEXTURED_TRIANGLE_BLEND_BLEND_ENABLE;
304
305 /* Shade model. */
306 if (ctx->Light.ShadeModel == GL_SMOOTH)
307 blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
308 else
309 blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT;
310
311 /* Texture environment. */
312 if (ctx->Texture._EnabledUnits)
313 blend |= get_texenv_mode(ctx->Texture.Unit[0].EnvMode);
314 else
315 blend |= get_texenv_mode(GL_MODULATE);
316
317 /* Secondary color */
318 if (NEED_SECONDARY_COLOR(ctx))
319 blend |= NV04_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE;
320
321 /* Fog. */
322 if (ctx->Fog.Enabled)
323 blend |= NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE;
324
325 BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_BLEND, 1);
326 OUT_RING(chan, blend);
327
328 BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_FOGCOLOR, 1);
329 OUT_RING(chan, pack_rgba_f(MESA_FORMAT_ARGB8888,
330 ctx->Fog.Color));
331 }
332 }