Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv30/nv30_transfer.c
4574 views
1
/*
2
* Copyright 2012 Red Hat Inc.
3
*
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:
10
*
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
13
*
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.
21
*
22
* Authors: Ben Skeggs
23
*
24
*/
25
26
#define XFER_ARGS \
27
struct nv30_context *nv30, enum nv30_transfer_filter filter, \
28
struct nv30_rect *src, struct nv30_rect *dst
29
30
#include "util/u_math.h"
31
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"
36
37
#include "nv30/nv30_context.h"
38
#include "nv30/nv30_transfer.h"
39
40
/* Various helper functions to transfer different types of data in a number
41
* of different ways.
42
*/
43
44
static inline bool
45
nv30_transfer_scaled(struct nv30_rect *src, struct nv30_rect *dst)
46
{
47
if (src->x1 - src->x0 != dst->x1 - dst->x0)
48
return true;
49
if (src->y1 - src->y0 != dst->y1 - dst->y0)
50
return true;
51
return false;
52
}
53
54
static inline bool
55
nv30_transfer_blit(XFER_ARGS)
56
{
57
if (nv30->screen->eng3d->oclass < NV40_3D_CLASS)
58
return false;
59
if (dst->offset & 63 || dst->pitch & 63 || dst->d > 1)
60
return false;
61
if (dst->w < 2 || dst->h < 2)
62
return false;
63
if (dst->cpp > 4 || (dst->cpp == 1 && !dst->pitch))
64
return false;
65
if (src->cpp > 4)
66
return false;
67
return true;
68
}
69
70
static inline struct nouveau_heap *
71
nv30_transfer_rect_vertprog(struct nv30_context *nv30)
72
{
73
struct nouveau_heap *heap = nv30->screen->vp_exec_heap;
74
struct nouveau_heap *vp;
75
76
vp = nv30->blit_vp;
77
if (!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);
82
}
83
84
if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp))
85
return NULL;
86
}
87
88
vp = nv30->blit_vp;
89
if (vp) {
90
struct nouveau_pushbuf *push = nv30->base.pushbuf;
91
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);
104
}
105
}
106
107
return vp;
108
}
109
110
111
static inline struct nv04_resource *
112
nv30_transfer_rect_fragprog(struct nv30_context *nv30)
113
{
114
struct nv04_resource *fp = nv04_resource(nv30->blit_fp);
115
struct pipe_context *pipe = &nv30->base.pipe;
116
117
if (!fp) {
118
nv30->blit_fp =
119
pipe_buffer_create(pipe->screen, 0, PIPE_USAGE_STAGING, 12 * 4);
120
if (nv30->blit_fp) {
121
struct pipe_transfer *transfer;
122
u32 *map = pipe_buffer_map(pipe, nv30->blit_fp,
123
PIPE_MAP_WRITE, &transfer);
124
if (map) {
125
map[0] = 0x17009e00; /* texr r0, i[tex0], texture[0]; end; */
126
map[1] = 0x1c9dc801;
127
map[2] = 0x0001c800;
128
map[3] = 0x3fe1c800;
129
map[4] = 0x01401e81; /* end; */
130
map[5] = 0x1c9dc800;
131
map[6] = 0x0001c800;
132
map[7] = 0x0001c800;
133
pipe_buffer_unmap(pipe, transfer);
134
}
135
136
fp = nv04_resource(nv30->blit_fp);
137
nouveau_buffer_migrate(&nv30->base, fp, NOUVEAU_BO_VRAM);
138
}
139
}
140
141
return fp;
142
}
143
144
static void
145
nv30_transfer_rect_blit(XFER_ARGS)
146
{
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 },
154
};
155
u32 texfmt, texswz;
156
u32 format, stride;
157
158
if (nouveau_pushbuf_space(push, 512, 8, 0) ||
159
nouveau_pushbuf_refn (push, refs, ARRAY_SIZE(refs)))
160
return;
161
162
/* various switches depending on cpp of the transfer */
163
switch (dst->cpp) {
164
case 4:
165
format = NV30_3D_RT_FORMAT_COLOR_A8R8G8B8 |
166
NV30_3D_RT_FORMAT_ZETA_Z24S8;
167
texfmt = NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8;
168
texswz = 0x0000aae4;
169
break;
170
case 2:
171
format = NV30_3D_RT_FORMAT_COLOR_R5G6B5 |
172
NV30_3D_RT_FORMAT_ZETA_Z16;
173
texfmt = NV40_3D_TEX_FORMAT_FORMAT_R5G6B5;
174
texswz = 0x0000a9e4;
175
break;
176
case 1:
177
format = NV30_3D_RT_FORMAT_COLOR_B8 |
178
NV30_3D_RT_FORMAT_ZETA_Z16;
179
texfmt = NV40_3D_TEX_FORMAT_FORMAT_L8;
180
texswz = 0x0000aaff;
181
break;
182
default:
183
assert(0);
184
return;
185
}
186
187
/* render target */
188
if (!dst->pitch) {
189
format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
190
format |= util_logbase2(dst->w) << 16;
191
format |= util_logbase2(dst->h) << 24;
192
stride = 64;
193
} else {
194
format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
195
stride = dst->pitch;
196
}
197
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);
209
210
nv30->dirty |= NV30_NEW_FRAMEBUFFER;
211
212
/* viewport state */
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);
225
226
nv30->dirty |= NV30_NEW_VIEWPORT;
227
228
/* blend state */
229
BEGIN_NV04(push, NV30_3D(COLOR_LOGIC_OP_ENABLE), 1);
230
PUSH_DATA (push, 0);
231
BEGIN_NV04(push, NV30_3D(DITHER_ENABLE), 1);
232
PUSH_DATA (push, 0);
233
BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1);
234
PUSH_DATA (push, 0);
235
BEGIN_NV04(push, NV30_3D(COLOR_MASK), 1);
236
PUSH_DATA (push, 0x01010101);
237
238
nv30->dirty |= NV30_NEW_BLEND;
239
240
/* depth-stencil-alpha state */
241
BEGIN_NV04(push, NV30_3D(DEPTH_WRITE_ENABLE), 2);
242
PUSH_DATA (push, 0);
243
PUSH_DATA (push, 0);
244
BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 1);
245
PUSH_DATA (push, 0);
246
BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(1)), 1);
247
PUSH_DATA (push, 0);
248
BEGIN_NV04(push, NV30_3D(ALPHA_FUNC_ENABLE), 1);
249
PUSH_DATA (push, 0);
250
251
nv30->dirty |= NV30_NEW_ZSA;
252
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);
257
PUSH_DATA (push, 0);
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);
262
PUSH_DATA (push, 0);
263
BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_ENABLE), 1);
264
PUSH_DATA (push, 0);
265
266
nv30->state.scissor_off = 0;
267
nv30->dirty |= NV30_NEW_RASTERIZER;
268
269
/* vertex program */
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);
279
280
nv30->dirty |= NV30_NEW_VERTPROG;
281
nv30->dirty |= NV30_NEW_CLIP;
282
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);
291
292
nv30->state.fragprog = NULL;
293
nv30->dirty |= NV30_NEW_FRAGPROG;
294
295
/* texture */
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;
300
if (src->d < 2)
301
texfmt |= NV30_3D_TEX_FORMAT_DIMS_2D;
302
else
303
texfmt |= NV30_3D_TEX_FORMAT_DIMS_3D;
304
if (src->pitch)
305
texfmt |= NV40_3D_TEX_FORMAT_LINEAR;
306
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);
316
switch (filter) {
317
case BILINEAR:
318
PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR |
319
NV30_3D_TEX_FILTER_MAG_LINEAR | 0x00002000);
320
break;
321
default:
322
PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST |
323
NV30_3D_TEX_FILTER_MAG_NEAREST | 0x00002000);
324
break;
325
}
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);
333
PUSH_DATA (push, 1);
334
335
nv30->fragprog.dirty_samplers |= 1;
336
nv30->dirty |= NV30_NEW_FRAGTEX;
337
338
/* blit! */
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);
370
}
371
372
static bool
373
nv30_transfer_sifm(XFER_ARGS)
374
{
375
if (!src->pitch || src->w > 1024 || src->h > 1024 || src->w < 2 || src->h < 2)
376
return false;
377
378
if (src->d > 1 || dst->d > 1)
379
return false;
380
381
if (dst->offset & 63)
382
return false;
383
384
if (!dst->pitch) {
385
if (dst->w > 2048 || dst->h > 2048 || dst->w < 2 || dst->h < 2)
386
return false;
387
} else {
388
if (dst->domain != NOUVEAU_BO_VRAM)
389
return false;
390
if (dst->pitch & 63)
391
return false;
392
}
393
394
return true;
395
}
396
397
static void
398
nv30_transfer_rect_sifm(XFER_ARGS)
399
400
{
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 },
405
};
406
struct nv04_fifo *fifo = push->channel->data;
407
unsigned si_fmt, si_arg;
408
unsigned ss_fmt;
409
410
switch (dst->cpp) {
411
case 4: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_A8R8G8B8; break;
412
case 2: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_R5G6B5; break;
413
default:
414
ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_Y8;
415
break;
416
}
417
418
switch (src->cpp) {
419
case 4: si_fmt = NV03_SIFM_COLOR_FORMAT_A8R8G8B8; break;
420
case 2: si_fmt = NV03_SIFM_COLOR_FORMAT_R5G6B5; break;
421
default:
422
si_fmt = NV03_SIFM_COLOR_FORMAT_AY8;
423
break;
424
}
425
426
if (filter == NEAREST) {
427
si_arg = NV03_SIFM_FORMAT_ORIGIN_CENTER;
428
si_arg |= NV03_SIFM_FORMAT_FILTER_POINT_SAMPLE;
429
} else {
430
si_arg = NV03_SIFM_FORMAT_ORIGIN_CORNER;
431
si_arg |= NV03_SIFM_FORMAT_FILTER_BILINEAR;
432
}
433
434
if (nouveau_pushbuf_space(push, 64, 6, 0) ||
435
nouveau_pushbuf_refn (push, refs, 2))
436
return;
437
438
if (dst->pitch) {
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);
449
} else {
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);
458
}
459
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);
476
}
477
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.
483
*/
484
485
static bool
486
nv30_transfer_m2mf(XFER_ARGS)
487
{
488
if (!src->pitch || !dst->pitch)
489
return false;
490
if (nv30_transfer_scaled(src, dst))
491
return false;
492
return true;
493
}
494
495
static void
496
nv30_transfer_rect_m2mf(XFER_ARGS)
497
{
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 },
502
};
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;
508
509
src_offset += (src->y0 * src->pitch) + (src->x0 * src->cpp);
510
dst_offset += (dst->y0 * dst->pitch) + (dst->x0 * dst->cpp);
511
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);
515
516
while (h) {
517
unsigned lines = (h > 2047) ? 2047 : h;
518
519
if (nouveau_pushbuf_space(push, 32, 2, 0) ||
520
nouveau_pushbuf_refn (push, refs, 2))
521
return;
522
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);
537
538
h -= lines;
539
src_offset += src->pitch * lines;
540
dst_offset += dst->pitch * lines;
541
}
542
}
543
544
static bool
545
nv30_transfer_cpu(XFER_ARGS)
546
{
547
if (nv30_transfer_scaled(src, dst))
548
return false;
549
return true;
550
}
551
552
static char *
553
linear_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
554
{
555
return base + (y * rect->pitch) + (x * rect->cpp);
556
}
557
558
static inline unsigned
559
swizzle2d(unsigned v, unsigned s)
560
{
561
v = (v | (v << 8)) & 0x00ff00ff;
562
v = (v | (v << 4)) & 0x0f0f0f0f;
563
v = (v | (v << 2)) & 0x33333333;
564
v = (v | (v << 1)) & 0x55555555;
565
return v << s;
566
}
567
568
static char *
569
swizzle2d_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
570
{
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;
576
unsigned m;
577
578
m = swizzle2d(x & km, 0);
579
m |= swizzle2d(y & km, 1);
580
m += ((ty * nx) + tx) << k << k;
581
582
return base + (m * rect->cpp);
583
}
584
585
static char *
586
swizzle3d_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
587
{
588
unsigned w = rect->w >> 1;
589
unsigned h = rect->h >> 1;
590
unsigned d = rect->d >> 1;
591
unsigned i = 0, o;
592
unsigned v = 0;
593
594
do {
595
o = i;
596
if (w) {
597
v |= (x & 1) << i++;
598
x >>= 1;
599
w >>= 1;
600
}
601
if (h) {
602
v |= (y & 1) << i++;
603
y >>= 1;
604
h >>= 1;
605
}
606
if (d) {
607
v |= (z & 1) << i++;
608
z >>= 1;
609
d >>= 1;
610
}
611
} while(o != i);
612
613
return base + (v * rect->cpp);
614
}
615
616
typedef char *(*get_ptr_t)(struct nv30_rect *, char *, int, int, int);
617
618
static inline get_ptr_t
619
get_ptr(struct nv30_rect *rect)
620
{
621
if (rect->pitch)
622
return linear_ptr;
623
624
if (rect->d <= 1)
625
return swizzle2d_ptr;
626
627
return swizzle3d_ptr;
628
}
629
630
static void
631
nv30_transfer_rect_cpu(XFER_ARGS)
632
{
633
get_ptr_t sp = get_ptr(src);
634
get_ptr_t dp = get_ptr(dst);
635
char *srcmap, *dstmap;
636
int x, y;
637
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;
642
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);
647
}
648
}
649
}
650
651
void
652
nv30_transfer_rect(struct nv30_context *nv30, enum nv30_transfer_filter filter,
653
struct nv30_rect *src, struct nv30_rect *dst)
654
{
655
static const struct {
656
char *name;
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 },
664
{}
665
};
666
667
for (method = methods; method->possible; method++) {
668
if (method->possible(nv30, filter, src, dst)) {
669
method->execute(nv30, filter, src, dst);
670
return;
671
}
672
}
673
674
assert(0);
675
}
676
677
void
678
nv30_transfer_push_data(struct nouveau_context *nv,
679
struct nouveau_bo *bo, unsigned offset, unsigned domain,
680
unsigned size, void *data)
681
{
682
/* use ifc, or scratch + copy_data? */
683
fprintf(stderr, "nv30: push_data not implemented\n");
684
}
685
686
void
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,
690
unsigned size)
691
{
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 },
696
};
697
struct nouveau_pushbuf *push = nv->pushbuf;
698
unsigned pages, lines;
699
700
pages = size >> 12;
701
size -= (pages << 12);
702
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);
706
707
while (pages) {
708
lines = (pages > 2047) ? 2047 : pages;
709
pages -= lines;
710
711
if (nouveau_pushbuf_space(push, 32, 2, 0) ||
712
nouveau_pushbuf_refn (push, refs, 2))
713
return;
714
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);
729
730
s_off += (lines << 12);
731
d_off += (lines << 12);
732
}
733
734
if (size) {
735
if (nouveau_pushbuf_space(push, 32, 2, 0) ||
736
nouveau_pushbuf_refn (push, refs, 2))
737
return;
738
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);
745
PUSH_DATA (push, 1);
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);
753
}
754
}
755
756