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