1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2012 Red Hat Inc. 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 * Authors: Ben Skeggs 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "draw/draw_context.h" 27bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "nv_object.xml.h" 30bf215546Sopenharmony_ci#include "nv30/nv30-40_3d.xml.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "nouveau_fence.h" 33bf215546Sopenharmony_ci#include "nv30/nv30_context.h" 34bf215546Sopenharmony_ci#include "nv30/nv30_transfer.h" 35bf215546Sopenharmony_ci#include "nv30/nv30_state.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_cistatic void 38bf215546Sopenharmony_cinv30_context_kick_notify(struct nouveau_pushbuf *push) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci struct nouveau_screen *screen; 41bf215546Sopenharmony_ci struct nv30_context *nv30; 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci if (!push->user_priv) 44bf215546Sopenharmony_ci return; 45bf215546Sopenharmony_ci nv30 = container_of(push->user_priv, struct nv30_context, bufctx); 46bf215546Sopenharmony_ci screen = &nv30->screen->base; 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci nouveau_fence_next(screen); 49bf215546Sopenharmony_ci nouveau_fence_update(screen, true); 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci if (push->bufctx) { 52bf215546Sopenharmony_ci struct nouveau_bufref *bref; 53bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY(bref, &push->bufctx->current, thead) { 54bf215546Sopenharmony_ci struct nv04_resource *res = bref->priv; 55bf215546Sopenharmony_ci if (res && res->mm) { 56bf215546Sopenharmony_ci nouveau_fence_ref(screen->fence.current, &res->fence); 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci if (bref->flags & NOUVEAU_BO_RD) 59bf215546Sopenharmony_ci res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci if (bref->flags & NOUVEAU_BO_WR) { 62bf215546Sopenharmony_ci nouveau_fence_ref(screen->fence.current, &res->fence_wr); 63bf215546Sopenharmony_ci res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING | 64bf215546Sopenharmony_ci NOUVEAU_BUFFER_STATUS_DIRTY; 65bf215546Sopenharmony_ci } 66bf215546Sopenharmony_ci } 67bf215546Sopenharmony_ci } 68bf215546Sopenharmony_ci } 69bf215546Sopenharmony_ci} 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_cistatic void 72bf215546Sopenharmony_cinv30_context_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence, 73bf215546Sopenharmony_ci unsigned flags) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci struct nv30_context *nv30 = nv30_context(pipe); 76bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nv30->base.pushbuf; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci if (fence) 79bf215546Sopenharmony_ci nouveau_fence_ref(nv30->screen->base.fence.current, 80bf215546Sopenharmony_ci (struct nouveau_fence **)fence); 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci PUSH_KICK(push); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci nouveau_context_update_frame_stats(&nv30->base); 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cistatic int 88bf215546Sopenharmony_cinv30_invalidate_resource_storage(struct nouveau_context *nv, 89bf215546Sopenharmony_ci struct pipe_resource *res, 90bf215546Sopenharmony_ci int ref) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci struct nv30_context *nv30 = nv30_context(&nv->pipe); 93bf215546Sopenharmony_ci unsigned i; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci if (res->bind & PIPE_BIND_RENDER_TARGET) { 96bf215546Sopenharmony_ci for (i = 0; i < nv30->framebuffer.nr_cbufs; ++i) { 97bf215546Sopenharmony_ci if (nv30->framebuffer.cbufs[i] && 98bf215546Sopenharmony_ci nv30->framebuffer.cbufs[i]->texture == res) { 99bf215546Sopenharmony_ci nv30->dirty |= NV30_NEW_FRAMEBUFFER; 100bf215546Sopenharmony_ci nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB); 101bf215546Sopenharmony_ci if (!--ref) 102bf215546Sopenharmony_ci return ref; 103bf215546Sopenharmony_ci } 104bf215546Sopenharmony_ci } 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci if (res->bind & PIPE_BIND_DEPTH_STENCIL) { 107bf215546Sopenharmony_ci if (nv30->framebuffer.zsbuf && 108bf215546Sopenharmony_ci nv30->framebuffer.zsbuf->texture == res) { 109bf215546Sopenharmony_ci nv30->dirty |= NV30_NEW_FRAMEBUFFER; 110bf215546Sopenharmony_ci nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB); 111bf215546Sopenharmony_ci if (!--ref) 112bf215546Sopenharmony_ci return ref; 113bf215546Sopenharmony_ci } 114bf215546Sopenharmony_ci } 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci if (res->bind & PIPE_BIND_VERTEX_BUFFER) { 117bf215546Sopenharmony_ci for (i = 0; i < nv30->num_vtxbufs; ++i) { 118bf215546Sopenharmony_ci if (nv30->vtxbuf[i].buffer.resource == res) { 119bf215546Sopenharmony_ci nv30->dirty |= NV30_NEW_ARRAYS; 120bf215546Sopenharmony_ci nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF); 121bf215546Sopenharmony_ci if (!--ref) 122bf215546Sopenharmony_ci return ref; 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci if (res->bind & PIPE_BIND_SAMPLER_VIEW) { 128bf215546Sopenharmony_ci for (i = 0; i < nv30->fragprog.num_textures; ++i) { 129bf215546Sopenharmony_ci if (nv30->fragprog.textures[i] && 130bf215546Sopenharmony_ci nv30->fragprog.textures[i]->texture == res) { 131bf215546Sopenharmony_ci nv30->dirty |= NV30_NEW_FRAGTEX; 132bf215546Sopenharmony_ci nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i)); 133bf215546Sopenharmony_ci if (!--ref) 134bf215546Sopenharmony_ci return ref; 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci for (i = 0; i < nv30->vertprog.num_textures; ++i) { 138bf215546Sopenharmony_ci if (nv30->vertprog.textures[i] && 139bf215546Sopenharmony_ci nv30->vertprog.textures[i]->texture == res) { 140bf215546Sopenharmony_ci nv30->dirty |= NV30_NEW_VERTTEX; 141bf215546Sopenharmony_ci nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VERTTEX(i)); 142bf215546Sopenharmony_ci if (!--ref) 143bf215546Sopenharmony_ci return ref; 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci return ref; 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_cistatic void 152bf215546Sopenharmony_cinv30_context_destroy(struct pipe_context *pipe) 153bf215546Sopenharmony_ci{ 154bf215546Sopenharmony_ci struct nv30_context *nv30 = nv30_context(pipe); 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci if (nv30->blitter) 157bf215546Sopenharmony_ci util_blitter_destroy(nv30->blitter); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci if (nv30->draw) 160bf215546Sopenharmony_ci draw_destroy(nv30->draw); 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci if (nv30->base.pipe.stream_uploader) 163bf215546Sopenharmony_ci u_upload_destroy(nv30->base.pipe.stream_uploader); 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci if (nv30->blit_vp) 166bf215546Sopenharmony_ci nouveau_heap_free(&nv30->blit_vp); 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci if (nv30->blit_fp) 169bf215546Sopenharmony_ci pipe_resource_reference(&nv30->blit_fp, NULL); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci if (nv30->screen->base.pushbuf->user_priv == &nv30->bufctx) 172bf215546Sopenharmony_ci nv30->screen->base.pushbuf->user_priv = NULL; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci nouveau_bufctx_del(&nv30->bufctx); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci if (nv30->screen->cur_ctx == nv30) 177bf215546Sopenharmony_ci nv30->screen->cur_ctx = NULL; 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci nouveau_context_destroy(&nv30->base); 180bf215546Sopenharmony_ci} 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci#define FAIL_CONTEXT_INIT(str, err) \ 183bf215546Sopenharmony_ci do { \ 184bf215546Sopenharmony_ci NOUVEAU_ERR(str, err); \ 185bf215546Sopenharmony_ci nv30_context_destroy(pipe); \ 186bf215546Sopenharmony_ci return NULL; \ 187bf215546Sopenharmony_ci } while(0) 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_cistruct pipe_context * 190bf215546Sopenharmony_cinv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) 191bf215546Sopenharmony_ci{ 192bf215546Sopenharmony_ci struct nv30_screen *screen = nv30_screen(pscreen); 193bf215546Sopenharmony_ci struct nv30_context *nv30 = CALLOC_STRUCT(nv30_context); 194bf215546Sopenharmony_ci struct nouveau_pushbuf *push; 195bf215546Sopenharmony_ci struct pipe_context *pipe; 196bf215546Sopenharmony_ci int ret; 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci if (!nv30) 199bf215546Sopenharmony_ci return NULL; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci nv30->screen = screen; 202bf215546Sopenharmony_ci nv30->base.screen = &screen->base; 203bf215546Sopenharmony_ci nv30->base.copy_data = nv30_transfer_copy_data; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci pipe = &nv30->base.pipe; 206bf215546Sopenharmony_ci pipe->screen = pscreen; 207bf215546Sopenharmony_ci pipe->priv = priv; 208bf215546Sopenharmony_ci pipe->destroy = nv30_context_destroy; 209bf215546Sopenharmony_ci pipe->flush = nv30_context_flush; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci nv30->base.pipe.stream_uploader = u_upload_create_default(&nv30->base.pipe); 212bf215546Sopenharmony_ci if (!nv30->base.pipe.stream_uploader) { 213bf215546Sopenharmony_ci nv30_context_destroy(pipe); 214bf215546Sopenharmony_ci return NULL; 215bf215546Sopenharmony_ci } 216bf215546Sopenharmony_ci nv30->base.pipe.const_uploader = nv30->base.pipe.stream_uploader; 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci /*XXX: *cough* per-context client */ 219bf215546Sopenharmony_ci nv30->base.client = screen->base.client; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci /*XXX: *cough* per-context pushbufs */ 222bf215546Sopenharmony_ci push = screen->base.pushbuf; 223bf215546Sopenharmony_ci nv30->base.pushbuf = push; 224bf215546Sopenharmony_ci push->kick_notify = nv30_context_kick_notify; 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci nv30->base.invalidate_resource_storage = nv30_invalidate_resource_storage; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci ret = nouveau_bufctx_new(nv30->base.client, 64, &nv30->bufctx); 229bf215546Sopenharmony_ci if (ret) { 230bf215546Sopenharmony_ci nv30_context_destroy(pipe); 231bf215546Sopenharmony_ci return NULL; 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci /*XXX: make configurable with performance vs quality, these defaults 235bf215546Sopenharmony_ci * match the binary driver's defaults 236bf215546Sopenharmony_ci */ 237bf215546Sopenharmony_ci if (screen->eng3d->oclass < NV40_3D_CLASS) 238bf215546Sopenharmony_ci nv30->config.filter = 0x00000004; 239bf215546Sopenharmony_ci else 240bf215546Sopenharmony_ci nv30->config.filter = 0x00002dc4; 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci nv30->config.aniso = NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_OFF; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci if (debug_get_bool_option("NV30_SWTNL", false)) 245bf215546Sopenharmony_ci nv30->draw_flags |= NV30_NEW_SWTNL; 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci nouveau_context_init(&nv30->base); 248bf215546Sopenharmony_ci nv30->sample_mask = 0xffff; 249bf215546Sopenharmony_ci nv30_vbo_init(pipe); 250bf215546Sopenharmony_ci nv30_query_init(pipe); 251bf215546Sopenharmony_ci nv30_state_init(pipe); 252bf215546Sopenharmony_ci nv30_resource_init(pipe); 253bf215546Sopenharmony_ci nv30_clear_init(pipe); 254bf215546Sopenharmony_ci nv30_fragprog_init(pipe); 255bf215546Sopenharmony_ci nv30_vertprog_init(pipe); 256bf215546Sopenharmony_ci nv30_texture_init(pipe); 257bf215546Sopenharmony_ci nv30_fragtex_init(pipe); 258bf215546Sopenharmony_ci nv40_verttex_init(pipe); 259bf215546Sopenharmony_ci nv30_draw_init(pipe); 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci nv30->blitter = util_blitter_create(pipe); 262bf215546Sopenharmony_ci if (!nv30->blitter) { 263bf215546Sopenharmony_ci nv30_context_destroy(pipe); 264bf215546Sopenharmony_ci return NULL; 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci nouveau_context_init_vdec(&nv30->base); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci return pipe; 270bf215546Sopenharmony_ci} 271