1fda9279dSmrg/*
2fda9279dSmrg * Copyright 2007 Arthur Huillet
3fda9279dSmrg *
4fda9279dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5fda9279dSmrg * copy of this software and associated documentation files (the "Software"),
6fda9279dSmrg * to deal in the Software without restriction, including without limitation
7fda9279dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fda9279dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9fda9279dSmrg * Software is furnished to do so, subject to the following conditions:
10fda9279dSmrg *
11fda9279dSmrg * The above copyright notice and this permission notice shall be included in
12fda9279dSmrg * all copies or substantial portions of the Software.
13fda9279dSmrg *
14fda9279dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fda9279dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fda9279dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17fda9279dSmrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18fda9279dSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19fda9279dSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20fda9279dSmrg * SOFTWARE.
21fda9279dSmrg */
22fda9279dSmrg
23fda9279dSmrg#ifdef HAVE_CONFIG_H
24fda9279dSmrg#include "config.h"
25fda9279dSmrg#endif
26fda9279dSmrg
27479f40c1Smrg#include "xorg-config.h"
28fda9279dSmrg#include "xf86xv.h"
29fda9279dSmrg#include <X11/extensions/Xv.h>
30fda9279dSmrg#include "exa.h"
31fda9279dSmrg#include "damage.h"
32fda9279dSmrg#include "dixstruct.h"
33fda9279dSmrg#include "fourcc.h"
34fda9279dSmrg
35fda9279dSmrg#include "nv_include.h"
36fda9279dSmrg#include "nv_dma.h"
37fda9279dSmrg
38fda9279dSmrg#include "hwdefs/nv_object.xml.h"
39fda9279dSmrg#include "hwdefs/nv01_2d.xml.h"
40fda9279dSmrg#include "nv04_accel.h"
41fda9279dSmrg
42fda9279dSmrg#define FOURCC_RGB 0x0000003
43fda9279dSmrg
44fda9279dSmrg#define VSYNC_POSSIBLE (pNv->dev->chipset >= 0x11)
45fda9279dSmrg
46fda9279dSmrgextern Atom xvSetDefaults, xvSyncToVBlank;
47fda9279dSmrg
48fda9279dSmrgBool
49fda9279dSmrgNVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset,
50fda9279dSmrg	       int id, int src_pitch, BoxPtr dstBox,
51fda9279dSmrg	       int x1, int y1, int x2, int y2,
52fda9279dSmrg	       short width, short height,
53fda9279dSmrg	       short src_w, short src_h,
54fda9279dSmrg	       short drw_w, short drw_h,
55fda9279dSmrg	       RegionPtr clipBoxes, PixmapPtr ppix)
56fda9279dSmrg{
57fda9279dSmrg	NVPtr	  pNv   = NVPTR(pScrn);
58fda9279dSmrg	NVPortPrivPtr  pPriv = GET_BLIT_PRIVATE(pNv);
59fda9279dSmrg	BoxPtr	 pbox;
60fda9279dSmrg	int	    nbox;
61fda9279dSmrg	CARD32	 dsdx, dtdy;
62fda9279dSmrg	CARD32	 dst_size, dst_point;
63fda9279dSmrg	CARD32	 src_point, src_format;
64fda9279dSmrg	struct nouveau_pushbuf *push = pNv->pushbuf;
65fda9279dSmrg	struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
66fda9279dSmrg	struct nv04_fifo *fifo = pNv->channel->data;
67fda9279dSmrg	int dst_format;
68fda9279dSmrg
69fda9279dSmrg	if (!NVAccelGetCtxSurf2DFormatFromPixmap(ppix, &dst_format))
70fda9279dSmrg		return BadImplementation;
71fda9279dSmrg
72fda9279dSmrg	pbox = REGION_RECTS(clipBoxes);
73fda9279dSmrg	nbox = REGION_NUM_RECTS(clipBoxes);
74fda9279dSmrg
75fda9279dSmrg	dsdx = (src_w << 20) / drw_w;
76fda9279dSmrg	dtdy = (src_h << 20) / drw_h;
77fda9279dSmrg
78fda9279dSmrg	dst_size  = ((dstBox->y2 - dstBox->y1) << 16) |
79fda9279dSmrg		     (dstBox->x2 - dstBox->x1);
80fda9279dSmrg	dst_point = (dstBox->y1 << 16) | dstBox->x1;
81fda9279dSmrg
82fda9279dSmrg	src_point = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
83fda9279dSmrg
84fda9279dSmrg	switch(id) {
85fda9279dSmrg	case FOURCC_RGB:
86fda9279dSmrg		src_format = NV03_SIFM_COLOR_FORMAT_X8R8G8B8;
87fda9279dSmrg		break;
88fda9279dSmrg	case FOURCC_UYVY:
89fda9279dSmrg		src_format = NV03_SIFM_COLOR_FORMAT_YB8V8YA8U8;
90fda9279dSmrg		break;
91fda9279dSmrg	default:
92fda9279dSmrg		src_format = NV03_SIFM_COLOR_FORMAT_V8YB8U8YA8;
93fda9279dSmrg		break;
94fda9279dSmrg	}
95fda9279dSmrg
96fda9279dSmrg	if (!PUSH_SPACE(push, 128))
97fda9279dSmrg		return BadImplementation;
98fda9279dSmrg	PUSH_RESET(push);
99fda9279dSmrg
100fda9279dSmrg	BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
101fda9279dSmrg	PUSH_DATA (push, dst_format);
102fda9279dSmrg	PUSH_DATA (push, (exaGetPixmapPitch(ppix) << 16) |
103fda9279dSmrg			  exaGetPixmapPitch(ppix));
104fda9279dSmrg	PUSH_MTHDl(push, NV04_SF2D(OFFSET_SOURCE), bo, 0,
105fda9279dSmrg			 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
106fda9279dSmrg	PUSH_MTHDl(push, NV04_SF2D(OFFSET_DESTIN), bo, 0,
107fda9279dSmrg			 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
108fda9279dSmrg
109fda9279dSmrg	BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1);
110fda9279dSmrg	PUSH_DATA (push, pNv->NvScaledImage->handle);
111fda9279dSmrg	BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
112fda9279dSmrg	PUSH_MTHDo(push, NV03_SIFM(DMA_IMAGE), src, NOUVEAU_BO_RD |
113fda9279dSmrg			 NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
114fda9279dSmrg			 fifo->vram, fifo->gart);
115fda9279dSmrg	if (pNv->dev->chipset >= 0x05) {
116fda9279dSmrg		BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 2);
117fda9279dSmrg		PUSH_DATA (push, src_format);
118fda9279dSmrg		PUSH_DATA (push, NV03_SIFM_OPERATION_SRCCOPY);
119fda9279dSmrg	} else {
120fda9279dSmrg		BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 1);
121fda9279dSmrg		PUSH_DATA (push, src_format);
122fda9279dSmrg	}
123fda9279dSmrg
124fda9279dSmrg	nouveau_pushbuf_bufctx(push, pNv->bufctx);
125fda9279dSmrg	if (nouveau_pushbuf_validate(push)) {
126fda9279dSmrg		nouveau_pushbuf_bufctx(push, NULL);
127fda9279dSmrg		return BadAlloc;
128fda9279dSmrg	}
129fda9279dSmrg
130fda9279dSmrg	if (pPriv->SyncToVBlank)
131fda9279dSmrg		NV11SyncToVBlank(ppix, dstBox);
132fda9279dSmrg
133fda9279dSmrg	while (nbox--) {
134fda9279dSmrg		if (!PUSH_SPACE(push, 16)) {
135fda9279dSmrg			nouveau_pushbuf_bufctx(push, NULL);
136fda9279dSmrg			return BadImplementation;
137fda9279dSmrg		}
138fda9279dSmrg
139fda9279dSmrg		BEGIN_NV04(push, NV04_RECT(COLOR1_A), 1);
140fda9279dSmrg		PUSH_DATA (push, 0);
141fda9279dSmrg
142fda9279dSmrg		BEGIN_NV04(push, NV03_SIFM(CLIP_POINT), 6);
143fda9279dSmrg		PUSH_DATA (push, (pbox->y1 << 16) | pbox->x1);
144fda9279dSmrg		PUSH_DATA (push, (pbox->y2 - pbox->y1) << 16 |
145fda9279dSmrg				 (pbox->x2 - pbox->x1));
146fda9279dSmrg		PUSH_DATA (push, dst_point);
147fda9279dSmrg		PUSH_DATA (push, dst_size);
148fda9279dSmrg		PUSH_DATA (push, dsdx);
149fda9279dSmrg		PUSH_DATA (push, dtdy);
150fda9279dSmrg		BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
151fda9279dSmrg		PUSH_DATA (push, (height << 16) | width);
152fda9279dSmrg		PUSH_DATA (push, NV03_SIFM_FORMAT_FILTER_BILINEAR |
153fda9279dSmrg				 NV03_SIFM_FORMAT_ORIGIN_CENTER | src_pitch);
154fda9279dSmrg		PUSH_RELOC(push, src, src_offset, NOUVEAU_BO_LOW, 0, 0);
155fda9279dSmrg		PUSH_DATA (push, src_point);
156fda9279dSmrg
157fda9279dSmrg		pbox++;
158fda9279dSmrg	}
159fda9279dSmrg
160fda9279dSmrg	nouveau_pushbuf_bufctx(push, NULL);
161fda9279dSmrg	PUSH_KICK(push);
162fda9279dSmrg	exaMarkSync(pScrn->pScreen);
163fda9279dSmrg
164fda9279dSmrg	pPriv->videoStatus = FREE_TIMER;
165fda9279dSmrg	pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
166fda9279dSmrg	extern void NVVideoTimerCallback(ScrnInfoPtr, Time);
167fda9279dSmrg	pNv->VideoTimerCallback = NVVideoTimerCallback;
168fda9279dSmrg	return Success;
169fda9279dSmrg}
170fda9279dSmrg
171fda9279dSmrg
172fda9279dSmrg/**
173fda9279dSmrg * NVSetBlitPortAttribute
174fda9279dSmrg * sets the attribute "attribute" of port "data" to value "value"
175fda9279dSmrg * supported attributes:
176fda9279dSmrg * - xvSyncToVBlank (values: 0,1)
177fda9279dSmrg * - xvSetDefaults (values: NA; SyncToVBlank will be set, if hardware supports it)
178fda9279dSmrg *
179fda9279dSmrg * @param pScrenInfo
180fda9279dSmrg * @param attribute attribute to set
181fda9279dSmrg * @param value value to which attribute is to be set
182fda9279dSmrg * @param data port from which the attribute is to be set
183fda9279dSmrg *
184fda9279dSmrg * @return Success, if setting is successful
185fda9279dSmrg * BadValue/BadMatch, if value/attribute are invalid
186fda9279dSmrg */
187fda9279dSmrgint
188fda9279dSmrgNVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
189fda9279dSmrg		       INT32 value, pointer data)
190fda9279dSmrg{
191fda9279dSmrg	NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
192fda9279dSmrg	NVPtr	   pNv = NVPTR(pScrn);
193fda9279dSmrg
194fda9279dSmrg	if ((attribute == xvSyncToVBlank) && VSYNC_POSSIBLE) {
195fda9279dSmrg		if ((value < 0) || (value > 1))
196fda9279dSmrg			return BadValue;
197fda9279dSmrg		pPriv->SyncToVBlank = value;
198fda9279dSmrg	} else
199fda9279dSmrg	if (attribute == xvSetDefaults) {
200fda9279dSmrg		pPriv->SyncToVBlank = VSYNC_POSSIBLE;
201fda9279dSmrg	} else
202fda9279dSmrg		return BadMatch;
203fda9279dSmrg
204fda9279dSmrg	return Success;
205fda9279dSmrg}
206fda9279dSmrg
207fda9279dSmrg/**
208fda9279dSmrg * NVGetBlitPortAttribute
209fda9279dSmrg * reads the value of attribute "attribute" from port "data" into INT32 "*value"
210fda9279dSmrg * currently only one attribute supported: xvSyncToVBlank
211fda9279dSmrg *
212fda9279dSmrg * @param pScrn unused
213fda9279dSmrg * @param attribute attribute to be read
214fda9279dSmrg * @param value value of attribute will be stored here
215fda9279dSmrg * @param data port from which attribute will be read
216fda9279dSmrg * @return Success, if queried attribute exists
217fda9279dSmrg */
218fda9279dSmrgint
219fda9279dSmrgNVGetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
220fda9279dSmrg		       INT32 *value, pointer data)
221fda9279dSmrg{
222fda9279dSmrg	NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
223fda9279dSmrg
224fda9279dSmrg	if(attribute == xvSyncToVBlank)
225fda9279dSmrg		*value = (pPriv->SyncToVBlank) ? 1 : 0;
226fda9279dSmrg	else
227fda9279dSmrg		return BadMatch;
228fda9279dSmrg
229fda9279dSmrg	return Success;
230fda9279dSmrg}
231fda9279dSmrg
232fda9279dSmrg/**
233fda9279dSmrg * NVStopBlitVideo
234fda9279dSmrg */
235fda9279dSmrgvoid
236fda9279dSmrgNVStopBlitVideo(ScrnInfoPtr pScrn, pointer data, Bool Exit)
237fda9279dSmrg{
238fda9279dSmrg}
239fda9279dSmrg
240