2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
27 struct nv30_context *nv30, enum nv30_transfer_filter filter, \
28 struct nv30_rect *src, struct nv30_rect *dst
30 #include "util/u_math.h"
32 #include "nv_object.xml.h"
33 #include "nv_m2mf.xml.h"
34 #include "nv30/nv01_2d.xml.h"
35 #include "nv30/nv30-40_3d.xml.h"
37 #include "nv30/nv30_context.h"
38 #include "nv30/nv30_transfer.h"
40 /* Various helper functions to transfer different types of data in a number
45 nv30_transfer_scaled(struct nv30_rect
*src
, struct nv30_rect
*dst
)
47 if (src
->x1
- src
->x0
!= dst
->x1
- dst
->x0
)
49 if (src
->y1
- src
->y0
!= dst
->y1
- dst
->y0
)
55 nv30_transfer_blit(XFER_ARGS
)
57 if (nv30
->screen
->eng3d
->oclass
< NV40_3D_CLASS
)
59 if (dst
->offset
& 63 || dst
->pitch
& 63 || dst
->d
> 1)
61 if (dst
->w
< 2 || dst
->h
< 2)
63 if (dst
->cpp
> 4 || (dst
->cpp
== 1 && !dst
->pitch
))
70 static inline struct nouveau_heap
*
71 nv30_transfer_rect_vertprog(struct nv30_context
*nv30
)
73 struct nouveau_heap
*heap
= nv30
->screen
->vp_exec_heap
;
74 struct nouveau_heap
*vp
;
78 if (nouveau_heap_alloc(heap
, 2, &nv30
->blit_vp
, &nv30
->blit_vp
)) {
79 while (heap
->next
&& heap
->size
< 2) {
80 struct nouveau_heap
**evict
= heap
->next
->priv
;
81 nouveau_heap_free(evict
);
84 if (nouveau_heap_alloc(heap
, 2, &nv30
->blit_vp
, &nv30
->blit_vp
))
90 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
92 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_FROM_ID
), 1);
93 PUSH_DATA (push
, vp
->start
);
94 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_INST(0)), 4);
95 PUSH_DATA (push
, 0x401f9c6c); /* mov o[hpos], a[0]; */
96 PUSH_DATA (push
, 0x0040000d);
97 PUSH_DATA (push
, 0x8106c083);
98 PUSH_DATA (push
, 0x6041ff80);
99 BEGIN_NV04(push
, NV30_3D(VP_UPLOAD_INST(0)), 4);
100 PUSH_DATA (push
, 0x401f9c6c); /* mov o[tex0], a[8]; end; */
101 PUSH_DATA (push
, 0x0040080d);
102 PUSH_DATA (push
, 0x8106c083);
103 PUSH_DATA (push
, 0x6041ff9d);
111 static inline struct nv04_resource
*
112 nv30_transfer_rect_fragprog(struct nv30_context
*nv30
)
114 struct nv04_resource
*fp
= nv04_resource(nv30
->blit_fp
);
115 struct pipe_context
*pipe
= &nv30
->base
.pipe
;
119 pipe_buffer_create(pipe
->screen
, 0, PIPE_USAGE_STAGING
, 12 * 4);
121 struct pipe_transfer
*transfer
;
122 u32
*map
= pipe_buffer_map(pipe
, nv30
->blit_fp
,
123 PIPE_TRANSFER_WRITE
, &transfer
);
125 map
[0] = 0x17009e00; /* texr r0, i[tex0], texture[0]; end; */
129 map
[4] = 0x01401e81; /* end; */
133 pipe_buffer_unmap(pipe
, transfer
);
136 fp
= nv04_resource(nv30
->blit_fp
);
137 nouveau_buffer_migrate(&nv30
->base
, fp
, NOUVEAU_BO_VRAM
);
145 nv30_transfer_rect_blit(XFER_ARGS
)
147 struct nv04_resource
*fp
= nv30_transfer_rect_fragprog(nv30
);
148 struct nouveau_heap
*vp
= nv30_transfer_rect_vertprog(nv30
);
149 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
150 struct nouveau_pushbuf_refn refs
[] = {
151 { fp
->bo
, fp
->domain
| NOUVEAU_BO_RD
},
152 { src
->bo
, src
->domain
| NOUVEAU_BO_RD
},
153 { dst
->bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
},
158 if (nouveau_pushbuf_space(push
, 512, 8, 0) ||
159 nouveau_pushbuf_refn (push
, refs
, ARRAY_SIZE(refs
)))
162 /* various switches depending on cpp of the transfer */
165 format
= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
|
166 NV30_3D_RT_FORMAT_ZETA_Z24S8
;
167 texfmt
= NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8
;
171 format
= NV30_3D_RT_FORMAT_COLOR_R5G6B5
|
172 NV30_3D_RT_FORMAT_ZETA_Z16
;
173 texfmt
= NV40_3D_TEX_FORMAT_FORMAT_R5G6B5
;
177 format
= NV30_3D_RT_FORMAT_COLOR_B8
|
178 NV30_3D_RT_FORMAT_ZETA_Z16
;
179 texfmt
= NV40_3D_TEX_FORMAT_FORMAT_L8
;
189 format
|= NV30_3D_RT_FORMAT_TYPE_SWIZZLED
;
190 format
|= util_logbase2(dst
->w
) << 16;
191 format
|= util_logbase2(dst
->h
) << 24;
194 format
|= NV30_3D_RT_FORMAT_TYPE_LINEAR
;
198 BEGIN_NV04(push
, NV30_3D(VIEWPORT_HORIZ
), 2);
199 PUSH_DATA (push
, dst
->w
<< 16);
200 PUSH_DATA (push
, dst
->h
<< 16);
201 BEGIN_NV04(push
, NV30_3D(RT_HORIZ
), 5);
202 PUSH_DATA (push
, dst
->w
<< 16);
203 PUSH_DATA (push
, dst
->h
<< 16);
204 PUSH_DATA (push
, format
);
205 PUSH_DATA (push
, stride
);
206 PUSH_RELOC(push
, dst
->bo
, dst
->offset
, NOUVEAU_BO_LOW
, 0, 0);
207 BEGIN_NV04(push
, NV30_3D(RT_ENABLE
), 1);
208 PUSH_DATA (push
, NV30_3D_RT_ENABLE_COLOR0
);
210 nv30
->dirty
|= NV30_NEW_FRAMEBUFFER
;
213 BEGIN_NV04(push
, NV30_3D(VIEWPORT_TRANSLATE_X
), 8);
214 PUSH_DATAf(push
, 0.0);
215 PUSH_DATAf(push
, 0.0);
216 PUSH_DATAf(push
, 0.0);
217 PUSH_DATAf(push
, 0.0);
218 PUSH_DATAf(push
, 1.0);
219 PUSH_DATAf(push
, 1.0);
220 PUSH_DATAf(push
, 1.0);
221 PUSH_DATAf(push
, 1.0);
222 BEGIN_NV04(push
, NV30_3D(DEPTH_RANGE_NEAR
), 2);
223 PUSH_DATAf(push
, 0.0);
224 PUSH_DATAf(push
, 1.0);
226 nv30
->dirty
|= NV30_NEW_VIEWPORT
;
229 BEGIN_NV04(push
, NV30_3D(COLOR_LOGIC_OP_ENABLE
), 1);
231 BEGIN_NV04(push
, NV30_3D(DITHER_ENABLE
), 1);
233 BEGIN_NV04(push
, NV30_3D(BLEND_FUNC_ENABLE
), 1);
235 BEGIN_NV04(push
, NV30_3D(COLOR_MASK
), 1);
236 PUSH_DATA (push
, 0x01010101);
238 nv30
->dirty
|= NV30_NEW_BLEND
;
240 /* depth-stencil-alpha state */
241 BEGIN_NV04(push
, NV30_3D(DEPTH_WRITE_ENABLE
), 2);
244 BEGIN_NV04(push
, NV30_3D(STENCIL_ENABLE(0)), 1);
246 BEGIN_NV04(push
, NV30_3D(STENCIL_ENABLE(1)), 1);
248 BEGIN_NV04(push
, NV30_3D(ALPHA_FUNC_ENABLE
), 1);
251 nv30
->dirty
|= NV30_NEW_ZSA
;
253 /* rasterizer state */
254 BEGIN_NV04(push
, NV30_3D(SHADE_MODEL
), 1);
255 PUSH_DATA (push
, NV30_3D_SHADE_MODEL_FLAT
);
256 BEGIN_NV04(push
, NV30_3D(CULL_FACE_ENABLE
), 1);
258 BEGIN_NV04(push
, NV30_3D(POLYGON_MODE_FRONT
), 2);
259 PUSH_DATA (push
, NV30_3D_POLYGON_MODE_FRONT_FILL
);
260 PUSH_DATA (push
, NV30_3D_POLYGON_MODE_BACK_FILL
);
261 BEGIN_NV04(push
, NV30_3D(POLYGON_OFFSET_FILL_ENABLE
), 1);
263 BEGIN_NV04(push
, NV30_3D(POLYGON_STIPPLE_ENABLE
), 1);
266 nv30
->state
.scissor_off
= 0;
267 nv30
->dirty
|= NV30_NEW_RASTERIZER
;
270 BEGIN_NV04(push
, NV30_3D(VP_START_FROM_ID
), 1);
271 PUSH_DATA (push
, vp
->start
);
272 BEGIN_NV04(push
, NV40_3D(VP_ATTRIB_EN
), 2);
273 PUSH_DATA (push
, 0x00000101); /* attrib: 0, 8 */
274 PUSH_DATA (push
, 0x00004000); /* result: hpos, tex0 */
275 BEGIN_NV04(push
, NV30_3D(ENGINE
), 1);
276 PUSH_DATA (push
, 0x00000103);
277 BEGIN_NV04(push
, NV30_3D(VP_CLIP_PLANES_ENABLE
), 1);
278 PUSH_DATA (push
, 0x00000000);
280 nv30
->dirty
|= NV30_NEW_VERTPROG
;
281 nv30
->dirty
|= NV30_NEW_CLIP
;
283 /* fragment program */
284 BEGIN_NV04(push
, NV30_3D(FP_ACTIVE_PROGRAM
), 1);
285 PUSH_RELOC(push
, fp
->bo
, fp
->offset
, fp
->domain
|
286 NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
287 NV30_3D_FP_ACTIVE_PROGRAM_DMA0
,
288 NV30_3D_FP_ACTIVE_PROGRAM_DMA1
);
289 BEGIN_NV04(push
, NV30_3D(FP_CONTROL
), 1);
290 PUSH_DATA (push
, 0x02000000);
292 nv30
->state
.fragprog
= NULL
;
293 nv30
->dirty
|= NV30_NEW_FRAGPROG
;
296 texfmt
|= 1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT
;
297 texfmt
|= NV30_3D_TEX_FORMAT_NO_BORDER
;
298 texfmt
|= NV40_3D_TEX_FORMAT_RECT
;
299 texfmt
|= 0x00008000;
301 texfmt
|= NV30_3D_TEX_FORMAT_DIMS_2D
;
303 texfmt
|= NV30_3D_TEX_FORMAT_DIMS_3D
;
305 texfmt
|= NV40_3D_TEX_FORMAT_LINEAR
;
307 BEGIN_NV04(push
, NV30_3D(TEX_OFFSET(0)), 8);
308 PUSH_RELOC(push
, src
->bo
, src
->offset
, NOUVEAU_BO_LOW
, 0, 0);
309 PUSH_RELOC(push
, src
->bo
, texfmt
, NOUVEAU_BO_OR
,
310 NV30_3D_TEX_FORMAT_DMA0
, NV30_3D_TEX_FORMAT_DMA1
);
311 PUSH_DATA (push
, NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE
|
312 NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE
|
313 NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE
);
314 PUSH_DATA (push
, NV40_3D_TEX_ENABLE_ENABLE
);
315 PUSH_DATA (push
, texswz
);
318 PUSH_DATA (push
, NV30_3D_TEX_FILTER_MIN_LINEAR
|
319 NV30_3D_TEX_FILTER_MAG_LINEAR
| 0x00002000);
322 PUSH_DATA (push
, NV30_3D_TEX_FILTER_MIN_NEAREST
|
323 NV30_3D_TEX_FILTER_MAG_NEAREST
| 0x00002000);
326 PUSH_DATA (push
, (src
->w
<< 16) | src
->h
);
327 PUSH_DATA (push
, 0x00000000);
328 BEGIN_NV04(push
, NV40_3D(TEX_SIZE1(0)), 1);
329 PUSH_DATA (push
, 0x00100000 | src
->pitch
);
330 BEGIN_NV04(push
, SUBC_3D(0x0b40), 1);
331 PUSH_DATA (push
, src
->d
< 2 ? 0x00000001 : 0x00000000);
332 BEGIN_NV04(push
, NV40_3D(TEX_CACHE_CTL
), 1);
335 nv30
->fragprog
.dirty_samplers
|= 1;
336 nv30
->dirty
|= NV30_NEW_FRAGTEX
;
339 BEGIN_NV04(push
, NV30_3D(SCISSOR_HORIZ
), 2);
340 PUSH_DATA (push
, (dst
->x1
- dst
->x0
) << 16 | dst
->x0
);
341 PUSH_DATA (push
, (dst
->y1
- dst
->y0
) << 16 | dst
->y0
);
342 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
343 PUSH_DATA (push
, NV30_3D_VERTEX_BEGIN_END_QUADS
);
344 BEGIN_NV04(push
, NV30_3D(VTX_ATTR_3F(8)), 3);
345 PUSH_DATAf(push
, src
->x0
);
346 PUSH_DATAf(push
, src
->y0
);
347 PUSH_DATAf(push
, src
->z
);
348 BEGIN_NV04(push
, NV30_3D(VTX_ATTR_2I(0)), 1);
349 PUSH_DATA (push
, (dst
->y0
<< 16) | dst
->x0
);
350 BEGIN_NV04(push
, NV30_3D(VTX_ATTR_3F(8)), 3);
351 PUSH_DATAf(push
, src
->x1
);
352 PUSH_DATAf(push
, src
->y0
);
353 PUSH_DATAf(push
, src
->z
);
354 BEGIN_NV04(push
, NV30_3D(VTX_ATTR_2I(0)), 1);
355 PUSH_DATA (push
, (dst
->y0
<< 16) | dst
->x1
);
356 BEGIN_NV04(push
, NV30_3D(VTX_ATTR_3F(8)), 3);
357 PUSH_DATAf(push
, src
->x1
);
358 PUSH_DATAf(push
, src
->y1
);
359 PUSH_DATAf(push
, src
->z
);
360 BEGIN_NV04(push
, NV30_3D(VTX_ATTR_2I(0)), 1);
361 PUSH_DATA (push
, (dst
->y1
<< 16) | dst
->x1
);
362 BEGIN_NV04(push
, NV30_3D(VTX_ATTR_3F(8)), 3);
363 PUSH_DATAf(push
, src
->x0
);
364 PUSH_DATAf(push
, src
->y1
);
365 PUSH_DATAf(push
, src
->z
);
366 BEGIN_NV04(push
, NV30_3D(VTX_ATTR_2I(0)), 1);
367 PUSH_DATA (push
, (dst
->y1
<< 16) | dst
->x0
);
368 BEGIN_NV04(push
, NV30_3D(VERTEX_BEGIN_END
), 1);
369 PUSH_DATA (push
, NV30_3D_VERTEX_BEGIN_END_STOP
);
373 nv30_transfer_sifm(XFER_ARGS
)
375 if (!src
->pitch
|| src
->w
> 1024 || src
->h
> 1024 || src
->w
< 2 || src
->h
< 2)
378 if (src
->d
> 1 || dst
->d
> 1)
381 if (dst
->offset
& 63)
385 if (dst
->w
> 2048 || dst
->h
> 2048 || dst
->w
< 2 || dst
->h
< 2)
388 if (dst
->domain
!= NOUVEAU_BO_VRAM
)
398 nv30_transfer_rect_sifm(XFER_ARGS
)
401 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
402 struct nouveau_pushbuf_refn refs
[] = {
403 { src
->bo
, src
->domain
| NOUVEAU_BO_RD
},
404 { dst
->bo
, dst
->domain
| NOUVEAU_BO_WR
},
406 struct nv04_fifo
*fifo
= push
->channel
->data
;
407 unsigned si_fmt
, si_arg
;
411 case 4: ss_fmt
= NV04_SURFACE_SWZ_FORMAT_COLOR_A8R8G8B8
; break;
412 case 2: ss_fmt
= NV04_SURFACE_SWZ_FORMAT_COLOR_R5G6B5
; break;
414 ss_fmt
= NV04_SURFACE_SWZ_FORMAT_COLOR_Y8
;
419 case 4: si_fmt
= NV03_SIFM_COLOR_FORMAT_A8R8G8B8
; break;
420 case 2: si_fmt
= NV03_SIFM_COLOR_FORMAT_R5G6B5
; break;
422 si_fmt
= NV03_SIFM_COLOR_FORMAT_AY8
;
426 if (filter
== NEAREST
) {
427 si_arg
= NV03_SIFM_FORMAT_ORIGIN_CENTER
;
428 si_arg
|= NV03_SIFM_FORMAT_FILTER_POINT_SAMPLE
;
430 si_arg
= NV03_SIFM_FORMAT_ORIGIN_CORNER
;
431 si_arg
|= NV03_SIFM_FORMAT_FILTER_BILINEAR
;
434 if (nouveau_pushbuf_space(push
, 64, 6, 0) ||
435 nouveau_pushbuf_refn (push
, refs
, 2))
439 BEGIN_NV04(push
, NV04_SF2D(DMA_IMAGE_SOURCE
), 2);
440 PUSH_RELOC(push
, dst
->bo
, 0, NOUVEAU_BO_OR
, fifo
->vram
, fifo
->gart
);
441 PUSH_RELOC(push
, dst
->bo
, 0, NOUVEAU_BO_OR
, fifo
->vram
, fifo
->gart
);
442 BEGIN_NV04(push
, NV04_SF2D(FORMAT
), 4);
443 PUSH_DATA (push
, ss_fmt
);
444 PUSH_DATA (push
, dst
->pitch
<< 16 | dst
->pitch
);
445 PUSH_RELOC(push
, dst
->bo
, dst
->offset
, NOUVEAU_BO_LOW
, 0, 0);
446 PUSH_RELOC(push
, dst
->bo
, dst
->offset
, NOUVEAU_BO_LOW
, 0, 0);
447 BEGIN_NV04(push
, NV05_SIFM(SURFACE
), 1);
448 PUSH_DATA (push
, nv30
->screen
->surf2d
->handle
);
450 BEGIN_NV04(push
, NV04_SSWZ(DMA_IMAGE
), 1);
451 PUSH_RELOC(push
, dst
->bo
, 0, NOUVEAU_BO_OR
, fifo
->vram
, fifo
->gart
);
452 BEGIN_NV04(push
, NV04_SSWZ(FORMAT
), 2);
453 PUSH_DATA (push
, ss_fmt
| (util_logbase2(dst
->w
) << 16) |
454 (util_logbase2(dst
->h
) << 24));
455 PUSH_RELOC(push
, dst
->bo
, dst
->offset
, NOUVEAU_BO_LOW
, 0, 0);
456 BEGIN_NV04(push
, NV05_SIFM(SURFACE
), 1);
457 PUSH_DATA (push
, nv30
->screen
->swzsurf
->handle
);
460 BEGIN_NV04(push
, NV03_SIFM(DMA_IMAGE
), 1);
461 PUSH_RELOC(push
, src
->bo
, 0, NOUVEAU_BO_OR
, fifo
->vram
, fifo
->gart
);
462 BEGIN_NV04(push
, NV03_SIFM(COLOR_FORMAT
), 8);
463 PUSH_DATA (push
, si_fmt
);
464 PUSH_DATA (push
, NV03_SIFM_OPERATION_SRCCOPY
);
465 PUSH_DATA (push
, ( dst
->y0
<< 16) | dst
->x0
);
466 PUSH_DATA (push
, ((dst
->y1
- dst
->y0
) << 16) | (dst
->x1
- dst
->x0
));
467 PUSH_DATA (push
, ( dst
->y0
<< 16) | dst
->x0
);
468 PUSH_DATA (push
, ((dst
->y1
- dst
->y0
) << 16) | (dst
->x1
- dst
->x0
));
469 PUSH_DATA (push
, ((src
->x1
- src
->x0
) << 20) / (dst
->x1
- dst
->x0
));
470 PUSH_DATA (push
, ((src
->y1
- src
->y0
) << 20) / (dst
->y1
- dst
->y0
));
471 BEGIN_NV04(push
, NV03_SIFM(SIZE
), 4);
472 PUSH_DATA (push
, align(src
->h
, 2) << 16 | align(src
->w
, 2));
473 PUSH_DATA (push
, src
->pitch
| si_arg
);
474 PUSH_RELOC(push
, src
->bo
, src
->offset
, NOUVEAU_BO_LOW
, 0, 0);
475 PUSH_DATA (push
, (src
->y0
<< 20) | src
->x0
<< 4);
478 /* The NOP+OFFSET_OUT stuff after each M2MF transfer *is* actually required
479 * to prevent some odd things from happening, easily reproducible by
480 * attempting to do conditional rendering that has a M2MF transfer done
481 * some time before it. 0x1e98 will fail with a DMA_W_PROTECTION (assuming
482 * that name is still accurate on nv4x) error.
486 nv30_transfer_m2mf(XFER_ARGS
)
488 if (!src
->pitch
|| !dst
->pitch
)
490 if (nv30_transfer_scaled(src
, dst
))
496 nv30_transfer_rect_m2mf(XFER_ARGS
)
498 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
499 struct nouveau_pushbuf_refn refs
[] = {
500 { src
->bo
, src
->domain
| NOUVEAU_BO_RD
},
501 { dst
->bo
, dst
->domain
| NOUVEAU_BO_WR
},
503 struct nv04_fifo
*fifo
= push
->channel
->data
;
504 unsigned src_offset
= src
->offset
;
505 unsigned dst_offset
= dst
->offset
;
506 unsigned w
= dst
->x1
- dst
->x0
;
507 unsigned h
= dst
->y1
- dst
->y0
;
509 src_offset
+= (src
->y0
* src
->pitch
) + (src
->x0
* src
->cpp
);
510 dst_offset
+= (dst
->y0
* dst
->pitch
) + (dst
->x0
* dst
->cpp
);
512 BEGIN_NV04(push
, NV03_M2MF(DMA_BUFFER_IN
), 2);
513 PUSH_DATA (push
, (src
->domain
== NOUVEAU_BO_VRAM
) ? fifo
->vram
: fifo
->gart
);
514 PUSH_DATA (push
, (dst
->domain
== NOUVEAU_BO_VRAM
) ? fifo
->vram
: fifo
->gart
);
517 unsigned lines
= (h
> 2047) ? 2047 : h
;
519 if (nouveau_pushbuf_space(push
, 32, 2, 0) ||
520 nouveau_pushbuf_refn (push
, refs
, 2))
523 BEGIN_NV04(push
, NV03_M2MF(OFFSET_IN
), 8);
524 PUSH_RELOC(push
, src
->bo
, src_offset
, NOUVEAU_BO_LOW
, 0, 0);
525 PUSH_RELOC(push
, dst
->bo
, dst_offset
, NOUVEAU_BO_LOW
, 0, 0);
526 PUSH_DATA (push
, src
->pitch
);
527 PUSH_DATA (push
, dst
->pitch
);
528 PUSH_DATA (push
, w
* src
->cpp
);
529 PUSH_DATA (push
, lines
);
530 PUSH_DATA (push
, NV03_M2MF_FORMAT_INPUT_INC_1
|
531 NV03_M2MF_FORMAT_OUTPUT_INC_1
);
532 PUSH_DATA (push
, 0x00000000);
533 BEGIN_NV04(push
, NV04_GRAPH(M2MF
, NOP
), 1);
534 PUSH_DATA (push
, 0x00000000);
535 BEGIN_NV04(push
, NV03_M2MF(OFFSET_OUT
), 1);
536 PUSH_DATA (push
, 0x00000000);
539 src_offset
+= src
->pitch
* lines
;
540 dst_offset
+= dst
->pitch
* lines
;
545 nv30_transfer_cpu(XFER_ARGS
)
547 if (nv30_transfer_scaled(src
, dst
))
553 linear_ptr(struct nv30_rect
*rect
, char *base
, int x
, int y
, int z
)
555 return base
+ (y
* rect
->pitch
) + (x
* rect
->cpp
);
558 static inline unsigned
559 swizzle2d(unsigned v
, unsigned s
)
561 v
= (v
| (v
<< 8)) & 0x00ff00ff;
562 v
= (v
| (v
<< 4)) & 0x0f0f0f0f;
563 v
= (v
| (v
<< 2)) & 0x33333333;
564 v
= (v
| (v
<< 1)) & 0x55555555;
569 swizzle2d_ptr(struct nv30_rect
*rect
, char *base
, int x
, int y
, int z
)
571 unsigned k
= util_logbase2(MIN2(rect
->w
, rect
->h
));
572 unsigned km
= (1 << k
) - 1;
573 unsigned nx
= rect
->w
>> k
;
574 unsigned tx
= x
>> k
;
575 unsigned ty
= y
>> k
;
578 m
= swizzle2d(x
& km
, 0);
579 m
|= swizzle2d(y
& km
, 1);
580 m
+= ((ty
* nx
) + tx
) << k
<< k
;
582 return base
+ (m
* rect
->cpp
);
586 swizzle3d_ptr(struct nv30_rect
*rect
, char *base
, int x
, int y
, int z
)
588 unsigned w
= rect
->w
>> 1;
589 unsigned h
= rect
->h
>> 1;
590 unsigned d
= rect
->d
>> 1;
613 return base
+ (v
* rect
->cpp
);
616 typedef char *(*get_ptr_t
)(struct nv30_rect
*, char *, int, int, int);
618 static inline get_ptr_t
619 get_ptr(struct nv30_rect
*rect
)
625 return swizzle2d_ptr
;
627 return swizzle3d_ptr
;
631 nv30_transfer_rect_cpu(XFER_ARGS
)
633 get_ptr_t sp
= get_ptr(src
);
634 get_ptr_t dp
= get_ptr(dst
);
635 char *srcmap
, *dstmap
;
638 nouveau_bo_map(src
->bo
, NOUVEAU_BO_RD
, nv30
->base
.client
);
639 nouveau_bo_map(dst
->bo
, NOUVEAU_BO_WR
, nv30
->base
.client
);
640 srcmap
= src
->bo
->map
+ src
->offset
;
641 dstmap
= dst
->bo
->map
+ dst
->offset
;
643 for (y
= 0; y
< (dst
->y1
- dst
->y0
); y
++) {
644 for (x
= 0; x
< (dst
->x1
- dst
->x0
); x
++) {
645 memcpy(dp(dst
, dstmap
, dst
->x0
+ x
, dst
->y0
+ y
, dst
->z
),
646 sp(src
, srcmap
, src
->x0
+ x
, src
->y0
+ y
, src
->z
), dst
->cpp
);
652 nv30_transfer_rect(struct nv30_context
*nv30
, enum nv30_transfer_filter filter
,
653 struct nv30_rect
*src
, struct nv30_rect
*dst
)
655 static const struct {
657 bool (*possible
)(XFER_ARGS
);
658 void (*execute
)(XFER_ARGS
);
659 } *method
, methods
[] = {
660 { "m2mf", nv30_transfer_m2mf
, nv30_transfer_rect_m2mf
},
661 { "sifm", nv30_transfer_sifm
, nv30_transfer_rect_sifm
},
662 { "blit", nv30_transfer_blit
, nv30_transfer_rect_blit
},
663 { "rect", nv30_transfer_cpu
, nv30_transfer_rect_cpu
},
667 for (method
= methods
; method
->possible
; method
++) {
668 if (method
->possible(nv30
, filter
, src
, dst
)) {
669 method
->execute(nv30
, filter
, src
, dst
);
678 nv30_transfer_push_data(struct nouveau_context
*nv
,
679 struct nouveau_bo
*bo
, unsigned offset
, unsigned domain
,
680 unsigned size
, void *data
)
682 /* use ifc, or scratch + copy_data? */
683 fprintf(stderr
, "nv30: push_data not implemented\n");
687 nv30_transfer_copy_data(struct nouveau_context
*nv
,
688 struct nouveau_bo
*dst
, unsigned d_off
, unsigned d_dom
,
689 struct nouveau_bo
*src
, unsigned s_off
, unsigned s_dom
,
692 struct nv04_fifo
*fifo
= nv
->screen
->channel
->data
;
693 struct nouveau_pushbuf_refn refs
[] = {
694 { src
, s_dom
| NOUVEAU_BO_RD
},
695 { dst
, d_dom
| NOUVEAU_BO_WR
},
697 struct nouveau_pushbuf
*push
= nv
->pushbuf
;
698 unsigned pages
, lines
;
701 size
-= (pages
<< 12);
703 BEGIN_NV04(push
, NV03_M2MF(DMA_BUFFER_IN
), 2);
704 PUSH_DATA (push
, (s_dom
== NOUVEAU_BO_VRAM
) ? fifo
->vram
: fifo
->gart
);
705 PUSH_DATA (push
, (d_dom
== NOUVEAU_BO_VRAM
) ? fifo
->vram
: fifo
->gart
);
708 lines
= (pages
> 2047) ? 2047 : pages
;
711 if (nouveau_pushbuf_space(push
, 32, 2, 0) ||
712 nouveau_pushbuf_refn (push
, refs
, 2))
715 BEGIN_NV04(push
, NV03_M2MF(OFFSET_IN
), 8);
716 PUSH_RELOC(push
, src
, s_off
, NOUVEAU_BO_LOW
, 0, 0);
717 PUSH_RELOC(push
, dst
, d_off
, NOUVEAU_BO_LOW
, 0, 0);
718 PUSH_DATA (push
, 4096);
719 PUSH_DATA (push
, 4096);
720 PUSH_DATA (push
, 4096);
721 PUSH_DATA (push
, lines
);
722 PUSH_DATA (push
, NV03_M2MF_FORMAT_INPUT_INC_1
|
723 NV03_M2MF_FORMAT_OUTPUT_INC_1
);
724 PUSH_DATA (push
, 0x00000000);
725 BEGIN_NV04(push
, NV04_GRAPH(M2MF
, NOP
), 1);
726 PUSH_DATA (push
, 0x00000000);
727 BEGIN_NV04(push
, NV03_M2MF(OFFSET_OUT
), 1);
728 PUSH_DATA (push
, 0x00000000);
730 s_off
+= (lines
<< 12);
731 d_off
+= (lines
<< 12);
735 if (nouveau_pushbuf_space(push
, 32, 2, 0) ||
736 nouveau_pushbuf_refn (push
, refs
, 2))
739 BEGIN_NV04(push
, NV03_M2MF(OFFSET_IN
), 8);
740 PUSH_RELOC(push
, src
, s_off
, NOUVEAU_BO_LOW
, 0, 0);
741 PUSH_RELOC(push
, dst
, d_off
, NOUVEAU_BO_LOW
, 0, 0);
742 PUSH_DATA (push
, size
);
743 PUSH_DATA (push
, size
);
744 PUSH_DATA (push
, size
);
746 PUSH_DATA (push
, NV03_M2MF_FORMAT_INPUT_INC_1
|
747 NV03_M2MF_FORMAT_OUTPUT_INC_1
);
748 PUSH_DATA (push
, 0x00000000);
749 BEGIN_NV04(push
, NV04_GRAPH(M2MF
, NOP
), 1);
750 PUSH_DATA (push
, 0x00000000);
751 BEGIN_NV04(push
, NV03_M2MF(OFFSET_OUT
), 1);
752 PUSH_DATA (push
, 0x00000000);