14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2007 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254a49301eSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg 284a49301eSmrg/** 29cdc920a0Smrg * Tiling engine. 304a49301eSmrg * 31cdc920a0Smrg * Builds per-tile display lists and executes them on calls to 32cdc920a0Smrg * lp_setup_flush(). 334a49301eSmrg */ 344a49301eSmrg 353464ebd5Sriastradh#include <limits.h> 363464ebd5Sriastradh 37cdc920a0Smrg#include "pipe/p_defines.h" 383464ebd5Sriastradh#include "util/u_framebuffer.h" 39cdc920a0Smrg#include "util/u_inlines.h" 404a49301eSmrg#include "util/u_memory.h" 41cdc920a0Smrg#include "util/u_pack_color.h" 427ec681f3Smrg#include "util/u_cpu_detect.h" 4301e04c3fSmrg#include "util/u_viewport.h" 44af69d88dSmrg#include "draw/draw_pipe.h" 4501e04c3fSmrg#include "util/os_time.h" 463464ebd5Sriastradh#include "lp_context.h" 473464ebd5Sriastradh#include "lp_memory.h" 48cdc920a0Smrg#include "lp_scene.h" 49cdc920a0Smrg#include "lp_texture.h" 50cdc920a0Smrg#include "lp_debug.h" 51cdc920a0Smrg#include "lp_fence.h" 523464ebd5Sriastradh#include "lp_query.h" 53cdc920a0Smrg#include "lp_rast.h" 54cdc920a0Smrg#include "lp_setup_context.h" 55cdc920a0Smrg#include "lp_screen.h" 563464ebd5Sriastradh#include "lp_state.h" 577ec681f3Smrg#include "lp_jit.h" 587ec681f3Smrg#include "frontend/sw_winsys.h" 594a49301eSmrg 60cdc920a0Smrg#include "draw/draw_context.h" 61cdc920a0Smrg#include "draw/draw_vbuf.h" 624a49301eSmrg 634a49301eSmrg 643464ebd5Sriastradhstatic boolean set_scene_state( struct lp_setup_context *, enum setup_state, 653464ebd5Sriastradh const char *reason); 663464ebd5Sriastradhstatic boolean try_update_scene_state( struct lp_setup_context *setup ); 674a49301eSmrg 684a49301eSmrg 693464ebd5Sriastradhstatic void 703464ebd5Sriastradhlp_setup_get_empty_scene(struct lp_setup_context *setup) 71cdc920a0Smrg{ 723464ebd5Sriastradh assert(setup->scene == NULL); 734a49301eSmrg 743464ebd5Sriastradh setup->scene_idx++; 7501e04c3fSmrg setup->scene_idx %= ARRAY_SIZE(setup->scenes); 763464ebd5Sriastradh 773464ebd5Sriastradh setup->scene = setup->scenes[setup->scene_idx]; 784a49301eSmrg 793464ebd5Sriastradh if (setup->scene->fence) { 803464ebd5Sriastradh if (LP_DEBUG & DEBUG_SETUP) 813464ebd5Sriastradh debug_printf("%s: wait for scene %d\n", 823464ebd5Sriastradh __FUNCTION__, setup->scene->fence->id); 834a49301eSmrg 843464ebd5Sriastradh lp_fence_wait(setup->scene->fence); 85cdc920a0Smrg } 863464ebd5Sriastradh 8701e04c3fSmrg lp_scene_begin_binning(setup->scene, &setup->fb); 88af69d88dSmrg 897ec681f3Smrg setup->scene->permit_linear_rasterizer = setup->permit_linear_rasterizer; 90cdc920a0Smrg} 914a49301eSmrg 924a49301eSmrg 93cdc920a0Smrgstatic void 943464ebd5Sriastradhfirst_triangle( struct lp_setup_context *setup, 95cdc920a0Smrg const float (*v0)[4], 96cdc920a0Smrg const float (*v1)[4], 97cdc920a0Smrg const float (*v2)[4]) 98cdc920a0Smrg{ 993464ebd5Sriastradh assert(setup->state == SETUP_ACTIVE); 100cdc920a0Smrg lp_setup_choose_triangle( setup ); 101cdc920a0Smrg setup->triangle( setup, v0, v1, v2 ); 102cdc920a0Smrg} 1034a49301eSmrg 1047ec681f3Smrgstatic boolean 1057ec681f3Smrgfirst_rectangle( struct lp_setup_context *setup, 1067ec681f3Smrg const float (*v0)[4], 1077ec681f3Smrg const float (*v1)[4], 1087ec681f3Smrg const float (*v2)[4], 1097ec681f3Smrg const float (*v3)[4], 1107ec681f3Smrg const float (*v4)[4], 1117ec681f3Smrg const float (*v5)[4]) 1127ec681f3Smrg{ 1137ec681f3Smrg assert(setup->state == SETUP_ACTIVE); 1147ec681f3Smrg lp_setup_choose_rect( setup ); 1157ec681f3Smrg return setup->rect( setup, v0, v1, v2, v3, v4, v5 ); 1167ec681f3Smrg} 1177ec681f3Smrg 118cdc920a0Smrgstatic void 1193464ebd5Sriastradhfirst_line( struct lp_setup_context *setup, 120cdc920a0Smrg const float (*v0)[4], 121cdc920a0Smrg const float (*v1)[4]) 122cdc920a0Smrg{ 1233464ebd5Sriastradh assert(setup->state == SETUP_ACTIVE); 124cdc920a0Smrg lp_setup_choose_line( setup ); 125cdc920a0Smrg setup->line( setup, v0, v1 ); 126cdc920a0Smrg} 1274a49301eSmrg 128cdc920a0Smrgstatic void 1293464ebd5Sriastradhfirst_point( struct lp_setup_context *setup, 130cdc920a0Smrg const float (*v0)[4]) 131cdc920a0Smrg{ 1323464ebd5Sriastradh assert(setup->state == SETUP_ACTIVE); 133cdc920a0Smrg lp_setup_choose_point( setup ); 134cdc920a0Smrg setup->point( setup, v0 ); 135cdc920a0Smrg} 1364a49301eSmrg 1377ec681f3Smrgvoid 1387ec681f3Smrglp_setup_reset( struct lp_setup_context *setup ) 139cdc920a0Smrg{ 140af69d88dSmrg unsigned i; 141af69d88dSmrg 142cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 1434a49301eSmrg 144cdc920a0Smrg /* Reset derived state */ 14501e04c3fSmrg for (i = 0; i < ARRAY_SIZE(setup->constants); ++i) { 146af69d88dSmrg setup->constants[i].stored_size = 0; 147af69d88dSmrg setup->constants[i].stored_data = NULL; 148af69d88dSmrg } 1497ec681f3Smrg 150cdc920a0Smrg setup->fs.stored = NULL; 151cdc920a0Smrg setup->dirty = ~0; 1524a49301eSmrg 153cdc920a0Smrg /* no current bin */ 154cdc920a0Smrg setup->scene = NULL; 1554a49301eSmrg 156cdc920a0Smrg /* Reset some state: 157cdc920a0Smrg */ 1583464ebd5Sriastradh memset(&setup->clear, 0, sizeof setup->clear); 1594a49301eSmrg 160cdc920a0Smrg /* Have an explicit "start-binning" call and get rid of this 161cdc920a0Smrg * pointer twiddling? 162cdc920a0Smrg */ 163cdc920a0Smrg setup->line = first_line; 164cdc920a0Smrg setup->point = first_point; 165cdc920a0Smrg setup->triangle = first_triangle; 1667ec681f3Smrg setup->rect = first_rectangle; 167cdc920a0Smrg} 1684a49301eSmrg 1694a49301eSmrg 170cdc920a0Smrg/** Rasterize all scene's bins */ 1714a49301eSmrgstatic void 1723464ebd5Sriastradhlp_setup_rasterize_scene( struct lp_setup_context *setup ) 1734a49301eSmrg{ 1743464ebd5Sriastradh struct lp_scene *scene = setup->scene; 1753464ebd5Sriastradh struct llvmpipe_screen *screen = llvmpipe_screen(scene->pipe->screen); 1763464ebd5Sriastradh 177af69d88dSmrg scene->num_active_queries = setup->active_binned_queries; 178af69d88dSmrg memcpy(scene->active_queries, setup->active_queries, 179af69d88dSmrg scene->num_active_queries * sizeof(scene->active_queries[0])); 180af69d88dSmrg 1813464ebd5Sriastradh lp_scene_end_binning(scene); 1824a49301eSmrg 1833464ebd5Sriastradh lp_fence_reference(&setup->last_fence, scene->fence); 1844a49301eSmrg 1853464ebd5Sriastradh if (setup->last_fence) 1863464ebd5Sriastradh setup->last_fence->issued = TRUE; 1873464ebd5Sriastradh 18801e04c3fSmrg mtx_lock(&screen->rast_mutex); 18901e04c3fSmrg 19001e04c3fSmrg /* FIXME: We enqueue the scene then wait on the rasterizer to finish. 19101e04c3fSmrg * This means we never actually run any vertex stuff in parallel to 19201e04c3fSmrg * rasterization (not in the same context at least) which is what the 19301e04c3fSmrg * multiple scenes per setup is about - when we get a new empty scene 19401e04c3fSmrg * any old one is already empty again because we waited here for 19501e04c3fSmrg * raster tasks to be finished. Ideally, we shouldn't need to wait here 19601e04c3fSmrg * and rely on fences elsewhere when waiting is necessary. 19701e04c3fSmrg * Certainly, lp_scene_end_rasterization() would need to be deferred too 19801e04c3fSmrg * and there's probably other bits why this doesn't actually work. 19901e04c3fSmrg */ 2003464ebd5Sriastradh lp_rast_queue_scene(screen->rast, scene); 2013464ebd5Sriastradh lp_rast_finish(screen->rast); 20201e04c3fSmrg mtx_unlock(&screen->rast_mutex); 2033464ebd5Sriastradh 2043464ebd5Sriastradh lp_scene_end_rasterization(setup->scene); 2053464ebd5Sriastradh lp_setup_reset( setup ); 2064a49301eSmrg 207cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); 2084a49301eSmrg} 2094a49301eSmrg 2104a49301eSmrg 2114a49301eSmrg 2123464ebd5Sriastradhstatic boolean 2133464ebd5Sriastradhbegin_binning( struct lp_setup_context *setup ) 2144a49301eSmrg{ 2153464ebd5Sriastradh struct lp_scene *scene = setup->scene; 2163464ebd5Sriastradh boolean need_zsload = FALSE; 2173464ebd5Sriastradh boolean ok; 2183464ebd5Sriastradh 2193464ebd5Sriastradh assert(scene); 2203464ebd5Sriastradh assert(scene->fence == NULL); 2213464ebd5Sriastradh 2223464ebd5Sriastradh /* Always create a fence: 2233464ebd5Sriastradh */ 2243464ebd5Sriastradh scene->fence = lp_fence_create(MAX2(1, setup->num_threads)); 2253464ebd5Sriastradh if (!scene->fence) 2263464ebd5Sriastradh return FALSE; 2273464ebd5Sriastradh 2283464ebd5Sriastradh ok = try_update_scene_state(setup); 2293464ebd5Sriastradh if (!ok) 2303464ebd5Sriastradh return FALSE; 2313464ebd5Sriastradh 2323464ebd5Sriastradh if (setup->fb.zsbuf && 2333464ebd5Sriastradh ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && 2343464ebd5Sriastradh util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) 2353464ebd5Sriastradh need_zsload = TRUE; 2364a49301eSmrg 237af69d88dSmrg LP_DBG(DEBUG_SETUP, "%s color clear bufs: %x depth: %s\n", __FUNCTION__, 238af69d88dSmrg setup->clear.flags >> 2, 2393464ebd5Sriastradh need_zsload ? "clear": "load"); 2404a49301eSmrg 241af69d88dSmrg if (setup->clear.flags & PIPE_CLEAR_COLOR) { 242af69d88dSmrg unsigned cbuf; 243af69d88dSmrg for (cbuf = 0; cbuf < setup->fb.nr_cbufs; cbuf++) { 244af69d88dSmrg assert(PIPE_CLEAR_COLOR0 == 1 << 2); 245af69d88dSmrg if (setup->clear.flags & (1 << (2 + cbuf))) { 246af69d88dSmrg union lp_rast_cmd_arg clearrb_arg; 247af69d88dSmrg struct lp_rast_clear_rb *cc_scene = 248af69d88dSmrg (struct lp_rast_clear_rb *) 249af69d88dSmrg lp_scene_alloc(scene, sizeof(struct lp_rast_clear_rb)); 250af69d88dSmrg 251af69d88dSmrg if (!cc_scene) { 252af69d88dSmrg return FALSE; 253af69d88dSmrg } 254af69d88dSmrg 255af69d88dSmrg cc_scene->cbuf = cbuf; 256af69d88dSmrg cc_scene->color_val = setup->clear.color_val[cbuf]; 257af69d88dSmrg clearrb_arg.clear_rb = cc_scene; 258af69d88dSmrg 259af69d88dSmrg if (!lp_scene_bin_everywhere(scene, 260af69d88dSmrg LP_RAST_OP_CLEAR_COLOR, 261af69d88dSmrg clearrb_arg)) 262af69d88dSmrg return FALSE; 263af69d88dSmrg } 2643464ebd5Sriastradh } 265cdc920a0Smrg } 2664a49301eSmrg 267cdc920a0Smrg if (setup->fb.zsbuf) { 2683464ebd5Sriastradh if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { 2693464ebd5Sriastradh ok = lp_scene_bin_everywhere( scene, 2703464ebd5Sriastradh LP_RAST_OP_CLEAR_ZSTENCIL, 2713464ebd5Sriastradh lp_rast_arg_clearzs( 2723464ebd5Sriastradh setup->clear.zsvalue, 2733464ebd5Sriastradh setup->clear.zsmask)); 2743464ebd5Sriastradh if (!ok) 2753464ebd5Sriastradh return FALSE; 2763464ebd5Sriastradh } 2773464ebd5Sriastradh } 2783464ebd5Sriastradh 2793464ebd5Sriastradh setup->clear.flags = 0; 2803464ebd5Sriastradh setup->clear.zsmask = 0; 2813464ebd5Sriastradh setup->clear.zsvalue = 0; 2823464ebd5Sriastradh 283af69d88dSmrg scene->had_queries = !!setup->active_binned_queries; 284af69d88dSmrg 285cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); 2863464ebd5Sriastradh return TRUE; 287cdc920a0Smrg} 2884a49301eSmrg 2894a49301eSmrg 290cdc920a0Smrg/* This basically bins and then flushes any outstanding full-screen 291cdc920a0Smrg * clears. 292cdc920a0Smrg * 293cdc920a0Smrg * TODO: fast path for fullscreen clears and no triangles. 2944a49301eSmrg */ 2953464ebd5Sriastradhstatic boolean 2963464ebd5Sriastradhexecute_clears( struct lp_setup_context *setup ) 2974a49301eSmrg{ 298cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 2994a49301eSmrg 3003464ebd5Sriastradh return begin_binning( setup ); 3014a49301eSmrg} 3024a49301eSmrg 3033464ebd5Sriastradhconst char *states[] = { 3043464ebd5Sriastradh "FLUSHED", 3053464ebd5Sriastradh "CLEARED", 3063464ebd5Sriastradh "ACTIVE " 3073464ebd5Sriastradh}; 3084a49301eSmrg 3093464ebd5Sriastradh 3103464ebd5Sriastradhstatic boolean 3113464ebd5Sriastradhset_scene_state( struct lp_setup_context *setup, 3123464ebd5Sriastradh enum setup_state new_state, 3133464ebd5Sriastradh const char *reason) 3144a49301eSmrg{ 315cdc920a0Smrg unsigned old_state = setup->state; 3164a49301eSmrg 317cdc920a0Smrg if (old_state == new_state) 3183464ebd5Sriastradh return TRUE; 3193464ebd5Sriastradh 3203464ebd5Sriastradh if (LP_DEBUG & DEBUG_SCENE) { 3213464ebd5Sriastradh debug_printf("%s old %s new %s%s%s\n", 3223464ebd5Sriastradh __FUNCTION__, 3233464ebd5Sriastradh states[old_state], 3243464ebd5Sriastradh states[new_state], 3253464ebd5Sriastradh (new_state == SETUP_FLUSHED) ? ": " : "", 3263464ebd5Sriastradh (new_state == SETUP_FLUSHED) ? reason : ""); 3273464ebd5Sriastradh 3283464ebd5Sriastradh if (new_state == SETUP_FLUSHED && setup->scene) 3293464ebd5Sriastradh lp_debug_draw_bins_by_cmd_length(setup->scene); 3303464ebd5Sriastradh } 3313464ebd5Sriastradh 3323464ebd5Sriastradh /* wait for a free/empty scene 3333464ebd5Sriastradh */ 3343464ebd5Sriastradh if (old_state == SETUP_FLUSHED) 3353464ebd5Sriastradh lp_setup_get_empty_scene(setup); 3364a49301eSmrg 337cdc920a0Smrg switch (new_state) { 3383464ebd5Sriastradh case SETUP_CLEARED: 339cdc920a0Smrg break; 3404a49301eSmrg 3413464ebd5Sriastradh case SETUP_ACTIVE: 3423464ebd5Sriastradh if (!begin_binning( setup )) 3433464ebd5Sriastradh goto fail; 344cdc920a0Smrg break; 3453464ebd5Sriastradh 346cdc920a0Smrg case SETUP_FLUSHED: 347cdc920a0Smrg if (old_state == SETUP_CLEARED) 3483464ebd5Sriastradh if (!execute_clears( setup )) 3493464ebd5Sriastradh goto fail; 3503464ebd5Sriastradh 3513464ebd5Sriastradh lp_setup_rasterize_scene( setup ); 3523464ebd5Sriastradh assert(setup->scene == NULL); 353cdc920a0Smrg break; 3543464ebd5Sriastradh 3553464ebd5Sriastradh default: 3563464ebd5Sriastradh assert(0 && "invalid setup state mode"); 3573464ebd5Sriastradh goto fail; 3584a49301eSmrg } 3594a49301eSmrg 360cdc920a0Smrg setup->state = new_state; 3613464ebd5Sriastradh return TRUE; 3623464ebd5Sriastradh 3633464ebd5Sriastradhfail: 3643464ebd5Sriastradh if (setup->scene) { 3653464ebd5Sriastradh lp_scene_end_rasterization(setup->scene); 3663464ebd5Sriastradh setup->scene = NULL; 3673464ebd5Sriastradh } 3683464ebd5Sriastradh 3693464ebd5Sriastradh setup->state = SETUP_FLUSHED; 3703464ebd5Sriastradh lp_setup_reset( setup ); 3713464ebd5Sriastradh return FALSE; 3724a49301eSmrg} 3734a49301eSmrg 3744a49301eSmrg 375cdc920a0Smrgvoid 3763464ebd5Sriastradhlp_setup_flush( struct lp_setup_context *setup, 3773464ebd5Sriastradh struct pipe_fence_handle **fence, 3783464ebd5Sriastradh const char *reason) 3794a49301eSmrg{ 3803464ebd5Sriastradh set_scene_state( setup, SETUP_FLUSHED, reason ); 3814a49301eSmrg 3823464ebd5Sriastradh if (fence) { 3833464ebd5Sriastradh lp_fence_reference((struct lp_fence **)fence, setup->last_fence); 3849f464c52Smaya if (!*fence) 3859f464c52Smaya *fence = (struct pipe_fence_handle *)lp_fence_create(0); 3863464ebd5Sriastradh } 3874a49301eSmrg} 3884a49301eSmrg 3894a49301eSmrg 390cdc920a0Smrgvoid 3913464ebd5Sriastradhlp_setup_bind_framebuffer( struct lp_setup_context *setup, 392cdc920a0Smrg const struct pipe_framebuffer_state *fb ) 3934a49301eSmrg{ 394cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 3954a49301eSmrg 396cdc920a0Smrg /* Flush any old scene. 397cdc920a0Smrg */ 3983464ebd5Sriastradh set_scene_state( setup, SETUP_FLUSHED, __FUNCTION__ ); 3993464ebd5Sriastradh 4003464ebd5Sriastradh /* 4013464ebd5Sriastradh * Ensure the old scene is not reused. 4023464ebd5Sriastradh */ 4033464ebd5Sriastradh assert(!setup->scene); 4044a49301eSmrg 405cdc920a0Smrg /* Set new state. This will be picked up later when we next need a 406cdc920a0Smrg * scene. 4074a49301eSmrg */ 408cdc920a0Smrg util_copy_framebuffer_state(&setup->fb, fb); 4093464ebd5Sriastradh setup->framebuffer.x0 = 0; 4103464ebd5Sriastradh setup->framebuffer.y0 = 0; 4113464ebd5Sriastradh setup->framebuffer.x1 = fb->width-1; 4123464ebd5Sriastradh setup->framebuffer.y1 = fb->height-1; 4133464ebd5Sriastradh setup->dirty |= LP_SETUP_NEW_SCISSOR; 4144a49301eSmrg} 4154a49301eSmrg 4164a49301eSmrg 417af69d88dSmrg/* 418af69d88dSmrg * Try to clear one color buffer of the attached fb, either by binning a clear 419af69d88dSmrg * command or queuing up the clear for later (when binning is started). 420af69d88dSmrg */ 4213464ebd5Sriastradhstatic boolean 422af69d88dSmrglp_setup_try_clear_color_buffer(struct lp_setup_context *setup, 423af69d88dSmrg const union pipe_color_union *color, 424af69d88dSmrg unsigned cbuf) 4254a49301eSmrg{ 426af69d88dSmrg union lp_rast_cmd_arg clearrb_arg; 427af69d88dSmrg union util_color uc; 428af69d88dSmrg enum pipe_format format = setup->fb.cbufs[cbuf]->format; 4294a49301eSmrg 430cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); 4314a49301eSmrg 4327ec681f3Smrg util_pack_color_union(format, &uc, color); 4334a49301eSmrg 434af69d88dSmrg if (setup->state == SETUP_ACTIVE) { 435af69d88dSmrg struct lp_scene *scene = setup->scene; 4363464ebd5Sriastradh 437af69d88dSmrg /* Add the clear to existing scene. In the unusual case where 438af69d88dSmrg * both color and depth-stencil are being cleared when there's 439af69d88dSmrg * already been some rendering, we could discard the currently 440af69d88dSmrg * binned scene and start again, but I don't see that as being 441af69d88dSmrg * a common usage. 442af69d88dSmrg */ 443af69d88dSmrg struct lp_rast_clear_rb *cc_scene = 444af69d88dSmrg (struct lp_rast_clear_rb *) 445af69d88dSmrg lp_scene_alloc_aligned(scene, sizeof(struct lp_rast_clear_rb), 8); 446af69d88dSmrg 447af69d88dSmrg if (!cc_scene) { 448af69d88dSmrg return FALSE; 449af69d88dSmrg } 4503464ebd5Sriastradh 451af69d88dSmrg cc_scene->cbuf = cbuf; 452af69d88dSmrg cc_scene->color_val = uc; 453af69d88dSmrg clearrb_arg.clear_rb = cc_scene; 4543464ebd5Sriastradh 455af69d88dSmrg if (!lp_scene_bin_everywhere(scene, 456af69d88dSmrg LP_RAST_OP_CLEAR_COLOR, 457af69d88dSmrg clearrb_arg)) 458af69d88dSmrg return FALSE; 459af69d88dSmrg } 460af69d88dSmrg else { 461af69d88dSmrg /* Put ourselves into the 'pre-clear' state, specifically to try 462af69d88dSmrg * and accumulate multiple clears to color and depth_stencil 4637ec681f3Smrg * buffers which the app or gallium frontend might issue 464af69d88dSmrg * separately. 465af69d88dSmrg */ 466af69d88dSmrg set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); 4673464ebd5Sriastradh 468af69d88dSmrg assert(PIPE_CLEAR_COLOR0 == (1 << 2)); 469af69d88dSmrg setup->clear.flags |= 1 << (cbuf + 2); 470af69d88dSmrg setup->clear.color_val[cbuf] = uc; 471cdc920a0Smrg } 4724a49301eSmrg 473af69d88dSmrg return TRUE; 474af69d88dSmrg} 475af69d88dSmrg 476af69d88dSmrgstatic boolean 477af69d88dSmrglp_setup_try_clear_zs(struct lp_setup_context *setup, 478af69d88dSmrg double depth, 479af69d88dSmrg unsigned stencil, 480af69d88dSmrg unsigned flags) 481af69d88dSmrg{ 482af69d88dSmrg uint64_t zsmask = 0; 483af69d88dSmrg uint64_t zsvalue = 0; 484af69d88dSmrg uint32_t zmask32; 485af69d88dSmrg uint8_t smask8; 48601e04c3fSmrg enum pipe_format format = setup->fb.zsbuf->format; 487af69d88dSmrg 488af69d88dSmrg LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); 489af69d88dSmrg 490af69d88dSmrg zmask32 = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; 491af69d88dSmrg smask8 = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; 492af69d88dSmrg 49301e04c3fSmrg zsvalue = util_pack64_z_stencil(format, depth, stencil); 494af69d88dSmrg 49501e04c3fSmrg zsmask = util_pack64_mask_z_stencil(format, zmask32, smask8); 496af69d88dSmrg 497af69d88dSmrg zsvalue &= zsmask; 498af69d88dSmrg 49901e04c3fSmrg if (format == PIPE_FORMAT_Z24X8_UNORM || 50001e04c3fSmrg format == PIPE_FORMAT_X8Z24_UNORM) { 50101e04c3fSmrg /* 50201e04c3fSmrg * Make full mask if there's "X" bits so we can do full 50301e04c3fSmrg * clear (without rmw). 50401e04c3fSmrg */ 50501e04c3fSmrg uint32_t zsmask_full = 0; 50601e04c3fSmrg zsmask_full = util_pack_mask_z_stencil(format, ~0, ~0); 50701e04c3fSmrg zsmask |= ~zsmask_full; 50801e04c3fSmrg } 50901e04c3fSmrg 510cdc920a0Smrg if (setup->state == SETUP_ACTIVE) { 5113464ebd5Sriastradh struct lp_scene *scene = setup->scene; 5123464ebd5Sriastradh 513cdc920a0Smrg /* Add the clear to existing scene. In the unusual case where 514cdc920a0Smrg * both color and depth-stencil are being cleared when there's 515cdc920a0Smrg * already been some rendering, we could discard the currently 516cdc920a0Smrg * binned scene and start again, but I don't see that as being 517cdc920a0Smrg * a common usage. 5184a49301eSmrg */ 519af69d88dSmrg if (!lp_scene_bin_everywhere(scene, 520af69d88dSmrg LP_RAST_OP_CLEAR_ZSTENCIL, 521af69d88dSmrg lp_rast_arg_clearzs(zsvalue, zsmask))) 522af69d88dSmrg return FALSE; 523cdc920a0Smrg } 524cdc920a0Smrg else { 525cdc920a0Smrg /* Put ourselves into the 'pre-clear' state, specifically to try 526cdc920a0Smrg * and accumulate multiple clears to color and depth_stencil 5277ec681f3Smrg * buffers which the app or gallium frontend might issue 528cdc920a0Smrg * separately. 529cdc920a0Smrg */ 5303464ebd5Sriastradh set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); 5314a49301eSmrg 532cdc920a0Smrg setup->clear.flags |= flags; 5333464ebd5Sriastradh 534af69d88dSmrg setup->clear.zsmask |= zsmask; 535af69d88dSmrg setup->clear.zsvalue = 536af69d88dSmrg (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); 537cdc920a0Smrg } 538af69d88dSmrg 5393464ebd5Sriastradh return TRUE; 5404a49301eSmrg} 5414a49301eSmrg 5423464ebd5Sriastradhvoid 5433464ebd5Sriastradhlp_setup_clear( struct lp_setup_context *setup, 544af69d88dSmrg const union pipe_color_union *color, 5453464ebd5Sriastradh double depth, 5463464ebd5Sriastradh unsigned stencil, 5473464ebd5Sriastradh unsigned flags ) 5484a49301eSmrg{ 549af69d88dSmrg unsigned i; 5504a49301eSmrg 551af69d88dSmrg /* 552af69d88dSmrg * Note any of these (max 9) clears could fail (but at most there should 553af69d88dSmrg * be just one failure!). This avoids doing the previous succeeded 554af69d88dSmrg * clears again (we still clear tiles twice if a clear command succeeded 555af69d88dSmrg * partially for one buffer). 556af69d88dSmrg */ 557af69d88dSmrg if (flags & PIPE_CLEAR_DEPTHSTENCIL) { 558af69d88dSmrg unsigned flagszs = flags & PIPE_CLEAR_DEPTHSTENCIL; 559af69d88dSmrg if (!lp_setup_try_clear_zs(setup, depth, stencil, flagszs)) { 560af69d88dSmrg lp_setup_flush(setup, NULL, __FUNCTION__); 5614a49301eSmrg 562af69d88dSmrg if (!lp_setup_try_clear_zs(setup, depth, stencil, flagszs)) 563af69d88dSmrg assert(0); 564af69d88dSmrg } 565af69d88dSmrg } 5664a49301eSmrg 567af69d88dSmrg if (flags & PIPE_CLEAR_COLOR) { 568af69d88dSmrg assert(PIPE_CLEAR_COLOR0 == (1 << 2)); 569af69d88dSmrg for (i = 0; i < setup->fb.nr_cbufs; i++) { 570af69d88dSmrg if ((flags & (1 << (2 + i))) && setup->fb.cbufs[i]) { 571af69d88dSmrg if (!lp_setup_try_clear_color_buffer(setup, color, i)) { 572af69d88dSmrg lp_setup_flush(setup, NULL, __FUNCTION__); 573af69d88dSmrg 574af69d88dSmrg if (!lp_setup_try_clear_color_buffer(setup, color, i)) 575af69d88dSmrg assert(0); 576af69d88dSmrg } 577af69d88dSmrg } 578af69d88dSmrg } 579af69d88dSmrg } 580af69d88dSmrg} 5814a49301eSmrg 5824a49301eSmrg 5834a49301eSmrg 584cdc920a0Smrgvoid 5853464ebd5Sriastradhlp_setup_set_triangle_state( struct lp_setup_context *setup, 586cdc920a0Smrg unsigned cull_mode, 587cdc920a0Smrg boolean ccw_is_frontface, 5883464ebd5Sriastradh boolean scissor, 589af69d88dSmrg boolean half_pixel_center, 5907ec681f3Smrg boolean bottom_edge_rule, 5917ec681f3Smrg boolean multisample) 5924a49301eSmrg{ 593cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 594cdc920a0Smrg 595cdc920a0Smrg setup->ccw_is_frontface = ccw_is_frontface; 596cdc920a0Smrg setup->cullmode = cull_mode; 597cdc920a0Smrg setup->triangle = first_triangle; 5987ec681f3Smrg setup->rect = first_rectangle; 5997ec681f3Smrg setup->multisample = multisample; 600af69d88dSmrg setup->pixel_offset = half_pixel_center ? 0.5f : 0.0f; 601af69d88dSmrg setup->bottom_edge_rule = bottom_edge_rule; 6023464ebd5Sriastradh 6033464ebd5Sriastradh if (setup->scissor_test != scissor) { 6043464ebd5Sriastradh setup->dirty |= LP_SETUP_NEW_SCISSOR; 6053464ebd5Sriastradh setup->scissor_test = scissor; 6063464ebd5Sriastradh } 6074a49301eSmrg} 6084a49301eSmrg 6093464ebd5Sriastradhvoid 6103464ebd5Sriastradhlp_setup_set_line_state( struct lp_setup_context *setup, 6117ec681f3Smrg float line_width, 6127ec681f3Smrg boolean line_rectangular) 6133464ebd5Sriastradh{ 6143464ebd5Sriastradh LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 6154a49301eSmrg 6163464ebd5Sriastradh setup->line_width = line_width; 6177ec681f3Smrg setup->rectangular_lines = line_rectangular; 6183464ebd5Sriastradh} 619cdc920a0Smrg 6203464ebd5Sriastradhvoid 6213464ebd5Sriastradhlp_setup_set_point_state( struct lp_setup_context *setup, 622af69d88dSmrg float point_size, 6237ec681f3Smrg boolean point_tri_clip, 6243464ebd5Sriastradh boolean point_size_per_vertex, 6253464ebd5Sriastradh uint sprite_coord_enable, 6267ec681f3Smrg uint sprite_coord_origin, 6277ec681f3Smrg boolean point_quad_rasterization) 6284a49301eSmrg{ 6293464ebd5Sriastradh LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 6304a49301eSmrg 6313464ebd5Sriastradh setup->point_size = point_size; 6323464ebd5Sriastradh setup->sprite_coord_enable = sprite_coord_enable; 6333464ebd5Sriastradh setup->sprite_coord_origin = sprite_coord_origin; 6347ec681f3Smrg setup->point_tri_clip = point_tri_clip; 6353464ebd5Sriastradh setup->point_size_per_vertex = point_size_per_vertex; 6367ec681f3Smrg setup->legacy_points = !point_quad_rasterization; 637cdc920a0Smrg} 6384a49301eSmrg 639cdc920a0Smrgvoid 6403464ebd5Sriastradhlp_setup_set_setup_variant( struct lp_setup_context *setup, 6413464ebd5Sriastradh const struct lp_setup_variant *variant) 642cdc920a0Smrg{ 6433464ebd5Sriastradh LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 6443464ebd5Sriastradh 6453464ebd5Sriastradh setup->setup.variant = variant; 6463464ebd5Sriastradh} 6473464ebd5Sriastradh 6483464ebd5Sriastradhvoid 6493464ebd5Sriastradhlp_setup_set_fs_variant( struct lp_setup_context *setup, 6503464ebd5Sriastradh struct lp_fragment_shader_variant *variant) 6513464ebd5Sriastradh{ 6523464ebd5Sriastradh LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, 6533464ebd5Sriastradh variant); 6544a49301eSmrg 6553464ebd5Sriastradh setup->fs.current.variant = variant; 656cdc920a0Smrg setup->dirty |= LP_SETUP_NEW_FS; 6574a49301eSmrg} 6584a49301eSmrg 659cdc920a0Smrgvoid 6603464ebd5Sriastradhlp_setup_set_fs_constants(struct lp_setup_context *setup, 661af69d88dSmrg unsigned num, 662af69d88dSmrg struct pipe_constant_buffer *buffers) 6634a49301eSmrg{ 664af69d88dSmrg unsigned i; 665af69d88dSmrg 666af69d88dSmrg LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers); 667cdc920a0Smrg 66801e04c3fSmrg assert(num <= ARRAY_SIZE(setup->constants)); 669cdc920a0Smrg 670af69d88dSmrg for (i = 0; i < num; ++i) { 6717ec681f3Smrg util_copy_constant_buffer(&setup->constants[i].current, &buffers[i], false); 672af69d88dSmrg } 67301e04c3fSmrg for (; i < ARRAY_SIZE(setup->constants); i++) { 6747ec681f3Smrg util_copy_constant_buffer(&setup->constants[i].current, NULL, false); 675af69d88dSmrg } 676cdc920a0Smrg setup->dirty |= LP_SETUP_NEW_CONSTANTS; 6774a49301eSmrg} 6784a49301eSmrg 6797ec681f3Smrgvoid 6807ec681f3Smrglp_setup_set_fs_ssbos(struct lp_setup_context *setup, 6817ec681f3Smrg unsigned num, 6827ec681f3Smrg struct pipe_shader_buffer *buffers) 6837ec681f3Smrg{ 6847ec681f3Smrg unsigned i; 6857ec681f3Smrg 6867ec681f3Smrg LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers); 6877ec681f3Smrg 6887ec681f3Smrg assert(num <= ARRAY_SIZE(setup->ssbos)); 6897ec681f3Smrg 6907ec681f3Smrg for (i = 0; i < num; ++i) { 6917ec681f3Smrg util_copy_shader_buffer(&setup->ssbos[i].current, &buffers[i]); 6927ec681f3Smrg } 6937ec681f3Smrg for (; i < ARRAY_SIZE(setup->ssbos); i++) { 6947ec681f3Smrg util_copy_shader_buffer(&setup->ssbos[i].current, NULL); 6957ec681f3Smrg } 6967ec681f3Smrg setup->dirty |= LP_SETUP_NEW_SSBOS; 6977ec681f3Smrg} 6987ec681f3Smrg 6997ec681f3Smrgvoid 7007ec681f3Smrglp_setup_set_fs_images(struct lp_setup_context *setup, 7017ec681f3Smrg unsigned num, 7027ec681f3Smrg struct pipe_image_view *images) 7037ec681f3Smrg{ 7047ec681f3Smrg unsigned i; 7057ec681f3Smrg 7067ec681f3Smrg LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) images); 7077ec681f3Smrg 7087ec681f3Smrg assert(num <= ARRAY_SIZE(setup->images)); 7097ec681f3Smrg 7107ec681f3Smrg for (i = 0; i < num; ++i) { 7117ec681f3Smrg struct pipe_image_view *image = &images[i]; 7127ec681f3Smrg util_copy_image_view(&setup->images[i].current, &images[i]); 7137ec681f3Smrg 7147ec681f3Smrg struct pipe_resource *res = image->resource; 7157ec681f3Smrg struct llvmpipe_resource *lp_res = llvmpipe_resource(res); 7167ec681f3Smrg struct lp_jit_image *jit_image; 7177ec681f3Smrg 7187ec681f3Smrg jit_image = &setup->fs.current.jit_context.images[i]; 7197ec681f3Smrg if (!lp_res) 7207ec681f3Smrg continue; 7217ec681f3Smrg if (!lp_res->dt) { 7227ec681f3Smrg /* regular texture - setup array of mipmap level offsets */ 7237ec681f3Smrg if (llvmpipe_resource_is_texture(res)) { 7247ec681f3Smrg jit_image->base = lp_res->tex_data; 7257ec681f3Smrg } else 7267ec681f3Smrg jit_image->base = lp_res->data; 7277ec681f3Smrg 7287ec681f3Smrg jit_image->width = res->width0; 7297ec681f3Smrg jit_image->height = res->height0; 7307ec681f3Smrg jit_image->depth = res->depth0; 7317ec681f3Smrg jit_image->num_samples = res->nr_samples; 7327ec681f3Smrg 7337ec681f3Smrg if (llvmpipe_resource_is_texture(res)) { 7347ec681f3Smrg uint32_t mip_offset = lp_res->mip_offsets[image->u.tex.level]; 7357ec681f3Smrg const uint32_t bw = util_format_get_blockwidth(image->resource->format); 7367ec681f3Smrg const uint32_t bh = util_format_get_blockheight(image->resource->format); 7377ec681f3Smrg 7387ec681f3Smrg jit_image->width = DIV_ROUND_UP(jit_image->width, bw); 7397ec681f3Smrg jit_image->height = DIV_ROUND_UP(jit_image->height, bh); 7407ec681f3Smrg jit_image->width = u_minify(jit_image->width, image->u.tex.level); 7417ec681f3Smrg jit_image->height = u_minify(jit_image->height, image->u.tex.level); 7427ec681f3Smrg 7437ec681f3Smrg if (res->target == PIPE_TEXTURE_1D_ARRAY || 7447ec681f3Smrg res->target == PIPE_TEXTURE_2D_ARRAY || 7457ec681f3Smrg res->target == PIPE_TEXTURE_3D || 7467ec681f3Smrg res->target == PIPE_TEXTURE_CUBE || 7477ec681f3Smrg res->target == PIPE_TEXTURE_CUBE_ARRAY) { 7487ec681f3Smrg /* 7497ec681f3Smrg * For array textures, we don't have first_layer, instead 7507ec681f3Smrg * adjust last_layer (stored as depth) plus the mip level offsets 7517ec681f3Smrg * (as we have mip-first layout can't just adjust base ptr). 7527ec681f3Smrg * XXX For mip levels, could do something similar. 7537ec681f3Smrg */ 7547ec681f3Smrg jit_image->depth = image->u.tex.last_layer - image->u.tex.first_layer + 1; 7557ec681f3Smrg mip_offset += image->u.tex.first_layer * lp_res->img_stride[image->u.tex.level]; 7567ec681f3Smrg } else 7577ec681f3Smrg jit_image->depth = u_minify(jit_image->depth, image->u.tex.level); 7587ec681f3Smrg 7597ec681f3Smrg jit_image->row_stride = lp_res->row_stride[image->u.tex.level]; 7607ec681f3Smrg jit_image->img_stride = lp_res->img_stride[image->u.tex.level]; 7617ec681f3Smrg jit_image->sample_stride = lp_res->sample_stride; 7627ec681f3Smrg jit_image->base = (uint8_t *)jit_image->base + mip_offset; 7637ec681f3Smrg } 7647ec681f3Smrg else { 7657ec681f3Smrg unsigned view_blocksize = util_format_get_blocksize(image->format); 7667ec681f3Smrg jit_image->width = image->u.buf.size / view_blocksize; 7677ec681f3Smrg jit_image->base = (uint8_t *)jit_image->base + image->u.buf.offset; 7687ec681f3Smrg } 7697ec681f3Smrg } 7707ec681f3Smrg } 7717ec681f3Smrg for (; i < ARRAY_SIZE(setup->images); i++) { 7727ec681f3Smrg util_copy_image_view(&setup->images[i].current, NULL); 7737ec681f3Smrg } 7747ec681f3Smrg setup->dirty |= LP_SETUP_NEW_FS; 7757ec681f3Smrg} 7764a49301eSmrg 777cdc920a0Smrgvoid 7783464ebd5Sriastradhlp_setup_set_alpha_ref_value( struct lp_setup_context *setup, 779cdc920a0Smrg float alpha_ref_value ) 7804a49301eSmrg{ 781cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value); 7824a49301eSmrg 783cdc920a0Smrg if(setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) { 784cdc920a0Smrg setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value; 785cdc920a0Smrg setup->dirty |= LP_SETUP_NEW_FS; 786cdc920a0Smrg } 787cdc920a0Smrg} 7884a49301eSmrg 789cdc920a0Smrgvoid 7903464ebd5Sriastradhlp_setup_set_stencil_ref_values( struct lp_setup_context *setup, 7913464ebd5Sriastradh const ubyte refs[2] ) 7923464ebd5Sriastradh{ 7933464ebd5Sriastradh LP_DBG(DEBUG_SETUP, "%s %d %d\n", __FUNCTION__, refs[0], refs[1]); 7943464ebd5Sriastradh 7953464ebd5Sriastradh if (setup->fs.current.jit_context.stencil_ref_front != refs[0] || 7963464ebd5Sriastradh setup->fs.current.jit_context.stencil_ref_back != refs[1]) { 7973464ebd5Sriastradh setup->fs.current.jit_context.stencil_ref_front = refs[0]; 7983464ebd5Sriastradh setup->fs.current.jit_context.stencil_ref_back = refs[1]; 7993464ebd5Sriastradh setup->dirty |= LP_SETUP_NEW_FS; 8003464ebd5Sriastradh } 8013464ebd5Sriastradh} 8023464ebd5Sriastradh 8033464ebd5Sriastradhvoid 8043464ebd5Sriastradhlp_setup_set_blend_color( struct lp_setup_context *setup, 805cdc920a0Smrg const struct pipe_blend_color *blend_color ) 806cdc920a0Smrg{ 807cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 8084a49301eSmrg 809cdc920a0Smrg assert(blend_color); 8104a49301eSmrg 811cdc920a0Smrg if(memcmp(&setup->blend_color.current, blend_color, sizeof *blend_color) != 0) { 812cdc920a0Smrg memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color); 813cdc920a0Smrg setup->dirty |= LP_SETUP_NEW_BLEND_COLOR; 814cdc920a0Smrg } 815cdc920a0Smrg} 8164a49301eSmrg 8174a49301eSmrg 818cdc920a0Smrgvoid 819af69d88dSmrglp_setup_set_scissors( struct lp_setup_context *setup, 820af69d88dSmrg const struct pipe_scissor_state *scissors ) 821cdc920a0Smrg{ 822af69d88dSmrg unsigned i; 823cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 8244a49301eSmrg 825af69d88dSmrg assert(scissors); 8264a49301eSmrg 827af69d88dSmrg for (i = 0; i < PIPE_MAX_VIEWPORTS; ++i) { 828af69d88dSmrg setup->scissors[i].x0 = scissors[i].minx; 829af69d88dSmrg setup->scissors[i].x1 = scissors[i].maxx-1; 830af69d88dSmrg setup->scissors[i].y0 = scissors[i].miny; 831af69d88dSmrg setup->scissors[i].y1 = scissors[i].maxy-1; 832af69d88dSmrg } 8333464ebd5Sriastradh setup->dirty |= LP_SETUP_NEW_SCISSOR; 8344a49301eSmrg} 8354a49301eSmrg 8367ec681f3Smrgvoid 8377ec681f3Smrglp_setup_set_sample_mask(struct lp_setup_context *setup, 8387ec681f3Smrg uint32_t sample_mask) 8397ec681f3Smrg{ 8407ec681f3Smrg if (setup->fs.current.jit_context.sample_mask != sample_mask) { 8417ec681f3Smrg setup->fs.current.jit_context.sample_mask = sample_mask; 8427ec681f3Smrg setup->dirty |= LP_SETUP_NEW_FS; 8437ec681f3Smrg } 8447ec681f3Smrg} 8454a49301eSmrg 846cdc920a0Smrgvoid 84701e04c3fSmrglp_setup_set_flatshade_first(struct lp_setup_context *setup, 84801e04c3fSmrg boolean flatshade_first) 8494a49301eSmrg{ 850cdc920a0Smrg setup->flatshade_first = flatshade_first; 8514a49301eSmrg} 8524a49301eSmrg 853af69d88dSmrgvoid 85401e04c3fSmrglp_setup_set_rasterizer_discard(struct lp_setup_context *setup, 85501e04c3fSmrg boolean rasterizer_discard) 856af69d88dSmrg{ 857af69d88dSmrg if (setup->rasterizer_discard != rasterizer_discard) { 858af69d88dSmrg setup->rasterizer_discard = rasterizer_discard; 85901e04c3fSmrg setup->line = first_line; 86001e04c3fSmrg setup->point = first_point; 86101e04c3fSmrg setup->triangle = first_triangle; 8627ec681f3Smrg setup->rect = first_rectangle; 863af69d88dSmrg } 864af69d88dSmrg} 8654a49301eSmrg 866cdc920a0Smrgvoid 86701e04c3fSmrglp_setup_set_vertex_info(struct lp_setup_context *setup, 86801e04c3fSmrg struct vertex_info *vertex_info) 8694a49301eSmrg{ 870cdc920a0Smrg /* XXX: just silently holding onto the pointer: 871cdc920a0Smrg */ 872cdc920a0Smrg setup->vertex_info = vertex_info; 8734a49301eSmrg} 8744a49301eSmrg 8754a49301eSmrg 8767ec681f3Smrgvoid 8777ec681f3Smrglp_setup_set_linear_mode( struct lp_setup_context *setup, 8787ec681f3Smrg boolean mode ) 8797ec681f3Smrg{ 8807ec681f3Smrg /* The linear rasterizer requires sse2 both at compile and runtime, 8817ec681f3Smrg * in particular for the code in lp_rast_linear_fallback.c. This 8827ec681f3Smrg * is more than ten-year-old technology, so it's a reasonable 8837ec681f3Smrg * baseline. 8847ec681f3Smrg */ 8857ec681f3Smrg#if defined(PIPE_ARCH_SSE) 8867ec681f3Smrg setup->permit_linear_rasterizer = (mode && 8877ec681f3Smrg util_get_cpu_caps()->has_sse2); 8887ec681f3Smrg#else 8897ec681f3Smrg setup->permit_linear_rasterizer = FALSE; 8907ec681f3Smrg#endif 8917ec681f3Smrg} 8927ec681f3Smrg 8937ec681f3Smrg 894af69d88dSmrg/** 895af69d88dSmrg * Called during state validation when LP_NEW_VIEWPORT is set. 896af69d88dSmrg */ 897af69d88dSmrgvoid 898af69d88dSmrglp_setup_set_viewports(struct lp_setup_context *setup, 899af69d88dSmrg unsigned num_viewports, 900af69d88dSmrg const struct pipe_viewport_state *viewports) 901af69d88dSmrg{ 902af69d88dSmrg struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); 9037ec681f3Smrg float half_height, x0, y0; 904af69d88dSmrg unsigned i; 905af69d88dSmrg 906af69d88dSmrg LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 907af69d88dSmrg 908af69d88dSmrg assert(num_viewports <= PIPE_MAX_VIEWPORTS); 909af69d88dSmrg assert(viewports); 910af69d88dSmrg 9117ec681f3Smrg /* 9127ec681f3Smrg * Linear rasterizer path for scissor/viewport intersection. 9137ec681f3Smrg * 9147ec681f3Smrg * Calculate "scissor" rect from the (first) viewport. 9157ec681f3Smrg * Just like stored scissor rects need inclusive coords. 9167ec681f3Smrg * For rounding, assume half pixel center (d3d9 should not end up 9177ec681f3Smrg * with fractional viewports) - quite obviously for msaa we'd need 9187ec681f3Smrg * fractional values here (and elsewhere for the point bounding box). 9197ec681f3Smrg * 9207ec681f3Smrg * See: lp_setup.c::try_update_scene_state 9217ec681f3Smrg */ 9227ec681f3Smrg half_height = fabsf(viewports[0].scale[1]); 9237ec681f3Smrg x0 = viewports[0].translate[0] - viewports[0].scale[0]; 9247ec681f3Smrg y0 = viewports[0].translate[1] - half_height; 9257ec681f3Smrg setup->vpwh.x0 = (int)(x0 + 0.5f); 9267ec681f3Smrg setup->vpwh.x1 = (int)(viewports[0].scale[0] * 2.0f + x0 - 0.5f); 9277ec681f3Smrg setup->vpwh.y0 = (int)(y0 + 0.5f); 9287ec681f3Smrg setup->vpwh.y1 = (int)(half_height * 2.0f + y0 - 0.5f); 9297ec681f3Smrg setup->dirty |= LP_SETUP_NEW_SCISSOR; 9307ec681f3Smrg 931af69d88dSmrg /* 932af69d88dSmrg * For use in lp_state_fs.c, propagate the viewport values for all viewports. 933af69d88dSmrg */ 934af69d88dSmrg for (i = 0; i < num_viewports; i++) { 935af69d88dSmrg float min_depth; 936af69d88dSmrg float max_depth; 93701e04c3fSmrg util_viewport_zmin_zmax(&viewports[i], lp->rasterizer->clip_halfz, 93801e04c3fSmrg &min_depth, &max_depth); 939af69d88dSmrg 940af69d88dSmrg if (setup->viewports[i].min_depth != min_depth || 941af69d88dSmrg setup->viewports[i].max_depth != max_depth) { 942af69d88dSmrg setup->viewports[i].min_depth = min_depth; 943af69d88dSmrg setup->viewports[i].max_depth = max_depth; 944af69d88dSmrg setup->dirty |= LP_SETUP_NEW_VIEWPORTS; 945af69d88dSmrg } 946af69d88dSmrg } 947af69d88dSmrg} 948af69d88dSmrg 949af69d88dSmrg 9504a49301eSmrg/** 9517ec681f3Smrg * Called directly by llvmpipe_set_sampler_views 9524a49301eSmrg */ 953cdc920a0Smrgvoid 9543464ebd5Sriastradhlp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, 9553464ebd5Sriastradh unsigned num, 9563464ebd5Sriastradh struct pipe_sampler_view **views) 9574a49301eSmrg{ 95801e04c3fSmrg unsigned i, max_tex_num; 9594a49301eSmrg 960cdc920a0Smrg LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 9614a49301eSmrg 962af69d88dSmrg assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); 9634a49301eSmrg 96401e04c3fSmrg max_tex_num = MAX2(num, setup->fs.current_tex_num); 96501e04c3fSmrg 96601e04c3fSmrg for (i = 0; i < max_tex_num; i++) { 9673464ebd5Sriastradh struct pipe_sampler_view *view = i < num ? views[i] : NULL; 9684a49301eSmrg 9697ec681f3Smrg /* We are going to overwrite/unref the current texture further below. If 9707ec681f3Smrg * set, make sure to unmap its resource to avoid leaking previous 9717ec681f3Smrg * mapping. */ 9727ec681f3Smrg if (setup->fs.current_tex[i]) 9737ec681f3Smrg llvmpipe_resource_unmap(setup->fs.current_tex[i], 0, 0); 9747ec681f3Smrg 9753464ebd5Sriastradh if (view) { 976af69d88dSmrg struct pipe_resource *res = view->texture; 977af69d88dSmrg struct llvmpipe_resource *lp_tex = llvmpipe_resource(res); 978cdc920a0Smrg struct lp_jit_texture *jit_tex; 979cdc920a0Smrg jit_tex = &setup->fs.current.jit_context.textures[i]; 9803464ebd5Sriastradh 9813464ebd5Sriastradh /* We're referencing the texture's internal data, so save a 9823464ebd5Sriastradh * reference to it. 9833464ebd5Sriastradh */ 984af69d88dSmrg pipe_resource_reference(&setup->fs.current_tex[i], res); 9853464ebd5Sriastradh 9863464ebd5Sriastradh if (!lp_tex->dt) { 987af69d88dSmrg /* regular texture - setup array of mipmap level offsets */ 9883464ebd5Sriastradh int j; 989af69d88dSmrg unsigned first_level = 0; 990af69d88dSmrg unsigned last_level = 0; 991af69d88dSmrg 992af69d88dSmrg if (llvmpipe_resource_is_texture(res)) { 993af69d88dSmrg first_level = view->u.tex.first_level; 994af69d88dSmrg last_level = view->u.tex.last_level; 995af69d88dSmrg assert(first_level <= last_level); 996af69d88dSmrg assert(last_level <= res->last_level); 997af69d88dSmrg jit_tex->base = lp_tex->tex_data; 998af69d88dSmrg } 999af69d88dSmrg else { 1000af69d88dSmrg jit_tex->base = lp_tex->data; 1001af69d88dSmrg } 1002af69d88dSmrg 1003af69d88dSmrg if (LP_PERF & PERF_TEX_MEM) { 1004af69d88dSmrg /* use dummy tile memory */ 1005af69d88dSmrg jit_tex->base = lp_dummy_tile; 1006af69d88dSmrg jit_tex->width = TILE_SIZE/8; 1007af69d88dSmrg jit_tex->height = TILE_SIZE/8; 1008af69d88dSmrg jit_tex->depth = 1; 1009af69d88dSmrg jit_tex->first_level = 0; 1010af69d88dSmrg jit_tex->last_level = 0; 1011af69d88dSmrg jit_tex->mip_offsets[0] = 0; 1012af69d88dSmrg jit_tex->row_stride[0] = 0; 1013af69d88dSmrg jit_tex->img_stride[0] = 0; 10147ec681f3Smrg jit_tex->num_samples = 0; 10157ec681f3Smrg jit_tex->sample_stride = 0; 1016af69d88dSmrg } 1017af69d88dSmrg else { 1018af69d88dSmrg jit_tex->width = res->width0; 1019af69d88dSmrg jit_tex->height = res->height0; 1020af69d88dSmrg jit_tex->depth = res->depth0; 1021af69d88dSmrg jit_tex->first_level = first_level; 1022af69d88dSmrg jit_tex->last_level = last_level; 10237ec681f3Smrg jit_tex->num_samples = res->nr_samples; 10247ec681f3Smrg jit_tex->sample_stride = 0; 1025af69d88dSmrg 1026af69d88dSmrg if (llvmpipe_resource_is_texture(res)) { 1027af69d88dSmrg for (j = first_level; j <= last_level; j++) { 1028af69d88dSmrg jit_tex->mip_offsets[j] = lp_tex->mip_offsets[j]; 1029af69d88dSmrg jit_tex->row_stride[j] = lp_tex->row_stride[j]; 1030af69d88dSmrg jit_tex->img_stride[j] = lp_tex->img_stride[j]; 1031af69d88dSmrg } 1032af69d88dSmrg 10337ec681f3Smrg jit_tex->sample_stride = lp_tex->sample_stride; 10347ec681f3Smrg 1035af69d88dSmrg if (res->target == PIPE_TEXTURE_1D_ARRAY || 1036af69d88dSmrg res->target == PIPE_TEXTURE_2D_ARRAY || 103701e04c3fSmrg res->target == PIPE_TEXTURE_CUBE || 1038af69d88dSmrg res->target == PIPE_TEXTURE_CUBE_ARRAY) { 1039af69d88dSmrg /* 1040af69d88dSmrg * For array textures, we don't have first_layer, instead 1041af69d88dSmrg * adjust last_layer (stored as depth) plus the mip level offsets 1042af69d88dSmrg * (as we have mip-first layout can't just adjust base ptr). 1043af69d88dSmrg * XXX For mip levels, could do something similar. 1044af69d88dSmrg */ 1045af69d88dSmrg jit_tex->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1; 1046af69d88dSmrg for (j = first_level; j <= last_level; j++) { 1047af69d88dSmrg jit_tex->mip_offsets[j] += view->u.tex.first_layer * 1048af69d88dSmrg lp_tex->img_stride[j]; 1049af69d88dSmrg } 105001e04c3fSmrg if (view->target == PIPE_TEXTURE_CUBE || 105101e04c3fSmrg view->target == PIPE_TEXTURE_CUBE_ARRAY) { 1052af69d88dSmrg assert(jit_tex->depth % 6 == 0); 1053af69d88dSmrg } 1054af69d88dSmrg assert(view->u.tex.first_layer <= view->u.tex.last_layer); 1055af69d88dSmrg assert(view->u.tex.last_layer < res->array_size); 1056af69d88dSmrg } 1057af69d88dSmrg } 1058af69d88dSmrg else { 1059af69d88dSmrg /* 106001e04c3fSmrg * For buffers, we don't have "offset", instead adjust 106101e04c3fSmrg * the size (stored as width) plus the base pointer. 1062af69d88dSmrg */ 1063af69d88dSmrg unsigned view_blocksize = util_format_get_blocksize(view->format); 1064af69d88dSmrg /* probably don't really need to fill that out */ 1065af69d88dSmrg jit_tex->mip_offsets[0] = 0; 1066af69d88dSmrg jit_tex->row_stride[0] = 0; 106701e04c3fSmrg jit_tex->img_stride[0] = 0; 1068af69d88dSmrg 1069af69d88dSmrg /* everything specified in number of elements here. */ 107001e04c3fSmrg jit_tex->width = view->u.buf.size / view_blocksize; 107101e04c3fSmrg jit_tex->base = (uint8_t *)jit_tex->base + view->u.buf.offset; 1072af69d88dSmrg /* XXX Unsure if we need to sanitize parameters? */ 107301e04c3fSmrg assert(view->u.buf.offset + view->u.buf.size <= res->width0); 10743464ebd5Sriastradh } 10753464ebd5Sriastradh } 1076cdc920a0Smrg } 1077cdc920a0Smrg else { 10783464ebd5Sriastradh /* display target texture/surface */ 10797ec681f3Smrg jit_tex->base = llvmpipe_resource_map(res, 0, 0, LP_TEX_USAGE_READ); 10803464ebd5Sriastradh jit_tex->row_stride[0] = lp_tex->row_stride[0]; 10813464ebd5Sriastradh jit_tex->img_stride[0] = lp_tex->img_stride[0]; 1082af69d88dSmrg jit_tex->mip_offsets[0] = 0; 1083af69d88dSmrg jit_tex->width = res->width0; 1084af69d88dSmrg jit_tex->height = res->height0; 1085af69d88dSmrg jit_tex->depth = res->depth0; 1086af69d88dSmrg jit_tex->first_level = jit_tex->last_level = 0; 10877ec681f3Smrg jit_tex->num_samples = res->nr_samples; 10887ec681f3Smrg jit_tex->sample_stride = 0; 1089af69d88dSmrg assert(jit_tex->base); 1090cdc920a0Smrg } 10913464ebd5Sriastradh } 109201e04c3fSmrg else { 109301e04c3fSmrg pipe_resource_reference(&setup->fs.current_tex[i], NULL); 109401e04c3fSmrg } 10953464ebd5Sriastradh } 109601e04c3fSmrg setup->fs.current_tex_num = num; 10974a49301eSmrg 10983464ebd5Sriastradh setup->dirty |= LP_SETUP_NEW_FS; 10993464ebd5Sriastradh} 11003464ebd5Sriastradh 11013464ebd5Sriastradh/** 11023464ebd5Sriastradh * Called during state validation when LP_NEW_SAMPLER is set. 11033464ebd5Sriastradh */ 11043464ebd5Sriastradhvoid 11053464ebd5Sriastradhlp_setup_set_fragment_sampler_state(struct lp_setup_context *setup, 11063464ebd5Sriastradh unsigned num, 1107af69d88dSmrg struct pipe_sampler_state **samplers) 11083464ebd5Sriastradh{ 11093464ebd5Sriastradh unsigned i; 11103464ebd5Sriastradh 11113464ebd5Sriastradh LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 11123464ebd5Sriastradh 11133464ebd5Sriastradh assert(num <= PIPE_MAX_SAMPLERS); 11143464ebd5Sriastradh 11153464ebd5Sriastradh for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 11163464ebd5Sriastradh const struct pipe_sampler_state *sampler = i < num ? samplers[i] : NULL; 11173464ebd5Sriastradh 11183464ebd5Sriastradh if (sampler) { 1119af69d88dSmrg struct lp_jit_sampler *jit_sam; 1120af69d88dSmrg jit_sam = &setup->fs.current.jit_context.samplers[i]; 11213464ebd5Sriastradh 1122af69d88dSmrg jit_sam->min_lod = sampler->min_lod; 1123af69d88dSmrg jit_sam->max_lod = sampler->max_lod; 1124af69d88dSmrg jit_sam->lod_bias = sampler->lod_bias; 11257ec681f3Smrg jit_sam->max_aniso = sampler->max_anisotropy; 1126af69d88dSmrg COPY_4V(jit_sam->border_color, sampler->border_color.f); 11274a49301eSmrg } 11284a49301eSmrg } 1129cdc920a0Smrg 1130cdc920a0Smrg setup->dirty |= LP_SETUP_NEW_FS; 11314a49301eSmrg} 11324a49301eSmrg 11334a49301eSmrg 11347ec681f3Smrg 11357ec681f3Smrg 11364a49301eSmrg/** 1137cdc920a0Smrg * Is the given texture referenced by any scene? 1138cdc920a0Smrg * Note: we have to check all scenes including any scenes currently 1139cdc920a0Smrg * being rendered and the current scene being built. 11404a49301eSmrg */ 1141cdc920a0Smrgunsigned 11423464ebd5Sriastradhlp_setup_is_resource_referenced( const struct lp_setup_context *setup, 11433464ebd5Sriastradh const struct pipe_resource *texture ) 11444a49301eSmrg{ 1145cdc920a0Smrg unsigned i; 1146cdc920a0Smrg 1147cdc920a0Smrg /* check the render targets */ 1148cdc920a0Smrg for (i = 0; i < setup->fb.nr_cbufs; i++) { 1149af69d88dSmrg if (setup->fb.cbufs[i] && setup->fb.cbufs[i]->texture == texture) 11503464ebd5Sriastradh return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 1151cdc920a0Smrg } 1152cdc920a0Smrg if (setup->fb.zsbuf && setup->fb.zsbuf->texture == texture) { 11533464ebd5Sriastradh return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 1154cdc920a0Smrg } 1155cdc920a0Smrg 1156cdc920a0Smrg /* check textures referenced by the scene */ 115701e04c3fSmrg for (i = 0; i < ARRAY_SIZE(setup->scenes); i++) { 11583464ebd5Sriastradh if (lp_scene_is_resource_referenced(setup->scenes[i], texture)) { 11593464ebd5Sriastradh return LP_REFERENCED_FOR_READ; 1160cdc920a0Smrg } 11614a49301eSmrg } 11624a49301eSmrg 11637ec681f3Smrg for (i = 0; i < ARRAY_SIZE(setup->ssbos); i++) { 11647ec681f3Smrg if (setup->ssbos[i].current.buffer == texture) 11657ec681f3Smrg return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 11667ec681f3Smrg } 11677ec681f3Smrg 11687ec681f3Smrg for (i = 0; i < ARRAY_SIZE(setup->images); i++) { 11697ec681f3Smrg if (setup->images[i].current.resource == texture) 11707ec681f3Smrg return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 11717ec681f3Smrg } 11727ec681f3Smrg 11733464ebd5Sriastradh return LP_UNREFERENCED; 11744a49301eSmrg} 11754a49301eSmrg 11764a49301eSmrg 11774a49301eSmrg/** 1178cdc920a0Smrg * Called by vbuf code when we're about to draw something. 1179af69d88dSmrg * 1180af69d88dSmrg * This function stores all dirty state in the current scene's display list 1181af69d88dSmrg * memory, via lp_scene_alloc(). We can not pass pointers of mutable state to 1182af69d88dSmrg * the JIT functions, as the JIT functions will be called later on, most likely 1183af69d88dSmrg * on a different thread. 1184af69d88dSmrg * 1185af69d88dSmrg * When processing dirty state it is imperative that we don't refer to any 1186af69d88dSmrg * pointers previously allocated with lp_scene_alloc() in this function (or any 1187af69d88dSmrg * function) as they may belong to a scene freed since then. 11884a49301eSmrg */ 11893464ebd5Sriastradhstatic boolean 11903464ebd5Sriastradhtry_update_scene_state( struct lp_setup_context *setup ) 11914a49301eSmrg{ 119201e04c3fSmrg static const float fake_const_buf[4]; 11933464ebd5Sriastradh boolean new_scene = (setup->fs.stored == NULL); 11943464ebd5Sriastradh struct lp_scene *scene = setup->scene; 1195af69d88dSmrg unsigned i; 11964a49301eSmrg 11973464ebd5Sriastradh assert(scene); 11984a49301eSmrg 1199af69d88dSmrg if (setup->dirty & LP_SETUP_NEW_VIEWPORTS) { 1200af69d88dSmrg /* 1201af69d88dSmrg * Record new depth range state for changes due to viewport updates. 1202af69d88dSmrg * 1203af69d88dSmrg * TODO: Collapse the existing viewport and depth range information 1204af69d88dSmrg * into one structure, for access by JIT. 1205af69d88dSmrg */ 1206af69d88dSmrg struct lp_jit_viewport *stored; 1207af69d88dSmrg 1208af69d88dSmrg stored = (struct lp_jit_viewport *) 1209af69d88dSmrg lp_scene_alloc(scene, sizeof setup->viewports); 1210af69d88dSmrg 1211af69d88dSmrg if (!stored) { 1212af69d88dSmrg assert(!new_scene); 1213af69d88dSmrg return FALSE; 1214af69d88dSmrg } 1215af69d88dSmrg 1216af69d88dSmrg memcpy(stored, setup->viewports, sizeof setup->viewports); 1217af69d88dSmrg 1218af69d88dSmrg setup->fs.current.jit_context.viewports = stored; 1219af69d88dSmrg setup->dirty |= LP_SETUP_NEW_FS; 1220af69d88dSmrg } 1221af69d88dSmrg 1222cdc920a0Smrg if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { 1223cdc920a0Smrg uint8_t *stored; 1224af69d88dSmrg float* fstored; 1225cdc920a0Smrg unsigned i, j; 1226af69d88dSmrg unsigned size; 1227af69d88dSmrg 1228af69d88dSmrg /* Alloc u8_blend_color (16 x i8) and f_blend_color (4 or 8 x f32) */ 1229af69d88dSmrg size = 4 * 16 * sizeof(uint8_t); 1230af69d88dSmrg size += (LP_MAX_VECTOR_LENGTH / 4) * sizeof(float); 1231af69d88dSmrg stored = lp_scene_alloc_aligned(scene, size, LP_MIN_VECTOR_ALIGN); 12324a49301eSmrg 12333464ebd5Sriastradh if (!stored) { 12343464ebd5Sriastradh assert(!new_scene); 12353464ebd5Sriastradh return FALSE; 12363464ebd5Sriastradh } 12374a49301eSmrg 1238af69d88dSmrg /* Store floating point colour */ 1239af69d88dSmrg fstored = (float*)(stored + 4*16); 1240af69d88dSmrg for (i = 0; i < (LP_MAX_VECTOR_LENGTH / 4); ++i) { 1241af69d88dSmrg fstored[i] = setup->blend_color.current.color[i % 4]; 1242af69d88dSmrg } 1243af69d88dSmrg 1244cdc920a0Smrg /* smear each blend color component across 16 ubyte elements */ 1245cdc920a0Smrg for (i = 0; i < 4; ++i) { 1246cdc920a0Smrg uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); 1247cdc920a0Smrg for (j = 0; j < 16; ++j) 1248cdc920a0Smrg stored[i*16 + j] = c; 1249cdc920a0Smrg } 12504a49301eSmrg 1251cdc920a0Smrg setup->blend_color.stored = stored; 1252af69d88dSmrg setup->fs.current.jit_context.u8_blend_color = stored; 1253af69d88dSmrg setup->fs.current.jit_context.f_blend_color = fstored; 1254cdc920a0Smrg setup->dirty |= LP_SETUP_NEW_FS; 12554a49301eSmrg } 12564a49301eSmrg 12577ec681f3Smrg struct llvmpipe_context *llvmpipe = llvmpipe_context(setup->pipe); 12587ec681f3Smrg if (llvmpipe->dirty & LP_NEW_FS_CONSTANTS) 12597ec681f3Smrg lp_setup_set_fs_constants(llvmpipe->setup, 12607ec681f3Smrg ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]), 12617ec681f3Smrg llvmpipe->constants[PIPE_SHADER_FRAGMENT]); 12627ec681f3Smrg 1263af69d88dSmrg if (setup->dirty & LP_SETUP_NEW_CONSTANTS) { 126401e04c3fSmrg for (i = 0; i < ARRAY_SIZE(setup->constants); ++i) { 1265af69d88dSmrg struct pipe_resource *buffer = setup->constants[i].current.buffer; 126601e04c3fSmrg const unsigned current_size = MIN2(setup->constants[i].current.buffer_size, 126701e04c3fSmrg LP_MAX_TGSI_CONST_BUFFER_SIZE); 1268af69d88dSmrg const ubyte *current_data = NULL; 1269af69d88dSmrg int num_constants; 1270af69d88dSmrg 127101e04c3fSmrg STATIC_ASSERT(DATA_BLOCK_SIZE >= LP_MAX_TGSI_CONST_BUFFER_SIZE); 127201e04c3fSmrg 1273af69d88dSmrg if (buffer) { 1274af69d88dSmrg /* resource buffer */ 1275af69d88dSmrg current_data = (ubyte *) llvmpipe_resource_data(buffer); 1276af69d88dSmrg } 1277af69d88dSmrg else if (setup->constants[i].current.user_buffer) { 1278af69d88dSmrg /* user-space buffer */ 1279af69d88dSmrg current_data = (ubyte *) setup->constants[i].current.user_buffer; 1280af69d88dSmrg } 1281af69d88dSmrg 12827ec681f3Smrg if (current_data && current_size >= sizeof(float)) { 1283af69d88dSmrg current_data += setup->constants[i].current.buffer_offset; 12844a49301eSmrg 1285af69d88dSmrg /* TODO: copy only the actually used constants? */ 12864a49301eSmrg 1287af69d88dSmrg if (setup->constants[i].stored_size != current_size || 1288af69d88dSmrg !setup->constants[i].stored_data || 1289af69d88dSmrg memcmp(setup->constants[i].stored_data, 1290af69d88dSmrg current_data, 1291af69d88dSmrg current_size) != 0) { 1292af69d88dSmrg void *stored; 12934a49301eSmrg 1294af69d88dSmrg stored = lp_scene_alloc(scene, current_size); 1295af69d88dSmrg if (!stored) { 1296af69d88dSmrg assert(!new_scene); 1297af69d88dSmrg return FALSE; 1298af69d88dSmrg } 12994a49301eSmrg 1300af69d88dSmrg memcpy(stored, 1301af69d88dSmrg current_data, 1302af69d88dSmrg current_size); 1303af69d88dSmrg setup->constants[i].stored_size = current_size; 1304af69d88dSmrg setup->constants[i].stored_data = stored; 13054a49301eSmrg } 130601e04c3fSmrg setup->fs.current.jit_context.constants[i] = 130701e04c3fSmrg setup->constants[i].stored_data; 13084a49301eSmrg } 1309af69d88dSmrg else { 1310af69d88dSmrg setup->constants[i].stored_size = 0; 1311af69d88dSmrg setup->constants[i].stored_data = NULL; 131201e04c3fSmrg setup->fs.current.jit_context.constants[i] = fake_const_buf; 1313af69d88dSmrg } 13144a49301eSmrg 1315af69d88dSmrg num_constants = 13167ec681f3Smrg DIV_ROUND_UP(setup->constants[i].stored_size, lp_get_constant_buffer_stride(scene->pipe->screen)); 1317af69d88dSmrg setup->fs.current.jit_context.num_constants[i] = num_constants; 1318af69d88dSmrg setup->dirty |= LP_SETUP_NEW_FS; 1319af69d88dSmrg } 1320cdc920a0Smrg } 1321cdc920a0Smrg 13227ec681f3Smrg if (setup->dirty & LP_SETUP_NEW_SSBOS) { 13237ec681f3Smrg for (i = 0; i < ARRAY_SIZE(setup->ssbos); ++i) { 13247ec681f3Smrg struct pipe_resource *buffer = setup->ssbos[i].current.buffer; 13257ec681f3Smrg const ubyte *current_data = NULL; 13267ec681f3Smrg 13277ec681f3Smrg if (!buffer) 13287ec681f3Smrg continue; 13297ec681f3Smrg /* resource buffer */ 13307ec681f3Smrg current_data = (ubyte *) llvmpipe_resource_data(buffer); 13317ec681f3Smrg if (current_data) { 13327ec681f3Smrg current_data += setup->ssbos[i].current.buffer_offset; 1333cdc920a0Smrg 13347ec681f3Smrg setup->fs.current.jit_context.ssbos[i] = (const uint32_t *)current_data; 13357ec681f3Smrg setup->fs.current.jit_context.num_ssbos[i] = setup->ssbos[i].current.buffer_size; 13367ec681f3Smrg } else { 13377ec681f3Smrg setup->fs.current.jit_context.ssbos[i] = NULL; 13387ec681f3Smrg setup->fs.current.jit_context.num_ssbos[i] = 0; 13397ec681f3Smrg } 13407ec681f3Smrg setup->dirty |= LP_SETUP_NEW_FS; 13417ec681f3Smrg } 13427ec681f3Smrg } 13433464ebd5Sriastradh if (setup->dirty & LP_SETUP_NEW_FS) { 13443464ebd5Sriastradh if (!setup->fs.stored || 13453464ebd5Sriastradh memcmp(setup->fs.stored, 13463464ebd5Sriastradh &setup->fs.current, 13473464ebd5Sriastradh sizeof setup->fs.current) != 0) 13483464ebd5Sriastradh { 13493464ebd5Sriastradh struct lp_rast_state *stored; 13503464ebd5Sriastradh 1351cdc920a0Smrg /* The fs state that's been stored in the scene is different from 1352cdc920a0Smrg * the new, current state. So allocate a new lp_rast_state object 1353cdc920a0Smrg * and append it to the bin's setup data buffer. 1354cdc920a0Smrg */ 13553464ebd5Sriastradh stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); 13563464ebd5Sriastradh if (!stored) { 13573464ebd5Sriastradh assert(!new_scene); 13583464ebd5Sriastradh return FALSE; 13593464ebd5Sriastradh } 13603464ebd5Sriastradh 13617ec681f3Smrg memcpy(&stored->jit_context, 13627ec681f3Smrg &setup->fs.current.jit_context, 13637ec681f3Smrg sizeof setup->fs.current.jit_context); 13647ec681f3Smrg stored->jit_context.aniso_filter_table = lp_build_sample_aniso_filter_table(); 13657ec681f3Smrg stored->variant = setup->fs.current.variant; 13667ec681f3Smrg 13677ec681f3Smrg if (!lp_scene_add_frag_shader_reference(scene, 13687ec681f3Smrg setup->fs.current.variant)) 13697ec681f3Smrg return FALSE; 13703464ebd5Sriastradh setup->fs.stored = stored; 13713464ebd5Sriastradh 13723464ebd5Sriastradh /* The scene now references the textures in the rasterization 13733464ebd5Sriastradh * state record. Note that now. 13743464ebd5Sriastradh */ 137501e04c3fSmrg for (i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) { 13763464ebd5Sriastradh if (setup->fs.current_tex[i]) { 13773464ebd5Sriastradh if (!lp_scene_add_resource_reference(scene, 13783464ebd5Sriastradh setup->fs.current_tex[i], 13793464ebd5Sriastradh new_scene)) { 13803464ebd5Sriastradh assert(!new_scene); 13813464ebd5Sriastradh return FALSE; 13823464ebd5Sriastradh } 13833464ebd5Sriastradh } 13844a49301eSmrg } 13854a49301eSmrg } 13864a49301eSmrg } 1387cdc920a0Smrg 13883464ebd5Sriastradh if (setup->dirty & LP_SETUP_NEW_SCISSOR) { 1389af69d88dSmrg unsigned i; 13907ec681f3Smrg 1391af69d88dSmrg for (i = 0; i < PIPE_MAX_VIEWPORTS; ++i) { 1392af69d88dSmrg setup->draw_regions[i] = setup->framebuffer; 1393af69d88dSmrg if (setup->scissor_test) { 1394af69d88dSmrg u_rect_possible_intersection(&setup->scissors[i], 1395af69d88dSmrg &setup->draw_regions[i]); 1396af69d88dSmrg } 13973464ebd5Sriastradh } 13987ec681f3Smrg if (setup->permit_linear_rasterizer) { 13997ec681f3Smrg /* NOTE: this only takes first vp into account. */ 14007ec681f3Smrg boolean need_vp_scissoring = !!memcmp(&setup->vpwh, &setup->framebuffer, 14017ec681f3Smrg sizeof(setup->framebuffer)); 14027ec681f3Smrg assert(setup->viewport_index_slot < 0); 14037ec681f3Smrg if (need_vp_scissoring) { 14047ec681f3Smrg u_rect_possible_intersection(&setup->vpwh, 14057ec681f3Smrg &setup->draw_regions[0]); 14067ec681f3Smrg } 14077ec681f3Smrg } 14087ec681f3Smrg else if (setup->point_tri_clip) { 14097ec681f3Smrg /* 14107ec681f3Smrg * for d3d-style point clipping, we're going to need 14117ec681f3Smrg * the fake vp scissor too. Hence do the intersection with vp, 14127ec681f3Smrg * but don't indicate this. As above this will only work for first vp 14137ec681f3Smrg * which should be ok because we instruct draw to only skip point 14147ec681f3Smrg * clipping when there's only one viewport (this works because d3d10 14157ec681f3Smrg * points are always single pixel). 14167ec681f3Smrg * (Also note that if we have permit_linear_rasterizer this will 14177ec681f3Smrg * cause large points to always get vp scissored, regardless the 14187ec681f3Smrg * point_tri_clip setting.) 14197ec681f3Smrg */ 14207ec681f3Smrg boolean need_vp_scissoring = !!memcmp(&setup->vpwh, &setup->framebuffer, 14217ec681f3Smrg sizeof(setup->framebuffer)); 14227ec681f3Smrg if (need_vp_scissoring) { 14237ec681f3Smrg u_rect_possible_intersection(&setup->vpwh, 14247ec681f3Smrg &setup->draw_regions[0]); 14257ec681f3Smrg } 14267ec681f3Smrg } 14273464ebd5Sriastradh } 1428af69d88dSmrg 1429cdc920a0Smrg setup->dirty = 0; 1430cdc920a0Smrg 1431cdc920a0Smrg assert(setup->fs.stored); 14323464ebd5Sriastradh return TRUE; 14333464ebd5Sriastradh} 14343464ebd5Sriastradh 14353464ebd5Sriastradhboolean 14363464ebd5Sriastradhlp_setup_update_state( struct lp_setup_context *setup, 14373464ebd5Sriastradh boolean update_scene ) 14383464ebd5Sriastradh{ 14393464ebd5Sriastradh /* Some of the 'draw' pipeline stages may have changed some driver state. 14403464ebd5Sriastradh * Make sure we've processed those state changes before anything else. 14413464ebd5Sriastradh * 14423464ebd5Sriastradh * XXX this is the only place where llvmpipe_context is used in the 14433464ebd5Sriastradh * setup code. This may get refactored/changed... 14443464ebd5Sriastradh */ 14453464ebd5Sriastradh { 14463464ebd5Sriastradh struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); 14473464ebd5Sriastradh if (lp->dirty) { 14483464ebd5Sriastradh llvmpipe_update_derived(lp); 14493464ebd5Sriastradh } 14503464ebd5Sriastradh 14513464ebd5Sriastradh if (lp->setup->dirty) { 14523464ebd5Sriastradh llvmpipe_update_setup(lp); 14533464ebd5Sriastradh } 14543464ebd5Sriastradh 14553464ebd5Sriastradh assert(setup->setup.variant); 14563464ebd5Sriastradh 14573464ebd5Sriastradh /* Will probably need to move this somewhere else, just need 14583464ebd5Sriastradh * to know about vertex shader point size attribute. 14593464ebd5Sriastradh */ 146001e04c3fSmrg setup->psize_slot = lp->psize_slot; 1461af69d88dSmrg setup->viewport_index_slot = lp->viewport_index_slot; 1462af69d88dSmrg setup->layer_slot = lp->layer_slot; 1463af69d88dSmrg setup->face_slot = lp->face_slot; 14643464ebd5Sriastradh 14653464ebd5Sriastradh assert(lp->dirty == 0); 14663464ebd5Sriastradh 14673464ebd5Sriastradh assert(lp->setup_variant.key.size == 14683464ebd5Sriastradh setup->setup.variant->key.size); 14693464ebd5Sriastradh 14703464ebd5Sriastradh assert(memcmp(&lp->setup_variant.key, 14713464ebd5Sriastradh &setup->setup.variant->key, 14723464ebd5Sriastradh setup->setup.variant->key.size) == 0); 14733464ebd5Sriastradh } 14743464ebd5Sriastradh 14753464ebd5Sriastradh if (update_scene && setup->state != SETUP_ACTIVE) { 14763464ebd5Sriastradh if (!set_scene_state( setup, SETUP_ACTIVE, __FUNCTION__ )) 14773464ebd5Sriastradh return FALSE; 14783464ebd5Sriastradh } 14793464ebd5Sriastradh 14803464ebd5Sriastradh /* Only call into update_scene_state() if we already have a 14813464ebd5Sriastradh * scene: 14823464ebd5Sriastradh */ 14833464ebd5Sriastradh if (update_scene && setup->scene) { 14843464ebd5Sriastradh assert(setup->state == SETUP_ACTIVE); 14853464ebd5Sriastradh 14863464ebd5Sriastradh if (try_update_scene_state(setup)) 14873464ebd5Sriastradh return TRUE; 14883464ebd5Sriastradh 14893464ebd5Sriastradh /* Update failed, try to restart the scene. 14903464ebd5Sriastradh * 14913464ebd5Sriastradh * Cannot call lp_setup_flush_and_restart() directly here 14923464ebd5Sriastradh * because of potential recursion. 14933464ebd5Sriastradh */ 14943464ebd5Sriastradh if (!set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__)) 14953464ebd5Sriastradh return FALSE; 14963464ebd5Sriastradh 14973464ebd5Sriastradh if (!set_scene_state(setup, SETUP_ACTIVE, __FUNCTION__)) 14983464ebd5Sriastradh return FALSE; 14993464ebd5Sriastradh 15003464ebd5Sriastradh if (!setup->scene) 15013464ebd5Sriastradh return FALSE; 15023464ebd5Sriastradh 15033464ebd5Sriastradh return try_update_scene_state(setup); 15043464ebd5Sriastradh } 15053464ebd5Sriastradh 15063464ebd5Sriastradh return TRUE; 15074a49301eSmrg} 15084a49301eSmrg 1509cdc920a0Smrg 1510cdc920a0Smrg 1511cdc920a0Smrg/* Only caller is lp_setup_vbuf_destroy() 1512cdc920a0Smrg */ 1513cdc920a0Smrgvoid 15143464ebd5Sriastradhlp_setup_destroy( struct lp_setup_context *setup ) 15154a49301eSmrg{ 15163464ebd5Sriastradh uint i; 15173464ebd5Sriastradh 15183464ebd5Sriastradh lp_setup_reset( setup ); 15194a49301eSmrg 15203464ebd5Sriastradh util_unreference_framebuffer_state(&setup->fb); 15213464ebd5Sriastradh 152201e04c3fSmrg for (i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) { 15237ec681f3Smrg struct pipe_resource **res_ptr = &setup->fs.current_tex[i]; 15247ec681f3Smrg if (*res_ptr) 15257ec681f3Smrg llvmpipe_resource_unmap(*res_ptr, 0, 0); 15267ec681f3Smrg pipe_resource_reference(res_ptr, NULL); 15273464ebd5Sriastradh } 15283464ebd5Sriastradh 152901e04c3fSmrg for (i = 0; i < ARRAY_SIZE(setup->constants); i++) { 1530af69d88dSmrg pipe_resource_reference(&setup->constants[i].current.buffer, NULL); 1531af69d88dSmrg } 15324a49301eSmrg 15337ec681f3Smrg for (i = 0; i < ARRAY_SIZE(setup->ssbos); i++) { 15347ec681f3Smrg pipe_resource_reference(&setup->ssbos[i].current.buffer, NULL); 15357ec681f3Smrg } 15367ec681f3Smrg 1537cdc920a0Smrg /* free the scenes in the 'empty' queue */ 153801e04c3fSmrg for (i = 0; i < ARRAY_SIZE(setup->scenes); i++) { 15393464ebd5Sriastradh struct lp_scene *scene = setup->scenes[i]; 15403464ebd5Sriastradh 15413464ebd5Sriastradh if (scene->fence) 15423464ebd5Sriastradh lp_fence_wait(scene->fence); 15433464ebd5Sriastradh 1544cdc920a0Smrg lp_scene_destroy(scene); 15454a49301eSmrg } 15464a49301eSmrg 15473464ebd5Sriastradh lp_fence_reference(&setup->last_fence, NULL); 15484a49301eSmrg 1549cdc920a0Smrg FREE( setup ); 15504a49301eSmrg} 15514a49301eSmrg 15524a49301eSmrg 15534a49301eSmrg/** 1554cdc920a0Smrg * Create a new primitive tiling engine. Plug it into the backend of 1555cdc920a0Smrg * the draw module. Currently also creates a rasterizer to use with 1556cdc920a0Smrg * it. 15574a49301eSmrg */ 15583464ebd5Sriastradhstruct lp_setup_context * 1559cdc920a0Smrglp_setup_create( struct pipe_context *pipe, 1560cdc920a0Smrg struct draw_context *draw ) 15614a49301eSmrg{ 15623464ebd5Sriastradh struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 1563af69d88dSmrg struct lp_setup_context *setup; 15644a49301eSmrg unsigned i; 15654a49301eSmrg 1566af69d88dSmrg setup = CALLOC_STRUCT(lp_setup_context); 1567af69d88dSmrg if (!setup) { 1568af69d88dSmrg goto no_setup; 1569af69d88dSmrg } 15704a49301eSmrg 1571cdc920a0Smrg lp_setup_init_vbuf(setup); 15723464ebd5Sriastradh 15733464ebd5Sriastradh /* Used only in update_state(): 1574cdc920a0Smrg */ 15753464ebd5Sriastradh setup->pipe = pipe; 1576cdc920a0Smrg 15773464ebd5Sriastradh 15783464ebd5Sriastradh setup->num_threads = screen->num_threads; 1579cdc920a0Smrg setup->vbuf = draw_vbuf_stage(draw, &setup->base); 1580af69d88dSmrg if (!setup->vbuf) { 1581af69d88dSmrg goto no_vbuf; 1582af69d88dSmrg } 1583cdc920a0Smrg 1584cdc920a0Smrg draw_set_rasterize_stage(draw, setup->vbuf); 1585cdc920a0Smrg draw_set_render(draw, &setup->base); 15864a49301eSmrg 1587cdc920a0Smrg /* create some empty scenes */ 1588cdc920a0Smrg for (i = 0; i < MAX_SCENES; i++) { 15893464ebd5Sriastradh setup->scenes[i] = lp_scene_create( pipe ); 1590af69d88dSmrg if (!setup->scenes[i]) { 1591af69d88dSmrg goto no_scenes; 1592af69d88dSmrg } 15934a49301eSmrg } 15944a49301eSmrg 1595cdc920a0Smrg setup->triangle = first_triangle; 1596cdc920a0Smrg setup->line = first_line; 1597cdc920a0Smrg setup->point = first_point; 1598cdc920a0Smrg 1599cdc920a0Smrg setup->dirty = ~0; 16004a49301eSmrg 160101e04c3fSmrg /* Initialize empty default fb correctly, so the rect is empty */ 160201e04c3fSmrg setup->framebuffer.x1 = -1; 160301e04c3fSmrg setup->framebuffer.y1 = -1; 160401e04c3fSmrg 16054a49301eSmrg return setup; 1606cdc920a0Smrg 1607af69d88dSmrgno_scenes: 1608af69d88dSmrg for (i = 0; i < MAX_SCENES; i++) { 1609af69d88dSmrg if (setup->scenes[i]) { 1610af69d88dSmrg lp_scene_destroy(setup->scenes[i]); 1611af69d88dSmrg } 1612af69d88dSmrg } 1613cdc920a0Smrg 1614af69d88dSmrg setup->vbuf->destroy(setup->vbuf); 1615af69d88dSmrgno_vbuf: 1616cdc920a0Smrg FREE(setup); 1617af69d88dSmrgno_setup: 1618cdc920a0Smrg return NULL; 16194a49301eSmrg} 16204a49301eSmrg 16213464ebd5Sriastradh 16223464ebd5Sriastradh/** 16233464ebd5Sriastradh * Put a BeginQuery command into all bins. 16243464ebd5Sriastradh */ 16253464ebd5Sriastradhvoid 16263464ebd5Sriastradhlp_setup_begin_query(struct lp_setup_context *setup, 16273464ebd5Sriastradh struct llvmpipe_query *pq) 16283464ebd5Sriastradh{ 16293464ebd5Sriastradh set_scene_state(setup, SETUP_ACTIVE, "begin_query"); 16303464ebd5Sriastradh 1631af69d88dSmrg if (!(pq->type == PIPE_QUERY_OCCLUSION_COUNTER || 1632af69d88dSmrg pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || 163301e04c3fSmrg pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || 16347ec681f3Smrg pq->type == PIPE_QUERY_PIPELINE_STATISTICS || 16357ec681f3Smrg pq->type == PIPE_QUERY_TIME_ELAPSED)) 1636af69d88dSmrg return; 1637af69d88dSmrg 1638af69d88dSmrg /* init the query to its beginning state */ 1639af69d88dSmrg assert(setup->active_binned_queries < LP_MAX_ACTIVE_BINNED_QUERIES); 1640af69d88dSmrg /* exceeding list size so just ignore the query */ 1641af69d88dSmrg if (setup->active_binned_queries >= LP_MAX_ACTIVE_BINNED_QUERIES) { 1642af69d88dSmrg return; 1643af69d88dSmrg } 1644af69d88dSmrg assert(setup->active_queries[setup->active_binned_queries] == NULL); 1645af69d88dSmrg setup->active_queries[setup->active_binned_queries] = pq; 1646af69d88dSmrg setup->active_binned_queries++; 1647af69d88dSmrg 1648af69d88dSmrg assert(setup->scene); 16493464ebd5Sriastradh if (setup->scene) { 16503464ebd5Sriastradh if (!lp_scene_bin_everywhere(setup->scene, 16513464ebd5Sriastradh LP_RAST_OP_BEGIN_QUERY, 16523464ebd5Sriastradh lp_rast_arg_query(pq))) { 16533464ebd5Sriastradh 16543464ebd5Sriastradh if (!lp_setup_flush_and_restart(setup)) 16553464ebd5Sriastradh return; 16563464ebd5Sriastradh 16573464ebd5Sriastradh if (!lp_scene_bin_everywhere(setup->scene, 16583464ebd5Sriastradh LP_RAST_OP_BEGIN_QUERY, 16593464ebd5Sriastradh lp_rast_arg_query(pq))) { 16603464ebd5Sriastradh return; 16613464ebd5Sriastradh } 16623464ebd5Sriastradh } 1663af69d88dSmrg setup->scene->had_queries |= TRUE; 16643464ebd5Sriastradh } 16653464ebd5Sriastradh} 16663464ebd5Sriastradh 16673464ebd5Sriastradh 16683464ebd5Sriastradh/** 16693464ebd5Sriastradh * Put an EndQuery command into all bins. 16703464ebd5Sriastradh */ 16713464ebd5Sriastradhvoid 16723464ebd5Sriastradhlp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) 16733464ebd5Sriastradh{ 16743464ebd5Sriastradh set_scene_state(setup, SETUP_ACTIVE, "end_query"); 16753464ebd5Sriastradh 1676af69d88dSmrg assert(setup->scene); 16773464ebd5Sriastradh if (setup->scene) { 16783464ebd5Sriastradh /* pq->fence should be the fence of the *last* scene which 16793464ebd5Sriastradh * contributed to the query result. 16803464ebd5Sriastradh */ 16813464ebd5Sriastradh lp_fence_reference(&pq->fence, setup->scene->fence); 16823464ebd5Sriastradh 1683af69d88dSmrg if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || 1684af69d88dSmrg pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || 168501e04c3fSmrg pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || 1686af69d88dSmrg pq->type == PIPE_QUERY_PIPELINE_STATISTICS || 16877ec681f3Smrg pq->type == PIPE_QUERY_TIMESTAMP || 16887ec681f3Smrg pq->type == PIPE_QUERY_TIME_ELAPSED) { 1689af69d88dSmrg if (pq->type == PIPE_QUERY_TIMESTAMP && 1690af69d88dSmrg !(setup->scene->tiles_x | setup->scene->tiles_y)) { 1691af69d88dSmrg /* 1692af69d88dSmrg * If there's a zero width/height framebuffer, there's no bins and 1693af69d88dSmrg * hence no rast task is ever run. So fill in something here instead. 1694af69d88dSmrg */ 1695af69d88dSmrg pq->end[0] = os_time_get_nano(); 1696af69d88dSmrg } 1697af69d88dSmrg 1698af69d88dSmrg if (!lp_scene_bin_everywhere(setup->scene, 1699af69d88dSmrg LP_RAST_OP_END_QUERY, 1700af69d88dSmrg lp_rast_arg_query(pq))) { 1701af69d88dSmrg if (!lp_setup_flush_and_restart(setup)) 1702af69d88dSmrg goto fail; 1703af69d88dSmrg 1704af69d88dSmrg if (!lp_scene_bin_everywhere(setup->scene, 1705af69d88dSmrg LP_RAST_OP_END_QUERY, 1706af69d88dSmrg lp_rast_arg_query(pq))) { 1707af69d88dSmrg goto fail; 1708af69d88dSmrg } 1709af69d88dSmrg } 1710af69d88dSmrg setup->scene->had_queries |= TRUE; 17113464ebd5Sriastradh } 17123464ebd5Sriastradh } 17133464ebd5Sriastradh else { 17143464ebd5Sriastradh lp_fence_reference(&pq->fence, setup->last_fence); 17153464ebd5Sriastradh } 1716af69d88dSmrg 1717af69d88dSmrgfail: 1718af69d88dSmrg /* Need to do this now not earlier since it still needs to be marked as 1719af69d88dSmrg * active when binning it would cause a flush. 1720af69d88dSmrg */ 1721af69d88dSmrg if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || 1722af69d88dSmrg pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || 172301e04c3fSmrg pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || 17247ec681f3Smrg pq->type == PIPE_QUERY_PIPELINE_STATISTICS || 17257ec681f3Smrg pq->type == PIPE_QUERY_TIME_ELAPSED) { 1726af69d88dSmrg unsigned i; 1727af69d88dSmrg 1728af69d88dSmrg /* remove from active binned query list */ 1729af69d88dSmrg for (i = 0; i < setup->active_binned_queries; i++) { 1730af69d88dSmrg if (setup->active_queries[i] == pq) 1731af69d88dSmrg break; 1732af69d88dSmrg } 1733af69d88dSmrg assert(i < setup->active_binned_queries); 1734af69d88dSmrg if (i == setup->active_binned_queries) 1735af69d88dSmrg return; 1736af69d88dSmrg setup->active_binned_queries--; 1737af69d88dSmrg setup->active_queries[i] = setup->active_queries[setup->active_binned_queries]; 1738af69d88dSmrg setup->active_queries[setup->active_binned_queries] = NULL; 1739af69d88dSmrg } 17403464ebd5Sriastradh} 17413464ebd5Sriastradh 17423464ebd5Sriastradh 17433464ebd5Sriastradhboolean 17443464ebd5Sriastradhlp_setup_flush_and_restart(struct lp_setup_context *setup) 17453464ebd5Sriastradh{ 17463464ebd5Sriastradh if (0) debug_printf("%s\n", __FUNCTION__); 17473464ebd5Sriastradh 17483464ebd5Sriastradh assert(setup->state == SETUP_ACTIVE); 17493464ebd5Sriastradh 17503464ebd5Sriastradh if (!set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__)) 17513464ebd5Sriastradh return FALSE; 17523464ebd5Sriastradh 17533464ebd5Sriastradh if (!lp_setup_update_state(setup, TRUE)) 17543464ebd5Sriastradh return FALSE; 17553464ebd5Sriastradh 17563464ebd5Sriastradh return TRUE; 17573464ebd5Sriastradh} 17583464ebd5Sriastradh 17597ec681f3Smrgvoid 17607ec681f3Smrglp_setup_add_scissor_planes(const struct u_rect *scissor, 17617ec681f3Smrg struct lp_rast_plane *plane_s, 17627ec681f3Smrg boolean s_planes[4], bool multisample) 17637ec681f3Smrg{ 17647ec681f3Smrg /* 17657ec681f3Smrg * When rasterizing scissored tris, use the intersection of the 17667ec681f3Smrg * triangle bounding box and the scissor rect to generate the 17677ec681f3Smrg * scissor planes. 17687ec681f3Smrg * 17697ec681f3Smrg * This permits us to cut off the triangle "tails" that are present 17707ec681f3Smrg * in the intermediate recursive levels caused when two of the 17717ec681f3Smrg * triangles edges don't diverge quickly enough to trivially reject 17727ec681f3Smrg * exterior blocks from the triangle. 17737ec681f3Smrg * 17747ec681f3Smrg * It's not really clear if it's worth worrying about these tails, 17757ec681f3Smrg * but since we generate the planes for each scissored tri, it's 17767ec681f3Smrg * free to trim them in this case. 17777ec681f3Smrg * 17787ec681f3Smrg * Note that otherwise, the scissor planes only vary in 'C' value, 17797ec681f3Smrg * and even then only on state-changes. Could alternatively store 17807ec681f3Smrg * these planes elsewhere. 17817ec681f3Smrg * (Or only store the c value together with a bit indicating which 17827ec681f3Smrg * scissor edge this is, so rasterization would treat them differently 17837ec681f3Smrg * (easier to evaluate) to ordinary planes.) 17847ec681f3Smrg */ 17857ec681f3Smrg int adj = multisample ? 127 : 0; 17867ec681f3Smrg if (s_planes[0]) { 17877ec681f3Smrg int x0 = scissor->x0 - 1; 17887ec681f3Smrg plane_s->dcdx = ~0U << 8; 17897ec681f3Smrg plane_s->dcdy = 0; 17907ec681f3Smrg plane_s->c = x0 << 8; 17917ec681f3Smrg plane_s->c += adj; 17927ec681f3Smrg plane_s->c = -plane_s->c; /* flip sign */ 17937ec681f3Smrg plane_s->eo = 1 << 8; 17947ec681f3Smrg plane_s++; 17957ec681f3Smrg } 17967ec681f3Smrg if (s_planes[1]) { 17977ec681f3Smrg int x1 = scissor->x1; 17987ec681f3Smrg plane_s->dcdx = 1 << 8; 17997ec681f3Smrg plane_s->dcdy = 0; 18007ec681f3Smrg plane_s->c = x1 << 8; 18017ec681f3Smrg plane_s->c += 127 + adj; 18027ec681f3Smrg plane_s->eo = 0 << 8; 18037ec681f3Smrg plane_s++; 18047ec681f3Smrg } 18057ec681f3Smrg if (s_planes[2]) { 18067ec681f3Smrg int y0 = scissor->y0 - 1; 18077ec681f3Smrg plane_s->dcdx = 0; 18087ec681f3Smrg plane_s->dcdy = 1 << 8; 18097ec681f3Smrg plane_s->c = y0 << 8; 18107ec681f3Smrg plane_s->c += adj; 18117ec681f3Smrg plane_s->c = -plane_s->c; /* flip sign */ 18127ec681f3Smrg plane_s->eo = 1 << 8; 18137ec681f3Smrg plane_s++; 18147ec681f3Smrg } 18157ec681f3Smrg if (s_planes[3]) { 18167ec681f3Smrg int y1 = scissor->y1; 18177ec681f3Smrg plane_s->dcdx = 0; 18187ec681f3Smrg plane_s->dcdy = ~0U << 8; 18197ec681f3Smrg plane_s->c = y1 << 8; 18207ec681f3Smrg plane_s->c += 127 + adj; 18217ec681f3Smrg plane_s->eo = 0; 18227ec681f3Smrg plane_s++; 18237ec681f3Smrg } 18247ec681f3Smrg} 1825