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