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 "nvc0_context.h"
33 #include "nvc0_resource.h"
34 
35 #include "nv50/nv50_defs.xml.h"
36 #include "nv50/nv50_texture.xml.h"
37 
38 #define NVC0_ENG2D_SUPPORTED_FORMATS 0xff9ccfe1cce3ccc9ULL
39 
40 /* return TRUE for formats that can be converted among each other by NVC0_2D */
41 static INLINE boolean
nvc0_2d_format_faithful(enum pipe_format format)42 nvc0_2d_format_faithful(enum pipe_format format)
43 {
44    uint8_t id = nvc0_format_table[format].rt;
45 
46    return (id >= 0xc0) && (NVC0_ENG2D_SUPPORTED_FORMATS & (1ULL << (id - 0xc0)));
47 }
48 
49 static INLINE uint8_t
nvc0_2d_format(enum pipe_format format)50 nvc0_2d_format(enum pipe_format format)
51 {
52    uint8_t id = nvc0_format_table[format].rt;
53 
54    /* Hardware values for color formats range from 0xc0 to 0xff,
55     * but the 2D engine doesn't support all of them.
56     */
57    if (nvc0_2d_format_faithful(format))
58       return id;
59 
60    switch (util_format_get_blocksize(format)) {
61    case 1:
62       return NV50_SURFACE_FORMAT_R8_UNORM;
63    case 2:
64       return NV50_SURFACE_FORMAT_R16_UNORM;
65    case 4:
66       return NV50_SURFACE_FORMAT_BGRA8_UNORM;
67    case 8:
68       return NV50_SURFACE_FORMAT_RGBA16_UNORM;
69    case 16:
70       return NV50_SURFACE_FORMAT_RGBA32_FLOAT;
71    default:
72       return 0;
73    }
74 }
75 
76 static int
nvc0_2d_texture_set(struct nouveau_pushbuf * push,boolean dst,struct nv50_miptree * mt,unsigned level,unsigned layer)77 nvc0_2d_texture_set(struct nouveau_pushbuf *push, boolean dst,
78                     struct nv50_miptree *mt, unsigned level, unsigned layer)
79 {
80    struct nouveau_bo *bo = mt->base.bo;
81    uint32_t width, height, depth;
82    uint32_t format;
83    uint32_t mthd = dst ? NVC0_2D_DST_FORMAT : NVC0_2D_SRC_FORMAT;
84    uint32_t offset = mt->level[level].offset;
85 
86    format = nvc0_2d_format(mt->base.base.format);
87    if (!format) {
88       NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
89                   util_format_name(mt->base.base.format));
90       return 1;
91    }
92 
93    width = u_minify(mt->base.base.width0, level) << mt->ms_x;
94    height = u_minify(mt->base.base.height0, level) << mt->ms_y;
95    depth = u_minify(mt->base.base.depth0, level);
96 
97    /* layer has to be < depth, and depth > tile depth / 2 */
98 
99    if (!mt->layout_3d) {
100       offset += mt->layer_stride * layer;
101       layer = 0;
102       depth = 1;
103    } else
104    if (!dst) {
105       offset += nvc0_mt_zslice_offset(mt, level, layer);
106       layer = 0;
107    }
108 
109    if (nouveau_bo_memtype(bo)) {
110       BEGIN_NVC0(push, SUBC_2D(mthd), 2);
111       PUSH_DATA (push, format);
112       PUSH_DATA (push, 1);
113       BEGIN_NVC0(push, SUBC_2D(mthd + 0x14), 5);
114       PUSH_DATA (push, mt->level[level].pitch);
115       PUSH_DATA (push, width);
116       PUSH_DATA (push, height);
117       PUSH_DATAh(push, bo->offset + offset);
118       PUSH_DATA (push, bo->offset + offset);
119    } else {
120       BEGIN_NVC0(push, SUBC_2D(mthd), 5);
121       PUSH_DATA (push, format);
122       PUSH_DATA (push, 0);
123       PUSH_DATA (push, mt->level[level].tile_mode);
124       PUSH_DATA (push, depth);
125       PUSH_DATA (push, layer);
126       BEGIN_NVC0(push, SUBC_2D(mthd + 0x18), 4);
127       PUSH_DATA (push, width);
128       PUSH_DATA (push, height);
129       PUSH_DATAh(push, bo->offset + offset);
130       PUSH_DATA (push, bo->offset + offset);
131    }
132 
133 #if 0
134    if (dst) {
135       BEGIN_NVC0(push, SUBC_2D(NVC0_2D_CLIP_X), 4);
136       PUSH_DATA (push, 0);
137       PUSH_DATA (push, 0);
138       PUSH_DATA (push, width);
139       PUSH_DATA (push, height);
140    }
141 #endif
142    return 0;
143 }
144 
145 static int
nvc0_2d_texture_do_copy(struct nouveau_pushbuf * push,struct nv50_miptree * dst,unsigned dst_level,unsigned dx,unsigned dy,unsigned dz,struct nv50_miptree * src,unsigned src_level,unsigned sx,unsigned sy,unsigned sz,unsigned w,unsigned h)146 nvc0_2d_texture_do_copy(struct nouveau_pushbuf *push,
147                         struct nv50_miptree *dst, unsigned dst_level,
148                         unsigned dx, unsigned dy, unsigned dz,
149                         struct nv50_miptree *src, unsigned src_level,
150                         unsigned sx, unsigned sy, unsigned sz,
151                         unsigned w, unsigned h)
152 {
153    static const uint32_t duvdxy[5] =
154    {
155       0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
156    };
157 
158    int ret;
159    uint32_t ctrl = 0x00;
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);
166    if (ret)
167       return ret;
168 
169    ret = nvc0_2d_texture_set(push, FALSE, src, src_level, sz);
170    if (ret)
171       return ret;
172 
173    /* NOTE: 2D engine doesn't work for MS8 */
174    if (src->ms_x)
175       ctrl = 0x11;
176 
177    /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */
178    BEGIN_NVC0(push, NVC0_2D(BLIT_CONTROL), 1);
179    PUSH_DATA (push, ctrl);
180    BEGIN_NVC0(push, NVC0_2D(BLIT_DST_X), 4);
181    PUSH_DATA (push, dx << dst->ms_x);
182    PUSH_DATA (push, dy << dst->ms_y);
183    PUSH_DATA (push, w << dst->ms_x);
184    PUSH_DATA (push, h << dst->ms_y);
185    BEGIN_NVC0(push, NVC0_2D(BLIT_DU_DX_FRACT), 4);
186    PUSH_DATA (push, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000);
187    PUSH_DATA (push, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f);
188    PUSH_DATA (push, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000);
189    PUSH_DATA (push, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f);
190    BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_X_FRACT), 4);
191    PUSH_DATA (push, 0);
192    PUSH_DATA (push, sx << src->ms_x);
193    PUSH_DATA (push, 0);
194    PUSH_DATA (push, sy << src->ms_x);
195 
196    return 0;
197 }
198 
199 static void
nvc0_resource_copy_region(struct pipe_context * pipe,struct pipe_resource * dst,unsigned dst_level,unsigned dstx,unsigned dsty,unsigned dstz,struct pipe_resource * src,unsigned src_level,const struct pipe_box * src_box)200 nvc0_resource_copy_region(struct pipe_context *pipe,
201                           struct pipe_resource *dst, unsigned dst_level,
202                           unsigned dstx, unsigned dsty, unsigned dstz,
203                           struct pipe_resource *src, unsigned src_level,
204                           const struct pipe_box *src_box)
205 {
206    struct nvc0_context *nvc0 = nvc0_context(pipe);
207    int ret;
208    boolean m2mf;
209    unsigned dst_layer = dstz, src_layer = src_box->z;
210 
211    /* Fallback for buffers. */
212    if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
213       util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
214                                 src, src_level, src_box);
215       return;
216    }
217 
218    /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */
219    assert((src->nr_samples | 1) == (dst->nr_samples | 1));
220 
221    m2mf = (src->format == dst->format) ||
222       (util_format_get_blocksizebits(src->format) ==
223        util_format_get_blocksizebits(dst->format));
224 
225    nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
226 
227    if (m2mf) {
228       struct nv50_m2mf_rect drect, srect;
229       unsigned i;
230       unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
231       unsigned ny = util_format_get_nblocksy(src->format, src_box->height);
232 
233       nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
234       nv50_m2mf_rect_setup(&srect, src, src_level,
235                            src_box->x, src_box->y, src_box->z);
236 
237       for (i = 0; i < src_box->depth; ++i) {
238          nvc0->m2mf_copy_rect(nvc0, &drect, &srect, nx, ny);
239 
240          if (nv50_miptree(dst)->layout_3d)
241             drect.z++;
242          else
243             drect.base += nv50_miptree(dst)->layer_stride;
244 
245          if (nv50_miptree(src)->layout_3d)
246             srect.z++;
247          else
248             srect.base += nv50_miptree(src)->layer_stride;
249       }
250       return;
251    }
252 
253    assert(nvc0_2d_format_faithful(src->format));
254    assert(nvc0_2d_format_faithful(dst->format));
255 
256    BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(src), RD);
257    BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(dst), WR);
258    nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
259    nouveau_pushbuf_validate(nvc0->base.pushbuf);
260 
261    for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
262       ret = nvc0_2d_texture_do_copy(nvc0->base.pushbuf,
263                                     nv50_miptree(dst), dst_level,
264                                     dstx, dsty, dst_layer,
265                                     nv50_miptree(src), src_level,
266                                     src_box->x, src_box->y, src_layer,
267                                     src_box->width, src_box->height);
268       if (ret)
269          break;
270    }
271    nouveau_bufctx_reset(nvc0->bufctx, 0);
272 }
273 
274 static void
nvc0_clear_render_target(struct pipe_context * pipe,struct pipe_surface * dst,const union pipe_color_union * color,unsigned dstx,unsigned dsty,unsigned width,unsigned height)275 nvc0_clear_render_target(struct pipe_context *pipe,
276                          struct pipe_surface *dst,
277                          const union pipe_color_union *color,
278                          unsigned dstx, unsigned dsty,
279                          unsigned width, unsigned height)
280 {
281    struct nvc0_context *nvc0 = nvc0_context(pipe);
282    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
283    struct nv50_surface *sf = nv50_surface(dst);
284    struct nv04_resource *res = nv04_resource(sf->base.texture);
285    unsigned z;
286 
287    BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);
288    PUSH_DATAf(push, color->f[0]);
289    PUSH_DATAf(push, color->f[1]);
290    PUSH_DATAf(push, color->f[2]);
291    PUSH_DATAf(push, color->f[3]);
292 
293    BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
294    PUSH_DATA (push, ( width << 16) | dstx);
295    PUSH_DATA (push, (height << 16) | dsty);
296 
297    BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1);
298    PUSH_DATA (push, 1);
299    BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9);
300    PUSH_DATAh(push, res->address + sf->offset);
301    PUSH_DATA (push, res->address + sf->offset);
302    if (likely(nouveau_bo_memtype(res->bo))) {
303       struct nv50_miptree *mt = nv50_miptree(dst->texture);
304 
305       PUSH_DATA(push, sf->width);
306       PUSH_DATA(push, sf->height);
307       PUSH_DATA(push, nvc0_format_table[dst->format].rt);
308       PUSH_DATA(push, (mt->layout_3d << 16) |
309                mt->level[sf->base.u.tex.level].tile_mode);
310       PUSH_DATA(push, dst->u.tex.first_layer + sf->depth);
311       PUSH_DATA(push, mt->layer_stride >> 2);
312       PUSH_DATA(push, dst->u.tex.first_layer);
313    } else {
314       if (res->base.target == PIPE_BUFFER) {
315          PUSH_DATA(push, 262144);
316          PUSH_DATA(push, 1);
317       } else {
318          PUSH_DATA(push, nv50_miptree(&res->base)->level[0].pitch);
319          PUSH_DATA(push, sf->height);
320       }
321       PUSH_DATA(push, nvc0_format_table[sf->base.format].rt);
322       PUSH_DATA(push, 1 << 12);
323       PUSH_DATA(push, 1);
324       PUSH_DATA(push, 0);
325       PUSH_DATA(push, 0);
326 
327       IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0);
328 
329       /* tiled textures don't have to be fenced, they're not mapped directly */
330       nvc0_resource_fence(res, NOUVEAU_BO_WR);
331    }
332 
333    for (z = 0; z < sf->depth; ++z) {
334       BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
335       PUSH_DATA (push, 0x3c |
336                  (z << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT));
337    }
338 
339    nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
340 }
341 
342 static void
nvc0_clear_depth_stencil(struct pipe_context * pipe,struct pipe_surface * dst,unsigned clear_flags,double depth,unsigned stencil,unsigned dstx,unsigned dsty,unsigned width,unsigned height)343 nvc0_clear_depth_stencil(struct pipe_context *pipe,
344                          struct pipe_surface *dst,
345                          unsigned clear_flags,
346                          double depth,
347                          unsigned stencil,
348                          unsigned dstx, unsigned dsty,
349                          unsigned width, unsigned height)
350 {
351 	struct nvc0_context *nvc0 = nvc0_context(pipe);
352 	struct nouveau_pushbuf *push = nvc0->base.pushbuf;
353 	struct nv50_miptree *mt = nv50_miptree(dst->texture);
354 	struct nv50_surface *sf = nv50_surface(dst);
355 	uint32_t mode = 0;
356 	int unk = mt->base.base.target == PIPE_TEXTURE_2D;
357 	unsigned z;
358 
359 	if (clear_flags & PIPE_CLEAR_DEPTH) {
360 		BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1);
361 		PUSH_DATAf(push, depth);
362 		mode |= NVC0_3D_CLEAR_BUFFERS_Z;
363 	}
364 
365 	if (clear_flags & PIPE_CLEAR_STENCIL) {
366 		BEGIN_NVC0(push, NVC0_3D(CLEAR_STENCIL), 1);
367 		PUSH_DATA (push, stencil & 0xff);
368 		mode |= NVC0_3D_CLEAR_BUFFERS_S;
369 	}
370 
371 	BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
372 	PUSH_DATA (push, ( width << 16) | dstx);
373 	PUSH_DATA (push, (height << 16) | dsty);
374 
375 	BEGIN_NVC0(push, NVC0_3D(ZETA_ADDRESS_HIGH), 5);
376 	PUSH_DATAh(push, mt->base.address + sf->offset);
377 	PUSH_DATA (push, mt->base.address + sf->offset);
378 	PUSH_DATA (push, nvc0_format_table[dst->format].rt);
379 	PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
380 	PUSH_DATA (push, mt->layer_stride >> 2);
381 	BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1);
382 	PUSH_DATA (push, 1);
383 	BEGIN_NVC0(push, NVC0_3D(ZETA_HORIZ), 3);
384 	PUSH_DATA (push, sf->width);
385 	PUSH_DATA (push, sf->height);
386 	PUSH_DATA (push, (unk << 16) | (dst->u.tex.first_layer + sf->depth));
387 	BEGIN_NVC0(push, NVC0_3D(ZETA_BASE_LAYER), 1);
388 	PUSH_DATA (push, dst->u.tex.first_layer);
389 
390 	for (z = 0; z < sf->depth; ++z) {
391 		BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
392 		PUSH_DATA (push, mode |
393 			   (z << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT));
394 	}
395 
396 	nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
397 }
398 
399 void
nvc0_clear(struct pipe_context * pipe,unsigned buffers,const union pipe_color_union * color,double depth,unsigned stencil)400 nvc0_clear(struct pipe_context *pipe, unsigned buffers,
401            const union pipe_color_union *color,
402            double depth, unsigned stencil)
403 {
404    struct nvc0_context *nvc0 = nvc0_context(pipe);
405    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
406    struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
407    unsigned i;
408    uint32_t mode = 0;
409 
410    /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
411    if (!nvc0_state_validate(nvc0, NVC0_NEW_FRAMEBUFFER, 9 + (fb->nr_cbufs * 2)))
412       return;
413 
414    if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
415       BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);
416       PUSH_DATAf(push, color->f[0]);
417       PUSH_DATAf(push, color->f[1]);
418       PUSH_DATAf(push, color->f[2]);
419       PUSH_DATAf(push, color->f[3]);
420       mode =
421          NVC0_3D_CLEAR_BUFFERS_R | NVC0_3D_CLEAR_BUFFERS_G |
422          NVC0_3D_CLEAR_BUFFERS_B | NVC0_3D_CLEAR_BUFFERS_A;
423    }
424 
425    if (buffers & PIPE_CLEAR_DEPTH) {
426       BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1);
427       PUSH_DATA (push, fui(depth));
428       mode |= NVC0_3D_CLEAR_BUFFERS_Z;
429    }
430 
431    if (buffers & PIPE_CLEAR_STENCIL) {
432       BEGIN_NVC0(push, NVC0_3D(CLEAR_STENCIL), 1);
433       PUSH_DATA (push, stencil & 0xff);
434       mode |= NVC0_3D_CLEAR_BUFFERS_S;
435    }
436 
437    BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
438    PUSH_DATA (push, mode);
439 
440    for (i = 1; i < fb->nr_cbufs; i++) {
441       BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
442       PUSH_DATA (push, (i << 6) | 0x3c);
443    }
444 }
445 
446 
447 struct nvc0_blitctx
448 {
449    struct nvc0_screen *screen;
450    struct {
451       struct pipe_framebuffer_state fb;
452       struct nvc0_program *vp;
453       struct nvc0_program *tcp;
454       struct nvc0_program *tep;
455       struct nvc0_program *gp;
456       struct nvc0_program *fp;
457       unsigned num_textures[5];
458       unsigned num_samplers[5];
459       struct pipe_sampler_view *texture[2];
460       struct nv50_tsc_entry *sampler[2];
461       unsigned dirty;
462    } saved;
463    struct nvc0_program vp;
464    struct nvc0_program fp;
465    struct nv50_tsc_entry sampler[2]; /* nearest, bilinear */
466    uint32_t fp_offset;
467    uint16_t color_mask;
468    uint8_t filter;
469 };
470 
471 static void
nvc0_blitctx_make_vp(struct nvc0_blitctx * blit)472 nvc0_blitctx_make_vp(struct nvc0_blitctx *blit)
473 {
474    static const uint32_t code[] =
475    {
476       0xfff01c66, 0x06000080, /* vfetch b128 { $r0 $r1 $r2 $r3 } a[0x80] */
477       0xfff11c26, 0x06000090, /* vfetch b64 { $r4 $r5 } a[0x90]*/
478       0x03f01c66, 0x0a7e0070, /* export b128 o[0x70] { $r0 $r1 $r2 $r3 } */
479       0x13f01c26, 0x0a7e0080, /* export b64 o[0x80] { $r4 $r5 } */
480       0x00001de7, 0x80000000, /* exit */
481    };
482 
483    blit->vp.type = PIPE_SHADER_VERTEX;
484    blit->vp.translated = TRUE;
485    blit->vp.code = (uint32_t *)code; /* no relocations -> no modification */
486    blit->vp.code_size = sizeof(code);
487    blit->vp.max_gpr = 6;
488    blit->vp.vp.edgeflag = PIPE_MAX_ATTRIBS;
489 
490    blit->vp.hdr[0]  = 0x00020461; /* vertprog magic */
491    blit->vp.hdr[4]  = 0x000ff000; /* no outputs read */
492    blit->vp.hdr[6]  = 0x0000003f; /* a[0x80], a[0x90] */
493    blit->vp.hdr[13] = 0x0003f000; /* o[0x70], o[0x80] */
494 }
495 
496 static void
nvc0_blitctx_make_fp(struct nvc0_blitctx * blit)497 nvc0_blitctx_make_fp(struct nvc0_blitctx *blit)
498 {
499    static const uint32_t code_nvc0[] = /* use nvc0dis */
500    {
501       /* 2 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT)
502        * NOTE:
503        * NVC0 doesn't like tex 3d on non-3d textures, but there should
504        * only be 2d and 2d-array MS resources anyway.
505        */
506       0xfff01c00, 0xc07e0080,
507       0xfff05c00, 0xc07e0084,
508       0x00001e86, 0x8013c000,
509       0x00001de7, 0x80000000,
510       /* size: 0x70 + padding  */
511       0, 0, 0, 0,
512 
513       /* 2 coords ZS in, S encoded in R, Z encoded in GBA (8_UNORM)
514        * Setup float outputs in a way that conversion to UNORM yields the
515        * desired byte value.
516        */
517       /* NOTE: need to repeat header */
518       0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
519       0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
520       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
521       0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
522       0xfff09c00, 0xc07e0080,
523       0xfff0dc00, 0xc07e0084,
524       0x00201e86, 0x80104000,
525       0x00205f06, 0x80104101,
526       0xfc009c02, 0x312dffff,
527       0x05001c88,
528       0x09009e88,
529       0x04001c02, 0x30ee0202,
530       0xfc205c02, 0x38000003,
531       0x0020dc02, 0x3803fc00,
532       0x00209c02, 0x380003fc,
533       0x05005c88,
534       0x0d00dc88,
535       0x09209e04, 0x18000000,
536       0x04105c02, 0x30ee0202,
537       0x0430dc02, 0x30ce0202,
538       0x04209c02, 0x30de0202,
539       0x00001de7, 0x80000000,
540       /* size: 0xd0 + padding */
541       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
542 
543       /* 2 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
544       0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
545       0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
546       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
547       0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
548       0xfff09c00, 0xc07e0080,
549       0xfff0dc00, 0xc07e0084,
550       0x00201e86, 0x80104000,
551       0x00205f06, 0x80104101,
552       0xfc009c02, 0x312dffff,
553       0x0500dc88,
554       0x09009e88,
555       0x0430dc02, 0x30ee0202,
556       0xfc201c02, 0x38000003,
557       0x00205c02, 0x380003fc,
558       0x00209c02, 0x3803fc00,
559       0x01001c88,
560       0x05005c88,
561       0x09209e04, 0x18000000,
562       0x04001c02, 0x30ee0202,
563       0x04105c02, 0x30de0202,
564       0x04209c02, 0x30ce0202,
565       0x00001de7, 0x80000000,
566    };
567    static const uint32_t code_nve4[] = /* use nvc0dis */
568    {
569       /* 2 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT)
570        * NOTE:
571        * NVC0 doesn't like tex 3d on non-3d textures, but there should
572        * only be 2d and 2d-array MS resources anyway.
573        */
574       0x2202e237, 0x200002ec,
575       0xfff01c00, 0xc07e0080,
576       0xfff05c00, 0xc07e0084,
577       0x00001e86, 0x8013c000,
578       0x00001de6, 0xf0000000,
579       0x00001de7, 0x80000000,
580       /* size: 0x80 */
581 
582       /* 2 coords ZS in, S encoded in R, Z encoded in GBA (8_UNORM)
583        * Setup float outputs in a way that conversion to UNORM yields the
584        * desired byte value.
585        */
586       /* NOTE: need to repeat header */
587       0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
588       0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
589       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
590       0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
591       0x0202e237, 0x22804c22,
592       0xfff09c00, 0xc07e0080,
593       0xfff0dc00, 0xc07e0084,
594       0x00201e86, 0x80104008,
595       0x00205f06, 0x80104009,
596       0x00001de6, 0xf0000000,
597       0xfc009c02, 0x312dffff,
598       0x05201e04, 0x18000000,
599       0x00428047, 0x22020272,
600       0x09209c84, 0x14000000,
601       0x04001c02, 0x30ee0202,
602       0xfc205c02, 0x38000003,
603       0x0020dc02, 0x3803fc00,
604       0x00209c02, 0x380003fc,
605       0x05205e04, 0x18000000,
606       0x0d20de04, 0x18000000,
607       0x42004277, 0x200002e0,
608       0x09209e04, 0x18000000,
609       0x04105c02, 0x30ee0202,
610       0x0430dc02, 0x30ce0202,
611       0x04209c02, 0x30de0202,
612       0x00001de7, 0x80000000,
613       /* size: 0x100 */
614 
615       /* 2 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
616       0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
617       0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
618       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
619       0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
620       0x0202e237, 0x22804c22,
621       0xfff09c00, 0xc07e0080,
622       0xfff0dc00, 0xc07e0084,
623       0x00201e86, 0x80104008,
624       0x00205f06, 0x80104009,
625       0x00001de6, 0xf0000000,
626       0xfc009c02, 0x312dffff,
627       0x0520de04, 0x18000000,
628       0x00428047, 0x22020272,
629       0x09209c84, 0x14000000,
630       0x0430dc02, 0x30ee0202,
631       0xfc201c02, 0x38000003,
632       0x00205c02, 0x380003fc,
633       0x00209c02, 0x3803fc00,
634       0x01201e04, 0x18000000,
635       0x05205e04, 0x18000000,
636       0x42004277, 0x200002e0,
637       0x09209e04, 0x18000000,
638       0x04001c02, 0x30ee0202,
639       0x04105c02, 0x30de0202,
640       0x04209c02, 0x30ce0202,
641       0x00001de7, 0x80000000,
642    };
643 
644    blit->fp.type = PIPE_SHADER_FRAGMENT;
645    blit->fp.translated = TRUE;
646    if (blit->screen->base.class_3d >= NVE4_3D_CLASS) {
647       blit->fp.code = (uint32_t *)code_nve4; /* const_cast */
648       blit->fp.code_size = sizeof(code_nve4);
649    } else {
650       blit->fp.code = (uint32_t *)code_nvc0; /* const_cast */
651       blit->fp.code_size = sizeof(code_nvc0);
652    }
653    blit->fp.max_gpr = 4;
654 
655    blit->fp.hdr[0]  = 0x00021462; /* fragprog magic */
656    blit->fp.hdr[5]  = 0x80000000;
657    blit->fp.hdr[6]  = 0x0000000f; /* 2 linear */
658    blit->fp.hdr[18] = 0x0000000f; /* 1 colour output */
659 }
660 
661 static void
nvc0_blitctx_make_sampler(struct nvc0_blitctx * blit)662 nvc0_blitctx_make_sampler(struct nvc0_blitctx *blit)
663 {
664    /* clamp to edge, min/max lod = 0, nearest filtering */
665 
666    blit->sampler[0].id = -1;
667 
668    blit->sampler[0].tsc[0] = NV50_TSC_0_SRGB_CONVERSION_ALLOWED |
669       (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPS__SHIFT) |
670       (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPT__SHIFT) |
671       (NV50_TSC_WRAP_CLAMP_TO_EDGE << NV50_TSC_0_WRAPR__SHIFT);
672    blit->sampler[0].tsc[1] =
673       NV50_TSC_1_MAGF_NEAREST | NV50_TSC_1_MINF_NEAREST | NV50_TSC_1_MIPF_NONE;
674 
675    /* clamp to edge, min/max lod = 0, bilinear filtering */
676 
677    blit->sampler[1].id = -1;
678 
679    blit->sampler[1].tsc[0] = blit->sampler[0].tsc[0];
680    blit->sampler[1].tsc[1] =
681       NV50_TSC_1_MAGF_LINEAR | NV50_TSC_1_MINF_LINEAR | NV50_TSC_1_MIPF_NONE;
682 }
683 
684 /* Since shaders cannot export stencil, we cannot copy stencil values when
685  * rendering to ZETA, so we attach the ZS surface to a colour render target.
686  */
687 static INLINE enum pipe_format
nvc0_blit_zeta_to_colour_format(enum pipe_format format)688 nvc0_blit_zeta_to_colour_format(enum pipe_format format)
689 {
690    switch (format) {
691    case PIPE_FORMAT_Z16_UNORM:               return PIPE_FORMAT_R16_UNORM;
692    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
693    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
694    case PIPE_FORMAT_Z24X8_UNORM:             return PIPE_FORMAT_R8G8B8A8_UNORM;
695    case PIPE_FORMAT_Z32_FLOAT:               return PIPE_FORMAT_R32_FLOAT;
696    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:    return PIPE_FORMAT_R32G32_FLOAT;
697    default:
698       assert(0);
699       return PIPE_FORMAT_NONE;
700    }
701 }
702 
703 static void
nvc0_blitctx_get_color_mask_and_fp(struct nvc0_blitctx * blit,enum pipe_format format,uint8_t mask)704 nvc0_blitctx_get_color_mask_and_fp(struct nvc0_blitctx *blit,
705                                    enum pipe_format format, uint8_t mask)
706 {
707    blit->color_mask = 0;
708 
709    switch (format) {
710    case PIPE_FORMAT_Z24X8_UNORM:
711    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
712       blit->fp_offset = 0x180;
713       if (mask & PIPE_MASK_Z)
714          blit->color_mask |= 0x0111;
715       if (mask & PIPE_MASK_S)
716          blit->color_mask |= 0x1000;
717       break;
718    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
719       blit->fp_offset = 0x80;
720       if (mask & PIPE_MASK_Z)
721          blit->color_mask |= 0x1110;
722       if (mask & PIPE_MASK_S)
723          blit->color_mask |= 0x0001;
724       break;
725    default:
726       blit->fp_offset = 0;
727       if (mask & (PIPE_MASK_R | PIPE_MASK_Z)) blit->color_mask |= 0x0001;
728       if (mask & (PIPE_MASK_G | PIPE_MASK_S)) blit->color_mask |= 0x0010;
729       if (mask & PIPE_MASK_B) blit->color_mask |= 0x0100;
730       if (mask & PIPE_MASK_A) blit->color_mask |= 0x1000;
731       break;
732    }
733 }
734 
735 static void
nvc0_blit_set_dst(struct nvc0_context * nvc0,struct pipe_resource * res,unsigned level,unsigned layer)736 nvc0_blit_set_dst(struct nvc0_context *nvc0,
737                   struct pipe_resource *res, unsigned level, unsigned layer)
738 {
739    struct pipe_context *pipe = &nvc0->base.pipe;
740    struct pipe_surface templ;
741 
742    if (util_format_is_depth_or_stencil(res->format))
743       templ.format = nvc0_blit_zeta_to_colour_format(res->format);
744    else
745       templ.format = res->format;
746 
747    templ.usage = PIPE_USAGE_STREAM;
748    templ.u.tex.level = level;
749    templ.u.tex.first_layer = templ.u.tex.last_layer = layer;
750 
751    nvc0->framebuffer.cbufs[0] = nvc0_miptree_surface_new(pipe, res, &templ);
752    nvc0->framebuffer.nr_cbufs = 1;
753    nvc0->framebuffer.zsbuf = NULL;
754    nvc0->framebuffer.width = nvc0->framebuffer.cbufs[0]->width;
755    nvc0->framebuffer.height = nvc0->framebuffer.cbufs[0]->height;
756 }
757 
758 static INLINE void
nvc0_blit_fixup_tic_entry(struct pipe_sampler_view * view,const boolean filter)759 nvc0_blit_fixup_tic_entry(struct pipe_sampler_view *view, const boolean filter)
760 {
761    struct nv50_tic_entry *ent = nv50_tic_entry(view);
762 
763    ent->tic[2] &= ~(1 << 31); /* scaled coordinates, ok with 3d textures ? */
764 
765    /* magic: */
766 
767    if (filter) {
768       /* affects quality of near vertical edges in MS8: */
769       ent->tic[3] = 0x20000000;
770    } else {
771       ent->tic[3] = 0;
772       ent->tic[6] = 0;
773    }
774 }
775 
776 static void
nvc0_blit_set_src(struct nvc0_context * nvc0,struct pipe_resource * res,unsigned level,unsigned layer,const boolean filter)777 nvc0_blit_set_src(struct nvc0_context *nvc0,
778                   struct pipe_resource *res, unsigned level, unsigned layer,
779                   const boolean filter)
780 {
781    struct pipe_context *pipe = &nvc0->base.pipe;
782    struct pipe_sampler_view templ;
783    int s;
784 
785    templ.format = res->format;
786    templ.u.tex.first_layer = templ.u.tex.last_layer = layer;
787    templ.u.tex.first_level = templ.u.tex.last_level = level;
788    templ.swizzle_r = PIPE_SWIZZLE_RED;
789    templ.swizzle_g = PIPE_SWIZZLE_GREEN;
790    templ.swizzle_b = PIPE_SWIZZLE_BLUE;
791    templ.swizzle_a = PIPE_SWIZZLE_ALPHA;
792 
793    nvc0->textures[4][0] = nvc0_create_sampler_view(pipe, res, &templ);
794    nvc0->textures[4][1] = NULL;
795 
796    nvc0_blit_fixup_tic_entry(nvc0->textures[4][0], filter);
797 
798    for (s = 0; s <= 3; ++s)
799       nvc0->num_textures[s] = 0;
800    nvc0->num_textures[4] = 1;
801 
802    templ.format = nv50_zs_to_s_format(res->format);
803    if (templ.format != res->format) {
804       nvc0->textures[4][1] = nvc0_create_sampler_view(pipe, res, &templ);
805       nvc0_blit_fixup_tic_entry(nvc0->textures[4][1], filter);
806       nvc0->num_textures[4] = 2;
807    }
808 }
809 
810 static void
nvc0_blitctx_prepare_state(struct nvc0_blitctx * blit)811 nvc0_blitctx_prepare_state(struct nvc0_blitctx *blit)
812 {
813    struct nouveau_pushbuf *push = blit->screen->base.pushbuf;
814 
815    /* TODO: maybe make this a MACRO (if we need more logic) ? */
816 
817    /* blend state */
818    BEGIN_NVC0(push, NVC0_3D(COLOR_MASK(0)), 1);
819    PUSH_DATA (push, blit->color_mask);
820    BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1);
821    PUSH_DATA (push, 0);
822    IMMED_NVC0(push, NVC0_3D(LOGIC_OP_ENABLE), 0);
823 
824    /* rasterizer state */
825    BEGIN_NVC0(push, NVC0_3D(FRAG_COLOR_CLAMP_EN), 1);
826    PUSH_DATA (push, 0);
827    IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_ENABLE), 0);
828    BEGIN_NVC0(push, NVC0_3D(MSAA_MASK(0)), 4);
829    PUSH_DATA (push, 0xffff);
830    PUSH_DATA (push, 0xffff);
831    PUSH_DATA (push, 0xffff);
832    PUSH_DATA (push, 0xffff);
833    BEGIN_NVC0(push, NVC0_3D(MACRO_POLYGON_MODE_FRONT), 1);
834    PUSH_DATA (push, NVC0_3D_MACRO_POLYGON_MODE_FRONT_FILL);
835    BEGIN_NVC0(push, NVC0_3D(MACRO_POLYGON_MODE_BACK), 1);
836    PUSH_DATA (push, NVC0_3D_MACRO_POLYGON_MODE_BACK_FILL);
837    IMMED_NVC0(push, NVC0_3D(POLYGON_SMOOTH_ENABLE), 0);
838    IMMED_NVC0(push, NVC0_3D(POLYGON_OFFSET_FILL_ENABLE), 0);
839    IMMED_NVC0(push, NVC0_3D(POLYGON_STIPPLE_ENABLE), 0);
840    IMMED_NVC0(push, NVC0_3D(CULL_FACE_ENABLE), 0);
841 
842    /* zsa state */
843    IMMED_NVC0(push, NVC0_3D(DEPTH_TEST_ENABLE), 0);
844    IMMED_NVC0(push, NVC0_3D(STENCIL_ENABLE), 0);
845    IMMED_NVC0(push, NVC0_3D(ALPHA_TEST_ENABLE), 0);
846 
847    /* disable transform feedback */
848    IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), 0);
849 }
850 
851 static void
nvc0_blitctx_pre_blit(struct nvc0_blitctx * blit,struct nvc0_context * nvc0)852 nvc0_blitctx_pre_blit(struct nvc0_blitctx *blit, struct nvc0_context *nvc0)
853 {
854    int s;
855 
856    blit->saved.fb.width = nvc0->framebuffer.width;
857    blit->saved.fb.height = nvc0->framebuffer.height;
858    blit->saved.fb.nr_cbufs = nvc0->framebuffer.nr_cbufs;
859    blit->saved.fb.cbufs[0] = nvc0->framebuffer.cbufs[0];
860    blit->saved.fb.zsbuf = nvc0->framebuffer.zsbuf;
861 
862    blit->saved.vp = nvc0->vertprog;
863    blit->saved.tcp = nvc0->tctlprog;
864    blit->saved.tep = nvc0->tevlprog;
865    blit->saved.gp = nvc0->gmtyprog;
866    blit->saved.fp = nvc0->fragprog;
867 
868    nvc0->vertprog = &blit->vp;
869    nvc0->fragprog = &blit->fp;
870    nvc0->tctlprog = NULL;
871    nvc0->tevlprog = NULL;
872    nvc0->gmtyprog = NULL;
873 
874    for (s = 0; s <= 4; ++s) {
875       blit->saved.num_textures[s] = nvc0->num_textures[s];
876       blit->saved.num_samplers[s] = nvc0->num_samplers[s];
877       nvc0->textures_dirty[s] = (1 << nvc0->num_textures[s]) - 1;
878       nvc0->samplers_dirty[s] = (1 << nvc0->num_samplers[s]) - 1;
879    }
880    blit->saved.texture[0] = nvc0->textures[4][0];
881    blit->saved.texture[1] = nvc0->textures[4][1];
882    blit->saved.sampler[0] = nvc0->samplers[4][0];
883    blit->saved.sampler[1] = nvc0->samplers[4][1];
884 
885    nvc0->samplers[4][0] = &blit->sampler[blit->filter];
886    nvc0->samplers[4][1] = &blit->sampler[blit->filter];
887 
888    for (s = 0; s <= 3; ++s)
889       nvc0->num_samplers[s] = 0;
890    nvc0->num_samplers[4] = 2;
891 
892    blit->saved.dirty = nvc0->dirty;
893 
894    nvc0->textures_dirty[4] |= 3;
895    nvc0->samplers_dirty[4] |= 3;
896 
897    nvc0->dirty = NVC0_NEW_FRAMEBUFFER |
898       NVC0_NEW_VERTPROG | NVC0_NEW_FRAGPROG |
899       NVC0_NEW_TCTLPROG | NVC0_NEW_TEVLPROG | NVC0_NEW_GMTYPROG |
900       NVC0_NEW_TEXTURES | NVC0_NEW_SAMPLERS;
901 }
902 
903 static void
nvc0_blitctx_post_blit(struct nvc0_context * nvc0,struct nvc0_blitctx * blit)904 nvc0_blitctx_post_blit(struct nvc0_context *nvc0, struct nvc0_blitctx *blit)
905 {
906    int s;
907 
908    pipe_surface_reference(&nvc0->framebuffer.cbufs[0], NULL);
909 
910    nvc0->framebuffer.width = blit->saved.fb.width;
911    nvc0->framebuffer.height = blit->saved.fb.height;
912    nvc0->framebuffer.nr_cbufs = blit->saved.fb.nr_cbufs;
913    nvc0->framebuffer.cbufs[0] = blit->saved.fb.cbufs[0];
914    nvc0->framebuffer.zsbuf = blit->saved.fb.zsbuf;
915 
916    nvc0->vertprog = blit->saved.vp;
917    nvc0->tctlprog = blit->saved.tcp;
918    nvc0->tevlprog = blit->saved.tep;
919    nvc0->gmtyprog = blit->saved.gp;
920    nvc0->fragprog = blit->saved.fp;
921 
922    pipe_sampler_view_reference(&nvc0->textures[4][0], NULL);
923    pipe_sampler_view_reference(&nvc0->textures[4][1], NULL);
924 
925    for (s = 0; s <= 4; ++s) {
926       nvc0->num_textures[s] = blit->saved.num_textures[s];
927       nvc0->num_samplers[s] = blit->saved.num_samplers[s];
928       nvc0->textures_dirty[s] = (1 << nvc0->num_textures[s]) - 1;
929       nvc0->samplers_dirty[s] = (1 << nvc0->num_samplers[s]) - 1;
930    }
931    nvc0->textures[4][0] = blit->saved.texture[0];
932    nvc0->textures[4][1] = blit->saved.texture[1];
933    nvc0->samplers[4][0] = blit->saved.sampler[0];
934    nvc0->samplers[4][1] = blit->saved.sampler[1];
935 
936    nvc0->textures_dirty[4] |= 3;
937    nvc0->samplers_dirty[4] |= 3;
938 
939    nvc0->dirty = blit->saved.dirty |
940       (NVC0_NEW_FRAMEBUFFER | NVC0_NEW_SCISSOR | NVC0_NEW_SAMPLE_MASK |
941        NVC0_NEW_RASTERIZER | NVC0_NEW_ZSA | NVC0_NEW_BLEND |
942        NVC0_NEW_TEXTURES | NVC0_NEW_SAMPLERS |
943        NVC0_NEW_VERTPROG | NVC0_NEW_FRAGPROG |
944        NVC0_NEW_TCTLPROG | NVC0_NEW_TEVLPROG | NVC0_NEW_GMTYPROG |
945        NVC0_NEW_TFB_TARGETS);
946 }
947 
948 static void
nvc0_resource_resolve(struct pipe_context * pipe,const struct pipe_resolve_info * info)949 nvc0_resource_resolve(struct pipe_context *pipe,
950                       const struct pipe_resolve_info *info)
951 {
952    struct nvc0_context *nvc0 = nvc0_context(pipe);
953    struct nvc0_screen *screen = nvc0->screen;
954    struct nvc0_blitctx *blit = screen->blitctx;
955    struct nouveau_pushbuf *push = screen->base.pushbuf;
956    struct pipe_resource *src = info->src.res;
957    struct pipe_resource *dst = info->dst.res;
958    float x0, x1, y0, y1;
959    float x_range, y_range;
960 
961    /* Would need more shader variants or, better, just change the TIC target.
962     * But no API creates 3D MS textures ...
963     */
964    if (src->target == PIPE_TEXTURE_3D)
965       return;
966 
967    nvc0_blitctx_get_color_mask_and_fp(blit, dst->format, info->mask);
968 
969    blit->filter = util_format_is_depth_or_stencil(dst->format) ? 0 : 1;
970 
971    nvc0_blitctx_pre_blit(blit, nvc0);
972 
973    nvc0_blit_set_dst(nvc0, dst, info->dst.level, info->dst.layer);
974    nvc0_blit_set_src(nvc0, src, 0,               info->src.layer, blit->filter);
975 
976    nvc0_blitctx_prepare_state(blit);
977 
978    nvc0_state_validate(nvc0, ~0, 36);
979 
980    x_range =
981       (float)(info->src.x1 - info->src.x0) /
982       (float)(info->dst.x1 - info->dst.x0);
983    y_range =
984       (float)(info->src.y1 - info->src.y0) /
985       (float)(info->dst.y1 - info->dst.y0);
986 
987    x0 = (float)info->src.x0 - x_range * (float)info->dst.x0;
988    y0 = (float)info->src.y0 - y_range * (float)info->dst.y0;
989 
990    x1 = x0 + 16384.0f * x_range;
991    y1 = y0 + 16384.0f * y_range;
992 
993    x0 *= (float)(1 << nv50_miptree(src)->ms_x);
994    x1 *= (float)(1 << nv50_miptree(src)->ms_x);
995    y0 *= (float)(1 << nv50_miptree(src)->ms_y);
996    y1 *= (float)(1 << nv50_miptree(src)->ms_y);
997 
998    BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1);
999    PUSH_DATA (push,
1000               blit->fp.code_base + blit->fp_offset);
1001 
1002    IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 0);
1003 
1004    /* Draw a large triangle in screen coordinates covering the whole
1005     * render target, with scissors defining the destination region.
1006     * The vertex is supplied with non-normalized texture coordinates
1007     * arranged in a way to yield the desired offset and scale.
1008     */
1009 
1010    BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2);
1011    PUSH_DATA (push, (info->dst.x1 << 16) | info->dst.x0);
1012    PUSH_DATA (push, (info->dst.y1 << 16) | info->dst.y0);
1013 
1014    IMMED_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL),
1015               NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES);
1016 
1017    BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
1018    PUSH_DATA (push, 0x74201);
1019    PUSH_DATAf(push, x0);
1020    PUSH_DATAf(push, y0);
1021    BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
1022    PUSH_DATA (push, 0x74200);
1023    PUSH_DATAf(push, 0.0f);
1024    PUSH_DATAf(push, 0.0f);
1025    BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
1026    PUSH_DATA (push, 0x74201);
1027    PUSH_DATAf(push, x1);
1028    PUSH_DATAf(push, y0);
1029    BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
1030    PUSH_DATA (push, 0x74200);
1031    PUSH_DATAf(push, 16384 << nv50_miptree(dst)->ms_x);
1032    PUSH_DATAf(push, 0.0f);
1033    BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
1034    PUSH_DATA (push, 0x74201);
1035    PUSH_DATAf(push, x0);
1036    PUSH_DATAf(push, y1);
1037    BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
1038    PUSH_DATA (push, 0x74200);
1039    PUSH_DATAf(push, 0.0f);
1040    PUSH_DATAf(push, 16384 << nv50_miptree(dst)->ms_y);
1041 
1042    IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0);
1043 
1044    /* re-enable normally constant state */
1045 
1046    IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 1);
1047 
1048    nvc0_blitctx_post_blit(nvc0, blit);
1049 }
1050 
1051 boolean
nvc0_blitctx_create(struct nvc0_screen * screen)1052 nvc0_blitctx_create(struct nvc0_screen *screen)
1053 {
1054    screen->blitctx = CALLOC_STRUCT(nvc0_blitctx);
1055    if (!screen->blitctx) {
1056       NOUVEAU_ERR("failed to allocate blit context\n");
1057       return FALSE;
1058    }
1059 
1060    screen->blitctx->screen = screen;
1061 
1062    nvc0_blitctx_make_vp(screen->blitctx);
1063    nvc0_blitctx_make_fp(screen->blitctx);
1064 
1065    nvc0_blitctx_make_sampler(screen->blitctx);
1066 
1067    screen->blitctx->color_mask = 0x1111;
1068 
1069    return TRUE;
1070 }
1071 
1072 
1073 void
nvc0_init_surface_functions(struct nvc0_context * nvc0)1074 nvc0_init_surface_functions(struct nvc0_context *nvc0)
1075 {
1076    struct pipe_context *pipe = &nvc0->base.pipe;
1077 
1078    pipe->resource_copy_region = nvc0_resource_copy_region;
1079    pipe->resource_resolve = nvc0_resource_resolve;
1080    pipe->clear_render_target = nvc0_clear_render_target;
1081    pipe->clear_depth_stencil = nvc0_clear_depth_stencil;
1082 }
1083 
1084