1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2010 Christoph Bumiller 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 "pipe/p_defines.h" 24bf215546Sopenharmony_ci#include "util/u_framebuffer.h" 25bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "nvc0/nvc0_context.h" 28bf215546Sopenharmony_ci#include "nvc0/nvc0_screen.h" 29bf215546Sopenharmony_ci#include "nvc0/nvc0_resource.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "xf86drm.h" 33bf215546Sopenharmony_ci#include "nouveau_drm.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_cistatic void 37bf215546Sopenharmony_cinvc0_svm_migrate(struct pipe_context *pipe, unsigned num_ptrs, 38bf215546Sopenharmony_ci const void* const* ptrs, const size_t *sizes, 39bf215546Sopenharmony_ci bool to_device, bool mem_undefined) 40bf215546Sopenharmony_ci{ 41bf215546Sopenharmony_ci struct nvc0_context *nvc0 = nvc0_context(pipe); 42bf215546Sopenharmony_ci struct nouveau_screen *screen = &nvc0->screen->base; 43bf215546Sopenharmony_ci int fd = screen->drm->fd; 44bf215546Sopenharmony_ci unsigned i; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci for (i = 0; i < num_ptrs; i++) { 47bf215546Sopenharmony_ci struct drm_nouveau_svm_bind args; 48bf215546Sopenharmony_ci uint64_t cmd, prio, target; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci args.va_start = (uint64_t)(uintptr_t)ptrs[i]; 51bf215546Sopenharmony_ci if (sizes && sizes[i]) { 52bf215546Sopenharmony_ci args.va_end = (uint64_t)(uintptr_t)ptrs[i] + sizes[i]; 53bf215546Sopenharmony_ci args.npages = DIV_ROUND_UP(args.va_end - args.va_start, 0x1000); 54bf215546Sopenharmony_ci } else { 55bf215546Sopenharmony_ci args.va_end = 0; 56bf215546Sopenharmony_ci args.npages = 0; 57bf215546Sopenharmony_ci } 58bf215546Sopenharmony_ci args.stride = 0; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci args.reserved0 = 0; 61bf215546Sopenharmony_ci args.reserved1 = 0; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci prio = 0; 64bf215546Sopenharmony_ci cmd = NOUVEAU_SVM_BIND_COMMAND__MIGRATE; 65bf215546Sopenharmony_ci target = to_device ? NOUVEAU_SVM_BIND_TARGET__GPU_VRAM : 0; 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci args.header = cmd << NOUVEAU_SVM_BIND_COMMAND_SHIFT; 68bf215546Sopenharmony_ci args.header |= prio << NOUVEAU_SVM_BIND_PRIORITY_SHIFT; 69bf215546Sopenharmony_ci args.header |= target << NOUVEAU_SVM_BIND_TARGET_SHIFT; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci /* This is best effort, so no garanty whatsoever */ 72bf215546Sopenharmony_ci drmCommandWrite(fd, DRM_NOUVEAU_SVM_BIND, 73bf215546Sopenharmony_ci &args, sizeof(args)); 74bf215546Sopenharmony_ci } 75bf215546Sopenharmony_ci} 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_cistatic void 79bf215546Sopenharmony_cinvc0_flush(struct pipe_context *pipe, 80bf215546Sopenharmony_ci struct pipe_fence_handle **fence, 81bf215546Sopenharmony_ci unsigned flags) 82bf215546Sopenharmony_ci{ 83bf215546Sopenharmony_ci struct nvc0_context *nvc0 = nvc0_context(pipe); 84bf215546Sopenharmony_ci struct nouveau_screen *screen = &nvc0->screen->base; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci if (fence) 87bf215546Sopenharmony_ci nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci PUSH_KICK(nvc0->base.pushbuf); /* fencing handled in kick_notify */ 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci nouveau_context_update_frame_stats(&nvc0->base); 92bf215546Sopenharmony_ci} 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_cistatic void 95bf215546Sopenharmony_cinvc0_texture_barrier(struct pipe_context *pipe, unsigned flags) 96bf215546Sopenharmony_ci{ 97bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0_context(pipe)->base.pushbuf; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); 100bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 0); 101bf215546Sopenharmony_ci} 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_cistatic void 104bf215546Sopenharmony_cinvc0_memory_barrier(struct pipe_context *pipe, unsigned flags) 105bf215546Sopenharmony_ci{ 106bf215546Sopenharmony_ci struct nvc0_context *nvc0 = nvc0_context(pipe); 107bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 108bf215546Sopenharmony_ci int i, s; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci if (!(flags & ~PIPE_BARRIER_UPDATE)) 111bf215546Sopenharmony_ci return; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_MAPPED_BUFFER) { 114bf215546Sopenharmony_ci for (i = 0; i < nvc0->num_vtxbufs; ++i) { 115bf215546Sopenharmony_ci if (!nvc0->vtxbuf[i].buffer.resource && !nvc0->vtxbuf[i].is_user_buffer) 116bf215546Sopenharmony_ci continue; 117bf215546Sopenharmony_ci if (nvc0->vtxbuf[i].buffer.resource->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) 118bf215546Sopenharmony_ci nvc0->base.vbo_dirty = true; 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci for (s = 0; s < 5 && !nvc0->cb_dirty; ++s) { 122bf215546Sopenharmony_ci uint32_t valid = nvc0->constbuf_valid[s]; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci while (valid && !nvc0->cb_dirty) { 125bf215546Sopenharmony_ci const unsigned i = ffs(valid) - 1; 126bf215546Sopenharmony_ci struct pipe_resource *res; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci valid &= ~(1 << i); 129bf215546Sopenharmony_ci if (nvc0->constbuf[s][i].user) 130bf215546Sopenharmony_ci continue; 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci res = nvc0->constbuf[s][i].u.buf; 133bf215546Sopenharmony_ci if (!res) 134bf215546Sopenharmony_ci continue; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci if (res->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) 137bf215546Sopenharmony_ci nvc0->cb_dirty = true; 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci } else { 141bf215546Sopenharmony_ci /* Pretty much any writing by shaders needs a serialize after 142bf215546Sopenharmony_ci * it. Especially when moving between 3d and compute pipelines, but even 143bf215546Sopenharmony_ci * without that. 144bf215546Sopenharmony_ci */ 145bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci /* If we're going to texture from a buffer/image written by a shader, we 149bf215546Sopenharmony_ci * must flush the texture cache. 150bf215546Sopenharmony_ci */ 151bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_TEXTURE) 152bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 0); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci if (flags & PIPE_BARRIER_CONSTANT_BUFFER) 155bf215546Sopenharmony_ci nvc0->cb_dirty = true; 156bf215546Sopenharmony_ci if (flags & (PIPE_BARRIER_VERTEX_BUFFER | PIPE_BARRIER_INDEX_BUFFER)) 157bf215546Sopenharmony_ci nvc0->base.vbo_dirty = true; 158bf215546Sopenharmony_ci} 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_cistatic void 161bf215546Sopenharmony_cinvc0_emit_string_marker(struct pipe_context *pipe, const char *str, int len) 162bf215546Sopenharmony_ci{ 163bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0_context(pipe)->base.pushbuf; 164bf215546Sopenharmony_ci int string_words = len / 4; 165bf215546Sopenharmony_ci int data_words; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci if (len <= 0) 168bf215546Sopenharmony_ci return; 169bf215546Sopenharmony_ci string_words = MIN2(string_words, NV04_PFIFO_MAX_PACKET_LEN); 170bf215546Sopenharmony_ci if (string_words == NV04_PFIFO_MAX_PACKET_LEN) 171bf215546Sopenharmony_ci data_words = string_words; 172bf215546Sopenharmony_ci else 173bf215546Sopenharmony_ci data_words = string_words + !!(len & 3); 174bf215546Sopenharmony_ci BEGIN_NIC0(push, SUBC_3D(NV04_GRAPH_NOP), data_words); 175bf215546Sopenharmony_ci if (string_words) 176bf215546Sopenharmony_ci PUSH_DATAp(push, str, string_words); 177bf215546Sopenharmony_ci if (string_words != data_words) { 178bf215546Sopenharmony_ci int data = 0; 179bf215546Sopenharmony_ci memcpy(&data, &str[string_words * 4], len & 3); 180bf215546Sopenharmony_ci PUSH_DATA (push, data); 181bf215546Sopenharmony_ci } 182bf215546Sopenharmony_ci} 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_cistatic enum pipe_reset_status 185bf215546Sopenharmony_cinvc0_get_device_reset_status(struct pipe_context *pipe) 186bf215546Sopenharmony_ci{ 187bf215546Sopenharmony_ci return PIPE_NO_RESET; 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic void 191bf215546Sopenharmony_cinvc0_context_unreference_resources(struct nvc0_context *nvc0) 192bf215546Sopenharmony_ci{ 193bf215546Sopenharmony_ci unsigned s, i; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci nouveau_bufctx_del(&nvc0->bufctx_3d); 196bf215546Sopenharmony_ci nouveau_bufctx_del(&nvc0->bufctx); 197bf215546Sopenharmony_ci nouveau_bufctx_del(&nvc0->bufctx_cp); 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci util_unreference_framebuffer_state(&nvc0->framebuffer); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci for (i = 0; i < nvc0->num_vtxbufs; ++i) 202bf215546Sopenharmony_ci pipe_vertex_buffer_unreference(&nvc0->vtxbuf[i]); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci for (s = 0; s < 6; ++s) { 205bf215546Sopenharmony_ci for (i = 0; i < nvc0->num_textures[s]; ++i) 206bf215546Sopenharmony_ci pipe_sampler_view_reference(&nvc0->textures[s][i], NULL); 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i) 209bf215546Sopenharmony_ci if (!nvc0->constbuf[s][i].user) 210bf215546Sopenharmony_ci pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, NULL); 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci for (i = 0; i < NVC0_MAX_BUFFERS; ++i) 213bf215546Sopenharmony_ci pipe_resource_reference(&nvc0->buffers[s][i].buffer, NULL); 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci for (i = 0; i < NVC0_MAX_IMAGES; ++i) { 216bf215546Sopenharmony_ci pipe_resource_reference(&nvc0->images[s][i].resource, NULL); 217bf215546Sopenharmony_ci if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) 218bf215546Sopenharmony_ci pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL); 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci for (s = 0; s < 2; ++s) { 223bf215546Sopenharmony_ci for (i = 0; i < NVC0_MAX_SURFACE_SLOTS; ++i) 224bf215546Sopenharmony_ci pipe_surface_reference(&nvc0->surfaces[s][i], NULL); 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci for (i = 0; i < nvc0->num_tfbbufs; ++i) 228bf215546Sopenharmony_ci pipe_so_target_reference(&nvc0->tfbbuf[i], NULL); 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci for (i = 0; i < nvc0->global_residents.size / sizeof(struct pipe_resource *); 231bf215546Sopenharmony_ci ++i) { 232bf215546Sopenharmony_ci struct pipe_resource **res = util_dynarray_element( 233bf215546Sopenharmony_ci &nvc0->global_residents, struct pipe_resource *, i); 234bf215546Sopenharmony_ci pipe_resource_reference(res, NULL); 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci util_dynarray_fini(&nvc0->global_residents); 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci if (nvc0->tcp_empty) 239bf215546Sopenharmony_ci nvc0->base.pipe.delete_tcs_state(&nvc0->base.pipe, nvc0->tcp_empty); 240bf215546Sopenharmony_ci} 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_cistatic void 243bf215546Sopenharmony_cinvc0_destroy(struct pipe_context *pipe) 244bf215546Sopenharmony_ci{ 245bf215546Sopenharmony_ci struct nvc0_context *nvc0 = nvc0_context(pipe); 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci if (nvc0->screen->cur_ctx == nvc0) { 248bf215546Sopenharmony_ci nvc0->screen->cur_ctx = NULL; 249bf215546Sopenharmony_ci nvc0->screen->save_state = nvc0->state; 250bf215546Sopenharmony_ci nvc0->screen->save_state.tfb = NULL; 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if (nvc0->base.pipe.stream_uploader) 254bf215546Sopenharmony_ci u_upload_destroy(nvc0->base.pipe.stream_uploader); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci /* Unset bufctx, we don't want to revalidate any resources after the flush. 257bf215546Sopenharmony_ci * Other contexts will always set their bufctx again on action calls. 258bf215546Sopenharmony_ci */ 259bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(nvc0->base.pushbuf, NULL); 260bf215546Sopenharmony_ci nouveau_pushbuf_kick(nvc0->base.pushbuf, nvc0->base.pushbuf->channel); 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci nvc0_context_unreference_resources(nvc0); 263bf215546Sopenharmony_ci nvc0_blitctx_destroy(nvc0); 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci list_for_each_entry_safe(struct nvc0_resident, pos, &nvc0->tex_head, list) { 266bf215546Sopenharmony_ci list_del(&pos->list); 267bf215546Sopenharmony_ci free(pos); 268bf215546Sopenharmony_ci } 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci list_for_each_entry_safe(struct nvc0_resident, pos, &nvc0->img_head, list) { 271bf215546Sopenharmony_ci list_del(&pos->list); 272bf215546Sopenharmony_ci free(pos); 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci nouveau_context_destroy(&nvc0->base); 276bf215546Sopenharmony_ci} 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_civoid 279bf215546Sopenharmony_cinvc0_default_kick_notify(struct nouveau_pushbuf *push) 280bf215546Sopenharmony_ci{ 281bf215546Sopenharmony_ci struct nvc0_screen *screen = push->user_priv; 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci if (screen) { 284bf215546Sopenharmony_ci nouveau_fence_next(&screen->base); 285bf215546Sopenharmony_ci nouveau_fence_update(&screen->base, true); 286bf215546Sopenharmony_ci if (screen->cur_ctx) 287bf215546Sopenharmony_ci screen->cur_ctx->state.flushed = true; 288bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1); 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci} 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_cistatic int 293bf215546Sopenharmony_cinvc0_invalidate_resource_storage(struct nouveau_context *ctx, 294bf215546Sopenharmony_ci struct pipe_resource *res, 295bf215546Sopenharmony_ci int ref) 296bf215546Sopenharmony_ci{ 297bf215546Sopenharmony_ci struct nvc0_context *nvc0 = nvc0_context(&ctx->pipe); 298bf215546Sopenharmony_ci unsigned s, i; 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci if (res->bind & PIPE_BIND_RENDER_TARGET) { 301bf215546Sopenharmony_ci for (i = 0; i < nvc0->framebuffer.nr_cbufs; ++i) { 302bf215546Sopenharmony_ci if (nvc0->framebuffer.cbufs[i] && 303bf215546Sopenharmony_ci nvc0->framebuffer.cbufs[i]->texture == res) { 304bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER; 305bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB); 306bf215546Sopenharmony_ci if (!--ref) 307bf215546Sopenharmony_ci return ref; 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci } 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci if (res->bind & PIPE_BIND_DEPTH_STENCIL) { 312bf215546Sopenharmony_ci if (nvc0->framebuffer.zsbuf && 313bf215546Sopenharmony_ci nvc0->framebuffer.zsbuf->texture == res) { 314bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER; 315bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB); 316bf215546Sopenharmony_ci if (!--ref) 317bf215546Sopenharmony_ci return ref; 318bf215546Sopenharmony_ci } 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci if (res->target == PIPE_BUFFER) { 322bf215546Sopenharmony_ci for (i = 0; i < nvc0->num_vtxbufs; ++i) { 323bf215546Sopenharmony_ci if (nvc0->vtxbuf[i].buffer.resource == res) { 324bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_ARRAYS; 325bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX); 326bf215546Sopenharmony_ci if (!--ref) 327bf215546Sopenharmony_ci return ref; 328bf215546Sopenharmony_ci } 329bf215546Sopenharmony_ci } 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci for (s = 0; s < 6; ++s) { 332bf215546Sopenharmony_ci for (i = 0; i < nvc0->num_textures[s]; ++i) { 333bf215546Sopenharmony_ci if (nvc0->textures[s][i] && 334bf215546Sopenharmony_ci nvc0->textures[s][i]->texture == res) { 335bf215546Sopenharmony_ci nvc0->textures_dirty[s] |= 1 << i; 336bf215546Sopenharmony_ci if (unlikely(s == 5)) { 337bf215546Sopenharmony_ci nvc0->dirty_cp |= NVC0_NEW_CP_TEXTURES; 338bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i)); 339bf215546Sopenharmony_ci } else { 340bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_TEXTURES; 341bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i)); 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci if (!--ref) 344bf215546Sopenharmony_ci return ref; 345bf215546Sopenharmony_ci } 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci } 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci for (s = 0; s < 6; ++s) { 350bf215546Sopenharmony_ci for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i) { 351bf215546Sopenharmony_ci if (!(nvc0->constbuf_valid[s] & (1 << i))) 352bf215546Sopenharmony_ci continue; 353bf215546Sopenharmony_ci if (!nvc0->constbuf[s][i].user && 354bf215546Sopenharmony_ci nvc0->constbuf[s][i].u.buf == res) { 355bf215546Sopenharmony_ci nvc0->constbuf_dirty[s] |= 1 << i; 356bf215546Sopenharmony_ci if (unlikely(s == 5)) { 357bf215546Sopenharmony_ci nvc0->dirty_cp |= NVC0_NEW_CP_CONSTBUF; 358bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_CB(i)); 359bf215546Sopenharmony_ci } else { 360bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_CONSTBUF; 361bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_CB(s, i)); 362bf215546Sopenharmony_ci } 363bf215546Sopenharmony_ci if (!--ref) 364bf215546Sopenharmony_ci return ref; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci } 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci for (s = 0; s < 6; ++s) { 370bf215546Sopenharmony_ci for (i = 0; i < NVC0_MAX_BUFFERS; ++i) { 371bf215546Sopenharmony_ci if (nvc0->buffers[s][i].buffer == res) { 372bf215546Sopenharmony_ci nvc0->buffers_dirty[s] |= 1 << i; 373bf215546Sopenharmony_ci if (unlikely(s == 5)) { 374bf215546Sopenharmony_ci nvc0->dirty_cp |= NVC0_NEW_CP_BUFFERS; 375bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_BUF); 376bf215546Sopenharmony_ci } else { 377bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_BUFFERS; 378bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_BUF); 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci if (!--ref) 381bf215546Sopenharmony_ci return ref; 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci } 384bf215546Sopenharmony_ci } 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci for (s = 0; s < 6; ++s) { 387bf215546Sopenharmony_ci for (i = 0; i < NVC0_MAX_IMAGES; ++i) { 388bf215546Sopenharmony_ci if (nvc0->images[s][i].resource == res) { 389bf215546Sopenharmony_ci nvc0->images_dirty[s] |= 1 << i; 390bf215546Sopenharmony_ci if (unlikely(s == 5)) { 391bf215546Sopenharmony_ci nvc0->dirty_cp |= NVC0_NEW_CP_SURFACES; 392bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF); 393bf215546Sopenharmony_ci } else { 394bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_SURFACES; 395bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF); 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci } 398bf215546Sopenharmony_ci if (!--ref) 399bf215546Sopenharmony_ci return ref; 400bf215546Sopenharmony_ci } 401bf215546Sopenharmony_ci } 402bf215546Sopenharmony_ci } 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci return ref; 405bf215546Sopenharmony_ci} 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_cistatic void 408bf215546Sopenharmony_cinvc0_context_get_sample_position(struct pipe_context *, unsigned, unsigned, 409bf215546Sopenharmony_ci float *); 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_cistruct pipe_context * 412bf215546Sopenharmony_cinvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) 413bf215546Sopenharmony_ci{ 414bf215546Sopenharmony_ci struct nvc0_screen *screen = nvc0_screen(pscreen); 415bf215546Sopenharmony_ci struct nvc0_context *nvc0; 416bf215546Sopenharmony_ci struct pipe_context *pipe; 417bf215546Sopenharmony_ci int ret; 418bf215546Sopenharmony_ci uint32_t flags; 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci nvc0 = CALLOC_STRUCT(nvc0_context); 421bf215546Sopenharmony_ci if (!nvc0) 422bf215546Sopenharmony_ci return NULL; 423bf215546Sopenharmony_ci pipe = &nvc0->base.pipe; 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci if (!nvc0_blitctx_create(nvc0)) 426bf215546Sopenharmony_ci goto out_err; 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci nvc0->base.pushbuf = screen->base.pushbuf; 429bf215546Sopenharmony_ci nvc0->base.client = screen->base.client; 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci ret = nouveau_bufctx_new(nvc0->base.client, 2, &nvc0->bufctx); 432bf215546Sopenharmony_ci if (!ret) 433bf215546Sopenharmony_ci ret = nouveau_bufctx_new(nvc0->base.client, NVC0_BIND_3D_COUNT, 434bf215546Sopenharmony_ci &nvc0->bufctx_3d); 435bf215546Sopenharmony_ci if (!ret) 436bf215546Sopenharmony_ci ret = nouveau_bufctx_new(nvc0->base.client, NVC0_BIND_CP_COUNT, 437bf215546Sopenharmony_ci &nvc0->bufctx_cp); 438bf215546Sopenharmony_ci if (ret) 439bf215546Sopenharmony_ci goto out_err; 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci nvc0->screen = screen; 442bf215546Sopenharmony_ci nvc0->base.screen = &screen->base; 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci pipe->screen = pscreen; 445bf215546Sopenharmony_ci pipe->priv = priv; 446bf215546Sopenharmony_ci pipe->stream_uploader = u_upload_create_default(pipe); 447bf215546Sopenharmony_ci if (!pipe->stream_uploader) 448bf215546Sopenharmony_ci goto out_err; 449bf215546Sopenharmony_ci pipe->const_uploader = pipe->stream_uploader; 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci pipe->destroy = nvc0_destroy; 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci pipe->draw_vbo = nvc0_draw_vbo; 454bf215546Sopenharmony_ci pipe->clear = nvc0_clear; 455bf215546Sopenharmony_ci pipe->launch_grid = (nvc0->screen->base.class_3d >= NVE4_3D_CLASS) ? 456bf215546Sopenharmony_ci nve4_launch_grid : nvc0_launch_grid; 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci pipe->svm_migrate = nvc0_svm_migrate; 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci pipe->flush = nvc0_flush; 461bf215546Sopenharmony_ci pipe->texture_barrier = nvc0_texture_barrier; 462bf215546Sopenharmony_ci pipe->memory_barrier = nvc0_memory_barrier; 463bf215546Sopenharmony_ci pipe->get_sample_position = nvc0_context_get_sample_position; 464bf215546Sopenharmony_ci pipe->emit_string_marker = nvc0_emit_string_marker; 465bf215546Sopenharmony_ci pipe->get_device_reset_status = nvc0_get_device_reset_status; 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci nouveau_context_init(&nvc0->base); 468bf215546Sopenharmony_ci nvc0_init_query_functions(nvc0); 469bf215546Sopenharmony_ci nvc0_init_surface_functions(nvc0); 470bf215546Sopenharmony_ci nvc0_init_state_functions(nvc0); 471bf215546Sopenharmony_ci nvc0_init_transfer_functions(nvc0); 472bf215546Sopenharmony_ci nvc0_init_resource_functions(pipe); 473bf215546Sopenharmony_ci if (nvc0->screen->base.class_3d >= NVE4_3D_CLASS) 474bf215546Sopenharmony_ci nvc0_init_bindless_functions(pipe); 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci list_inithead(&nvc0->tex_head); 477bf215546Sopenharmony_ci list_inithead(&nvc0->img_head); 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci nvc0->base.invalidate_resource_storage = nvc0_invalidate_resource_storage; 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci pipe->create_video_codec = nvc0_create_decoder; 482bf215546Sopenharmony_ci pipe->create_video_buffer = nvc0_video_buffer_create; 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci /* shader builtin library is per-screen, but we need a context for m2mf */ 485bf215546Sopenharmony_ci nvc0_program_library_upload(nvc0); 486bf215546Sopenharmony_ci nvc0_program_init_tcp_empty(nvc0); 487bf215546Sopenharmony_ci if (!nvc0->tcp_empty) 488bf215546Sopenharmony_ci goto out_err; 489bf215546Sopenharmony_ci /* set the empty tctl prog on next draw in case one is never set */ 490bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_TCTLPROG; 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci /* Do not bind the COMPUTE driver constbuf at screen initialization because 493bf215546Sopenharmony_ci * CBs are aliased between 3D and COMPUTE, but make sure it will be bound if 494bf215546Sopenharmony_ci * a grid is launched later. */ 495bf215546Sopenharmony_ci nvc0->dirty_cp |= NVC0_NEW_CP_DRIVERCONST; 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci /* now that there are no more opportunities for errors, set the current 498bf215546Sopenharmony_ci * context if there isn't already one. 499bf215546Sopenharmony_ci */ 500bf215546Sopenharmony_ci if (!screen->cur_ctx) { 501bf215546Sopenharmony_ci nvc0->state = screen->save_state; 502bf215546Sopenharmony_ci screen->cur_ctx = nvc0; 503bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx); 504bf215546Sopenharmony_ci } 505bf215546Sopenharmony_ci screen->base.pushbuf->kick_notify = nvc0_default_kick_notify; 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci /* add permanently resident buffers to bufctxts */ 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci flags = NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RD; 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_3d, 3D_SCREEN, flags, screen->uniform_bo); 512bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_3d, 3D_SCREEN, flags, screen->txc); 513bf215546Sopenharmony_ci if (screen->compute) { 514bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->uniform_bo); 515bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->txc); 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci flags = NV_VRAM_DOMAIN(&screen->base) | NOUVEAU_BO_RDWR; 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci if (screen->poly_cache) 521bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_3d, 3D_SCREEN, flags, screen->poly_cache); 522bf215546Sopenharmony_ci if (screen->compute) 523bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->tls); 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR; 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_3d, 3D_SCREEN, flags, screen->fence.bo); 528bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->fence.bo); 529bf215546Sopenharmony_ci if (screen->compute) 530bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->fence.bo); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci nvc0->base.scratch.bo_size = 2 << 20; 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci memset(nvc0->tex_handles, ~0, sizeof(nvc0->tex_handles)); 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci util_dynarray_init(&nvc0->global_residents, NULL); 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci // Make sure that the first TSC entry has SRGB conversion bit set, since we 539bf215546Sopenharmony_ci // use it as a fallback on Fermi for TXF, and on Kepler+ generations for 540bf215546Sopenharmony_ci // FBFETCH handling (which also uses TXF). 541bf215546Sopenharmony_ci // 542bf215546Sopenharmony_ci // NOTE: Preliminary testing suggests that this isn't necessary at all at 543bf215546Sopenharmony_ci // least on GM20x (untested on Kepler). However this is ~free, so no reason 544bf215546Sopenharmony_ci // not to do it. 545bf215546Sopenharmony_ci if (!screen->tsc.entries[0]) 546bf215546Sopenharmony_ci nvc0_upload_tsc0(nvc0); 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci // On Fermi, mark samplers dirty so that the proper binding can happen 549bf215546Sopenharmony_ci if (screen->base.class_3d < NVE4_3D_CLASS) { 550bf215546Sopenharmony_ci for (int s = 0; s < 6; s++) 551bf215546Sopenharmony_ci nvc0->samplers_dirty[s] = 1; 552bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_SAMPLERS; 553bf215546Sopenharmony_ci nvc0->dirty_cp |= NVC0_NEW_CP_SAMPLERS; 554bf215546Sopenharmony_ci } 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci return pipe; 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ciout_err: 559bf215546Sopenharmony_ci if (nvc0) { 560bf215546Sopenharmony_ci if (pipe->stream_uploader) 561bf215546Sopenharmony_ci u_upload_destroy(pipe->stream_uploader); 562bf215546Sopenharmony_ci if (nvc0->bufctx_3d) 563bf215546Sopenharmony_ci nouveau_bufctx_del(&nvc0->bufctx_3d); 564bf215546Sopenharmony_ci if (nvc0->bufctx_cp) 565bf215546Sopenharmony_ci nouveau_bufctx_del(&nvc0->bufctx_cp); 566bf215546Sopenharmony_ci if (nvc0->bufctx) 567bf215546Sopenharmony_ci nouveau_bufctx_del(&nvc0->bufctx); 568bf215546Sopenharmony_ci FREE(nvc0->blit); 569bf215546Sopenharmony_ci FREE(nvc0); 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci return NULL; 572bf215546Sopenharmony_ci} 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_civoid 575bf215546Sopenharmony_cinvc0_bufctx_fence(struct nvc0_context *nvc0, struct nouveau_bufctx *bufctx, 576bf215546Sopenharmony_ci bool on_flush) 577bf215546Sopenharmony_ci{ 578bf215546Sopenharmony_ci struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending; 579bf215546Sopenharmony_ci struct nouveau_list *it; 580bf215546Sopenharmony_ci NOUVEAU_DRV_STAT_IFD(unsigned count = 0); 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_ci for (it = list->next; it != list; it = it->next) { 583bf215546Sopenharmony_ci struct nouveau_bufref *ref = (struct nouveau_bufref *)it; 584bf215546Sopenharmony_ci struct nv04_resource *res = ref->priv; 585bf215546Sopenharmony_ci if (res) 586bf215546Sopenharmony_ci nvc0_resource_validate(res, (unsigned)ref->priv_data); 587bf215546Sopenharmony_ci NOUVEAU_DRV_STAT_IFD(count++); 588bf215546Sopenharmony_ci } 589bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&nvc0->screen->base, resource_validate_count, count); 590bf215546Sopenharmony_ci} 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ciconst void * 593bf215546Sopenharmony_cinvc0_get_sample_locations(unsigned sample_count) 594bf215546Sopenharmony_ci{ 595bf215546Sopenharmony_ci static const uint8_t ms1[1][2] = { { 0x8, 0x8 } }; 596bf215546Sopenharmony_ci static const uint8_t ms2[2][2] = { 597bf215546Sopenharmony_ci { 0x4, 0x4 }, { 0xc, 0xc } }; /* surface coords (0,0), (1,0) */ 598bf215546Sopenharmony_ci static const uint8_t ms4[4][2] = { 599bf215546Sopenharmony_ci { 0x6, 0x2 }, { 0xe, 0x6 }, /* (0,0), (1,0) */ 600bf215546Sopenharmony_ci { 0x2, 0xa }, { 0xa, 0xe } }; /* (0,1), (1,1) */ 601bf215546Sopenharmony_ci static const uint8_t ms8[8][2] = { 602bf215546Sopenharmony_ci { 0x1, 0x7 }, { 0x5, 0x3 }, /* (0,0), (1,0) */ 603bf215546Sopenharmony_ci { 0x3, 0xd }, { 0x7, 0xb }, /* (0,1), (1,1) */ 604bf215546Sopenharmony_ci { 0x9, 0x5 }, { 0xf, 0x1 }, /* (2,0), (3,0) */ 605bf215546Sopenharmony_ci { 0xb, 0xf }, { 0xd, 0x9 } }; /* (2,1), (3,1) */ 606bf215546Sopenharmony_ci#if 0 607bf215546Sopenharmony_ci /* NOTE: there are alternative modes for MS2 and MS8, currently not used */ 608bf215546Sopenharmony_ci static const uint8_t ms8_alt[8][2] = { 609bf215546Sopenharmony_ci { 0x9, 0x5 }, { 0x7, 0xb }, /* (2,0), (1,1) */ 610bf215546Sopenharmony_ci { 0xd, 0x9 }, { 0x5, 0x3 }, /* (3,1), (1,0) */ 611bf215546Sopenharmony_ci { 0x3, 0xd }, { 0x1, 0x7 }, /* (0,1), (0,0) */ 612bf215546Sopenharmony_ci { 0xb, 0xf }, { 0xf, 0x1 } }; /* (2,1), (3,0) */ 613bf215546Sopenharmony_ci#endif 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci const uint8_t (*ptr)[2]; 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci switch (sample_count) { 618bf215546Sopenharmony_ci case 0: 619bf215546Sopenharmony_ci case 1: ptr = ms1; break; 620bf215546Sopenharmony_ci case 2: ptr = ms2; break; 621bf215546Sopenharmony_ci case 4: ptr = ms4; break; 622bf215546Sopenharmony_ci case 8: ptr = ms8; break; 623bf215546Sopenharmony_ci default: 624bf215546Sopenharmony_ci assert(0); 625bf215546Sopenharmony_ci return NULL; /* bad sample count -> undefined locations */ 626bf215546Sopenharmony_ci } 627bf215546Sopenharmony_ci return ptr; 628bf215546Sopenharmony_ci} 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_cistatic void 631bf215546Sopenharmony_cinvc0_context_get_sample_position(struct pipe_context *pipe, 632bf215546Sopenharmony_ci unsigned sample_count, unsigned sample_index, 633bf215546Sopenharmony_ci float *xy) 634bf215546Sopenharmony_ci{ 635bf215546Sopenharmony_ci const uint8_t (*ptr)[2]; 636bf215546Sopenharmony_ci 637bf215546Sopenharmony_ci ptr = nvc0_get_sample_locations(sample_count); 638bf215546Sopenharmony_ci if (!ptr) 639bf215546Sopenharmony_ci return; 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ci xy[0] = ptr[sample_index][0] * 0.0625f; 642bf215546Sopenharmony_ci xy[1] = ptr[sample_index][1] * 0.0625f; 643bf215546Sopenharmony_ci} 644