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