1fda9279dSmrg/*
2fda9279dSmrg * Copyright 2007 Stephane Marchesin
3fda9279dSmrg * Copyright 2007 Arthur Huillet
4fda9279dSmrg * Copyright 2007 Peter Winters
5fda9279dSmrg * Copyright 2009 Francisco Jerez
6fda9279dSmrg *
7fda9279dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
8fda9279dSmrg * copy of this software and associated documentation files (the "Software"),
9fda9279dSmrg * to deal in the Software without restriction, including without limitation
10fda9279dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11fda9279dSmrg * and/or sell copies of the Software, and to permit persons to whom the
12fda9279dSmrg * Software is furnished to do so, subject to the following conditions:
13fda9279dSmrg *
14fda9279dSmrg * The above copyright notice and this permission notice shall be included in
15fda9279dSmrg * all copies or substantial portions of the Software.
16fda9279dSmrg *
17fda9279dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18fda9279dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19fda9279dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20fda9279dSmrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21fda9279dSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22fda9279dSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23fda9279dSmrg * SOFTWARE.
24fda9279dSmrg */
25fda9279dSmrg
26fda9279dSmrg#ifdef HAVE_CONFIG_H
27fda9279dSmrg#include "config.h"
28fda9279dSmrg#endif
29fda9279dSmrg
30fda9279dSmrg#include "nv_include.h"
31fda9279dSmrg
32fda9279dSmrg#include "hwdefs/nv_object.xml.h"
33fda9279dSmrg#include "hwdefs/nv10_3d.xml.h"
34fda9279dSmrg#include "nv04_accel.h"
35fda9279dSmrg
36fda9279dSmrg/* Texture/Render target formats. */
37fda9279dSmrgstatic struct pict_format {
38fda9279dSmrg	int exa;
39fda9279dSmrg	int hw;
40fda9279dSmrg} nv10_tex_format_pot[] = {
41fda9279dSmrg	{ PICT_a8,       0x80  },
42fda9279dSmrg	{ PICT_r5g6b5,	 0x280 },
43fda9279dSmrg	{ PICT_x8r8g8b8, 0x300 },
44fda9279dSmrg	{ PICT_a8r8g8b8, 0x300 },
45fda9279dSmrg	{},
46fda9279dSmrg
47fda9279dSmrg}, nv10_tex_format_rect[] = {
48fda9279dSmrg	{ PICT_a8,       0x980 },
49fda9279dSmrg	{ PICT_r5g6b5,   0x880 },
50fda9279dSmrg	{ PICT_x8r8g8b8, 0x900 },
51fda9279dSmrg	{ PICT_a8r8g8b8, 0x900 },
52fda9279dSmrg	{},
53fda9279dSmrg
54fda9279dSmrg}, nv20_tex_format_rect[] = {
55fda9279dSmrg	{ PICT_a8,	 0xd80 },
56fda9279dSmrg	{ PICT_r5g6b5,   0x880 },
57fda9279dSmrg	{ PICT_x8r8g8b8, 0x900 },
58fda9279dSmrg	{ PICT_a8r8g8b8, 0x900 },
59fda9279dSmrg	{},
60fda9279dSmrg
61fda9279dSmrg}, nv10_rt_format[] = {
62fda9279dSmrg	{ PICT_r5g6b5,	 0x103 },
63fda9279dSmrg	{ PICT_x8r8g8b8, 0x108 },
64fda9279dSmrg	{ PICT_a8r8g8b8, 0x108 },
65fda9279dSmrg	{},
66fda9279dSmrg};
67fda9279dSmrg
68fda9279dSmrgstatic int
69fda9279dSmrgget_tex_format(NVPtr pNv, PicturePtr pict)
70fda9279dSmrg{
71fda9279dSmrg	/* If repeat is set we're always handling a 1x1 texture with
72fda9279dSmrg	 * ARGB/XRGB destination, in that case we change the format to
73fda9279dSmrg	 * use the POT (swizzled) matching format.
74fda9279dSmrg	 */
75fda9279dSmrg	struct pict_format *format =
76fda9279dSmrg		pict->repeat != RepeatNone ? nv10_tex_format_pot :
77fda9279dSmrg		pNv->Architecture == NV_ARCH_20 ? nv20_tex_format_rect :
78fda9279dSmrg		nv10_tex_format_rect;
79fda9279dSmrg
80fda9279dSmrg	for (; format->hw; format++) {
81fda9279dSmrg		if (format->exa == pict->format)
82fda9279dSmrg			return format->hw;
83fda9279dSmrg	}
84fda9279dSmrg
85fda9279dSmrg	return 0;
86fda9279dSmrg}
87fda9279dSmrg
88fda9279dSmrgstatic int
89fda9279dSmrgget_rt_format(PicturePtr pict)
90fda9279dSmrg{
91fda9279dSmrg	struct pict_format *format = nv10_rt_format;
92fda9279dSmrg
93fda9279dSmrg	for (; format->hw; format++) {
94fda9279dSmrg		if (format->exa == pict->format)
95fda9279dSmrg			return format->hw;
96fda9279dSmrg	}
97fda9279dSmrg
98fda9279dSmrg	return 0;
99fda9279dSmrg}
100fda9279dSmrg
101fda9279dSmrg/* Blending functions. */
102fda9279dSmrg#define SF(x) NV10_3D_BLEND_FUNC_SRC_##x
103fda9279dSmrg#define DF(x) NV10_3D_BLEND_FUNC_DST_##x
104fda9279dSmrg
105fda9279dSmrgstatic struct pict_op {
106fda9279dSmrg	int src;
107fda9279dSmrg	int dst;
108fda9279dSmrg
109fda9279dSmrg} nv10_pict_op[] = {
110fda9279dSmrg	{ SF(ZERO),		   DF(ZERO) },		      /* Clear */
111fda9279dSmrg	{ SF(ONE),		   DF(ZERO) },		      /* Src */
112fda9279dSmrg	{ SF(ZERO),		   DF(ONE) },		      /* Dst */
113fda9279dSmrg	{ SF(ONE),		   DF(ONE_MINUS_SRC_ALPHA) }, /* Over */
114fda9279dSmrg	{ SF(ONE_MINUS_DST_ALPHA), DF(ONE) },		      /* OverReverse */
115fda9279dSmrg	{ SF(DST_ALPHA),	   DF(ZERO) },                /* In */
116fda9279dSmrg	{ SF(ZERO),		   DF(SRC_ALPHA) },           /* InReverse */
117fda9279dSmrg	{ SF(ONE_MINUS_DST_ALPHA), DF(ZERO) },		      /* Out */
118fda9279dSmrg	{ SF(ZERO),		   DF(ONE_MINUS_SRC_ALPHA) }, /* OutReverse */
119fda9279dSmrg	{ SF(DST_ALPHA),	   DF(ONE_MINUS_SRC_ALPHA) }, /* Atop */
120fda9279dSmrg	{ SF(ONE_MINUS_DST_ALPHA), DF(SRC_ALPHA) },	      /* AtopReverse */
121fda9279dSmrg	{ SF(ONE_MINUS_DST_ALPHA), DF(ONE_MINUS_SRC_ALPHA) }, /* Xor */
122fda9279dSmrg	{ SF(ONE),		   DF(ONE) },		      /* Add */
123fda9279dSmrg};
124fda9279dSmrg
125fda9279dSmrgstatic inline Bool
126fda9279dSmrgneeds_src_alpha(int op)
127fda9279dSmrg{
128fda9279dSmrg	return nv10_pict_op[op].dst == DF(ONE_MINUS_SRC_ALPHA)
129fda9279dSmrg		|| nv10_pict_op[op].dst == DF(SRC_ALPHA);
130fda9279dSmrg}
131fda9279dSmrg
132fda9279dSmrgstatic inline Bool
133fda9279dSmrgneeds_src(int op)
134fda9279dSmrg{
135fda9279dSmrg	return nv10_pict_op[op].src != SF(ZERO);
136fda9279dSmrg}
137fda9279dSmrg
138fda9279dSmrgstatic inline Bool
139fda9279dSmrgeffective_component_alpha(PicturePtr mask)
140fda9279dSmrg{
141fda9279dSmrg	return mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format);
142fda9279dSmrg}
143fda9279dSmrg
144fda9279dSmrgstatic Bool
145fda9279dSmrgcheck_texture(NVPtr pNv, PicturePtr pict)
146fda9279dSmrg{
147fda9279dSmrg	int w = 1, h = 1;
148fda9279dSmrg
149fda9279dSmrg	if (pict->pDrawable) {
150fda9279dSmrg		w = pict->pDrawable->width;
151fda9279dSmrg		h = pict->pDrawable->height;
152fda9279dSmrg	} else {
153fda9279dSmrg		if (pict->pSourcePict->type != SourcePictTypeSolidFill)
154fda9279dSmrg			NOUVEAU_FALLBACK("gradient pictures unsupported\n");
155fda9279dSmrg	}
156fda9279dSmrg
157fda9279dSmrg	if (w > 2046 || h > 2046)
158fda9279dSmrg		NOUVEAU_FALLBACK("picture too large, %dx%d\n", w, h);
159fda9279dSmrg
160fda9279dSmrg	if (!get_tex_format(pNv, pict))
161fda9279dSmrg		return FALSE;
162fda9279dSmrg
163fda9279dSmrg	if (pict->filter != PictFilterNearest &&
164fda9279dSmrg	    pict->filter != PictFilterBilinear)
165fda9279dSmrg		return FALSE;
166fda9279dSmrg
167fda9279dSmrg	/* We cannot repeat on NV10 because NPOT textures do not
168fda9279dSmrg	 * support this. unfortunately. */
169fda9279dSmrg	if (pict->repeat != RepeatNone)
170fda9279dSmrg		/* we can repeat 1x1 textures */
171fda9279dSmrg		if (!(w == 1 && h == 1))
172fda9279dSmrg			return FALSE;
173fda9279dSmrg
174fda9279dSmrg	return TRUE;
175fda9279dSmrg}
176fda9279dSmrg
177fda9279dSmrgstatic Bool
178fda9279dSmrgcheck_render_target(PicturePtr pict)
179fda9279dSmrg{
180fda9279dSmrg	int w = pict->pDrawable->width;
181fda9279dSmrg	int h = pict->pDrawable->height;
182fda9279dSmrg
183fda9279dSmrg	if (w > 4096 || h > 4096)
184fda9279dSmrg		return FALSE;
185fda9279dSmrg
186fda9279dSmrg	if (!get_rt_format(pict))
187fda9279dSmrg		return FALSE;
188fda9279dSmrg
189fda9279dSmrg	return TRUE;
190fda9279dSmrg}
191fda9279dSmrg
192fda9279dSmrgstatic Bool
193fda9279dSmrgcheck_pict_op(int op)
194fda9279dSmrg{
195fda9279dSmrg	/* We do no saturate, disjoint, conjoint, though we
196fda9279dSmrg	 * could do e.g. DisjointClear which really is
197fda9279dSmrg	 * Clear. */
198fda9279dSmrg	return op < PictOpSaturate;
199fda9279dSmrg}
200fda9279dSmrg
201fda9279dSmrg#if 0
202fda9279dSmrgstatic void
203fda9279dSmrgprint_fallback_info(char *reason, int op, PicturePtr src, PicturePtr mask,
204fda9279dSmrg		    PicturePtr dst)
205fda9279dSmrg{
206fda9279dSmrg	char out2[4096];
207fda9279dSmrg	char *out = out2;
208fda9279dSmrg
209fda9279dSmrg	sprintf(out, "%s  ", reason);
210fda9279dSmrg	out += strlen(out);
211fda9279dSmrg
212fda9279dSmrg	switch (op) {
213fda9279dSmrg	case PictOpClear:
214fda9279dSmrg		sprintf(out, "PictOpClear ");
215fda9279dSmrg		break;
216fda9279dSmrg	case PictOpSrc:
217fda9279dSmrg		sprintf(out, "PictOpSrc ");
218fda9279dSmrg		break;
219fda9279dSmrg	case PictOpDst:
220fda9279dSmrg		sprintf(out, "PictOpDst ");
221fda9279dSmrg		break;
222fda9279dSmrg	case PictOpOver:
223fda9279dSmrg		sprintf(out, "PictOpOver ");
224fda9279dSmrg		break;
225fda9279dSmrg	case PictOpOutReverse:
226fda9279dSmrg		sprintf(out, "PictOpOutReverse ");
227fda9279dSmrg		break;
228fda9279dSmrg	case PictOpAdd:
229fda9279dSmrg		sprintf(out, "PictOpAdd ");
230fda9279dSmrg		break;
231fda9279dSmrg	default:
232fda9279dSmrg		sprintf(out, "PictOp%d ", op);
233fda9279dSmrg	}
234fda9279dSmrg	out += strlen(out);
235fda9279dSmrg
236fda9279dSmrg	switch (src->format) {
237fda9279dSmrg	case PICT_a8r8g8b8:
238fda9279dSmrg		sprintf(out, "A8R8G8B8 ");
239fda9279dSmrg		break;
240fda9279dSmrg	case PICT_x8r8g8b8:
241fda9279dSmrg		sprintf(out, "X8R8G8B8 ");
242fda9279dSmrg		break;
243fda9279dSmrg	case PICT_x8b8g8r8:
244fda9279dSmrg		sprintf(out, "X8B8G8R8 ");
245fda9279dSmrg		break;
246fda9279dSmrg	case PICT_r5g6b5:
247fda9279dSmrg		sprintf(out, "R5G6B5 ");
248fda9279dSmrg		break;
249fda9279dSmrg	case PICT_a8:
250fda9279dSmrg		sprintf(out, "A8 ");
251fda9279dSmrg		break;
252fda9279dSmrg	case PICT_a1:
253fda9279dSmrg		sprintf(out, "A1 ");
254fda9279dSmrg		break;
255fda9279dSmrg	default:
256fda9279dSmrg		sprintf(out, "%x ", src->format);
257fda9279dSmrg	}
258fda9279dSmrg	out += strlen(out);
259fda9279dSmrg
260fda9279dSmrg	sprintf(out, "(%dx%d) ", src->pDrawable->width,
261fda9279dSmrg		src->pDrawable->height);
262fda9279dSmrg	if (src->repeat != RepeatNone)
263fda9279dSmrg		strcat(out, "R ");
264fda9279dSmrg	strcat(out, "-> ");
265fda9279dSmrg	out += strlen(out);
266fda9279dSmrg
267fda9279dSmrg	switch (dst->format) {
268fda9279dSmrg	case PICT_a8r8g8b8:
269fda9279dSmrg		sprintf(out, "A8R8G8B8 ");
270fda9279dSmrg		break;
271fda9279dSmrg	case PICT_x8r8g8b8:
272fda9279dSmrg		sprintf(out, "X8R8G8B8  ");
273fda9279dSmrg		break;
274fda9279dSmrg	case PICT_x8b8g8r8:
275fda9279dSmrg		sprintf(out, "X8B8G8R8  ");
276fda9279dSmrg		break;
277fda9279dSmrg	case PICT_r5g6b5:
278fda9279dSmrg		sprintf(out, "R5G6B5 ");
279fda9279dSmrg		break;
280fda9279dSmrg	case PICT_a8:
281fda9279dSmrg		sprintf(out, "A8  ");
282fda9279dSmrg		break;
283fda9279dSmrg	case PICT_a1:
284fda9279dSmrg		sprintf(out, "A1  ");
285fda9279dSmrg		break;
286fda9279dSmrg	default:
287fda9279dSmrg		sprintf(out, "%x  ", dst->format);
288fda9279dSmrg	}
289fda9279dSmrg	out += strlen(out);
290fda9279dSmrg
291fda9279dSmrg	sprintf(out, "(%dx%d) ", dst->pDrawable->width,
292fda9279dSmrg		dst->pDrawable->height);
293fda9279dSmrg	if (dst->repeat != RepeatNone)
294fda9279dSmrg		strcat(out, "R ");
295fda9279dSmrg	out += strlen(out);
296fda9279dSmrg
297fda9279dSmrg	if (!mask)
298fda9279dSmrg		sprintf(out, "& NONE");
299fda9279dSmrg	else {
300fda9279dSmrg		switch (mask->format) {
301fda9279dSmrg		case PICT_a8r8g8b8:
302fda9279dSmrg			sprintf(out, "& A8R8G8B8 ");
303fda9279dSmrg			break;
304fda9279dSmrg		case PICT_x8r8g8b8:
305fda9279dSmrg			sprintf(out, "& X8R8G8B8  ");
306fda9279dSmrg			break;
307fda9279dSmrg		case PICT_x8b8g8r8:
308fda9279dSmrg			sprintf(out, "& X8B8G8R8  ");
309fda9279dSmrg			break;
310fda9279dSmrg		case PICT_a8:
311fda9279dSmrg			sprintf(out, "& A8  ");
312fda9279dSmrg			break;
313fda9279dSmrg		case PICT_a1:
314fda9279dSmrg			sprintf(out, "& A1  ");
315fda9279dSmrg			break;
316fda9279dSmrg		default:
317fda9279dSmrg			sprintf(out, "& %x  ", mask->format);
318fda9279dSmrg		}
319fda9279dSmrg		out += strlen(out);
320fda9279dSmrg
321fda9279dSmrg		sprintf(out, "(%dx%d) ", mask->pDrawable->width,
322fda9279dSmrg			mask->pDrawable->height);
323fda9279dSmrg		if (mask->repeat != RepeatNone)
324fda9279dSmrg			strcat(out, "R ");
325fda9279dSmrg		if (mask->componentAlpha)
326fda9279dSmrg			strcat(out, "C ");
327fda9279dSmrg		out += strlen(out);
328fda9279dSmrg	}
329fda9279dSmrg	strcat(out, "\n");
330fda9279dSmrg
331fda9279dSmrg	xf86DrvMsg(0, X_INFO, "%s", out2);
332fda9279dSmrg}
333fda9279dSmrg#else
334fda9279dSmrg#define print_fallback_info(...)
335fda9279dSmrg#endif
336fda9279dSmrg
337fda9279dSmrgBool
338fda9279dSmrgNV10EXACheckComposite(int op, PicturePtr src, PicturePtr mask, PicturePtr dst)
339fda9279dSmrg{
340fda9279dSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
341fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
342fda9279dSmrg
343fda9279dSmrg	if (!check_pict_op(op)) {
344fda9279dSmrg		print_fallback_info("pictop", op, src, mask, dst);
345fda9279dSmrg		return FALSE;
346fda9279dSmrg	}
347fda9279dSmrg
348fda9279dSmrg	if (!check_render_target(dst)) {
349fda9279dSmrg		print_fallback_info("dst", op, src, mask, dst);
350fda9279dSmrg		return FALSE;
351fda9279dSmrg	}
352fda9279dSmrg
353fda9279dSmrg	if (!check_texture(pNv, src)) {
354fda9279dSmrg		print_fallback_info("src", op, src, mask, dst);
355fda9279dSmrg		return FALSE;
356fda9279dSmrg	}
357fda9279dSmrg
358fda9279dSmrg	if (mask) {
359fda9279dSmrg		if (!check_texture(pNv, mask)) {
360fda9279dSmrg			print_fallback_info("mask", op, src,
361fda9279dSmrg					    mask, dst);
362fda9279dSmrg			return FALSE;
363fda9279dSmrg		}
364fda9279dSmrg
365fda9279dSmrg		if (effective_component_alpha(mask) &&
366fda9279dSmrg		    needs_src(op) && needs_src_alpha(op)) {
367fda9279dSmrg			print_fallback_info("ca-mask", op, src,
368fda9279dSmrg					    mask, dst);
369fda9279dSmrg			return FALSE;
370fda9279dSmrg		}
371fda9279dSmrg	}
372fda9279dSmrg
373fda9279dSmrg	print_fallback_info("Accelerating", op, src, mask, dst);
374fda9279dSmrg	return TRUE;
375fda9279dSmrg}
376fda9279dSmrg
377fda9279dSmrgstatic Bool
378fda9279dSmrgsetup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap)
379fda9279dSmrg{
380fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
381fda9279dSmrg	struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);
382fda9279dSmrg	unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
383fda9279dSmrg	unsigned h = pict->pDrawable->height;
384fda9279dSmrg	unsigned w = pict->pDrawable->width;
385fda9279dSmrg	unsigned format;
386fda9279dSmrg
387fda9279dSmrg	format = NV10_3D_TEX_FORMAT_WRAP_T_CLAMP_TO_EDGE |
388fda9279dSmrg		 NV10_3D_TEX_FORMAT_WRAP_S_CLAMP_TO_EDGE |
389fda9279dSmrg		 log2i(w) << 20 | log2i(h) << 16 |
390fda9279dSmrg		 1 << 12 | /* lod == 1 */
391fda9279dSmrg		 get_tex_format(pNv, pict) |
392fda9279dSmrg		 0x50 /* UNK */;
393fda9279dSmrg
394fda9279dSmrg	/* NPOT_SIZE expects an even number for width, we can round up uneven
395fda9279dSmrg	 * numbers here because EXA always gives 64 byte aligned pixmaps and
396fda9279dSmrg	 * for all formats we support 64 bytes represents an even number of
397fda9279dSmrg	 * pixels
398fda9279dSmrg	 */
399fda9279dSmrg	w = (w + 1) & ~1;
400fda9279dSmrg
401fda9279dSmrg	BEGIN_NV04(push, NV10_3D(TEX_OFFSET(unit)), 1);
402fda9279dSmrg	PUSH_MTHDl(push, NV10_3D(TEX_OFFSET(unit)), bo, 0, reloc);
403fda9279dSmrg	BEGIN_NV04(push, NV10_3D(TEX_FORMAT(unit)), 1);
404fda9279dSmrg	PUSH_MTHDs(push, NV10_3D(TEX_FORMAT(unit)), bo, format, reloc,
405fda9279dSmrg			 NV10_3D_TEX_FORMAT_DMA0,
406fda9279dSmrg			 NV10_3D_TEX_FORMAT_DMA1);
407fda9279dSmrg	BEGIN_NV04(push, NV10_3D(TEX_ENABLE(unit)), 1 );
408fda9279dSmrg	PUSH_DATA (push, NV10_3D_TEX_ENABLE_ENABLE);
409fda9279dSmrg	BEGIN_NV04(push, NV10_3D(TEX_NPOT_PITCH(unit)), 1);
410fda9279dSmrg	PUSH_DATA (push, exaGetPixmapPitch(pixmap) << 16);
411fda9279dSmrg	BEGIN_NV04(push, NV10_3D(TEX_NPOT_SIZE(unit)), 1);
412fda9279dSmrg	PUSH_DATA (push, (w << 16) | h);
413fda9279dSmrg	BEGIN_NV04(push, NV10_3D(TEX_FILTER(unit)), 1);
414fda9279dSmrg	if (pict->filter == PictFilterNearest)
415fda9279dSmrg		PUSH_DATA(push, NV10_3D_TEX_FILTER_MAGNIFY_NEAREST |
416fda9279dSmrg				NV10_3D_TEX_FILTER_MINIFY_NEAREST);
417fda9279dSmrg	else
418fda9279dSmrg		PUSH_DATA(push, NV10_3D_TEX_FILTER_MAGNIFY_LINEAR |
419fda9279dSmrg				NV10_3D_TEX_FILTER_MINIFY_LINEAR);
420fda9279dSmrg	if (pict->transform) {
421fda9279dSmrg		BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(unit)), 1);
422fda9279dSmrg		PUSH_DATA (push, 1);
423fda9279dSmrg		BEGIN_NV04(push, NV10_3D(TEX_MATRIX(unit, 0)), 16);
424fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][0]));
425fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][1]));
426fda9279dSmrg		PUSH_DATAf(push, 0.f);
427fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][2]));
428fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][0]));
429fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][1]));
430fda9279dSmrg		PUSH_DATAf(push, 0.f);
431fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][2]));
432fda9279dSmrg		PUSH_DATAf(push, 0.0f);
433fda9279dSmrg		PUSH_DATAf(push, 0.0f);
434fda9279dSmrg		PUSH_DATAf(push, 0.0f);
435fda9279dSmrg		PUSH_DATAf(push, 0.0f);
436fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][0]));
437fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][1]));
438fda9279dSmrg		PUSH_DATAf(push, 0.0f);
439fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][2]));
440fda9279dSmrg	} else {
441fda9279dSmrg		BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(unit)), 1);
442fda9279dSmrg		PUSH_DATA (push, 0);
443fda9279dSmrg	}
444fda9279dSmrg
445fda9279dSmrg	return TRUE;
446fda9279dSmrg}
447fda9279dSmrg
448fda9279dSmrgstatic Bool
449fda9279dSmrgsetup_render_target(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap)
450fda9279dSmrg{
451fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
452fda9279dSmrg	struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);
453fda9279dSmrg
454fda9279dSmrg	BEGIN_NV04(push, NV10_3D(RT_FORMAT), 3);
455fda9279dSmrg	PUSH_DATA (push, get_rt_format(pict));
456fda9279dSmrg	PUSH_DATA (push, (exaGetPixmapPitch(pixmap) << 16 |
457fda9279dSmrg			  exaGetPixmapPitch(pixmap)));
458fda9279dSmrg	PUSH_MTHDl(push, NV10_3D(COLOR_OFFSET), bo, 0,
459fda9279dSmrg			 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
460fda9279dSmrg	return TRUE;
461fda9279dSmrg}
462fda9279dSmrg
463fda9279dSmrgstatic void
464fda9279dSmrgsetup_blend_function(NVPtr pNv, PicturePtr pdpict, PicturePtr pmpict, int alu)
465fda9279dSmrg{
466fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
467fda9279dSmrg	struct pict_op *op = &nv10_pict_op[alu];
468fda9279dSmrg	int src_factor = op->src;
469fda9279dSmrg	int dst_factor = op->dst;
470fda9279dSmrg
471fda9279dSmrg	if (src_factor == SF(ONE_MINUS_DST_ALPHA) &&
472fda9279dSmrg	    !PICT_FORMAT_A(pdpict->format))
473fda9279dSmrg		/* ONE_MINUS_DST_ALPHA doesn't always do the right thing for
474fda9279dSmrg		 * framebuffers without alpha channel. But it's the same as
475fda9279dSmrg		 * ZERO in that case.
476fda9279dSmrg		 */
477fda9279dSmrg		src_factor = SF(ZERO);
478fda9279dSmrg
479fda9279dSmrg	if (effective_component_alpha(pmpict)) {
480fda9279dSmrg		if (dst_factor == DF(SRC_ALPHA))
481fda9279dSmrg			dst_factor = DF(SRC_COLOR);
482fda9279dSmrg		else if (dst_factor == DF(ONE_MINUS_SRC_ALPHA))
483fda9279dSmrg			dst_factor = DF(ONE_MINUS_SRC_COLOR);
484fda9279dSmrg	}
485fda9279dSmrg
486fda9279dSmrg	BEGIN_NV04(push, NV10_3D(BLEND_FUNC_SRC), 2);
487fda9279dSmrg	PUSH_DATA (push, src_factor);
488fda9279dSmrg	PUSH_DATA (push, dst_factor);
489fda9279dSmrg	BEGIN_NV04(push, NV10_3D(BLEND_FUNC_ENABLE), 1);
490fda9279dSmrg	PUSH_DATA (push, 1);
491fda9279dSmrg}
492fda9279dSmrg
493fda9279dSmrg#define RCSRC_COL(i)  (0x01 + (unit))
494fda9279dSmrg#define RCSRC_TEX(i)  (0x08 + (unit))
495fda9279dSmrg#define RCSEL_COLOR   (0x00)
496fda9279dSmrg#define RCSEL_ALPHA   (0x10)
497fda9279dSmrg#define RCINP_ZERO    (0x00)
498fda9279dSmrg#define RCINP_ONE     (0x20)
499fda9279dSmrg#define RCINP_A__SHIFT 24
500fda9279dSmrg#define RCINP_B__SHIFT 16
501fda9279dSmrg
502fda9279dSmrgstatic Bool
503fda9279dSmrgsetup_picture(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap, int unit,
504fda9279dSmrg	      uint32_t *color, uint32_t *alpha)
505fda9279dSmrg{
506fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
507fda9279dSmrg	uint32_t shift, source;
508fda9279dSmrg
509fda9279dSmrg	if (pict && pict->pDrawable) {
510fda9279dSmrg		if (!setup_texture(pNv, unit, pict, pixmap))
511fda9279dSmrg			return FALSE;
512fda9279dSmrg		source = RCSRC_TEX(unit);
513fda9279dSmrg	} else
514fda9279dSmrg	if (pict) {
515fda9279dSmrg		BEGIN_NV04(push, NV10_3D(RC_COLOR(unit)), 1);
516fda9279dSmrg		PUSH_DATA (push, pict->pSourcePict->solidFill.color);
517fda9279dSmrg		source = RCSRC_COL(unit);
518fda9279dSmrg	}
519fda9279dSmrg
520fda9279dSmrg	if (pict && PICT_FORMAT_RGB(pict->format))
521fda9279dSmrg		*color = RCSEL_COLOR | source;
522fda9279dSmrg	else
523fda9279dSmrg		*color = RCSEL_COLOR | RCINP_ZERO;
524fda9279dSmrg
525fda9279dSmrg	if (pict && PICT_FORMAT_A(pict->format))
526fda9279dSmrg		*alpha = RCSEL_ALPHA | source;
527fda9279dSmrg	else
528fda9279dSmrg		*alpha = RCSEL_ALPHA | RCINP_ONE;
529fda9279dSmrg
530fda9279dSmrg	if (unit)
531fda9279dSmrg		shift = RCINP_B__SHIFT;
532fda9279dSmrg	else
533fda9279dSmrg		shift = RCINP_A__SHIFT;
534fda9279dSmrg	*color <<= shift;
535fda9279dSmrg	*alpha <<= shift;
536fda9279dSmrg	return TRUE;
537fda9279dSmrg}
538fda9279dSmrg
539fda9279dSmrgBool
540fda9279dSmrgNV10EXAPrepareComposite(int op,
541fda9279dSmrg			PicturePtr pict_src,
542fda9279dSmrg			PicturePtr pict_mask,
543fda9279dSmrg			PicturePtr pict_dst,
544fda9279dSmrg			PixmapPtr src,
545fda9279dSmrg			PixmapPtr mask,
546fda9279dSmrg			PixmapPtr dst)
547fda9279dSmrg{
548fda9279dSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(dst->drawable.pScreen);
549fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
550fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
551fda9279dSmrg	uint32_t sc, sa, mc, ma;
552fda9279dSmrg
553fda9279dSmrg	if (!PUSH_SPACE(push, 128))
554fda9279dSmrg		return FALSE;
555fda9279dSmrg	PUSH_RESET(push);
556fda9279dSmrg
557fda9279dSmrg	/* setup render target and blending */
558fda9279dSmrg	if (!setup_render_target(pNv, pict_dst, dst))
559fda9279dSmrg		return FALSE;
560fda9279dSmrg	setup_blend_function(pNv, pict_dst, pict_mask, op);
561fda9279dSmrg
562fda9279dSmrg	/* select picture sources */
563fda9279dSmrg	if (!setup_picture(pNv, pict_src, src, 0, &sc, &sa))
564fda9279dSmrg		return FALSE;
565fda9279dSmrg	if (!setup_picture(pNv, pict_mask, mask, 1, &mc, &ma))
566fda9279dSmrg		return FALSE;
567fda9279dSmrg
568fda9279dSmrg	/* configure register combiners */
569fda9279dSmrg	BEGIN_NV04(push, NV10_3D(RC_IN_ALPHA(0)), 1);
570fda9279dSmrg	PUSH_DATA (push, sa | ma);
571fda9279dSmrg	BEGIN_NV04(push, NV10_3D(RC_IN_RGB(0)), 1);
572fda9279dSmrg	if (effective_component_alpha(pict_mask)) {
573fda9279dSmrg		if (needs_src_alpha(op))
574fda9279dSmrg			PUSH_DATA(push, sa | mc);
575fda9279dSmrg		else
576fda9279dSmrg			PUSH_DATA(push, sc | mc);
577fda9279dSmrg	} else {
578fda9279dSmrg		PUSH_DATA(push, sc | ma);
579fda9279dSmrg	}
580fda9279dSmrg
581fda9279dSmrg	nouveau_pushbuf_bufctx(push, pNv->bufctx);
582fda9279dSmrg	if (nouveau_pushbuf_validate(push)) {
583fda9279dSmrg		nouveau_pushbuf_bufctx(push, NULL);
584fda9279dSmrg		return FALSE;
585fda9279dSmrg	}
586fda9279dSmrg
587fda9279dSmrg	pNv->pspict = pict_src;
588fda9279dSmrg	pNv->pmpict = pict_mask;
589fda9279dSmrg	return TRUE;
590fda9279dSmrg}
591fda9279dSmrg
592fda9279dSmrgstatic inline void
593fda9279dSmrgPUSH_VTX2s(struct nouveau_pushbuf *push,
594fda9279dSmrg	   int x1, int y1, int x2, int y2, int dx, int dy)
595fda9279dSmrg{
596fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_TX0_2I), 1);
597fda9279dSmrg	PUSH_DATA (push, ((y1 & 0xffff) << 16) | (x1 & 0xffff));
598fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_TX1_2I), 1);
599fda9279dSmrg	PUSH_DATA (push, ((y2 & 0xffff) << 16) | (x2 & 0xffff));
600fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_POS_3F_X), 3);
601fda9279dSmrg	PUSH_DATAf(push, dx);
602fda9279dSmrg	PUSH_DATAf(push, dy);
603fda9279dSmrg	PUSH_DATAf(push, 0.0);
604fda9279dSmrg}
605fda9279dSmrg
606fda9279dSmrgvoid
607fda9279dSmrgNV10EXAComposite(PixmapPtr pix_dst,
608fda9279dSmrg		 int sx, int sy, int mx, int my, int dx, int dy, int w, int h)
609fda9279dSmrg{
610fda9279dSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pix_dst->drawable.pScreen);
611fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
612fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
613fda9279dSmrg
614fda9279dSmrg	if (!PUSH_SPACE(push, 64))
615fda9279dSmrg		return;
616fda9279dSmrg
617fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_BEGIN_END), 1);
618fda9279dSmrg	PUSH_DATA (push, NV10_3D_VERTEX_BEGIN_END_QUADS);
619fda9279dSmrg	PUSH_VTX2s(push, sx, sy, mx, my, dx, dy);
620fda9279dSmrg	PUSH_VTX2s(push, sx + w, sy, mx + w, my, dx + w, dy);
621fda9279dSmrg	PUSH_VTX2s(push, sx + w, sy + h, mx + w, my + h, dx + w, dy + h);
622fda9279dSmrg	PUSH_VTX2s(push, sx, sy + h, mx, my + h, dx, dy + h);
623fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_BEGIN_END), 1);
624fda9279dSmrg	PUSH_DATA (push, NV10_3D_VERTEX_BEGIN_END_STOP);
625fda9279dSmrg}
626fda9279dSmrg
627fda9279dSmrgvoid
628fda9279dSmrgNV10EXADoneComposite(PixmapPtr dst)
629fda9279dSmrg{
630fda9279dSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(dst->drawable.pScreen);
631fda9279dSmrg	nouveau_pushbuf_bufctx(NVPTR(pScrn)->pushbuf, NULL);
632fda9279dSmrg}
633fda9279dSmrg
634fda9279dSmrgBool
635fda9279dSmrgNVAccelInitNV10TCL(ScrnInfoPtr pScrn)
636fda9279dSmrg{
637fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
638fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
639fda9279dSmrg	struct nv04_fifo *fifo = pNv->channel->data;
640fda9279dSmrg	uint32_t class = 0;
641fda9279dSmrg	int i;
642fda9279dSmrg
643fda9279dSmrg	if (((pNv->dev->chipset & 0xf0) != NV_ARCH_10) &&
644fda9279dSmrg	    ((pNv->dev->chipset & 0xf0) != NV_ARCH_20))
645fda9279dSmrg		return FALSE;
646fda9279dSmrg
647fda9279dSmrg	if (pNv->dev->chipset >= 0x20 || pNv->dev->chipset == 0x1a)
648fda9279dSmrg		class = NV15_3D_CLASS;
649fda9279dSmrg	else if (pNv->dev->chipset >= 0x17)
650fda9279dSmrg		class = NV17_3D_CLASS;
651fda9279dSmrg	else if (pNv->dev->chipset >= 0x11)
652fda9279dSmrg		class = NV15_3D_CLASS;
653fda9279dSmrg	else
654fda9279dSmrg		class = NV10_3D_CLASS;
655fda9279dSmrg
656fda9279dSmrg	if (nouveau_object_new(pNv->channel, Nv3D, class, NULL, 0, &pNv->Nv3D))
657fda9279dSmrg		return FALSE;
658fda9279dSmrg
659fda9279dSmrg	if (!PUSH_SPACE(push, 256))
660fda9279dSmrg		return FALSE;
661fda9279dSmrg
662fda9279dSmrg	BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1);
663fda9279dSmrg	PUSH_DATA (push, pNv->Nv3D->handle);
664fda9279dSmrg	BEGIN_NV04(push, NV10_3D(DMA_NOTIFY), 1);
665fda9279dSmrg	PUSH_DATA (push, pNv->NvNull->handle);
666fda9279dSmrg
667fda9279dSmrg	BEGIN_NV04(push, NV10_3D(DMA_TEXTURE0), 2);
668fda9279dSmrg	PUSH_DATA (push, fifo->vram);
669fda9279dSmrg	PUSH_DATA (push, fifo->gart);
670fda9279dSmrg
671fda9279dSmrg	BEGIN_NV04(push, NV10_3D(DMA_COLOR), 2);
672fda9279dSmrg	PUSH_DATA (push, fifo->vram);
673fda9279dSmrg	PUSH_DATA (push, fifo->vram);
674fda9279dSmrg
675fda9279dSmrg	BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1);
676fda9279dSmrg	PUSH_DATA (push, 0);
677fda9279dSmrg
678fda9279dSmrg	BEGIN_NV04(push, NV10_3D(RT_HORIZ), 2);
679fda9279dSmrg	PUSH_DATA (push, 2048 << 16 | 0);
680fda9279dSmrg	PUSH_DATA (push, 2048 << 16 | 0);
681fda9279dSmrg
682fda9279dSmrg	BEGIN_NV04(push, NV10_3D(ZETA_OFFSET), 1);
683fda9279dSmrg	PUSH_DATA (push, 0);
684fda9279dSmrg
685fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_MODE), 1);
686fda9279dSmrg	PUSH_DATA (push, 0);
687fda9279dSmrg
688fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_HORIZ(0)), 1);
689fda9279dSmrg	PUSH_DATA (push, 0x7ff << 16 | 0x800);
690fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_VERT(0)), 1);
691fda9279dSmrg	PUSH_DATA (push, 0x7ff << 16 | 0x800);
692fda9279dSmrg
693fda9279dSmrg	for (i = 1; i < 8; i++) {
694fda9279dSmrg		BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_HORIZ(i)), 1);
695fda9279dSmrg		PUSH_DATA (push, 0);
696fda9279dSmrg		BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_VERT(i)), 1);
697fda9279dSmrg		PUSH_DATA (push, 0);
698fda9279dSmrg	}
699fda9279dSmrg
70016ee1e9aSmrg	BEGIN_NV04(push, NV10_3D(UNK0290), 1);
701fda9279dSmrg	PUSH_DATA (push, (0x10<<16)|1);
70216ee1e9aSmrg	BEGIN_NV04(push, NV10_3D(UNK03F4), 1);
703fda9279dSmrg	PUSH_DATA (push, 0);
704fda9279dSmrg
705fda9279dSmrg	BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1);
706fda9279dSmrg	PUSH_DATA (push, 0);
707fda9279dSmrg
708fda9279dSmrg	if (class != NV10_3D_CLASS) {
709fda9279dSmrg		/* For nv11, nv17 */
71016ee1e9aSmrg		BEGIN_NV04(push, SUBC_3D(NV15_3D_FLIP_SET_READ), 3);
711fda9279dSmrg		PUSH_DATA (push, 0);
712fda9279dSmrg		PUSH_DATA (push, 1);
713fda9279dSmrg		PUSH_DATA (push, 2);
714fda9279dSmrg
71516ee1e9aSmrg		BEGIN_NV04(push, NV15_BLIT(FLIP_SET_READ), 3);
716fda9279dSmrg		PUSH_DATA (push, 0);
717fda9279dSmrg		PUSH_DATA (push, 1);
718fda9279dSmrg		PUSH_DATA (push, 2);
719fda9279dSmrg
720fda9279dSmrg		BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1);
721fda9279dSmrg		PUSH_DATA (push, 0);
722fda9279dSmrg	}
723fda9279dSmrg
724fda9279dSmrg	BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1);
725fda9279dSmrg	PUSH_DATA (push, 0);
726fda9279dSmrg
727fda9279dSmrg	/* Set state */
728fda9279dSmrg	BEGIN_NV04(push, NV10_3D(FOG_ENABLE), 1);
729fda9279dSmrg	PUSH_DATA (push, 0);
730fda9279dSmrg	BEGIN_NV04(push, NV10_3D(ALPHA_FUNC_ENABLE), 1);
731fda9279dSmrg	PUSH_DATA (push, 0);
732fda9279dSmrg	BEGIN_NV04(push, NV10_3D(ALPHA_FUNC_FUNC), 2);
733fda9279dSmrg	PUSH_DATA (push, 0x207);
734fda9279dSmrg	PUSH_DATA (push, 0);
735fda9279dSmrg	BEGIN_NV04(push, NV10_3D(TEX_ENABLE(0)), 2);
736fda9279dSmrg	PUSH_DATA (push, 0);
737fda9279dSmrg	PUSH_DATA (push, 0);
738fda9279dSmrg	BEGIN_NV04(push, NV10_3D(RC_IN_ALPHA(0)), 6);
739fda9279dSmrg	PUSH_DATA (push, 0);
740fda9279dSmrg	PUSH_DATA (push, 0);
741fda9279dSmrg	PUSH_DATA (push, 0);
742fda9279dSmrg	PUSH_DATA (push, 0);
743fda9279dSmrg	PUSH_DATA (push, 0);
744fda9279dSmrg	PUSH_DATA (push, 0);
745fda9279dSmrg	BEGIN_NV04(push, NV10_3D(RC_OUT_ALPHA(0)), 6);
746fda9279dSmrg	PUSH_DATA (push, 0x00000c00);
747fda9279dSmrg	PUSH_DATA (push, 0);
748fda9279dSmrg	PUSH_DATA (push, 0x00000c00);
749fda9279dSmrg	PUSH_DATA (push, 0x18000000);
750fda9279dSmrg	PUSH_DATA (push, 0x300c0000);
751fda9279dSmrg	PUSH_DATA (push, 0x00001c80);
752fda9279dSmrg	BEGIN_NV04(push, NV10_3D(BLEND_FUNC_ENABLE), 1);
753fda9279dSmrg	PUSH_DATA (push, 0);
754fda9279dSmrg	BEGIN_NV04(push, NV10_3D(DITHER_ENABLE), 2);
755fda9279dSmrg	PUSH_DATA (push, 1);
756fda9279dSmrg	PUSH_DATA (push, 0);
757fda9279dSmrg	BEGIN_NV04(push, NV10_3D(LINE_SMOOTH_ENABLE), 1);
758fda9279dSmrg	PUSH_DATA (push, 0);
759fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_WEIGHT_ENABLE), 2);
760fda9279dSmrg	PUSH_DATA (push, 0);
761fda9279dSmrg	PUSH_DATA (push, 0);
762fda9279dSmrg	BEGIN_NV04(push, NV10_3D(BLEND_FUNC_SRC), 4);
763fda9279dSmrg	PUSH_DATA (push, 1);
764fda9279dSmrg	PUSH_DATA (push, 0);
765fda9279dSmrg	PUSH_DATA (push, 0);
766fda9279dSmrg	PUSH_DATA (push, 0x8006);
767fda9279dSmrg	BEGIN_NV04(push, NV10_3D(STENCIL_MASK), 8);
768fda9279dSmrg	PUSH_DATA (push, 0xff);
769fda9279dSmrg	PUSH_DATA (push, 0x207);
770fda9279dSmrg	PUSH_DATA (push, 0);
771fda9279dSmrg	PUSH_DATA (push, 0xff);
772fda9279dSmrg	PUSH_DATA (push, 0x1e00);
773fda9279dSmrg	PUSH_DATA (push, 0x1e00);
774fda9279dSmrg	PUSH_DATA (push, 0x1e00);
775fda9279dSmrg	PUSH_DATA (push, 0x1d01);
776fda9279dSmrg	BEGIN_NV04(push, NV10_3D(NORMALIZE_ENABLE), 1);
777fda9279dSmrg	PUSH_DATA (push, 0);
778fda9279dSmrg	BEGIN_NV04(push, NV10_3D(FOG_ENABLE), 2);
779fda9279dSmrg	PUSH_DATA (push, 0);
780fda9279dSmrg	PUSH_DATA (push, 0);
781fda9279dSmrg	BEGIN_NV04(push, NV10_3D(LIGHT_MODEL), 1);
782fda9279dSmrg	PUSH_DATA (push, 0);
783fda9279dSmrg	BEGIN_NV04(push, NV10_3D(SEPARATE_SPECULAR_ENABLE), 1);
784fda9279dSmrg	PUSH_DATA (push, 0);
785fda9279dSmrg	BEGIN_NV04(push, NV10_3D(ENABLED_LIGHTS), 1);
786fda9279dSmrg	PUSH_DATA (push, 0);
787fda9279dSmrg	BEGIN_NV04(push, NV10_3D(POLYGON_OFFSET_POINT_ENABLE), 3);
788fda9279dSmrg	PUSH_DATA (push, 0);
789fda9279dSmrg	PUSH_DATA (push, 0);
790fda9279dSmrg	PUSH_DATA (push, 0);
791fda9279dSmrg	BEGIN_NV04(push, NV10_3D(DEPTH_FUNC), 1);
792fda9279dSmrg	PUSH_DATA (push, 0x201);
793fda9279dSmrg	BEGIN_NV04(push, NV10_3D(DEPTH_WRITE_ENABLE), 1);
794fda9279dSmrg	PUSH_DATA (push, 0);
795fda9279dSmrg	BEGIN_NV04(push, NV10_3D(DEPTH_TEST_ENABLE), 1);
796fda9279dSmrg	PUSH_DATA (push, 0);
797fda9279dSmrg	BEGIN_NV04(push, NV10_3D(POLYGON_OFFSET_FACTOR), 2);
798fda9279dSmrg	PUSH_DATA (push, 0);
799fda9279dSmrg	PUSH_DATA (push, 0);
800fda9279dSmrg	BEGIN_NV04(push, NV10_3D(POINT_SIZE), 1);
801fda9279dSmrg	PUSH_DATA (push, 8);
802fda9279dSmrg	BEGIN_NV04(push, NV10_3D(POINT_PARAMETERS_ENABLE), 2);
803fda9279dSmrg	PUSH_DATA (push, 0);
804fda9279dSmrg	PUSH_DATA (push, 0);
805fda9279dSmrg	BEGIN_NV04(push, NV10_3D(LINE_WIDTH), 1);
806fda9279dSmrg	PUSH_DATA (push, 8);
807fda9279dSmrg	BEGIN_NV04(push, NV10_3D(LINE_SMOOTH_ENABLE), 1);
808fda9279dSmrg	PUSH_DATA (push, 0);
809fda9279dSmrg	BEGIN_NV04(push, NV10_3D(POLYGON_MODE_FRONT), 2);
810fda9279dSmrg	PUSH_DATA (push, 0x1b02);
811fda9279dSmrg	PUSH_DATA (push, 0x1b02);
812fda9279dSmrg	BEGIN_NV04(push, NV10_3D(CULL_FACE), 2);
813fda9279dSmrg	PUSH_DATA (push, 0x405);
814fda9279dSmrg	PUSH_DATA (push, 0x901);
815fda9279dSmrg	BEGIN_NV04(push, NV10_3D(POLYGON_SMOOTH_ENABLE), 1);
816fda9279dSmrg	PUSH_DATA (push, 0);
817fda9279dSmrg	BEGIN_NV04(push, NV10_3D(CULL_FACE_ENABLE), 1);
818fda9279dSmrg	PUSH_DATA (push, 0);
819fda9279dSmrg	BEGIN_NV04(push, NV10_3D(TEX_GEN_MODE(0, 0)), 8);
820fda9279dSmrg	for (i = 0; i < 8; i++)
821fda9279dSmrg		PUSH_DATA (push, 0);
822fda9279dSmrg
823fda9279dSmrg	BEGIN_NV04(push, NV10_3D(FOG_COEFF(0)), 3);
824fda9279dSmrg	PUSH_DATA (push, 0x3fc00000);	/* -1.50 */
825fda9279dSmrg	PUSH_DATA (push, 0xbdb8aa0a);	/* -0.09 */
826fda9279dSmrg	PUSH_DATA (push, 0);		/*  0.00 */
827fda9279dSmrg
828fda9279dSmrg	BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1);
829fda9279dSmrg	PUSH_DATA (push, 0);
830fda9279dSmrg
831fda9279dSmrg	BEGIN_NV04(push, NV10_3D(FOG_MODE), 2);
832fda9279dSmrg	PUSH_DATA (push, 0x802);
833fda9279dSmrg	PUSH_DATA (push, 2);
834fda9279dSmrg	/* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
835fda9279dSmrg	 * using texturing, except when using the texture matrix
836fda9279dSmrg	 */
837fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VIEW_MATRIX_ENABLE), 1);
838fda9279dSmrg	PUSH_DATA (push, 6);
839fda9279dSmrg	BEGIN_NV04(push, NV10_3D(COLOR_MASK), 1);
840fda9279dSmrg	PUSH_DATA (push, 0x01010101);
841fda9279dSmrg
842fda9279dSmrg	BEGIN_NV04(push, NV10_3D(PROJECTION_MATRIX(0)), 16);
843fda9279dSmrg	for(i = 0; i < 16; i++)
844fda9279dSmrg		PUSH_DATAf(push, i/4 == i%4 ? 1.0 : 0.0);
845fda9279dSmrg
846fda9279dSmrg	BEGIN_NV04(push, NV10_3D(DEPTH_RANGE_NEAR), 2);
847fda9279dSmrg	PUSH_DATA (push, 0);
848fda9279dSmrg	PUSH_DATAf(push, 65536.0);
849fda9279dSmrg
850fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VIEWPORT_TRANSLATE_X), 4);
851fda9279dSmrg	PUSH_DATAf(push, -2048.0);
852fda9279dSmrg	PUSH_DATAf(push, -2048.0);
853fda9279dSmrg	PUSH_DATAf(push, 0);
854fda9279dSmrg	PUSH_DATA (push, 0);
855fda9279dSmrg
856fda9279dSmrg	/* Set vertex component */
857fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_COL_4F_R), 4);
858fda9279dSmrg	PUSH_DATAf(push, 1.0);
859fda9279dSmrg	PUSH_DATAf(push, 1.0);
860fda9279dSmrg	PUSH_DATAf(push, 1.0);
861fda9279dSmrg	PUSH_DATAf(push, 1.0);
862fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_COL2_3F_R), 3);
863fda9279dSmrg	PUSH_DATA (push, 0);
864fda9279dSmrg	PUSH_DATA (push, 0);
865fda9279dSmrg	PUSH_DATA (push, 0);
866fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_NOR_3F_X), 3);
867fda9279dSmrg	PUSH_DATA (push, 0);
868fda9279dSmrg	PUSH_DATA (push, 0);
869fda9279dSmrg	PUSH_DATAf(push, 1.0);
870fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_TX0_4F_S), 4);
871fda9279dSmrg	PUSH_DATAf(push, 0.0);
872fda9279dSmrg	PUSH_DATAf(push, 0.0);
873fda9279dSmrg	PUSH_DATAf(push, 0.0);
874fda9279dSmrg	PUSH_DATAf(push, 1.0);
875fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_TX1_4F_S), 4);
876fda9279dSmrg	PUSH_DATAf(push, 0.0);
877fda9279dSmrg	PUSH_DATAf(push, 0.0);
878fda9279dSmrg	PUSH_DATAf(push, 0.0);
879fda9279dSmrg	PUSH_DATAf(push, 1.0);
880fda9279dSmrg	BEGIN_NV04(push, NV10_3D(VERTEX_FOG_1F), 1);
881fda9279dSmrg	PUSH_DATAf(push, 0.0);
882fda9279dSmrg	BEGIN_NV04(push, NV10_3D(EDGEFLAG_ENABLE), 1);
883fda9279dSmrg	PUSH_DATA (push, 1);
884fda9279dSmrg
885fda9279dSmrg	return TRUE;
886fda9279dSmrg}
887