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
34static unsigned
35get_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
59static unsigned
60get_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
84static unsigned
85get_blend_func(unsigned func)
86{
87	switch (func) {
88	case GL_ZERO:
89		return 0x1;
90	case GL_ONE:
91		return 0x2;
92	case GL_SRC_COLOR:
93		return 0x3;
94	case GL_ONE_MINUS_SRC_COLOR:
95		return 0x4;
96	case GL_SRC_ALPHA:
97		return 0x5;
98	case GL_ONE_MINUS_SRC_ALPHA:
99		return 0x6;
100	case GL_DST_ALPHA:
101		return 0x7;
102	case GL_ONE_MINUS_DST_ALPHA:
103		return 0x8;
104	case GL_DST_COLOR:
105		return 0x9;
106	case GL_ONE_MINUS_DST_COLOR:
107		return 0xa;
108	case GL_SRC_ALPHA_SATURATE:
109		return 0xb;
110	default:
111		assert(0);
112	}
113}
114
115void
116nv04_defer_control(struct gl_context *ctx, int emit)
117{
118	context_dirty(ctx, CONTROL);
119}
120
121void
122nv04_emit_control(struct gl_context *ctx, int emit)
123{
124	struct nv04_context *nv04 = to_nv04_context(ctx);
125	int cull = ctx->Polygon.CullFaceMode;
126	int front = ctx->Polygon.FrontFace;
127
128	nv04->ctrl[0] = NV04_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_FIXED |
129			NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN_CORNER;
130	nv04->ctrl[1] = 0;
131	nv04->ctrl[2] = 0;
132
133	/* Dithering. */
134	if (ctx->Color.DitherFlag)
135		nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE;
136
137	/* Cull mode. */
138	if (!ctx->Polygon.CullFlag)
139		nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_NONE;
140	else if (cull == GL_FRONT_AND_BACK)
141		nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_BOTH;
142	else
143		nv04->ctrl[0] |= (cull == GL_FRONT) ^ (front == GL_CCW) ?
144				 NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CW :
145				 NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CCW;
146
147	/* Depth test. */
148	if (ctx->Depth.Test)
149		nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE;
150	if (ctx->Depth.Mask)
151		nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE;
152
153	nv04->ctrl[0] |= get_comparison_op(ctx->Depth.Func) << 16;
154
155	/* Alpha test. */
156	if (ctx->Color.AlphaEnabled)
157		nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE;
158
159	nv04->ctrl[0] |= get_comparison_op(ctx->Color.AlphaFunc) << 8 |
160			 FLOAT_TO_UBYTE(ctx->Color.AlphaRef);
161
162	/* Color mask. */
163	if (ctx->Color.ColorMask[0][RCOMP])
164		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE;
165	if (ctx->Color.ColorMask[0][GCOMP])
166		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE;
167	if (ctx->Color.ColorMask[0][BCOMP])
168		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE;
169	if (ctx->Color.ColorMask[0][ACOMP])
170		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE;
171
172	/* Stencil test. */
173	if (ctx->Stencil.WriteMask[0])
174		nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE;
175
176	if (ctx->Stencil.Enabled)
177		nv04->ctrl[1] |= NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE;
178
179	nv04->ctrl[1] |= get_comparison_op(ctx->Stencil.Function[0]) << 4 |
180			 ctx->Stencil.Ref[0] << 8 |
181			 ctx->Stencil.ValueMask[0] << 16 |
182			 ctx->Stencil.WriteMask[0] << 24;
183
184	nv04->ctrl[2] |= get_stencil_op(ctx->Stencil.ZPassFunc[0]) << 8 |
185			 get_stencil_op(ctx->Stencil.ZFailFunc[0]) << 4 |
186			 get_stencil_op(ctx->Stencil.FailFunc[0]);
187}
188
189void
190nv04_defer_blend(struct gl_context *ctx, int emit)
191{
192	context_dirty(ctx, BLEND);
193}
194
195void
196nv04_emit_blend(struct gl_context *ctx, int emit)
197{
198	struct nv04_context *nv04 = to_nv04_context(ctx);
199
200	nv04->blend &= NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP__MASK;
201	nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_MASK_BIT_MSB |
202		       NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE;
203
204	/* Alpha blending. */
205	nv04->blend |= get_blend_func(ctx->Color.Blend[0].DstRGB) << 28 |
206		       get_blend_func(ctx->Color.Blend[0].SrcRGB) << 24;
207
208	if (ctx->Color.BlendEnabled)
209		nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_BLEND_ENABLE;
210
211	/* Shade model. */
212	if (ctx->Light.ShadeModel == GL_SMOOTH)
213		nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
214	else
215		nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT;
216
217	/* Secondary color */
218	if (_mesa_need_secondary_color(ctx))
219		nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE;
220
221	/* Fog. */
222	if (ctx->Fog.Enabled) {
223		nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE;
224		nv04->fog = pack_rgba_f(MESA_FORMAT_ARGB8888, ctx->Fog.Color);
225	}
226}
227