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