2 * Copyright 2012 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "draw/draw_context.h"
27 #include "util/u_upload_mgr.h"
29 #include "nv_object.xml.h"
30 #include "nv30/nv30-40_3d.xml.h"
32 #include "nouveau_fence.h"
33 #include "nv30/nv30_context.h"
34 #include "nv30/nv30_transfer.h"
35 #include "nv30/nv30_state.h"
38 nv30_context_kick_notify(struct nouveau_pushbuf
*push
)
40 struct nouveau_screen
*screen
;
41 struct nv30_context
*nv30
;
45 nv30
= container_of(push
->user_priv
, nv30
, bufctx
);
46 screen
= &nv30
->screen
->base
;
48 nouveau_fence_next(screen
);
49 nouveau_fence_update(screen
, true);
52 struct nouveau_bufref
*bref
;
53 LIST_FOR_EACH_ENTRY(bref
, &push
->bufctx
->current
, thead
) {
54 struct nv04_resource
*res
= bref
->priv
;
56 nouveau_fence_ref(screen
->fence
.current
, &res
->fence
);
58 if (bref
->flags
& NOUVEAU_BO_RD
)
59 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_READING
;
61 if (bref
->flags
& NOUVEAU_BO_WR
) {
62 nouveau_fence_ref(screen
->fence
.current
, &res
->fence_wr
);
63 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
|
64 NOUVEAU_BUFFER_STATUS_DIRTY
;
72 nv30_context_flush(struct pipe_context
*pipe
, struct pipe_fence_handle
**fence
,
75 struct nv30_context
*nv30
= nv30_context(pipe
);
76 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
79 nouveau_fence_ref(nv30
->screen
->base
.fence
.current
,
80 (struct nouveau_fence
**)fence
);
84 nouveau_context_update_frame_stats(&nv30
->base
);
88 nv30_invalidate_resource_storage(struct nouveau_context
*nv
,
89 struct pipe_resource
*res
,
92 struct nv30_context
*nv30
= nv30_context(&nv
->pipe
);
95 if (res
->bind
& PIPE_BIND_RENDER_TARGET
) {
96 for (i
= 0; i
< nv30
->framebuffer
.nr_cbufs
; ++i
) {
97 if (nv30
->framebuffer
.cbufs
[i
] &&
98 nv30
->framebuffer
.cbufs
[i
]->texture
== res
) {
99 nv30
->dirty
|= NV30_NEW_FRAMEBUFFER
;
100 nouveau_bufctx_reset(nv30
->bufctx
, BUFCTX_FB
);
106 if (res
->bind
& PIPE_BIND_DEPTH_STENCIL
) {
107 if (nv30
->framebuffer
.zsbuf
&&
108 nv30
->framebuffer
.zsbuf
->texture
== res
) {
109 nv30
->dirty
|= NV30_NEW_FRAMEBUFFER
;
110 nouveau_bufctx_reset(nv30
->bufctx
, BUFCTX_FB
);
116 if (res
->bind
& PIPE_BIND_VERTEX_BUFFER
) {
117 for (i
= 0; i
< nv30
->num_vtxbufs
; ++i
) {
118 if (nv30
->vtxbuf
[i
].buffer
.resource
== res
) {
119 nv30
->dirty
|= NV30_NEW_ARRAYS
;
120 nouveau_bufctx_reset(nv30
->bufctx
, BUFCTX_VTXBUF
);
127 if (res
->bind
& PIPE_BIND_SAMPLER_VIEW
) {
128 for (i
= 0; i
< nv30
->fragprog
.num_textures
; ++i
) {
129 if (nv30
->fragprog
.textures
[i
] &&
130 nv30
->fragprog
.textures
[i
]->texture
== res
) {
131 nv30
->dirty
|= NV30_NEW_FRAGTEX
;
132 nouveau_bufctx_reset(nv30
->bufctx
, BUFCTX_FRAGTEX(i
));
137 for (i
= 0; i
< nv30
->vertprog
.num_textures
; ++i
) {
138 if (nv30
->vertprog
.textures
[i
] &&
139 nv30
->vertprog
.textures
[i
]->texture
== res
) {
140 nv30
->dirty
|= NV30_NEW_VERTTEX
;
141 nouveau_bufctx_reset(nv30
->bufctx
, BUFCTX_VERTTEX(i
));
152 nv30_context_destroy(struct pipe_context
*pipe
)
154 struct nv30_context
*nv30
= nv30_context(pipe
);
157 util_blitter_destroy(nv30
->blitter
);
160 draw_destroy(nv30
->draw
);
162 if (nv30
->base
.pipe
.stream_uploader
)
163 u_upload_destroy(nv30
->base
.pipe
.stream_uploader
);
166 nouveau_heap_free(&nv30
->blit_vp
);
169 pipe_resource_reference(&nv30
->blit_fp
, NULL
);
171 if (nv30
->screen
->base
.pushbuf
->user_priv
== &nv30
->bufctx
)
172 nv30
->screen
->base
.pushbuf
->user_priv
= NULL
;
174 nouveau_bufctx_del(&nv30
->bufctx
);
176 if (nv30
->screen
->cur_ctx
== nv30
)
177 nv30
->screen
->cur_ctx
= NULL
;
179 nouveau_context_destroy(&nv30
->base
);
182 #define FAIL_CONTEXT_INIT(str, err) \
184 NOUVEAU_ERR(str, err); \
185 nv30_context_destroy(pipe); \
189 struct pipe_context
*
190 nv30_context_create(struct pipe_screen
*pscreen
, void *priv
, unsigned ctxflags
)
192 struct nv30_screen
*screen
= nv30_screen(pscreen
);
193 struct nv30_context
*nv30
= CALLOC_STRUCT(nv30_context
);
194 struct nouveau_pushbuf
*push
;
195 struct pipe_context
*pipe
;
201 nv30
->screen
= screen
;
202 nv30
->base
.screen
= &screen
->base
;
203 nv30
->base
.copy_data
= nv30_transfer_copy_data
;
205 pipe
= &nv30
->base
.pipe
;
206 pipe
->screen
= pscreen
;
208 pipe
->destroy
= nv30_context_destroy
;
209 pipe
->flush
= nv30_context_flush
;
211 nv30
->base
.pipe
.stream_uploader
= u_upload_create_default(&nv30
->base
.pipe
);
212 if (!nv30
->base
.pipe
.stream_uploader
) {
213 nv30_context_destroy(pipe
);
216 nv30
->base
.pipe
.const_uploader
= nv30
->base
.pipe
.stream_uploader
;
218 /*XXX: *cough* per-context client */
219 nv30
->base
.client
= screen
->base
.client
;
221 /*XXX: *cough* per-context pushbufs */
222 push
= screen
->base
.pushbuf
;
223 nv30
->base
.pushbuf
= push
;
224 push
->kick_notify
= nv30_context_kick_notify
;
226 nv30
->base
.invalidate_resource_storage
= nv30_invalidate_resource_storage
;
228 ret
= nouveau_bufctx_new(nv30
->base
.client
, 64, &nv30
->bufctx
);
230 nv30_context_destroy(pipe
);
234 /*XXX: make configurable with performance vs quality, these defaults
235 * match the binary driver's defaults
237 if (screen
->eng3d
->oclass
< NV40_3D_CLASS
)
238 nv30
->config
.filter
= 0x00000004;
240 nv30
->config
.filter
= 0x00002dc4;
242 nv30
->config
.aniso
= NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_OFF
;
244 if (debug_get_bool_option("NV30_SWTNL", false))
245 nv30
->draw_flags
|= NV30_NEW_SWTNL
;
247 nouveau_context_init(&nv30
->base
);
248 nv30
->sample_mask
= 0xffff;
250 nv30_query_init(pipe
);
251 nv30_state_init(pipe
);
252 nv30_resource_init(pipe
);
253 nv30_clear_init(pipe
);
254 nv30_fragprog_init(pipe
);
255 nv30_vertprog_init(pipe
);
256 nv30_texture_init(pipe
);
257 nv30_fragtex_init(pipe
);
258 nv40_verttex_init(pipe
);
259 nv30_draw_init(pipe
);
261 nv30
->blitter
= util_blitter_create(pipe
);
262 if (!nv30
->blitter
) {
263 nv30_context_destroy(pipe
);
267 nouveau_context_init_vdec(&nv30
->base
);