randr12: The last step to make lower flatpanel resolutions working.
[nouveau] / src / nv50_exa.c
1 #include "nv_include.h"
2
3 #define NV50EXA_LOCALS(p)                                              \
4         ScrnInfoPtr pScrn = xf86Screens[(p)->drawable.pScreen->myNum]; \
5         NVPtr pNv = NVPTR(pScrn);                                      \
6         (void)pNv
7
8 static Bool
9 NV50EXA2DSurfaceFormat(PixmapPtr pPix, uint32_t *fmt)
10 {
11         NV50EXA_LOCALS(pPix);
12
13         switch (pPix->drawable.depth) {
14         case 8 : *fmt = NV50_2D_SRC_FORMAT_8BPP; break;
15         case 15: *fmt = NV50_2D_SRC_FORMAT_15BPP; break;
16         case 16: *fmt = NV50_2D_SRC_FORMAT_16BPP; break;
17         case 24: *fmt = NV50_2D_SRC_FORMAT_24BPP; break;
18         case 32: *fmt = NV50_2D_SRC_FORMAT_32BPP; break;
19         default:
20                  xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
21                             "Unknown surface format for bpp=%d\n",
22                             pPix->drawable.depth);
23                  return FALSE;
24         }
25
26         return TRUE;
27 }
28
29 static Bool
30 NV50EXAAcquireSurface2D(PixmapPtr pPix, int is_src)
31 {
32         NV50EXA_LOCALS(pPix);
33         int mthd = is_src ? NV50_2D_SRC_FORMAT : NV50_2D_DST_FORMAT;
34         uint32_t fmt;
35
36         if (!NV50EXA2DSurfaceFormat(pPix, &fmt))
37                 return FALSE;
38
39         BEGIN_RING(Nv2D, mthd, 2);
40         OUT_RING  (fmt);
41         OUT_RING  (1);
42
43         BEGIN_RING(Nv2D, mthd + 0x14, 5);
44         OUT_RING  ((uint32_t)exaGetPixmapPitch(pPix));
45         OUT_RING  (pPix->drawable.width);
46         OUT_RING  (pPix->drawable.height);
47         OUT_RING  (0);
48         OUT_RING  (NVAccelGetPixmapOffset(pPix));
49
50         if (is_src == 0) {
51                 BEGIN_RING(Nv2D, NV50_2D_CLIP_X, 4);
52                 OUT_RING  (0);
53                 OUT_RING  (0);
54                 OUT_RING  (pPix->drawable.width);
55                 OUT_RING  (pPix->drawable.height);
56         }
57
58         return TRUE;
59 }
60
61 static Bool
62 NV50EXAAcquireSurfaces(PixmapPtr pdPix)
63 {
64         NV50EXA_LOCALS(pdPix);
65
66         return TRUE;
67 }
68
69 static void
70 NV50EXAReleaseSurfaces(PixmapPtr pdPix)
71 {
72         NV50EXA_LOCALS(pdPix);
73
74         BEGIN_RING(Nv2D, NV50_2D_NOP, 1);
75         OUT_RING  (0);
76         FIRE_RING();
77 }
78
79 static void
80 NV50EXASetPattern(PixmapPtr pdPix, int col0, int col1, int pat0, int pat1)
81 {
82         NV50EXA_LOCALS(pdPix);
83
84         BEGIN_RING(Nv2D, NV50_2D_PATTERN_COLOR(0), 4);
85         OUT_RING  (col0);
86         OUT_RING  (col1);
87         OUT_RING  (pat0);
88         OUT_RING  (pat1);
89 }
90
91 extern const int NVCopyROP[16];
92 static void
93 NV50EXASetROP(PixmapPtr pdPix, int alu, Pixel planemask)
94 {
95         NV50EXA_LOCALS(pdPix);
96         int rop = NVCopyROP[alu];
97
98         BEGIN_RING(Nv2D, NV50_2D_OPERATION, 1);
99         if(alu == GXcopy && planemask == ~0) {
100                 OUT_RING  (NV50_2D_OPERATION_SRCCOPY);
101                 return;
102         } else {
103                 OUT_RING  (NV50_2D_OPERATION_ROP_AND);
104         }
105
106         BEGIN_RING(Nv2D, NV50_2D_PATTERN_FORMAT, 1);
107         switch (pdPix->drawable.depth) {
108                 case  8: OUT_RING  (3); break;
109                 case 15: OUT_RING  (1); break;
110                 case 16: OUT_RING  (0); break;
111                 case 24:
112                 case 32:
113                 default:
114                          OUT_RING  (2);
115                          break;
116         }
117
118         if(planemask != ~0) {
119                 NV50EXASetPattern(pdPix, 0, planemask, ~0, ~0);
120                 rop = (rop & 0xf0) | 0x0a;
121         } else
122         if((pNv->currentRop & 0x0f) == 0x0a) {
123                 NV50EXASetPattern(pdPix, ~0, ~0, ~0, ~0);
124         }
125
126         if (pNv->currentRop != rop) {
127                 BEGIN_RING(Nv2D, NV50_2D_ROP, 1);
128                 OUT_RING  (rop);
129                 pNv->currentRop = rop;
130         }
131 }
132
133 Bool
134 NV50EXAPrepareSolid(PixmapPtr pdPix, int alu, Pixel planemask, Pixel fg)
135 {
136         NV50EXA_LOCALS(pdPix);
137         uint32_t fmt;
138
139         if(pdPix->drawable.depth > 24)
140                 return FALSE;
141         if (!NV50EXA2DSurfaceFormat(pdPix, &fmt))
142                 return FALSE;
143
144         if (!NV50EXAAcquireSurface2D(pdPix, 0))
145                 return FALSE;
146         if (!NV50EXAAcquireSurfaces(pdPix))
147                 return FALSE;
148         NV50EXASetROP(pdPix, alu, planemask);
149
150         BEGIN_RING(Nv2D, 0x580, 3);
151         OUT_RING  (4);
152         OUT_RING  (fmt);
153         OUT_RING  (fg);
154
155         return TRUE;
156 }
157
158 void
159 NV50EXASolid(PixmapPtr pdPix, int x1, int y1, int x2, int y2)
160 {
161         NV50EXA_LOCALS(pdPix);
162
163         BEGIN_RING(Nv2D, NV50_2D_RECT_X1, 4);
164         OUT_RING  (x1);
165         OUT_RING  (y1);
166         OUT_RING  (x2);
167         OUT_RING  (y2);
168
169         if((x2 - x1) * (y2 - y1) >= 512)
170                 FIRE_RING();
171 }
172
173 void
174 NV50EXADoneSolid(PixmapPtr pdPix)
175 {
176         NV50EXA_LOCALS(pdPix);
177
178         NV50EXAReleaseSurfaces(pdPix);
179 }
180
181 Bool
182 NV50EXAPrepareCopy(PixmapPtr psPix, PixmapPtr pdPix, int dx, int dy,
183                    int alu, Pixel planemask)
184 {
185         NV50EXA_LOCALS(pdPix);
186
187         if (!NV50EXAAcquireSurface2D(psPix, 1))
188                 return FALSE;
189         if (!NV50EXAAcquireSurface2D(pdPix, 0))
190                 return FALSE;
191         if (!NV50EXAAcquireSurfaces(pdPix))
192                 return FALSE;
193         NV50EXASetROP(pdPix, alu, planemask);
194
195         return TRUE;
196 }
197
198 void
199 NV50EXACopy(PixmapPtr pdPix, int srcX , int srcY,
200                              int dstX , int dstY,
201                              int width, int height)
202 {
203         NV50EXA_LOCALS(pdPix);
204
205         BEGIN_RING(Nv2D, 0x0110, 1);
206         OUT_RING  (0);
207         BEGIN_RING(Nv2D, NV50_2D_BLIT_DST_X, 12);
208         OUT_RING  (dstX);
209         OUT_RING  (dstY);
210         OUT_RING  (width);
211         OUT_RING  (height);
212         OUT_RING  (0);
213         OUT_RING  (1);
214         OUT_RING  (0);
215         OUT_RING  (1);
216         OUT_RING  (0);
217         OUT_RING  (srcX);
218         OUT_RING  (0);
219         OUT_RING  (srcY);
220
221         if(width * height >= 512)
222                 FIRE_RING();
223 }
224
225 void
226 NV50EXADoneCopy(PixmapPtr pdPix)
227 {
228         NV50EXA_LOCALS(pdPix);
229
230         NV50EXAReleaseSurfaces(pdPix);
231 }
232
233