1/*
2 * Copyright 2007 Arthur Huillet
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 "xorg-config.h"
28#include "xf86xv.h"
29#include <X11/extensions/Xv.h>
30#include "exa.h"
31#include "damage.h"
32#include "dixstruct.h"
33#include "fourcc.h"
34
35#include "nv_include.h"
36#include "nv_dma.h"
37
38#include "hwdefs/nv_object.xml.h"
39#include "hwdefs/nv01_2d.xml.h"
40#include "nv04_accel.h"
41
42#define FOURCC_RGB 0x0000003
43
44#define VSYNC_POSSIBLE (pNv->dev->chipset >= 0x11)
45
46extern Atom xvSetDefaults, xvSyncToVBlank;
47
48Bool
49NVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset,
50	       int id, int src_pitch, BoxPtr dstBox,
51	       int x1, int y1, int x2, int y2,
52	       short width, short height,
53	       short src_w, short src_h,
54	       short drw_w, short drw_h,
55	       RegionPtr clipBoxes, PixmapPtr ppix)
56{
57	NVPtr	  pNv   = NVPTR(pScrn);
58	NVPortPrivPtr  pPriv = GET_BLIT_PRIVATE(pNv);
59	BoxPtr	 pbox;
60	int	    nbox;
61	CARD32	 dsdx, dtdy;
62	CARD32	 dst_size, dst_point;
63	CARD32	 src_point, src_format;
64	struct nouveau_pushbuf *push = pNv->pushbuf;
65	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
66	struct nv04_fifo *fifo = pNv->channel->data;
67	int dst_format;
68
69	if (!NVAccelGetCtxSurf2DFormatFromPixmap(ppix, &dst_format))
70		return BadImplementation;
71
72	pbox = REGION_RECTS(clipBoxes);
73	nbox = REGION_NUM_RECTS(clipBoxes);
74
75	dsdx = (src_w << 20) / drw_w;
76	dtdy = (src_h << 20) / drw_h;
77
78	dst_size  = ((dstBox->y2 - dstBox->y1) << 16) |
79		     (dstBox->x2 - dstBox->x1);
80	dst_point = (dstBox->y1 << 16) | dstBox->x1;
81
82	src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
83
84	switch(id) {
85	case FOURCC_RGB:
86		src_format = NV03_SIFM_COLOR_FORMAT_X8R8G8B8;
87		break;
88	case FOURCC_UYVY:
89		src_format = NV03_SIFM_COLOR_FORMAT_YB8V8YA8U8;
90		break;
91	default:
92		src_format = NV03_SIFM_COLOR_FORMAT_V8YB8U8YA8;
93		break;
94	}
95
96	if (!PUSH_SPACE(push, 128))
97		return BadImplementation;
98	PUSH_RESET(push);
99
100	BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
101	PUSH_DATA (push, dst_format);
102	PUSH_DATA (push, (exaGetPixmapPitch(ppix) << 16) |
103			  exaGetPixmapPitch(ppix));
104	PUSH_MTHDl(push, NV04_SF2D(OFFSET_SOURCE), bo, 0,
105			 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
106	PUSH_MTHDl(push, NV04_SF2D(OFFSET_DESTIN), bo, 0,
107			 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
108
109	BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1);
110	PUSH_DATA (push, pNv->NvScaledImage->handle);
111	BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
112	PUSH_MTHDo(push, NV03_SIFM(DMA_IMAGE), src, NOUVEAU_BO_RD |
113			 NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
114			 fifo->vram, fifo->gart);
115	if (pNv->dev->chipset >= 0x05) {
116		BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 2);
117		PUSH_DATA (push, src_format);
118		PUSH_DATA (push, NV03_SIFM_OPERATION_SRCCOPY);
119	} else {
120		BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 1);
121		PUSH_DATA (push, src_format);
122	}
123
124	nouveau_pushbuf_bufctx(push, pNv->bufctx);
125	if (nouveau_pushbuf_validate(push)) {
126		nouveau_pushbuf_bufctx(push, NULL);
127		return BadAlloc;
128	}
129
130	if (pPriv->SyncToVBlank)
131		NV11SyncToVBlank(ppix, dstBox);
132
133	while (nbox--) {
134		if (!PUSH_SPACE(push, 16)) {
135			nouveau_pushbuf_bufctx(push, NULL);
136			return BadImplementation;
137		}
138
139		BEGIN_NV04(push, NV04_RECT(COLOR1_A), 1);
140		PUSH_DATA (push, 0);
141
142		BEGIN_NV04(push, NV03_SIFM(CLIP_POINT), 6);
143		PUSH_DATA (push, (pbox->y1 << 16) | pbox->x1);
144		PUSH_DATA (push, (pbox->y2 - pbox->y1) << 16 |
145				 (pbox->x2 - pbox->x1));
146		PUSH_DATA (push, dst_point);
147		PUSH_DATA (push, dst_size);
148		PUSH_DATA (push, dsdx);
149		PUSH_DATA (push, dtdy);
150		BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
151		PUSH_DATA (push, (height << 16) | width);
152		PUSH_DATA (push, NV03_SIFM_FORMAT_FILTER_BILINEAR |
153				 NV03_SIFM_FORMAT_ORIGIN_CENTER | src_pitch);
154		PUSH_RELOC(push, src, src_offset, NOUVEAU_BO_LOW, 0, 0);
155		PUSH_DATA (push, src_point);
156
157		pbox++;
158	}
159
160	nouveau_pushbuf_bufctx(push, NULL);
161	PUSH_KICK(push);
162	exaMarkSync(pScrn->pScreen);
163
164	pPriv->videoStatus = FREE_TIMER;
165	pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
166	extern void NVVideoTimerCallback(ScrnInfoPtr, Time);
167	pNv->VideoTimerCallback = NVVideoTimerCallback;
168	return Success;
169}
170
171
172/**
173 * NVSetBlitPortAttribute
174 * sets the attribute "attribute" of port "data" to value "value"
175 * supported attributes:
176 * - xvSyncToVBlank (values: 0,1)
177 * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
178 *
179 * @param pScrenInfo
180 * @param attribute attribute to set
181 * @param value value to which attribute is to be set
182 * @param data port from which the attribute is to be set
183 *
184 * @return Success, if setting is successful
185 * BadValue/BadMatch, if value/attribute are invalid
186 */
187int
188NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
189		       INT32 value, pointer data)
190{
191	NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
192	NVPtr	   pNv = NVPTR(pScrn);
193
194	if ((attribute == xvSyncToVBlank) && VSYNC_POSSIBLE) {
195		if ((value < 0) || (value > 1))
196			return BadValue;
197		pPriv->SyncToVBlank = value;
198	} else
199	if (attribute == xvSetDefaults) {
200		pPriv->SyncToVBlank = VSYNC_POSSIBLE;
201	} else
202		return BadMatch;
203
204	return Success;
205}
206
207/**
208 * NVGetBlitPortAttribute
209 * reads the value of attribute "attribute" from port "data" into INT32 "*value"
210 * currently only one attribute supported: xvSyncToVBlank
211 *
212 * @param pScrn unused
213 * @param attribute attribute to be read
214 * @param value value of attribute will be stored here
215 * @param data port from which attribute will be read
216 * @return Success, if queried attribute exists
217 */
218int
219NVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
220		       INT32 *value, pointer data)
221{
222	NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
223
224	if(attribute == xvSyncToVBlank)
225		*value = (pPriv->SyncToVBlank) ? 1 : 0;
226	else
227		return BadMatch;
228
229	return Success;
230}
231
232/**
233 * NVStopBlitVideo
234 */
235void
236NVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
237{
238}
239
240