nvc0_xv.c revision fda9279d
1/*
2 * Copyright 2008 Ben Skeggs
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "xf86xv.h"
28#include <X11/extensions/Xv.h>
29#include "exa.h"
30#include "damage.h"
31#include "dixstruct.h"
32#include "fourcc.h"
33
34#include "nv_include.h"
35#include "nvc0_accel.h"
36
37extern Atom xvSyncToVBlank, xvSetDefaults;
38
39static Bool
40nvc0_xv_check_image_put(PixmapPtr ppix)
41{
42	switch (ppix->drawable.bitsPerPixel) {
43	case 32:
44	case 24:
45	case 16:
46	case 15:
47		break;
48	default:
49		return FALSE;
50	}
51
52	if (!nv50_style_tiled_pixmap(ppix))
53		return FALSE;
54
55	return TRUE;
56}
57
58int
59nvc0_xv_image_put(ScrnInfoPtr pScrn,
60		  struct nouveau_bo *src, int packed_y, int uv,
61		  int id, int src_pitch, BoxPtr dstBox,
62		  int x1, int y1, int x2, int y2,
63		  uint16_t width, uint16_t height,
64		  uint16_t src_w, uint16_t src_h,
65		  uint16_t drw_w, uint16_t drw_h,
66		  RegionPtr clipBoxes, PixmapPtr ppix,
67		  NVPortPrivPtr pPriv)
68{
69	NVPtr pNv = NVPTR(pScrn);
70	struct nouveau_bo *dst = nouveau_pixmap_bo(ppix);
71	struct nouveau_pushbuf_refn refs[] = {
72		{ pNv->scratch, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR },
73		{ src, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD },
74		{ dst, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR },
75	};
76	struct nouveau_pushbuf *push = pNv->pushbuf;
77	uint32_t mode = 0xd0005000 | (src->config.nvc0.tile_mode << 18);
78	float X1, X2, Y1, Y2;
79	BoxPtr pbox;
80	int nbox;
81
82	if (!nvc0_xv_check_image_put(ppix))
83		return BadMatch;
84
85	if (!PUSH_SPACE(push, 256))
86		return BadImplementation;
87
88	BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 8);
89	PUSH_DATA (push, dst->offset >> 32);
90	PUSH_DATA (push, dst->offset);
91	PUSH_DATA (push, ppix->drawable.width);
92	PUSH_DATA (push, ppix->drawable.height);
93	switch (ppix->drawable.bitsPerPixel) {
94	case 32: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGRA8_UNORM); break;
95	case 24: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGRX8_UNORM); break;
96	case 16: PUSH_DATA (push, NV50_SURFACE_FORMAT_B5G6R5_UNORM); break;
97	case 15: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGR5_X1_UNORM); break;
98	}
99	PUSH_DATA (push, dst->config.nvc0.tile_mode);
100	PUSH_DATA (push, 1);
101	PUSH_DATA (push, 0);
102
103	BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1);
104	PUSH_DATA (push, 0);
105
106	PUSH_DATAu(push, pNv->scratch, TIC_OFFSET, 16);
107	if (id == FOURCC_YV12 || id == FOURCC_I420) {
108	PUSH_DATA (push, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
109			 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
110			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
111			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
112			 NV50TIC_0_0_FMT_8);
113	PUSH_DATA (push, ((src->offset + packed_y)));
114	PUSH_DATA (push, ((src->offset + packed_y) >> 32) | mode);
115	PUSH_DATA (push, 0x00300000);
116	PUSH_DATA (push, width);
117	PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | height);
118	PUSH_DATA (push, 0x03000000);
119	PUSH_DATA (push, 0x00000000);
120	PUSH_DATA (push, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM |
121			 NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
122			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
123			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
124			 NV50TIC_0_0_FMT_8_8);
125	PUSH_DATA (push, ((src->offset + uv)));
126	PUSH_DATA (push, ((src->offset + uv) >> 32) | mode);
127	PUSH_DATA (push, 0x00300000);
128	PUSH_DATA (push, width >> 1);
129	PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | (height >> 1));
130	PUSH_DATA (push, 0x03000000);
131	PUSH_DATA (push, 0x00000000);
132	} else {
133	if (id == FOURCC_UYVY) {
134	PUSH_DATA (push, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM |
135			 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
136			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
137			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
138			 NV50TIC_0_0_FMT_8_8);
139	} else {
140	PUSH_DATA (push, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
141			 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
142			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
143			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
144			 NV50TIC_0_0_FMT_8_8);
145	}
146	PUSH_DATA (push, ((src->offset + packed_y)));
147	PUSH_DATA (push, ((src->offset + packed_y) >> 32) | mode);
148	PUSH_DATA (push, 0x00300000);
149	PUSH_DATA (push, width);
150	PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | height);
151	PUSH_DATA (push, 0x03000000);
152	PUSH_DATA (push, 0x00000000);
153	if (id == FOURCC_UYVY) {
154	PUSH_DATA (push, NV50TIC_0_0_MAPA_C2 | NV50TIC_0_0_TYPEA_UNORM |
155			 NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
156			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
157			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
158			 NV50TIC_0_0_FMT_8_8_8_8);
159	} else {
160	PUSH_DATA (push, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
161			 NV50TIC_0_0_MAPB_C1 | NV50TIC_0_0_TYPEB_UNORM |
162			 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
163			 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
164			 NV50TIC_0_0_FMT_8_8_8_8);
165	}
166	PUSH_DATA (push, ((src->offset + packed_y)));
167	PUSH_DATA (push, ((src->offset + packed_y) >> 32) | mode);
168	PUSH_DATA (push, 0x00300000);
169	PUSH_DATA (push, (width >> 1));
170	PUSH_DATA (push, (1 << NV50TIC_0_5_DEPTH_SHIFT) | height);
171	PUSH_DATA (push, 0x03000000);
172	PUSH_DATA (push, 0x00000000);
173	}
174
175	PUSH_DATAu(push, pNv->scratch, TSC_OFFSET, 16);
176	PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE |
177			 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE |
178			 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE);
179	PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR |
180			 NV50TSC_1_1_MINF_LINEAR |
181			 NV50TSC_1_1_MIPF_NONE);
182	PUSH_DATA (push, 0x00000000);
183	PUSH_DATA (push, 0x00000000);
184	PUSH_DATA (push, 0x00000000);
185	PUSH_DATA (push, 0x00000000);
186	PUSH_DATA (push, 0x00000000);
187	PUSH_DATA (push, 0x00000000);
188	PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE |
189			 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE |
190			 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE);
191	PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR |
192			 NV50TSC_1_1_MINF_LINEAR |
193			 NV50TSC_1_1_MIPF_NONE);
194	PUSH_DATA (push, 0x00000000);
195	PUSH_DATA (push, 0x00000000);
196	PUSH_DATA (push, 0x00000000);
197	PUSH_DATA (push, 0x00000000);
198	PUSH_DATA (push, 0x00000000);
199	PUSH_DATA (push, 0x00000000);
200
201	BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1);
202	PUSH_DATA (push, PFP_NV12);
203
204	BEGIN_NVC0(push, NVC0_3D(TSC_FLUSH), 1);
205	PUSH_DATA (push, 0);
206	BEGIN_NVC0(push, NVC0_3D(TIC_FLUSH), 1);
207	PUSH_DATA (push, 0);
208	BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1);
209	PUSH_DATA (push, 0);
210
211	PUSH_DATAu(push, pNv->scratch, PVP_DATA, 11);
212	PUSH_DATAf(push, 1.0);
213	PUSH_DATAf(push, 0.0);
214	PUSH_DATAf(push, 0.0);
215	PUSH_DATAf(push, 0.0);
216	PUSH_DATAf(push, 1.0);
217	PUSH_DATAf(push, 0.0);
218	PUSH_DATAf(push, 0.0);
219	PUSH_DATAf(push, 0.0);
220	PUSH_DATAf(push, 1.0);
221	PUSH_DATAf(push, 1.0 / width);
222	PUSH_DATAf(push, 1.0 / height);
223
224	if (pPriv->SyncToVBlank) {
225		NVC0SyncToVBlank(ppix, dstBox);
226	}
227
228	/* These are fixed point values in the 16.16 format. */
229	X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000;
230	Y1 = (float)(y1>>16)+(float)(y1&0xFFFF)/(float)0x10000;
231	X2 = (float)(x2>>16)+(float)(x2&0xFFFF)/(float)0x10000;
232	Y2 = (float)(y2>>16)+(float)(y2&0xFFFF)/(float)0x10000;
233
234	pbox = REGION_RECTS(clipBoxes);
235	nbox = REGION_NUM_RECTS(clipBoxes);
236	while(nbox--) {
237		float tx1=X1+(float)(pbox->x1 - dstBox->x1)*(X2-X1)/(float)(drw_w);
238		float tx2=X1+(float)(pbox->x2 - dstBox->x1)*(src_w)/(float)(drw_w);
239		float ty1=Y1+(float)(pbox->y1 - dstBox->y1)*(Y2-Y1)/(float)(drw_h);
240		float ty2=Y1+(float)(pbox->y2 - dstBox->y1)*(src_h)/(float)(drw_h);
241		int sx1=pbox->x1;
242		int sx2=pbox->x2;
243		int sy1=pbox->y1;
244		int sy2=pbox->y2;
245
246		if (nouveau_pushbuf_space(push, 64, 0, 0) ||
247		    nouveau_pushbuf_refn (push, refs, 3))
248			return BadImplementation;
249
250		BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2);
251		PUSH_DATA (push, sx2 << NVC0_3D_SCISSOR_HORIZ_MAX__SHIFT | sx1);
252		PUSH_DATA (push, sy2 << NVC0_3D_SCISSOR_VERT_MAX__SHIFT | sy1 );
253
254		BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1);
255		PUSH_DATA (push, NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES);
256		PUSH_VTX1s(push, tx1, ty1, sx1, sy1);
257		PUSH_VTX1s(push, tx2+(tx2-tx1), ty1, sx2+(sx2-sx1), sy1);
258		PUSH_VTX1s(push, tx1, ty2+(ty2-ty1), sx1, sy2+(sy2-sy1));
259		BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 1);
260		PUSH_DATA (push, 0);
261
262		pbox++;
263	}
264
265	PUSH_KICK(push);
266	return Success;
267}
268
269void
270nvc0_xv_csc_update(NVPtr pNv, float yco, float *off, float *uco, float *vco)
271{
272	struct nouveau_pushbuf *push = pNv->pushbuf;
273
274	if (nouveau_pushbuf_space(push, 64, 0, 0) ||
275	    nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) {
276					pNv->scratch, NOUVEAU_BO_WR |
277					NOUVEAU_BO_VRAM }, 1))
278		return;
279
280	BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
281	PUSH_DATA (push, 256);
282	PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA) >> 32);
283	PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA));
284	BEGIN_NVC0(push, NVC0_3D(CB_POS), 11);
285	PUSH_DATA (push, 0);
286	PUSH_DATAf(push, yco);
287	PUSH_DATAf(push, off[0]);
288	PUSH_DATAf(push, off[1]);
289	PUSH_DATAf(push, off[2]);
290	PUSH_DATAf(push, uco[0]);
291	PUSH_DATAf(push, uco[1]);
292	PUSH_DATAf(push, uco[2]);
293	PUSH_DATAf(push, vco[0]);
294	PUSH_DATAf(push, vco[1]);
295	PUSH_DATAf(push, vco[2]);
296}
297