Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / gallium / winsys / dri / nouveau / nv04_surface.c
1 #include "pipe/p_context.h"
2 #include "pipe/p_format.h"
3
4 #include "nouveau_context.h"
5
6 static INLINE int
7 nv04_surface_format(enum pipe_format format)
8 {
9 switch (format) {
10 case PIPE_FORMAT_A8_UNORM:
11 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
12 case PIPE_FORMAT_R5G6B5_UNORM:
13 return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
14 case PIPE_FORMAT_A8R8G8B8_UNORM:
15 case PIPE_FORMAT_Z24S8_UNORM:
16 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
17 default:
18 return -1;
19 }
20 }
21
22 static INLINE int
23 nv04_rect_format(enum pipe_format format)
24 {
25 switch (format) {
26 case PIPE_FORMAT_A8_UNORM:
27 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
28 case PIPE_FORMAT_R5G6B5_UNORM:
29 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
30 case PIPE_FORMAT_A8R8G8B8_UNORM:
31 case PIPE_FORMAT_Z24S8_UNORM:
32 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
33 default:
34 return -1;
35 }
36 }
37
38 static void
39 nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy,
40 unsigned sx, unsigned sy, unsigned w, unsigned h)
41 {
42 struct nouveau_channel *chan = nv->nvc->channel;
43 struct pipe_surface *dst = nv->surf_dst;
44 struct pipe_surface *src = nv->surf_src;
45 unsigned dst_offset, src_offset;
46
47 dst_offset = dst->offset + (dy * dst->stride) + (dx * dst->block.size);
48 src_offset = src->offset + (sy * src->stride) + (sx * src->block.size);
49
50 while (h) {
51 int count = (h > 2047) ? 2047 : h;
52
53 BEGIN_RING(chan, nv->nvc->NvM2MF,
54 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
55 OUT_RELOCl(chan, nouveau_buffer(src->buffer)->bo, src_offset,
56 NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
57 OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst_offset,
58 NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
59 OUT_RING (chan, src->stride);
60 OUT_RING (chan, dst->stride);
61 OUT_RING (chan, w * src->block.size);
62 OUT_RING (chan, count);
63 OUT_RING (chan, 0x0101);
64 OUT_RING (chan, 0);
65
66 h -= count;
67 src_offset += src->stride * count;
68 dst_offset += dst->stride * count;
69 }
70 }
71
72 static void
73 nv04_surface_copy_blit(struct nouveau_context *nv, unsigned dx, unsigned dy,
74 unsigned sx, unsigned sy, unsigned w, unsigned h)
75 {
76 struct nouveau_channel *chan = nv->nvc->channel;
77
78 BEGIN_RING(chan, nv->nvc->NvImageBlit, 0x0300, 3);
79 OUT_RING (chan, (sy << 16) | sx);
80 OUT_RING (chan, (dy << 16) | dx);
81 OUT_RING (chan, ( h << 16) | w);
82 }
83
84 static int
85 nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
86 struct pipe_surface *src)
87 {
88 struct nouveau_channel *chan = nv->nvc->channel;
89 int format;
90
91 if (src->format != dst->format)
92 return 1;
93
94 /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
95 * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
96 */
97 if ((src->offset & 63) || (dst->offset & 63)) {
98 BEGIN_RING(nv->nvc->channel, nv->nvc->NvM2MF,
99 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
100 OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo,
101 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
102 OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
103 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
104
105 nv->surface_copy = nv04_surface_copy_m2mf;
106 nv->surf_dst = dst;
107 nv->surf_src = src;
108 return 0;
109
110 }
111
112 if ((format = nv04_surface_format(dst->format)) < 0) {
113 NOUVEAU_ERR("Bad surface format 0x%x\n", dst->format);
114 return 1;
115 }
116 nv->surface_copy = nv04_surface_copy_blit;
117
118 BEGIN_RING(chan, nv->nvc->NvCtxSurf2D,
119 NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
120 OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo,
121 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
122 OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
123 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
124
125 BEGIN_RING(chan, nv->nvc->NvCtxSurf2D,
126 NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
127 OUT_RING (chan, format);
128 OUT_RING (chan, (dst->stride << 16) | src->stride);
129 OUT_RELOCl(chan, nouveau_buffer(src->buffer)->bo, src->offset,
130 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
131 OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset,
132 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
133
134 return 0;
135 }
136
137 static void
138 nv04_surface_copy_done(struct nouveau_context *nv)
139 {
140 FIRE_RING(nv->nvc->channel);
141 }
142
143 static int
144 nv04_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
145 unsigned dx, unsigned dy, unsigned w, unsigned h,
146 unsigned value)
147 {
148 struct nouveau_channel *chan = nv->nvc->channel;
149 struct nouveau_grobj *surf2d = nv->nvc->NvCtxSurf2D;
150 struct nouveau_grobj *rect = nv->nvc->NvGdiRect;
151 int cs2d_format, gdirect_format;
152
153 if ((cs2d_format = nv04_surface_format(dst->format)) < 0) {
154 NOUVEAU_ERR("Bad format = %d\n", dst->format);
155 return 1;
156 }
157
158 if ((gdirect_format = nv04_rect_format(dst->format)) < 0) {
159 NOUVEAU_ERR("Bad format = %d\n", dst->format);
160 return 1;
161 }
162
163 BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
164 OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
165 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
166 OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
167 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
168 BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
169 OUT_RING (chan, cs2d_format);
170 OUT_RING (chan, (dst->stride << 16) | dst->stride);
171 OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset,
172 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
173 OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset,
174 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
175
176 BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
177 OUT_RING (chan, gdirect_format);
178 BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
179 OUT_RING (chan, value);
180 BEGIN_RING(chan, rect,
181 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
182 OUT_RING (chan, (dx << 16) | dy);
183 OUT_RING (chan, ( w << 16) | h);
184
185 FIRE_RING(chan);
186 return 0;
187 }
188
189 int
190 nouveau_surface_channel_create_nv04(struct nouveau_channel_context *nvc)
191 {
192 struct nouveau_channel *chan = nvc->channel;
193 unsigned chipset = nvc->channel->device->chipset, class;
194 int ret;
195
196 if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, 0x39,
197 &nvc->NvM2MF))) {
198 NOUVEAU_ERR("Error creating m2mf object: %d\n", ret);
199 return 1;
200 }
201 BIND_RING (chan, nvc->NvM2MF, nvc->next_subchannel++);
202 BEGIN_RING(chan, nvc->NvM2MF,
203 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
204 OUT_RING (chan, nvc->sync_notifier->handle);
205
206 class = chipset < 0x10 ? NV04_CONTEXT_SURFACES_2D :
207 NV10_CONTEXT_SURFACES_2D;
208 if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
209 &nvc->NvCtxSurf2D))) {
210 NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret);
211 return 1;
212 }
213 BIND_RING (chan, nvc->NvCtxSurf2D, nvc->next_subchannel++);
214 BEGIN_RING(chan, nvc->NvCtxSurf2D,
215 NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
216 OUT_RING (chan, nvc->channel->vram->handle);
217 OUT_RING (chan, nvc->channel->vram->handle);
218
219 class = chipset < 0x10 ? NV04_IMAGE_BLIT : NV12_IMAGE_BLIT;
220 if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
221 &nvc->NvImageBlit))) {
222 NOUVEAU_ERR("Error creating blit object: %d\n", ret);
223 return 1;
224 }
225 BIND_RING (chan, nvc->NvImageBlit, nvc->next_subchannel++);
226 BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
227 OUT_RING (chan, nvc->sync_notifier->handle);
228 BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_SURFACE, 1);
229 OUT_RING (chan, nvc->NvCtxSurf2D->handle);
230 BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1);
231 OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY);
232
233 class = NV04_GDI_RECTANGLE_TEXT;
234 if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
235 &nvc->NvGdiRect))) {
236 NOUVEAU_ERR("Error creating rect object: %d\n", ret);
237 return 1;
238 }
239 BIND_RING (chan, nvc->NvGdiRect, nvc->next_subchannel++);
240 BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
241 OUT_RING (chan, nvc->sync_notifier->handle);
242 BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
243 OUT_RING (chan, nvc->NvCtxSurf2D->handle);
244 BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
245 OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
246 BEGIN_RING(chan, nvc->NvGdiRect,
247 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
248 OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
249
250 switch (chipset & 0xf0) {
251 case 0x00:
252 case 0x10:
253 class = NV04_SWIZZLED_SURFACE;
254 break;
255 case 0x20:
256 class = NV20_SWIZZLED_SURFACE;
257 break;
258 case 0x30:
259 class = NV30_SWIZZLED_SURFACE;
260 break;
261 case 0x40:
262 case 0x60:
263 class = NV40_SWIZZLED_SURFACE;
264 break;
265 default:
266 /* Famous last words: this really can't happen.. */
267 assert(0);
268 break;
269 }
270
271 ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
272 &nvc->NvSwzSurf);
273 if (ret) {
274 NOUVEAU_ERR("Error creating swizzled surface: %d\n", ret);
275 return 1;
276 }
277
278 BIND_RING (chan, nvc->NvSwzSurf, nvc->next_subchannel++);
279 BEGIN_RING(chan, nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_DMA_NOTIFY, 1);
280 OUT_RING (chan, nvc->sync_notifier->handle);
281 BEGIN_RING(chan, nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
282 OUT_RING (chan, nvc->channel->vram->handle);
283
284 if (chipset < 0x10) {
285 class = NV04_SCALED_IMAGE_FROM_MEMORY;
286 } else
287 if (chipset < 0x40) {
288 class = NV10_SCALED_IMAGE_FROM_MEMORY;
289 } else {
290 class = NV40_SCALED_IMAGE_FROM_MEMORY;
291 }
292
293 ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
294 &nvc->NvSIFM);
295 if (ret) {
296 NOUVEAU_ERR("Error creating scaled image object: %d\n", ret);
297 return 1;
298 }
299
300 BIND_RING (chan, nvc->NvSIFM, nvc->next_subchannel++);
301
302 return 0;
303 }
304
305 int
306 nouveau_surface_init_nv04(struct nouveau_context *nv)
307 {
308 nv->surface_copy_prep = nv04_surface_copy_prep;
309 nv->surface_copy = nv04_surface_copy_blit;
310 nv->surface_copy_done = nv04_surface_copy_done;
311 nv->surface_fill = nv04_surface_fill;
312 return 0;
313 }
314