1fda9279dSmrg/*
2fda9279dSmrg * Copyright 2007-2008 Maarten Maathuis
3fda9279dSmrg * Copyright 2008 Stephane Marchesin
4fda9279dSmrg *
5fda9279dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
6fda9279dSmrg * copy of this software and associated documentation files (the "Software"),
7fda9279dSmrg * to deal in the Software without restriction, including without limitation
8fda9279dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9fda9279dSmrg * and/or sell copies of the Software, and to permit persons to whom the
10fda9279dSmrg * Software is furnished to do so, subject to the following conditions:
11fda9279dSmrg *
12fda9279dSmrg * The above copyright notice and this permission notice (including the next
13fda9279dSmrg * paragraph) shall be included in all copies or substantial portions of the
14fda9279dSmrg * Software.
15fda9279dSmrg *
16fda9279dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17fda9279dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18fda9279dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19fda9279dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20fda9279dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21fda9279dSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22fda9279dSmrg * DEALINGS IN THE SOFTWARE.
23fda9279dSmrg */
24fda9279dSmrg
25fda9279dSmrg#ifdef HAVE_CONFIG_H
26fda9279dSmrg#include "config.h"
27fda9279dSmrg#endif
28fda9279dSmrg
29479f40c1Smrg#include "xorg-config.h"
30fda9279dSmrg#include "xf86xv.h"
31fda9279dSmrg#include <X11/extensions/Xv.h>
32fda9279dSmrg#include "exa.h"
33fda9279dSmrg#include "damage.h"
34fda9279dSmrg#include "dixstruct.h"
35fda9279dSmrg#include "fourcc.h"
36fda9279dSmrg
37fda9279dSmrg#include "nv_include.h"
38fda9279dSmrg#include "nv_dma.h"
39fda9279dSmrg
40fda9279dSmrg#include "hwdefs/nv30-40_3d.xml.h"
41fda9279dSmrg#include "nv04_accel.h"
42fda9279dSmrg
43fda9279dSmrgextern Atom xvSyncToVBlank, xvSetDefaults;
44fda9279dSmrg
45fda9279dSmrg#define SWIZZLE(ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)			\
46fda9279dSmrg	(									\
47fda9279dSmrg	NV30_3D_TEX_SWIZZLE_S0_X_##ts0x | NV30_3D_TEX_SWIZZLE_S0_Y_##ts0y	|	\
48fda9279dSmrg	NV30_3D_TEX_SWIZZLE_S0_Z_##ts0z | NV30_3D_TEX_SWIZZLE_S0_W_##ts0w	|	\
49fda9279dSmrg	NV30_3D_TEX_SWIZZLE_S1_X_##ts1x | NV30_3D_TEX_SWIZZLE_S1_Y_##ts1y |	\
50fda9279dSmrg	NV30_3D_TEX_SWIZZLE_S1_Z_##ts1z | NV30_3D_TEX_SWIZZLE_S1_W_##ts1w		\
51fda9279dSmrg	)
52fda9279dSmrg
53fda9279dSmrg/*
54fda9279dSmrg * Texture 0 : filter table
55fda9279dSmrg * Texture 1 : Y data
56fda9279dSmrg * Texture 2 : UV data
57fda9279dSmrg */
58fda9279dSmrgstatic Bool
59fda9279dSmrgNV30VideoTexture(ScrnInfoPtr pScrn, struct nouveau_bo *src, int offset,
60fda9279dSmrg		 uint16_t width, uint16_t height, uint16_t src_pitch, int unit)
61fda9279dSmrg{
62fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
63fda9279dSmrg	unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
64fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
65fda9279dSmrg	uint32_t card_fmt = 0;
66fda9279dSmrg	uint32_t card_swz = 0;
67fda9279dSmrg	int h = log2i(height);
68fda9279dSmrg	int w = log2i(width);
69fda9279dSmrg
70fda9279dSmrg	switch (unit) {
71fda9279dSmrg	case 0:
72fda9279dSmrg		card_fmt = NV30_3D_TEX_FORMAT_FORMAT_A8R8G8B8;
73fda9279dSmrg		card_swz = SWIZZLE(S1, S1, S1, S1, X, Y, Z, W);
74fda9279dSmrg		break;
75fda9279dSmrg	case 1:
76fda9279dSmrg		card_fmt = NV30_3D_TEX_FORMAT_FORMAT_I8_RECT;
77fda9279dSmrg		card_swz = SWIZZLE(S1, S1, S1, S1, X, X, X, X);
78fda9279dSmrg		break;
79fda9279dSmrg	case 2:
80fda9279dSmrg		card_fmt = NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT;
81fda9279dSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
82fda9279dSmrg		card_swz = SWIZZLE(S1, S1, S1, S1, Z, W, X, Y);
83fda9279dSmrg#else
84fda9279dSmrg		card_swz = SWIZZLE(S1, S1, S1, S1, W, Z, Y, X);
85fda9279dSmrg#endif
86fda9279dSmrg		break;
87fda9279dSmrg	}
88fda9279dSmrg
89fda9279dSmrg	BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8);
90fda9279dSmrg	PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), src, offset, reloc);
91fda9279dSmrg	if (unit == 0) {
92fda9279dSmrg		PUSH_MTHD (push, NV30_3D(TEX_FORMAT(unit)), src,
93fda9279dSmrg				 NV30_3D_TEX_FORMAT_DIMS_1D |
94fda9279dSmrg				 card_fmt | (1 << 16) | 8 /* no idea */ |
95fda9279dSmrg				 (w << NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT) |
96fda9279dSmrg				 (h << NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT),
97fda9279dSmrg				 reloc | NOUVEAU_BO_OR,
98fda9279dSmrg				 NV30_3D_TEX_FORMAT_DMA0,
99fda9279dSmrg				 NV30_3D_TEX_FORMAT_DMA1);
100fda9279dSmrg		PUSH_DATA (push, NV30_3D_TEX_WRAP_S_REPEAT |
101fda9279dSmrg				 NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE |
102fda9279dSmrg				 NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE);
103fda9279dSmrg	} else {
104fda9279dSmrg		PUSH_MTHD (push, NV30_3D(TEX_FORMAT(unit)), src,
105fda9279dSmrg				 NV30_3D_TEX_FORMAT_DIMS_2D |
106fda9279dSmrg				 card_fmt | (1 << 16) | 8 /* no idea */ |
107fda9279dSmrg				 (w << NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT) |
108fda9279dSmrg				 (h << NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT),
109fda9279dSmrg				 reloc | NOUVEAU_BO_OR,
110fda9279dSmrg				 NV30_3D_TEX_FORMAT_DMA0,
111fda9279dSmrg				 NV30_3D_TEX_FORMAT_DMA1);
112fda9279dSmrg		PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE |
113fda9279dSmrg				 NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE |
114fda9279dSmrg				 NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE);
115fda9279dSmrg	}
116fda9279dSmrg
117fda9279dSmrg	PUSH_DATA (push, NV30_3D_TEX_ENABLE_ENABLE);
118fda9279dSmrg	PUSH_DATA (push, (src_pitch << NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT) |
119fda9279dSmrg			 card_swz);
120fda9279dSmrg	if (unit == 0)
121fda9279dSmrg		PUSH_DATA (push, NV30_3D_TEX_FILTER_SIGNED_ALPHA |
122fda9279dSmrg				 NV30_3D_TEX_FILTER_SIGNED_RED |
123fda9279dSmrg				 NV30_3D_TEX_FILTER_SIGNED_GREEN |
124fda9279dSmrg				 NV30_3D_TEX_FILTER_SIGNED_BLUE |
125fda9279dSmrg				 NV30_3D_TEX_FILTER_MIN_LINEAR |
126fda9279dSmrg				 NV30_3D_TEX_FILTER_MAG_LINEAR | 0x2000);
127fda9279dSmrg	else
128fda9279dSmrg		PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR |
129fda9279dSmrg				 NV30_3D_TEX_FILTER_MAG_LINEAR | 0x2000);
130fda9279dSmrg	PUSH_DATA (push, (width << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | height);
131fda9279dSmrg	PUSH_DATA (push, 0); /* border ARGB */
132fda9279dSmrg	BEGIN_NV04(push, NV30_3D(TEX_MATRIX_ENABLE(unit)), 1);
133fda9279dSmrg	PUSH_DATA (push, 0);
134fda9279dSmrg
135fda9279dSmrg	return TRUE;
136fda9279dSmrg}
137fda9279dSmrg
13822d74663Smrgstatic Bool
139fda9279dSmrgNV30GetSurfaceFormat(PixmapPtr ppix, int *fmt_ret)
140fda9279dSmrg{
141fda9279dSmrg	switch (ppix->drawable.bitsPerPixel) {
142fda9279dSmrg		case 32:
143fda9279dSmrg			*fmt_ret = NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
144fda9279dSmrg			break;
145fda9279dSmrg		case 24:
146fda9279dSmrg			*fmt_ret = NV30_3D_RT_FORMAT_COLOR_X8R8G8B8;
147fda9279dSmrg			break;
148fda9279dSmrg		case 16:
149fda9279dSmrg			*fmt_ret = NV30_3D_RT_FORMAT_COLOR_R5G6B5;
150fda9279dSmrg			break;
151fda9279dSmrg		case 8:
152fda9279dSmrg			*fmt_ret = NV30_3D_RT_FORMAT_COLOR_B8;
153fda9279dSmrg			break;
154fda9279dSmrg		default:
155fda9279dSmrg			return FALSE;
156fda9279dSmrg	}
157fda9279dSmrg
158fda9279dSmrg	return TRUE;
159fda9279dSmrg}
160fda9279dSmrg
161fda9279dSmrgvoid
162fda9279dSmrgNV30StopTexturedVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
163fda9279dSmrg{
164fda9279dSmrg}
165fda9279dSmrg
166fda9279dSmrg#define VERTEX_OUT(sx,sy,dx,dy) do {                                           \
167fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VTX_ATTR_2F_X(8)), 4);                        \
168fda9279dSmrg	PUSH_DATAf(push, (sx)); PUSH_DATAf(push, (sy));                        \
169fda9279dSmrg	PUSH_DATAf(push, (sx)/2.0); PUSH_DATAf(push, (sy)/2.0);                \
170fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);                          \
171fda9279dSmrg	PUSH_DATA (push, (((dy)&0xffff)<<16)|((dx)&0xffff));                   \
172fda9279dSmrg} while(0)
173fda9279dSmrg
174fda9279dSmrgint
175fda9279dSmrgNV30PutTextureImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset,
176fda9279dSmrg		    int src_offset2, int id, int src_pitch, BoxPtr dstBox,
177fda9279dSmrg		    int x1, int y1, int x2, int y2,
178fda9279dSmrg		    uint16_t width, uint16_t height,
179fda9279dSmrg		    uint16_t src_w, uint16_t src_h,
180fda9279dSmrg		    uint16_t drw_w, uint16_t drw_h,
181fda9279dSmrg		    RegionPtr clipBoxes,
182fda9279dSmrg		    PixmapPtr ppix,
183fda9279dSmrg		    NVPortPrivPtr pPriv)
184fda9279dSmrg{
185fda9279dSmrg	NVPtr pNv = NVPTR(pScrn);
186fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
187fda9279dSmrg	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
188fda9279dSmrg	Bool bicubic = pPriv->bicubic;
189fda9279dSmrg	float X1, X2, Y1, Y2;
190fda9279dSmrg	BoxPtr pbox;
191fda9279dSmrg	int nbox;
192fda9279dSmrg	int dst_format = 0;
193fda9279dSmrg
194fda9279dSmrg	if (drw_w > 4096 || drw_h > 4096) {
195fda9279dSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
196fda9279dSmrg			"XV: Draw size too large.\n");
197fda9279dSmrg		return BadAlloc;
198fda9279dSmrg	}
199fda9279dSmrg
200fda9279dSmrg	if (!NV30GetSurfaceFormat(ppix, &dst_format)) {
201fda9279dSmrg		ErrorF("No surface format, bad.\n");
202fda9279dSmrg		return BadImplementation;
203fda9279dSmrg	}
204fda9279dSmrg
205fda9279dSmrg	pbox = REGION_RECTS(clipBoxes);
206fda9279dSmrg	nbox = REGION_NUM_RECTS(clipBoxes);
207fda9279dSmrg
208fda9279dSmrg	if (!PUSH_SPACE(push, 128))
209fda9279dSmrg		return FALSE;
210fda9279dSmrg	PUSH_RESET(push);
211fda9279dSmrg
212fda9279dSmrg	BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1);
213fda9279dSmrg	PUSH_DATA (push, 0);
214fda9279dSmrg	BEGIN_NV04(push, NV30_3D(RT_FORMAT), 3);
215fda9279dSmrg	PUSH_DATA (push, NV30_3D_RT_FORMAT_TYPE_LINEAR |
216fda9279dSmrg			 NV30_3D_RT_FORMAT_ZETA_Z24S8 |
217fda9279dSmrg			 dst_format);
218fda9279dSmrg	PUSH_DATA (push, (exaGetPixmapPitch(ppix) << 16) |
219fda9279dSmrg			  exaGetPixmapPitch(ppix));
220fda9279dSmrg	PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), bo, 0,
221fda9279dSmrg			 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
222fda9279dSmrg
223fda9279dSmrg	if (pNv->dev->chipset == 0x30) {
224fda9279dSmrg		int x = 0;
225fda9279dSmrg		int y = 0;
226fda9279dSmrg		int w = ppix->drawable.x + ppix->drawable.width;
227fda9279dSmrg		int h = ppix->drawable.y + ppix->drawable.height;
228fda9279dSmrg
229fda9279dSmrg		BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
230fda9279dSmrg		PUSH_DATA (push, (w<<16)|x);
231fda9279dSmrg		PUSH_DATA (push, (h<<16)|y);
232fda9279dSmrg		BEGIN_NV04(push, NV30_3D(VIEWPORT_CLIP_HORIZ(0)), 2);
233fda9279dSmrg		PUSH_DATA (push, (w-1+x)<<16);
234fda9279dSmrg		PUSH_DATA (push, (h-1+y)<<16);
235fda9279dSmrg		BEGIN_NV04(push, NV30_3D(VIEWPORT_TX_ORIGIN), 1);
236fda9279dSmrg		PUSH_DATA (push, (y<<16)|x);
237fda9279dSmrg	}
238fda9279dSmrg
239fda9279dSmrg	BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1);
240fda9279dSmrg	PUSH_DATA (push, NV30_3D_TEX_UNITS_ENABLE_TX0 |
241fda9279dSmrg			 NV30_3D_TEX_UNITS_ENABLE_TX1);
242fda9279dSmrg
243fda9279dSmrg	if (!NV30VideoTexture(pScrn, pNv->scratch, XV_TABLE, XV_TABLE_SIZE,
244fda9279dSmrg				     1, 0, 0) ||
245fda9279dSmrg	    !NV30VideoTexture(pScrn, src, src_offset, src_w, src_h,
246fda9279dSmrg		    	      src_pitch, 1))
247fda9279dSmrg		return BadImplementation;
248fda9279dSmrg
249fda9279dSmrg	/* We've got NV12 format, which means half width and half height
250fda9279dSmrg	 * texture of chroma channels.
251fda9279dSmrg	 */
252fda9279dSmrg	if (!NV30VideoTexture(pScrn, src, src_offset2, src_w/2, src_h/2,
253fda9279dSmrg			      src_pitch, 2)) {
254fda9279dSmrg		PUSH_RESET(push);
255fda9279dSmrg		return BadImplementation;
256fda9279dSmrg	}
257fda9279dSmrg
258fda9279dSmrg	BEGIN_NV04(push, NV30_3D(TEX_ENABLE(3)), 1);
259fda9279dSmrg	PUSH_DATA (push, 0x0);
260fda9279dSmrg
261fda9279dSmrg	if (drw_w / 2 < src_w || drw_h / 2 < src_h)
262fda9279dSmrg		bicubic = FALSE;
263fda9279dSmrg
264fda9279dSmrg	BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);
265fda9279dSmrg	PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch,
266fda9279dSmrg			 bicubic ? PFP_NV12_BICUBIC : PFP_NV12_BILINEAR,
267fda9279dSmrg			 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
268fda9279dSmrg			 NOUVEAU_BO_OR,
269fda9279dSmrg			 NV30_3D_FP_ACTIVE_PROGRAM_DMA0,
270fda9279dSmrg			 NV30_3D_FP_ACTIVE_PROGRAM_DMA1);
271fda9279dSmrg	BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1);
272fda9279dSmrg	PUSH_DATA (push, 0x0001000f);
273fda9279dSmrg	BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);
274fda9279dSmrg	PUSH_DATA (push, 0x00000001);
275fda9279dSmrg	BEGIN_NV04(push, NV30_3D(RC_ENABLE), 1);
276fda9279dSmrg	PUSH_DATA (push, 0x00000000);
277fda9279dSmrg
278fda9279dSmrg	nouveau_pushbuf_bufctx(push, pNv->bufctx);
279fda9279dSmrg	if (nouveau_pushbuf_validate(push)) {
280fda9279dSmrg		nouveau_pushbuf_bufctx(push, NULL);
281fda9279dSmrg		return BadAlloc;
282fda9279dSmrg	}
283fda9279dSmrg
284fda9279dSmrg	/* Before rendering we wait for vblank in the non-composited case. */
285fda9279dSmrg	if (pPriv->SyncToVBlank)
286fda9279dSmrg		NV11SyncToVBlank(ppix, dstBox);
287fda9279dSmrg
288fda9279dSmrg	/* These are fixed point values in the 16.16 format. */
289fda9279dSmrg	X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000;
290fda9279dSmrg	Y1 = (float)(y1>>16)+(float)(y1&0xFFFF)/(float)0x10000;
291fda9279dSmrg	X2 = (float)(x2>>16)+(float)(x2&0xFFFF)/(float)0x10000;
292fda9279dSmrg	Y2 = (float)(y2>>16)+(float)(y2&0xFFFF)/(float)0x10000;
293fda9279dSmrg
294fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
295fda9279dSmrg	PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_TRIANGLES);
296fda9279dSmrg	while (nbox--) {
297fda9279dSmrg		float tx1=X1+(float)(pbox->x1 - dstBox->x1)*(X2-X1)/(float)(drw_w);
298fda9279dSmrg		float tx2=X1+(float)(pbox->x2 - dstBox->x1)*(src_w)/(float)(drw_w);
299fda9279dSmrg		float ty1=Y1+(float)(pbox->y1 - dstBox->y1)*(Y2-Y1)/(float)(drw_h);
300fda9279dSmrg		float ty2=Y1+(float)(pbox->y2 - dstBox->y1)*(src_h)/(float)(drw_h);
301fda9279dSmrg		int sx1=pbox->x1;
302fda9279dSmrg		int sx2=pbox->x2;
303fda9279dSmrg		int sy1=pbox->y1;
304fda9279dSmrg		int sy2=pbox->y2;
305fda9279dSmrg
306fda9279dSmrg		if (!PUSH_SPACE(push, 64)) {
307fda9279dSmrg			nouveau_pushbuf_bufctx(push, NULL);
308fda9279dSmrg			return BadImplementation;
309fda9279dSmrg		}
310fda9279dSmrg
311fda9279dSmrg		BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
312fda9279dSmrg		PUSH_DATA (push, (sx2 << 16) | 0);
313fda9279dSmrg		PUSH_DATA (push, (sy2 << 16) | 0);
314fda9279dSmrg
315fda9279dSmrg		VERTEX_OUT(tx1, ty1, sx1, sy1);
316fda9279dSmrg		VERTEX_OUT(tx2+(tx2-tx1), ty1, sx2+(sx2-sx1), sy1);
317fda9279dSmrg		VERTEX_OUT(tx1, ty2+(ty2-ty1), sx1, sy2+(sy2-sy1));
318fda9279dSmrg
319fda9279dSmrg		pbox++;
320fda9279dSmrg	}
321fda9279dSmrg	BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
322fda9279dSmrg	PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
323fda9279dSmrg
324fda9279dSmrg	if (pNv->dev->chipset == 0x30) {
325fda9279dSmrg		BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
326fda9279dSmrg		PUSH_DATA (push, 4096 << 16);
327fda9279dSmrg		PUSH_DATA (push, 4096 << 16);
328fda9279dSmrg		BEGIN_NV04(push, NV30_3D(VIEWPORT_CLIP_HORIZ(0)), 2);
329fda9279dSmrg		PUSH_DATA (push, 4095 << 16);
330fda9279dSmrg		PUSH_DATA (push, 4095 << 16);
331fda9279dSmrg		BEGIN_NV04(push, NV30_3D(VIEWPORT_TX_ORIGIN), 1);
332fda9279dSmrg		PUSH_DATA (push, 0);
333fda9279dSmrg	}
334fda9279dSmrg
335fda9279dSmrg	nouveau_pushbuf_bufctx(push, NULL);
336fda9279dSmrg	PUSH_KICK(push);
337fda9279dSmrg	return Success;
338fda9279dSmrg}
339fda9279dSmrg
340fda9279dSmrg/**
341fda9279dSmrg * NV30SetTexturePortAttribute
342fda9279dSmrg * sets the attribute "attribute" of port "data" to value "value"
343fda9279dSmrg * supported attributes:
344fda9279dSmrg * Sync to vblank.
345fda9279dSmrg *
346fda9279dSmrg * @param pScrenInfo
347fda9279dSmrg * @param attribute attribute to set
348fda9279dSmrg * @param value value to which attribute is to be set
349fda9279dSmrg * @param data port from which the attribute is to be set
350fda9279dSmrg *
351fda9279dSmrg * @return Success, if setting is successful
352fda9279dSmrg * BadValue/BadMatch, if value/attribute are invalid
353fda9279dSmrg */
354fda9279dSmrgint
355fda9279dSmrgNV30SetTexturePortAttribute(ScrnInfoPtr pScrn, Atom attribute,
356fda9279dSmrg                       INT32 value, pointer data)
357fda9279dSmrg{
358fda9279dSmrg        NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
359fda9279dSmrg
360fda9279dSmrg        if (attribute == xvSyncToVBlank) {
361fda9279dSmrg                if ((value < 0) || (value > 1))
362fda9279dSmrg                        return BadValue;
363fda9279dSmrg                pPriv->SyncToVBlank = value;
364fda9279dSmrg        } else
365fda9279dSmrg        if (attribute == xvSetDefaults) {
366fda9279dSmrg                pPriv->SyncToVBlank = TRUE;
367fda9279dSmrg        } else
368fda9279dSmrg                return BadMatch;
369fda9279dSmrg
370fda9279dSmrg        return Success;
371fda9279dSmrg}
372fda9279dSmrg
373fda9279dSmrg/**
374fda9279dSmrg * NV30GetTexturePortAttribute
375fda9279dSmrg * reads the value of attribute "attribute" from port "data" into INT32 "*value"
376fda9279dSmrg * Sync to vblank.
377fda9279dSmrg *
378fda9279dSmrg * @param pScrn unused
379fda9279dSmrg * @param attribute attribute to be read
380fda9279dSmrg * @param value value of attribute will be stored here
381fda9279dSmrg * @param data port from which attribute will be read
382fda9279dSmrg * @return Success, if queried attribute exists
383fda9279dSmrg */
384fda9279dSmrgint
385fda9279dSmrgNV30GetTexturePortAttribute(ScrnInfoPtr pScrn, Atom attribute,
386fda9279dSmrg                       INT32 *value, pointer data)
387fda9279dSmrg{
388fda9279dSmrg        NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
389fda9279dSmrg
390fda9279dSmrg        if(attribute == xvSyncToVBlank)
391fda9279dSmrg                *value = (pPriv->SyncToVBlank) ? 1 : 0;
392fda9279dSmrg        else
393fda9279dSmrg                return BadMatch;
394fda9279dSmrg
395fda9279dSmrg        return Success;
396fda9279dSmrg}
397fda9279dSmrg
398