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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 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/format/u_format.h" 30#include "util/u_surface.h" 31 32#include "tgsi/tgsi_ureg.h" 33 34#include "os/os_thread.h" 35 36#include "nvc0/nvc0_context.h" 37#include "nvc0/nvc0_resource.h" 38 39#include "nv50/g80_defs.xml.h" 40#include "nv50/g80_texture.xml.h" 41 42/* these are used in nv50_blit.h */ 43#define NV50_ENG2D_SUPPORTED_FORMATS 0xff9ccfe1cce3ccc9ULL 44#define NV50_ENG2D_NOCONVERT_FORMATS 0x009cc02000000000ULL 45#define NV50_ENG2D_LUMINANCE_FORMATS 0x001cc02000000000ULL 46#define NV50_ENG2D_INTENSITY_FORMATS 0x0080000000000000ULL 47#define NV50_ENG2D_OPERATION_FORMATS 0x060001c000638000ULL 48 49#define NOUVEAU_DRIVER 0xc0 50#include "nv50/nv50_blit.h" 51 52static inline uint8_t 53nvc0_2d_format(enum pipe_format format, bool dst, bool dst_src_equal) 54{ 55 uint8_t id = nvc0_format_table[format].rt; 56 57 /* A8_UNORM is treated as I8_UNORM as far as the 2D engine is concerned. */ 58 if (!dst && unlikely(format == PIPE_FORMAT_I8_UNORM) && !dst_src_equal) 59 return G80_SURFACE_FORMAT_A8_UNORM; 60 61 /* Hardware values for color formats range from 0xc0 to 0xff, 62 * but the 2D engine doesn't support all of them. 63 */ 64 if (nv50_2d_format_supported(format)) 65 return id; 66 assert(dst_src_equal); 67 68 switch (util_format_get_blocksize(format)) { 69 case 1: 70 return G80_SURFACE_FORMAT_R8_UNORM; 71 case 2: 72 return G80_SURFACE_FORMAT_RG8_UNORM; 73 case 4: 74 return G80_SURFACE_FORMAT_BGRA8_UNORM; 75 case 8: 76 return G80_SURFACE_FORMAT_RGBA16_UNORM; 77 case 16: 78 return G80_SURFACE_FORMAT_RGBA32_FLOAT; 79 default: 80 assert(0); 81 return 0; 82 } 83} 84 85static int 86nvc0_2d_texture_set(struct nouveau_pushbuf *push, bool dst, 87 struct nv50_miptree *mt, unsigned level, unsigned layer, 88 enum pipe_format pformat, bool dst_src_pformat_equal) 89{ 90 struct nouveau_bo *bo = mt->base.bo; 91 uint32_t width, height, depth; 92 uint32_t format; 93 uint32_t mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT; 94 uint32_t offset = mt->level[level].offset; 95 96 format = nvc0_2d_format(pformat, dst, dst_src_pformat_equal); 97 if (!format) { 98 NOUVEAU_ERR("invalid/unsupported surface format: %s\n", 99 util_format_name(pformat)); 100 return 1; 101 } 102 103 width = u_minify(mt->base.base.width0, level) << mt->ms_x; 104 height = u_minify(mt->base.base.height0, level) << mt->ms_y; 105 depth = u_minify(mt->base.base.depth0, level); 106 107 /* layer has to be < depth, and depth > tile depth / 2 */ 108 109 if (!mt->layout_3d) { 110 offset += mt->layer_stride * layer; 111 layer = 0; 112 depth = 1; 113 } else 114 if (!dst) { 115 offset += nvc0_mt_zslice_offset(mt, level, layer); 116 layer = 0; 117 } 118 119 if (!nouveau_bo_memtype(bo)) { 120 BEGIN_NVC0(push, SUBC_2D(mthd), 2); 121 PUSH_DATA (push, format); 122 PUSH_DATA (push, 1); 123 BEGIN_NVC0(push, SUBC_2D(mthd + 0x14), 5); 124 PUSH_DATA (push, mt->level[level].pitch); 125 PUSH_DATA (push, width); 126 PUSH_DATA (push, height); 127 PUSH_DATAh(push, bo->offset + offset); 128 PUSH_DATA (push, bo->offset + offset); 129 } else { 130 BEGIN_NVC0(push, SUBC_2D(mthd), 5); 131 PUSH_DATA (push, format); 132 PUSH_DATA (push, 0); 133 PUSH_DATA (push, mt->level[level].tile_mode); 134 PUSH_DATA (push, depth); 135 PUSH_DATA (push, layer); 136 BEGIN_NVC0(push, SUBC_2D(mthd + 0x18), 4); 137 PUSH_DATA (push, width); 138 PUSH_DATA (push, height); 139 PUSH_DATAh(push, bo->offset + offset); 140 PUSH_DATA (push, bo->offset + offset); 141 } 142 143 if (dst) { 144 IMMED_NVC0(push, SUBC_2D(NVC0_2D_SET_DST_COLOR_RENDER_TO_ZETA_SURFACE), 145 util_format_is_depth_or_stencil(pformat)); 146 } 147 148#if 0 149 if (dst) { 150 BEGIN_NVC0(push, SUBC_2D(NVC0_2D_CLIP_X), 4); 151 PUSH_DATA (push, 0); 152 PUSH_DATA (push, 0); 153 PUSH_DATA (push, width); 154 PUSH_DATA (push, height); 155 } 156#endif 157 return 0; 158} 159 160static int 161nvc0_2d_texture_do_copy(struct nouveau_pushbuf *push, 162 struct nv50_miptree *dst, unsigned dst_level, 163 unsigned dx, unsigned dy, unsigned dz, 164 struct nv50_miptree *src, unsigned src_level, 165 unsigned sx, unsigned sy, unsigned sz, 166 unsigned w, unsigned h) 167{ 168 const enum pipe_format dfmt = dst->base.base.format; 169 const enum pipe_format sfmt = src->base.base.format; 170 int ret; 171 bool eqfmt = dfmt == sfmt; 172 173 if (!PUSH_SPACE(push, 2 * 16 + 32)) 174 return PIPE_ERROR; 175 176 ret = nvc0_2d_texture_set(push, true, dst, dst_level, dz, dfmt, eqfmt); 177 if (ret) 178 return ret; 179 180 ret = nvc0_2d_texture_set(push, false, src, src_level, sz, sfmt, eqfmt); 181 if (ret) 182 return ret; 183 184 IMMED_NVC0(push, NVC0_2D(BLIT_CONTROL), 0x00); 185 BEGIN_NVC0(push, NVC0_2D(BLIT_DST_X), 4); 186 PUSH_DATA (push, dx << dst->ms_x); 187 PUSH_DATA (push, dy << dst->ms_y); 188 PUSH_DATA (push, w << dst->ms_x); 189 PUSH_DATA (push, h << dst->ms_y); 190 BEGIN_NVC0(push, NVC0_2D(BLIT_DU_DX_FRACT), 4); 191 PUSH_DATA (push, 0); 192 PUSH_DATA (push, 1); 193 PUSH_DATA (push, 0); 194 PUSH_DATA (push, 1); 195 BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_X_FRACT), 4); 196 PUSH_DATA (push, 0); 197 PUSH_DATA (push, sx << src->ms_x); 198 PUSH_DATA (push, 0); 199 PUSH_DATA (push, sy << src->ms_y); 200 201 return 0; 202} 203 204static void 205nvc0_resource_copy_region(struct pipe_context *pipe, 206 struct pipe_resource *dst, unsigned dst_level, 207 unsigned dstx, unsigned dsty, unsigned dstz, 208 struct pipe_resource *src, unsigned src_level, 209 const struct pipe_box *src_box) 210{ 211 struct nvc0_context *nvc0 = nvc0_context(pipe); 212 int ret; 213 bool m2mf; 214 unsigned dst_layer = dstz, src_layer = src_box->z; 215 216 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 217 nouveau_copy_buffer(&nvc0->base, 218 nv04_resource(dst), dstx, 219 nv04_resource(src), src_box->x, src_box->width); 220 NOUVEAU_DRV_STAT(&nvc0->screen->base, buf_copy_bytes, src_box->width); 221 return; 222 } 223 NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_copy_count, 1); 224 225 /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */ 226 assert((src->nr_samples | 1) == (dst->nr_samples | 1)); 227 228 m2mf = (src->format == dst->format) || 229 (util_format_get_blocksizebits(src->format) == 230 util_format_get_blocksizebits(dst->format)); 231 232 nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; 233 234 if (m2mf) { 235 struct nv50_miptree *src_mt = nv50_miptree(src); 236 struct nv50_miptree *dst_mt = nv50_miptree(dst); 237 struct nv50_m2mf_rect drect, srect; 238 unsigned i; 239 unsigned nx = util_format_get_nblocksx(src->format, src_box->width) 240 << src_mt->ms_x; 241 unsigned ny = util_format_get_nblocksy(src->format, src_box->height) 242 << src_mt->ms_y; 243 244 nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz); 245 nv50_m2mf_rect_setup(&srect, src, src_level, 246 src_box->x, src_box->y, src_box->z); 247 248 for (i = 0; i < src_box->depth; ++i) { 249 nvc0->m2mf_copy_rect(nvc0, &drect, &srect, nx, ny); 250 251 if (dst_mt->layout_3d) 252 drect.z++; 253 else 254 drect.base += dst_mt->layer_stride; 255 256 if (src_mt->layout_3d) 257 srect.z++; 258 else 259 srect.base += src_mt->layer_stride; 260 } 261 return; 262 } 263 264 assert(nv50_2d_dst_format_faithful(dst->format)); 265 assert(nv50_2d_src_format_faithful(src->format)); 266 267 BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(src), RD); 268 BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(dst), WR); 269 nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx); 270 nouveau_pushbuf_validate(nvc0->base.pushbuf); 271 272 for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) { 273 ret = nvc0_2d_texture_do_copy(nvc0->base.pushbuf, 274 nv50_miptree(dst), dst_level, 275 dstx, dsty, dst_layer, 276 nv50_miptree(src), src_level, 277 src_box->x, src_box->y, src_layer, 278 src_box->width, src_box->height); 279 if (ret) 280 break; 281 } 282 nouveau_bufctx_reset(nvc0->bufctx, 0); 283} 284 285static void 286nvc0_clear_render_target(struct pipe_context *pipe, 287 struct pipe_surface *dst, 288 const union pipe_color_union *color, 289 unsigned dstx, unsigned dsty, 290 unsigned width, unsigned height, 291 bool render_condition_enabled) 292{ 293 struct nvc0_context *nvc0 = nvc0_context(pipe); 294 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 295 struct nv50_surface *sf = nv50_surface(dst); 296 struct nv04_resource *res = nv04_resource(sf->base.texture); 297 unsigned z; 298 299 assert(dst->texture->target != PIPE_BUFFER); 300 301 if (!PUSH_SPACE(push, 32 + sf->depth)) 302 return; 303 304 PUSH_REFN (push, res->bo, res->domain | NOUVEAU_BO_WR); 305 306 BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4); 307 PUSH_DATAf(push, color->f[0]); 308 PUSH_DATAf(push, color->f[1]); 309 PUSH_DATAf(push, color->f[2]); 310 PUSH_DATAf(push, color->f[3]); 311 312 BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); 313 PUSH_DATA (push, ( width << 16) | dstx); 314 PUSH_DATA (push, (height << 16) | dsty); 315 316 BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1); 317 PUSH_DATA (push, 1); 318 BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9); 319 PUSH_DATAh(push, res->address + sf->offset); 320 PUSH_DATA (push, res->address + sf->offset); 321 if (likely(nouveau_bo_memtype(res->bo))) { 322 struct nv50_miptree *mt = nv50_miptree(dst->texture); 323 324 PUSH_DATA(push, sf->width); 325 PUSH_DATA(push, sf->height); 326 PUSH_DATA(push, nvc0_format_table[dst->format].rt); 327 PUSH_DATA(push, (mt->layout_3d << 16) | 328 mt->level[sf->base.u.tex.level].tile_mode); 329 PUSH_DATA(push, dst->u.tex.first_layer + sf->depth); 330 PUSH_DATA(push, mt->layer_stride >> 2); 331 PUSH_DATA(push, dst->u.tex.first_layer); 332 IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), mt->ms_mode); 333 } else { 334 if (res->base.target == PIPE_BUFFER) { 335 PUSH_DATA(push, 262144); 336 PUSH_DATA(push, 1); 337 } else { 338 PUSH_DATA(push, nv50_miptree(&res->base)->level[0].pitch); 339 PUSH_DATA(push, sf->height); 340 } 341 PUSH_DATA(push, nvc0_format_table[sf->base.format].rt); 342 PUSH_DATA(push, 1 << 12); 343 PUSH_DATA(push, 1); 344 PUSH_DATA(push, 0); 345 PUSH_DATA(push, 0); 346 347 IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0); 348 IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), 0); 349 350 /* tiled textures don't have to be fenced, they're not mapped directly */ 351 nvc0_resource_fence(res, NOUVEAU_BO_WR); 352 } 353 354 if (!render_condition_enabled) 355 IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS); 356 357 BEGIN_NIC0(push, NVC0_3D(CLEAR_BUFFERS), sf->depth); 358 for (z = 0; z < sf->depth; ++z) { 359 PUSH_DATA (push, 0x3c | 360 (z << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 361 } 362 363 if (!render_condition_enabled) 364 IMMED_NVC0(push, NVC0_3D(COND_MODE), nvc0->cond_condmode); 365 366 nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER; 367} 368 369static void 370nvc0_clear_buffer_push_nvc0(struct pipe_context *pipe, 371 struct pipe_resource *res, 372 unsigned offset, unsigned size, 373 const void *data, int data_size) 374{ 375 struct nvc0_context *nvc0 = nvc0_context(pipe); 376 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 377 struct nv04_resource *buf = nv04_resource(res); 378 unsigned i; 379 380 nouveau_bufctx_refn(nvc0->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR); 381 nouveau_pushbuf_bufctx(push, nvc0->bufctx); 382 nouveau_pushbuf_validate(push); 383 384 unsigned count = (size + 3) / 4; 385 unsigned data_words = data_size / 4; 386 387 while (count) { 388 unsigned nr_data = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN) / data_words; 389 unsigned nr = nr_data * data_words; 390 391 if (!PUSH_SPACE(push, nr + 9)) 392 break; 393 394 BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2); 395 PUSH_DATAh(push, buf->address + offset); 396 PUSH_DATA (push, buf->address + offset); 397 BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2); 398 PUSH_DATA (push, MIN2(size, nr * 4)); 399 PUSH_DATA (push, 1); 400 BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1); 401 PUSH_DATA (push, 0x100111); 402 403 /* must not be interrupted (trap on QUERY fence, 0x50 works however) */ 404 BEGIN_NIC0(push, NVC0_M2MF(DATA), nr); 405 for (i = 0; i < nr_data; i++) 406 PUSH_DATAp(push, data, data_words); 407 408 count -= nr; 409 offset += nr * 4; 410 size -= nr * 4; 411 } 412 413 nvc0_resource_validate(buf, NOUVEAU_BO_WR); 414 415 nouveau_bufctx_reset(nvc0->bufctx, 0); 416} 417 418static void 419nvc0_clear_buffer_push_nve4(struct pipe_context *pipe, 420 struct pipe_resource *res, 421 unsigned offset, unsigned size, 422 const void *data, int data_size) 423{ 424 struct nvc0_context *nvc0 = nvc0_context(pipe); 425 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 426 struct nv04_resource *buf = nv04_resource(res); 427 unsigned i; 428 429 nouveau_bufctx_refn(nvc0->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR); 430 nouveau_pushbuf_bufctx(push, nvc0->bufctx); 431 nouveau_pushbuf_validate(push); 432 433 unsigned count = (size + 3) / 4; 434 unsigned data_words = data_size / 4; 435 436 while (count) { 437 unsigned nr_data = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN) / data_words; 438 unsigned nr = nr_data * data_words; 439 440 if (!PUSH_SPACE(push, nr + 10)) 441 break; 442 443 BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH), 2); 444 PUSH_DATAh(push, buf->address + offset); 445 PUSH_DATA (push, buf->address + offset); 446 BEGIN_NVC0(push, NVE4_P2MF(UPLOAD_LINE_LENGTH_IN), 2); 447 PUSH_DATA (push, MIN2(size, nr * 4)); 448 PUSH_DATA (push, 1); 449 /* must not be interrupted (trap on QUERY fence, 0x50 works however) */ 450 BEGIN_1IC0(push, NVE4_P2MF(UPLOAD_EXEC), nr + 1); 451 PUSH_DATA (push, 0x1001); 452 for (i = 0; i < nr_data; i++) 453 PUSH_DATAp(push, data, data_words); 454 455 count -= nr; 456 offset += nr * 4; 457 size -= nr * 4; 458 } 459 460 nvc0_resource_validate(buf, NOUVEAU_BO_WR); 461 462 nouveau_bufctx_reset(nvc0->bufctx, 0); 463} 464 465static void 466nvc0_clear_buffer_push(struct pipe_context *pipe, 467 struct pipe_resource *res, 468 unsigned offset, unsigned size, 469 const void *data, int data_size) 470{ 471 struct nvc0_context *nvc0 = nvc0_context(pipe); 472 unsigned tmp; 473 474 if (data_size == 1) { 475 tmp = *(unsigned char *)data; 476 tmp = (tmp << 24) | (tmp << 16) | (tmp << 8) | tmp; 477 data = &tmp; 478 data_size = 4; 479 } else if (data_size == 2) { 480 tmp = *(unsigned short *)data; 481 tmp = (tmp << 16) | tmp; 482 data = &tmp; 483 data_size = 4; 484 } 485 486 if (nvc0->screen->base.class_3d < NVE4_3D_CLASS) 487 nvc0_clear_buffer_push_nvc0(pipe, res, offset, size, data, data_size); 488 else 489 nvc0_clear_buffer_push_nve4(pipe, res, offset, size, data, data_size); 490} 491 492static void 493nvc0_clear_buffer(struct pipe_context *pipe, 494 struct pipe_resource *res, 495 unsigned offset, unsigned size, 496 const void *data, int data_size) 497{ 498 struct nvc0_context *nvc0 = nvc0_context(pipe); 499 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 500 struct nv04_resource *buf = nv04_resource(res); 501 union pipe_color_union color; 502 enum pipe_format dst_fmt; 503 unsigned width, height, elements; 504 505 assert(res->target == PIPE_BUFFER); 506 assert(nouveau_bo_memtype(buf->bo) == 0); 507 508 switch (data_size) { 509 case 16: 510 dst_fmt = PIPE_FORMAT_R32G32B32A32_UINT; 511 memcpy(&color.ui, data, 16); 512 break; 513 case 12: 514 /* RGB32 is not a valid RT format. This will be handled by the pushbuf 515 * uploader. 516 */ 517 dst_fmt = PIPE_FORMAT_NONE; /* Init dst_fmt to silence gcc warning */ 518 break; 519 case 8: 520 dst_fmt = PIPE_FORMAT_R32G32_UINT; 521 memcpy(&color.ui, data, 8); 522 memset(&color.ui[2], 0, 8); 523 break; 524 case 4: 525 dst_fmt = PIPE_FORMAT_R32_UINT; 526 memcpy(&color.ui, data, 4); 527 memset(&color.ui[1], 0, 12); 528 break; 529 case 2: 530 dst_fmt = PIPE_FORMAT_R16_UINT; 531 color.ui[0] = util_cpu_to_le32( 532 util_le16_to_cpu(*(unsigned short *)data)); 533 memset(&color.ui[1], 0, 12); 534 break; 535 case 1: 536 dst_fmt = PIPE_FORMAT_R8_UINT; 537 color.ui[0] = util_cpu_to_le32(*(unsigned char *)data); 538 memset(&color.ui[1], 0, 12); 539 break; 540 default: 541 assert(!"Unsupported element size"); 542 return; 543 } 544 545 util_range_add(&buf->base, &buf->valid_buffer_range, offset, offset + size); 546 547 assert(size % data_size == 0); 548 549 if (data_size == 12) { 550 nvc0_clear_buffer_push(pipe, res, offset, size, data, data_size); 551 return; 552 } 553 554 if (offset & 0xff) { 555 unsigned fixup_size = MIN2(size, align(offset, 0x100) - offset); 556 assert(fixup_size % data_size == 0); 557 nvc0_clear_buffer_push(pipe, res, offset, fixup_size, data, data_size); 558 offset += fixup_size; 559 size -= fixup_size; 560 if (!size) 561 return; 562 } 563 564 elements = size / data_size; 565 height = (elements + 16383) / 16384; 566 width = elements / height; 567 if (height > 1) 568 width &= ~0xff; 569 assert(width > 0); 570 571 if (!PUSH_SPACE(push, 40)) 572 return; 573 574 PUSH_REFN (push, buf->bo, buf->domain | NOUVEAU_BO_WR); 575 576 BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4); 577 PUSH_DATA (push, color.ui[0]); 578 PUSH_DATA (push, color.ui[1]); 579 PUSH_DATA (push, color.ui[2]); 580 PUSH_DATA (push, color.ui[3]); 581 BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); 582 PUSH_DATA (push, width << 16); 583 PUSH_DATA (push, height << 16); 584 585 IMMED_NVC0(push, NVC0_3D(RT_CONTROL), 1); 586 587 BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9); 588 PUSH_DATAh(push, buf->address + offset); 589 PUSH_DATA (push, buf->address + offset); 590 PUSH_DATA (push, align(width * data_size, 0x100)); 591 PUSH_DATA (push, height); 592 PUSH_DATA (push, nvc0_format_table[dst_fmt].rt); 593 PUSH_DATA (push, NVC0_3D_RT_TILE_MODE_LINEAR); 594 PUSH_DATA (push, 1); 595 PUSH_DATA (push, 0); 596 PUSH_DATA (push, 0); 597 598 IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0); 599 IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), 0); 600 601 IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS); 602 603 IMMED_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 0x3c); 604 605 IMMED_NVC0(push, NVC0_3D(COND_MODE), nvc0->cond_condmode); 606 607 nvc0_resource_validate(buf, NOUVEAU_BO_WR); 608 609 if (width * height != elements) { 610 offset += width * height * data_size; 611 width = elements - width * height; 612 nvc0_clear_buffer_push(pipe, res, offset, width * data_size, 613 data, data_size); 614 } 615 616 nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER; 617} 618 619static void 620nvc0_clear_depth_stencil(struct pipe_context *pipe, 621 struct pipe_surface *dst, 622 unsigned clear_flags, 623 double depth, 624 unsigned stencil, 625 unsigned dstx, unsigned dsty, 626 unsigned width, unsigned height, 627 bool render_condition_enabled) 628{ 629 struct nvc0_context *nvc0 = nvc0_context(pipe); 630 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 631 struct nv50_miptree *mt = nv50_miptree(dst->texture); 632 struct nv50_surface *sf = nv50_surface(dst); 633 uint32_t mode = 0; 634 int unk = mt->base.base.target == PIPE_TEXTURE_2D; 635 unsigned z; 636 637 assert(dst->texture->target != PIPE_BUFFER); 638 639 if (!PUSH_SPACE(push, 32 + sf->depth)) 640 return; 641 642 PUSH_REFN (push, mt->base.bo, mt->base.domain | NOUVEAU_BO_WR); 643 644 if (clear_flags & PIPE_CLEAR_DEPTH) { 645 BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1); 646 PUSH_DATAf(push, depth); 647 mode |= NVC0_3D_CLEAR_BUFFERS_Z; 648 } 649 650 if (clear_flags & PIPE_CLEAR_STENCIL) { 651 BEGIN_NVC0(push, NVC0_3D(CLEAR_STENCIL), 1); 652 PUSH_DATA (push, stencil & 0xff); 653 mode |= NVC0_3D_CLEAR_BUFFERS_S; 654 } 655 656 BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); 657 PUSH_DATA (push, ( width << 16) | dstx); 658 PUSH_DATA (push, (height << 16) | dsty); 659 660 BEGIN_NVC0(push, NVC0_3D(ZETA_ADDRESS_HIGH), 5); 661 PUSH_DATAh(push, mt->base.address + sf->offset); 662 PUSH_DATA (push, mt->base.address + sf->offset); 663 PUSH_DATA (push, nvc0_format_table[dst->format].rt); 664 PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode); 665 PUSH_DATA (push, mt->layer_stride >> 2); 666 BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1); 667 PUSH_DATA (push, 1); 668 BEGIN_NVC0(push, NVC0_3D(ZETA_HORIZ), 3); 669 PUSH_DATA (push, sf->width); 670 PUSH_DATA (push, sf->height); 671 PUSH_DATA (push, (unk << 16) | (dst->u.tex.first_layer + sf->depth)); 672 BEGIN_NVC0(push, NVC0_3D(ZETA_BASE_LAYER), 1); 673 PUSH_DATA (push, dst->u.tex.first_layer); 674 IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), mt->ms_mode); 675 676 if (!render_condition_enabled) 677 IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS); 678 679 BEGIN_NIC0(push, NVC0_3D(CLEAR_BUFFERS), sf->depth); 680 for (z = 0; z < sf->depth; ++z) { 681 PUSH_DATA (push, mode | 682 (z << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 683 } 684 685 if (!render_condition_enabled) 686 IMMED_NVC0(push, NVC0_3D(COND_MODE), nvc0->cond_condmode); 687 688 nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER; 689} 690 691void 692nvc0_clear(struct pipe_context *pipe, unsigned buffers, 693 const struct pipe_scissor_state *scissor_state, 694 const union pipe_color_union *color, 695 double depth, unsigned stencil) 696{ 697 struct nvc0_context *nvc0 = nvc0_context(pipe); 698 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 699 struct pipe_framebuffer_state *fb = &nvc0->framebuffer; 700 unsigned i, j, k; 701 uint32_t mode = 0; 702 703 /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */ 704 if (!nvc0_state_validate_3d(nvc0, NVC0_NEW_3D_FRAMEBUFFER)) 705 return; 706 707 if (scissor_state) { 708 uint32_t minx = scissor_state->minx; 709 uint32_t maxx = MIN2(fb->width, scissor_state->maxx); 710 uint32_t miny = scissor_state->miny; 711 uint32_t maxy = MIN2(fb->height, scissor_state->maxy); 712 if (maxx <= minx || maxy <= miny) 713 return; 714 715 BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); 716 PUSH_DATA (push, minx | (maxx - minx) << 16); 717 PUSH_DATA (push, miny | (maxy - miny) << 16); 718 } 719 720 if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { 721 BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4); 722 PUSH_DATAf(push, color->f[0]); 723 PUSH_DATAf(push, color->f[1]); 724 PUSH_DATAf(push, color->f[2]); 725 PUSH_DATAf(push, color->f[3]); 726 if (buffers & PIPE_CLEAR_COLOR0) 727 mode = 728 NVC0_3D_CLEAR_BUFFERS_R | NVC0_3D_CLEAR_BUFFERS_G | 729 NVC0_3D_CLEAR_BUFFERS_B | NVC0_3D_CLEAR_BUFFERS_A; 730 } 731 732 if (buffers & PIPE_CLEAR_DEPTH) { 733 BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1); 734 PUSH_DATA (push, fui(depth)); 735 mode |= NVC0_3D_CLEAR_BUFFERS_Z; 736 } 737 738 if (buffers & PIPE_CLEAR_STENCIL) { 739 BEGIN_NVC0(push, NVC0_3D(CLEAR_STENCIL), 1); 740 PUSH_DATA (push, stencil & 0xff); 741 mode |= NVC0_3D_CLEAR_BUFFERS_S; 742 } 743 744 if (mode) { 745 int zs_layers = 0, color0_layers = 0; 746 if (fb->cbufs[0] && (mode & 0x3c)) 747 color0_layers = fb->cbufs[0]->u.tex.last_layer - 748 fb->cbufs[0]->u.tex.first_layer + 1; 749 if (fb->zsbuf && (mode & ~0x3c)) 750 zs_layers = fb->zsbuf->u.tex.last_layer - 751 fb->zsbuf->u.tex.first_layer + 1; 752 753 for (j = 0; j < MIN2(zs_layers, color0_layers); j++) { 754 BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1); 755 PUSH_DATA(push, mode | (j << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 756 } 757 for (k = j; k < zs_layers; k++) { 758 BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1); 759 PUSH_DATA(push, (mode & ~0x3c) | (k << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 760 } 761 for (k = j; k < color0_layers; k++) { 762 BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1); 763 PUSH_DATA(push, (mode & 0x3c) | (k << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 764 } 765 } 766 767 for (i = 1; i < fb->nr_cbufs; i++) { 768 struct pipe_surface *sf = fb->cbufs[i]; 769 if (!sf || !(buffers & (PIPE_CLEAR_COLOR0 << i))) 770 continue; 771 for (j = 0; j <= sf->u.tex.last_layer - sf->u.tex.first_layer; j++) { 772 BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1); 773 PUSH_DATA (push, (i << 6) | 0x3c | 774 (j << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 775 } 776 } 777 778 /* restore screen scissor */ 779 if (scissor_state) { 780 BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); 781 PUSH_DATA (push, fb->width << 16); 782 PUSH_DATA (push, fb->height << 16); 783 } 784} 785 786static void 787gm200_evaluate_depth_buffer(struct pipe_context *pipe) 788{ 789 struct nvc0_context *nvc0 = nvc0_context(pipe); 790 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 791 792 nvc0_state_validate_3d(nvc0, NVC0_NEW_3D_FRAMEBUFFER); 793 IMMED_NVC0(push, SUBC_3D(0x11fc), 1); 794} 795 796 797/* =============================== BLIT CODE =================================== 798 */ 799 800struct nvc0_blitter 801{ 802 struct nvc0_program *fp[NV50_BLIT_MAX_TEXTURE_TYPES][NV50_BLIT_MODES]; 803 struct nvc0_program *vp; 804 805 struct nv50_tsc_entry sampler[2]; /* nearest, bilinear */ 806 807 mtx_t mutex; 808 809 struct nvc0_screen *screen; 810}; 811 812struct nvc0_blitctx 813{ 814 struct nvc0_context *nvc0; 815 struct nvc0_program *fp; 816 struct nvc0_program *vp; 817 uint8_t mode; 818 uint16_t color_mask; 819 uint8_t filter; 820 uint8_t render_condition_enable; 821 enum pipe_texture_target target; 822 struct { 823 struct pipe_framebuffer_state fb; 824 struct nvc0_window_rect_stateobj window_rect; 825 struct nvc0_rasterizer_stateobj *rast; 826 struct nvc0_program *vp; 827 struct nvc0_program *tcp; 828 struct nvc0_program *tep; 829 struct nvc0_program *gp; 830 struct nvc0_program *fp; 831 unsigned num_textures[5]; 832 unsigned num_samplers[5]; 833 struct pipe_sampler_view *texture[2]; 834 struct nv50_tsc_entry *sampler[2]; 835 unsigned min_samples; 836 uint32_t dirty_3d; 837 } saved; 838 struct nvc0_rasterizer_stateobj rast; 839}; 840 841static void * 842nvc0_blitter_make_vp(struct pipe_context *pipe) 843{ 844 struct ureg_program *ureg; 845 struct ureg_src ipos, itex; 846 struct ureg_dst opos, otex; 847 848 ureg = ureg_create(PIPE_SHADER_VERTEX); 849 if (!ureg) 850 return NULL; 851 852 opos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 853 ipos = ureg_DECL_vs_input(ureg, 0); 854 otex = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); 855 itex = ureg_DECL_vs_input(ureg, 1); 856 857 ureg_MOV(ureg, ureg_writemask(opos, TGSI_WRITEMASK_XY ), ipos); 858 ureg_MOV(ureg, ureg_writemask(otex, TGSI_WRITEMASK_XYZ), itex); 859 ureg_END(ureg); 860 861 return ureg_create_shader_and_destroy(ureg, pipe); 862} 863 864static void 865nvc0_blitter_make_sampler(struct nvc0_blitter *blit) 866{ 867 /* clamp to edge, min/max lod = 0, nearest filtering */ 868 869 blit->sampler[0].id = -1; 870 871 blit->sampler[0].tsc[0] = G80_TSC_0_SRGB_CONVERSION | 872 (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_U__SHIFT) | 873 (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_V__SHIFT) | 874 (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_P__SHIFT); 875 blit->sampler[0].tsc[1] = 876 G80_TSC_1_MAG_FILTER_NEAREST | 877 G80_TSC_1_MIN_FILTER_NEAREST | 878 G80_TSC_1_MIP_FILTER_NONE; 879 880 /* clamp to edge, min/max lod = 0, bilinear filtering */ 881 882 blit->sampler[1].id = -1; 883 884 blit->sampler[1].tsc[0] = blit->sampler[0].tsc[0]; 885 blit->sampler[1].tsc[1] = 886 G80_TSC_1_MAG_FILTER_LINEAR | 887 G80_TSC_1_MIN_FILTER_LINEAR | 888 G80_TSC_1_MIP_FILTER_NONE; 889} 890 891static void 892nvc0_blit_select_vp(struct nvc0_blitctx *ctx) 893{ 894 struct nvc0_blitter *blitter = ctx->nvc0->screen->blitter; 895 896 if (!blitter->vp) { 897 mtx_lock(&blitter->mutex); 898 if (!blitter->vp) 899 blitter->vp = nvc0_blitter_make_vp(&ctx->nvc0->base.pipe); 900 mtx_unlock(&blitter->mutex); 901 } 902 ctx->vp = blitter->vp; 903} 904 905static void 906nvc0_blit_select_fp(struct nvc0_blitctx *ctx, const struct pipe_blit_info *info) 907{ 908 struct nvc0_blitter *blitter = ctx->nvc0->screen->blitter; 909 910 const enum pipe_texture_target ptarg = 911 nv50_blit_reinterpret_pipe_texture_target(info->src.resource->target); 912 913 const unsigned targ = nv50_blit_texture_type(ptarg); 914 const unsigned mode = ctx->mode; 915 916 if (!blitter->fp[targ][mode]) { 917 mtx_lock(&blitter->mutex); 918 if (!blitter->fp[targ][mode]) 919 blitter->fp[targ][mode] = 920 nv50_blitter_make_fp(&ctx->nvc0->base.pipe, mode, ptarg); 921 mtx_unlock(&blitter->mutex); 922 } 923 ctx->fp = blitter->fp[targ][mode]; 924} 925 926static void 927nvc0_blit_set_dst(struct nvc0_blitctx *ctx, 928 struct pipe_resource *res, unsigned level, unsigned layer, 929 enum pipe_format format) 930{ 931 struct nvc0_context *nvc0 = ctx->nvc0; 932 struct pipe_context *pipe = &nvc0->base.pipe; 933 struct pipe_surface templ; 934 935 if (util_format_is_depth_or_stencil(format)) 936 templ.format = nv50_blit_zeta_to_colour_format(format); 937 else 938 templ.format = format; 939 940 templ.u.tex.level = level; 941 templ.u.tex.first_layer = templ.u.tex.last_layer = layer; 942 943 if (layer == -1) { 944 templ.u.tex.first_layer = 0; 945 templ.u.tex.last_layer = 946 (res->target == PIPE_TEXTURE_3D ? res->depth0 : res->array_size) - 1; 947 } 948 949 nvc0->framebuffer.cbufs[0] = nvc0_miptree_surface_new(pipe, res, &templ); 950 nvc0->framebuffer.nr_cbufs = 1; 951 nvc0->framebuffer.zsbuf = NULL; 952 nvc0->framebuffer.width = nvc0->framebuffer.cbufs[0]->width; 953 nvc0->framebuffer.height = nvc0->framebuffer.cbufs[0]->height; 954} 955 956static void 957nvc0_blit_set_src(struct nvc0_blitctx *ctx, 958 struct pipe_resource *res, unsigned level, unsigned layer, 959 enum pipe_format format, const uint8_t filter) 960{ 961 struct nvc0_context *nvc0 = ctx->nvc0; 962 struct pipe_context *pipe = &nvc0->base.pipe; 963 struct pipe_sampler_view templ; 964 uint32_t flags; 965 unsigned s; 966 enum pipe_texture_target target; 967 968 target = nv50_blit_reinterpret_pipe_texture_target(res->target); 969 970 templ.target = target; 971 templ.format = format; 972 templ.u.tex.first_layer = templ.u.tex.last_layer = layer; 973 templ.u.tex.first_level = templ.u.tex.last_level = level; 974 templ.swizzle_r = PIPE_SWIZZLE_X; 975 templ.swizzle_g = PIPE_SWIZZLE_Y; 976 templ.swizzle_b = PIPE_SWIZZLE_Z; 977 templ.swizzle_a = PIPE_SWIZZLE_W; 978 979 if (layer == -1) { 980 templ.u.tex.first_layer = 0; 981 templ.u.tex.last_layer = 982 (res->target == PIPE_TEXTURE_3D ? res->depth0 : res->array_size) - 1; 983 } 984 985 flags = res->last_level ? 0 : NV50_TEXVIEW_SCALED_COORDS; 986 flags |= NV50_TEXVIEW_ACCESS_RESOLVE; 987 if (filter && res->nr_samples == 8) 988 flags |= NV50_TEXVIEW_FILTER_MSAA8; 989 990 nvc0->textures[4][0] = nvc0_create_texture_view( 991 pipe, res, &templ, flags); 992 nvc0->textures[4][1] = NULL; 993 994 for (s = 0; s <= 3; ++s) 995 nvc0->num_textures[s] = 0; 996 nvc0->num_textures[4] = 1; 997 998 templ.format = nv50_zs_to_s_format(format); 999 if (templ.format != format) { 1000 nvc0->textures[4][1] = nvc0_create_texture_view( 1001 pipe, res, &templ, flags); 1002 nvc0->num_textures[4] = 2; 1003 } 1004} 1005 1006static void 1007nvc0_blitctx_prepare_state(struct nvc0_blitctx *blit) 1008{ 1009 struct nouveau_pushbuf *push = blit->nvc0->base.pushbuf; 1010 1011 /* TODO: maybe make this a MACRO (if we need more logic) ? */ 1012 1013 if (blit->nvc0->cond_query && !blit->render_condition_enable) 1014 IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS); 1015 1016 /* blend state */ 1017 BEGIN_NVC0(push, NVC0_3D(COLOR_MASK(0)), 1); 1018 PUSH_DATA (push, blit->color_mask); 1019 IMMED_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 0); 1020 IMMED_NVC0(push, NVC0_3D(LOGIC_OP_ENABLE), 0); 1021 1022 /* rasterizer state */ 1023 IMMED_NVC0(push, NVC0_3D(FRAG_COLOR_CLAMP_EN), 0); 1024 IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_ENABLE), 0); 1025 BEGIN_NVC0(push, NVC0_3D(MSAA_MASK(0)), 4); 1026 PUSH_DATA (push, 0xffff); 1027 PUSH_DATA (push, 0xffff); 1028 PUSH_DATA (push, 0xffff); 1029 PUSH_DATA (push, 0xffff); 1030 BEGIN_NVC0(push, NVC0_3D(MACRO_POLYGON_MODE_FRONT), 1); 1031 PUSH_DATA (push, NVC0_3D_MACRO_POLYGON_MODE_FRONT_FILL); 1032 BEGIN_NVC0(push, NVC0_3D(MACRO_POLYGON_MODE_BACK), 1); 1033 PUSH_DATA (push, NVC0_3D_MACRO_POLYGON_MODE_BACK_FILL); 1034 IMMED_NVC0(push, NVC0_3D(POLYGON_SMOOTH_ENABLE), 0); 1035 IMMED_NVC0(push, NVC0_3D(POLYGON_OFFSET_FILL_ENABLE), 0); 1036 IMMED_NVC0(push, NVC0_3D(POLYGON_STIPPLE_ENABLE), 0); 1037 IMMED_NVC0(push, NVC0_3D(CULL_FACE_ENABLE), 0); 1038 1039 /* zsa state */ 1040 IMMED_NVC0(push, NVC0_3D(DEPTH_TEST_ENABLE), 0); 1041 IMMED_NVC0(push, NVC0_3D(DEPTH_BOUNDS_EN), 0); 1042 IMMED_NVC0(push, NVC0_3D(STENCIL_ENABLE), 0); 1043 IMMED_NVC0(push, NVC0_3D(ALPHA_TEST_ENABLE), 0); 1044 1045 /* disable transform feedback */ 1046 IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), 0); 1047} 1048 1049static void 1050nvc0_blitctx_pre_blit(struct nvc0_blitctx *ctx, 1051 const struct pipe_blit_info *info) 1052{ 1053 struct nvc0_context *nvc0 = ctx->nvc0; 1054 struct nvc0_blitter *blitter = nvc0->screen->blitter; 1055 int s; 1056 1057 ctx->saved.fb.width = nvc0->framebuffer.width; 1058 ctx->saved.fb.height = nvc0->framebuffer.height; 1059 ctx->saved.fb.samples = nvc0->framebuffer.samples; 1060 ctx->saved.fb.layers = nvc0->framebuffer.layers; 1061 ctx->saved.fb.nr_cbufs = nvc0->framebuffer.nr_cbufs; 1062 ctx->saved.fb.cbufs[0] = nvc0->framebuffer.cbufs[0]; 1063 ctx->saved.fb.zsbuf = nvc0->framebuffer.zsbuf; 1064 1065 ctx->saved.rast = nvc0->rast; 1066 1067 ctx->saved.vp = nvc0->vertprog; 1068 ctx->saved.tcp = nvc0->tctlprog; 1069 ctx->saved.tep = nvc0->tevlprog; 1070 ctx->saved.gp = nvc0->gmtyprog; 1071 ctx->saved.fp = nvc0->fragprog; 1072 1073 ctx->saved.min_samples = nvc0->min_samples; 1074 ctx->saved.window_rect = nvc0->window_rect; 1075 1076 nvc0->rast = &ctx->rast; 1077 1078 nvc0->vertprog = ctx->vp; 1079 nvc0->tctlprog = NULL; 1080 nvc0->tevlprog = NULL; 1081 nvc0->gmtyprog = NULL; 1082 nvc0->fragprog = ctx->fp; 1083 1084 nvc0->window_rect.rects = 1085 MIN2(info->num_window_rectangles, NVC0_MAX_WINDOW_RECTANGLES); 1086 nvc0->window_rect.inclusive = info->window_rectangle_include; 1087 if (nvc0->window_rect.rects) 1088 memcpy(nvc0->window_rect.rect, info->window_rectangles, 1089 sizeof(struct pipe_scissor_state) * nvc0->window_rect.rects); 1090 1091 for (s = 0; s <= 4; ++s) { 1092 ctx->saved.num_textures[s] = nvc0->num_textures[s]; 1093 ctx->saved.num_samplers[s] = nvc0->num_samplers[s]; 1094 nvc0->textures_dirty[s] = (1 << nvc0->num_textures[s]) - 1; 1095 nvc0->samplers_dirty[s] = (1 << nvc0->num_samplers[s]) - 1; 1096 } 1097 ctx->saved.texture[0] = nvc0->textures[4][0]; 1098 ctx->saved.texture[1] = nvc0->textures[4][1]; 1099 ctx->saved.sampler[0] = nvc0->samplers[4][0]; 1100 ctx->saved.sampler[1] = nvc0->samplers[4][1]; 1101 1102 nvc0->samplers[4][0] = &blitter->sampler[ctx->filter]; 1103 nvc0->samplers[4][1] = &blitter->sampler[ctx->filter]; 1104 1105 for (s = 0; s <= 3; ++s) 1106 nvc0->num_samplers[s] = 0; 1107 nvc0->num_samplers[4] = 2; 1108 1109 nvc0->min_samples = 1; 1110 1111 ctx->saved.dirty_3d = nvc0->dirty_3d; 1112 1113 nvc0->textures_dirty[4] |= 3; 1114 nvc0->samplers_dirty[4] |= 3; 1115 1116 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB); 1117 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(4, 0)); 1118 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(4, 1)); 1119 1120 nvc0->dirty_3d = NVC0_NEW_3D_FRAMEBUFFER | NVC0_NEW_3D_MIN_SAMPLES | 1121 NVC0_NEW_3D_VERTPROG | NVC0_NEW_3D_FRAGPROG | 1122 NVC0_NEW_3D_TCTLPROG | NVC0_NEW_3D_TEVLPROG | NVC0_NEW_3D_GMTYPROG | 1123 NVC0_NEW_3D_TEXTURES | NVC0_NEW_3D_SAMPLERS | NVC0_NEW_3D_WINDOW_RECTS; 1124} 1125 1126static void 1127nvc0_blitctx_post_blit(struct nvc0_blitctx *blit) 1128{ 1129 struct nvc0_context *nvc0 = blit->nvc0; 1130 int s; 1131 1132 pipe_surface_reference(&nvc0->framebuffer.cbufs[0], NULL); 1133 1134 nvc0->framebuffer.width = blit->saved.fb.width; 1135 nvc0->framebuffer.height = blit->saved.fb.height; 1136 nvc0->framebuffer.samples = blit->saved.fb.samples; 1137 nvc0->framebuffer.layers = blit->saved.fb.layers; 1138 nvc0->framebuffer.nr_cbufs = blit->saved.fb.nr_cbufs; 1139 nvc0->framebuffer.cbufs[0] = blit->saved.fb.cbufs[0]; 1140 nvc0->framebuffer.zsbuf = blit->saved.fb.zsbuf; 1141 1142 nvc0->rast = blit->saved.rast; 1143 1144 nvc0->vertprog = blit->saved.vp; 1145 nvc0->tctlprog = blit->saved.tcp; 1146 nvc0->tevlprog = blit->saved.tep; 1147 nvc0->gmtyprog = blit->saved.gp; 1148 nvc0->fragprog = blit->saved.fp; 1149 1150 nvc0->min_samples = blit->saved.min_samples; 1151 nvc0->window_rect = blit->saved.window_rect; 1152 1153 pipe_sampler_view_reference(&nvc0->textures[4][0], NULL); 1154 pipe_sampler_view_reference(&nvc0->textures[4][1], NULL); 1155 1156 for (s = 0; s <= 4; ++s) { 1157 nvc0->num_textures[s] = blit->saved.num_textures[s]; 1158 nvc0->num_samplers[s] = blit->saved.num_samplers[s]; 1159 nvc0->textures_dirty[s] = (1 << nvc0->num_textures[s]) - 1; 1160 nvc0->samplers_dirty[s] = (1 << nvc0->num_samplers[s]) - 1; 1161 } 1162 nvc0->textures[4][0] = blit->saved.texture[0]; 1163 nvc0->textures[4][1] = blit->saved.texture[1]; 1164 nvc0->samplers[4][0] = blit->saved.sampler[0]; 1165 nvc0->samplers[4][1] = blit->saved.sampler[1]; 1166 1167 nvc0->textures_dirty[4] |= 3; 1168 nvc0->samplers_dirty[4] |= 3; 1169 1170 if (nvc0->cond_query && !blit->render_condition_enable) 1171 nvc0->base.pipe.render_condition(&nvc0->base.pipe, nvc0->cond_query, 1172 nvc0->cond_cond, nvc0->cond_mode); 1173 1174 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX_TMP); 1175 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEXT); 1176 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB); 1177 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(4, 0)); 1178 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(4, 1)); 1179 nouveau_scratch_done(&nvc0->base); 1180 1181 nvc0->dirty_3d = blit->saved.dirty_3d | 1182 (NVC0_NEW_3D_FRAMEBUFFER | NVC0_NEW_3D_SCISSOR | NVC0_NEW_3D_SAMPLE_MASK | 1183 NVC0_NEW_3D_RASTERIZER | NVC0_NEW_3D_ZSA | NVC0_NEW_3D_BLEND | 1184 NVC0_NEW_3D_VIEWPORT | NVC0_NEW_3D_WINDOW_RECTS | 1185 NVC0_NEW_3D_TEXTURES | NVC0_NEW_3D_SAMPLERS | 1186 NVC0_NEW_3D_VERTPROG | NVC0_NEW_3D_FRAGPROG | 1187 NVC0_NEW_3D_TCTLPROG | NVC0_NEW_3D_TEVLPROG | NVC0_NEW_3D_GMTYPROG | 1188 NVC0_NEW_3D_TFB_TARGETS | NVC0_NEW_3D_VERTEX | NVC0_NEW_3D_ARRAYS); 1189 nvc0->scissors_dirty |= 1; 1190 nvc0->viewports_dirty |= 1; 1191 1192 nvc0->base.pipe.set_min_samples(&nvc0->base.pipe, blit->saved.min_samples); 1193} 1194 1195static void 1196nvc0_blit_3d(struct nvc0_context *nvc0, const struct pipe_blit_info *info) 1197{ 1198 struct nvc0_screen *screen = nvc0->screen; 1199 struct nvc0_blitctx *blit = nvc0->blit; 1200 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 1201 struct pipe_resource *src = info->src.resource; 1202 struct pipe_resource *dst = info->dst.resource; 1203 struct nouveau_bo *vtxbuf_bo; 1204 uint32_t stride, length, *vbuf; 1205 uint64_t vtxbuf; 1206 int32_t minx, maxx, miny, maxy; 1207 int32_t i, n; 1208 float x0, x1, y0, y1, z; 1209 float dz; 1210 float x_range, y_range; 1211 1212 blit->mode = nv50_blit_select_mode(info); 1213 blit->color_mask = nv50_blit_derive_color_mask(info); 1214 blit->filter = nv50_blit_get_filter(info); 1215 blit->render_condition_enable = info->render_condition_enable; 1216 1217 nvc0_blit_select_vp(blit); 1218 nvc0_blit_select_fp(blit, info); 1219 nvc0_blitctx_pre_blit(blit, info); 1220 1221 nvc0_blit_set_dst(blit, dst, info->dst.level, -1, info->dst.format); 1222 nvc0_blit_set_src(blit, src, info->src.level, -1, info->src.format, 1223 blit->filter); 1224 1225 nvc0_blitctx_prepare_state(blit); 1226 1227 nvc0_state_validate_3d(nvc0, ~0); 1228 1229 x_range = (float)info->src.box.width / (float)info->dst.box.width; 1230 y_range = (float)info->src.box.height / (float)info->dst.box.height; 1231 1232 x0 = (float)info->src.box.x - x_range * (float)info->dst.box.x; 1233 y0 = (float)info->src.box.y - y_range * (float)info->dst.box.y; 1234 1235 x1 = x0 + 32768.0f * x_range; 1236 y1 = y0 + 32768.0f * y_range; 1237 1238 x0 *= (float)(1 << nv50_miptree(src)->ms_x); 1239 x1 *= (float)(1 << nv50_miptree(src)->ms_x); 1240 y0 *= (float)(1 << nv50_miptree(src)->ms_y); 1241 y1 *= (float)(1 << nv50_miptree(src)->ms_y); 1242 1243 dz = (float)info->src.box.depth / (float)info->dst.box.depth; 1244 z = (float)info->src.box.z; 1245 if (nv50_miptree(src)->layout_3d) 1246 z += 0.5f * dz; 1247 1248 if (src->last_level > 0) { 1249 /* If there are mip maps, GPU always assumes normalized coordinates. */ 1250 const unsigned l = info->src.level; 1251 const float fh = u_minify(src->width0 << nv50_miptree(src)->ms_x, l); 1252 const float fv = u_minify(src->height0 << nv50_miptree(src)->ms_y, l); 1253 x0 /= fh; 1254 x1 /= fh; 1255 y0 /= fv; 1256 y1 /= fv; 1257 if (nv50_miptree(src)->layout_3d) { 1258 z /= u_minify(src->depth0, l); 1259 dz /= u_minify(src->depth0, l); 1260 } 1261 } 1262 1263 bool serialize = false; 1264 struct nv50_miptree *mt = nv50_miptree(dst); 1265 if (screen->eng3d->oclass >= TU102_3D_CLASS) { 1266 IMMED_NVC0(push, SUBC_3D(TU102_3D_SET_COLOR_RENDER_TO_ZETA_SURFACE), 1267 util_format_is_depth_or_stencil(info->dst.format)); 1268 } else { 1269 /* When flipping a surface from zeta <-> color "mode", we have to wait for 1270 * the GPU to flush its current draws. 1271 */ 1272 serialize = util_format_is_depth_or_stencil(info->dst.format); 1273 if (serialize && mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 1274 IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); 1275 } 1276 } 1277 1278 IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 0); 1279 IMMED_NVC0(push, NVC0_3D(VIEW_VOLUME_CLIP_CTRL), 0x2 | 1280 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_RANGE_0_1); 1281 BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(0)), 2); 1282 PUSH_DATA (push, nvc0->framebuffer.width << 16); 1283 PUSH_DATA (push, nvc0->framebuffer.height << 16); 1284 1285 /* Draw a large triangle in screen coordinates covering the whole 1286 * render target, with scissors defining the destination region. 1287 * The vertex is supplied with non-normalized texture coordinates 1288 * arranged in a way to yield the desired offset and scale. 1289 * 1290 * Note that while the source texture is presented to the sampler as 1291 * non-MSAA (even if it is), the destination texture is treated as MSAA for 1292 * rendering. This means that 1293 * - destination coordinates shouldn't be scaled 1294 * - without per-sample rendering, the target will be a solid-fill for all 1295 * of the samples 1296 * 1297 * The last point implies that this process is very bad for 1:1 blits, as 1298 * well as scaled blits between MSAA surfaces. This works fine for 1299 * upscaling and downscaling though. The 1:1 blits should ideally be 1300 * handled by the 2d engine, which can do it perfectly. 1301 */ 1302 1303 minx = info->dst.box.x; 1304 maxx = info->dst.box.x + info->dst.box.width; 1305 miny = info->dst.box.y; 1306 maxy = info->dst.box.y + info->dst.box.height; 1307 if (info->scissor_enable) { 1308 minx = MAX2(minx, info->scissor.minx); 1309 maxx = MIN2(maxx, info->scissor.maxx); 1310 miny = MAX2(miny, info->scissor.miny); 1311 maxy = MIN2(maxy, info->scissor.maxy); 1312 } 1313 BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2); 1314 PUSH_DATA (push, (maxx << 16) | minx); 1315 PUSH_DATA (push, (maxy << 16) | miny); 1316 1317 stride = (3 + 2) * 4; 1318 length = stride * 3 * info->dst.box.depth; 1319 1320 vbuf = nouveau_scratch_get(&nvc0->base, length, &vtxbuf, &vtxbuf_bo); 1321 if (!vbuf) { 1322 assert(vbuf); 1323 return; 1324 } 1325 1326 BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, 1327 NOUVEAU_BO_GART | NOUVEAU_BO_RD, vtxbuf_bo); 1328 BCTX_REFN_bo(nvc0->bufctx_3d, 3D_TEXT, 1329 NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD, screen->text); 1330 nouveau_pushbuf_validate(push); 1331 1332 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(0)), 4); 1333 PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | stride << 1334 NVC0_3D_VERTEX_ARRAY_FETCH_STRIDE__SHIFT); 1335 PUSH_DATAh(push, vtxbuf); 1336 PUSH_DATA (push, vtxbuf); 1337 PUSH_DATA (push, 0); 1338 if (screen->eng3d->oclass < TU102_3D_CLASS) 1339 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(0)), 2); 1340 else 1341 BEGIN_NVC0(push, SUBC_3D(TU102_3D_VERTEX_ARRAY_LIMIT_HIGH(0)), 2); 1342 PUSH_DATAh(push, vtxbuf + length - 1); 1343 PUSH_DATA (push, vtxbuf + length - 1); 1344 1345 n = MAX2(2, nvc0->state.num_vtxelts); 1346 1347 BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), n); 1348 PUSH_DATA (push, NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT | 1349 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32_32 | 0x00 << 1350 NVC0_3D_VERTEX_ATTRIB_FORMAT_OFFSET__SHIFT); 1351 PUSH_DATA (push, NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT | 1352 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32_32_32 | 0x08 << 1353 NVC0_3D_VERTEX_ATTRIB_FORMAT_OFFSET__SHIFT); 1354 for (i = 2; i < n; i++) { 1355 PUSH_DATA(push, NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT | 1356 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32 | 1357 NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST); 1358 } 1359 for (i = 1; i < n; ++i) 1360 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 1361 if (nvc0->state.instance_elts) { 1362 nvc0->state.instance_elts = 0; 1363 BEGIN_NVC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_PER_INSTANCE), 2); 1364 PUSH_DATA (push, n); 1365 PUSH_DATA (push, 0); 1366 } 1367 nvc0->state.num_vtxelts = 2; 1368 1369 if (nvc0->state.prim_restart) { 1370 IMMED_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 0); 1371 nvc0->state.prim_restart = 0; 1372 } 1373 1374 if (nvc0->state.index_bias) { 1375 IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0); 1376 IMMED_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 0); 1377 nvc0->state.index_bias = 0; 1378 } 1379 1380 for (i = 0; i < info->dst.box.depth; ++i, z += dz) { 1381 if (info->dst.box.z + i) { 1382 BEGIN_NVC0(push, NVC0_3D(LAYER), 1); 1383 PUSH_DATA (push, info->dst.box.z + i); 1384 } 1385 1386 *(vbuf++) = fui(0.0f); 1387 *(vbuf++) = fui(0.0f); 1388 *(vbuf++) = fui(x0); 1389 *(vbuf++) = fui(y0); 1390 *(vbuf++) = fui(z); 1391 1392 *(vbuf++) = fui(32768.0f); 1393 *(vbuf++) = fui(0.0f); 1394 *(vbuf++) = fui(x1); 1395 *(vbuf++) = fui(y0); 1396 *(vbuf++) = fui(z); 1397 1398 *(vbuf++) = fui(0.0f); 1399 *(vbuf++) = fui(32768.0f); 1400 *(vbuf++) = fui(x0); 1401 *(vbuf++) = fui(y1); 1402 *(vbuf++) = fui(z); 1403 1404 IMMED_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1405 NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES); 1406 BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2); 1407 PUSH_DATA (push, i * 3); 1408 PUSH_DATA (push, 3); 1409 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 1410 } 1411 if (info->dst.box.z + info->dst.box.depth - 1) 1412 IMMED_NVC0(push, NVC0_3D(LAYER), 0); 1413 1414 nvc0_blitctx_post_blit(blit); 1415 1416 /* restore viewport transform */ 1417 IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 1); 1418 if (screen->eng3d->oclass >= TU102_3D_CLASS) 1419 IMMED_NVC0(push, SUBC_3D(TU102_3D_SET_COLOR_RENDER_TO_ZETA_SURFACE), 0); 1420 else if (serialize) 1421 /* mark the surface as reading, which will force a serialize next time 1422 * it's used for writing. 1423 */ 1424 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_READING; 1425} 1426 1427static void 1428nvc0_blit_eng2d(struct nvc0_context *nvc0, const struct pipe_blit_info *info) 1429{ 1430 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 1431 struct nv50_miptree *dst = nv50_miptree(info->dst.resource); 1432 struct nv50_miptree *src = nv50_miptree(info->src.resource); 1433 const int32_t srcx_adj = info->src.box.width < 0 ? -1 : 0; 1434 const int32_t srcy_adj = info->src.box.height < 0 ? -1 : 0; 1435 const int dz = info->dst.box.z; 1436 const int sz = info->src.box.z; 1437 uint32_t dstw, dsth; 1438 int32_t dstx, dsty; 1439 int64_t srcx, srcy; 1440 int64_t du_dx, dv_dy; 1441 int i; 1442 uint32_t mode; 1443 uint32_t mask = nv50_blit_eng2d_get_mask(info); 1444 bool b; 1445 1446 mode = nv50_blit_get_filter(info) ? 1447 NV50_2D_BLIT_CONTROL_FILTER_BILINEAR : 1448 NV50_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE; 1449 mode |= (src->base.base.nr_samples > dst->base.base.nr_samples) ? 1450 NV50_2D_BLIT_CONTROL_ORIGIN_CORNER : NV50_2D_BLIT_CONTROL_ORIGIN_CENTER; 1451 1452 du_dx = ((int64_t)info->src.box.width << 32) / info->dst.box.width; 1453 dv_dy = ((int64_t)info->src.box.height << 32) / info->dst.box.height; 1454 1455 b = info->dst.format == info->src.format; 1456 nvc0_2d_texture_set(push, 1, dst, info->dst.level, dz, info->dst.format, b); 1457 nvc0_2d_texture_set(push, 0, src, info->src.level, sz, info->src.format, b); 1458 1459 if (info->scissor_enable) { 1460 BEGIN_NVC0(push, NVC0_2D(CLIP_X), 5); 1461 PUSH_DATA (push, info->scissor.minx << dst->ms_x); 1462 PUSH_DATA (push, info->scissor.miny << dst->ms_y); 1463 PUSH_DATA (push, (info->scissor.maxx - info->scissor.minx) << dst->ms_x); 1464 PUSH_DATA (push, (info->scissor.maxy - info->scissor.miny) << dst->ms_y); 1465 PUSH_DATA (push, 1); /* enable */ 1466 } 1467 1468 if (nvc0->cond_query && info->render_condition_enable) 1469 IMMED_NVC0(push, NVC0_2D(COND_MODE), nvc0->cond_condmode); 1470 1471 if (mask != 0xffffffff) { 1472 IMMED_NVC0(push, NVC0_2D(ROP), 0xca); /* DPSDxax */ 1473 IMMED_NVC0(push, NVC0_2D(PATTERN_COLOR_FORMAT), 1474 NV50_2D_PATTERN_COLOR_FORMAT_A8R8G8B8); 1475 BEGIN_NVC0(push, NVC0_2D(PATTERN_BITMAP_COLOR(0)), 4); 1476 PUSH_DATA (push, 0x00000000); 1477 PUSH_DATA (push, mask); 1478 PUSH_DATA (push, 0xffffffff); 1479 PUSH_DATA (push, 0xffffffff); 1480 IMMED_NVC0(push, NVC0_2D(OPERATION), NV50_2D_OPERATION_ROP); 1481 } else 1482 if (info->src.format != info->dst.format) { 1483 if (info->src.format == PIPE_FORMAT_R8_UNORM || 1484 info->src.format == PIPE_FORMAT_R8_SNORM || 1485 info->src.format == PIPE_FORMAT_R16_UNORM || 1486 info->src.format == PIPE_FORMAT_R16_SNORM || 1487 info->src.format == PIPE_FORMAT_R16_FLOAT || 1488 info->src.format == PIPE_FORMAT_R32_FLOAT) { 1489 mask = 0xffff0000; /* also makes condition for OPERATION reset true */ 1490 BEGIN_NVC0(push, NVC0_2D(BETA4), 2); 1491 PUSH_DATA (push, mask); 1492 PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY_PREMULT); 1493 } else 1494 if (info->src.format == PIPE_FORMAT_A8_UNORM) { 1495 mask = 0xff000000; 1496 BEGIN_NVC0(push, NVC0_2D(BETA4), 2); 1497 PUSH_DATA (push, mask); 1498 PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY_PREMULT); 1499 } 1500 } 1501 1502 if (src->ms_x > dst->ms_x || src->ms_y > dst->ms_y) { 1503 /* ms_x is always >= ms_y */ 1504 du_dx <<= src->ms_x - dst->ms_x; 1505 dv_dy <<= src->ms_y - dst->ms_y; 1506 } else { 1507 du_dx >>= dst->ms_x - src->ms_x; 1508 dv_dy >>= dst->ms_y - src->ms_y; 1509 } 1510 1511 srcx = (int64_t)(info->src.box.x + srcx_adj) << (src->ms_x + 32); 1512 srcy = (int64_t)(info->src.box.y + srcy_adj) << (src->ms_y + 32); 1513 1514 if (src->base.base.nr_samples > dst->base.base.nr_samples) { 1515 /* center src coorinates for proper MS resolve filtering */ 1516 srcx += (int64_t)1 << (src->ms_x + 31); 1517 srcy += (int64_t)1 << (src->ms_y + 31); 1518 } 1519 1520 dstx = info->dst.box.x << dst->ms_x; 1521 dsty = info->dst.box.y << dst->ms_y; 1522 1523 dstw = info->dst.box.width << dst->ms_x; 1524 dsth = info->dst.box.height << dst->ms_y; 1525 1526 if (dstx < 0) { 1527 dstw += dstx; 1528 srcx -= du_dx * dstx; 1529 dstx = 0; 1530 } 1531 if (dsty < 0) { 1532 dsth += dsty; 1533 srcy -= dv_dy * dsty; 1534 dsty = 0; 1535 } 1536 1537 IMMED_NVC0(push, NVC0_2D(BLIT_CONTROL), mode); 1538 BEGIN_NVC0(push, NVC0_2D(BLIT_DST_X), 4); 1539 PUSH_DATA (push, dstx); 1540 PUSH_DATA (push, dsty); 1541 PUSH_DATA (push, dstw); 1542 PUSH_DATA (push, dsth); 1543 BEGIN_NVC0(push, NVC0_2D(BLIT_DU_DX_FRACT), 4); 1544 PUSH_DATA (push, du_dx); 1545 PUSH_DATA (push, du_dx >> 32); 1546 PUSH_DATA (push, dv_dy); 1547 PUSH_DATA (push, dv_dy >> 32); 1548 1549 BCTX_REFN(nvc0->bufctx, 2D, &dst->base, WR); 1550 BCTX_REFN(nvc0->bufctx, 2D, &src->base, RD); 1551 nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx); 1552 if (nouveau_pushbuf_validate(nvc0->base.pushbuf)) 1553 return; 1554 1555 for (i = 0; i < info->dst.box.depth; ++i) { 1556 if (i > 0) { 1557 /* no scaling in z-direction possible for eng2d blits */ 1558 if (dst->layout_3d) { 1559 BEGIN_NVC0(push, NVC0_2D(DST_LAYER), 1); 1560 PUSH_DATA (push, info->dst.box.z + i); 1561 } else { 1562 const unsigned z = info->dst.box.z + i; 1563 const uint64_t address = dst->base.address + 1564 dst->level[info->dst.level].offset + 1565 z * dst->layer_stride; 1566 BEGIN_NVC0(push, NVC0_2D(DST_ADDRESS_HIGH), 2); 1567 PUSH_DATAh(push, address); 1568 PUSH_DATA (push, address); 1569 } 1570 if (src->layout_3d) { 1571 /* not possible because of depth tiling */ 1572 assert(0); 1573 } else { 1574 const unsigned z = info->src.box.z + i; 1575 const uint64_t address = src->base.address + 1576 src->level[info->src.level].offset + 1577 z * src->layer_stride; 1578 BEGIN_NVC0(push, NVC0_2D(SRC_ADDRESS_HIGH), 2); 1579 PUSH_DATAh(push, address); 1580 PUSH_DATA (push, address); 1581 } 1582 BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_Y_INT), 1); /* trigger */ 1583 PUSH_DATA (push, srcy >> 32); 1584 } else { 1585 BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_X_FRACT), 4); 1586 PUSH_DATA (push, srcx); 1587 PUSH_DATA (push, srcx >> 32); 1588 PUSH_DATA (push, srcy); 1589 PUSH_DATA (push, srcy >> 32); 1590 } 1591 } 1592 nvc0_resource_validate(&dst->base, NOUVEAU_BO_WR); 1593 nvc0_resource_validate(&src->base, NOUVEAU_BO_RD); 1594 1595 nouveau_bufctx_reset(nvc0->bufctx, NVC0_BIND_2D); 1596 1597 if (info->scissor_enable) 1598 IMMED_NVC0(push, NVC0_2D(CLIP_ENABLE), 0); 1599 if (mask != 0xffffffff) 1600 IMMED_NVC0(push, NVC0_2D(OPERATION), NV50_2D_OPERATION_SRCCOPY); 1601 if (nvc0->cond_query && info->render_condition_enable) 1602 IMMED_NVC0(push, NVC0_2D(COND_MODE), NV50_2D_COND_MODE_ALWAYS); 1603} 1604 1605static void 1606nvc0_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) 1607{ 1608 struct nvc0_context *nvc0 = nvc0_context(pipe); 1609 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 1610 bool eng3d = false; 1611 1612 if (info->src.box.width == 0 || info->src.box.height == 0 || 1613 info->dst.box.width == 0 || info->dst.box.height == 0) { 1614 util_debug_message(&nvc0->base.debug, ERROR, 1615 "Blit with zero-size src or dst box"); 1616 return; 1617 } 1618 1619 if (util_format_is_depth_or_stencil(info->dst.resource->format)) { 1620 if (!(info->mask & PIPE_MASK_ZS)) 1621 return; 1622 if (info->dst.resource->format == PIPE_FORMAT_Z32_FLOAT || 1623 info->dst.resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) 1624 eng3d = true; 1625 if (info->filter != PIPE_TEX_FILTER_NEAREST) 1626 eng3d = true; 1627 } else { 1628 if (!(info->mask & PIPE_MASK_RGBA)) 1629 return; 1630 if (info->mask != PIPE_MASK_RGBA) 1631 eng3d = true; 1632 } 1633 1634 if (nv50_miptree(info->src.resource)->layout_3d) { 1635 eng3d = true; 1636 } else 1637 if (info->src.box.depth != info->dst.box.depth) { 1638 eng3d = true; 1639 debug_printf("blit: cannot filter array or cube textures in z direction"); 1640 } 1641 1642 if (!eng3d && info->dst.format != info->src.format) { 1643 if (!nv50_2d_dst_format_faithful(info->dst.format)) { 1644 eng3d = true; 1645 } else 1646 if (!nv50_2d_src_format_faithful(info->src.format)) { 1647 if (!util_format_is_luminance(info->src.format)) { 1648 if (!nv50_2d_dst_format_ops_supported(info->dst.format)) 1649 eng3d = true; 1650 else 1651 if (util_format_is_intensity(info->src.format)) 1652 eng3d = info->src.format != PIPE_FORMAT_I8_UNORM; 1653 else 1654 if (util_format_is_alpha(info->src.format)) 1655 eng3d = info->src.format != PIPE_FORMAT_A8_UNORM; 1656 else 1657 if (util_format_is_srgb(info->dst.format) && 1658 util_format_get_nr_components(info->src.format) == 1) 1659 eng3d = true; 1660 else 1661 eng3d = !nv50_2d_format_supported(info->src.format); 1662 } 1663 } else 1664 if (util_format_is_luminance_alpha(info->src.format)) 1665 eng3d = true; 1666 } 1667 1668 if (info->src.resource->nr_samples == 8 && 1669 info->dst.resource->nr_samples <= 1) 1670 eng3d = true; 1671#if 0 1672 /* FIXME: can't make this work with eng2d anymore, at least not on nv50 */ 1673 if (info->src.resource->nr_samples > 1 || 1674 info->dst.resource->nr_samples > 1) 1675 eng3d = true; 1676#endif 1677 /* FIXME: find correct src coordinates adjustments */ 1678 if ((info->src.box.width != info->dst.box.width && 1679 info->src.box.width != -info->dst.box.width) || 1680 (info->src.box.height != info->dst.box.height && 1681 info->src.box.height != -info->dst.box.height)) 1682 eng3d = true; 1683 1684 if (info->num_window_rectangles > 0 || info->window_rectangle_include) 1685 eng3d = true; 1686 1687 if (nvc0->screen->num_occlusion_queries_active) 1688 IMMED_NVC0(push, NVC0_3D(SAMPLECNT_ENABLE), 0); 1689 1690 if (!eng3d) 1691 nvc0_blit_eng2d(nvc0, info); 1692 else 1693 nvc0_blit_3d(nvc0, info); 1694 1695 if (nvc0->screen->num_occlusion_queries_active) 1696 IMMED_NVC0(push, NVC0_3D(SAMPLECNT_ENABLE), 1); 1697 1698 NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_blit_count, 1); 1699} 1700 1701static void 1702nvc0_flush_resource(struct pipe_context *ctx, 1703 struct pipe_resource *resource) 1704{ 1705} 1706 1707bool 1708nvc0_blitter_create(struct nvc0_screen *screen) 1709{ 1710 screen->blitter = CALLOC_STRUCT(nvc0_blitter); 1711 if (!screen->blitter) { 1712 NOUVEAU_ERR("failed to allocate blitter struct\n"); 1713 return false; 1714 } 1715 screen->blitter->screen = screen; 1716 1717 (void) mtx_init(&screen->blitter->mutex, mtx_plain); 1718 1719 nvc0_blitter_make_sampler(screen->blitter); 1720 1721 return true; 1722} 1723 1724void 1725nvc0_blitter_destroy(struct nvc0_screen *screen) 1726{ 1727 struct nvc0_blitter *blitter = screen->blitter; 1728 unsigned i, m; 1729 1730 for (i = 0; i < NV50_BLIT_MAX_TEXTURE_TYPES; ++i) { 1731 for (m = 0; m < NV50_BLIT_MODES; ++m) { 1732 struct nvc0_program *prog = blitter->fp[i][m]; 1733 if (prog) { 1734 nvc0_program_destroy(NULL, prog); 1735 FREE((void *)prog->pipe.tokens); 1736 FREE(prog); 1737 } 1738 } 1739 } 1740 1741 mtx_destroy(&blitter->mutex); 1742 FREE(blitter); 1743} 1744 1745bool 1746nvc0_blitctx_create(struct nvc0_context *nvc0) 1747{ 1748 nvc0->blit = CALLOC_STRUCT(nvc0_blitctx); 1749 if (!nvc0->blit) { 1750 NOUVEAU_ERR("failed to allocate blit context\n"); 1751 return false; 1752 } 1753 1754 nvc0->blit->nvc0 = nvc0; 1755 1756 nvc0->blit->rast.pipe.half_pixel_center = 1; 1757 1758 return true; 1759} 1760 1761void 1762nvc0_blitctx_destroy(struct nvc0_context *nvc0) 1763{ 1764 FREE(nvc0->blit); 1765} 1766 1767void 1768nvc0_init_surface_functions(struct nvc0_context *nvc0) 1769{ 1770 struct pipe_context *pipe = &nvc0->base.pipe; 1771 1772 pipe->resource_copy_region = nvc0_resource_copy_region; 1773 pipe->blit = nvc0_blit; 1774 pipe->flush_resource = nvc0_flush_resource; 1775 pipe->clear_render_target = nvc0_clear_render_target; 1776 pipe->clear_depth_stencil = nvc0_clear_depth_stencil; 1777 pipe->clear_texture = nv50_clear_texture; 1778 pipe->clear_buffer = nvc0_clear_buffer; 1779 if (nvc0->screen->base.class_3d >= GM200_3D_CLASS) 1780 pipe->evaluate_depth_buffer = gm200_evaluate_depth_buffer; 1781} 1782