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