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