1 #include "pipe/p_context.h"
2 #include "pipe/p_format.h"
4 #include "nouveau_context.h"
6 static INLINE
int log2i(int i
)
33 nv04_surface_format(enum pipe_format format
)
36 case PIPE_FORMAT_A8_UNORM
:
37 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8
;
38 case PIPE_FORMAT_R5G6B5_UNORM
:
39 return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5
;
40 case PIPE_FORMAT_A8R8G8B8_UNORM
:
41 case PIPE_FORMAT_Z24S8_UNORM
:
42 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32
;
49 nv04_rect_format(enum pipe_format format
)
52 case PIPE_FORMAT_A8_UNORM
:
53 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
54 case PIPE_FORMAT_R5G6B5_UNORM
:
55 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5
;
56 case PIPE_FORMAT_A8R8G8B8_UNORM
:
57 case PIPE_FORMAT_Z24S8_UNORM
:
58 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
65 nv04_surface_copy_m2mf(struct nouveau_context
*nv
, unsigned dx
, unsigned dy
,
66 unsigned sx
, unsigned sy
, unsigned w
, unsigned h
)
68 struct nouveau_channel
*chan
= nv
->nvc
->channel
;
69 struct pipe_surface
*dst
= nv
->surf_dst
;
70 struct pipe_surface
*src
= nv
->surf_src
;
71 unsigned dst_offset
, src_offset
;
73 dst_offset
= dst
->offset
+ (dy
* dst
->stride
) + (dx
* dst
->block
.size
);
74 src_offset
= src
->offset
+ (sy
* src
->stride
) + (sx
* src
->block
.size
);
77 int count
= (h
> 2047) ? 2047 : h
;
79 BEGIN_RING(chan
, nv
->nvc
->NvM2MF
,
80 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
81 OUT_RELOCl(chan
, nouveau_buffer(src
->buffer
)->bo
, src_offset
,
82 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
83 OUT_RELOCl(chan
, nouveau_buffer(dst
->buffer
)->bo
, dst_offset
,
84 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_WR
);
85 OUT_RING (chan
, src
->stride
);
86 OUT_RING (chan
, dst
->stride
);
87 OUT_RING (chan
, w
* src
->block
.size
);
88 OUT_RING (chan
, count
);
89 OUT_RING (chan
, 0x0101);
93 src_offset
+= src
->stride
* count
;
94 dst_offset
+= dst
->stride
* count
;
99 nv04_surface_copy_blit(struct nouveau_context
*nv
, unsigned dx
, unsigned dy
,
100 unsigned sx
, unsigned sy
, unsigned w
, unsigned h
)
102 struct nouveau_channel
*chan
= nv
->nvc
->channel
;
104 BEGIN_RING(chan
, nv
->nvc
->NvImageBlit
, 0x0300, 3);
105 OUT_RING (chan
, (sy
<< 16) | sx
);
106 OUT_RING (chan
, (dy
<< 16) | dx
);
107 OUT_RING (chan
, ( h
<< 16) | w
);
111 nv04_surface_copy_prep_swizzled(struct nouveau_context
*nv
,
112 struct pipe_surface
*dst
,
113 struct pipe_surface
*src
)
115 struct nouveau_channel
*chan
= nv
->nvc
->channel
;
117 BEGIN_RING(chan
, nv
->nvc
->NvSwzSurf
,
118 NV04_SWIZZLED_SURFACE_FORMAT
, 2);
119 /* FIXME: read destination format from somewhere */
121 NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8
122 | (log2i(dst
->width
)<<NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT
)
123 | (log2i(dst
->height
)<<NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT
) );
124 OUT_RELOCo(chan
, nouveau_buffer(dst
->buffer
)->bo
,
125 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
127 BEGIN_RING(chan
, nv
->nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION
, 13);
128 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE
);
129 /* FIXME: read source format from somewhere */
130 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8
);
131 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY
);
133 OUT_RING (chan
, (src
->height
<<16) | src
->width
);
135 OUT_RING (chan
, (src
->height
<<16) | src
->width
);
136 OUT_RING (chan
, 1<<20);
137 OUT_RING (chan
, 1<<20);
138 OUT_RING (chan
, (src
->height
<<16) | src
->width
);
141 | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER
142 | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE
);
143 OUT_RELOCo(chan
, nouveau_buffer(src
->buffer
)->bo
,
144 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
147 BEGIN_RING(chan
, nv
->nvc
->NvM2MF
,
148 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
, 2);
149 OUT_RELOCo(chan
, nouveau_buffer(src
->buffer
)->bo
,
150 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
151 OUT_RELOCo(chan
, nouveau_buffer(dst
->buffer
)->bo
,
152 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
154 nv
->surface_copy
= nv04_surface_copy_m2mf
;
161 nv04_surface_copy_prep(struct nouveau_context
*nv
, struct pipe_surface
*dst
,
162 struct pipe_surface
*src
)
164 struct nouveau_channel
*chan
= nv
->nvc
->channel
;
167 if (src
->format
!= dst
->format
)
170 /* Setup transfer to swizzle the texture to vram if needed */
171 /* FIXME/TODO: check proper limits of this operation */
172 if (nouveau_buffer(dst
->buffer
)->bo
->flags
& NOUVEAU_BO_SWIZZLED
) {
173 /* FIXME: Disable it for the moment */
174 /*return nv04_surface_copy_prep_swizzled(nv, dst, src);*/
177 /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
178 * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
180 if ((src
->offset
& 63) || (dst
->offset
& 63)) {
181 BEGIN_RING(nv
->nvc
->channel
, nv
->nvc
->NvM2MF
,
182 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
, 2);
183 OUT_RELOCo(chan
, nouveau_buffer(src
->buffer
)->bo
,
184 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
185 OUT_RELOCo(chan
, nouveau_buffer(dst
->buffer
)->bo
,
186 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
188 nv
->surface_copy
= nv04_surface_copy_m2mf
;
195 if ((format
= nv04_surface_format(dst
->format
)) < 0) {
196 NOUVEAU_ERR("Bad surface format 0x%x\n", dst
->format
);
199 nv
->surface_copy
= nv04_surface_copy_blit
;
201 BEGIN_RING(chan
, nv
->nvc
->NvCtxSurf2D
,
202 NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
203 OUT_RELOCo(chan
, nouveau_buffer(src
->buffer
)->bo
,
204 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
205 OUT_RELOCo(chan
, nouveau_buffer(dst
->buffer
)->bo
,
206 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
208 BEGIN_RING(chan
, nv
->nvc
->NvCtxSurf2D
,
209 NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
210 OUT_RING (chan
, format
);
211 OUT_RING (chan
, (dst
->stride
<< 16) | src
->stride
);
212 OUT_RELOCl(chan
, nouveau_buffer(src
->buffer
)->bo
, src
->offset
,
213 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
214 OUT_RELOCl(chan
, nouveau_buffer(dst
->buffer
)->bo
, dst
->offset
,
215 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
221 nv04_surface_copy_done(struct nouveau_context
*nv
)
223 FIRE_RING(nv
->nvc
->channel
);
227 nv04_surface_fill(struct nouveau_context
*nv
, struct pipe_surface
*dst
,
228 unsigned dx
, unsigned dy
, unsigned w
, unsigned h
,
231 struct nouveau_channel
*chan
= nv
->nvc
->channel
;
232 struct nouveau_grobj
*surf2d
= nv
->nvc
->NvCtxSurf2D
;
233 struct nouveau_grobj
*rect
= nv
->nvc
->NvGdiRect
;
234 int cs2d_format
, gdirect_format
;
236 if ((cs2d_format
= nv04_surface_format(dst
->format
)) < 0) {
237 NOUVEAU_ERR("Bad format = %d\n", dst
->format
);
241 if ((gdirect_format
= nv04_rect_format(dst
->format
)) < 0) {
242 NOUVEAU_ERR("Bad format = %d\n", dst
->format
);
246 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
247 OUT_RELOCo(chan
, nouveau_buffer(dst
->buffer
)->bo
,
248 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
249 OUT_RELOCo(chan
, nouveau_buffer(dst
->buffer
)->bo
,
250 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
251 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
252 OUT_RING (chan
, cs2d_format
);
253 OUT_RING (chan
, (dst
->stride
<< 16) | dst
->stride
);
254 OUT_RELOCl(chan
, nouveau_buffer(dst
->buffer
)->bo
, dst
->offset
,
255 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
256 OUT_RELOCl(chan
, nouveau_buffer(dst
->buffer
)->bo
, dst
->offset
,
257 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
259 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT
, 1);
260 OUT_RING (chan
, gdirect_format
);
261 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR1_A
, 1);
262 OUT_RING (chan
, value
);
263 BEGIN_RING(chan
, rect
,
264 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
265 OUT_RING (chan
, (dx
<< 16) | dy
);
266 OUT_RING (chan
, ( w
<< 16) | h
);
273 nouveau_surface_channel_create_nv04(struct nouveau_channel_context
*nvc
)
275 struct nouveau_channel
*chan
= nvc
->channel
;
276 unsigned chipset
= nvc
->channel
->device
->chipset
, class;
279 if ((ret
= nouveau_grobj_alloc(chan
, nvc
->next_handle
++, 0x39,
281 NOUVEAU_ERR("Error creating m2mf object: %d\n", ret
);
284 BIND_RING (chan
, nvc
->NvM2MF
, nvc
->next_subchannel
++);
285 BEGIN_RING(chan
, nvc
->NvM2MF
,
286 NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY
, 1);
287 OUT_RING (chan
, nvc
->sync_notifier
->handle
);
289 class = chipset
< 0x10 ? NV04_CONTEXT_SURFACES_2D
:
290 NV10_CONTEXT_SURFACES_2D
;
291 if ((ret
= nouveau_grobj_alloc(chan
, nvc
->next_handle
++, class,
292 &nvc
->NvCtxSurf2D
))) {
293 NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret
);
296 BIND_RING (chan
, nvc
->NvCtxSurf2D
, nvc
->next_subchannel
++);
297 BEGIN_RING(chan
, nvc
->NvCtxSurf2D
,
298 NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
299 OUT_RING (chan
, nvc
->channel
->vram
->handle
);
300 OUT_RING (chan
, nvc
->channel
->vram
->handle
);
302 class = chipset
< 0x10 ? NV04_IMAGE_BLIT
: NV12_IMAGE_BLIT
;
303 if ((ret
= nouveau_grobj_alloc(chan
, nvc
->next_handle
++, class,
304 &nvc
->NvImageBlit
))) {
305 NOUVEAU_ERR("Error creating blit object: %d\n", ret
);
308 BIND_RING (chan
, nvc
->NvImageBlit
, nvc
->next_subchannel
++);
309 BEGIN_RING(chan
, nvc
->NvImageBlit
, NV04_IMAGE_BLIT_DMA_NOTIFY
, 1);
310 OUT_RING (chan
, nvc
->sync_notifier
->handle
);
311 BEGIN_RING(chan
, nvc
->NvImageBlit
, NV04_IMAGE_BLIT_SURFACE
, 1);
312 OUT_RING (chan
, nvc
->NvCtxSurf2D
->handle
);
313 BEGIN_RING(chan
, nvc
->NvImageBlit
, NV04_IMAGE_BLIT_OPERATION
, 1);
314 OUT_RING (chan
, NV04_IMAGE_BLIT_OPERATION_SRCCOPY
);
316 class = NV04_GDI_RECTANGLE_TEXT
;
317 if ((ret
= nouveau_grobj_alloc(chan
, nvc
->next_handle
++, class,
319 NOUVEAU_ERR("Error creating rect object: %d\n", ret
);
322 BIND_RING (chan
, nvc
->NvGdiRect
, nvc
->next_subchannel
++);
323 BEGIN_RING(chan
, nvc
->NvGdiRect
, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY
, 1);
324 OUT_RING (chan
, nvc
->sync_notifier
->handle
);
325 BEGIN_RING(chan
, nvc
->NvGdiRect
, NV04_GDI_RECTANGLE_TEXT_SURFACE
, 1);
326 OUT_RING (chan
, nvc
->NvCtxSurf2D
->handle
);
327 BEGIN_RING(chan
, nvc
->NvGdiRect
, NV04_GDI_RECTANGLE_TEXT_OPERATION
, 1);
328 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY
);
329 BEGIN_RING(chan
, nvc
->NvGdiRect
,
330 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT
, 1);
331 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE
);
333 switch (chipset
& 0xf0) {
336 class = NV04_SWIZZLED_SURFACE
;
339 class = NV20_SWIZZLED_SURFACE
;
342 class = NV30_SWIZZLED_SURFACE
;
346 class = NV40_SWIZZLED_SURFACE
;
349 /* Famous last words: this really can't happen.. */
354 ret
= nouveau_grobj_alloc(chan
, nvc
->next_handle
++, class,
357 NOUVEAU_ERR("Error creating swizzled surface: %d\n", ret
);
361 BIND_RING (chan
, nvc
->NvSwzSurf
, nvc
->next_subchannel
++);
362 BEGIN_RING(chan
, nvc
->NvSwzSurf
, NV04_SWIZZLED_SURFACE_DMA_NOTIFY
, 1);
363 OUT_RING (chan
, nvc
->sync_notifier
->handle
);
364 BEGIN_RING(chan
, nvc
->NvSwzSurf
, NV04_SWIZZLED_SURFACE_DMA_IMAGE
, 1);
365 OUT_RING (chan
, nvc
->channel
->vram
->handle
);
367 if (chipset
< 0x10) {
368 class = NV04_SCALED_IMAGE_FROM_MEMORY
;
370 if (chipset
< 0x40) {
371 class = NV10_SCALED_IMAGE_FROM_MEMORY
;
373 class = NV40_SCALED_IMAGE_FROM_MEMORY
;
376 ret
= nouveau_grobj_alloc(chan
, nvc
->next_handle
++, class,
379 NOUVEAU_ERR("Error creating scaled image object: %d\n", ret
);
383 BIND_RING (chan
, nvc
->NvSIFM
, nvc
->next_subchannel
++);
384 BEGIN_RING(chan
, nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY
, 1);
386 BEGIN_RING(chan
, nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE
, 1);
387 OUT_RING (chan
, nvc
->channel
->vram
->handle
);
388 BEGIN_RING(chan
, nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE
, 1);
389 OUT_RING (chan
, nvc
->NvSwzSurf
->handle
);
390 BEGIN_RING(chan
, nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_PATTERN
, 1);
392 BEGIN_RING(chan
, nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_ROP
, 1);
394 BEGIN_RING(chan
, nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_BETA1
, 1);
396 BEGIN_RING(chan
, nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_BETA4
, 1);
398 BEGIN_RING(chan
, nvc
->NvSIFM
, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION
, 1);
399 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY
);
405 nouveau_surface_init_nv04(struct nouveau_context
*nv
)
407 nv
->surface_copy_prep
= nv04_surface_copy_prep
;
408 nv
->surface_copy
= nv04_surface_copy_blit
;
409 nv
->surface_copy_done
= nv04_surface_copy_done
;
410 nv
->surface_fill
= nv04_surface_fill
;