• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
4  * All Rights Reserved.
5  * Copyright 2008 VMware, Inc.  All rights reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 /* Author:
30  *    Keith Whitwell <keithw@vmware.com>
31  */
32 
33 #include "draw/draw_context.h"
34 #include "draw/draw_vbuf.h"
35 #include "pipe/p_defines.h"
36 #include "util/u_inlines.h"
37 #include "util/u_math.h"
38 #include "util/u_memory.h"
39 #include "util/list.h"
40 #include "util/u_upload_mgr.h"
41 #include "lp_clear.h"
42 #include "lp_context.h"
43 #include "lp_flush.h"
44 #include "lp_perf.h"
45 #include "lp_state.h"
46 #include "lp_surface.h"
47 #include "lp_query.h"
48 #include "lp_setup.h"
49 #include "lp_screen.h"
50 #include "lp_fence.h"
51 
52 /* This is only safe if there's just one concurrent context */
53 #ifdef EMBEDDED_DEVICE
54 #define USE_GLOBAL_LLVM_CONTEXT
55 #endif
56 
llvmpipe_destroy(struct pipe_context * pipe)57 static void llvmpipe_destroy( struct pipe_context *pipe )
58 {
59    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
60    struct llvmpipe_screen *lp_screen = llvmpipe_screen(pipe->screen);
61    uint i;
62 
63    mtx_lock(&lp_screen->ctx_mutex);
64    list_del(&llvmpipe->list);
65    mtx_unlock(&lp_screen->ctx_mutex);
66    lp_print_counters();
67 
68    if (llvmpipe->csctx) {
69       lp_csctx_destroy(llvmpipe->csctx);
70    }
71    if (llvmpipe->blitter) {
72       util_blitter_destroy(llvmpipe->blitter);
73    }
74 
75    if (llvmpipe->pipe.stream_uploader)
76       u_upload_destroy(llvmpipe->pipe.stream_uploader);
77 
78    /* This will also destroy llvmpipe->setup:
79     */
80    if (llvmpipe->draw)
81       draw_destroy( llvmpipe->draw );
82 
83    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
84       pipe_surface_reference(&llvmpipe->framebuffer.cbufs[i], NULL);
85    }
86 
87    pipe_surface_reference(&llvmpipe->framebuffer.zsbuf, NULL);
88 
89    for (enum pipe_shader_type s = PIPE_SHADER_VERTEX; s < PIPE_SHADER_TYPES; s++) {
90       for (i = 0; i < ARRAY_SIZE(llvmpipe->sampler_views[0]); i++) {
91          pipe_sampler_view_reference(&llvmpipe->sampler_views[s][i], NULL);
92       }
93       for (i = 0; i < LP_MAX_TGSI_SHADER_IMAGES; i++) {
94          pipe_resource_reference(&llvmpipe->images[s][i].resource, NULL);
95       }
96       for (i = 0; i < LP_MAX_TGSI_SHADER_BUFFERS; i++) {
97          pipe_resource_reference(&llvmpipe->ssbos[s][i].buffer, NULL);
98       }
99       for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[s]); i++) {
100          pipe_resource_reference(&llvmpipe->constants[s][i].buffer, NULL);
101       }
102    }
103 
104    for (i = 0; i < llvmpipe->num_vertex_buffers; i++) {
105       pipe_vertex_buffer_unreference(&llvmpipe->vertex_buffer[i]);
106    }
107 
108    lp_delete_setup_variants(llvmpipe);
109 
110 #ifndef USE_GLOBAL_LLVM_CONTEXT
111    LLVMContextDispose(llvmpipe->context);
112 #endif
113    llvmpipe->context = NULL;
114 
115    align_free( llvmpipe );
116 }
117 
118 static void
do_flush(struct pipe_context * pipe,struct pipe_fence_handle ** fence,unsigned flags)119 do_flush( struct pipe_context *pipe,
120           struct pipe_fence_handle **fence,
121           unsigned flags)
122 {
123    llvmpipe_flush(pipe, fence, __FUNCTION__);
124 }
125 
126 static void
llvmpipe_fence_server_sync(struct pipe_context * pipe,struct pipe_fence_handle * fence)127 llvmpipe_fence_server_sync(struct pipe_context *pipe,
128                            struct pipe_fence_handle *fence)
129 {
130    struct lp_fence *f = (struct lp_fence *)fence;
131 
132    if (!f->issued)
133       return;
134    lp_fence_wait(f);
135 }
136 
137 static void
llvmpipe_render_condition(struct pipe_context * pipe,struct pipe_query * query,bool condition,enum pipe_render_cond_flag mode)138 llvmpipe_render_condition(struct pipe_context *pipe,
139                           struct pipe_query *query,
140                           bool condition,
141                           enum pipe_render_cond_flag mode)
142 {
143    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
144 
145    llvmpipe->render_cond_query = query;
146    llvmpipe->render_cond_mode = mode;
147    llvmpipe->render_cond_cond = condition;
148 }
149 
150 static void
llvmpipe_render_condition_mem(struct pipe_context * pipe,struct pipe_resource * buffer,unsigned offset,bool condition)151 llvmpipe_render_condition_mem(struct pipe_context *pipe,
152                               struct pipe_resource *buffer,
153                               unsigned offset,
154                               bool condition)
155 {
156    struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
157 
158    llvmpipe->render_cond_buffer = llvmpipe_resource(buffer);
159    llvmpipe->render_cond_offset = offset;
160    llvmpipe->render_cond_cond = condition;
161 }
162 
163 static void
llvmpipe_texture_barrier(struct pipe_context * pipe,unsigned flags)164 llvmpipe_texture_barrier(struct pipe_context *pipe, unsigned flags)
165 {
166    llvmpipe_finish(pipe, "barrier");
167 }
168 
lp_draw_disk_cache_find_shader(void * cookie,struct lp_cached_code * cache,unsigned char ir_sha1_cache_key[20])169 static void lp_draw_disk_cache_find_shader(void *cookie,
170                                            struct lp_cached_code *cache,
171                                            unsigned char ir_sha1_cache_key[20])
172 {
173    struct llvmpipe_screen *screen = cookie;
174    lp_disk_cache_find_shader(screen, cache, ir_sha1_cache_key);
175 }
176 
lp_draw_disk_cache_insert_shader(void * cookie,struct lp_cached_code * cache,unsigned char ir_sha1_cache_key[20])177 static void lp_draw_disk_cache_insert_shader(void *cookie,
178                                              struct lp_cached_code *cache,
179                                              unsigned char ir_sha1_cache_key[20])
180 {
181    struct llvmpipe_screen *screen = cookie;
182    lp_disk_cache_insert_shader(screen, cache, ir_sha1_cache_key);
183 }
184 
185 static enum pipe_reset_status
llvmpipe_get_device_reset_status(struct pipe_context * pipe)186 llvmpipe_get_device_reset_status(struct pipe_context *pipe)
187 {
188    return PIPE_NO_RESET;
189 }
190 
191 struct pipe_context *
llvmpipe_create_context(struct pipe_screen * screen,void * priv,unsigned flags)192 llvmpipe_create_context(struct pipe_screen *screen, void *priv,
193                         unsigned flags)
194 {
195    struct llvmpipe_context *llvmpipe;
196    struct llvmpipe_screen *lp_screen = llvmpipe_screen(screen);
197 
198    if (!llvmpipe_screen_late_init(lp_screen))
199       return NULL;
200 
201    llvmpipe = align_malloc(sizeof(struct llvmpipe_context), 16);
202    if (!llvmpipe)
203       return NULL;
204 
205    memset(llvmpipe, 0, sizeof *llvmpipe);
206 
207    list_inithead(&llvmpipe->fs_variants_list.list);
208 
209    list_inithead(&llvmpipe->setup_variants_list.list);
210 
211    list_inithead(&llvmpipe->cs_variants_list.list);
212 
213    llvmpipe->pipe.screen = screen;
214    llvmpipe->pipe.priv = priv;
215 
216    /* Init the pipe context methods */
217    llvmpipe->pipe.destroy = llvmpipe_destroy;
218    llvmpipe->pipe.set_framebuffer_state = llvmpipe_set_framebuffer_state;
219    llvmpipe->pipe.clear = llvmpipe_clear;
220    llvmpipe->pipe.flush = do_flush;
221    llvmpipe->pipe.texture_barrier = llvmpipe_texture_barrier;
222 
223    llvmpipe->pipe.render_condition = llvmpipe_render_condition;
224    llvmpipe->pipe.render_condition_mem = llvmpipe_render_condition_mem;
225 
226    llvmpipe->pipe.fence_server_sync = llvmpipe_fence_server_sync;
227    llvmpipe->pipe.get_device_reset_status = llvmpipe_get_device_reset_status;
228    llvmpipe_init_blend_funcs(llvmpipe);
229    llvmpipe_init_clip_funcs(llvmpipe);
230    llvmpipe_init_draw_funcs(llvmpipe);
231    llvmpipe_init_compute_funcs(llvmpipe);
232    llvmpipe_init_sampler_funcs(llvmpipe);
233    llvmpipe_init_query_funcs( llvmpipe );
234    llvmpipe_init_vertex_funcs(llvmpipe);
235    llvmpipe_init_so_funcs(llvmpipe);
236    llvmpipe_init_fs_funcs(llvmpipe);
237    llvmpipe_init_vs_funcs(llvmpipe);
238    llvmpipe_init_gs_funcs(llvmpipe);
239    llvmpipe_init_tess_funcs(llvmpipe);
240    llvmpipe_init_rasterizer_funcs(llvmpipe);
241    llvmpipe_init_context_resource_funcs( &llvmpipe->pipe );
242    llvmpipe_init_surface_functions(llvmpipe);
243 
244 #ifdef USE_GLOBAL_LLVM_CONTEXT
245    llvmpipe->context = LLVMGetGlobalContext();
246 #else
247    llvmpipe->context = LLVMContextCreate();
248 #endif
249 
250    if (!llvmpipe->context)
251       goto fail;
252 
253 #if LLVM_VERSION_MAJOR >= 15
254    LLVMContextSetOpaquePointers(llvmpipe->context, false);
255 #endif
256 
257    /*
258     * Create drawing context and plug our rendering stage into it.
259     */
260    llvmpipe->draw = draw_create_with_llvm_context(&llvmpipe->pipe,
261                                                   llvmpipe->context);
262    if (!llvmpipe->draw)
263       goto fail;
264 
265    draw_set_disk_cache_callbacks(llvmpipe->draw,
266                                  lp_screen,
267                                  lp_draw_disk_cache_find_shader,
268                                  lp_draw_disk_cache_insert_shader);
269 
270    draw_set_constant_buffer_stride(llvmpipe->draw, lp_get_constant_buffer_stride(screen));
271 
272    /* FIXME: devise alternative to draw_texture_samplers */
273 
274    llvmpipe->setup = lp_setup_create( &llvmpipe->pipe,
275                                       llvmpipe->draw );
276    if (!llvmpipe->setup)
277       goto fail;
278 
279    llvmpipe->csctx = lp_csctx_create( &llvmpipe->pipe );
280    if (!llvmpipe->csctx)
281       goto fail;
282    llvmpipe->pipe.stream_uploader = u_upload_create_default(&llvmpipe->pipe);
283    if (!llvmpipe->pipe.stream_uploader)
284       goto fail;
285    llvmpipe->pipe.const_uploader = llvmpipe->pipe.stream_uploader;
286 
287    llvmpipe->blitter = util_blitter_create(&llvmpipe->pipe);
288    if (!llvmpipe->blitter) {
289       goto fail;
290    }
291 
292    /* must be done before installing Draw stages */
293    util_blitter_cache_all_shaders(llvmpipe->blitter);
294 
295    /* plug in AA line/point stages */
296    draw_install_aaline_stage(llvmpipe->draw, &llvmpipe->pipe);
297    draw_install_aapoint_stage(llvmpipe->draw, &llvmpipe->pipe);
298    draw_install_pstipple_stage(llvmpipe->draw, &llvmpipe->pipe);
299 
300    /* convert points and lines into triangles:
301     * (otherwise, draw points and lines natively)
302     */
303    draw_wide_point_sprites(llvmpipe->draw, FALSE);
304    draw_enable_point_sprites(llvmpipe->draw, FALSE);
305    draw_wide_point_threshold(llvmpipe->draw, 10000.0);
306    draw_wide_line_threshold(llvmpipe->draw, 10000.0);
307 
308    /* initial state for clipping - enabled, with no guardband */
309    draw_set_driver_clipping(llvmpipe->draw, FALSE, FALSE, FALSE, TRUE);
310 
311    lp_reset_counters();
312 
313    /* If llvmpipe_set_scissor_states() is never called, we still need to
314     * make sure that derived scissor state is computed.
315     * See https://bugs.freedesktop.org/show_bug.cgi?id=101709
316     */
317    llvmpipe->dirty |= LP_NEW_SCISSOR;
318 
319    mtx_lock(&lp_screen->ctx_mutex);
320    list_addtail(&llvmpipe->list, &lp_screen->ctx_list);
321    mtx_unlock(&lp_screen->ctx_mutex);
322    return &llvmpipe->pipe;
323 
324  fail:
325    llvmpipe_destroy(&llvmpipe->pipe);
326    return NULL;
327 }
328 
329