1 #include "pipe/p_context.h"
2 #include "pipe/p_format.h"
3 #include "util/u_memory.h"
4 #include "util/u_math.h"
6 #include "nouveau/nouveau_winsys.h"
7 #include "nouveau/nouveau_util.h"
8 #include "nv04_surface_2d.h"
11 nv04_surface_format(enum pipe_format format
)
14 case PIPE_FORMAT_A8_UNORM
:
15 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8
;
16 case PIPE_FORMAT_R16_SNORM
:
17 case PIPE_FORMAT_R5G6B5_UNORM
:
18 return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5
;
19 case PIPE_FORMAT_X8R8G8B8_UNORM
:
20 case PIPE_FORMAT_A8R8G8B8_UNORM
:
21 return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8
;
22 case PIPE_FORMAT_Z24S8_UNORM
:
23 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32
;
30 nv04_rect_format(enum pipe_format format
)
33 case PIPE_FORMAT_A8_UNORM
:
34 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
35 case PIPE_FORMAT_R5G6B5_UNORM
:
36 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5
;
37 case PIPE_FORMAT_A8R8G8B8_UNORM
:
38 case PIPE_FORMAT_Z24S8_UNORM
:
39 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
46 nv04_scaled_image_format(enum pipe_format format
)
49 case PIPE_FORMAT_A1R5G5B5_UNORM
:
50 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5
;
51 case PIPE_FORMAT_A8R8G8B8_UNORM
:
52 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8
;
53 case PIPE_FORMAT_X8R8G8B8_UNORM
:
54 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8
;
55 case PIPE_FORMAT_R5G6B5_UNORM
:
56 case PIPE_FORMAT_R16_SNORM
:
57 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5
;
63 static INLINE
unsigned
64 nv04_swizzle_bits(unsigned x
, unsigned y
)
66 unsigned u
= (x
& 0x001) << 0 |
79 unsigned v
= (y
& 0x001) << 1 |
95 nv04_surface_copy_swizzle(struct nv04_surface_2d
*ctx
,
96 struct pipe_surface
*dst
, int dx
, int dy
,
97 struct pipe_surface
*src
, int sx
, int sy
,
100 struct nouveau_channel
*chan
= ctx
->nvws
->channel
;
101 struct nouveau_grobj
*swzsurf
= ctx
->swzsurf
;
102 struct nouveau_grobj
*sifm
= ctx
->sifm
;
103 struct nouveau_bo
*src_bo
= ctx
->nvws
->get_bo(ctx
->buf(src
));
104 struct nouveau_bo
*dst_bo
= ctx
->nvws
->get_bo(ctx
->buf(dst
));
105 const unsigned max_w
= 1024;
106 const unsigned max_h
= 1024;
107 int i
, src_offset
= src
->offset
, dst_offset
= dst
->offset
, src_stride
= src
->stride
;
110 assert(!(w
& (w
- 1)) && !(h
& (h
- 1)));
112 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_DMA_IMAGE
, 1);
113 OUT_RELOCo(chan
, dst_bo
,
114 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
116 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE
, 1);
117 OUT_RELOCo(chan
, src_bo
,
118 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
119 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE
, 1);
120 OUT_RING (chan
, swzsurf
->handle
);
122 /* Upload, then swizzle each mipmap level in turn */
123 for (i
=0; i
<src
->texture
->last_level
; i
++) {
124 unsigned sub_w
, sub_h
;
127 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_FORMAT
, 1);
128 OUT_RING (chan
, nv04_surface_format(dst
->format
) |
129 log2i(w
) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT
|
130 log2i(h
) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT
);
132 sub_w
= w
> max_w
? max_w
: w
;
133 sub_h
= h
> max_h
? max_h
: h
;
135 for (cy
= 0; cy
< h
; cy
+= sub_h
) {
136 for (cx
= 0; cx
< w
; cx
+= sub_w
) {
138 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_OFFSET
, 1);
139 OUT_RELOCl(chan
, dst_bo
, dst_offset
+ nv04_swizzle_bits(cx
, cy
) *
140 dst
->block
.size
, NOUVEAU_BO_GART
|
141 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
143 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION
, 9);
144 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE
);
145 OUT_RING (chan
, nv04_scaled_image_format(src
->format
));
146 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY
);
148 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
150 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
151 OUT_RING (chan
, 1 << 20);
152 OUT_RING (chan
, 1 << 20);
154 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE
, 4);
155 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
156 OUT_RING (chan
, src_stride
|
157 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER
|
158 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE
);
159 OUT_RELOCl(chan
, src_bo
, src_offset
+ cy
* src_stride
+
160 cx
* src
->block
.size
, NOUVEAU_BO_GART
|
161 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
166 /* FIXME: need to find next offset for both source and dest */
167 src_offset
+= w
* h
* dst
->block
.size
;
168 /*src_offset = align(src_offset, 64);*/
169 dst_offset
+= w
* h
* dst
->block
.size
;
170 /*dst_offset = align(dst_offset, 64);*/
180 nv04_surface_copy_m2mf(struct nv04_surface_2d
*ctx
,
181 struct pipe_surface
*dst
, int dx
, int dy
,
182 struct pipe_surface
*src
, int sx
, int sy
, int w
, int h
)
184 struct nouveau_channel
*chan
= ctx
->nvws
->channel
;
185 struct nouveau_grobj
*m2mf
= ctx
->m2mf
;
186 struct nouveau_bo
*src_bo
= ctx
->nvws
->get_bo(ctx
->buf(src
));
187 struct nouveau_bo
*dst_bo
= ctx
->nvws
->get_bo(ctx
->buf(dst
));
188 unsigned dst_offset
, src_offset
;
190 dst_offset
= dst
->offset
+ (dy
* dst
->stride
) + (dx
* dst
->block
.size
);
191 src_offset
= src
->offset
+ (sy
* src
->stride
) + (sx
* src
->block
.size
);
193 WAIT_RING (chan
, 3 + ((h
/ 2047) + 1) * 9);
194 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
, 2);
195 OUT_RELOCo(chan
, src_bo
,
196 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
197 OUT_RELOCo(chan
, dst_bo
,
198 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
201 int count
= (h
> 2047) ? 2047 : h
;
203 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
204 OUT_RELOCl(chan
, src_bo
, src_offset
,
205 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
206 OUT_RELOCl(chan
, dst_bo
, dst_offset
,
207 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_WR
);
208 OUT_RING (chan
, src
->stride
);
209 OUT_RING (chan
, dst
->stride
);
210 OUT_RING (chan
, w
* src
->block
.size
);
211 OUT_RING (chan
, count
);
212 OUT_RING (chan
, 0x0101);
216 src_offset
+= src
->stride
* count
;
217 dst_offset
+= dst
->stride
* count
;
224 nv04_surface_copy_blit(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
225 int dx
, int dy
, struct pipe_surface
*src
, int sx
, int sy
,
228 struct nouveau_channel
*chan
= ctx
->nvws
->channel
;
229 struct nouveau_grobj
*surf2d
= ctx
->surf2d
;
230 struct nouveau_grobj
*blit
= ctx
->blit
;
231 struct nouveau_bo
*src_bo
= ctx
->nvws
->get_bo(ctx
->buf(src
));
232 struct nouveau_bo
*dst_bo
= ctx
->nvws
->get_bo(ctx
->buf(dst
));
235 format
= nv04_surface_format(dst
->format
);
239 WAIT_RING (chan
, 12);
240 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
241 OUT_RELOCo(chan
, src_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
242 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
243 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
244 OUT_RING (chan
, format
);
245 OUT_RING (chan
, (dst
->stride
<< 16) | src
->stride
);
246 OUT_RELOCl(chan
, src_bo
, src
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
247 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
249 BEGIN_RING(chan
, blit
, 0x0300, 3);
250 OUT_RING (chan
, (sy
<< 16) | sx
);
251 OUT_RING (chan
, (dy
<< 16) | dx
);
252 OUT_RING (chan
, ( h
<< 16) | w
);
258 nv04_surface_copy(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
259 int dx
, int dy
, struct pipe_surface
*src
, int sx
, int sy
,
262 int src_linear
= src
->texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
;
263 int dst_linear
= dst
->texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
;
265 assert(src
->format
== dst
->format
);
267 /* Setup transfer to swizzle the texture to vram if needed */
268 /* FIXME/TODO: check proper limits of this operation */
269 if (src_linear
^ dst_linear
) {
270 nv04_surface_copy_swizzle(ctx
, dst
, dx
, dy
, src
, sx
, sy
, w
, h
);
274 /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
275 * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
277 if ((src
->offset
& 63) || (dst
->offset
& 63)) {
278 nv04_surface_copy_m2mf(ctx
, dst
, dx
, dy
, src
, sx
, sy
, w
, h
);
282 nv04_surface_copy_blit(ctx
, dst
, dx
, dy
, src
, sx
, sy
, w
, h
);
286 nv04_surface_fill(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
287 int dx
, int dy
, int w
, int h
, unsigned value
)
289 struct nouveau_channel
*chan
= ctx
->nvws
->channel
;
290 struct nouveau_grobj
*surf2d
= ctx
->surf2d
;
291 struct nouveau_grobj
*rect
= ctx
->rect
;
292 struct nouveau_bo
*dst_bo
= ctx
->nvws
->get_bo(ctx
->buf(dst
));
293 int cs2d_format
, gdirect_format
;
295 cs2d_format
= nv04_surface_format(dst
->format
);
296 assert(cs2d_format
>= 0);
298 gdirect_format
= nv04_rect_format(dst
->format
);
299 assert(gdirect_format
>= 0);
301 WAIT_RING (chan
, 16);
302 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
303 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
304 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
305 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
306 OUT_RING (chan
, cs2d_format
);
307 OUT_RING (chan
, (dst
->stride
<< 16) | dst
->stride
);
308 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
309 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
311 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT
, 1);
312 OUT_RING (chan
, gdirect_format
);
313 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR1_A
, 1);
314 OUT_RING (chan
, value
);
315 BEGIN_RING(chan
, rect
,
316 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
317 OUT_RING (chan
, (dx
<< 16) | dy
);
318 OUT_RING (chan
, ( w
<< 16) | h
);
322 nv04_surface_2d_takedown(struct nv04_surface_2d
**pctx
)
324 struct nv04_surface_2d
*ctx
;
331 nouveau_notifier_free(&ctx
->ntfy
);
332 nouveau_grobj_free(&ctx
->m2mf
);
333 nouveau_grobj_free(&ctx
->surf2d
);
334 nouveau_grobj_free(&ctx
->swzsurf
);
335 nouveau_grobj_free(&ctx
->rect
);
336 nouveau_grobj_free(&ctx
->blit
);
337 nouveau_grobj_free(&ctx
->sifm
);
342 struct nv04_surface_2d
*
343 nv04_surface_2d_init(struct nouveau_winsys
*nvws
)
345 struct nv04_surface_2d
*ctx
= CALLOC_STRUCT(nv04_surface_2d
);
346 struct nouveau_channel
*chan
= nvws
->channel
;
347 unsigned handle
= 0x88000000, class;
353 ret
= nouveau_notifier_alloc(chan
, handle
++, 1, &ctx
->ntfy
);
355 nv04_surface_2d_takedown(&ctx
);
359 ret
= nouveau_grobj_alloc(chan
, handle
++, 0x0039, &ctx
->m2mf
);
361 nv04_surface_2d_takedown(&ctx
);
365 BEGIN_RING(chan
, ctx
->m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY
, 1);
366 OUT_RING (chan
, ctx
->ntfy
->handle
);
368 if (chan
->device
->chipset
< 0x10)
369 class = NV04_CONTEXT_SURFACES_2D
;
371 class = NV10_CONTEXT_SURFACES_2D
;
373 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->surf2d
);
375 nv04_surface_2d_takedown(&ctx
);
379 BEGIN_RING(chan
, ctx
->surf2d
,
380 NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
381 OUT_RING (chan
, chan
->vram
->handle
);
382 OUT_RING (chan
, chan
->vram
->handle
);
384 if (chan
->device
->chipset
< 0x10)
385 class = NV04_IMAGE_BLIT
;
387 class = NV12_IMAGE_BLIT
;
389 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->blit
);
391 nv04_surface_2d_takedown(&ctx
);
395 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_DMA_NOTIFY
, 1);
396 OUT_RING (chan
, ctx
->ntfy
->handle
);
397 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_SURFACE
, 1);
398 OUT_RING (chan
, ctx
->surf2d
->handle
);
399 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_OPERATION
, 1);
400 OUT_RING (chan
, NV04_IMAGE_BLIT_OPERATION_SRCCOPY
);
402 ret
= nouveau_grobj_alloc(chan
, handle
++, NV04_GDI_RECTANGLE_TEXT
,
405 nv04_surface_2d_takedown(&ctx
);
409 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY
, 1);
410 OUT_RING (chan
, ctx
->ntfy
->handle
);
411 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_SURFACE
, 1);
412 OUT_RING (chan
, ctx
->surf2d
->handle
);
413 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_OPERATION
, 1);
414 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY
);
415 BEGIN_RING(chan
, ctx
->rect
,
416 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT
, 1);
417 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE
);
419 switch (chan
->device
->chipset
& 0xf0) {
422 class = NV04_SWIZZLED_SURFACE
;
425 class = NV20_SWIZZLED_SURFACE
;
428 class = NV30_SWIZZLED_SURFACE
;
432 class = NV40_SWIZZLED_SURFACE
;
435 /* Famous last words: this really can't happen.. */
440 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->swzsurf
);
442 nv04_surface_2d_takedown(&ctx
);
446 if (chan
->device
->chipset
< 0x10) {
447 class = NV04_SCALED_IMAGE_FROM_MEMORY
;
449 if (chan
->device
->chipset
< 0x40) {
450 class = NV10_SCALED_IMAGE_FROM_MEMORY
;
452 class = NV40_SCALED_IMAGE_FROM_MEMORY
;
455 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->sifm
);
457 nv04_surface_2d_takedown(&ctx
);
462 ctx
->copy
= nv04_surface_copy
;
463 ctx
->fill
= nv04_surface_fill
;