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
57static 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
118static void
119do_flush( struct pipe_context *pipe,
120          struct pipe_fence_handle **fence,
121          unsigned flags)
122{
123   llvmpipe_flush(pipe, fence, __FUNCTION__);
124}
125
126static void
127llvmpipe_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
137static void
138llvmpipe_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
150static void
151llvmpipe_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
163static void
164llvmpipe_texture_barrier(struct pipe_context *pipe, unsigned flags)
165{
166   llvmpipe_finish(pipe, "barrier");
167}
168
169static 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
177static 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
185static enum pipe_reset_status
186llvmpipe_get_device_reset_status(struct pipe_context *pipe)
187{
188   return PIPE_NO_RESET;
189}
190
191struct pipe_context *
192llvmpipe_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