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