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_math.h" 31#include "util/u_surface.h" 32 33#include "tgsi/tgsi_ureg.h" 34 35#include "os/os_thread.h" 36 37#include "nv50/nv50_context.h" 38#include "nv50/nv50_resource.h" 39 40#include "nv50/g80_defs.xml.h" 41#include "nv50/g80_texture.xml.h" 42 43/* these are used in nv50_blit.h */ 44#define NV50_ENG2D_SUPPORTED_FORMATS 0xff0843e080608409ULL 45#define NV50_ENG2D_NOCONVERT_FORMATS 0x0008402000000000ULL 46#define NV50_ENG2D_LUMINANCE_FORMATS 0x0008402000000000ULL 47#define NV50_ENG2D_INTENSITY_FORMATS 0x0000000000000000ULL 48#define NV50_ENG2D_OPERATION_FORMATS 0x060001c000608000ULL 49 50#define NOUVEAU_DRIVER 0x50 51#include "nv50/nv50_blit.h" 52 53static inline uint8_t 54nv50_2d_format(enum pipe_format format, bool dst, bool dst_src_equal) 55{ 56 uint8_t id = nv50_format_table[format].rt; 57 58 /* Hardware values for color formats range from 0xc0 to 0xff, 59 * but the 2D engine doesn't support all of them. 60 */ 61 if ((id >= 0xc0) && (NV50_ENG2D_SUPPORTED_FORMATS & (1ULL << (id - 0xc0)))) 62 return id; 63 assert(dst_src_equal); 64 65 switch (util_format_get_blocksize(format)) { 66 case 1: 67 return G80_SURFACE_FORMAT_R8_UNORM; 68 case 2: 69 return G80_SURFACE_FORMAT_R16_UNORM; 70 case 4: 71 return G80_SURFACE_FORMAT_BGRA8_UNORM; 72 case 8: 73 return G80_SURFACE_FORMAT_RGBA16_FLOAT; 74 case 16: 75 return G80_SURFACE_FORMAT_RGBA32_FLOAT; 76 default: 77 return 0; 78 } 79} 80 81static int 82nv50_2d_texture_set(struct nouveau_pushbuf *push, int dst, 83 struct nv50_miptree *mt, unsigned level, unsigned layer, 84 enum pipe_format pformat, bool dst_src_pformat_equal) 85{ 86 struct nouveau_bo *bo = mt->base.bo; 87 uint32_t width, height, depth; 88 uint32_t format; 89 uint32_t mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT; 90 uint32_t offset = mt->level[level].offset; 91 92 format = nv50_2d_format(pformat, dst, dst_src_pformat_equal); 93 if (!format) { 94 NOUVEAU_ERR("invalid/unsupported surface format: %s\n", 95 util_format_name(pformat)); 96 return 1; 97 } 98 99 width = u_minify(mt->base.base.width0, level) << mt->ms_x; 100 height = u_minify(mt->base.base.height0, level) << mt->ms_y; 101 depth = u_minify(mt->base.base.depth0, level); 102 103 offset = mt->level[level].offset; 104 if (!mt->layout_3d) { 105 offset += mt->layer_stride * layer; 106 depth = 1; 107 layer = 0; 108 } else 109 if (!dst) { 110 offset += nv50_mt_zslice_offset(mt, level, layer); 111 layer = 0; 112 } 113 114 if (!nouveau_bo_memtype(bo)) { 115 BEGIN_NV04(push, SUBC_2D(mthd), 2); 116 PUSH_DATA (push, format); 117 PUSH_DATA (push, 1); 118 BEGIN_NV04(push, SUBC_2D(mthd + 0x14), 5); 119 PUSH_DATA (push, mt->level[level].pitch); 120 PUSH_DATA (push, width); 121 PUSH_DATA (push, height); 122 PUSH_DATAh(push, mt->base.address + offset); 123 PUSH_DATA (push, mt->base.address + offset); 124 } else { 125 BEGIN_NV04(push, SUBC_2D(mthd), 5); 126 PUSH_DATA (push, format); 127 PUSH_DATA (push, 0); 128 PUSH_DATA (push, mt->level[level].tile_mode); 129 PUSH_DATA (push, depth); 130 PUSH_DATA (push, layer); 131 BEGIN_NV04(push, SUBC_2D(mthd + 0x18), 4); 132 PUSH_DATA (push, width); 133 PUSH_DATA (push, height); 134 PUSH_DATAh(push, mt->base.address + offset); 135 PUSH_DATA (push, mt->base.address + offset); 136 } 137 138#if 0 139 if (dst) { 140 BEGIN_NV04(push, SUBC_2D(NV50_2D_CLIP_X), 4); 141 PUSH_DATA (push, 0); 142 PUSH_DATA (push, 0); 143 PUSH_DATA (push, width); 144 PUSH_DATA (push, height); 145 } 146#endif 147 return 0; 148} 149 150static int 151nv50_2d_texture_do_copy(struct nouveau_pushbuf *push, 152 struct nv50_miptree *dst, unsigned dst_level, 153 unsigned dx, unsigned dy, unsigned dz, 154 struct nv50_miptree *src, unsigned src_level, 155 unsigned sx, unsigned sy, unsigned sz, 156 unsigned w, unsigned h) 157{ 158 const enum pipe_format dfmt = dst->base.base.format; 159 const enum pipe_format sfmt = src->base.base.format; 160 int ret; 161 bool eqfmt = dfmt == sfmt; 162 163 if (!PUSH_SPACE(push, 2 * 16 + 32)) 164 return PIPE_ERROR; 165 166 ret = nv50_2d_texture_set(push, 1, dst, dst_level, dz, dfmt, eqfmt); 167 if (ret) 168 return ret; 169 170 ret = nv50_2d_texture_set(push, 0, src, src_level, sz, sfmt, eqfmt); 171 if (ret) 172 return ret; 173 174 BEGIN_NV04(push, NV50_2D(BLIT_CONTROL), 1); 175 PUSH_DATA (push, NV50_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE); 176 BEGIN_NV04(push, NV50_2D(BLIT_DST_X), 4); 177 PUSH_DATA (push, dx << dst->ms_x); 178 PUSH_DATA (push, dy << dst->ms_y); 179 PUSH_DATA (push, w << dst->ms_x); 180 PUSH_DATA (push, h << dst->ms_y); 181 BEGIN_NV04(push, NV50_2D(BLIT_DU_DX_FRACT), 4); 182 PUSH_DATA (push, 0); 183 PUSH_DATA (push, 1); 184 PUSH_DATA (push, 0); 185 PUSH_DATA (push, 1); 186 BEGIN_NV04(push, NV50_2D(BLIT_SRC_X_FRACT), 4); 187 PUSH_DATA (push, 0); 188 PUSH_DATA (push, sx << src->ms_x); 189 PUSH_DATA (push, 0); 190 PUSH_DATA (push, sy << src->ms_y); 191 192 return 0; 193} 194 195static void 196nv50_resource_copy_region(struct pipe_context *pipe, 197 struct pipe_resource *dst, unsigned dst_level, 198 unsigned dstx, unsigned dsty, unsigned dstz, 199 struct pipe_resource *src, unsigned src_level, 200 const struct pipe_box *src_box) 201{ 202 struct nv50_context *nv50 = nv50_context(pipe); 203 int ret; 204 bool m2mf; 205 unsigned dst_layer = dstz, src_layer = src_box->z; 206 207 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 208 nouveau_copy_buffer(&nv50->base, 209 nv04_resource(dst), dstx, 210 nv04_resource(src), src_box->x, src_box->width); 211 return; 212 } 213 214 /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */ 215 assert((src->nr_samples | 1) == (dst->nr_samples | 1)); 216 217 m2mf = (src->format == dst->format) || 218 (util_format_get_blocksizebits(src->format) == 219 util_format_get_blocksizebits(dst->format)); 220 221 nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; 222 223 if (m2mf) { 224 struct nv50_miptree *src_mt = nv50_miptree(src); 225 struct nv50_miptree *dst_mt = nv50_miptree(dst); 226 struct nv50_m2mf_rect drect, srect; 227 unsigned i; 228 unsigned nx = util_format_get_nblocksx(src->format, src_box->width) 229 << src_mt->ms_x; 230 unsigned ny = util_format_get_nblocksy(src->format, src_box->height) 231 << src_mt->ms_y; 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 nv50_m2mf_transfer_rect(nv50, &drect, &srect, nx, ny); 239 240 if (dst_mt->layout_3d) 241 drect.z++; 242 else 243 drect.base += dst_mt->layer_stride; 244 245 if (src_mt->layout_3d) 246 srect.z++; 247 else 248 srect.base += src_mt->layer_stride; 249 } 250 return; 251 } 252 253 assert((src->format == dst->format) || 254 (nv50_2d_src_format_faithful(src->format) && 255 nv50_2d_dst_format_faithful(dst->format))); 256 257 BCTX_REFN(nv50->bufctx, 2D, nv04_resource(src), RD); 258 BCTX_REFN(nv50->bufctx, 2D, nv04_resource(dst), WR); 259 nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx); 260 nouveau_pushbuf_validate(nv50->base.pushbuf); 261 262 for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) { 263 ret = nv50_2d_texture_do_copy(nv50->base.pushbuf, 264 nv50_miptree(dst), dst_level, 265 dstx, dsty, dst_layer, 266 nv50_miptree(src), src_level, 267 src_box->x, src_box->y, src_layer, 268 src_box->width, src_box->height); 269 if (ret) 270 break; 271 } 272 nouveau_bufctx_reset(nv50->bufctx, NV50_BIND_2D); 273} 274 275static void 276nv50_clear_render_target(struct pipe_context *pipe, 277 struct pipe_surface *dst, 278 const union pipe_color_union *color, 279 unsigned dstx, unsigned dsty, 280 unsigned width, unsigned height, 281 bool render_condition_enabled) 282{ 283 struct nv50_context *nv50 = nv50_context(pipe); 284 struct nouveau_pushbuf *push = nv50->base.pushbuf; 285 struct nv50_miptree *mt = nv50_miptree(dst->texture); 286 struct nv50_surface *sf = nv50_surface(dst); 287 struct nouveau_bo *bo = mt->base.bo; 288 unsigned z; 289 290 assert(dst->texture->target != PIPE_BUFFER); 291 292 BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4); 293 PUSH_DATAf(push, color->f[0]); 294 PUSH_DATAf(push, color->f[1]); 295 PUSH_DATAf(push, color->f[2]); 296 PUSH_DATAf(push, color->f[3]); 297 298 if (nouveau_pushbuf_space(push, 64 + sf->depth, 1, 0)) 299 return; 300 301 PUSH_REFN(push, bo, mt->base.domain | NOUVEAU_BO_WR); 302 303 BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); 304 PUSH_DATA (push, ( width << 16) | dstx); 305 PUSH_DATA (push, (height << 16) | dsty); 306 BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2); 307 PUSH_DATA (push, 8192 << 16); 308 PUSH_DATA (push, 8192 << 16); 309 nv50->scissors_dirty |= 1; 310 311 BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1); 312 PUSH_DATA (push, 1); 313 BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5); 314 PUSH_DATAh(push, mt->base.address + sf->offset); 315 PUSH_DATA (push, mt->base.address + sf->offset); 316 PUSH_DATA (push, nv50_format_table[dst->format].rt); 317 PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode); 318 PUSH_DATA (push, mt->layer_stride >> 2); 319 BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2); 320 if (nouveau_bo_memtype(bo)) 321 PUSH_DATA(push, sf->width); 322 else 323 PUSH_DATA(push, NV50_3D_RT_HORIZ_LINEAR | mt->level[0].pitch); 324 PUSH_DATA (push, sf->height); 325 BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1); 326 if (mt->layout_3d) 327 PUSH_DATA(push, NV50_3D_RT_ARRAY_MODE_MODE_3D | 512); 328 else 329 PUSH_DATA(push, 512); 330 331 BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1); 332 PUSH_DATA (push, mt->ms_mode); 333 334 if (!nouveau_bo_memtype(bo)) { 335 BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1); 336 PUSH_DATA (push, 0); 337 } 338 339 /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */ 340 341 BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2); 342 PUSH_DATA (push, (width << 16) | dstx); 343 PUSH_DATA (push, (height << 16) | dsty); 344 345 if (!render_condition_enabled) { 346 BEGIN_NV04(push, NV50_3D(COND_MODE), 1); 347 PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS); 348 } 349 350 BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), sf->depth); 351 for (z = 0; z < sf->depth; ++z) { 352 PUSH_DATA (push, 0x3c | 353 (z << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 354 } 355 356 if (!render_condition_enabled) { 357 BEGIN_NV04(push, NV50_3D(COND_MODE), 1); 358 PUSH_DATA (push, nv50->cond_condmode); 359 } 360 361 nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_SCISSOR; 362} 363 364static void 365nv50_clear_depth_stencil(struct pipe_context *pipe, 366 struct pipe_surface *dst, 367 unsigned clear_flags, 368 double depth, 369 unsigned stencil, 370 unsigned dstx, unsigned dsty, 371 unsigned width, unsigned height, 372 bool render_condition_enabled) 373{ 374 struct nv50_context *nv50 = nv50_context(pipe); 375 struct nouveau_pushbuf *push = nv50->base.pushbuf; 376 struct nv50_miptree *mt = nv50_miptree(dst->texture); 377 struct nv50_surface *sf = nv50_surface(dst); 378 struct nouveau_bo *bo = mt->base.bo; 379 uint32_t mode = 0; 380 unsigned z; 381 382 assert(dst->texture->target != PIPE_BUFFER); 383 assert(nouveau_bo_memtype(bo)); /* ZETA cannot be linear */ 384 385 if (clear_flags & PIPE_CLEAR_DEPTH) { 386 BEGIN_NV04(push, NV50_3D(CLEAR_DEPTH), 1); 387 PUSH_DATAf(push, depth); 388 mode |= NV50_3D_CLEAR_BUFFERS_Z; 389 } 390 391 if (clear_flags & PIPE_CLEAR_STENCIL) { 392 BEGIN_NV04(push, NV50_3D(CLEAR_STENCIL), 1); 393 PUSH_DATA (push, stencil & 0xff); 394 mode |= NV50_3D_CLEAR_BUFFERS_S; 395 } 396 397 if (nouveau_pushbuf_space(push, 64 + sf->depth, 1, 0)) 398 return; 399 400 PUSH_REFN(push, bo, mt->base.domain | NOUVEAU_BO_WR); 401 402 BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); 403 PUSH_DATA (push, ( width << 16) | dstx); 404 PUSH_DATA (push, (height << 16) | dsty); 405 BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2); 406 PUSH_DATA (push, 8192 << 16); 407 PUSH_DATA (push, 8192 << 16); 408 nv50->scissors_dirty |= 1; 409 410 BEGIN_NV04(push, NV50_3D(ZETA_ADDRESS_HIGH), 5); 411 PUSH_DATAh(push, mt->base.address + sf->offset); 412 PUSH_DATA (push, mt->base.address + sf->offset); 413 PUSH_DATA (push, nv50_format_table[dst->format].rt); 414 PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode); 415 PUSH_DATA (push, mt->layer_stride >> 2); 416 BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1); 417 PUSH_DATA (push, 1); 418 BEGIN_NV04(push, NV50_3D(ZETA_HORIZ), 3); 419 PUSH_DATA (push, sf->width); 420 PUSH_DATA (push, sf->height); 421 PUSH_DATA (push, (1 << 16) | 1); 422 423 BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1); 424 PUSH_DATA (push, 512); 425 426 BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1); 427 PUSH_DATA (push, mt->ms_mode); 428 429 BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2); 430 PUSH_DATA (push, (width << 16) | dstx); 431 PUSH_DATA (push, (height << 16) | dsty); 432 433 if (!render_condition_enabled) { 434 BEGIN_NV04(push, NV50_3D(COND_MODE), 1); 435 PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS); 436 } 437 438 BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), sf->depth); 439 for (z = 0; z < sf->depth; ++z) { 440 PUSH_DATA (push, mode | 441 (z << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 442 } 443 444 if (!render_condition_enabled) { 445 BEGIN_NV04(push, NV50_3D(COND_MODE), 1); 446 PUSH_DATA (push, nv50->cond_condmode); 447 } 448 449 nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_SCISSOR; 450} 451 452void 453nv50_clear_texture(struct pipe_context *pipe, 454 struct pipe_resource *res, 455 unsigned level, 456 const struct pipe_box *box, 457 const void *data) 458{ 459 struct pipe_surface tmpl = {{0}}, *sf; 460 461 tmpl.format = res->format; 462 tmpl.u.tex.first_layer = box->z; 463 tmpl.u.tex.last_layer = box->z + box->depth - 1; 464 tmpl.u.tex.level = level; 465 sf = pipe->create_surface(pipe, res, &tmpl); 466 if (!sf) 467 return; 468 469 if (util_format_is_depth_or_stencil(res->format)) { 470 float depth = 0; 471 uint8_t stencil = 0; 472 unsigned clear = 0; 473 const struct util_format_description *desc = 474 util_format_description(res->format); 475 476 if (util_format_has_depth(desc)) { 477 clear |= PIPE_CLEAR_DEPTH; 478 util_format_unpack_z_float(res->format, &depth, data, 1); 479 } 480 if (util_format_has_stencil(desc)) { 481 clear |= PIPE_CLEAR_STENCIL; 482 util_format_unpack_s_8uint(res->format, &stencil, data, 1); 483 } 484 pipe->clear_depth_stencil(pipe, sf, clear, depth, stencil, 485 box->x, box->y, box->width, box->height, false); 486 } else { 487 union pipe_color_union color; 488 489 switch (util_format_get_blocksizebits(res->format)) { 490 case 128: 491 sf->format = PIPE_FORMAT_R32G32B32A32_UINT; 492 memcpy(&color.ui, data, 128 / 8); 493 break; 494 case 64: 495 sf->format = PIPE_FORMAT_R32G32_UINT; 496 memcpy(&color.ui, data, 64 / 8); 497 memset(&color.ui[2], 0, 64 / 8); 498 break; 499 case 32: 500 sf->format = PIPE_FORMAT_R32_UINT; 501 memcpy(&color.ui, data, 32 / 8); 502 memset(&color.ui[1], 0, 96 / 8); 503 break; 504 case 16: 505 sf->format = PIPE_FORMAT_R16_UINT; 506 color.ui[0] = util_cpu_to_le32( 507 util_le16_to_cpu(*(unsigned short *)data)); 508 memset(&color.ui[1], 0, 96 / 8); 509 break; 510 case 8: 511 sf->format = PIPE_FORMAT_R8_UINT; 512 color.ui[0] = util_cpu_to_le32(*(unsigned char *)data); 513 memset(&color.ui[1], 0, 96 / 8); 514 break; 515 default: 516 assert(!"Unknown texel element size"); 517 return; 518 } 519 520 pipe->clear_render_target(pipe, sf, &color, 521 box->x, box->y, box->width, box->height, false); 522 } 523 pipe->surface_destroy(pipe, sf); 524} 525 526void 527nv50_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state, 528 const union pipe_color_union *color, 529 double depth, unsigned stencil) 530{ 531 struct nv50_context *nv50 = nv50_context(pipe); 532 struct nouveau_pushbuf *push = nv50->base.pushbuf; 533 struct pipe_framebuffer_state *fb = &nv50->framebuffer; 534 unsigned i, j, k; 535 uint32_t mode = 0; 536 537 /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */ 538 if (!nv50_state_validate_3d(nv50, NV50_NEW_3D_FRAMEBUFFER)) 539 return; 540 541 if (scissor_state) { 542 uint32_t minx = scissor_state->minx; 543 uint32_t maxx = MIN2(fb->width, scissor_state->maxx); 544 uint32_t miny = scissor_state->miny; 545 uint32_t maxy = MIN2(fb->height, scissor_state->maxy); 546 if (maxx <= minx || maxy <= miny) 547 return; 548 549 BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); 550 PUSH_DATA (push, minx | (maxx - minx) << 16); 551 PUSH_DATA (push, miny | (maxy - miny) << 16); 552 } 553 554 /* We have to clear ALL of the layers, not up to the min number of layers 555 * of any attachment. */ 556 BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1); 557 PUSH_DATA (push, (nv50->rt_array_mode & NV50_3D_RT_ARRAY_MODE_MODE_3D) | 512); 558 559 if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { 560 BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4); 561 PUSH_DATAf(push, color->f[0]); 562 PUSH_DATAf(push, color->f[1]); 563 PUSH_DATAf(push, color->f[2]); 564 PUSH_DATAf(push, color->f[3]); 565 if (buffers & PIPE_CLEAR_COLOR0) 566 mode = 567 NV50_3D_CLEAR_BUFFERS_R | NV50_3D_CLEAR_BUFFERS_G | 568 NV50_3D_CLEAR_BUFFERS_B | NV50_3D_CLEAR_BUFFERS_A; 569 } 570 571 if (buffers & PIPE_CLEAR_DEPTH) { 572 BEGIN_NV04(push, NV50_3D(CLEAR_DEPTH), 1); 573 PUSH_DATA (push, fui(depth)); 574 mode |= NV50_3D_CLEAR_BUFFERS_Z; 575 } 576 577 if (buffers & PIPE_CLEAR_STENCIL) { 578 BEGIN_NV04(push, NV50_3D(CLEAR_STENCIL), 1); 579 PUSH_DATA (push, stencil & 0xff); 580 mode |= NV50_3D_CLEAR_BUFFERS_S; 581 } 582 583 if (mode) { 584 int zs_layers = 0, color0_layers = 0; 585 if (fb->cbufs[0] && (mode & 0x3c)) 586 color0_layers = nv50_surface(fb->cbufs[0])->depth; 587 if (fb->zsbuf && (mode & ~0x3c)) 588 zs_layers = nv50_surface(fb->zsbuf)->depth; 589 590 for (j = 0; j < MIN2(zs_layers, color0_layers); j++) { 591 BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1); 592 PUSH_DATA(push, mode | (j << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 593 } 594 for (k = j; k < zs_layers; k++) { 595 BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1); 596 PUSH_DATA(push, (mode & ~0x3c) | (k << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 597 } 598 for (k = j; k < color0_layers; k++) { 599 BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1); 600 PUSH_DATA(push, (mode & 0x3c) | (k << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 601 } 602 } 603 604 for (i = 1; i < fb->nr_cbufs; i++) { 605 struct pipe_surface *sf = fb->cbufs[i]; 606 if (!sf || !(buffers & (PIPE_CLEAR_COLOR0 << i))) 607 continue; 608 for (j = 0; j < nv50_surface(sf)->depth; j++) { 609 BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1); 610 PUSH_DATA (push, (i << 6) | 0x3c | 611 (j << NV50_3D_CLEAR_BUFFERS_LAYER__SHIFT)); 612 } 613 } 614 615 /* restore the array mode */ 616 BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1); 617 PUSH_DATA (push, nv50->rt_array_mode); 618 619 /* restore screen scissor */ 620 if (scissor_state) { 621 BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); 622 PUSH_DATA (push, fb->width << 16); 623 PUSH_DATA (push, fb->height << 16); 624 } 625} 626 627static void 628nv50_clear_buffer_push(struct pipe_context *pipe, 629 struct pipe_resource *res, 630 unsigned offset, unsigned size, 631 const void *data, int data_size) 632{ 633 struct nv50_context *nv50 = nv50_context(pipe); 634 struct nouveau_pushbuf *push = nv50->base.pushbuf; 635 struct nv04_resource *buf = nv04_resource(res); 636 unsigned count = (size + 3) / 4; 637 unsigned xcoord = offset & 0xff; 638 unsigned tmp, i; 639 640 if (data_size == 1) { 641 tmp = *(unsigned char *)data; 642 tmp = (tmp << 24) | (tmp << 16) | (tmp << 8) | tmp; 643 data = &tmp; 644 data_size = 4; 645 } else if (data_size == 2) { 646 tmp = *(unsigned short *)data; 647 tmp = (tmp << 16) | tmp; 648 data = &tmp; 649 data_size = 4; 650 } 651 652 unsigned data_words = data_size / 4; 653 654 nouveau_bufctx_refn(nv50->bufctx, 0, buf->bo, buf->domain | NOUVEAU_BO_WR); 655 nouveau_pushbuf_bufctx(push, nv50->bufctx); 656 nouveau_pushbuf_validate(push); 657 658 offset &= ~0xff; 659 660 BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); 661 PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 662 PUSH_DATA (push, 1); 663 BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); 664 PUSH_DATA (push, 262144); 665 PUSH_DATA (push, 65536); 666 PUSH_DATA (push, 1); 667 PUSH_DATAh(push, buf->address + offset); 668 PUSH_DATA (push, buf->address + offset); 669 BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); 670 PUSH_DATA (push, 0); 671 PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 672 BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); 673 PUSH_DATA (push, size); 674 PUSH_DATA (push, 1); 675 PUSH_DATA (push, 0); 676 PUSH_DATA (push, 1); 677 PUSH_DATA (push, 0); 678 PUSH_DATA (push, 1); 679 PUSH_DATA (push, 0); 680 PUSH_DATA (push, xcoord); 681 PUSH_DATA (push, 0); 682 PUSH_DATA (push, 0); 683 684 while (count) { 685 unsigned nr_data = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN) / data_words; 686 unsigned nr = nr_data * data_words; 687 688 BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr); 689 for (i = 0; i < nr_data; i++) 690 PUSH_DATAp(push, data, data_words); 691 692 count -= nr; 693 } 694 695 nv50_resource_validate(buf, NOUVEAU_BO_WR); 696 697 nouveau_bufctx_reset(nv50->bufctx, 0); 698} 699 700static void 701nv50_clear_buffer(struct pipe_context *pipe, 702 struct pipe_resource *res, 703 unsigned offset, unsigned size, 704 const void *data, int data_size) 705{ 706 struct nv50_context *nv50 = nv50_context(pipe); 707 struct nouveau_pushbuf *push = nv50->base.pushbuf; 708 struct nv04_resource *buf = (struct nv04_resource *)res; 709 union pipe_color_union color; 710 enum pipe_format dst_fmt; 711 unsigned width, height, elements; 712 713 assert(res->target == PIPE_BUFFER); 714 assert(nouveau_bo_memtype(buf->bo) == 0); 715 716 switch (data_size) { 717 case 16: 718 dst_fmt = PIPE_FORMAT_R32G32B32A32_UINT; 719 memcpy(&color.ui, data, 16); 720 break; 721 case 8: 722 dst_fmt = PIPE_FORMAT_R32G32_UINT; 723 memcpy(&color.ui, data, 8); 724 memset(&color.ui[2], 0, 8); 725 break; 726 case 4: 727 dst_fmt = PIPE_FORMAT_R32_UINT; 728 memcpy(&color.ui, data, 4); 729 memset(&color.ui[1], 0, 12); 730 break; 731 case 2: 732 dst_fmt = PIPE_FORMAT_R16_UINT; 733 color.ui[0] = util_cpu_to_le32( 734 util_le16_to_cpu(*(unsigned short *)data)); 735 memset(&color.ui[1], 0, 12); 736 break; 737 case 1: 738 dst_fmt = PIPE_FORMAT_R8_UINT; 739 color.ui[0] = util_cpu_to_le32(*(unsigned char *)data); 740 memset(&color.ui[1], 0, 12); 741 break; 742 default: 743 assert(!"Unsupported element size"); 744 return; 745 } 746 747 util_range_add(&buf->base, &buf->valid_buffer_range, offset, offset + size); 748 749 assert(size % data_size == 0); 750 751 if (offset & 0xff) { 752 unsigned fixup_size = MIN2(size, align(offset, 0x100) - offset); 753 assert(fixup_size % data_size == 0); 754 nv50_clear_buffer_push(pipe, res, offset, fixup_size, data, data_size); 755 offset += fixup_size; 756 size -= fixup_size; 757 if (!size) 758 return; 759 } 760 761 elements = size / data_size; 762 height = (elements + 8191) / 8192; 763 width = elements / height; 764 if (height > 1) 765 width &= ~0xff; 766 assert(width > 0); 767 768 BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4); 769 PUSH_DATA (push, color.ui[0]); 770 PUSH_DATA (push, color.ui[1]); 771 PUSH_DATA (push, color.ui[2]); 772 PUSH_DATA (push, color.ui[3]); 773 774 if (nouveau_pushbuf_space(push, 64, 1, 0)) 775 return; 776 777 PUSH_REFN(push, buf->bo, buf->domain | NOUVEAU_BO_WR); 778 779 BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2); 780 PUSH_DATA (push, width << 16); 781 PUSH_DATA (push, height << 16); 782 BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2); 783 PUSH_DATA (push, 8192 << 16); 784 PUSH_DATA (push, 8192 << 16); 785 nv50->scissors_dirty |= 1; 786 787 BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1); 788 PUSH_DATA (push, 1); 789 BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5); 790 PUSH_DATAh(push, buf->address + offset); 791 PUSH_DATA (push, buf->address + offset); 792 PUSH_DATA (push, nv50_format_table[dst_fmt].rt); 793 PUSH_DATA (push, 0); 794 PUSH_DATA (push, 0); 795 BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2); 796 PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | align(width * data_size, 0x100)); 797 PUSH_DATA (push, height); 798 BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1); 799 PUSH_DATA (push, 0); 800 BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1); 801 PUSH_DATA (push, 0); 802 803 /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */ 804 805 BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2); 806 PUSH_DATA (push, (width << 16)); 807 PUSH_DATA (push, (height << 16)); 808 809 BEGIN_NV04(push, NV50_3D(COND_MODE), 1); 810 PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS); 811 812 BEGIN_NI04(push, NV50_3D(CLEAR_BUFFERS), 1); 813 PUSH_DATA (push, 0x3c); 814 815 BEGIN_NV04(push, NV50_3D(COND_MODE), 1); 816 PUSH_DATA (push, nv50->cond_condmode); 817 818 nv50_resource_validate(buf, NOUVEAU_BO_WR); 819 820 if (width * height != elements) { 821 offset += width * height * data_size; 822 width = elements - width * height; 823 nv50_clear_buffer_push(pipe, res, offset, width * data_size, 824 data, data_size); 825 } 826 827 nv50->dirty_3d |= NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_SCISSOR; 828} 829 830/* =============================== BLIT CODE =================================== 831 */ 832 833struct nv50_blitter 834{ 835 struct nv50_program *fp[NV50_BLIT_MAX_TEXTURE_TYPES][NV50_BLIT_MODES]; 836 struct nv50_program vp; 837 838 struct nv50_tsc_entry sampler[2]; /* nearest, bilinear */ 839 840 mtx_t mutex; 841}; 842 843struct nv50_blitctx 844{ 845 struct nv50_context *nv50; 846 struct nv50_program *fp; 847 uint8_t mode; 848 uint16_t color_mask; 849 uint8_t filter; 850 uint8_t render_condition_enable; 851 enum pipe_texture_target target; 852 struct { 853 struct pipe_framebuffer_state fb; 854 struct nv50_window_rect_stateobj window_rect; 855 struct nv50_rasterizer_stateobj *rast; 856 struct nv50_program *vp; 857 struct nv50_program *gp; 858 struct nv50_program *fp; 859 unsigned num_textures[NV50_MAX_3D_SHADER_STAGES]; 860 unsigned num_samplers[NV50_MAX_3D_SHADER_STAGES]; 861 struct pipe_sampler_view *texture[2]; 862 struct nv50_tsc_entry *sampler[2]; 863 unsigned min_samples; 864 uint32_t dirty_3d; 865 } saved; 866 struct nv50_rasterizer_stateobj rast; 867}; 868 869static void 870nv50_blitter_make_vp(struct nv50_blitter *blit) 871{ 872 static const uint32_t code[] = 873 { 874 0x10000001, 0x0423c788, /* mov b32 o[0x00] s[0x00] */ /* HPOS.x */ 875 0x10000205, 0x0423c788, /* mov b32 o[0x04] s[0x04] */ /* HPOS.y */ 876 0x10000409, 0x0423c788, /* mov b32 o[0x08] s[0x08] */ /* TEXC.x */ 877 0x1000060d, 0x0423c788, /* mov b32 o[0x0c] s[0x0c] */ /* TEXC.y */ 878 0x10000811, 0x0423c789, /* mov b32 o[0x10] s[0x10] */ /* TEXC.z */ 879 }; 880 881 blit->vp.type = PIPE_SHADER_VERTEX; 882 blit->vp.translated = true; 883 blit->vp.code = (uint32_t *)code; /* const_cast */ 884 blit->vp.code_size = sizeof(code); 885 blit->vp.max_gpr = 4; 886 blit->vp.max_out = 5; 887 blit->vp.out_nr = 2; 888 blit->vp.out[0].mask = 0x3; 889 blit->vp.out[0].sn = TGSI_SEMANTIC_POSITION; 890 blit->vp.out[1].hw = 2; 891 blit->vp.out[1].mask = 0x7; 892 blit->vp.out[1].sn = TGSI_SEMANTIC_GENERIC; 893 blit->vp.out[1].si = 0; 894 blit->vp.vp.attrs[0] = 0x73; 895 blit->vp.vp.psiz = 0x40; 896 blit->vp.vp.edgeflag = 0x40; 897} 898 899void * 900nv50_blitter_make_fp(struct pipe_context *pipe, 901 unsigned mode, 902 enum pipe_texture_target ptarg) 903{ 904 struct ureg_program *ureg; 905 struct ureg_src tc; 906 struct ureg_dst out; 907 struct ureg_dst data; 908 909 const unsigned target = nv50_blit_get_tgsi_texture_target(ptarg); 910 911 bool tex_rgbaz = false; 912 bool tex_s = false; 913 bool cvt_un8 = false; 914 915 bool int_clamp = mode == NV50_BLIT_MODE_INT_CLAMP; 916 if (int_clamp) 917 mode = NV50_BLIT_MODE_PASS; 918 919 if (mode != NV50_BLIT_MODE_PASS && 920 mode != NV50_BLIT_MODE_Z24X8 && 921 mode != NV50_BLIT_MODE_X8Z24) 922 tex_s = true; 923 924 if (mode != NV50_BLIT_MODE_X24S8 && 925 mode != NV50_BLIT_MODE_S8X24 && 926 mode != NV50_BLIT_MODE_XS) 927 tex_rgbaz = true; 928 929 if (mode != NV50_BLIT_MODE_PASS && 930 mode != NV50_BLIT_MODE_ZS && 931 mode != NV50_BLIT_MODE_XS) 932 cvt_un8 = true; 933 934 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 935 if (!ureg) 936 return NULL; 937 938 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 939 tc = ureg_DECL_fs_input( 940 ureg, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_LINEAR); 941 942 if (ptarg == PIPE_TEXTURE_1D_ARRAY) { 943 /* Adjust coordinates. Depth is in z, but TEX expects it to be in y. */ 944 tc = ureg_swizzle(tc, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Z, 945 TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z); 946 } 947 948 data = ureg_DECL_temporary(ureg); 949 950 if (tex_s) { 951 ureg_TEX(ureg, ureg_writemask(data, TGSI_WRITEMASK_X), 952 target, tc, ureg_DECL_sampler(ureg, 1)); 953 ureg_MOV(ureg, ureg_writemask(data, TGSI_WRITEMASK_Y), 954 ureg_scalar(ureg_src(data), TGSI_SWIZZLE_X)); 955 } 956 if (tex_rgbaz) { 957 const unsigned mask = (mode == NV50_BLIT_MODE_PASS) ? 958 TGSI_WRITEMASK_XYZW : TGSI_WRITEMASK_X; 959 ureg_TEX(ureg, ureg_writemask(data, mask), 960 target, tc, ureg_DECL_sampler(ureg, 0)); 961 } 962 963 /* handle signed to unsigned integer conversions */ 964 if (int_clamp) 965 ureg_UMIN(ureg, data, ureg_src(data), ureg_imm1u(ureg, 0x7fffffff)); 966 967 if (cvt_un8) { 968 struct ureg_src mask; 969 struct ureg_src scale; 970 struct ureg_dst outz; 971 struct ureg_dst outs; 972 struct ureg_dst zdst3 = ureg_writemask(data, TGSI_WRITEMASK_XYZ); 973 struct ureg_dst zdst = ureg_writemask(data, TGSI_WRITEMASK_X); 974 struct ureg_dst sdst = ureg_writemask(data, TGSI_WRITEMASK_Y); 975 struct ureg_src zsrc3 = ureg_src(data); 976 struct ureg_src zsrc = ureg_scalar(zsrc3, TGSI_SWIZZLE_X); 977 struct ureg_src ssrc = ureg_scalar(zsrc3, TGSI_SWIZZLE_Y); 978 struct ureg_src zshuf; 979 980 mask = ureg_imm3u(ureg, 0x0000ff, 0x00ff00, 0xff0000); 981 scale = ureg_imm4f(ureg, 982 1.0f / 0x0000ff, 1.0f / 0x00ff00, 1.0f / 0xff0000, 983 (1 << 24) - 1); 984 985 if (mode == NV50_BLIT_MODE_Z24S8 || 986 mode == NV50_BLIT_MODE_X24S8 || 987 mode == NV50_BLIT_MODE_Z24X8) { 988 outz = ureg_writemask(out, TGSI_WRITEMASK_XYZ); 989 outs = ureg_writemask(out, TGSI_WRITEMASK_W); 990 zshuf = ureg_src(data); 991 } else { 992 outz = ureg_writemask(out, TGSI_WRITEMASK_YZW); 993 outs = ureg_writemask(out, TGSI_WRITEMASK_X); 994 zshuf = ureg_swizzle(zsrc3, TGSI_SWIZZLE_W, 995 TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z); 996 } 997 998 if (tex_s) { 999 ureg_I2F(ureg, sdst, ssrc); 1000 ureg_MUL(ureg, outs, ssrc, ureg_scalar(scale, TGSI_SWIZZLE_X)); 1001 } 1002 1003 if (tex_rgbaz) { 1004 ureg_MUL(ureg, zdst, zsrc, ureg_scalar(scale, TGSI_SWIZZLE_W)); 1005 ureg_F2I(ureg, zdst, zsrc); 1006 ureg_AND(ureg, zdst3, zsrc, mask); 1007 ureg_I2F(ureg, zdst3, zsrc3); 1008 ureg_MUL(ureg, zdst3, zsrc3, scale); 1009 ureg_MOV(ureg, outz, zshuf); 1010 } 1011 } else { 1012 unsigned mask = TGSI_WRITEMASK_XYZW; 1013 1014 if (mode != NV50_BLIT_MODE_PASS) { 1015 mask &= ~TGSI_WRITEMASK_ZW; 1016 if (!tex_s) 1017 mask = TGSI_WRITEMASK_X; 1018 if (!tex_rgbaz) 1019 mask = TGSI_WRITEMASK_Y; 1020 } 1021 ureg_MOV(ureg, ureg_writemask(out, mask), ureg_src(data)); 1022 } 1023 ureg_END(ureg); 1024 1025 return ureg_create_shader_and_destroy(ureg, pipe); 1026} 1027 1028static void 1029nv50_blitter_make_sampler(struct nv50_blitter *blit) 1030{ 1031 /* clamp to edge, min/max lod = 0, nearest filtering */ 1032 1033 blit->sampler[0].id = -1; 1034 1035 blit->sampler[0].tsc[0] = G80_TSC_0_SRGB_CONVERSION | 1036 (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_U__SHIFT) | 1037 (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_V__SHIFT) | 1038 (G80_TSC_WRAP_CLAMP_TO_EDGE << G80_TSC_0_ADDRESS_P__SHIFT); 1039 blit->sampler[0].tsc[1] = 1040 G80_TSC_1_MAG_FILTER_NEAREST | 1041 G80_TSC_1_MIN_FILTER_NEAREST | 1042 G80_TSC_1_MIP_FILTER_NONE; 1043 1044 /* clamp to edge, min/max lod = 0, bilinear filtering */ 1045 1046 blit->sampler[1].id = -1; 1047 1048 blit->sampler[1].tsc[0] = blit->sampler[0].tsc[0]; 1049 blit->sampler[1].tsc[1] = 1050 G80_TSC_1_MAG_FILTER_LINEAR | 1051 G80_TSC_1_MIN_FILTER_LINEAR | 1052 G80_TSC_1_MIP_FILTER_NONE; 1053} 1054 1055unsigned 1056nv50_blit_select_mode(const struct pipe_blit_info *info) 1057{ 1058 const unsigned mask = info->mask; 1059 1060 switch (info->dst.resource->format) { 1061 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 1062 case PIPE_FORMAT_Z24X8_UNORM: 1063 case PIPE_FORMAT_X24S8_UINT: 1064 switch (mask & PIPE_MASK_ZS) { 1065 case PIPE_MASK_ZS: return NV50_BLIT_MODE_Z24S8; 1066 case PIPE_MASK_Z: return NV50_BLIT_MODE_Z24X8; 1067 default: 1068 return NV50_BLIT_MODE_X24S8; 1069 } 1070 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 1071 case PIPE_FORMAT_X8Z24_UNORM: 1072 case PIPE_FORMAT_S8X24_UINT: 1073 switch (mask & PIPE_MASK_ZS) { 1074 case PIPE_MASK_ZS: return NV50_BLIT_MODE_S8Z24; 1075 case PIPE_MASK_Z: return NV50_BLIT_MODE_X8Z24; 1076 default: 1077 return NV50_BLIT_MODE_S8X24; 1078 } 1079 case PIPE_FORMAT_Z32_FLOAT: 1080 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 1081 case PIPE_FORMAT_X32_S8X24_UINT: 1082 switch (mask & PIPE_MASK_ZS) { 1083 case PIPE_MASK_ZS: return NV50_BLIT_MODE_ZS; 1084 case PIPE_MASK_Z: return NV50_BLIT_MODE_PASS; 1085 default: 1086 return NV50_BLIT_MODE_XS; 1087 } 1088 default: 1089 if (util_format_is_pure_uint(info->src.format) && 1090 util_format_is_pure_sint(info->dst.format)) 1091 return NV50_BLIT_MODE_INT_CLAMP; 1092 return NV50_BLIT_MODE_PASS; 1093 } 1094} 1095 1096static void 1097nv50_blit_select_fp(struct nv50_blitctx *ctx, const struct pipe_blit_info *info) 1098{ 1099 struct nv50_blitter *blitter = ctx->nv50->screen->blitter; 1100 1101 const enum pipe_texture_target ptarg = 1102 nv50_blit_reinterpret_pipe_texture_target(info->src.resource->target); 1103 1104 const unsigned targ = nv50_blit_texture_type(ptarg); 1105 const unsigned mode = ctx->mode; 1106 1107 if (!blitter->fp[targ][mode]) { 1108 mtx_lock(&blitter->mutex); 1109 if (!blitter->fp[targ][mode]) 1110 blitter->fp[targ][mode] = 1111 nv50_blitter_make_fp(&ctx->nv50->base.pipe, mode, ptarg); 1112 mtx_unlock(&blitter->mutex); 1113 } 1114 ctx->fp = blitter->fp[targ][mode]; 1115} 1116 1117static void 1118nv50_blit_set_dst(struct nv50_blitctx *ctx, 1119 struct pipe_resource *res, unsigned level, unsigned layer, 1120 enum pipe_format format) 1121{ 1122 struct nv50_context *nv50 = ctx->nv50; 1123 struct pipe_context *pipe = &nv50->base.pipe; 1124 struct pipe_surface templ; 1125 1126 if (util_format_is_depth_or_stencil(format)) 1127 templ.format = nv50_blit_zeta_to_colour_format(format); 1128 else 1129 templ.format = format; 1130 1131 templ.u.tex.level = level; 1132 templ.u.tex.first_layer = templ.u.tex.last_layer = layer; 1133 1134 if (layer == -1) { 1135 templ.u.tex.first_layer = 0; 1136 templ.u.tex.last_layer = 1137 (res->target == PIPE_TEXTURE_3D ? res->depth0 : res->array_size) - 1; 1138 } 1139 1140 nv50->framebuffer.cbufs[0] = nv50_miptree_surface_new(pipe, res, &templ); 1141 nv50->framebuffer.nr_cbufs = 1; 1142 nv50->framebuffer.zsbuf = NULL; 1143 nv50->framebuffer.width = nv50->framebuffer.cbufs[0]->width; 1144 nv50->framebuffer.height = nv50->framebuffer.cbufs[0]->height; 1145} 1146 1147static void 1148nv50_blit_set_src(struct nv50_blitctx *blit, 1149 struct pipe_resource *res, unsigned level, unsigned layer, 1150 enum pipe_format format, const uint8_t filter) 1151{ 1152 struct nv50_context *nv50 = blit->nv50; 1153 struct pipe_context *pipe = &nv50->base.pipe; 1154 struct pipe_sampler_view templ; 1155 uint32_t flags; 1156 enum pipe_texture_target target; 1157 1158 target = nv50_blit_reinterpret_pipe_texture_target(res->target); 1159 1160 templ.target = target; 1161 templ.format = format; 1162 templ.u.tex.first_level = templ.u.tex.last_level = level; 1163 templ.u.tex.first_layer = templ.u.tex.last_layer = layer; 1164 templ.swizzle_r = PIPE_SWIZZLE_X; 1165 templ.swizzle_g = PIPE_SWIZZLE_Y; 1166 templ.swizzle_b = PIPE_SWIZZLE_Z; 1167 templ.swizzle_a = PIPE_SWIZZLE_W; 1168 1169 if (layer == -1) { 1170 templ.u.tex.first_layer = 0; 1171 templ.u.tex.last_layer = 1172 (res->target == PIPE_TEXTURE_3D ? res->depth0 : res->array_size) - 1; 1173 } 1174 1175 flags = res->last_level ? 0 : NV50_TEXVIEW_SCALED_COORDS; 1176 flags |= NV50_TEXVIEW_ACCESS_RESOLVE; 1177 if (filter && res->nr_samples == 8) 1178 flags |= NV50_TEXVIEW_FILTER_MSAA8; 1179 1180 nv50->textures[NV50_SHADER_STAGE_FRAGMENT][0] = nv50_create_texture_view( 1181 pipe, res, &templ, flags); 1182 nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1] = NULL; 1183 1184 nv50->num_textures[NV50_SHADER_STAGE_VERTEX] = 0; 1185 nv50->num_textures[NV50_SHADER_STAGE_GEOMETRY] = 0; 1186 nv50->num_textures[NV50_SHADER_STAGE_FRAGMENT] = 1; 1187 1188 templ.format = nv50_zs_to_s_format(format); 1189 if (templ.format != res->format) { 1190 nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1] = nv50_create_texture_view( 1191 pipe, res, &templ, flags); 1192 nv50->num_textures[NV50_SHADER_STAGE_FRAGMENT] = 2; 1193 } 1194} 1195 1196static void 1197nv50_blitctx_prepare_state(struct nv50_blitctx *blit) 1198{ 1199 struct nouveau_pushbuf *push = blit->nv50->base.pushbuf; 1200 1201 if (blit->nv50->cond_query && !blit->render_condition_enable) { 1202 BEGIN_NV04(push, NV50_3D(COND_MODE), 1); 1203 PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS); 1204 } 1205 1206 /* blend state */ 1207 BEGIN_NV04(push, NV50_3D(COLOR_MASK(0)), 1); 1208 PUSH_DATA (push, blit->color_mask); 1209 BEGIN_NV04(push, NV50_3D(BLEND_ENABLE(0)), 1); 1210 PUSH_DATA (push, 0); 1211 BEGIN_NV04(push, NV50_3D(LOGIC_OP_ENABLE), 1); 1212 PUSH_DATA (push, 0); 1213 1214 /* rasterizer state */ 1215#ifndef NV50_SCISSORS_CLIPPING 1216 BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(0)), 1); 1217 PUSH_DATA (push, 1); 1218#endif 1219 BEGIN_NV04(push, NV50_3D(VERTEX_TWO_SIDE_ENABLE), 1); 1220 PUSH_DATA (push, 0); 1221 BEGIN_NV04(push, NV50_3D(FRAG_COLOR_CLAMP_EN), 1); 1222 PUSH_DATA (push, 0); 1223 BEGIN_NV04(push, NV50_3D(MULTISAMPLE_ENABLE), 1); 1224 PUSH_DATA (push, 0); 1225 BEGIN_NV04(push, NV50_3D(MSAA_MASK(0)), 4); 1226 PUSH_DATA (push, 0xffff); 1227 PUSH_DATA (push, 0xffff); 1228 PUSH_DATA (push, 0xffff); 1229 PUSH_DATA (push, 0xffff); 1230 BEGIN_NV04(push, NV50_3D(POLYGON_MODE_FRONT), 3); 1231 PUSH_DATA (push, NV50_3D_POLYGON_MODE_FRONT_FILL); 1232 PUSH_DATA (push, NV50_3D_POLYGON_MODE_BACK_FILL); 1233 PUSH_DATA (push, 0); 1234 BEGIN_NV04(push, NV50_3D(CULL_FACE_ENABLE), 1); 1235 PUSH_DATA (push, 0); 1236 BEGIN_NV04(push, NV50_3D(POLYGON_STIPPLE_ENABLE), 1); 1237 PUSH_DATA (push, 0); 1238 BEGIN_NV04(push, NV50_3D(POLYGON_OFFSET_FILL_ENABLE), 1); 1239 PUSH_DATA (push, 0); 1240 1241 /* zsa state */ 1242 BEGIN_NV04(push, NV50_3D(DEPTH_TEST_ENABLE), 1); 1243 PUSH_DATA (push, 0); 1244 BEGIN_NV04(push, NV50_3D(DEPTH_BOUNDS_EN), 1); 1245 PUSH_DATA (push, 0); 1246 BEGIN_NV04(push, NV50_3D(STENCIL_ENABLE), 1); 1247 PUSH_DATA (push, 0); 1248 BEGIN_NV04(push, NV50_3D(ALPHA_TEST_ENABLE), 1); 1249 PUSH_DATA (push, 0); 1250} 1251 1252static void 1253nv50_blitctx_pre_blit(struct nv50_blitctx *ctx, 1254 const struct pipe_blit_info *info) 1255{ 1256 struct nv50_context *nv50 = ctx->nv50; 1257 struct nv50_blitter *blitter = nv50->screen->blitter; 1258 int s; 1259 1260 ctx->saved.fb.width = nv50->framebuffer.width; 1261 ctx->saved.fb.height = nv50->framebuffer.height; 1262 ctx->saved.fb.nr_cbufs = nv50->framebuffer.nr_cbufs; 1263 ctx->saved.fb.cbufs[0] = nv50->framebuffer.cbufs[0]; 1264 ctx->saved.fb.zsbuf = nv50->framebuffer.zsbuf; 1265 1266 ctx->saved.rast = nv50->rast; 1267 1268 ctx->saved.vp = nv50->vertprog; 1269 ctx->saved.gp = nv50->gmtyprog; 1270 ctx->saved.fp = nv50->fragprog; 1271 1272 ctx->saved.min_samples = nv50->min_samples; 1273 ctx->saved.window_rect = nv50->window_rect; 1274 1275 nv50->rast = &ctx->rast; 1276 1277 nv50->vertprog = &blitter->vp; 1278 nv50->gmtyprog = NULL; 1279 nv50->fragprog = ctx->fp; 1280 1281 nv50->window_rect.rects = 1282 MIN2(info->num_window_rectangles, NV50_MAX_WINDOW_RECTANGLES); 1283 nv50->window_rect.inclusive = info->window_rectangle_include; 1284 if (nv50->window_rect.rects) 1285 memcpy(nv50->window_rect.rect, info->window_rectangles, 1286 sizeof(struct pipe_scissor_state) * nv50->window_rect.rects); 1287 1288 for (s = 0; s < NV50_MAX_3D_SHADER_STAGES; ++s) { 1289 ctx->saved.num_textures[s] = nv50->num_textures[s]; 1290 ctx->saved.num_samplers[s] = nv50->num_samplers[s]; 1291 } 1292 ctx->saved.texture[0] = nv50->textures[NV50_SHADER_STAGE_FRAGMENT][0]; 1293 ctx->saved.texture[1] = nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1]; 1294 ctx->saved.sampler[0] = nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][0]; 1295 ctx->saved.sampler[1] = nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][1]; 1296 1297 nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][0] = &blitter->sampler[ctx->filter]; 1298 nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][1] = &blitter->sampler[ctx->filter]; 1299 1300 nv50->num_samplers[NV50_SHADER_STAGE_VERTEX] = 0; 1301 nv50->num_samplers[NV50_SHADER_STAGE_GEOMETRY] = 0; 1302 nv50->num_samplers[NV50_SHADER_STAGE_FRAGMENT] = 2; 1303 1304 nv50->min_samples = 1; 1305 1306 ctx->saved.dirty_3d = nv50->dirty_3d; 1307 1308 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB); 1309 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_TEXTURES); 1310 1311 nv50->dirty_3d = 1312 NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_MIN_SAMPLES | 1313 NV50_NEW_3D_VERTPROG | NV50_NEW_3D_FRAGPROG | NV50_NEW_3D_GMTYPROG | 1314 NV50_NEW_3D_TEXTURES | NV50_NEW_3D_SAMPLERS | NV50_NEW_3D_WINDOW_RECTS; 1315} 1316 1317static void 1318nv50_blitctx_post_blit(struct nv50_blitctx *blit) 1319{ 1320 struct nv50_context *nv50 = blit->nv50; 1321 int s; 1322 1323 pipe_surface_reference(&nv50->framebuffer.cbufs[0], NULL); 1324 1325 nv50->framebuffer.width = blit->saved.fb.width; 1326 nv50->framebuffer.height = blit->saved.fb.height; 1327 nv50->framebuffer.nr_cbufs = blit->saved.fb.nr_cbufs; 1328 nv50->framebuffer.cbufs[0] = blit->saved.fb.cbufs[0]; 1329 nv50->framebuffer.zsbuf = blit->saved.fb.zsbuf; 1330 1331 nv50->rast = blit->saved.rast; 1332 1333 nv50->vertprog = blit->saved.vp; 1334 nv50->gmtyprog = blit->saved.gp; 1335 nv50->fragprog = blit->saved.fp; 1336 1337 nv50->min_samples = blit->saved.min_samples; 1338 nv50->window_rect = blit->saved.window_rect; 1339 1340 pipe_sampler_view_reference(&nv50->textures[NV50_SHADER_STAGE_FRAGMENT][0], NULL); 1341 pipe_sampler_view_reference(&nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1], NULL); 1342 1343 for (s = 0; s < NV50_MAX_3D_SHADER_STAGES; ++s) { 1344 nv50->num_textures[s] = blit->saved.num_textures[s]; 1345 nv50->num_samplers[s] = blit->saved.num_samplers[s]; 1346 } 1347 nv50->textures[NV50_SHADER_STAGE_FRAGMENT][0] = blit->saved.texture[0]; 1348 nv50->textures[NV50_SHADER_STAGE_FRAGMENT][1] = blit->saved.texture[1]; 1349 nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][0] = blit->saved.sampler[0]; 1350 nv50->samplers[NV50_SHADER_STAGE_FRAGMENT][1] = blit->saved.sampler[1]; 1351 1352 if (nv50->cond_query && !blit->render_condition_enable) 1353 nv50->base.pipe.render_condition(&nv50->base.pipe, nv50->cond_query, 1354 nv50->cond_cond, nv50->cond_mode); 1355 1356 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB); 1357 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_TEXTURES); 1358 1359 nv50->dirty_3d = blit->saved.dirty_3d | 1360 (NV50_NEW_3D_FRAMEBUFFER | NV50_NEW_3D_SCISSOR | NV50_NEW_3D_SAMPLE_MASK | 1361 NV50_NEW_3D_RASTERIZER | NV50_NEW_3D_ZSA | NV50_NEW_3D_BLEND | 1362 NV50_NEW_3D_TEXTURES | NV50_NEW_3D_SAMPLERS | NV50_NEW_3D_WINDOW_RECTS | 1363 NV50_NEW_3D_VERTPROG | NV50_NEW_3D_GMTYPROG | NV50_NEW_3D_FRAGPROG); 1364 nv50->scissors_dirty |= 1; 1365 1366 nv50->base.pipe.set_min_samples(&nv50->base.pipe, blit->saved.min_samples); 1367} 1368 1369 1370static void 1371nv50_blit_3d(struct nv50_context *nv50, const struct pipe_blit_info *info) 1372{ 1373 struct nv50_blitctx *blit = nv50->blit; 1374 struct nouveau_pushbuf *push = nv50->base.pushbuf; 1375 struct pipe_resource *src = info->src.resource; 1376 struct pipe_resource *dst = info->dst.resource; 1377 int32_t minx, maxx, miny, maxy; 1378 int32_t i; 1379 float x0, x1, y0, y1, z; 1380 float dz; 1381 float x_range, y_range; 1382 1383 blit->mode = nv50_blit_select_mode(info); 1384 blit->color_mask = nv50_blit_derive_color_mask(info); 1385 blit->filter = nv50_blit_get_filter(info); 1386 blit->render_condition_enable = info->render_condition_enable; 1387 1388 nv50_blit_select_fp(blit, info); 1389 nv50_blitctx_pre_blit(blit, info); 1390 1391 nv50_blit_set_dst(blit, dst, info->dst.level, -1, info->dst.format); 1392 nv50_blit_set_src(blit, src, info->src.level, -1, info->src.format, 1393 blit->filter); 1394 1395 nv50_blitctx_prepare_state(blit); 1396 1397 nv50_state_validate_3d(nv50, ~0); 1398 1399 /* When flipping a surface from zeta <-> color "mode", we have to wait for 1400 * the GPU to flush its current draws. 1401 */ 1402 struct nv50_miptree *mt = nv50_miptree(dst); 1403 bool serialize = util_format_is_depth_or_stencil(info->dst.format); 1404 if (serialize && mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 1405 BEGIN_NV04(push, SUBC_3D(NV50_GRAPH_SERIALIZE), 1); 1406 PUSH_DATA (push, 0); 1407 } 1408 1409 x_range = (float)info->src.box.width / (float)info->dst.box.width; 1410 y_range = (float)info->src.box.height / (float)info->dst.box.height; 1411 1412 x0 = (float)info->src.box.x - x_range * (float)info->dst.box.x; 1413 y0 = (float)info->src.box.y - y_range * (float)info->dst.box.y; 1414 1415 x1 = x0 + 16384.0f * x_range; 1416 y1 = y0 + 16384.0f * y_range; 1417 1418 x0 *= (float)(1 << nv50_miptree(src)->ms_x); 1419 x1 *= (float)(1 << nv50_miptree(src)->ms_x); 1420 y0 *= (float)(1 << nv50_miptree(src)->ms_y); 1421 y1 *= (float)(1 << nv50_miptree(src)->ms_y); 1422 1423 /* XXX: multiply by 6 for cube arrays ? */ 1424 dz = (float)info->src.box.depth / (float)info->dst.box.depth; 1425 z = (float)info->src.box.z; 1426 if (nv50_miptree(src)->layout_3d) 1427 z += 0.5f * dz; 1428 1429 if (src->last_level > 0) { 1430 /* If there are mip maps, GPU always assumes normalized coordinates. */ 1431 const unsigned l = info->src.level; 1432 const float fh = u_minify(src->width0 << nv50_miptree(src)->ms_x, l); 1433 const float fv = u_minify(src->height0 << nv50_miptree(src)->ms_y, l); 1434 x0 /= fh; 1435 x1 /= fh; 1436 y0 /= fv; 1437 y1 /= fv; 1438 if (nv50_miptree(src)->layout_3d) { 1439 z /= u_minify(src->depth0, l); 1440 dz /= u_minify(src->depth0, l); 1441 } 1442 } 1443 1444 BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1); 1445 PUSH_DATA (push, 0); 1446 BEGIN_NV04(push, NV50_3D(VIEW_VOLUME_CLIP_CTRL), 1); 1447 PUSH_DATA (push, 0x1); 1448 1449 /* Draw a large triangle in screen coordinates covering the whole 1450 * render target, with scissors defining the destination region. 1451 * The vertex is supplied with non-normalized texture coordinates 1452 * arranged in a way to yield the desired offset and scale. 1453 */ 1454 1455 minx = info->dst.box.x; 1456 maxx = info->dst.box.x + info->dst.box.width; 1457 miny = info->dst.box.y; 1458 maxy = info->dst.box.y + info->dst.box.height; 1459 if (info->scissor_enable) { 1460 minx = MAX2(minx, info->scissor.minx); 1461 maxx = MIN2(maxx, info->scissor.maxx); 1462 miny = MAX2(miny, info->scissor.miny); 1463 maxy = MIN2(maxy, info->scissor.maxy); 1464 } 1465 BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2); 1466 PUSH_DATA (push, (maxx << 16) | minx); 1467 PUSH_DATA (push, (maxy << 16) | miny); 1468 1469 for (i = 0; i < info->dst.box.depth; ++i, z += dz) { 1470 if (info->dst.box.z + i) { 1471 BEGIN_NV04(push, NV50_3D(LAYER), 1); 1472 PUSH_DATA (push, info->dst.box.z + i); 1473 } 1474 PUSH_SPACE(push, 32); 1475 BEGIN_NV04(push, NV50_3D(VERTEX_BEGIN_GL), 1); 1476 PUSH_DATA (push, NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES); 1477 BEGIN_NV04(push, NV50_3D(VTX_ATTR_3F_X(1)), 3); 1478 PUSH_DATAf(push, x0); 1479 PUSH_DATAf(push, y0); 1480 PUSH_DATAf(push, z); 1481 BEGIN_NV04(push, NV50_3D(VTX_ATTR_2F_X(0)), 2); 1482 PUSH_DATAf(push, 0.0f); 1483 PUSH_DATAf(push, 0.0f); 1484 BEGIN_NV04(push, NV50_3D(VTX_ATTR_3F_X(1)), 3); 1485 PUSH_DATAf(push, x1); 1486 PUSH_DATAf(push, y0); 1487 PUSH_DATAf(push, z); 1488 BEGIN_NV04(push, NV50_3D(VTX_ATTR_2F_X(0)), 2); 1489 PUSH_DATAf(push, 16384.0f); 1490 PUSH_DATAf(push, 0.0f); 1491 BEGIN_NV04(push, NV50_3D(VTX_ATTR_3F_X(1)), 3); 1492 PUSH_DATAf(push, x0); 1493 PUSH_DATAf(push, y1); 1494 PUSH_DATAf(push, z); 1495 BEGIN_NV04(push, NV50_3D(VTX_ATTR_2F_X(0)), 2); 1496 PUSH_DATAf(push, 0.0f); 1497 PUSH_DATAf(push, 16384.0f); 1498 BEGIN_NV04(push, NV50_3D(VERTEX_END_GL), 1); 1499 PUSH_DATA (push, 0); 1500 } 1501 if (info->dst.box.z + info->dst.box.depth - 1) { 1502 BEGIN_NV04(push, NV50_3D(LAYER), 1); 1503 PUSH_DATA (push, 0); 1504 } 1505 1506 /* re-enable normally constant state */ 1507 1508 BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1); 1509 PUSH_DATA (push, 1); 1510 1511 /* mark the surface as reading, which will force a serialize next time it's 1512 * used for writing. 1513 */ 1514 if (serialize) 1515 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_READING; 1516 1517 nv50_blitctx_post_blit(blit); 1518} 1519 1520static void 1521nv50_blit_eng2d(struct nv50_context *nv50, const struct pipe_blit_info *info) 1522{ 1523 struct nouveau_pushbuf *push = nv50->base.pushbuf; 1524 struct nv50_miptree *dst = nv50_miptree(info->dst.resource); 1525 struct nv50_miptree *src = nv50_miptree(info->src.resource); 1526 const int32_t srcx_adj = info->src.box.width < 0 ? -1 : 0; 1527 const int32_t srcy_adj = info->src.box.height < 0 ? -1 : 0; 1528 const int32_t dz = info->dst.box.z; 1529 const int32_t sz = info->src.box.z; 1530 uint32_t dstw, dsth; 1531 int32_t dstx, dsty; 1532 int64_t srcx, srcy; 1533 int64_t du_dx, dv_dy; 1534 int i; 1535 uint32_t mode; 1536 uint32_t mask = nv50_blit_eng2d_get_mask(info); 1537 bool b; 1538 1539 mode = nv50_blit_get_filter(info) ? 1540 NV50_2D_BLIT_CONTROL_FILTER_BILINEAR : 1541 NV50_2D_BLIT_CONTROL_FILTER_POINT_SAMPLE; 1542 mode |= (src->base.base.nr_samples > dst->base.base.nr_samples) ? 1543 NV50_2D_BLIT_CONTROL_ORIGIN_CORNER : NV50_2D_BLIT_CONTROL_ORIGIN_CENTER; 1544 1545 du_dx = ((int64_t)info->src.box.width << 32) / info->dst.box.width; 1546 dv_dy = ((int64_t)info->src.box.height << 32) / info->dst.box.height; 1547 1548 b = info->dst.format == info->src.format; 1549 nv50_2d_texture_set(push, 1, dst, info->dst.level, dz, info->dst.format, b); 1550 nv50_2d_texture_set(push, 0, src, info->src.level, sz, info->src.format, b); 1551 1552 if (info->scissor_enable) { 1553 BEGIN_NV04(push, NV50_2D(CLIP_X), 5); 1554 PUSH_DATA (push, info->scissor.minx << dst->ms_x); 1555 PUSH_DATA (push, info->scissor.miny << dst->ms_y); 1556 PUSH_DATA (push, (info->scissor.maxx - info->scissor.minx) << dst->ms_x); 1557 PUSH_DATA (push, (info->scissor.maxy - info->scissor.miny) << dst->ms_y); 1558 PUSH_DATA (push, 1); /* enable */ 1559 } 1560 1561 if (nv50->cond_query && info->render_condition_enable) { 1562 BEGIN_NV04(push, NV50_2D(COND_MODE), 1); 1563 PUSH_DATA (push, nv50->cond_condmode); 1564 } 1565 1566 if (mask != 0xffffffff) { 1567 BEGIN_NV04(push, NV50_2D(ROP), 1); 1568 PUSH_DATA (push, 0xca); /* DPSDxax */ 1569 BEGIN_NV04(push, NV50_2D(PATTERN_COLOR_FORMAT), 1); 1570 PUSH_DATA (push, NV50_2D_PATTERN_COLOR_FORMAT_A8R8G8B8); 1571 BEGIN_NV04(push, NV50_2D(PATTERN_BITMAP_COLOR(0)), 4); 1572 PUSH_DATA (push, 0x00000000); 1573 PUSH_DATA (push, mask); 1574 PUSH_DATA (push, 0xffffffff); 1575 PUSH_DATA (push, 0xffffffff); 1576 BEGIN_NV04(push, NV50_2D(OPERATION), 1); 1577 PUSH_DATA (push, NV50_2D_OPERATION_ROP); 1578 } else 1579 if (info->src.format != info->dst.format) { 1580 if (info->src.format == PIPE_FORMAT_R8_UNORM || 1581 info->src.format == PIPE_FORMAT_R16_UNORM || 1582 info->src.format == PIPE_FORMAT_R16_FLOAT || 1583 info->src.format == PIPE_FORMAT_R32_FLOAT) { 1584 mask = 0xffff0000; /* also makes condition for OPERATION reset true */ 1585 BEGIN_NV04(push, NV50_2D(BETA4), 2); 1586 PUSH_DATA (push, mask); 1587 PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY_PREMULT); 1588 } 1589 } 1590 1591 if (src->ms_x > dst->ms_x || src->ms_y > dst->ms_y) { 1592 /* ms_x is always >= ms_y */ 1593 du_dx <<= src->ms_x - dst->ms_x; 1594 dv_dy <<= src->ms_y - dst->ms_y; 1595 } else { 1596 du_dx >>= dst->ms_x - src->ms_x; 1597 dv_dy >>= dst->ms_y - src->ms_y; 1598 } 1599 1600 srcx = (int64_t)(info->src.box.x + srcx_adj) << (src->ms_x + 32); 1601 srcy = (int64_t)(info->src.box.y + srcy_adj) << (src->ms_y + 32); 1602 1603 if (src->base.base.nr_samples > dst->base.base.nr_samples) { 1604 /* center src coorinates for proper MS resolve filtering */ 1605 srcx += (int64_t)1 << (src->ms_x + 31); 1606 srcy += (int64_t)1 << (src->ms_y + 31); 1607 } 1608 1609 dstx = info->dst.box.x << dst->ms_x; 1610 dsty = info->dst.box.y << dst->ms_y; 1611 1612 dstw = info->dst.box.width << dst->ms_x; 1613 dsth = info->dst.box.height << dst->ms_y; 1614 1615 if (dstx < 0) { 1616 dstw += dstx; 1617 srcx -= du_dx * dstx; 1618 dstx = 0; 1619 } 1620 if (dsty < 0) { 1621 dsth += dsty; 1622 srcy -= dv_dy * dsty; 1623 dsty = 0; 1624 } 1625 1626 BEGIN_NV04(push, NV50_2D(BLIT_CONTROL), 1); 1627 PUSH_DATA (push, mode); 1628 BEGIN_NV04(push, NV50_2D(BLIT_DST_X), 4); 1629 PUSH_DATA (push, dstx); 1630 PUSH_DATA (push, dsty); 1631 PUSH_DATA (push, dstw); 1632 PUSH_DATA (push, dsth); 1633 BEGIN_NV04(push, NV50_2D(BLIT_DU_DX_FRACT), 4); 1634 PUSH_DATA (push, du_dx); 1635 PUSH_DATA (push, du_dx >> 32); 1636 PUSH_DATA (push, dv_dy); 1637 PUSH_DATA (push, dv_dy >> 32); 1638 1639 BCTX_REFN(nv50->bufctx, 2D, &dst->base, WR); 1640 BCTX_REFN(nv50->bufctx, 2D, &src->base, RD); 1641 nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx); 1642 if (nouveau_pushbuf_validate(nv50->base.pushbuf)) 1643 return; 1644 1645 for (i = 0; i < info->dst.box.depth; ++i) { 1646 if (i > 0) { 1647 /* no scaling in z-direction possible for eng2d blits */ 1648 if (dst->layout_3d) { 1649 BEGIN_NV04(push, NV50_2D(DST_LAYER), 1); 1650 PUSH_DATA (push, info->dst.box.z + i); 1651 } else { 1652 const unsigned z = info->dst.box.z + i; 1653 const uint64_t address = dst->base.address + 1654 dst->level[info->dst.level].offset + 1655 z * dst->layer_stride; 1656 BEGIN_NV04(push, NV50_2D(DST_ADDRESS_HIGH), 2); 1657 PUSH_DATAh(push, address); 1658 PUSH_DATA (push, address); 1659 } 1660 if (src->layout_3d) { 1661 /* not possible because of depth tiling */ 1662 assert(0); 1663 } else { 1664 const unsigned z = info->src.box.z + i; 1665 const uint64_t address = src->base.address + 1666 src->level[info->src.level].offset + 1667 z * src->layer_stride; 1668 BEGIN_NV04(push, NV50_2D(SRC_ADDRESS_HIGH), 2); 1669 PUSH_DATAh(push, address); 1670 PUSH_DATA (push, address); 1671 } 1672 BEGIN_NV04(push, NV50_2D(BLIT_SRC_Y_INT), 1); /* trigger */ 1673 PUSH_DATA (push, srcy >> 32); 1674 } else { 1675 BEGIN_NV04(push, NV50_2D(BLIT_SRC_X_FRACT), 4); 1676 PUSH_DATA (push, srcx); 1677 PUSH_DATA (push, srcx >> 32); 1678 PUSH_DATA (push, srcy); 1679 PUSH_DATA (push, srcy >> 32); 1680 } 1681 } 1682 nv50_bufctx_fence(nv50->bufctx, false); 1683 1684 nouveau_bufctx_reset(nv50->bufctx, NV50_BIND_2D); 1685 1686 if (info->scissor_enable) { 1687 BEGIN_NV04(push, NV50_2D(CLIP_ENABLE), 1); 1688 PUSH_DATA (push, 0); 1689 } 1690 if (mask != 0xffffffff) { 1691 BEGIN_NV04(push, NV50_2D(OPERATION), 1); 1692 PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY); 1693 } 1694 if (nv50->cond_query && info->render_condition_enable) { 1695 BEGIN_NV04(push, NV50_2D(COND_MODE), 1); 1696 PUSH_DATA (push, NV50_2D_COND_MODE_ALWAYS); 1697 } 1698} 1699 1700static void 1701nv50_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) 1702{ 1703 struct nv50_context *nv50 = nv50_context(pipe); 1704 struct nouveau_pushbuf *push = nv50->base.pushbuf; 1705 bool eng3d = FALSE; 1706 1707 if (info->src.box.width == 0 || info->src.box.height == 0 || 1708 info->dst.box.width == 0 || info->dst.box.height == 0) { 1709 pipe_debug_message(&nv50->base.debug, ERROR, 1710 "Blit with zero-size src or dst box"); 1711 return; 1712 } 1713 1714 if (util_format_is_depth_or_stencil(info->dst.resource->format)) { 1715 if (!(info->mask & PIPE_MASK_ZS)) 1716 return; 1717 if (info->dst.resource->format == PIPE_FORMAT_Z32_FLOAT || 1718 info->dst.resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) 1719 eng3d = true; 1720 if (info->filter != PIPE_TEX_FILTER_NEAREST) 1721 eng3d = true; 1722 } else { 1723 if (!(info->mask & PIPE_MASK_RGBA)) 1724 return; 1725 if (info->mask != PIPE_MASK_RGBA) 1726 eng3d = true; 1727 } 1728 1729 if (nv50_miptree(info->src.resource)->layout_3d) { 1730 eng3d = true; 1731 } else 1732 if (info->src.box.depth != info->dst.box.depth) { 1733 eng3d = true; 1734 debug_printf("blit: cannot filter array or cube textures in z direction"); 1735 } 1736 1737 if (!eng3d && info->dst.format != info->src.format) { 1738 if (!nv50_2d_dst_format_faithful(info->dst.format) || 1739 !nv50_2d_src_format_faithful(info->src.format)) { 1740 eng3d = true; 1741 } else 1742 if (!nv50_2d_src_format_faithful(info->src.format)) { 1743 if (!util_format_is_luminance(info->src.format)) { 1744 if (util_format_is_intensity(info->src.format)) 1745 eng3d = true; 1746 else 1747 if (!nv50_2d_dst_format_ops_supported(info->dst.format)) 1748 eng3d = true; 1749 else 1750 eng3d = !nv50_2d_format_supported(info->src.format); 1751 } 1752 } else 1753 if (util_format_is_luminance_alpha(info->src.format)) 1754 eng3d = true; 1755 } 1756 1757 if (info->src.resource->nr_samples == 8 && 1758 info->dst.resource->nr_samples <= 1) 1759 eng3d = true; 1760 1761 if (info->num_window_rectangles > 0 || info->window_rectangle_include) 1762 eng3d = true; 1763 1764 /* FIXME: can't make this work with eng2d anymore */ 1765 if ((info->src.resource->nr_samples | 1) != 1766 (info->dst.resource->nr_samples | 1)) 1767 eng3d = true; 1768 1769 /* FIXME: find correct src coordinate adjustments */ 1770 if ((info->src.box.width != info->dst.box.width && 1771 info->src.box.width != -info->dst.box.width) || 1772 (info->src.box.height != info->dst.box.height && 1773 info->src.box.height != -info->dst.box.height)) 1774 eng3d = true; 1775 1776 if (nv50->screen->num_occlusion_queries_active) { 1777 BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1); 1778 PUSH_DATA (push, 0); 1779 } 1780 1781 if (!eng3d) 1782 nv50_blit_eng2d(nv50, info); 1783 else 1784 nv50_blit_3d(nv50, info); 1785 1786 if (nv50->screen->num_occlusion_queries_active) { 1787 BEGIN_NV04(push, NV50_3D(SAMPLECNT_ENABLE), 1); 1788 PUSH_DATA (push, 1); 1789 } 1790} 1791 1792static void 1793nv50_flush_resource(struct pipe_context *ctx, 1794 struct pipe_resource *resource) 1795{ 1796} 1797 1798bool 1799nv50_blitter_create(struct nv50_screen *screen) 1800{ 1801 screen->blitter = CALLOC_STRUCT(nv50_blitter); 1802 if (!screen->blitter) { 1803 NOUVEAU_ERR("failed to allocate blitter struct\n"); 1804 return false; 1805 } 1806 1807 (void) mtx_init(&screen->blitter->mutex, mtx_plain); 1808 1809 nv50_blitter_make_vp(screen->blitter); 1810 nv50_blitter_make_sampler(screen->blitter); 1811 1812 return true; 1813} 1814 1815void 1816nv50_blitter_destroy(struct nv50_screen *screen) 1817{ 1818 struct nv50_blitter *blitter = screen->blitter; 1819 unsigned i, m; 1820 1821 for (i = 0; i < NV50_BLIT_MAX_TEXTURE_TYPES; ++i) { 1822 for (m = 0; m < NV50_BLIT_MODES; ++m) { 1823 struct nv50_program *prog = blitter->fp[i][m]; 1824 if (prog) { 1825 nv50_program_destroy(NULL, prog); 1826 FREE((void *)prog->pipe.tokens); 1827 FREE(prog); 1828 } 1829 } 1830 } 1831 1832 mtx_destroy(&blitter->mutex); 1833 FREE(blitter); 1834} 1835 1836bool 1837nv50_blitctx_create(struct nv50_context *nv50) 1838{ 1839 nv50->blit = CALLOC_STRUCT(nv50_blitctx); 1840 if (!nv50->blit) { 1841 NOUVEAU_ERR("failed to allocate blit context\n"); 1842 return false; 1843 } 1844 1845 nv50->blit->nv50 = nv50; 1846 1847 nv50->blit->rast.pipe.half_pixel_center = 1; 1848 1849 return true; 1850} 1851 1852void 1853nv50_init_surface_functions(struct nv50_context *nv50) 1854{ 1855 struct pipe_context *pipe = &nv50->base.pipe; 1856 1857 pipe->resource_copy_region = nv50_resource_copy_region; 1858 pipe->blit = nv50_blit; 1859 pipe->flush_resource = nv50_flush_resource; 1860 pipe->clear_texture = nv50_clear_texture; 1861 pipe->clear_render_target = nv50_clear_render_target; 1862 pipe->clear_depth_stencil = nv50_clear_depth_stencil; 1863 pipe->clear_buffer = nv50_clear_buffer; 1864} 1865