1fda9279dSmrg/*
2fda9279dSmrg * Copyright 2007 Ben Skeggs
3fda9279dSmrg * Copyright 2007 Stephane Marchesin
4fda9279dSmrg * Copyright 2007 Jeremy Kolb
5fda9279dSmrg * Copyright 2007 Patrice Mandin
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#include "nv_include.h"
27fda9279dSmrg
28fda9279dSmrg#include "hwdefs/nv_object.xml.h"
29fda9279dSmrg#include "hwdefs/nv30-40_3d.xml.h"
30fda9279dSmrg#include "nv04_accel.h"
31fda9279dSmrg
32fda9279dSmrgtypedef struct nv_pict_surface_format {
33fda9279dSmrg	int	 pict_fmt;
34fda9279dSmrg	uint32_t card_fmt;
35fda9279dSmrg} nv_pict_surface_format_t;
36fda9279dSmrg
37fda9279dSmrgtypedef struct nv_pict_texture_format {
38fda9279dSmrg	int	 pict_fmt;
39fda9279dSmrg	uint32_t card_fmt;
40fda9279dSmrg	uint32_t card_swz;
41fda9279dSmrg} nv_pict_texture_format_t;
42fda9279dSmrg
43fda9279dSmrgtypedef struct nv_pict_op {
44fda9279dSmrg	Bool	 src_alpha;
45fda9279dSmrg	Bool	 dst_alpha;
46fda9279dSmrg	uint32_t src_card_op;
47fda9279dSmrg	uint32_t dst_card_op;
48fda9279dSmrg} nv_pict_op_t;
49fda9279dSmrg
50fda9279dSmrgstatic nv_pict_surface_format_t
51fda9279dSmrgNV30SurfaceFormat[] = {
52fda9279dSmrg	{ PICT_a8r8g8b8	, 0x148 },
53fda9279dSmrg	{ PICT_a8b8g8r8	, 0x150 },
54fda9279dSmrg	{ PICT_x8r8g8b8	, 0x145 },
55fda9279dSmrg	{ PICT_x8b8g8r8	, 0x14f },
56fda9279dSmrg	{ PICT_r5g6b5	, 0x143 },
57fda9279dSmrg	{ PICT_a8       , 0x149 },
58fda9279dSmrg	{ PICT_x1r5g5b5	, 0x142 },
59fda9279dSmrg};
60fda9279dSmrg
61fda9279dSmrgstatic nv_pict_surface_format_t *
62fda9279dSmrgNV30_GetPictSurfaceFormat(int format)
63fda9279dSmrg{
64fda9279dSmrg	int i;
65fda9279dSmrg
66fda9279dSmrg	for(i=0;i<sizeof(NV30SurfaceFormat)/sizeof(NV30SurfaceFormat[0]);i++)
67fda9279dSmrg	{
68fda9279dSmrg		if (NV30SurfaceFormat[i].pict_fmt == format)
69fda9279dSmrg			return &NV30SurfaceFormat[i];
70fda9279dSmrg	}
71fda9279dSmrg
72fda9279dSmrg	return NULL;
73fda9279dSmrg}
74fda9279dSmrg
75fda9279dSmrg/* should be in nouveau_reg.h at some point.. */
76fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S0_X_ZERO	 0
77fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S0_X_ONE	 1
78fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S0_X_S1		 2
79fda9279dSmrg
80fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S0_X_SHIFT	14
81fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S0_Y_SHIFT	12
82fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S0_Z_SHIFT	10
83fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S0_W_SHIFT	 8
84fda9279dSmrg
85fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S1_X_X		 3
86fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S1_X_Y		 2
87fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S1_X_Z		 1
88fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S1_X_W		 0
89fda9279dSmrg
90fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S1_X_SHIFT	 6
91fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S1_Y_SHIFT	 4
92fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S1_Z_SHIFT	 2
93fda9279dSmrg#define NV30_3D_TEX_SWIZZLE_UNIT_S1_W_SHIFT	 0
94fda9279dSmrg
95fda9279dSmrg#define _(r,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)                       \
96fda9279dSmrg  {                                                                           \
97fda9279dSmrg  PICT_##r,                                                                   \
98fda9279dSmrg  (tf),                                                                       \
99fda9279dSmrg  (NV30_3D_TEX_SWIZZLE_UNIT_S0_X_##ts0x << NV30_3D_TEX_SWIZZLE_UNIT_S0_X_SHIFT)|\
100fda9279dSmrg  (NV30_3D_TEX_SWIZZLE_UNIT_S0_X_##ts0y << NV30_3D_TEX_SWIZZLE_UNIT_S0_Y_SHIFT)|\
101fda9279dSmrg  (NV30_3D_TEX_SWIZZLE_UNIT_S0_X_##ts0z << NV30_3D_TEX_SWIZZLE_UNIT_S0_Z_SHIFT)|\
102fda9279dSmrg  (NV30_3D_TEX_SWIZZLE_UNIT_S0_X_##ts0w << NV30_3D_TEX_SWIZZLE_UNIT_S0_W_SHIFT)|\
103fda9279dSmrg  (NV30_3D_TEX_SWIZZLE_UNIT_S1_X_##ts1x << NV30_3D_TEX_SWIZZLE_UNIT_S1_X_SHIFT)|\
104fda9279dSmrg  (NV30_3D_TEX_SWIZZLE_UNIT_S1_X_##ts1y << NV30_3D_TEX_SWIZZLE_UNIT_S1_Y_SHIFT)|\
105fda9279dSmrg  (NV30_3D_TEX_SWIZZLE_UNIT_S1_X_##ts1z << NV30_3D_TEX_SWIZZLE_UNIT_S1_Z_SHIFT)|\
106fda9279dSmrg  (NV30_3D_TEX_SWIZZLE_UNIT_S1_X_##ts1w << NV30_3D_TEX_SWIZZLE_UNIT_S1_W_SHIFT)\
107fda9279dSmrg  }
108fda9279dSmrg
109fda9279dSmrgstatic nv_pict_texture_format_t
110fda9279dSmrgNV30TextureFormat[] = {
111fda9279dSmrg	_(a8r8g8b8, 0x12,   S1,   S1,   S1,   S1, X, Y, Z, W),
112fda9279dSmrg	_(a8b8g8r8, 0x12,   S1,   S1,   S1,   S1, Z, Y, X, W),
113fda9279dSmrg	_(x8r8g8b8, 0x12,   S1,   S1,   S1,  ONE, X, Y, Z, W),
114fda9279dSmrg	_(x8b8g8r8, 0x12,   S1,   S1,   S1,  ONE, Z, Y, X, W),
115fda9279dSmrg
116fda9279dSmrg	_(a1r5g5b5, 0x10,   S1,   S1,   S1,   S1, X, Y, Z, W),
117fda9279dSmrg	_(x1r5g5b5, 0x10,   S1,   S1,   S1,  ONE, X, Y, Z, W),
118fda9279dSmrg	_(a1b5g5r5, 0x10,   S1,   S1,   S1,   S1, Z, Y, X, W),
119fda9279dSmrg	_(x1b5g5r5, 0x10,   S1,   S1,   S1,  ONE, Z, Y, X, W),
120fda9279dSmrg
121fda9279dSmrg	_(x4r4g4b4, 0x1d,   S1,   S1,   S1,  ONE, X, Y, Z, W),
122fda9279dSmrg	_(a4r4g4b4, 0x1d,   S1,   S1,   S1,   S1, X, Y, Z, W),
123fda9279dSmrg	_(x4b4g4r4, 0x1d,   S1,   S1,   S1,  ONE, Z, Y, X, W),
124fda9279dSmrg	_(a4b4g4r4, 0x1d,   S1,   S1,   S1,   S1, Z, Y, X, W),
125fda9279dSmrg
126fda9279dSmrg	_(      a8, 0x1b, ZERO, ZERO, ZERO,   S1, X, X, X, X),
127fda9279dSmrg
128fda9279dSmrg	_(  r5g6b5, 0x11,   S1,   S1,   S1,  ONE, X, Y, Z, W),
129fda9279dSmrg	_(  b5g6r5, 0x11,   S1,   S1,   S1,  ONE, Z, Y, X, W),
130fda9279dSmrg};
131fda9279dSmrg
132fda9279dSmrg
133fda9279dSmrgstatic nv_pict_texture_format_t *
134fda9279dSmrgNV30_GetPictTextureFormat(int format)
135fda9279dSmrg{
136fda9279dSmrg	int i;
137fda9279dSmrg
138fda9279dSmrg	for(i=0;i<sizeof(NV30TextureFormat)/sizeof(NV30TextureFormat[0]);i++)
139fda9279dSmrg	{
140fda9279dSmrg		if (NV30TextureFormat[i].pict_fmt == format)
141fda9279dSmrg			return &NV30TextureFormat[i];
142fda9279dSmrg	}
143fda9279dSmrg
144fda9279dSmrg	return NULL;
145fda9279dSmrg}
146fda9279dSmrg
147fda9279dSmrg#define NV30_3D_BF_ZERO                                     0x0000
148fda9279dSmrg#define NV30_3D_BF_ONE                                      0x0001
149fda9279dSmrg#define NV30_3D_BF_SRC_COLOR                                0x0300
150fda9279dSmrg#define NV30_3D_BF_ONE_MINUS_SRC_COLOR                      0x0301
151fda9279dSmrg#define NV30_3D_BF_SRC_ALPHA                                0x0302
152fda9279dSmrg#define NV30_3D_BF_ONE_MINUS_SRC_ALPHA                      0x0303
153fda9279dSmrg#define NV30_3D_BF_DST_ALPHA                                0x0304
154fda9279dSmrg#define NV30_3D_BF_ONE_MINUS_DST_ALPHA                      0x0305
155fda9279dSmrg#define NV30_3D_BF_DST_COLOR                                0x0306
156fda9279dSmrg#define NV30_3D_BF_ONE_MINUS_DST_COLOR                      0x0307
157fda9279dSmrg#define NV30_3D_BF_ALPHA_SATURATE                           0x0308
158fda9279dSmrg#define BF(bf) NV30_3D_BF_##bf
159fda9279dSmrg
160fda9279dSmrgstatic nv_pict_op_t
161fda9279dSmrgNV30PictOp[] = {
162fda9279dSmrg/* Clear       */ { 0, 0, BF(               ZERO), BF(               ZERO) },
163fda9279dSmrg/* Src         */ { 0, 0, BF(                ONE), BF(               ZERO) },
164fda9279dSmrg/* Dst         */ { 0, 0, BF(               ZERO), BF(                ONE) },
165fda9279dSmrg/* Over        */ { 1, 0, BF(                ONE), BF(ONE_MINUS_SRC_ALPHA) },
166fda9279dSmrg/* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF(                ONE) },
167fda9279dSmrg/* In          */ { 0, 1, BF(          DST_ALPHA), BF(               ZERO) },
168fda9279dSmrg/* InReverse   */ { 1, 0, BF(               ZERO), BF(          SRC_ALPHA) },
169fda9279dSmrg/* Out         */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF(               ZERO) },
170fda9279dSmrg/* OutReverse  */ { 1, 0, BF(               ZERO), BF(ONE_MINUS_SRC_ALPHA) },
171fda9279dSmrg/* Atop        */ { 1, 1, BF(          DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
172fda9279dSmrg/* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(          SRC_ALPHA) },
173fda9279dSmrg/* Xor         */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
174fda9279dSmrg/* Add         */ { 0, 0, BF(                ONE), BF(                ONE) }
175fda9279dSmrg};
176fda9279dSmrg
177fda9279dSmrgstatic nv_pict_op_t *
178fda9279dSmrgNV30_GetPictOpRec(int op)
179fda9279dSmrg{
180fda9279dSmrg	if (op >= PictOpSaturate)
181fda9279dSmrg		return NULL;
182fda9279dSmrg#if 0
183fda9279dSmrg	switch(op)
184fda9279dSmrg	{
185fda9279dSmrg		case 0:ErrorF("Op Clear\n");break;
186fda9279dSmrg		case 1:ErrorF("Op Src\n");break;
187fda9279dSmrg		case 2:ErrorF("Op Dst\n");break;
188fda9279dSmrg		case 3:ErrorF("Op Over\n");break;
189fda9279dSmrg		case 4:ErrorF("Op OverReverse\n");break;
190fda9279dSmrg		case 5:ErrorF("Op In\n");break;
191fda9279dSmrg		case 6:ErrorF("Op InReverse\n");break;
192fda9279dSmrg		case 7:ErrorF("Op Out\n");break;
193fda9279dSmrg		case 8:ErrorF("Op OutReverse\n");break;
194fda9279dSmrg		case 9:ErrorF("Op Atop\n");break;
195fda9279dSmrg		case 10:ErrorF("Op AtopReverse\n");break;
196fda9279dSmrg		case 11:ErrorF("Op Xor\n");break;
197fda9279dSmrg		case 12:ErrorF("Op Add\n");break;
198fda9279dSmrg	}
199fda9279dSmrg#endif
200fda9279dSmrg	return &NV30PictOp[op];
201fda9279dSmrg}
202fda9279dSmrg
203fda9279dSmrgstatic void
204fda9279dSmrgNV30_SetupBlend(ScrnInfoPtr pScrn, nv_pict_op_t *blend,
205fda9279dSmrg		PictFormatShort dest_format, Bool component_alpha)
206fda9279dSmrg{
207fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
208fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
209fda9279dSmrg	uint32_t sblend, dblend;
210fda9279dSmrg
211fda9279dSmrg	sblend = blend->src_card_op;
212fda9279dSmrg	dblend = blend->dst_card_op;
213fda9279dSmrg
214fda9279dSmrg	if (blend->dst_alpha) {
215fda9279dSmrg		if (!PICT_FORMAT_A(dest_format)) {
216fda9279dSmrg			if (sblend == BF(DST_ALPHA)) {
217fda9279dSmrg				sblend = BF(ONE);
218fda9279dSmrg			} else if (sblend == BF(ONE_MINUS_DST_ALPHA)) {
219fda9279dSmrg				sblend = BF(ZERO);
220fda9279dSmrg			}
221fda9279dSmrg		} else if (dest_format == PICT_a8) {
222fda9279dSmrg			if (sblend == BF(DST_ALPHA)) {
223fda9279dSmrg				sblend = BF(DST_COLOR);
224fda9279dSmrg			} else if (sblend == BF(ONE_MINUS_DST_ALPHA)) {
225fda9279dSmrg				sblend = BF(ONE_MINUS_DST_COLOR);
226fda9279dSmrg			}
227fda9279dSmrg		}
228fda9279dSmrg	}
229fda9279dSmrg
230fda9279dSmrg	if (blend->src_alpha && (component_alpha || dest_format == PICT_a8)) {
231fda9279dSmrg		if (dblend == BF(SRC_ALPHA)) {
232fda9279dSmrg			dblend = BF(SRC_COLOR);
233fda9279dSmrg		} else if (dblend == BF(ONE_MINUS_SRC_ALPHA)) {
234fda9279dSmrg			dblend = BF(ONE_MINUS_SRC_COLOR);
235fda9279dSmrg		}
236fda9279dSmrg	}
237fda9279dSmrg
238fda9279dSmrg	if (sblend == BF(ONE) && dblend == BF(ZERO)) {
239fda9279dSmrg		BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1);
240fda9279dSmrg		PUSH_DATA (push, 0);
241fda9279dSmrg	} else {
242fda9279dSmrg		BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 3);
243fda9279dSmrg		PUSH_DATA (push, 1);
244fda9279dSmrg		PUSH_DATA (push, (sblend << 16) | sblend);
245fda9279dSmrg		PUSH_DATA (push, (dblend << 16) | dblend);
246fda9279dSmrg	}
247fda9279dSmrg}
248fda9279dSmrg
249fda9279dSmrgstatic Bool
250fda9279dSmrgNV30EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit)
251fda9279dSmrg{
252fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
253fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
254fda9279dSmrg	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
255fda9279dSmrg	nv_pict_texture_format_t *fmt;
256fda9279dSmrg	unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
257fda9279dSmrg	uint32_t pitch = exaGetPixmapPitch(pPix);
258fda9279dSmrg	uint32_t log2h = log2i(pPix->drawable.height);
259fda9279dSmrg	uint32_t log2w = log2i(pPix->drawable.width);
260fda9279dSmrg	uint32_t card_filter, card_repeat;
261fda9279dSmrg
262fda9279dSmrg	fmt = NV30_GetPictTextureFormat(pPict->format);
263fda9279dSmrg	if (!fmt)
264fda9279dSmrg		return FALSE;
265fda9279dSmrg
266fda9279dSmrg	card_repeat = 3; /* repeatNone */
267fda9279dSmrg
268fda9279dSmrg	if (pPict->filter == PictFilterBilinear)
269fda9279dSmrg		card_filter = 2;
270fda9279dSmrg	else
271fda9279dSmrg		card_filter = 1;
272fda9279dSmrg
273fda9279dSmrg	BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8);
274fda9279dSmrg	PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), bo, 0, reloc);
275fda9279dSmrg	PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), bo, (1 << 16) | 8 |
276fda9279dSmrg			 NV30_3D_TEX_FORMAT_DIMS_2D |
277fda9279dSmrg			 (fmt->card_fmt << NV30_3D_TEX_FORMAT_FORMAT__SHIFT) |
278fda9279dSmrg			 (log2w << NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT) |
279fda9279dSmrg			 (log2h << NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT),
280fda9279dSmrg			 reloc, NV30_3D_TEX_FORMAT_DMA0,
281fda9279dSmrg			 NV30_3D_TEX_FORMAT_DMA1);
282fda9279dSmrg	PUSH_DATA (push, (card_repeat << NV30_3D_TEX_WRAP_S__SHIFT) |
283fda9279dSmrg			 (card_repeat << NV30_3D_TEX_WRAP_T__SHIFT) |
284fda9279dSmrg			 (card_repeat << NV30_3D_TEX_WRAP_R__SHIFT));
285fda9279dSmrg	PUSH_DATA (push, NV30_3D_TEX_ENABLE_ENABLE);
286fda9279dSmrg	PUSH_DATA (push, (pitch << NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT ) |
287fda9279dSmrg			 fmt->card_swz);
288fda9279dSmrg	PUSH_DATA (push, (card_filter << NV30_3D_TEX_FILTER_MIN__SHIFT) |
289fda9279dSmrg			 (card_filter << NV30_3D_TEX_FILTER_MAG__SHIFT) |
290fda9279dSmrg			 0x2000 /* engine lock */);
291fda9279dSmrg	PUSH_DATA (push, (pPix->drawable.width <<
292fda9279dSmrg			  NV30_3D_TEX_NPOT_SIZE_W__SHIFT) |
293fda9279dSmrg			 pPix->drawable.height);
294fda9279dSmrg	PUSH_DATA (push, 0x00000000); /* border ARGB */
295fda9279dSmrg	if (pPict->transform) {
296fda9279dSmrg		BEGIN_NV04(push, NV30_3D(TEX_MATRIX_ENABLE(unit)), 1);
297fda9279dSmrg		PUSH_DATA (push, 1);
298fda9279dSmrg		BEGIN_NV04(push, NV30_3D(TEX_MATRIX(unit, 0)), 16);
299fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][0]));
300fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][1]));
301fda9279dSmrg		PUSH_DATAf(push, 0.f);
302fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][2]));
303fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][0]));
304fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][1]));
305fda9279dSmrg		PUSH_DATAf(push, 0.f);
306fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][2]));
307fda9279dSmrg		PUSH_DATAf(push, 0.0f);
308fda9279dSmrg		PUSH_DATAf(push, 0.0f);
309fda9279dSmrg		PUSH_DATAf(push, 0.0f);
310fda9279dSmrg		PUSH_DATAf(push, 0.0f);
311fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][0]));
312fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][1]));
313fda9279dSmrg		PUSH_DATAf(push, 0.0f);
314fda9279dSmrg		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][2]));
315fda9279dSmrg	} else {
316fda9279dSmrg		BEGIN_NV04(push, NV30_3D(TEX_MATRIX_ENABLE(unit)), 1);
317fda9279dSmrg		PUSH_DATA (push, 0);
318fda9279dSmrg	}
319fda9279dSmrg
320fda9279dSmrg	return TRUE;
321fda9279dSmrg}
322fda9279dSmrg
323fda9279dSmrg#define RCSRC_COL(i)  (0x01 + (unit))
324fda9279dSmrg#define RCSRC_TEX(i)  (0x08 + (unit)) /* fragprog register */
325fda9279dSmrg#define RCSEL_COLOR   (0x00)
326fda9279dSmrg#define RCSEL_ALPHA   (0x10)
327fda9279dSmrg#define RCINP_ZERO    (0x00)
328fda9279dSmrg#define RCINP_ONE     (0x20)
329fda9279dSmrg#define RCINP_A__SHIFT 24
330fda9279dSmrg#define RCINP_B__SHIFT 16
331fda9279dSmrg
332fda9279dSmrgstatic Bool
333fda9279dSmrgNV30EXAPicture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit,
334fda9279dSmrg	       uint32_t *color, uint32_t *alpha, uint32_t *solid)
335fda9279dSmrg{
336fda9279dSmrg	uint32_t shift, source;
337fda9279dSmrg
338fda9279dSmrg	if (pPict && pPict->pDrawable) {
339fda9279dSmrg		if (!NV30EXATexture(pScrn, pPix, pPict, unit))
340fda9279dSmrg			return FALSE;
341fda9279dSmrg		*solid = 0x00000000;
342fda9279dSmrg		source = RCSRC_TEX(unit);
343fda9279dSmrg	} else
344fda9279dSmrg	if (pPict) {
345fda9279dSmrg		*solid = pPict->pSourcePict->solidFill.color;
346fda9279dSmrg		source = RCSRC_COL(unit);
347fda9279dSmrg	}
348fda9279dSmrg
349fda9279dSmrg	if (pPict && PICT_FORMAT_RGB(pPict->format))
350fda9279dSmrg		*color = RCSEL_COLOR | source;
351fda9279dSmrg	else
352fda9279dSmrg		*color = RCSEL_ALPHA | RCINP_ZERO;
353fda9279dSmrg
354fda9279dSmrg	if (pPict && PICT_FORMAT_A(pPict->format))
355fda9279dSmrg		*alpha = RCSEL_ALPHA | source;
356fda9279dSmrg	else
357fda9279dSmrg		*alpha = RCSEL_ALPHA | RCINP_ONE;
358fda9279dSmrg
359fda9279dSmrg	if (unit)
360fda9279dSmrg		shift = RCINP_B__SHIFT;
361fda9279dSmrg	else
362fda9279dSmrg		shift = RCINP_A__SHIFT;
363fda9279dSmrg	*color <<= shift;
364fda9279dSmrg	*alpha <<= shift;
365fda9279dSmrg	return TRUE;
366fda9279dSmrg}
367fda9279dSmrg
368fda9279dSmrgstatic Bool
369fda9279dSmrgNV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict)
370fda9279dSmrg{
371fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
372fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
373fda9279dSmrg	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
374fda9279dSmrg	uint32_t pitch = exaGetPixmapPitch(pPix);
375fda9279dSmrg	nv_pict_surface_format_t *fmt;
376fda9279dSmrg
377fda9279dSmrg	fmt = NV30_GetPictSurfaceFormat(pPict->format);
378fda9279dSmrg	if (!fmt) {
379fda9279dSmrg		ErrorF("AIII no format\n");
380fda9279dSmrg		return FALSE;
381fda9279dSmrg	}
382fda9279dSmrg
383fda9279dSmrg	BEGIN_NV04(push, NV30_3D(RT_FORMAT), 3);
384fda9279dSmrg	PUSH_DATA (push, fmt->card_fmt); /* format */
385fda9279dSmrg	PUSH_DATA (push, pitch << 16 | pitch);
386fda9279dSmrg	PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), bo, 0,
387fda9279dSmrg			 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
388fda9279dSmrg	return TRUE;
389fda9279dSmrg}
390fda9279dSmrg
391fda9279dSmrgstatic Bool
392fda9279dSmrgNV30EXACheckCompositeTexture(PicturePtr pPict, PicturePtr pdPict, int op)
393fda9279dSmrg{
394fda9279dSmrg	nv_pict_texture_format_t *fmt;
395fda9279dSmrg	int w = 1, h = 1;
396fda9279dSmrg
397fda9279dSmrg	if (pPict->pDrawable) {
398fda9279dSmrg		w = pPict->pDrawable->width;
399fda9279dSmrg		h = pPict->pDrawable->height;
400fda9279dSmrg	} else {
401fda9279dSmrg		if (pPict->pSourcePict->type != SourcePictTypeSolidFill)
402fda9279dSmrg			NOUVEAU_FALLBACK("gradient pictures unsupported\n");
403fda9279dSmrg	}
404fda9279dSmrg
405fda9279dSmrg	if ((w > 4096) || (h > 4096))
406fda9279dSmrg		NOUVEAU_FALLBACK("picture too large, %dx%d\n", w, h);
407fda9279dSmrg
408fda9279dSmrg	fmt = NV30_GetPictTextureFormat(pPict->format);
409fda9279dSmrg	if (!fmt)
410fda9279dSmrg		NOUVEAU_FALLBACK("picture format 0x%08x not supported\n",
411fda9279dSmrg				pPict->format);
412fda9279dSmrg
413fda9279dSmrg	if (pPict->filter != PictFilterNearest &&
414fda9279dSmrg			pPict->filter != PictFilterBilinear)
415fda9279dSmrg		NOUVEAU_FALLBACK("filter 0x%x not supported\n", pPict->filter);
416fda9279dSmrg
417fda9279dSmrg	if (!(w==1 && h==1) && pPict->repeat && pPict->repeatType != RepeatNone)
418fda9279dSmrg		NOUVEAU_FALLBACK("repeat 0x%x not supported (surface %dx%d)\n",
419fda9279dSmrg				 pPict->repeatType,w,h);
420fda9279dSmrg
421fda9279dSmrg	/* Opengl and Render disagree on what should be sampled outside an XRGB
422fda9279dSmrg	 * texture (with no repeating). Opengl has a hardcoded alpha value of
423fda9279dSmrg	 * 1.0, while render expects 0.0. We assume that clipping is done for
424fda9279dSmrg	 * untranformed sources.
425fda9279dSmrg	 */
426fda9279dSmrg	if (NV30PictOp[op].src_alpha && !pPict->repeat &&
427fda9279dSmrg		pPict->transform && (PICT_FORMAT_A(pPict->format) == 0)
428fda9279dSmrg		&& (PICT_FORMAT_A(pdPict->format) != 0))
429fda9279dSmrg		NOUVEAU_FALLBACK("REPEAT_NONE unsupported for XRGB source\n");
430fda9279dSmrg
431fda9279dSmrg	return TRUE;
432fda9279dSmrg}
433fda9279dSmrg
434fda9279dSmrgBool
435fda9279dSmrgNV30EXACheckComposite(int op, PicturePtr psPict,
436fda9279dSmrg		PicturePtr pmPict,
437fda9279dSmrg		PicturePtr pdPict)
438fda9279dSmrg{
439fda9279dSmrg	nv_pict_surface_format_t *fmt;
440fda9279dSmrg	nv_pict_op_t *opr;
441fda9279dSmrg
442fda9279dSmrg	opr = NV30_GetPictOpRec(op);
443fda9279dSmrg	if (!opr)
444fda9279dSmrg		NOUVEAU_FALLBACK("unsupported blend op 0x%x\n", op);
445fda9279dSmrg
446fda9279dSmrg	fmt = NV30_GetPictSurfaceFormat(pdPict->format);
447fda9279dSmrg	if (!fmt)
448fda9279dSmrg		NOUVEAU_FALLBACK("dst picture format 0x%08x not supported\n",
449fda9279dSmrg				pdPict->format);
450fda9279dSmrg
451fda9279dSmrg	if (!NV30EXACheckCompositeTexture(psPict, pdPict, op))
452fda9279dSmrg		NOUVEAU_FALLBACK("src picture\n");
453fda9279dSmrg	if (pmPict) {
454fda9279dSmrg		if (pmPict->componentAlpha &&
455fda9279dSmrg				PICT_FORMAT_RGB(pmPict->format) &&
456fda9279dSmrg				opr->src_alpha && opr->src_card_op != BF(ZERO))
457fda9279dSmrg			NOUVEAU_FALLBACK("mask CA + SA\n");
458fda9279dSmrg		if (!NV30EXACheckCompositeTexture(pmPict, pdPict, op))
459fda9279dSmrg			NOUVEAU_FALLBACK("mask picture\n");
460fda9279dSmrg	}
461fda9279dSmrg
462fda9279dSmrg	return TRUE;
463fda9279dSmrg}
464fda9279dSmrg
465fda9279dSmrgBool
466fda9279dSmrgNV30EXAPrepareComposite(int op, PicturePtr psPict,
467fda9279dSmrg		PicturePtr pmPict,
468fda9279dSmrg		PicturePtr pdPict,
469fda9279dSmrg		PixmapPtr  psPix,
470fda9279dSmrg		PixmapPtr  pmPix,
471fda9279dSmrg		PixmapPtr  pdPix)
472fda9279dSmrg{
473fda9279dSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen);
474fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
475fda9279dSmrg	nv_pict_op_t *blend = NV30_GetPictOpRec(op);
476fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
477fda9279dSmrg	uint32_t sc, sa, mc, ma, solid[2];
478fda9279dSmrg
479fda9279dSmrg	if (!PUSH_SPACE(push, 128))
480fda9279dSmrg		return FALSE;
481fda9279dSmrg	PUSH_RESET(push);
482fda9279dSmrg
483fda9279dSmrg	/* setup render target and blending */
484fda9279dSmrg	if (!NV30_SetupSurface(pScrn, pdPix, pdPict))
485fda9279dSmrg		return FALSE;
486fda9279dSmrg	NV30_SetupBlend(pScrn, blend, pdPict->format,
487fda9279dSmrg			(pmPict && pmPict->componentAlpha &&
488fda9279dSmrg			 PICT_FORMAT_RGB(pmPict->format)));
489fda9279dSmrg
490fda9279dSmrg	/* select picture sources */
491fda9279dSmrg	if (!NV30EXAPicture(pScrn, psPix, psPict, 0, &sc, &sa, &solid[0]))
492fda9279dSmrg		return FALSE;
493fda9279dSmrg	if (!NV30EXAPicture(pScrn, pmPix, pmPict, 1, &mc, &ma, &solid[1]))
494fda9279dSmrg		return FALSE;
495fda9279dSmrg
496fda9279dSmrg	/* configure register combiners */
497fda9279dSmrg	BEGIN_NV04(push, NV30_3D(RC_IN_ALPHA(0)), 6);
498fda9279dSmrg	PUSH_DATA (push, sa | ma);
499fda9279dSmrg	if (pmPict &&
500fda9279dSmrg	    pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) {
501fda9279dSmrg		if (blend->src_alpha)
502fda9279dSmrg			PUSH_DATA(push, sa | mc);
503fda9279dSmrg		else
504fda9279dSmrg			PUSH_DATA(push, sc | mc);
505fda9279dSmrg	} else {
506fda9279dSmrg		PUSH_DATA(push, sc | ma);
507fda9279dSmrg	}
508fda9279dSmrg	PUSH_DATA (push, solid[0]);
509fda9279dSmrg	PUSH_DATA (push, solid[1]);
510fda9279dSmrg	PUSH_DATA (push, 0x00000c00);
511fda9279dSmrg	PUSH_DATA (push, 0x00000c00);
512fda9279dSmrg	BEGIN_NV04(push, NV30_3D(RC_FINAL0), 3);
513fda9279dSmrg	if (pdPict->format != PICT_a8)
514fda9279dSmrg		PUSH_DATA (push, 0x0000000c);
515fda9279dSmrg	else
516fda9279dSmrg		PUSH_DATA (push, 0x0000001c);
517fda9279dSmrg	PUSH_DATA (push, 0x00001c00);
518fda9279dSmrg	PUSH_DATA (push, 0x01000101);
519fda9279dSmrg
520fda9279dSmrg	/* select fragprog which just sources textures for combiners */
521fda9279dSmrg	BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);
522fda9279dSmrg	PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch, PFP_PASS,
523fda9279dSmrg			 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
524fda9279dSmrg			 NOUVEAU_BO_OR,
525fda9279dSmrg			 NV30_3D_FP_ACTIVE_PROGRAM_DMA0,
526fda9279dSmrg			 NV30_3D_FP_ACTIVE_PROGRAM_DMA1);
527fda9279dSmrg	BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1);
528fda9279dSmrg	PUSH_DATA (push, 0x0001000f);
529fda9279dSmrg	BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);
530fda9279dSmrg	PUSH_DATA (push, 0x00000000);
531fda9279dSmrg	BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1);
532fda9279dSmrg	PUSH_DATA (push, 3);
533fda9279dSmrg
534fda9279dSmrg	nouveau_pushbuf_bufctx(push, pNv->bufctx);
535fda9279dSmrg	if (nouveau_pushbuf_validate(push)) {
536fda9279dSmrg		nouveau_pushbuf_bufctx(push, NULL);
537fda9279dSmrg		return FALSE;
538fda9279dSmrg	}
539fda9279dSmrg
540fda9279dSmrg	return TRUE;
541fda9279dSmrg}
542fda9279dSmrg
543fda9279dSmrgstatic __inline__ void
544fda9279dSmrgPUSH_VTX2s(struct nouveau_pushbuf *push,
545fda9279dSmrg	   int x1, int y1, int x2, int y2, int dx, int dy)
546fda9279dSmrg{
547fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(8)), 2);
548fda9279dSmrg	PUSH_DATA (push, ((y1 & 0xffff) << 16) | (x1 & 0xffff));
549fda9279dSmrg	PUSH_DATA (push, ((y2 & 0xffff) << 16) | (x2 & 0xffff));
550fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
551fda9279dSmrg	PUSH_DATA (push, ((dy & 0xffff) << 16) | (dx & 0xffff));
552fda9279dSmrg}
553fda9279dSmrg
554fda9279dSmrgvoid
555fda9279dSmrgNV30EXAComposite(PixmapPtr pdPix,
556fda9279dSmrg		 int sx, int sy, int mx, int my, int dx, int dy, int w, int h)
557fda9279dSmrg{
558fda9279dSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen);
559fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
560fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
561fda9279dSmrg
562fda9279dSmrg	if (!PUSH_SPACE(push, 64))
563fda9279dSmrg		return;
564fda9279dSmrg
565fda9279dSmrg	/* We're drawing a triangle, we need to scissor it to a quad. */
566fda9279dSmrg	/* The scissors are here for a good reason, we don't get the full
567fda9279dSmrg	 * image, but just a part.
568fda9279dSmrg	 */
569fda9279dSmrg	/* Handling the cliprects is done for us already. */
570fda9279dSmrg	BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
571fda9279dSmrg	PUSH_DATA (push, (w << 16) | dx);
572fda9279dSmrg	PUSH_DATA (push, (h << 16) | dy);
573fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
574fda9279dSmrg	PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_TRIANGLES);
575fda9279dSmrg	PUSH_VTX2s(push, sx, sy + (h * 2), mx, my + (h * 2), dx, dy + (h * 2));
576fda9279dSmrg	PUSH_VTX2s(push, sx, sy, mx, my, dx, dy);
577fda9279dSmrg	PUSH_VTX2s(push, sx + (w * 2), sy, mx + (w * 2), my, dx + (w * 2), dy);
578fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
579fda9279dSmrg	PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
580fda9279dSmrg}
581fda9279dSmrg
582fda9279dSmrgvoid
583fda9279dSmrgNV30EXADoneComposite(PixmapPtr pdPix)
584fda9279dSmrg{
585fda9279dSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen);
586fda9279dSmrg	nouveau_pushbuf_bufctx(NVPTR(pScrn)->pushbuf, NULL);
587fda9279dSmrg}
588fda9279dSmrg
589fda9279dSmrgBool
590fda9279dSmrgNVAccelInitNV30TCL(ScrnInfoPtr pScrn)
591fda9279dSmrg{
592fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
593fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
594fda9279dSmrg	struct nv04_fifo *fifo = pNv->channel->data;
595fda9279dSmrg	uint32_t class = 0, chipset;
596fda9279dSmrg	int i;
597fda9279dSmrg
598fda9279dSmrg	NVXVComputeBicubicFilter(pNv->scratch, XV_TABLE, XV_TABLE_SIZE);
599fda9279dSmrg
600fda9279dSmrg#define NV30TCL_CHIPSET_3X_MASK 0x00000003
601fda9279dSmrg#define NV35TCL_CHIPSET_3X_MASK 0x000001e0
602fda9279dSmrg#define NV30_3D_CHIPSET_3X_MASK 0x00000010
603fda9279dSmrg
604fda9279dSmrg	chipset = pNv->dev->chipset;
605fda9279dSmrg	if ((chipset & 0xf0) != NV_ARCH_30)
606fda9279dSmrg		return TRUE;
607fda9279dSmrg	chipset &= 0xf;
608fda9279dSmrg
609fda9279dSmrg	if (NV30TCL_CHIPSET_3X_MASK & (1<<chipset))
610fda9279dSmrg		class = NV30_3D_CLASS;
611fda9279dSmrg	else if (NV35TCL_CHIPSET_3X_MASK & (1<<chipset))
612fda9279dSmrg		class = NV35_3D_CLASS;
613fda9279dSmrg	else if (NV30_3D_CHIPSET_3X_MASK & (1<<chipset))
614fda9279dSmrg		class = NV34_3D_CLASS;
615fda9279dSmrg	else {
616fda9279dSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
617fda9279dSmrg			   "NV30EXA: Unknown chipset NV3%1x\n", chipset);
618fda9279dSmrg		return FALSE;
619fda9279dSmrg	}
620fda9279dSmrg
621fda9279dSmrg	if (nouveau_object_new(pNv->channel, Nv3D, class, NULL, 0, &pNv->Nv3D))
622fda9279dSmrg		return FALSE;
623fda9279dSmrg
624fda9279dSmrg	if (!PUSH_SPACE(push, 256))
625fda9279dSmrg		return FALSE;
626fda9279dSmrg
627fda9279dSmrg	BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1);
628fda9279dSmrg	PUSH_DATA (push, pNv->Nv3D->handle);
629fda9279dSmrg	BEGIN_NV04(push, NV30_3D(DMA_TEXTURE0), 3);
630fda9279dSmrg	PUSH_DATA (push, fifo->vram);
631fda9279dSmrg	PUSH_DATA (push, fifo->gart);
632fda9279dSmrg	PUSH_DATA (push, fifo->vram);
633fda9279dSmrg	BEGIN_NV04(push, NV30_3D(DMA_UNK1AC), 1);
634fda9279dSmrg	PUSH_DATA (push, fifo->vram);
635fda9279dSmrg	BEGIN_NV04(push, NV30_3D(DMA_COLOR0), 2);
636fda9279dSmrg	PUSH_DATA (push, fifo->vram);
637fda9279dSmrg	PUSH_DATA (push, fifo->vram);
638fda9279dSmrg	BEGIN_NV04(push, NV30_3D(DMA_UNK1B0), 1);
639fda9279dSmrg	PUSH_DATA (push, fifo->vram);
640fda9279dSmrg
641fda9279dSmrg	for (i=1; i<8; i++) {
642fda9279dSmrg		BEGIN_NV04(push, NV30_3D(VIEWPORT_CLIP_HORIZ(i)), 2);
643fda9279dSmrg		PUSH_DATA (push, 0);
644fda9279dSmrg		PUSH_DATA (push, 0);
645fda9279dSmrg	}
646fda9279dSmrg
64716ee1e9aSmrg	BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
648fda9279dSmrg	PUSH_DATA (push, 1);
649fda9279dSmrg
65016ee1e9aSmrg	BEGIN_NV04(push, NV40_3D(MIPMAP_ROUNDING), 1);
65116ee1e9aSmrg	PUSH_DATA (push, NV40_3D_MIPMAP_ROUNDING_MODE_DOWN);
65216ee1e9aSmrg	BEGIN_NV04(push, NV30_3D(FLATSHADE_FIRST), 1);
653fda9279dSmrg	PUSH_DATA (push, 0);
654fda9279dSmrg	BEGIN_NV04(push, SUBC_3D(0x1d80), 1);
655fda9279dSmrg	PUSH_DATA (push, 3);
65616ee1e9aSmrg	BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1);
657fda9279dSmrg	PUSH_DATA (push, 0x00030004);
658fda9279dSmrg
659fda9279dSmrg	/* NEW */
660fda9279dSmrg	BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
661fda9279dSmrg	PUSH_DATA (push, 0);
662fda9279dSmrg	BEGIN_NV04(push, SUBC_3D(0x17e0), 3);
663fda9279dSmrg	PUSH_DATA (push, 0);
664fda9279dSmrg	PUSH_DATA (push, 0);
665fda9279dSmrg	PUSH_DATA (push, 0x3f800000);
666fda9279dSmrg	BEGIN_NV04(push, SUBC_3D(0x1f80), 16);
667fda9279dSmrg	PUSH_DATA (push, 0); PUSH_DATA (push, 0); PUSH_DATA (push, 0); PUSH_DATA (push, 0);
668fda9279dSmrg	PUSH_DATA (push, 0); PUSH_DATA (push, 0); PUSH_DATA (push, 0); PUSH_DATA (push, 0);
669fda9279dSmrg	PUSH_DATA (push, 0x0000ffff);
670fda9279dSmrg	PUSH_DATA (push, 0); PUSH_DATA (push, 0); PUSH_DATA (push, 0); PUSH_DATA (push, 0);
671fda9279dSmrg	PUSH_DATA (push, 0); PUSH_DATA (push, 0); PUSH_DATA (push, 0);
672fda9279dSmrg
67316ee1e9aSmrg	BEGIN_NV04(push, NV30_3D(FLIP_SET_READ), 3);
674fda9279dSmrg	PUSH_DATA (push, 0);
675fda9279dSmrg	PUSH_DATA (push, 1);
676fda9279dSmrg	PUSH_DATA (push, 2);
677fda9279dSmrg
67816ee1e9aSmrg	BEGIN_NV04(push, NV15_BLIT(FLIP_SET_READ), 3);
679fda9279dSmrg	PUSH_DATA (push, 0);
680fda9279dSmrg	PUSH_DATA (push, 1);
681fda9279dSmrg	PUSH_DATA (push, 2);
682fda9279dSmrg
68316ee1e9aSmrg	BEGIN_NV04(push, NV30_3D(COORD_CONVENTIONS), 1);
684fda9279dSmrg	PUSH_DATA (push, 0x00001200);
685fda9279dSmrg
686fda9279dSmrg	BEGIN_NV04(push, NV30_3D(MULTISAMPLE_CONTROL), 1);
687fda9279dSmrg	PUSH_DATA (push, 0xffff0000);
688fda9279dSmrg
689fda9279dSmrg	/* Attempt to setup a known state.. Probably missing a heap of
690fda9279dSmrg	 * stuff here..
691fda9279dSmrg	 */
692fda9279dSmrg	BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 1);
693fda9279dSmrg	PUSH_DATA (push, 0);
694fda9279dSmrg	BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(1)), 1);
695fda9279dSmrg	PUSH_DATA (push, 0);
696fda9279dSmrg	BEGIN_NV04(push, NV30_3D(ALPHA_FUNC_ENABLE), 1);
697fda9279dSmrg	PUSH_DATA (push, 0);
698fda9279dSmrg	BEGIN_NV04(push, NV30_3D(DEPTH_WRITE_ENABLE), 2);
699fda9279dSmrg	PUSH_DATA (push, 0); /* wr disable */
700fda9279dSmrg	PUSH_DATA (push, 0); /* test disable */
701fda9279dSmrg	BEGIN_NV04(push, NV30_3D(COLOR_MASK), 1);
702fda9279dSmrg	PUSH_DATA (push, 0x01010101); /* TR,TR,TR,TR */
703fda9279dSmrg	BEGIN_NV04(push, NV30_3D(CULL_FACE_ENABLE), 1);
704fda9279dSmrg	PUSH_DATA (push, 0);
705fda9279dSmrg	BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 5);
706fda9279dSmrg	PUSH_DATA (push, 0);				/* Blend enable */
707fda9279dSmrg	PUSH_DATA (push, 0);				/* Blend src */
708fda9279dSmrg	PUSH_DATA (push, 0);				/* Blend dst */
709fda9279dSmrg	PUSH_DATA (push, 0x00000000);			/* Blend colour */
710fda9279dSmrg	PUSH_DATA (push, 0x8006);			/* FUNC_ADD */
711fda9279dSmrg	BEGIN_NV04(push, NV30_3D(COLOR_LOGIC_OP_ENABLE), 2);
712fda9279dSmrg	PUSH_DATA (push, 0);
713fda9279dSmrg	PUSH_DATA (push, 0x1503 /*GL_COPY*/);
714fda9279dSmrg	BEGIN_NV04(push, NV30_3D(DITHER_ENABLE), 1);
715fda9279dSmrg	PUSH_DATA (push, 1);
716fda9279dSmrg	BEGIN_NV04(push, NV30_3D(SHADE_MODEL), 1);
717fda9279dSmrg	PUSH_DATA (push, 0x1d01 /*GL_SMOOTH*/);
718fda9279dSmrg	BEGIN_NV04(push, NV30_3D(POLYGON_OFFSET_FACTOR),2);
719fda9279dSmrg	PUSH_DATAf(push, 0.0);
720fda9279dSmrg	PUSH_DATAf(push, 0.0);
721fda9279dSmrg	BEGIN_NV04(push, NV30_3D(POLYGON_MODE_FRONT), 2);
722fda9279dSmrg	PUSH_DATA (push, 0x1b02 /*GL_FILL*/);
723fda9279dSmrg	PUSH_DATA (push, 0x1b02 /*GL_FILL*/);
724fda9279dSmrg	/* - Disable texture units
725fda9279dSmrg	 * - Set fragprog to MOVR result.color, fragment.color */
726fda9279dSmrg	for (i=0;i<4;i++) {
727fda9279dSmrg		BEGIN_NV04(push, NV30_3D(TEX_ENABLE(i)), 1);
728fda9279dSmrg		PUSH_DATA (push, 0);
729fda9279dSmrg	}
730fda9279dSmrg	/* Polygon stipple */
731fda9279dSmrg	BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_PATTERN(0)), 0x20);
732fda9279dSmrg	for (i=0;i<0x20;i++)
733fda9279dSmrg		PUSH_DATA (push, 0xFFFFFFFF);
734fda9279dSmrg
735fda9279dSmrg	BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
736fda9279dSmrg	PUSH_DATAf(push, 0.0);
737fda9279dSmrg	PUSH_DATAf(push, 1.0);
738fda9279dSmrg
739fda9279dSmrg	/* Ok.  If you start X with the nvidia driver, kill it, and then
740fda9279dSmrg	 * start X with nouveau you will get black rendering instead of
741fda9279dSmrg	 * what you'd expect.  This fixes the problem, and it seems that
742fda9279dSmrg	 * it's not needed between nouveau restarts - which suggests that
743fda9279dSmrg	 * the 3D context (wherever it's stored?) survives somehow.
744fda9279dSmrg	 */
74516ee1e9aSmrg	//BEGIN_NV04(push, NV30_3D(FP_CONTROL),1);
746fda9279dSmrg	//PUSH_DATA (push, 0x03008000);
747fda9279dSmrg
748fda9279dSmrg	int w=4096;
749fda9279dSmrg	int h=4096;
750fda9279dSmrg	int pitch=4096*4;
751fda9279dSmrg	BEGIN_NV04(push, NV30_3D(RT_HORIZ), 5);
752fda9279dSmrg	PUSH_DATA (push, w<<16);
753fda9279dSmrg	PUSH_DATA (push, h<<16);
754fda9279dSmrg	PUSH_DATA (push, 0x148); /* format */
755fda9279dSmrg	PUSH_DATA (push, pitch << 16 | pitch);
756fda9279dSmrg	PUSH_DATA (push, 0x0);
757fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VIEWPORT_TX_ORIGIN), 1);
758fda9279dSmrg	PUSH_DATA (push, 0);
75916ee1e9aSmrg        BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
760fda9279dSmrg        PUSH_DATA (push, (w<<16) | 0);
761fda9279dSmrg        PUSH_DATA (push, (h<<16) | 0);
762fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VIEWPORT_CLIP_HORIZ(0)), 2);
763fda9279dSmrg	PUSH_DATA (push, (w-1)<<16);
764fda9279dSmrg	PUSH_DATA (push, (h-1)<<16);
765fda9279dSmrg	BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
766fda9279dSmrg	PUSH_DATA (push, w<<16);
767fda9279dSmrg	PUSH_DATA (push, h<<16);
768fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
769fda9279dSmrg	PUSH_DATA (push, w<<16);
770fda9279dSmrg	PUSH_DATA (push, h<<16);
771fda9279dSmrg
772fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
773fda9279dSmrg	PUSH_DATAf(push, 0.0);
774fda9279dSmrg	PUSH_DATAf(push, 0.0);
775fda9279dSmrg	PUSH_DATAf(push, 0.0);
776fda9279dSmrg	PUSH_DATAf(push, 0.0);
777fda9279dSmrg	PUSH_DATAf(push, 1.0);
778fda9279dSmrg	PUSH_DATAf(push, 1.0);
779fda9279dSmrg	PUSH_DATAf(push, 1.0);
780fda9279dSmrg	PUSH_DATAf(push, 0.0);
781fda9279dSmrg
782fda9279dSmrg	BEGIN_NV04(push, NV30_3D(MODELVIEW_MATRIX(0)), 16);
783fda9279dSmrg	PUSH_DATAf(push, 1.0);
784fda9279dSmrg	PUSH_DATAf(push, 0.0);
785fda9279dSmrg	PUSH_DATAf(push, 0.0);
786fda9279dSmrg	PUSH_DATAf(push, 0.0);
787fda9279dSmrg	PUSH_DATAf(push, 0.0);
788fda9279dSmrg	PUSH_DATAf(push, 1.0);
789fda9279dSmrg	PUSH_DATAf(push, 0.0);
790fda9279dSmrg	PUSH_DATAf(push, 0.0);
791fda9279dSmrg	PUSH_DATAf(push, 0.0);
792fda9279dSmrg	PUSH_DATAf(push, 0.0);
793fda9279dSmrg	PUSH_DATAf(push, 1.0);
794fda9279dSmrg	PUSH_DATAf(push, 0.0);
795fda9279dSmrg	PUSH_DATAf(push, 0.0);
796fda9279dSmrg	PUSH_DATAf(push, 0.0);
797fda9279dSmrg	PUSH_DATAf(push, 0.0);
798fda9279dSmrg	PUSH_DATAf(push, 1.0);
799fda9279dSmrg
800fda9279dSmrg	BEGIN_NV04(push, NV30_3D(PROJECTION_MATRIX(0)), 16);
801fda9279dSmrg	PUSH_DATAf(push, 1.0);
802fda9279dSmrg	PUSH_DATAf(push, 0.0);
803fda9279dSmrg	PUSH_DATAf(push, 0.0);
804fda9279dSmrg	PUSH_DATAf(push, 0.0);
805fda9279dSmrg	PUSH_DATAf(push, 0.0);
806fda9279dSmrg	PUSH_DATAf(push, 1.0);
807fda9279dSmrg	PUSH_DATAf(push, 0.0);
808fda9279dSmrg	PUSH_DATAf(push, 0.0);
809fda9279dSmrg	PUSH_DATAf(push, 0.0);
810fda9279dSmrg	PUSH_DATAf(push, 0.0);
811fda9279dSmrg	PUSH_DATAf(push, 1.0);
812fda9279dSmrg	PUSH_DATAf(push, 0.0);
813fda9279dSmrg	PUSH_DATAf(push, 0.0);
814fda9279dSmrg	PUSH_DATAf(push, 0.0);
815fda9279dSmrg	PUSH_DATAf(push, 0.0);
816fda9279dSmrg	PUSH_DATAf(push, 1.0);
817fda9279dSmrg
818fda9279dSmrg	BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
819fda9279dSmrg	PUSH_DATA (push, 4096<<16);
820fda9279dSmrg	PUSH_DATA (push, 4096<<16);
821fda9279dSmrg
822fda9279dSmrg	PUSH_DATAu(push, pNv->scratch, PFP_PASS, 2 * 4);
823fda9279dSmrg	PUSH_DATAs(push, 0x18009e80); /* txph r0, a[tex0], t[0] */
824fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc801);
825fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
826fda9279dSmrg	PUSH_DATAs(push, 0x3fe1c800);
827fda9279dSmrg	PUSH_DATAs(push, 0x1802be83); /* txph r1, a[tex1], t[1] */
828fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc801); /* exit */
829fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
830fda9279dSmrg	PUSH_DATAs(push, 0x3fe1c800);
831fda9279dSmrg
832fda9279dSmrg	PUSH_DATAu(push, pNv->scratch, PFP_NV12_BILINEAR, 8 * 4);
833fda9279dSmrg	PUSH_DATAs(push, 0x17028200); /* texr r0.x, a[tex0], t[1] */
834fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc801);
835fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
836fda9279dSmrg	PUSH_DATAs(push, 0x3fe1c800);
837fda9279dSmrg	PUSH_DATAs(push, 0x04000e02); /* madr r1.xyz, r0.x, imm.x, imm.yzww */
838fda9279dSmrg	PUSH_DATAs(push, 0x1c9c0000);
839fda9279dSmrg	PUSH_DATAs(push, 0x00000002);
840fda9279dSmrg	PUSH_DATAs(push, 0x0001f202);
841fda9279dSmrg	PUSH_DATAs(push, 0x3f9507c8); /* { 1.16, -0.87, 0.53, -1.08 } */
842fda9279dSmrg	PUSH_DATAs(push, 0xbf5ee393);
843fda9279dSmrg	PUSH_DATAs(push, 0x3f078fef);
844fda9279dSmrg	PUSH_DATAs(push, 0xbf8a6762);
845fda9279dSmrg	PUSH_DATAs(push, 0x1704ac80); /* texr r0.yz, a[tex1], t[2] */
846fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc801);
847fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
848fda9279dSmrg	PUSH_DATAs(push, 0x3fe1c800);
849fda9279dSmrg	PUSH_DATAs(push, 0x04000e02); /* madr r1.xyz, r0.y, imm, r1 */
850fda9279dSmrg	PUSH_DATAs(push, 0x1c9cab00);
851fda9279dSmrg	PUSH_DATAs(push, 0x0001c802);
852fda9279dSmrg	PUSH_DATAs(push, 0x0001c804);
853fda9279dSmrg	PUSH_DATAs(push, 0x00000000); /* { 0.00, -0.39, 2.02, 0.00 } */
854fda9279dSmrg	PUSH_DATAs(push, 0xbec890d6);
855fda9279dSmrg	PUSH_DATAs(push, 0x40011687);
856fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
857fda9279dSmrg	PUSH_DATAs(push, 0x04000e81); /* madr r0.xyz, r0.z, imm, r1 */
858fda9279dSmrg	PUSH_DATAs(push, 0x1c9d5500);
859fda9279dSmrg	PUSH_DATAs(push, 0x0001c802);
860fda9279dSmrg	PUSH_DATAs(push, 0x0001c804);
861fda9279dSmrg	PUSH_DATAs(push, 0x3fcc432d); /* { 1.60, -0.81, 0.00, 0.00 } */
862fda9279dSmrg	PUSH_DATAs(push, 0xbf501a37);
863fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
864fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
865fda9279dSmrg
866fda9279dSmrg	PUSH_DATAu(push, pNv->scratch, PFP_NV12_BICUBIC, 24 * 4);
867fda9279dSmrg	PUSH_DATAs(push, 0x01008604); /* movr r2.xy, a[tex0] */
868fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc801);
869fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
870fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
871fda9279dSmrg	PUSH_DATAs(push, 0x03000600); /* addr r0.xy, r2, imm.x */
872fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc808);
873fda9279dSmrg	PUSH_DATAs(push, 0x00000002);
874fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
875fda9279dSmrg	PUSH_DATAs(push, 0x3f000000); /* { 0.50, 0.00, 0.00, 0.00 } */
876fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
877fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
878fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
879fda9279dSmrg	PUSH_DATAs(push, 0x17000e06); /* texr r3.xyz, r0, t[0] */
880fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc800);
881fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
882fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
883fda9279dSmrg	PUSH_DATAs(push, 0x17000e00); /* texr r0.xyz, r0.y, t[0] */
884fda9279dSmrg	PUSH_DATAs(push, 0x1c9caa00);
885fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
886fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
887fda9279dSmrg	PUSH_DATAs(push, 0x02000a02); /* mulr r1.xz, r3.xxyy, imm.xxyy */
888fda9279dSmrg	PUSH_DATAs(push, 0x1c9ca00c);
889fda9279dSmrg	PUSH_DATAs(push, 0x0000a002);
890fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
891fda9279dSmrg	PUSH_DATAs(push, 0xbf800000); /* { -1.00, 1.00, 0.00, 0.00 } */
892fda9279dSmrg	PUSH_DATAs(push, 0x3f800000);
893fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
894fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
895fda9279dSmrg	PUSH_DATAs(push, 0x02001402); /* mulr r1.yw, r0.xxyy, imm.xxyy */
896fda9279dSmrg	PUSH_DATAs(push, 0x1c9ca000);
897fda9279dSmrg	PUSH_DATAs(push, 0x0000a002);
898fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
899fda9279dSmrg	PUSH_DATAs(push, 0xbf800000); /* { -1.00, 1.00, 0.00, 0.00 } */
900fda9279dSmrg	PUSH_DATAs(push, 0x3f800000);
901fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
902fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
903fda9279dSmrg	PUSH_DATAs(push, 0x03001e04); /* addr r2, r2.xyxy, r1 */
904fda9279dSmrg	PUSH_DATAs(push, 0x1c9c8808);
905fda9279dSmrg	PUSH_DATAs(push, 0x0001c804);
906fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
907fda9279dSmrg	PUSH_DATAs(push, 0x17020200); /* texr r0.x, r2, t[1] */
908fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc808);
909fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
910fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
911fda9279dSmrg	PUSH_DATAs(push, 0x17020402); /* texr r1.y, r2.xwxw, t[1] */
912fda9279dSmrg	PUSH_DATAs(push, 0x1c9d9808);
913fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
914fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
915fda9279dSmrg	PUSH_DATAs(push, 0x17020202); /* texr r1.x, r2.zyxy, t[1] */
916fda9279dSmrg	PUSH_DATAs(push, 0x1c9c8c08);
917fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
918fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
919fda9279dSmrg	PUSH_DATAs(push, 0x1f400280); /* lrph r0.x, r0.z, r0, r1.y */
920fda9279dSmrg	PUSH_DATAs(push, 0x1c9d5400);
921fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
922fda9279dSmrg	PUSH_DATAs(push, 0x0000aa04);
923fda9279dSmrg	PUSH_DATAs(push, 0x17020400); /* texr r0.y, r2.zwzz, t[1] */
924fda9279dSmrg	PUSH_DATAs(push, 0x1c9d5c08);
925fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
926fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
927fda9279dSmrg	PUSH_DATAs(push, 0x1f400480); /* lrph r0.y, r0.z, r1.x, r0 */
928fda9279dSmrg	PUSH_DATAs(push, 0x1c9d5400);
929fda9279dSmrg	PUSH_DATAs(push, 0x00000004);
930fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
931fda9279dSmrg	PUSH_DATAs(push, 0x1f400280); /* lrph r0.x, r3.z, r0, r0.y */
932fda9279dSmrg	PUSH_DATAs(push, 0x1c9d540c);
933fda9279dSmrg	PUSH_DATAs(push, 0x0001c900);
934fda9279dSmrg	PUSH_DATAs(push, 0x0000ab00);
935fda9279dSmrg	PUSH_DATAs(push, 0x04400e80); /* madh r0.xyz, r0.x, imm.x, imm.yzww */
936fda9279dSmrg	PUSH_DATAs(push, 0x1c9c0100);
937fda9279dSmrg	PUSH_DATAs(push, 0x00000002);
938fda9279dSmrg	PUSH_DATAs(push, 0x0001f202);
939fda9279dSmrg	PUSH_DATAs(push, 0x3f9507c8); /* { 1.16, -0.87, 0.53, -1.08 } */
940fda9279dSmrg	PUSH_DATAs(push, 0xbf5ee393);
941fda9279dSmrg	PUSH_DATAs(push, 0x3f078fef);
942fda9279dSmrg	PUSH_DATAs(push, 0xbf8a6762);
943fda9279dSmrg	PUSH_DATAs(push, 0x1704ac02); /* texr r1.yz, a[tex1], t[2] */
944fda9279dSmrg	PUSH_DATAs(push, 0x1c9dc801);
945fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
946fda9279dSmrg	PUSH_DATAs(push, 0x0001c800);
947fda9279dSmrg	PUSH_DATAs(push, 0x04400e80); /* madh r0.xyz, r1.y, imm, r0 */
948fda9279dSmrg	PUSH_DATAs(push, 0x1c9caa04);
949fda9279dSmrg	PUSH_DATAs(push, 0x0001c802);
950fda9279dSmrg	PUSH_DATAs(push, 0x0001c900);
951fda9279dSmrg	PUSH_DATAs(push, 0x00000000); /* { 0.00, -0.39, 2.02, 0.00 } */
952fda9279dSmrg	PUSH_DATAs(push, 0xbec890d6);
953fda9279dSmrg	PUSH_DATAs(push, 0x40011687);
954fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
955fda9279dSmrg	PUSH_DATAs(push, 0x04400e81); /* madh r0.xyz, r1.z, imm, r0 */
956fda9279dSmrg	PUSH_DATAs(push, 0x1c9d5404);
957fda9279dSmrg	PUSH_DATAs(push, 0x0001c802);
958fda9279dSmrg	PUSH_DATAs(push, 0x0001c900);
959fda9279dSmrg	PUSH_DATAs(push, 0x3fcc432d); /* { 1.60, -0.81, 0.00, 0.00 } */
960fda9279dSmrg	PUSH_DATAs(push, 0xbf501a37);
961fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
962fda9279dSmrg	PUSH_DATAs(push, 0x00000000);
963fda9279dSmrg
964fda9279dSmrg	return TRUE;
965fda9279dSmrg}
966