nv10_xv_ovl.c revision fda9279d
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 "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 "nv_dma.h"
36
37extern Atom xvBrightness, xvContrast, xvColorKey, xvSaturation;
38extern Atom xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer;
39extern Atom xvITURBT709, xvSyncToVBlank, xvOnCRTCNb;
40
41/**
42 * NV10PutOverlayImage
43 * program hardware to overlay image into front buffer
44 *
45 * @param pScrn screen
46 * @param offset card offset to the pixel data
47 * @param id format of image
48 * @param dstPitch pitch of the pixel data in VRAM
49 * @param dstBox destination box
50 * @param x1 first source point - x
51 * @param y1 first source point - y
52 * @param x2 second source point - x
53 * @param y2 second source point - y
54 * @param width width of the source image = x2 - x1
55 * @param height height
56 * @param src_w width of the image data in VRAM
57 * @param src_h height
58 * @param drw_w width of the image to draw to screen
59 * @param drw_h height
60 * @param clipBoxes ???
61 */
62void
63NV10PutOverlayImage(ScrnInfoPtr pScrn,
64		    struct nouveau_bo *src, int offset, int uvoffset, int id,
65		    int dstPitch, BoxPtr dstBox, int x1, int y1, int x2, int y2,
66		    short width, short height, short src_w, short src_h,
67		    short drw_w, short drw_h, RegionPtr clipBoxes)
68{
69	NVPtr         pNv    = NVPTR(pScrn);
70	NVPortPrivPtr pPriv  = GET_OVERLAY_PRIVATE(pNv);
71#ifdef NVOVL_SUPPORT
72	int           buffer = pPriv->currentBuffer;
73	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
74	xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC];
75
76	if (crtc->mode.Flags & V_DBLSCAN) {
77		dstBox->y1 <<= 1;
78		dstBox->y2 <<= 1;
79		drw_h <<= 1;
80	}
81
82	/* paint the color key */
83        if(pPriv->autopaintColorKey && (pPriv->grabbedByV4L ||
84                !REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes))) {
85                /* we always paint V4L's color key */
86                if (!pPriv->grabbedByV4L)
87                        REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
88                {
89                xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
90                }
91        }
92
93        //xf86DrvMsg(0, X_INFO, "SIZE_IN h %d w %d, POINT_IN x %d y %d, DS_DX %d DT_DY %d, POINT_OUT x %d y %d SIZE_OUT h %d w %d\n", height, width, x1 >>
94	//16,y1>>16, (src_w << 20) / drw_w, (src_h << 20) / drw_h,  (dstBox->x1),(dstBox->y1), (dstBox->y2 - dstBox->y1), (dstBox->x2 - dstBox->x1));
95
96        nvWriteVIDEO(pNv, NV_PVIDEO_BASE(buffer)     , 0);
97        nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(buffer),
98			  src->offset + offset);
99        nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_IN(buffer)  , (height << 16) | width);
100        nvWriteVIDEO(pNv, NV_PVIDEO_POINT_IN(buffer) ,
101                          ((y1 << 4) & 0xffff0000) | (x1 >> 12));
102        nvWriteVIDEO(pNv, NV_PVIDEO_DS_DX(buffer)    , (src_w << 20) / drw_w);
103        nvWriteVIDEO(pNv, NV_PVIDEO_DT_DY(buffer)    , (src_h << 20) / drw_h);
104        nvWriteVIDEO(pNv, NV_PVIDEO_POINT_OUT(buffer),
105                          (dstBox->y1 << 16) | dstBox->x1);
106        nvWriteVIDEO(pNv, NV_PVIDEO_SIZE_OUT(buffer) ,
107                          ((dstBox->y2 - dstBox->y1) << 16) |
108                           (dstBox->x2 - dstBox->x1));
109
110        dstPitch |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;   /* use color key */
111        if(id != FOURCC_UYVY)
112                dstPitch |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8;
113        if(pPriv->iturbt_709)
114                dstPitch |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
115
116        if( id == FOURCC_YV12 || id == FOURCC_I420 )
117                dstPitch |= NV_PVIDEO_FORMAT_PLANAR;
118
119        /* Those are important only for planar formats (NV12) */
120        if (uvoffset) {
121                nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_BASE(buffer), 0);
122                nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_OFFSET_BUFF(buffer),
123				  src->offset + uvoffset);
124	}
125
126        nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
127        nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
128        nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 :  0x1);
129#endif
130
131        pPriv->videoStatus = CLIENT_VIDEO_ON;
132}
133
134/**
135 * NV10SetOverlayPortAttribute
136 * sets the attribute "attribute" of port "data" to value "value"
137 * calls NVResetVideo(pScrn) to apply changes to hardware
138 *
139 * @param pScrenInfo
140 * @param attribute attribute to set
141 * @param value value to which attribute is to be set
142 * @param data port from which the attribute is to be set
143 *
144 * @return Success, if setting is successful
145 * BadValue/BadMatch, if value/attribute are invalid
146 * @see NVResetVideo(ScrnInfoPtr pScrn)
147 */
148int
149NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
150                          INT32 value, pointer data)
151{
152        NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
153
154        if (attribute == xvBrightness) {
155                if ((value < -512) || (value > 512))
156                        return BadValue;
157                pPriv->brightness = value;
158        } else
159        if (attribute == xvDoubleBuffer) {
160                if ((value < 0) || (value > 1))
161                        return BadValue;
162                pPriv->doubleBuffer = value;
163        } else
164        if (attribute == xvContrast) {
165                if ((value < 0) || (value > 8191))
166                        return BadValue;
167                pPriv->contrast = value;
168        } else
169        if (attribute == xvHue) {
170                value %= 360;
171                if (value < 0)
172                        value += 360;
173                pPriv->hue = value;
174        } else
175        if (attribute == xvSaturation) {
176                if ((value < 0) || (value > 8191))
177                        return BadValue;
178                pPriv->saturation = value;
179        } else
180        if (attribute == xvColorKey) {
181                pPriv->colorKey = value;
182                REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
183        } else
184        if (attribute == xvAutopaintColorKey) {
185                if ((value < 0) || (value > 1))
186                        return BadValue;
187                pPriv->autopaintColorKey = value;
188        } else
189        if (attribute == xvITURBT709) {
190                if ((value < 0) || (value > 1))
191                        return BadValue;
192                pPriv->iturbt_709 = value;
193        } else
194        if (attribute == xvSetDefaults) {
195                NVSetPortDefaults(pScrn, pPriv);
196        } else
197#ifdef NVOVL_SUPPORT
198        if ( attribute == xvOnCRTCNb) {
199		NVPtr pNv = NVPTR(pScrn);
200
201                if ((value < 0) || (value > 1))
202                        return BadValue;
203                pPriv->overlayCRTC = value;
204                NVWriteCRTC(pNv, value, NV_PCRTC_ENGINE_CTRL,
205			    NVReadCRTC(pNv, value, NV_PCRTC_ENGINE_CTRL) | NV_CRTC_FSEL_OVERLAY);
206                NVWriteCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL,
207			    NVReadCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL) & ~NV_CRTC_FSEL_OVERLAY);
208        } else
209#endif
210                return BadMatch;
211
212        NV10WriteOverlayParameters(pScrn);
213
214        return Success;
215}
216
217/**
218 * NV10GetOverlayPortAttribute
219 *
220 * @param pScrn unused
221 * @param attribute attribute to be read
222 * @param value value of attribute will be stored in this pointer
223 * @param data port from which attribute will be read
224 * @return Success, if queried attribute exists
225 */
226int
227NV10GetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
228                          INT32 *value, pointer data)
229{
230        NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
231
232        if (attribute == xvBrightness)
233                *value = pPriv->brightness;
234        else if (attribute == xvDoubleBuffer)
235                *value = (pPriv->doubleBuffer) ? 1 : 0;
236        else if (attribute == xvContrast)
237                *value = pPriv->contrast;
238        else if (attribute == xvSaturation)
239                *value = pPriv->saturation;
240        else if (attribute == xvHue)
241                *value = pPriv->hue;
242        else if (attribute == xvColorKey)
243                *value = pPriv->colorKey;
244        else if (attribute == xvAutopaintColorKey)
245                *value = (pPriv->autopaintColorKey) ? 1 : 0;
246        else if (attribute == xvITURBT709)
247                *value = (pPriv->iturbt_709) ? 1 : 0;
248        else if (attribute == xvOnCRTCNb)
249                *value = (pPriv->overlayCRTC) ? 1 : 0;
250        else
251                return BadMatch;
252
253        return Success;
254}
255
256/**
257 * NV10StopOverlay
258 * Tell the hardware to stop the overlay
259 */
260void
261NV10StopOverlay (ScrnInfoPtr pScrn)
262{
263#ifdef NVOVL_SUPPORT
264    NVPtr pNv = NVPTR(pScrn);
265    nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
266#endif
267}
268
269/**
270 * NV10WriteOverlayParameters
271 * Tell the hardware about parameters that are too expensive to be set
272 * on every frame
273 */
274void
275NV10WriteOverlayParameters (ScrnInfoPtr pScrn)
276{
277    NVPtr          pNv     = NVPTR(pScrn);
278    NVPortPrivPtr  pPriv   = GET_OVERLAY_PRIVATE(pNv);
279    int            satSine, satCosine;
280    double         angle;
281
282    angle = (double)pPriv->hue * 3.1415927 / 180.0;
283
284    satSine = pPriv->saturation * sin(angle);
285    if (satSine < -1024)
286	satSine = -1024;
287    satCosine = pPriv->saturation * cos(angle);
288    if (satCosine < -1024)
289	satCosine = -1024;
290
291#ifdef NVOVL_SUPPORT
292    nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
293	    pPriv->contrast);
294    nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
295	    pPriv->contrast);
296    nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(0), (satSine << 16) |
297	    (satCosine & 0xffff));
298    nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
299	    (satCosine & 0xffff));
300    nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
301#endif
302}
303
304