dbd4fa3b7942dbca6ae3e320e5af76cd7980fda2
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_surface.c
1 /*
2 * Copyright 2008 Ben Skeggs
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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include <stdint.h>
24
25 #include "pipe/p_defines.h"
26
27 #include "util/u_inlines.h"
28 #include "util/u_pack_color.h"
29 #include "util/u_format.h"
30 #include "util/u_surface.h"
31
32 #include "os/os_thread.h"
33
34 #include "nvc0_context.h"
35 #include "nvc0_resource.h"
36
37 #include "nv50/nv50_defs.xml.h"
38 #include "nv50/nv50_texture.xml.h"
39 #include "nv50/nv50_blit.h"
40
41 #define NVC0_ENG2D_SUPPORTED_FORMATS 0xff9ccfe1cce3ccc9ULL
42
43 /* return TRUE for formats that can be converted among each other by NVC0_2D */
44 static INLINE boolean
45 nvc0_2d_format_faithful(enum pipe_format format)
46 {
47 uint8_t id = nvc0_format_table[format].rt;
48
49 return (id >= 0xc0) && (NVC0_ENG2D_SUPPORTED_FORMATS & (1ULL << (id - 0xc0)));
50 }
51
52 static INLINE uint8_t
53 nvc0_2d_format(enum pipe_format format)
54 {
55 uint8_t id = nvc0_format_table[format].rt;
56
57 /* Hardware values for color formats range from 0xc0 to 0xff,
58 * but the 2D engine doesn't support all of them.
59 */
60 if (nvc0_2d_format_faithful(format))
61 return id;
62
63 switch (util_format_get_blocksize(format)) {
64 case 1:
65 return NV50_SURFACE_FORMAT_R8_UNORM;
66 case 2:
67 return NV50_SURFACE_FORMAT_R16_UNORM;
68 case 4:
69 return NV50_SURFACE_FORMAT_BGRA8_UNORM;
70 case 8:
71 return NV50_SURFACE_FORMAT_RGBA16_UNORM;
72 case 16:
73 return NV50_SURFACE_FORMAT_RGBA32_FLOAT;
74 default:
75 return 0;
76 }
77 }
78
79 static int
80 nvc0_2d_texture_set(struct nouveau_pushbuf *push, boolean dst,
81 struct nv50_miptree *mt, unsigned level, unsigned layer,
82 enum pipe_format pformat)
83 {
84 struct nouveau_bo *bo = mt->base.bo;
85 uint32_t width, height, depth;
86 uint32_t format;
87 uint32_t mthd = dst ? NVC0_2D_DST_FORMAT : NVC0_2D_SRC_FORMAT;
88 uint32_t offset = mt->level[level].offset;
89
90 format = nvc0_2d_format(pformat);
91 if (!format) {
92 NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
93 util_format_name(pformat));
94 return 1;
95 }
96
97 width = u_minify(mt->base.base.width0, level) << mt->ms_x;
98 height = u_minify(mt->base.base.height0, level) << mt->ms_y;
99 depth = u_minify(mt->base.base.depth0, level);
100
101 /* layer has to be < depth, and depth > tile depth / 2 */
102
103 if (!mt->layout_3d) {
104 offset += mt->layer_stride * layer;
105 layer = 0;
106 depth = 1;
107 } else
108 if (!dst) {
109 offset += nvc0_mt_zslice_offset(mt, level, layer);
110 layer = 0;
111 }
112
113 if (!nouveau_bo_memtype(bo)) {
114 BEGIN_NVC0(push, SUBC_2D(mthd), 2);
115 PUSH_DATA (push, format);
116 PUSH_DATA (push, 1);
117 BEGIN_NVC0(push, SUBC_2D(mthd + 0x14), 5);
118 PUSH_DATA (push, mt->level[level].pitch);
119 PUSH_DATA (push, width);
120 PUSH_DATA (push, height);
121 PUSH_DATAh(push, bo->offset + offset);
122 PUSH_DATA (push, bo->offset + offset);
123 } else {
124 BEGIN_NVC0(push, SUBC_2D(mthd), 5);
125 PUSH_DATA (push, format);
126 PUSH_DATA (push, 0);
127 PUSH_DATA (push, mt->level[level].tile_mode);
128 PUSH_DATA (push, depth);
129 PUSH_DATA (push, layer);
130 BEGIN_NVC0(push, SUBC_2D(mthd + 0x18), 4);
131 PUSH_DATA (push, width);
132 PUSH_DATA (push, height);
133 PUSH_DATAh(push, bo->offset + offset);
134 PUSH_DATA (push, bo->offset + offset);
135 }
136
137 #if 0
138 if (dst) {
139 BEGIN_NVC0(push, SUBC_2D(NVC0_2D_CLIP_X), 4);
140 PUSH_DATA (push, 0);
141 PUSH_DATA (push, 0);
142 PUSH_DATA (push, width);
143 PUSH_DATA (push, height);
144 }
145 #endif
146 return 0;
147 }
148
149 static int
150 nvc0_2d_texture_do_copy(struct nouveau_pushbuf *push,
151 struct nv50_miptree *dst, unsigned dst_level,
152 unsigned dx, unsigned dy, unsigned dz,
153 struct nv50_miptree *src, unsigned src_level,
154 unsigned sx, unsigned sy, unsigned sz,
155 unsigned w, unsigned h)
156 {
157 const enum pipe_format dfmt = dst->base.base.format;
158 const enum pipe_format sfmt = src->base.base.format;
159 int ret;
160
161 ret = PUSH_SPACE(push, 2 * 16 + 32);
162 if (ret)
163 return ret;
164
165 ret = nvc0_2d_texture_set(push, TRUE, dst, dst_level, dz, dfmt);
166 if (ret)
167 return ret;
168
169 ret = nvc0_2d_texture_set(push, FALSE, src, src_level, sz, sfmt);
170 if (ret)
171 return ret;
172
173 IMMED_NVC0(push, NVC0_2D(BLIT_CONTROL), 0x00);
174 BEGIN_NVC0(push, NVC0_2D(BLIT_DST_X), 4);
175 PUSH_DATA (push, dx << dst->ms_x);
176 PUSH_DATA (push, dy << dst->ms_y);
177 PUSH_DATA (push, w << dst->ms_x);
178 PUSH_DATA (push, h << dst->ms_y);
179 BEGIN_NVC0(push, NVC0_2D(BLIT_DU_DX_FRACT), 4);
180 PUSH_DATA (push, 0);
181 PUSH_DATA (push, 1);
182 PUSH_DATA (push, 0);
183 PUSH_DATA (push, 1);
184 BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_X_FRACT), 4);
185 PUSH_DATA (push, 0);
186 PUSH_DATA (push, sx << src->ms_x);
187 PUSH_DATA (push, 0);
188 PUSH_DATA (push, sy << src->ms_x);
189
190 return 0;
191 }
192
193 static void
194 nvc0_resource_copy_region(struct pipe_context *pipe,
195 struct pipe_resource *dst, unsigned dst_level,
196 unsigned dstx, unsigned dsty, unsigned dstz,
197 struct pipe_resource *src, unsigned src_level,
198 const struct pipe_box *src_box)
199 {
200 struct nvc0_context *nvc0 = nvc0_context(pipe);
201 int ret;
202 boolean m2mf;
203 unsigned dst_layer = dstz, src_layer = src_box->z;
204
205 /* Fallback for buffers. */
206 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
207 util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
208 src, src_level, src_box);
209 return;
210 }
211
212 /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */
213 assert((src->nr_samples | 1) == (dst->nr_samples | 1));
214
215 m2mf = (src->format == dst->format) ||
216 (util_format_get_blocksizebits(src->format) ==
217 util_format_get_blocksizebits(dst->format));
218
219 nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
220
221 if (m2mf) {
222 struct nv50_m2mf_rect drect, srect;
223 unsigned i;
224 unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
225 unsigned ny = util_format_get_nblocksy(src->format, src_box->height);
226
227 nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
228 nv50_m2mf_rect_setup(&srect, src, src_level,
229 src_box->x, src_box->y, src_box->z);
230
231 for (i = 0; i < src_box->depth; ++i) {
232 nvc0->m2mf_copy_rect(nvc0, &drect, &srect, nx, ny);
233
234 if (nv50_miptree(dst)->layout_3d)
235 drect.z++;
236 else
237 drect.base += nv50_miptree(dst)->layer_stride;
238
239 if (nv50_miptree(src)->layout_3d)
240 srect.z++;
241 else
242 srect.base += nv50_miptree(src)->layer_stride;
243 }
244 return;
245 }
246
247 assert(nvc0_2d_format_faithful(src->format));
248 assert(nvc0_2d_format_faithful(dst->format));
249
250 BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(src), RD);
251 BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(dst), WR);
252 nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
253 nouveau_pushbuf_validate(nvc0->base.pushbuf);
254
255 for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
256 ret = nvc0_2d_texture_do_copy(nvc0->base.pushbuf,
257 nv50_miptree(dst), dst_level,
258 dstx, dsty, dst_layer,
259 nv50_miptree(src), src_level,
260 src_box->x, src_box->y, src_layer,
261 src_box->width, src_box->height);
262 if (ret)
263 break;
264 }
265 nouveau_bufctx_reset(nvc0->bufctx, 0);
266 }
267
268 static void
269 nvc0_clear_render_target(struct pipe_context *pipe,
270 struct pipe_surface *dst,
271 const union pipe_color_union *color,
272 unsigned dstx, unsigned dsty,
273 unsigned width, unsigned height)
274 {
275 struct nvc0_context *nvc0 = nvc0_context(pipe);
276 struct nouveau_pushbuf *push = nvc0->base.pushbuf;
277 struct nv50_surface *sf = nv50_surface(dst);
278 struct nv04_resource *res = nv04_resource(sf->base.texture);
279 unsigned z;
280
281 BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);
282 PUSH_DATAf(push, color->f[0]);
283 PUSH_DATAf(push, color->f[1]);
284 PUSH_DATAf(push, color->f[2]);
285 PUSH_DATAf(push, color->f[3]);
286
287 BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
288 PUSH_DATA (push, ( width << 16) | dstx);
289 PUSH_DATA (push, (height << 16) | dsty);
290
291 BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1);
292 PUSH_DATA (push, 1);
293 BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9);
294 PUSH_DATAh(push, res->address + sf->offset);
295 PUSH_DATA (push, res->address + sf->offset);
296 if (likely(nouveau_bo_memtype(res->bo))) {
297 struct nv50_miptree *mt = nv50_miptree(dst->texture);
298
299 PUSH_DATA(push, sf->width);
300 PUSH_DATA(push, sf->height);
301 PUSH_DATA(push, nvc0_format_table[dst->format].rt);
302 PUSH_DATA(push, (mt->layout_3d << 16) |
303 mt->level[sf->base.u.tex.level].tile_mode);
304 PUSH_DATA(push, dst->u.tex.first_layer + sf->depth);
305 PUSH_DATA(push, mt->layer_stride >> 2);
306 PUSH_DATA(push, dst->u.tex.first_layer);
307 } else {
308 if (res->base.target == PIPE_BUFFER) {
309 PUSH_DATA(push, 262144);
310 PUSH_DATA(push, 1);
311 } else {
312 PUSH_DATA(push, nv50_miptree(&res->base)->level[0].pitch);
313 PUSH_DATA(push, sf->height);
314 }
315 PUSH_DATA(push, nvc0_format_table[sf->base.format].rt);
316 PUSH_DATA(push, 1 << 12);
317 PUSH_DATA(push, 1);
318 PUSH_DATA(push, 0);
319 PUSH_DATA(push, 0);
320
321 IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0);
322
323 /* tiled textures don't have to be fenced, they're not mapped directly */
324 nvc0_resource_fence(res, NOUVEAU_BO_WR);
325 }
326
327 for (z = 0; z < sf->depth; ++z) {
328 BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
329 PUSH_DATA (push, 0x3c |
330 (z << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT));
331 }
332
333 nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
334 }
335
336 static void
337 nvc0_clear_depth_stencil(struct pipe_context *pipe,
338 struct pipe_surface *dst,
339 unsigned clear_flags,
340 double depth,
341 unsigned stencil,
342 unsigned dstx, unsigned dsty,
343 unsigned width, unsigned height)
344 {
345 struct nvc0_context *nvc0 = nvc0_context(pipe);
346 struct nouveau_pushbuf *push = nvc0->base.pushbuf;
347 struct nv50_miptree *mt = nv50_miptree(dst->texture);
348 struct nv50_surface *sf = nv50_surface(dst);
349 uint32_t mode = 0;
350 int unk = mt->base.base.target == PIPE_TEXTURE_2D;
351 unsigned z;
352
353 if (clear_flags & PIPE_CLEAR_DEPTH) {
354 BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1);
355 PUSH_DATAf(push, depth);
356 mode |= NVC0_3D_CLEAR_BUFFERS_Z;
357 }
358
359 if (clear_flags & PIPE_CLEAR_STENCIL) {
360 BEGIN_NVC0(push, NVC0_3D(CLEAR_STENCIL), 1);
361 PUSH_DATA (push, stencil & 0xff);
362 mode |= NVC0_3D_CLEAR_BUFFERS_S;
363 }
364
365 BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
366 PUSH_DATA (push, ( width << 16) | dstx);
367 PUSH_DATA (push, (height << 16) | dsty);
368
369 BEGIN_NVC0(push, NVC0_3D(ZETA_ADDRESS_HIGH), 5);
370 PUSH_DATAh(push, mt->base.address + sf->offset);
371 PUSH_DATA (push, mt->base.address + sf->offset);
372 PUSH_DATA (push, nvc0_format_table[dst->format].rt);
373 PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
374 PUSH_DATA (push, mt->layer_stride >> 2);
375 BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1);
376 PUSH_DATA (push, 1);
377 BEGIN_NVC0(push, NVC0_3D(ZETA_HORIZ), 3);
378 PUSH_DATA (push, sf->width);
379 PUSH_DATA (push, sf->height);
380 PUSH_DATA (push, (unk << 16) | (dst->u.tex.first_layer + sf->depth));
381 BEGIN_NVC0(push, NVC0_3D(ZETA_BASE_LAYER), 1);
382 PUSH_DATA (push, dst->u.tex.first_layer);
383
384 for (z = 0; z < sf->depth; ++z) {
385 BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
386 PUSH_DATA (push, mode |
387 (z << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT));
388 }
389
390 nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
391 }
392
393 void
394 nvc0_clear(struct pipe_context *pipe, unsigned buffers,
395 const union pipe_color_union *color,
396 double depth, unsigned stencil)
397 {
398 struct nvc0_context *nvc0 = nvc0_context(pipe);
399 struct nouveau_pushbuf *push = nvc0->base.pushbuf;
400 struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
401 unsigned i;
402 uint32_t mode = 0;
403
404 /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
405 if (!nvc0_state_validate(nvc0, NVC0_NEW_FRAMEBUFFER, 9 + (fb->nr_cbufs * 2)))
406 return;
407
408 if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
409 BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);
410 PUSH_DATAf(push, color->f[0]);
411 PUSH_DATAf(push, color->f[1]);
412 PUSH_DATAf(push, color->f[2]);
413 PUSH_DATAf(push, color->f[3]);
414 mode =
415 NVC0_3D_CLEAR_BUFFERS_R | NVC0_3D_CLEAR_BUFFERS_G |
416 NVC0_3D_CLEAR_BUFFERS_B | NVC0_3D_CLEAR_BUFFERS_A;
417 }
418
419 if (buffers & PIPE_CLEAR_DEPTH) {
420 BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1);
421 PUSH_DATA (push, fui(depth));
422 mode |= NVC0_3D_CLEAR_BUFFERS_Z;
423 }
424
425 if (buffers & PIPE_CLEAR_STENCIL) {
426 BEGIN_NVC0(push, NVC0_3D(CLEAR_STENCIL), 1);
427 PUSH_DATA (push, stencil & 0xff);
428 mode |= NVC0_3D_CLEAR_BUFFERS_S;
429 }
430
431 BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
432 PUSH_DATA (push, mode);
433
434 for (i = 1; i < fb->nr_cbufs; i++) {
435 BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
436 PUSH_DATA (push, (i << 6) | 0x3c);
437 }
438 }
439
440
441 /* =============================== BLIT CODE ===================================
442 */
443
444 struct nvc0_blitter
445 {
446 struct nvc0_program *fp[NV50_BLIT_MAX_TEXTURE_TYPES][NV50_BLIT_MODES];
447 struct nvc0_program vp;
448
449 struct nv50_tsc_entry sampler[2]; /* nearest, bilinear */
450
451 pipe_mutex mutex;
452
453 struct nvc0_screen *screen;
454 };
455
456 struct nvc0_blitctx
457 {
458 struct nvc0_context *nvc0;
459 struct nvc0_program *fp;
460 uint8_t mode;
461 uint16_t color_mask;
462 uint8_t filter;
463 enum pipe_texture_target target;
464 struct {
465 struct pipe_framebuffer_state fb;
466 struct nvc0_program *vp;
467 struct nvc0_program *tcp;
468 struct nvc0_program *tep;
469 struct nvc0_program *gp;
470 struct nvc0_program *fp;
471 unsigned num_textures[5];
472 unsigned num_samplers[5];
473 struct pipe_sampler_view *texture[2];
474 struct nv50_tsc_entry *sampler[2];
475 uint32_t dirty;
476 } saved;
477 };
478
479 static void
480 nvc0_blitter_make_vp(struct nvc0_blitter *blit)
481 {
482 static const uint32_t code_nvc0[] =
483 {
484 0xfff01c66, 0x06000080, /* vfetch b128 { $r0 $r1 $r2 $r3 } a[0x80] */
485 0xfff11c26, 0x06000090, /* vfetch b96 { $r4 $r5 $r6 } a[0x90]*/
486 0x03f01c66, 0x0a7e0070, /* export b128 o[0x70] { $r0 $r1 $r2 $r3 } */
487 0x13f01c26, 0x0a7e0080, /* export b96 o[0x80] { $r4 $r5 $r6 } */
488 0x00001de7, 0x80000000, /* exit */
489 };
490 static const uint32_t code_nve4[] =
491 {
492 0x00000007, 0x20000000, /* sched */
493 0xfff01c66, 0x06000080, /* vfetch b128 { $r0 $r1 $r2 $r3 } a[0x80] */
494 0xfff11c46, 0x06000090, /* vfetch b96 { $r4 $r5 $r6 } a[0x90]*/
495 0x03f01c66, 0x0a7e0070, /* export b128 o[0x70] { $r0 $r1 $r2 $r3 } */
496 0x13f01c46, 0x0a7e0080, /* export b96 o[0x80] { $r4 $r5 $r6 } */
497 0x00001de7, 0x80000000, /* exit */
498 };
499
500 blit->vp.type = PIPE_SHADER_VERTEX;
501 blit->vp.translated = TRUE;
502 if (blit->screen->base.class_3d >= NVE4_3D_CLASS) {
503 blit->vp.code = (uint32_t *)code_nve4; /* const_cast */
504 blit->vp.code_size = sizeof(code_nve4);
505 } else {
506 blit->vp.code = (uint32_t *)code_nvc0; /* const_cast */
507 blit->vp.code_size = sizeof(code_nvc0);
508 }
509 blit->vp.max_gpr = 7;
510 blit->vp.vp.edgeflag = PIPE_MAX_ATTRIBS;
511
512 blit->vp.hdr[0] = 0x00020461; /* vertprog magic */
513 blit->vp.hdr[4] = 0x000ff000; /* no outputs read */
514 blit->vp.hdr[6] = 0x0000003f; /* a[0x80], a[0x90] */
515 blit->vp.hdr[13] = 0x0003f000; /* o[0x70], o[0x80] */
516 }
517
518 static void
519 nvc0_blitter_make_sampler(struct nvc0_blitter *blit)
520 {
521 /* clamp to edge, min/max lod = 0, nearest filtering */
522
523 blit->sampler[0].id = -1;
524
525 blit->sampler[0].tsc[0] = NV50_TSC_0_SRGB_CONVERSION_ALLOWED |
526 (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPS__SHIFT) |
527 (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPT__SHIFT) |
528 (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPR__SHIFT);
529 blit->sampler[0].tsc[1] =
530 NV50_TSC_1_MAGF_NEAREST | NV50_TSC_1_MINF_NEAREST | NV50_TSC_1_MIPF_NONE;
531
532 /* clamp to edge, min/max lod = 0, bilinear filtering */
533
534 blit->sampler[1].id = -1;
535
536 blit->sampler[1].tsc[0] = blit->sampler[0].tsc[0];
537 blit->sampler[1].tsc[1] =
538 NV50_TSC_1_MAGF_LINEAR | NV50_TSC_1_MINF_LINEAR | NV50_TSC_1_MIPF_NONE;
539 }
540
541 static void
542 nvc0_blit_select_fp(struct nvc0_blitctx *ctx, const struct pipe_blit_info *info)
543 {
544 struct nvc0_blitter *blitter = ctx->nvc0->screen->blitter;
545
546 const enum pipe_texture_target ptarg =
547 nv50_blit_reinterpret_pipe_texture_target(info->dst.resource->target);
548
549 const unsigned targ = nv50_blit_texture_type(ptarg);
550 const unsigned mode = ctx->mode;
551
552 if (!blitter->fp[targ][mode]) {
553 pipe_mutex_lock(blitter->mutex);
554 if (!blitter->fp[targ][mode])
555 blitter->fp[targ][mode] =
556 nv50_blitter_make_fp(&ctx->nvc0->base.pipe, mode, targ);
557 pipe_mutex_unlock(blitter->mutex);
558 }
559 ctx->fp = blitter->fp[targ][mode];
560 }
561
562 static void
563 nvc0_blit_set_dst(struct nvc0_blitctx *ctx,
564 struct pipe_resource *res, unsigned level, unsigned layer,
565 enum pipe_format format)
566 {
567 struct nvc0_context *nvc0 = ctx->nvc0;
568 struct pipe_context *pipe = &nvc0->base.pipe;
569 struct pipe_surface templ;
570
571 if (util_format_is_depth_or_stencil(format))
572 templ.format = nv50_blit_zeta_to_colour_format(format);
573 else
574 templ.format = format;
575
576 templ.usage = PIPE_USAGE_STREAM;
577 templ.u.tex.level = level;
578 templ.u.tex.first_layer = templ.u.tex.last_layer = layer;
579
580 if (layer == -1) {
581 templ.u.tex.first_layer = 0;
582 templ.u.tex.last_layer =
583 (res->target == PIPE_TEXTURE_3D ? res->depth0 : res->array_size) - 1;
584 }
585
586 nvc0->framebuffer.cbufs[0] = nvc0_miptree_surface_new(pipe, res, &templ);
587 nvc0->framebuffer.nr_cbufs = 1;
588 nvc0->framebuffer.zsbuf = NULL;
589 nvc0->framebuffer.width = nvc0->framebuffer.cbufs[0]->width;
590 nvc0->framebuffer.height = nvc0->framebuffer.cbufs[0]->height;
591 }
592
593 static void
594 nvc0_blit_set_src(struct nvc0_blitctx *ctx,
595 struct pipe_resource *res, unsigned level, unsigned layer,
596 enum pipe_format format, const uint8_t filter)
597 {
598 struct nvc0_context *nvc0 = ctx->nvc0;
599 struct pipe_context *pipe = &nvc0->base.pipe;
600 struct pipe_sampler_view templ;
601 uint32_t flags;
602 unsigned s;
603 enum pipe_texture_target target;
604
605 target = nv50_blit_reinterpret_pipe_texture_target(res->target);
606
607 templ.format = format;
608 templ.u.tex.first_layer = templ.u.tex.last_layer = layer;
609 templ.u.tex.first_level = templ.u.tex.last_level = level;
610 templ.swizzle_r = PIPE_SWIZZLE_RED;
611 templ.swizzle_g = PIPE_SWIZZLE_GREEN;
612 templ.swizzle_b = PIPE_SWIZZLE_BLUE;
613 templ.swizzle_a = PIPE_SWIZZLE_ALPHA;
614
615 if (layer == -1) {
616 templ.u.tex.first_layer = 0;
617 templ.u.tex.last_layer =
618 (res->target == PIPE_TEXTURE_3D ? res->depth0 : res->array_size) - 1;
619 }
620
621 flags = res->last_level ? 0 : NV50_TEXVIEW_SCALED_COORDS;
622 if (filter && res->nr_samples == 8)
623 flags |= NV50_TEXVIEW_FILTER_MSAA8;
624
625 nvc0->textures[4][0] = nvc0_create_texture_view(
626 pipe, res, &templ, flags, target);
627 nvc0->textures[4][1] = NULL;
628
629 for (s = 0; s <= 3; ++s)
630 nvc0->num_textures[s] = 0;
631 nvc0->num_textures[4] = 1;
632
633 templ.format = nv50_zs_to_s_format(format);
634 if (templ.format != format) {
635 nvc0->textures[4][1] = nvc0_create_texture_view(
636 pipe, res, &templ, flags, target);
637 nvc0->num_textures[4] = 2;
638 }
639 }
640
641 static void
642 nvc0_blitctx_prepare_state(struct nvc0_blitctx *blit)
643 {
644 struct nouveau_pushbuf *push = blit->nvc0->base.pushbuf;
645
646 /* TODO: maybe make this a MACRO (if we need more logic) ? */
647
648 if (blit->nvc0->cond_query)
649 IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS);
650
651 /* blend state */
652 BEGIN_NVC0(push, NVC0_3D(COLOR_MASK(0)), 1);
653 PUSH_DATA (push, blit->color_mask);
654 IMMED_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 0);
655 IMMED_NVC0(push, NVC0_3D(LOGIC_OP_ENABLE), 0);
656
657 /* rasterizer state */
658 IMMED_NVC0(push, NVC0_3D(FRAG_COLOR_CLAMP_EN), 0);
659 IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_ENABLE), 0);
660 BEGIN_NVC0(push, NVC0_3D(MSAA_MASK(0)), 4);
661 PUSH_DATA (push, 0xffff);
662 PUSH_DATA (push, 0xffff);
663 PUSH_DATA (push, 0xffff);
664 PUSH_DATA (push, 0xffff);
665 BEGIN_NVC0(push, NVC0_3D(MACRO_POLYGON_MODE_FRONT), 1);
666 PUSH_DATA (push, NVC0_3D_MACRO_POLYGON_MODE_FRONT_FILL);
667 BEGIN_NVC0(push, NVC0_3D(MACRO_POLYGON_MODE_BACK), 1);
668 PUSH_DATA (push, NVC0_3D_MACRO_POLYGON_MODE_BACK_FILL);
669 IMMED_NVC0(push, NVC0_3D(POLYGON_SMOOTH_ENABLE), 0);
670 IMMED_NVC0(push, NVC0_3D(POLYGON_OFFSET_FILL_ENABLE), 0);
671 IMMED_NVC0(push, NVC0_3D(POLYGON_STIPPLE_ENABLE), 0);
672 IMMED_NVC0(push, NVC0_3D(CULL_FACE_ENABLE), 0);
673
674 /* zsa state */
675 IMMED_NVC0(push, NVC0_3D(DEPTH_TEST_ENABLE), 0);
676 IMMED_NVC0(push, NVC0_3D(STENCIL_ENABLE), 0);
677 IMMED_NVC0(push, NVC0_3D(ALPHA_TEST_ENABLE), 0);
678
679 /* disable transform feedback */
680 IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), 0);
681 }
682
683 static void
684 nvc0_blitctx_pre_blit(struct nvc0_blitctx *ctx)
685 {
686 struct nvc0_context *nvc0 = ctx->nvc0;
687 struct nvc0_blitter *blitter = nvc0->screen->blitter;
688 int s;
689
690 ctx->saved.fb.width = nvc0->framebuffer.width;
691 ctx->saved.fb.height = nvc0->framebuffer.height;
692 ctx->saved.fb.nr_cbufs = nvc0->framebuffer.nr_cbufs;
693 ctx->saved.fb.cbufs[0] = nvc0->framebuffer.cbufs[0];
694 ctx->saved.fb.zsbuf = nvc0->framebuffer.zsbuf;
695
696 ctx->saved.vp = nvc0->vertprog;
697 ctx->saved.tcp = nvc0->tctlprog;
698 ctx->saved.tep = nvc0->tevlprog;
699 ctx->saved.gp = nvc0->gmtyprog;
700 ctx->saved.fp = nvc0->fragprog;
701
702 nvc0->vertprog = &blitter->vp;
703 nvc0->tctlprog = NULL;
704 nvc0->tevlprog = NULL;
705 nvc0->gmtyprog = NULL;
706 nvc0->fragprog = ctx->fp;
707
708 for (s = 0; s <= 4; ++s) {
709 ctx->saved.num_textures[s] = nvc0->num_textures[s];
710 ctx->saved.num_samplers[s] = nvc0->num_samplers[s];
711 nvc0->textures_dirty[s] = (1 << nvc0->num_textures[s]) - 1;
712 nvc0->samplers_dirty[s] = (1 << nvc0->num_samplers[s]) - 1;
713 }
714 ctx->saved.texture[0] = nvc0->textures[4][0];
715 ctx->saved.texture[1] = nvc0->textures[4][1];
716 ctx->saved.sampler[0] = nvc0->samplers[4][0];
717 ctx->saved.sampler[1] = nvc0->samplers[4][1];
718
719 nvc0->samplers[4][0] = &blitter->sampler[ctx->filter];
720 nvc0->samplers[4][1] = &blitter->sampler[ctx->filter];
721
722 for (s = 0; s <= 3; ++s)
723 nvc0->num_samplers[s] = 0;
724 nvc0->num_samplers[4] = 2;
725
726 ctx->saved.dirty = nvc0->dirty;
727
728 nvc0->textures_dirty[4] |= 3;
729 nvc0->samplers_dirty[4] |= 3;
730
731 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB);
732 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(4, 0));
733 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(4, 1));
734
735 nvc0->dirty = NVC0_NEW_FRAMEBUFFER |
736 NVC0_NEW_VERTPROG | NVC0_NEW_FRAGPROG |
737 NVC0_NEW_TCTLPROG | NVC0_NEW_TEVLPROG | NVC0_NEW_GMTYPROG |
738 NVC0_NEW_TEXTURES | NVC0_NEW_SAMPLERS;
739 }
740
741 static void
742 nvc0_blitctx_post_blit(struct nvc0_blitctx *blit)
743 {
744 struct nvc0_context *nvc0 = blit->nvc0;
745 int s;
746
747 pipe_surface_reference(&nvc0->framebuffer.cbufs[0], NULL);
748
749 nvc0->framebuffer.width = blit->saved.fb.width;
750 nvc0->framebuffer.height = blit->saved.fb.height;
751 nvc0->framebuffer.nr_cbufs = blit->saved.fb.nr_cbufs;
752 nvc0->framebuffer.cbufs[0] = blit->saved.fb.cbufs[0];
753 nvc0->framebuffer.zsbuf = blit->saved.fb.zsbuf;
754
755 nvc0->vertprog = blit->saved.vp;
756 nvc0->tctlprog = blit->saved.tcp;
757 nvc0->tevlprog = blit->saved.tep;
758 nvc0->gmtyprog = blit->saved.gp;
759 nvc0->fragprog = blit->saved.fp;
760
761 pipe_sampler_view_reference(&nvc0->textures[4][0], NULL);
762 pipe_sampler_view_reference(&nvc0->textures[4][1], NULL);
763
764 for (s = 0; s <= 4; ++s) {
765 nvc0->num_textures[s] = blit->saved.num_textures[s];
766 nvc0->num_samplers[s] = blit->saved.num_samplers[s];
767 nvc0->textures_dirty[s] = (1 << nvc0->num_textures[s]) - 1;
768 nvc0->samplers_dirty[s] = (1 << nvc0->num_samplers[s]) - 1;
769 }
770 nvc0->textures[4][0] = blit->saved.texture[0];
771 nvc0->textures[4][1] = blit->saved.texture[1];
772 nvc0->samplers[4][0] = blit->saved.sampler[0];
773 nvc0->samplers[4][1] = blit->saved.sampler[1];
774
775 nvc0->textures_dirty[4] |= 3;
776 nvc0->samplers_dirty[4] |= 3;
777
778 if (nvc0->cond_query)
779 nvc0->base.pipe.render_condition(&nvc0->base.pipe, nvc0->cond_query,
780 nvc0->cond_mode);
781
782 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB);
783 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(4, 0));
784 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_TEX(4, 1));
785
786 nvc0->dirty = blit->saved.dirty |
787 (NVC0_NEW_FRAMEBUFFER | NVC0_NEW_SCISSOR | NVC0_NEW_SAMPLE_MASK |
788 NVC0_NEW_RASTERIZER | NVC0_NEW_ZSA | NVC0_NEW_BLEND |
789 NVC0_NEW_TEXTURES | NVC0_NEW_SAMPLERS |
790 NVC0_NEW_VERTPROG | NVC0_NEW_FRAGPROG |
791 NVC0_NEW_TCTLPROG | NVC0_NEW_TEVLPROG | NVC0_NEW_GMTYPROG |
792 NVC0_NEW_TFB_TARGETS);
793 }
794
795 static void
796 nvc0_blit_3d(struct nvc0_context *nvc0, const struct pipe_blit_info *info)
797 {
798 struct nvc0_blitctx *blit = nvc0->blit;
799 struct nouveau_pushbuf *push = nvc0->base.pushbuf;
800 struct pipe_resource *src = info->src.resource;
801 struct pipe_resource *dst = info->dst.resource;
802 int32_t minx, maxx, miny, maxy;
803 int32_t i;
804 float x0, x1, y0, y1, z;
805 float dz;
806 float x_range, y_range;
807
808 blit->mode = nv50_blit_select_mode(info);
809 blit->color_mask = nv50_blit_derive_color_mask(info);
810 blit->filter = nv50_blit_get_filter(info);
811
812 nvc0_blit_select_fp(blit, info);
813 nvc0_blitctx_pre_blit(blit);
814
815 nvc0_blit_set_dst(blit, dst, info->dst.level, 0, info->dst.format);
816 nvc0_blit_set_src(blit, src, info->src.level, -1, info->src.format,
817 blit->filter);
818
819 nvc0_blitctx_prepare_state(blit);
820
821 nvc0_state_validate(nvc0, ~0, 48);
822
823 x_range = (float)info->src.box.width / (float)info->dst.box.width;
824 y_range = (float)info->src.box.height / (float)info->dst.box.height;
825
826 x0 = (float)info->src.box.x - x_range * (float)info->dst.box.x;
827 y0 = (float)info->src.box.y - y_range * (float)info->dst.box.y;
828
829 x1 = x0 + 16384.0f * x_range;
830 y1 = y0 + 16384.0f * y_range;
831
832 x0 *= (float)(1 << nv50_miptree(src)->ms_x);
833 x1 *= (float)(1 << nv50_miptree(src)->ms_x);
834 y0 *= (float)(1 << nv50_miptree(src)->ms_y);
835 y1 *= (float)(1 << nv50_miptree(src)->ms_y);
836
837 if (src->last_level > 0) {
838 /* If there are mip maps, GPU always assumes normalized coordinates. */
839 const unsigned l = info->src.level;
840 const float fh = u_minify(src->width0 << nv50_miptree(src)->ms_x, l);
841 const float fv = u_minify(src->height0 << nv50_miptree(src)->ms_y, l);
842 x0 /= fh;
843 x1 /= fh;
844 y0 /= fv;
845 y1 /= fv;
846 }
847
848 dz = (float)info->src.box.depth / (float)info->dst.box.depth;
849 z = (float)info->src.box.z;
850 if (nv50_miptree(src)->layout_3d)
851 z += 0.5f * dz;
852
853 IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 0);
854 BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(0)), 2);
855 PUSH_DATA (push, nvc0->framebuffer.width << 16);
856 PUSH_DATA (push, nvc0->framebuffer.height << 16);
857
858 /* Draw a large triangle in screen coordinates covering the whole
859 * render target, with scissors defining the destination region.
860 * The vertex is supplied with non-normalized texture coordinates
861 * arranged in a way to yield the desired offset and scale.
862 */
863
864 minx = info->dst.box.x;
865 maxx = info->dst.box.x + info->dst.box.width;
866 miny = info->dst.box.y;
867 maxy = info->dst.box.y + info->dst.box.height;
868 if (info->scissor_enable) {
869 minx = MAX2(minx, info->scissor.minx);
870 maxx = MIN2(maxx, info->scissor.maxx);
871 miny = MAX2(miny, info->scissor.miny);
872 maxy = MIN2(maxy, info->scissor.maxy);
873 }
874 BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2);
875 PUSH_DATA (push, (maxx << 16) | minx);
876 PUSH_DATA (push, (maxy << 16) | miny);
877
878 for (i = 0; i < info->dst.box.depth; ++i, z += dz) {
879 if (info->dst.box.z + i) {
880 BEGIN_NVC0(push, NVC0_3D(LAYER), 1);
881 PUSH_DATA (push, info->dst.box.z + i);
882 }
883
884 IMMED_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL),
885 NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES);
886
887 BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 4);
888 PUSH_DATA (push, 0x74301);
889 PUSH_DATAf(push, x0);
890 PUSH_DATAf(push, y0);
891 PUSH_DATAf(push, z);
892 BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
893 PUSH_DATA (push, 0x74200);
894 PUSH_DATAf(push, 0.0f);
895 PUSH_DATAf(push, 0.0f);
896 BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 4);
897 PUSH_DATA (push, 0x74301);
898 PUSH_DATAf(push, x1);
899 PUSH_DATAf(push, y0);
900 PUSH_DATAf(push, z);
901 BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
902 PUSH_DATA (push, 0x74200);
903 PUSH_DATAf(push, 16384 << nv50_miptree(dst)->ms_x);
904 PUSH_DATAf(push, 0.0f);
905 BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 4);
906 PUSH_DATA (push, 0x74301);
907 PUSH_DATAf(push, x0);
908 PUSH_DATAf(push, y1);
909 PUSH_DATAf(push, z);
910 BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
911 PUSH_DATA (push, 0x74200);
912 PUSH_DATAf(push, 0.0f);
913 PUSH_DATAf(push, 16384 << nv50_miptree(dst)->ms_y);
914
915 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0);
916 }
917 if (info->dst.box.z + info->dst.box.depth - 1)
918 IMMED_NVC0(push, NVC0_3D(LAYER), 0);
919
920 /* re-enable normally constant state */
921
922 IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 1);
923
924 nvc0_blitctx_post_blit(blit);
925 }
926
927 static void
928 nvc0_blit_eng2d(struct nvc0_context *nvc0, const struct pipe_blit_info *info)
929 {
930 struct nouveau_pushbuf *push = nvc0->base.pushbuf;
931 struct nv50_miptree *dst = nv50_miptree(info->dst.resource);
932 struct nv50_miptree *src = nv50_miptree(info->src.resource);
933 const int32_t srcx_adj = info->src.box.width < 0 ? -1 : 0;
934 const int32_t srcy_adj = info->src.box.height < 0 ? -1 : 0;
935 const int dz = info->dst.box.z;
936 const int sz = info->src.box.z;
937 uint32_t dstw, dsth;
938 int32_t dstx, dsty;
939 int64_t srcx, srcy;
940 int64_t du_dx, dv_dy;
941 int i;
942 uint32_t mode;
943 const uint32_t mask = nv50_blit_eng2d_get_mask(info);
944
945 mode = nv50_blit_get_filter(info) ?
946 NVC0_2D_BLIT_CONTROL_FILTER_BILINEAR :
947 NVC0_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE;
948 mode |= (src->base.base.nr_samples > dst->base.base.nr_samples) ?
949 NVC0_2D_BLIT_CONTROL_ORIGIN_CORNER : NVC0_2D_BLIT_CONTROL_ORIGIN_CENTER;
950
951 du_dx = ((int64_t)info->src.box.width << 32) / info->dst.box.width;
952 dv_dy = ((int64_t)info->src.box.height << 32) / info->dst.box.height;
953
954 nvc0_2d_texture_set(push, 1, dst, info->dst.level, dz, info->dst.format);
955 nvc0_2d_texture_set(push, 0, src, info->src.level, sz, info->src.format);
956
957 if (info->scissor_enable) {
958 BEGIN_NVC0(push, NVC0_2D(CLIP_X), 5);
959 PUSH_DATA (push, info->scissor.minx << dst->ms_x);
960 PUSH_DATA (push, info->scissor.miny << dst->ms_y);
961 PUSH_DATA (push, (info->scissor.maxx - info->scissor.minx) << dst->ms_x);
962 PUSH_DATA (push, (info->scissor.maxy - info->scissor.miny) << dst->ms_y);
963 PUSH_DATA (push, 1); /* enable */
964 }
965
966 if (mask != 0xffffffff) {
967 IMMED_NVC0(push, NVC0_2D(ROP), 0xca); /* DPSDxax */
968 IMMED_NVC0(push, NVC0_2D(PATTERN_COLOR_FORMAT),
969 NVC0_2D_PATTERN_COLOR_FORMAT_32BPP);
970 BEGIN_NVC0(push, NVC0_2D(PATTERN_COLOR(0)), 4);
971 PUSH_DATA (push, 0x00000000);
972 PUSH_DATA (push, mask);
973 PUSH_DATA (push, 0xffffffff);
974 PUSH_DATA (push, 0xffffffff);
975 IMMED_NVC0(push, NVC0_2D(OPERATION), NVC0_2D_OPERATION_ROP);
976 }
977
978 if (src->ms_x > dst->ms_x || src->ms_y > dst->ms_y) {
979 /* ms_x is always >= ms_y */
980 du_dx <<= src->ms_x - dst->ms_x;
981 dv_dy <<= src->ms_y - dst->ms_y;
982 } else {
983 du_dx >>= dst->ms_x - src->ms_x;
984 dv_dy >>= dst->ms_y - src->ms_y;
985 }
986
987 srcx = (int64_t)(info->src.box.x + srcx_adj) << (src->ms_x + 32);
988 srcy = (int64_t)(info->src.box.y + srcy_adj) << (src->ms_y + 32);
989
990 if (src->base.base.nr_samples > dst->base.base.nr_samples) {
991 /* center src coorinates for proper MS resolve filtering */
992 srcx += (int64_t)src->ms_x << 32;
993 srcy += (int64_t)src->ms_y << 32;
994 }
995
996 dstx = info->dst.box.x << dst->ms_x;
997 dsty = info->dst.box.y << dst->ms_y;
998
999 dstw = info->dst.box.width << dst->ms_x;
1000 dsth = info->dst.box.height << dst->ms_y;
1001
1002 if (dstx < 0) {
1003 dstw += dstx;
1004 srcx -= du_dx * dstx;
1005 dstx = 0;
1006 }
1007 if (dsty < 0) {
1008 dsth += dsty;
1009 srcy -= dv_dy * dsty;
1010 dsty = 0;
1011 }
1012
1013 IMMED_NVC0(push, NVC0_2D(BLIT_CONTROL), mode);
1014 BEGIN_NVC0(push, NVC0_2D(BLIT_DST_X), 4);
1015 PUSH_DATA (push, dstx);
1016 PUSH_DATA (push, dsty);
1017 PUSH_DATA (push, dstw);
1018 PUSH_DATA (push, dsth);
1019 BEGIN_NVC0(push, NVC0_2D(BLIT_DU_DX_FRACT), 4);
1020 PUSH_DATA (push, du_dx);
1021 PUSH_DATA (push, du_dx >> 32);
1022 PUSH_DATA (push, dv_dy);
1023 PUSH_DATA (push, dv_dy >> 32);
1024
1025 BCTX_REFN(nvc0->bufctx, 2D, &dst->base, WR);
1026 BCTX_REFN(nvc0->bufctx, 2D, &src->base, RD);
1027 nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
1028 if (nouveau_pushbuf_validate(nvc0->base.pushbuf))
1029 return;
1030
1031 for (i = 0; i < info->dst.box.depth; ++i) {
1032 if (i > 0) {
1033 /* no scaling in z-direction possible for eng2d blits */
1034 if (dst->layout_3d) {
1035 BEGIN_NVC0(push, NVC0_2D(DST_LAYER), 1);
1036 PUSH_DATA (push, info->dst.box.z + i);
1037 } else {
1038 const unsigned z = info->dst.box.z + i;
1039 BEGIN_NVC0(push, NVC0_2D(DST_ADDRESS_HIGH), 2);
1040 PUSH_DATAh(push, dst->base.address + z * dst->layer_stride);
1041 PUSH_DATA (push, dst->base.address + z * dst->layer_stride);
1042 }
1043 if (src->layout_3d) {
1044 /* not possible because of depth tiling */
1045 assert(0);
1046 } else {
1047 const unsigned z = info->src.box.z + i;
1048 BEGIN_NVC0(push, NVC0_2D(SRC_ADDRESS_HIGH), 2);
1049 PUSH_DATAh(push, src->base.address + z * src->layer_stride);
1050 PUSH_DATA (push, src->base.address + z * src->layer_stride);
1051 }
1052 BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_Y_INT), 1); /* trigger */
1053 PUSH_DATA (push, srcy >> 32);
1054 } else {
1055 BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_X_FRACT), 4);
1056 PUSH_DATA (push, srcx);
1057 PUSH_DATA (push, srcx >> 32);
1058 PUSH_DATA (push, srcy);
1059 PUSH_DATA (push, srcy >> 32);
1060 }
1061 }
1062 nvc0_bufctx_fence(nvc0, nvc0->bufctx, FALSE);
1063
1064 nouveau_bufctx_reset(nvc0->bufctx, NVC0_BIND_2D);
1065
1066 if (info->scissor_enable)
1067 IMMED_NVC0(push, NVC0_2D(CLIP_ENABLE), 0);
1068 if (mask != 0xffffffff)
1069 IMMED_NVC0(push, NVC0_2D(OPERATION), NVC0_2D_OPERATION_SRCCOPY);
1070 }
1071
1072 static void
1073 nvc0_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
1074 {
1075 struct nvc0_context *nvc0 = nvc0_context(pipe);
1076 boolean eng3d = FALSE;
1077
1078 if (util_format_is_depth_or_stencil(info->dst.resource->format)) {
1079 if (!(info->mask & PIPE_MASK_ZS))
1080 return;
1081 if (info->dst.resource->format == PIPE_FORMAT_Z32_FLOAT ||
1082 info->dst.resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
1083 eng3d = TRUE;
1084 if (info->filter != PIPE_TEX_FILTER_NEAREST)
1085 eng3d = TRUE;
1086 } else {
1087 if (!(info->mask & PIPE_MASK_RGBA))
1088 return;
1089 if (info->mask != PIPE_MASK_RGBA)
1090 eng3d = TRUE;
1091 }
1092
1093 if (nv50_miptree(info->src.resource)->layout_3d) {
1094 eng3d = TRUE;
1095 } else
1096 if (info->src.box.depth != info->dst.box.depth) {
1097 eng3d = TRUE;
1098 debug_printf("blit: cannot filter array or cube textures in z direction");
1099 }
1100
1101 if (!eng3d && info->dst.format != info->src.format)
1102 if (!nvc0_2d_format_faithful(info->dst.format) ||
1103 !nvc0_2d_format_faithful(info->src.format))
1104 eng3d = TRUE;
1105
1106 if (info->src.resource->nr_samples == 8 &&
1107 info->dst.resource->nr_samples <= 1)
1108 eng3d = TRUE;
1109 #if 0
1110 /* FIXME: can't make this work with eng2d anymore, at least not on nv50 */
1111 if (info->src.resource->nr_samples > 1 ||
1112 info->dst.resource->nr_samples > 1)
1113 eng3d = TRUE;
1114 #endif
1115 /* FIXME: find correct src coordinates adjustments */
1116 if ((info->src.box.width != info->dst.box.width &&
1117 info->src.box.width != -info->dst.box.width) ||
1118 (info->src.box.height != info->dst.box.height &&
1119 info->src.box.height != -info->dst.box.height))
1120 eng3d = TRUE;
1121
1122 if (!eng3d)
1123 nvc0_blit_eng2d(nvc0, info);
1124 else
1125 nvc0_blit_3d(nvc0, info);
1126 }
1127
1128 boolean
1129 nvc0_blitter_create(struct nvc0_screen *screen)
1130 {
1131 screen->blitter = CALLOC_STRUCT(nvc0_blitter);
1132 if (!screen->blitter) {
1133 NOUVEAU_ERR("failed to allocate blitter struct\n");
1134 return FALSE;
1135 }
1136 screen->blitter->screen = screen;
1137
1138 pipe_mutex_init(screen->blitter->mutex);
1139
1140 nvc0_blitter_make_vp(screen->blitter);
1141 nvc0_blitter_make_sampler(screen->blitter);
1142
1143 return TRUE;
1144 }
1145
1146 void
1147 nvc0_blitter_destroy(struct nvc0_screen *screen)
1148 {
1149 struct nvc0_blitter *blitter = screen->blitter;
1150 unsigned i, m;
1151
1152 for (i = 0; i < NV50_BLIT_MAX_TEXTURE_TYPES; ++i) {
1153 for (m = 0; m < NV50_BLIT_MODES; ++m) {
1154 struct nvc0_program *prog = blitter->fp[i][m];
1155 if (prog) {
1156 nvc0_program_destroy(NULL, prog);
1157 FREE((void *)prog->pipe.tokens);
1158 FREE(prog);
1159 }
1160 }
1161 }
1162
1163 FREE(blitter);
1164 }
1165
1166 boolean
1167 nvc0_blitctx_create(struct nvc0_context *nvc0)
1168 {
1169 nvc0->blit = CALLOC_STRUCT(nvc0_blitctx);
1170 if (!nvc0->blit) {
1171 NOUVEAU_ERR("failed to allocate blit context\n");
1172 return FALSE;
1173 }
1174
1175 nvc0->blit->nvc0 = nvc0;
1176
1177 return TRUE;
1178 }
1179
1180 void
1181 nvc0_init_surface_functions(struct nvc0_context *nvc0)
1182 {
1183 struct pipe_context *pipe = &nvc0->base.pipe;
1184
1185 pipe->resource_copy_region = nvc0_resource_copy_region;
1186 pipe->blit = nvc0_blit;
1187 pipe->clear_render_target = nvc0_clear_render_target;
1188 pipe->clear_depth_stencil = nvc0_clear_depth_stencil;
1189 }
1190