fence: ref could destroy the object it was referencing, fix that!
[nouveau] / src / nv50_xv.c
1 /*
2  * Copyright 2008 Ben Skeggs
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 #include "nv50_accel.h"
37 #include "nv50_texture.h"
38
39 static Bool
40 nv50_xv_check_image_put(PixmapPtr ppix)
41 {
42         struct nouveau_pixmap *nvpix;
43
44         nvpix = exaGetPixmapDriverPrivate(ppix);
45         if (!nvpix || !nvpix->bo)
46                 return FALSE;
47
48         switch (ppix->drawable.depth) {
49         case 32:
50         case 24:
51         case 16:
52                 break;
53         default:
54                 return FALSE;
55         }
56
57         if (!nvpix->bo->tiled)
58                 return FALSE;
59
60         return TRUE;
61 }
62
63 int
64 nv50_xv_image_put(ScrnInfoPtr pScrn,
65                   struct nouveau_bo *src, int src_offset, int src_offset2,
66                   int id, int src_pitch, BoxPtr dstBox,
67                   int x1, int y1, int x2, int y2,
68                   uint16_t width, uint16_t height,
69                   uint16_t src_w, uint16_t src_h,
70                   uint16_t drw_w, uint16_t drw_h,
71                   RegionPtr clipBoxes, PixmapPtr ppix,
72                   NVPortPrivPtr pPriv)
73 {
74         NVPtr pNv = NVPTR(pScrn);
75         struct nouveau_channel *chan = pNv->chan;
76         struct nouveau_grobj *tesla = pNv->Nv3D;
77         float X1, X2, Y1, Y2;
78         BoxPtr pbox;
79         int nbox;
80
81         if (!nv50_xv_check_image_put(ppix))
82                 return BadMatch;
83
84         BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5);
85         OUT_PIXMAPh(chan, ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
86         OUT_PIXMAPl(chan, ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
87         switch (ppix->drawable.depth) {
88         case 32: OUT_RING  (chan, NV50TCL_RT_FORMAT_32BPP); break;
89         case 24: OUT_RING  (chan, NV50TCL_RT_FORMAT_24BPP); break;
90         case 16: OUT_RING  (chan, NV50TCL_RT_FORMAT_16BPP); break;
91         }
92         OUT_RING  (chan, 0);
93         OUT_RING  (chan, 0);
94         BEGIN_RING(chan, tesla, NV50TCL_RT_HORIZ(0), 2);
95         OUT_RING  (chan, ppix->drawable.width);
96         OUT_RING  (chan, ppix->drawable.height);
97         BEGIN_RING(chan, tesla, 0x1224, 1);
98         OUT_RING  (chan, 1);
99
100         BEGIN_RING(chan, tesla, NV50TCL_BLEND_ENABLE(0), 1);
101         OUT_RING  (chan, 0);
102
103         BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
104         OUT_RING  (chan, CB_TIC);
105         BEGIN_RING(chan, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 16);
106         if (id == FOURCC_YV12 || id == FOURCC_I420) {
107         OUT_RING  (chan, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
108                          NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
109                          NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
110                          NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
111                          NV50TIC_0_0_FMT_8);
112         OUT_RELOCl(chan, src,
113                          src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
114         OUT_RING  (chan, 0xd0005000);
115         OUT_RING  (chan, 0x00300000);
116         OUT_RING  (chan, src_w);
117         OUT_RING  (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | src_h);
118         OUT_RING  (chan, 0x03000000);
119         OUT_RELOCh(chan, src,
120                          src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
121         OUT_RING  (chan, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM |
122                          NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
123                          NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
124                          NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
125                          NV50TIC_0_0_FMT_8_8);
126         OUT_RELOCl(chan, src,
127                          src_offset2, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
128         OUT_RING  (chan, 0xd0005000);
129         OUT_RING  (chan, 0x00300000);
130         OUT_RING  (chan, src_w >> 1);
131         OUT_RING  (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | (src_h >> 1));
132         OUT_RING  (chan, 0x03000000);
133         OUT_RELOCh(chan, src,
134                          src_offset2, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
135         } else {
136         OUT_RING  (chan, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
137                          NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
138                          NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
139                          NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
140                          NV50TIC_0_0_FMT_8_8);
141         OUT_RELOCl(chan, src,
142                          src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
143         OUT_RING  (chan, 0xd0005000);
144         OUT_RING  (chan, 0x00300000);
145         OUT_RING  (chan, src_w);
146         OUT_RING  (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | src_h);
147         OUT_RING  (chan, 0x03000000);
148         OUT_RELOCh(chan, src,
149                          src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
150         OUT_RING  (chan, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
151                          NV50TIC_0_0_MAPR_C1 | NV50TIC_0_0_TYPER_UNORM |
152                          NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
153                          NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
154                          NV50TIC_0_0_FMT_8_8_8_8);
155         OUT_RELOCl(chan, src,
156                          src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
157         OUT_RING  (chan, 0xd0005000);
158         OUT_RING  (chan, 0x00300000);
159         OUT_RING  (chan, (src_w >> 1));
160         OUT_RING  (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | src_h);
161         OUT_RING  (chan, 0x03000000);
162         OUT_RELOCh(chan, src,
163                          src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
164         }
165
166         BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
167         OUT_RING  (chan, CB_TSC);
168         BEGIN_RING(chan, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 16);
169         OUT_RING  (chan, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE |
170                          NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE |
171                          NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE);
172         OUT_RING  (chan, NV50TSC_1_1_MAGF_LINEAR |
173                          NV50TSC_1_1_MINF_LINEAR |
174                          NV50TSC_1_1_MIPF_NONE);
175         OUT_RING  (chan, 0x00000000);
176         OUT_RING  (chan, 0x00000000);
177         OUT_RING  (chan, 0x00000000);
178         OUT_RING  (chan, 0x00000000);
179         OUT_RING  (chan, 0x00000000);
180         OUT_RING  (chan, 0x00000000);
181         OUT_RING  (chan, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE |
182                          NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE |
183                          NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE);
184         OUT_RING  (chan, NV50TSC_1_1_MAGF_LINEAR |
185                          NV50TSC_1_1_MINF_LINEAR |
186                          NV50TSC_1_1_MIPF_NONE);
187         OUT_RING  (chan, 0x00000000);
188         OUT_RING  (chan, 0x00000000);
189         OUT_RING  (chan, 0x00000000);
190         OUT_RING  (chan, 0x00000000);
191         OUT_RING  (chan, 0x00000000);
192         OUT_RING  (chan, 0x00000000);
193
194         BEGIN_RING(chan, tesla, NV50TCL_FP_START_ID, 1);
195         OUT_RING  (chan, PFP_NV12);
196
197         BEGIN_RING(chan, tesla, 0x1334, 1);
198         OUT_RING  (chan, 0);
199
200         BEGIN_RING(chan, tesla, 0x1458, 1);
201         OUT_RING  (chan, 1);
202         BEGIN_RING(chan, tesla, 0x1458, 1);
203         OUT_RING  (chan, 0x203);
204
205         /* These are fixed point values in the 16.16 format. */
206         X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000;
207         Y1 = (float)(y1>>16)+(float)(y1&0xFFFF)/(float)0x10000;
208         X2 = (float)(x2>>16)+(float)(x2&0xFFFF)/(float)0x10000;
209         Y2 = (float)(y2>>16)+(float)(y2&0xFFFF)/(float)0x10000;
210
211         BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
212         OUT_RING  (chan, NV50TCL_VERTEX_BEGIN_QUADS);
213
214         pbox = REGION_RECTS(clipBoxes);
215         nbox = REGION_NUM_RECTS(clipBoxes);
216         while(nbox--) {
217                 float tx1=X1+(float)(pbox->x1 - dstBox->x1)*(X2-X1)/(float)(drw_w);
218                 float tx2=X1+(float)(pbox->x2 - dstBox->x1)*(src_w)/(float)(drw_w);
219                 float ty1=Y1+(float)(pbox->y1 - dstBox->y1)*(Y2-Y1)/(float)(drw_h);
220                 float ty2=Y1+(float)(pbox->y2 - dstBox->y1)*(src_h)/(float)(drw_h);
221                 int sx1=pbox->x1;
222                 int sx2=pbox->x2;
223                 int sy1=pbox->y1;
224                 int sy2=pbox->y2;
225
226                 tx1 = tx1 / src_w;
227                 tx2 = tx2 / src_w;
228                 ty1 = ty1 / src_h;
229                 ty2 = ty2 / src_h;
230
231                 VTX2s(pNv, tx1, ty1, tx1, ty1, sx1, sy1);
232                 VTX2s(pNv, tx2, ty1, tx2, ty1, sx2, sy1);
233                 VTX2s(pNv, tx2, ty2, tx2, ty2, sx2, sy2);
234                 VTX2s(pNv, tx1, ty2, tx1, ty2, sx1, sy2);
235
236                 pbox++;
237         }
238
239         BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
240         OUT_RING  (chan, 0);
241
242         FIRE_RING (chan);
243
244         return Success;
245 }
246
247 void
248 nv50_xv_video_stop(ScrnInfoPtr pScrn, pointer data, Bool exit)
249 {
250 }
251
252 int
253 nv50_xv_port_attribute_set(ScrnInfoPtr pScrn, Atom attribute,
254                            INT32 value, pointer data)
255 {
256         return BadMatch;
257 }
258
259 int
260 nv50_xv_port_attribute_get(ScrnInfoPtr pScrn, Atom attribute,
261                            INT32 *value, pointer data)
262 {
263         return BadMatch;
264 }
265