1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/** 29bf215546Sopenharmony_ci * Tiling engine. 30bf215546Sopenharmony_ci * 31bf215546Sopenharmony_ci * Builds per-tile display lists and executes them on calls to 32bf215546Sopenharmony_ci * lp_setup_flush(). 33bf215546Sopenharmony_ci */ 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include <limits.h> 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#include "pipe/p_defines.h" 38bf215546Sopenharmony_ci#include "util/u_framebuffer.h" 39bf215546Sopenharmony_ci#include "util/u_inlines.h" 40bf215546Sopenharmony_ci#include "util/u_memory.h" 41bf215546Sopenharmony_ci#include "util/u_pack_color.h" 42bf215546Sopenharmony_ci#include "util/u_cpu_detect.h" 43bf215546Sopenharmony_ci#include "util/u_viewport.h" 44bf215546Sopenharmony_ci#include "draw/draw_pipe.h" 45bf215546Sopenharmony_ci#include "util/os_time.h" 46bf215546Sopenharmony_ci#include "lp_context.h" 47bf215546Sopenharmony_ci#include "lp_memory.h" 48bf215546Sopenharmony_ci#include "lp_scene.h" 49bf215546Sopenharmony_ci#include "lp_texture.h" 50bf215546Sopenharmony_ci#include "lp_debug.h" 51bf215546Sopenharmony_ci#include "lp_fence.h" 52bf215546Sopenharmony_ci#include "lp_query.h" 53bf215546Sopenharmony_ci#include "lp_rast.h" 54bf215546Sopenharmony_ci#include "lp_setup_context.h" 55bf215546Sopenharmony_ci#include "lp_screen.h" 56bf215546Sopenharmony_ci#include "lp_state.h" 57bf215546Sopenharmony_ci#include "lp_jit.h" 58bf215546Sopenharmony_ci#include "frontend/sw_winsys.h" 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci#include "draw/draw_context.h" 61bf215546Sopenharmony_ci#include "draw/draw_vbuf.h" 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_cistatic boolean set_scene_state(struct lp_setup_context *, enum setup_state, 65bf215546Sopenharmony_ci const char *reason); 66bf215546Sopenharmony_cistatic boolean try_update_scene_state(struct lp_setup_context *setup); 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic unsigned 70bf215546Sopenharmony_cilp_setup_wait_empty_scene(struct lp_setup_context *setup) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci /* just use the first scene if we run out */ 73bf215546Sopenharmony_ci if (setup->scenes[0]->fence) { 74bf215546Sopenharmony_ci debug_printf("%s: wait for scene %d\n", 75bf215546Sopenharmony_ci __FUNCTION__, setup->scenes[0]->fence->id); 76bf215546Sopenharmony_ci lp_fence_wait(setup->scenes[0]->fence); 77bf215546Sopenharmony_ci lp_scene_end_rasterization(setup->scenes[0]); 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci return 0; 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_cistatic void 84bf215546Sopenharmony_cilp_setup_get_empty_scene(struct lp_setup_context *setup) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci assert(setup->scene == NULL); 87bf215546Sopenharmony_ci unsigned i; 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci /* try and find a scene that isn't being used */ 90bf215546Sopenharmony_ci for (i = 0; i < setup->num_active_scenes; i++) { 91bf215546Sopenharmony_ci if (setup->scenes[i]->fence) { 92bf215546Sopenharmony_ci if (lp_fence_signalled(setup->scenes[i]->fence)) { 93bf215546Sopenharmony_ci lp_scene_end_rasterization(setup->scenes[i]); 94bf215546Sopenharmony_ci break; 95bf215546Sopenharmony_ci } 96bf215546Sopenharmony_ci } else { 97bf215546Sopenharmony_ci break; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci if (setup->num_active_scenes + 1 > MAX_SCENES) { 102bf215546Sopenharmony_ci i = lp_setup_wait_empty_scene(setup); 103bf215546Sopenharmony_ci } else if (i == setup->num_active_scenes) { 104bf215546Sopenharmony_ci /* allocate a new scene */ 105bf215546Sopenharmony_ci struct lp_scene *scene = lp_scene_create(setup); 106bf215546Sopenharmony_ci if (!scene) { 107bf215546Sopenharmony_ci /* block and reuse scenes */ 108bf215546Sopenharmony_ci i = lp_setup_wait_empty_scene(setup); 109bf215546Sopenharmony_ci } else { 110bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "allocated scene: %d\n", setup->num_active_scenes); 111bf215546Sopenharmony_ci setup->scenes[setup->num_active_scenes] = scene; 112bf215546Sopenharmony_ci i = setup->num_active_scenes; 113bf215546Sopenharmony_ci setup->num_active_scenes++; 114bf215546Sopenharmony_ci } 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci setup->scene = setup->scenes[i]; 118bf215546Sopenharmony_ci setup->scene->permit_linear_rasterizer = setup->permit_linear_rasterizer; 119bf215546Sopenharmony_ci lp_scene_begin_binning(setup->scene, &setup->fb); 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic void 124bf215546Sopenharmony_cifirst_triangle(struct lp_setup_context *setup, 125bf215546Sopenharmony_ci const float (*v0)[4], 126bf215546Sopenharmony_ci const float (*v1)[4], 127bf215546Sopenharmony_ci const float (*v2)[4]) 128bf215546Sopenharmony_ci{ 129bf215546Sopenharmony_ci assert(setup->state == SETUP_ACTIVE); 130bf215546Sopenharmony_ci lp_setup_choose_triangle(setup); 131bf215546Sopenharmony_ci setup->triangle(setup, v0, v1, v2); 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_cistatic boolean 136bf215546Sopenharmony_cifirst_rectangle(struct lp_setup_context *setup, 137bf215546Sopenharmony_ci const float (*v0)[4], 138bf215546Sopenharmony_ci const float (*v1)[4], 139bf215546Sopenharmony_ci const float (*v2)[4], 140bf215546Sopenharmony_ci const float (*v3)[4], 141bf215546Sopenharmony_ci const float (*v4)[4], 142bf215546Sopenharmony_ci const float (*v5)[4]) 143bf215546Sopenharmony_ci{ 144bf215546Sopenharmony_ci assert(setup->state == SETUP_ACTIVE); 145bf215546Sopenharmony_ci lp_setup_choose_rect(setup); 146bf215546Sopenharmony_ci return setup->rect(setup, v0, v1, v2, v3, v4, v5); 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_cistatic void 151bf215546Sopenharmony_cifirst_line(struct lp_setup_context *setup, 152bf215546Sopenharmony_ci const float (*v0)[4], 153bf215546Sopenharmony_ci const float (*v1)[4]) 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci assert(setup->state == SETUP_ACTIVE); 156bf215546Sopenharmony_ci lp_setup_choose_line(setup); 157bf215546Sopenharmony_ci setup->line(setup, v0, v1); 158bf215546Sopenharmony_ci} 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_cistatic void 162bf215546Sopenharmony_cifirst_point(struct lp_setup_context *setup, 163bf215546Sopenharmony_ci const float (*v0)[4]) 164bf215546Sopenharmony_ci{ 165bf215546Sopenharmony_ci assert(setup->state == SETUP_ACTIVE); 166bf215546Sopenharmony_ci lp_setup_choose_point(setup); 167bf215546Sopenharmony_ci setup->point(setup, v0); 168bf215546Sopenharmony_ci} 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_civoid 172bf215546Sopenharmony_cilp_setup_reset(struct lp_setup_context *setup) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci /* Reset derived state */ 177bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->constants); ++i) { 178bf215546Sopenharmony_ci setup->constants[i].stored_size = 0; 179bf215546Sopenharmony_ci setup->constants[i].stored_data = NULL; 180bf215546Sopenharmony_ci } 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci setup->fs.stored = NULL; 183bf215546Sopenharmony_ci setup->dirty = ~0; 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci /* no current bin */ 186bf215546Sopenharmony_ci setup->scene = NULL; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci /* Reset some state: 189bf215546Sopenharmony_ci */ 190bf215546Sopenharmony_ci memset(&setup->clear, 0, sizeof(setup->clear)); 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci /* Have an explicit "start-binning" call and get rid of this 193bf215546Sopenharmony_ci * pointer twiddling? 194bf215546Sopenharmony_ci */ 195bf215546Sopenharmony_ci setup->line = first_line; 196bf215546Sopenharmony_ci setup->point = first_point; 197bf215546Sopenharmony_ci setup->triangle = first_triangle; 198bf215546Sopenharmony_ci setup->rect = first_rectangle; 199bf215546Sopenharmony_ci} 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci/** Rasterize all scene's bins */ 203bf215546Sopenharmony_cistatic void 204bf215546Sopenharmony_cilp_setup_rasterize_scene(struct lp_setup_context *setup) 205bf215546Sopenharmony_ci{ 206bf215546Sopenharmony_ci struct lp_scene *scene = setup->scene; 207bf215546Sopenharmony_ci struct llvmpipe_screen *screen = llvmpipe_screen(scene->pipe->screen); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci scene->num_active_queries = setup->active_binned_queries; 210bf215546Sopenharmony_ci memcpy(scene->active_queries, setup->active_queries, 211bf215546Sopenharmony_ci scene->num_active_queries * sizeof(scene->active_queries[0])); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci lp_scene_end_binning(scene); 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci mtx_lock(&screen->rast_mutex); 216bf215546Sopenharmony_ci lp_rast_queue_scene(screen->rast, scene); 217bf215546Sopenharmony_ci mtx_unlock(&screen->rast_mutex); 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci lp_setup_reset(setup); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_cistatic boolean 226bf215546Sopenharmony_cibegin_binning(struct lp_setup_context *setup) 227bf215546Sopenharmony_ci{ 228bf215546Sopenharmony_ci struct lp_scene *scene = setup->scene; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci assert(scene); 231bf215546Sopenharmony_ci assert(scene->fence == NULL); 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci /* Always create a fence: 234bf215546Sopenharmony_ci */ 235bf215546Sopenharmony_ci scene->fence = lp_fence_create(MAX2(1, setup->num_threads)); 236bf215546Sopenharmony_ci if (!scene->fence) 237bf215546Sopenharmony_ci return FALSE; 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci if (!try_update_scene_state(setup)) { 240bf215546Sopenharmony_ci return FALSE; 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci boolean need_zsload = FALSE; 244bf215546Sopenharmony_ci if (setup->fb.zsbuf && 245bf215546Sopenharmony_ci ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && 246bf215546Sopenharmony_ci util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) { 247bf215546Sopenharmony_ci need_zsload = TRUE; 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s color clear bufs: %x depth: %s\n", __FUNCTION__, 251bf215546Sopenharmony_ci setup->clear.flags >> 2, 252bf215546Sopenharmony_ci need_zsload ? "clear": "load"); 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci if (setup->clear.flags & PIPE_CLEAR_COLOR) { 255bf215546Sopenharmony_ci for (unsigned cbuf = 0; cbuf < setup->fb.nr_cbufs; cbuf++) { 256bf215546Sopenharmony_ci assert(PIPE_CLEAR_COLOR0 == 1 << 2); 257bf215546Sopenharmony_ci if (setup->clear.flags & (1 << (2 + cbuf))) { 258bf215546Sopenharmony_ci union lp_rast_cmd_arg clearrb_arg; 259bf215546Sopenharmony_ci struct lp_rast_clear_rb *cc_scene = 260bf215546Sopenharmony_ci (struct lp_rast_clear_rb *) 261bf215546Sopenharmony_ci lp_scene_alloc(scene, sizeof(struct lp_rast_clear_rb)); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci if (!cc_scene) { 264bf215546Sopenharmony_ci return FALSE; 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci cc_scene->cbuf = cbuf; 268bf215546Sopenharmony_ci cc_scene->color_val = setup->clear.color_val[cbuf]; 269bf215546Sopenharmony_ci clearrb_arg.clear_rb = cc_scene; 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci if (!lp_scene_bin_everywhere(scene, 272bf215546Sopenharmony_ci LP_RAST_OP_CLEAR_COLOR, 273bf215546Sopenharmony_ci clearrb_arg)) { 274bf215546Sopenharmony_ci return FALSE; 275bf215546Sopenharmony_ci } 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci if (setup->fb.zsbuf) { 281bf215546Sopenharmony_ci if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { 282bf215546Sopenharmony_ci if (!lp_scene_bin_everywhere(scene, 283bf215546Sopenharmony_ci LP_RAST_OP_CLEAR_ZSTENCIL, 284bf215546Sopenharmony_ci lp_rast_arg_clearzs( 285bf215546Sopenharmony_ci setup->clear.zsvalue, 286bf215546Sopenharmony_ci setup->clear.zsmask))) { 287bf215546Sopenharmony_ci return FALSE; 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci setup->clear.flags = 0; 293bf215546Sopenharmony_ci setup->clear.zsmask = 0; 294bf215546Sopenharmony_ci setup->clear.zsvalue = 0; 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci scene->had_queries = !!setup->active_binned_queries; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); 299bf215546Sopenharmony_ci return TRUE; 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci/* This basically bins and then flushes any outstanding full-screen 304bf215546Sopenharmony_ci * clears. 305bf215546Sopenharmony_ci * 306bf215546Sopenharmony_ci * TODO: fast path for fullscreen clears and no triangles. 307bf215546Sopenharmony_ci */ 308bf215546Sopenharmony_cistatic boolean 309bf215546Sopenharmony_ciexecute_clears(struct lp_setup_context *setup) 310bf215546Sopenharmony_ci{ 311bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci return begin_binning(setup); 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_cistatic const char *states[] = { 318bf215546Sopenharmony_ci "FLUSHED", 319bf215546Sopenharmony_ci "CLEARED", 320bf215546Sopenharmony_ci "ACTIVE " 321bf215546Sopenharmony_ci}; 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_cistatic boolean 325bf215546Sopenharmony_ciset_scene_state(struct lp_setup_context *setup, 326bf215546Sopenharmony_ci enum setup_state new_state, 327bf215546Sopenharmony_ci const char *reason) 328bf215546Sopenharmony_ci{ 329bf215546Sopenharmony_ci const unsigned old_state = setup->state; 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci if (old_state == new_state) 332bf215546Sopenharmony_ci return TRUE; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci if (LP_DEBUG & DEBUG_SCENE) { 335bf215546Sopenharmony_ci debug_printf("%s old %s new %s%s%s\n", 336bf215546Sopenharmony_ci __FUNCTION__, 337bf215546Sopenharmony_ci states[old_state], 338bf215546Sopenharmony_ci states[new_state], 339bf215546Sopenharmony_ci (new_state == SETUP_FLUSHED) ? ": " : "", 340bf215546Sopenharmony_ci (new_state == SETUP_FLUSHED) ? reason : ""); 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci if (new_state == SETUP_FLUSHED && setup->scene) 343bf215546Sopenharmony_ci lp_debug_draw_bins_by_cmd_length(setup->scene); 344bf215546Sopenharmony_ci } 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci /* wait for a free/empty scene 347bf215546Sopenharmony_ci */ 348bf215546Sopenharmony_ci if (old_state == SETUP_FLUSHED) 349bf215546Sopenharmony_ci lp_setup_get_empty_scene(setup); 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci switch (new_state) { 352bf215546Sopenharmony_ci case SETUP_CLEARED: 353bf215546Sopenharmony_ci break; 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci case SETUP_ACTIVE: 356bf215546Sopenharmony_ci if (!begin_binning(setup)) 357bf215546Sopenharmony_ci goto fail; 358bf215546Sopenharmony_ci break; 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci case SETUP_FLUSHED: 361bf215546Sopenharmony_ci if (old_state == SETUP_CLEARED) 362bf215546Sopenharmony_ci if (!execute_clears(setup)) 363bf215546Sopenharmony_ci goto fail; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci lp_setup_rasterize_scene(setup); 366bf215546Sopenharmony_ci assert(setup->scene == NULL); 367bf215546Sopenharmony_ci break; 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci default: 370bf215546Sopenharmony_ci assert(0 && "invalid setup state mode"); 371bf215546Sopenharmony_ci goto fail; 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci setup->state = new_state; 375bf215546Sopenharmony_ci return TRUE; 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_cifail: 378bf215546Sopenharmony_ci if (setup->scene) { 379bf215546Sopenharmony_ci lp_scene_end_rasterization(setup->scene); 380bf215546Sopenharmony_ci setup->scene = NULL; 381bf215546Sopenharmony_ci } 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci setup->state = SETUP_FLUSHED; 384bf215546Sopenharmony_ci lp_setup_reset(setup); 385bf215546Sopenharmony_ci return FALSE; 386bf215546Sopenharmony_ci} 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_civoid 390bf215546Sopenharmony_cilp_setup_flush(struct lp_setup_context *setup, 391bf215546Sopenharmony_ci const char *reason) 392bf215546Sopenharmony_ci{ 393bf215546Sopenharmony_ci set_scene_state(setup, SETUP_FLUSHED, reason); 394bf215546Sopenharmony_ci} 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_civoid 398bf215546Sopenharmony_cilp_setup_bind_framebuffer(struct lp_setup_context *setup, 399bf215546Sopenharmony_ci const struct pipe_framebuffer_state *fb) 400bf215546Sopenharmony_ci{ 401bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci /* Flush any old scene. 404bf215546Sopenharmony_ci */ 405bf215546Sopenharmony_ci set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__); 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci /* 408bf215546Sopenharmony_ci * Ensure the old scene is not reused. 409bf215546Sopenharmony_ci */ 410bf215546Sopenharmony_ci assert(!setup->scene); 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci /* Set new state. This will be picked up later when we next need a 413bf215546Sopenharmony_ci * scene. 414bf215546Sopenharmony_ci */ 415bf215546Sopenharmony_ci util_copy_framebuffer_state(&setup->fb, fb); 416bf215546Sopenharmony_ci setup->framebuffer.x0 = 0; 417bf215546Sopenharmony_ci setup->framebuffer.y0 = 0; 418bf215546Sopenharmony_ci setup->framebuffer.x1 = fb->width-1; 419bf215546Sopenharmony_ci setup->framebuffer.y1 = fb->height-1; 420bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_SCISSOR; 421bf215546Sopenharmony_ci} 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci/* 425bf215546Sopenharmony_ci * Try to clear one color buffer of the attached fb, either by binning a clear 426bf215546Sopenharmony_ci * command or queuing up the clear for later (when binning is started). 427bf215546Sopenharmony_ci */ 428bf215546Sopenharmony_cistatic boolean 429bf215546Sopenharmony_cilp_setup_try_clear_color_buffer(struct lp_setup_context *setup, 430bf215546Sopenharmony_ci const union pipe_color_union *color, 431bf215546Sopenharmony_ci unsigned cbuf) 432bf215546Sopenharmony_ci{ 433bf215546Sopenharmony_ci union lp_rast_cmd_arg clearrb_arg; 434bf215546Sopenharmony_ci union util_color uc; 435bf215546Sopenharmony_ci const enum pipe_format format = setup->fb.cbufs[cbuf]->format; 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci util_pack_color_union(format, &uc, color); 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci if (setup->state == SETUP_ACTIVE) { 442bf215546Sopenharmony_ci struct lp_scene *scene = setup->scene; 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci /* Add the clear to existing scene. In the unusual case where 445bf215546Sopenharmony_ci * both color and depth-stencil are being cleared when there's 446bf215546Sopenharmony_ci * already been some rendering, we could discard the currently 447bf215546Sopenharmony_ci * binned scene and start again, but I don't see that as being 448bf215546Sopenharmony_ci * a common usage. 449bf215546Sopenharmony_ci */ 450bf215546Sopenharmony_ci struct lp_rast_clear_rb *cc_scene = 451bf215546Sopenharmony_ci (struct lp_rast_clear_rb *) 452bf215546Sopenharmony_ci lp_scene_alloc_aligned(scene, sizeof(struct lp_rast_clear_rb), 8); 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci if (!cc_scene) { 455bf215546Sopenharmony_ci return FALSE; 456bf215546Sopenharmony_ci } 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci cc_scene->cbuf = cbuf; 459bf215546Sopenharmony_ci cc_scene->color_val = uc; 460bf215546Sopenharmony_ci clearrb_arg.clear_rb = cc_scene; 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci if (!lp_scene_bin_everywhere(scene, 463bf215546Sopenharmony_ci LP_RAST_OP_CLEAR_COLOR, 464bf215546Sopenharmony_ci clearrb_arg)) { 465bf215546Sopenharmony_ci return FALSE; 466bf215546Sopenharmony_ci } 467bf215546Sopenharmony_ci } 468bf215546Sopenharmony_ci else { 469bf215546Sopenharmony_ci /* Put ourselves into the 'pre-clear' state, specifically to try 470bf215546Sopenharmony_ci * and accumulate multiple clears to color and depth_stencil 471bf215546Sopenharmony_ci * buffers which the app or gallium frontend might issue 472bf215546Sopenharmony_ci * separately. 473bf215546Sopenharmony_ci */ 474bf215546Sopenharmony_ci set_scene_state(setup, SETUP_CLEARED, __FUNCTION__); 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci assert(PIPE_CLEAR_COLOR0 == (1 << 2)); 477bf215546Sopenharmony_ci setup->clear.flags |= 1 << (cbuf + 2); 478bf215546Sopenharmony_ci setup->clear.color_val[cbuf] = uc; 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci return TRUE; 482bf215546Sopenharmony_ci} 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_cistatic boolean 486bf215546Sopenharmony_cilp_setup_try_clear_zs(struct lp_setup_context *setup, 487bf215546Sopenharmony_ci double depth, 488bf215546Sopenharmony_ci unsigned stencil, 489bf215546Sopenharmony_ci unsigned flags) 490bf215546Sopenharmony_ci{ 491bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci enum pipe_format format = setup->fb.zsbuf->format; 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci const uint32_t zmask32 = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; 496bf215546Sopenharmony_ci const uint8_t smask8 = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci uint64_t zsvalue = util_pack64_z_stencil(format, depth, stencil); 499bf215546Sopenharmony_ci uint64_t zsmask = util_pack64_mask_z_stencil(format, zmask32, smask8); 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci zsvalue &= zsmask; 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci if (format == PIPE_FORMAT_Z24X8_UNORM || 504bf215546Sopenharmony_ci format == PIPE_FORMAT_X8Z24_UNORM) { 505bf215546Sopenharmony_ci /* 506bf215546Sopenharmony_ci * Make full mask if there's "X" bits so we can do full 507bf215546Sopenharmony_ci * clear (without rmw). 508bf215546Sopenharmony_ci */ 509bf215546Sopenharmony_ci uint32_t zsmask_full = util_pack_mask_z_stencil(format, ~0, ~0); 510bf215546Sopenharmony_ci zsmask |= ~zsmask_full; 511bf215546Sopenharmony_ci } 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci if (setup->state == SETUP_ACTIVE) { 514bf215546Sopenharmony_ci struct lp_scene *scene = setup->scene; 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci /* Add the clear to existing scene. In the unusual case where 517bf215546Sopenharmony_ci * both color and depth-stencil are being cleared when there's 518bf215546Sopenharmony_ci * already been some rendering, we could discard the currently 519bf215546Sopenharmony_ci * binned scene and start again, but I don't see that as being 520bf215546Sopenharmony_ci * a common usage. 521bf215546Sopenharmony_ci */ 522bf215546Sopenharmony_ci if (!lp_scene_bin_everywhere(scene, 523bf215546Sopenharmony_ci LP_RAST_OP_CLEAR_ZSTENCIL, 524bf215546Sopenharmony_ci lp_rast_arg_clearzs(zsvalue, zsmask))) 525bf215546Sopenharmony_ci return FALSE; 526bf215546Sopenharmony_ci } 527bf215546Sopenharmony_ci else { 528bf215546Sopenharmony_ci /* Put ourselves into the 'pre-clear' state, specifically to try 529bf215546Sopenharmony_ci * and accumulate multiple clears to color and depth_stencil 530bf215546Sopenharmony_ci * buffers which the app or gallium frontend might issue 531bf215546Sopenharmony_ci * separately. 532bf215546Sopenharmony_ci */ 533bf215546Sopenharmony_ci set_scene_state(setup, SETUP_CLEARED, __FUNCTION__); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci setup->clear.flags |= flags; 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci setup->clear.zsmask |= zsmask; 538bf215546Sopenharmony_ci setup->clear.zsvalue = 539bf215546Sopenharmony_ci (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci return TRUE; 543bf215546Sopenharmony_ci} 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_civoid 547bf215546Sopenharmony_cilp_setup_clear(struct lp_setup_context *setup, 548bf215546Sopenharmony_ci const union pipe_color_union *color, 549bf215546Sopenharmony_ci double depth, 550bf215546Sopenharmony_ci unsigned stencil, 551bf215546Sopenharmony_ci unsigned flags) 552bf215546Sopenharmony_ci{ 553bf215546Sopenharmony_ci /* 554bf215546Sopenharmony_ci * Note any of these (max 9) clears could fail (but at most there should 555bf215546Sopenharmony_ci * be just one failure!). This avoids doing the previous succeeded 556bf215546Sopenharmony_ci * clears again (we still clear tiles twice if a clear command succeeded 557bf215546Sopenharmony_ci * partially for one buffer). 558bf215546Sopenharmony_ci */ 559bf215546Sopenharmony_ci if (flags & PIPE_CLEAR_DEPTHSTENCIL) { 560bf215546Sopenharmony_ci unsigned flagszs = flags & PIPE_CLEAR_DEPTHSTENCIL; 561bf215546Sopenharmony_ci if (!lp_setup_try_clear_zs(setup, depth, stencil, flagszs)) { 562bf215546Sopenharmony_ci set_scene_state( setup, SETUP_FLUSHED, __FUNCTION__ ); 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci if (!lp_setup_try_clear_zs(setup, depth, stencil, flagszs)) 565bf215546Sopenharmony_ci assert(0); 566bf215546Sopenharmony_ci } 567bf215546Sopenharmony_ci } 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ci if (flags & PIPE_CLEAR_COLOR) { 570bf215546Sopenharmony_ci assert(PIPE_CLEAR_COLOR0 == (1 << 2)); 571bf215546Sopenharmony_ci for (unsigned i = 0; i < setup->fb.nr_cbufs; i++) { 572bf215546Sopenharmony_ci if ((flags & (1 << (2 + i))) && setup->fb.cbufs[i]) { 573bf215546Sopenharmony_ci if (!lp_setup_try_clear_color_buffer(setup, color, i)) { 574bf215546Sopenharmony_ci set_scene_state( setup, SETUP_FLUSHED, __FUNCTION__ ); 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci if (!lp_setup_try_clear_color_buffer(setup, color, i)) 577bf215546Sopenharmony_ci assert(0); 578bf215546Sopenharmony_ci } 579bf215546Sopenharmony_ci } 580bf215546Sopenharmony_ci } 581bf215546Sopenharmony_ci } 582bf215546Sopenharmony_ci} 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_civoid 586bf215546Sopenharmony_cilp_setup_bind_rasterizer( struct lp_setup_context *setup, 587bf215546Sopenharmony_ci const struct pipe_rasterizer_state *rast) 588bf215546Sopenharmony_ci{ 589bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci setup->ccw_is_frontface = rast->front_ccw; 592bf215546Sopenharmony_ci setup->cullmode = rast->cull_face; 593bf215546Sopenharmony_ci setup->triangle = first_triangle; 594bf215546Sopenharmony_ci setup->rect = first_rectangle; 595bf215546Sopenharmony_ci setup->multisample = rast->multisample; 596bf215546Sopenharmony_ci setup->pixel_offset = rast->half_pixel_center ? 0.5f : 0.0f; 597bf215546Sopenharmony_ci setup->bottom_edge_rule = rast->bottom_edge_rule; 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci if (setup->scissor_test != rast->scissor) { 600bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_SCISSOR; 601bf215546Sopenharmony_ci setup->scissor_test = rast->scissor; 602bf215546Sopenharmony_ci } 603bf215546Sopenharmony_ci 604bf215546Sopenharmony_ci setup->flatshade_first = rast->flatshade_first; 605bf215546Sopenharmony_ci setup->line_width = rast->line_width; 606bf215546Sopenharmony_ci setup->rectangular_lines = rast->line_rectangular; 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci setup->point_size = rast->point_size; 609bf215546Sopenharmony_ci setup->sprite_coord_enable = rast->sprite_coord_enable; 610bf215546Sopenharmony_ci setup->sprite_coord_origin = rast->sprite_coord_mode; 611bf215546Sopenharmony_ci setup->point_tri_clip = rast->point_size_per_vertex; 612bf215546Sopenharmony_ci setup->point_size_per_vertex = rast->point_size_per_vertex; 613bf215546Sopenharmony_ci setup->legacy_points = !rast->point_quad_rasterization && !setup->multisample; 614bf215546Sopenharmony_ci} 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_civoid 618bf215546Sopenharmony_cilp_setup_set_setup_variant(struct lp_setup_context *setup, 619bf215546Sopenharmony_ci const struct lp_setup_variant *variant) 620bf215546Sopenharmony_ci{ 621bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 622bf215546Sopenharmony_ci 623bf215546Sopenharmony_ci setup->setup.variant = variant; 624bf215546Sopenharmony_ci} 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_civoid 628bf215546Sopenharmony_cilp_setup_set_fs_variant(struct lp_setup_context *setup, 629bf215546Sopenharmony_ci struct lp_fragment_shader_variant *variant) 630bf215546Sopenharmony_ci{ 631bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, variant); 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ci setup->fs.current.variant = variant; 634bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 635bf215546Sopenharmony_ci} 636bf215546Sopenharmony_ci 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_civoid 639bf215546Sopenharmony_cilp_setup_set_fs_constants(struct lp_setup_context *setup, 640bf215546Sopenharmony_ci unsigned num, 641bf215546Sopenharmony_ci struct pipe_constant_buffer *buffers) 642bf215546Sopenharmony_ci{ 643bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers); 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_ci assert(num <= ARRAY_SIZE(setup->constants)); 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_ci unsigned i; 648bf215546Sopenharmony_ci for (i = 0; i < num; ++i) { 649bf215546Sopenharmony_ci util_copy_constant_buffer(&setup->constants[i].current, 650bf215546Sopenharmony_ci &buffers[i], false); 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci for (; i < ARRAY_SIZE(setup->constants); i++) { 653bf215546Sopenharmony_ci util_copy_constant_buffer(&setup->constants[i].current, NULL, false); 654bf215546Sopenharmony_ci } 655bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_CONSTANTS; 656bf215546Sopenharmony_ci} 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_civoid 660bf215546Sopenharmony_cilp_setup_set_fs_ssbos(struct lp_setup_context *setup, 661bf215546Sopenharmony_ci unsigned num, 662bf215546Sopenharmony_ci struct pipe_shader_buffer *buffers, 663bf215546Sopenharmony_ci uint32_t ssbo_write_mask) 664bf215546Sopenharmony_ci{ 665bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers); 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci assert(num <= ARRAY_SIZE(setup->ssbos)); 668bf215546Sopenharmony_ci 669bf215546Sopenharmony_ci unsigned i; 670bf215546Sopenharmony_ci for (i = 0; i < num; ++i) { 671bf215546Sopenharmony_ci util_copy_shader_buffer(&setup->ssbos[i].current, &buffers[i]); 672bf215546Sopenharmony_ci } 673bf215546Sopenharmony_ci for (; i < ARRAY_SIZE(setup->ssbos); i++) { 674bf215546Sopenharmony_ci util_copy_shader_buffer(&setup->ssbos[i].current, NULL); 675bf215546Sopenharmony_ci } 676bf215546Sopenharmony_ci setup->ssbo_write_mask = ssbo_write_mask; 677bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_SSBOS; 678bf215546Sopenharmony_ci} 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_civoid 682bf215546Sopenharmony_cilp_setup_set_fs_images(struct lp_setup_context *setup, 683bf215546Sopenharmony_ci unsigned num, 684bf215546Sopenharmony_ci struct pipe_image_view *images) 685bf215546Sopenharmony_ci{ 686bf215546Sopenharmony_ci unsigned i; 687bf215546Sopenharmony_ci 688bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) images); 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ci assert(num <= ARRAY_SIZE(setup->images)); 691bf215546Sopenharmony_ci 692bf215546Sopenharmony_ci for (i = 0; i < num; ++i) { 693bf215546Sopenharmony_ci const struct pipe_image_view *image = &images[i]; 694bf215546Sopenharmony_ci util_copy_image_view(&setup->images[i].current, &images[i]); 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci struct pipe_resource *res = image->resource; 697bf215546Sopenharmony_ci struct llvmpipe_resource *lp_res = llvmpipe_resource(res); 698bf215546Sopenharmony_ci struct lp_jit_image *jit_image = &setup->fs.current.jit_context.images[i]; 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci if (!lp_res) 701bf215546Sopenharmony_ci continue; 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci if (!lp_res->dt) { 704bf215546Sopenharmony_ci /* regular texture - setup array of mipmap level offsets */ 705bf215546Sopenharmony_ci if (llvmpipe_resource_is_texture(res)) { 706bf215546Sopenharmony_ci jit_image->base = lp_res->tex_data; 707bf215546Sopenharmony_ci } else { 708bf215546Sopenharmony_ci jit_image->base = lp_res->data; 709bf215546Sopenharmony_ci } 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci jit_image->width = res->width0; 712bf215546Sopenharmony_ci jit_image->height = res->height0; 713bf215546Sopenharmony_ci jit_image->depth = res->depth0; 714bf215546Sopenharmony_ci jit_image->num_samples = res->nr_samples; 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci if (llvmpipe_resource_is_texture(res)) { 717bf215546Sopenharmony_ci uint32_t mip_offset = lp_res->mip_offsets[image->u.tex.level]; 718bf215546Sopenharmony_ci const uint32_t bw = util_format_get_blockwidth(image->resource->format); 719bf215546Sopenharmony_ci const uint32_t bh = util_format_get_blockheight(image->resource->format); 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci jit_image->width = DIV_ROUND_UP(jit_image->width, bw); 722bf215546Sopenharmony_ci jit_image->height = DIV_ROUND_UP(jit_image->height, bh); 723bf215546Sopenharmony_ci jit_image->width = u_minify(jit_image->width, image->u.tex.level); 724bf215546Sopenharmony_ci jit_image->height = u_minify(jit_image->height, image->u.tex.level); 725bf215546Sopenharmony_ci 726bf215546Sopenharmony_ci if (res->target == PIPE_TEXTURE_1D_ARRAY || 727bf215546Sopenharmony_ci res->target == PIPE_TEXTURE_2D_ARRAY || 728bf215546Sopenharmony_ci res->target == PIPE_TEXTURE_3D || 729bf215546Sopenharmony_ci res->target == PIPE_TEXTURE_CUBE || 730bf215546Sopenharmony_ci res->target == PIPE_TEXTURE_CUBE_ARRAY) { 731bf215546Sopenharmony_ci /* 732bf215546Sopenharmony_ci * For array textures, we don't have first_layer, instead 733bf215546Sopenharmony_ci * adjust last_layer (stored as depth) plus the mip level offsets 734bf215546Sopenharmony_ci * (as we have mip-first layout can't just adjust base ptr). 735bf215546Sopenharmony_ci * XXX For mip levels, could do something similar. 736bf215546Sopenharmony_ci */ 737bf215546Sopenharmony_ci jit_image->depth = image->u.tex.last_layer - image->u.tex.first_layer + 1; 738bf215546Sopenharmony_ci mip_offset += image->u.tex.first_layer * lp_res->img_stride[image->u.tex.level]; 739bf215546Sopenharmony_ci } else 740bf215546Sopenharmony_ci jit_image->depth = u_minify(jit_image->depth, image->u.tex.level); 741bf215546Sopenharmony_ci 742bf215546Sopenharmony_ci jit_image->row_stride = lp_res->row_stride[image->u.tex.level]; 743bf215546Sopenharmony_ci jit_image->img_stride = lp_res->img_stride[image->u.tex.level]; 744bf215546Sopenharmony_ci jit_image->sample_stride = lp_res->sample_stride; 745bf215546Sopenharmony_ci jit_image->base = (uint8_t *)jit_image->base + mip_offset; 746bf215546Sopenharmony_ci } 747bf215546Sopenharmony_ci else { 748bf215546Sopenharmony_ci unsigned view_blocksize = util_format_get_blocksize(image->format); 749bf215546Sopenharmony_ci jit_image->width = image->u.buf.size / view_blocksize; 750bf215546Sopenharmony_ci jit_image->base = (uint8_t *)jit_image->base + image->u.buf.offset; 751bf215546Sopenharmony_ci } 752bf215546Sopenharmony_ci } 753bf215546Sopenharmony_ci } 754bf215546Sopenharmony_ci for (; i < ARRAY_SIZE(setup->images); i++) { 755bf215546Sopenharmony_ci util_copy_image_view(&setup->images[i].current, NULL); 756bf215546Sopenharmony_ci } 757bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 758bf215546Sopenharmony_ci} 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_civoid 762bf215546Sopenharmony_cilp_setup_set_alpha_ref_value(struct lp_setup_context *setup, 763bf215546Sopenharmony_ci float alpha_ref_value) 764bf215546Sopenharmony_ci{ 765bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value); 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_ci if (setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) { 768bf215546Sopenharmony_ci setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value; 769bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 770bf215546Sopenharmony_ci } 771bf215546Sopenharmony_ci} 772bf215546Sopenharmony_ci 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_civoid 775bf215546Sopenharmony_cilp_setup_set_stencil_ref_values(struct lp_setup_context *setup, 776bf215546Sopenharmony_ci const ubyte refs[2]) 777bf215546Sopenharmony_ci{ 778bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s %d %d\n", __FUNCTION__, refs[0], refs[1]); 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci if (setup->fs.current.jit_context.stencil_ref_front != refs[0] || 781bf215546Sopenharmony_ci setup->fs.current.jit_context.stencil_ref_back != refs[1]) { 782bf215546Sopenharmony_ci setup->fs.current.jit_context.stencil_ref_front = refs[0]; 783bf215546Sopenharmony_ci setup->fs.current.jit_context.stencil_ref_back = refs[1]; 784bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 785bf215546Sopenharmony_ci } 786bf215546Sopenharmony_ci} 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_civoid 790bf215546Sopenharmony_cilp_setup_set_blend_color(struct lp_setup_context *setup, 791bf215546Sopenharmony_ci const struct pipe_blend_color *blend_color) 792bf215546Sopenharmony_ci{ 793bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 794bf215546Sopenharmony_ci 795bf215546Sopenharmony_ci assert(blend_color); 796bf215546Sopenharmony_ci 797bf215546Sopenharmony_ci if (memcmp(&setup->blend_color.current, 798bf215546Sopenharmony_ci blend_color, sizeof *blend_color) != 0) { 799bf215546Sopenharmony_ci memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color); 800bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_BLEND_COLOR; 801bf215546Sopenharmony_ci } 802bf215546Sopenharmony_ci} 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci 805bf215546Sopenharmony_civoid 806bf215546Sopenharmony_cilp_setup_set_scissors(struct lp_setup_context *setup, 807bf215546Sopenharmony_ci const struct pipe_scissor_state *scissors) 808bf215546Sopenharmony_ci{ 809bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci assert(scissors); 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci for (unsigned i = 0; i < PIPE_MAX_VIEWPORTS; ++i) { 814bf215546Sopenharmony_ci setup->scissors[i].x0 = scissors[i].minx; 815bf215546Sopenharmony_ci setup->scissors[i].x1 = scissors[i].maxx-1; 816bf215546Sopenharmony_ci setup->scissors[i].y0 = scissors[i].miny; 817bf215546Sopenharmony_ci setup->scissors[i].y1 = scissors[i].maxy-1; 818bf215546Sopenharmony_ci } 819bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_SCISSOR; 820bf215546Sopenharmony_ci} 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_civoid 824bf215546Sopenharmony_cilp_setup_set_sample_mask(struct lp_setup_context *setup, 825bf215546Sopenharmony_ci uint32_t sample_mask) 826bf215546Sopenharmony_ci{ 827bf215546Sopenharmony_ci if (setup->fs.current.jit_context.sample_mask != sample_mask) { 828bf215546Sopenharmony_ci setup->fs.current.jit_context.sample_mask = sample_mask; 829bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 830bf215546Sopenharmony_ci } 831bf215546Sopenharmony_ci} 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci 834bf215546Sopenharmony_civoid 835bf215546Sopenharmony_cilp_setup_set_rasterizer_discard(struct lp_setup_context *setup, 836bf215546Sopenharmony_ci boolean rasterizer_discard) 837bf215546Sopenharmony_ci{ 838bf215546Sopenharmony_ci if (setup->rasterizer_discard != rasterizer_discard) { 839bf215546Sopenharmony_ci setup->rasterizer_discard = rasterizer_discard; 840bf215546Sopenharmony_ci setup->line = first_line; 841bf215546Sopenharmony_ci setup->point = first_point; 842bf215546Sopenharmony_ci setup->triangle = first_triangle; 843bf215546Sopenharmony_ci setup->rect = first_rectangle; 844bf215546Sopenharmony_ci } 845bf215546Sopenharmony_ci} 846bf215546Sopenharmony_ci 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_civoid 849bf215546Sopenharmony_cilp_setup_set_vertex_info(struct lp_setup_context *setup, 850bf215546Sopenharmony_ci struct vertex_info *vertex_info) 851bf215546Sopenharmony_ci{ 852bf215546Sopenharmony_ci /* XXX: just silently holding onto the pointer: 853bf215546Sopenharmony_ci */ 854bf215546Sopenharmony_ci setup->vertex_info = vertex_info; 855bf215546Sopenharmony_ci} 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_ci 858bf215546Sopenharmony_civoid 859bf215546Sopenharmony_cilp_setup_set_linear_mode(struct lp_setup_context *setup, 860bf215546Sopenharmony_ci boolean mode) 861bf215546Sopenharmony_ci{ 862bf215546Sopenharmony_ci /* The linear rasterizer requires sse2 both at compile and runtime, 863bf215546Sopenharmony_ci * in particular for the code in lp_rast_linear_fallback.c. This 864bf215546Sopenharmony_ci * is more than ten-year-old technology, so it's a reasonable 865bf215546Sopenharmony_ci * baseline. 866bf215546Sopenharmony_ci */ 867bf215546Sopenharmony_ci#if defined(PIPE_ARCH_SSE) 868bf215546Sopenharmony_ci setup->permit_linear_rasterizer = (mode && 869bf215546Sopenharmony_ci util_get_cpu_caps()->has_sse2); 870bf215546Sopenharmony_ci#else 871bf215546Sopenharmony_ci setup->permit_linear_rasterizer = FALSE; 872bf215546Sopenharmony_ci#endif 873bf215546Sopenharmony_ci} 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_ci/** 877bf215546Sopenharmony_ci * Called during state validation when LP_NEW_VIEWPORT is set. 878bf215546Sopenharmony_ci */ 879bf215546Sopenharmony_civoid 880bf215546Sopenharmony_cilp_setup_set_viewports(struct lp_setup_context *setup, 881bf215546Sopenharmony_ci unsigned num_viewports, 882bf215546Sopenharmony_ci const struct pipe_viewport_state *viewports) 883bf215546Sopenharmony_ci{ 884bf215546Sopenharmony_ci struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); 885bf215546Sopenharmony_ci 886bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 887bf215546Sopenharmony_ci 888bf215546Sopenharmony_ci assert(num_viewports <= PIPE_MAX_VIEWPORTS); 889bf215546Sopenharmony_ci assert(viewports); 890bf215546Sopenharmony_ci 891bf215546Sopenharmony_ci /* 892bf215546Sopenharmony_ci * Linear rasterizer path for scissor/viewport intersection. 893bf215546Sopenharmony_ci * 894bf215546Sopenharmony_ci * Calculate "scissor" rect from the (first) viewport. 895bf215546Sopenharmony_ci * Just like stored scissor rects need inclusive coords. 896bf215546Sopenharmony_ci * For rounding, assume half pixel center (d3d9 should not end up 897bf215546Sopenharmony_ci * with fractional viewports) - quite obviously for msaa we'd need 898bf215546Sopenharmony_ci * fractional values here (and elsewhere for the point bounding box). 899bf215546Sopenharmony_ci * 900bf215546Sopenharmony_ci * See: lp_setup.c::try_update_scene_state 901bf215546Sopenharmony_ci */ 902bf215546Sopenharmony_ci const float half_height = fabsf(viewports[0].scale[1]); 903bf215546Sopenharmony_ci const float x0 = viewports[0].translate[0] - viewports[0].scale[0]; 904bf215546Sopenharmony_ci const float y0 = viewports[0].translate[1] - half_height; 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci setup->vpwh.x0 = (int)(x0 + 0.499f); 907bf215546Sopenharmony_ci setup->vpwh.x1 = (int)(viewports[0].scale[0] * 2.0f + x0 - 0.501f); 908bf215546Sopenharmony_ci setup->vpwh.y0 = (int)(y0 + 0.499f); 909bf215546Sopenharmony_ci setup->vpwh.y1 = (int)(half_height * 2.0f + y0 - 0.501f); 910bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_SCISSOR; 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_ci /* 913bf215546Sopenharmony_ci * For use in lp_state_fs.c, propagate the viewport values for all viewports. 914bf215546Sopenharmony_ci */ 915bf215546Sopenharmony_ci for (unsigned i = 0; i < num_viewports; i++) { 916bf215546Sopenharmony_ci float min_depth, max_depth; 917bf215546Sopenharmony_ci util_viewport_zmin_zmax(&viewports[i], lp->rasterizer->clip_halfz, 918bf215546Sopenharmony_ci &min_depth, &max_depth); 919bf215546Sopenharmony_ci 920bf215546Sopenharmony_ci if (setup->viewports[i].min_depth != min_depth || 921bf215546Sopenharmony_ci setup->viewports[i].max_depth != max_depth) { 922bf215546Sopenharmony_ci setup->viewports[i].min_depth = min_depth; 923bf215546Sopenharmony_ci setup->viewports[i].max_depth = max_depth; 924bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_VIEWPORTS; 925bf215546Sopenharmony_ci } 926bf215546Sopenharmony_ci } 927bf215546Sopenharmony_ci} 928bf215546Sopenharmony_ci 929bf215546Sopenharmony_ci 930bf215546Sopenharmony_ci/** 931bf215546Sopenharmony_ci * Called directly by llvmpipe_set_sampler_views 932bf215546Sopenharmony_ci */ 933bf215546Sopenharmony_civoid 934bf215546Sopenharmony_cilp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, 935bf215546Sopenharmony_ci unsigned num, 936bf215546Sopenharmony_ci struct pipe_sampler_view **views) 937bf215546Sopenharmony_ci{ 938bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 939bf215546Sopenharmony_ci 940bf215546Sopenharmony_ci assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); 941bf215546Sopenharmony_ci 942bf215546Sopenharmony_ci const unsigned max_tex_num = MAX2(num, setup->fs.current_tex_num); 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci for (unsigned i = 0; i < max_tex_num; i++) { 945bf215546Sopenharmony_ci const struct pipe_sampler_view *view = i < num ? views[i] : NULL; 946bf215546Sopenharmony_ci 947bf215546Sopenharmony_ci /* We are going to overwrite/unref the current texture further below. If 948bf215546Sopenharmony_ci * set, make sure to unmap its resource to avoid leaking previous 949bf215546Sopenharmony_ci * mapping. */ 950bf215546Sopenharmony_ci if (setup->fs.current_tex[i]) 951bf215546Sopenharmony_ci llvmpipe_resource_unmap(setup->fs.current_tex[i], 0, 0); 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ci if (view) { 954bf215546Sopenharmony_ci struct pipe_resource *res = view->texture; 955bf215546Sopenharmony_ci struct llvmpipe_resource *lp_tex = llvmpipe_resource(res); 956bf215546Sopenharmony_ci struct lp_jit_texture *jit_tex; 957bf215546Sopenharmony_ci jit_tex = &setup->fs.current.jit_context.textures[i]; 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_ci /* We're referencing the texture's internal data, so save a 960bf215546Sopenharmony_ci * reference to it. 961bf215546Sopenharmony_ci */ 962bf215546Sopenharmony_ci pipe_resource_reference(&setup->fs.current_tex[i], res); 963bf215546Sopenharmony_ci 964bf215546Sopenharmony_ci if (!lp_tex->dt) { 965bf215546Sopenharmony_ci /* regular texture - setup array of mipmap level offsets */ 966bf215546Sopenharmony_ci unsigned first_level = 0; 967bf215546Sopenharmony_ci unsigned last_level = 0; 968bf215546Sopenharmony_ci 969bf215546Sopenharmony_ci if (llvmpipe_resource_is_texture(res)) { 970bf215546Sopenharmony_ci first_level = view->u.tex.first_level; 971bf215546Sopenharmony_ci last_level = view->u.tex.last_level; 972bf215546Sopenharmony_ci assert(first_level <= last_level); 973bf215546Sopenharmony_ci assert(last_level <= res->last_level); 974bf215546Sopenharmony_ci jit_tex->base = lp_tex->tex_data; 975bf215546Sopenharmony_ci } 976bf215546Sopenharmony_ci else { 977bf215546Sopenharmony_ci jit_tex->base = lp_tex->data; 978bf215546Sopenharmony_ci } 979bf215546Sopenharmony_ci 980bf215546Sopenharmony_ci if (LP_PERF & PERF_TEX_MEM) { 981bf215546Sopenharmony_ci /* use dummy tile memory */ 982bf215546Sopenharmony_ci jit_tex->base = lp_dummy_tile; 983bf215546Sopenharmony_ci jit_tex->width = TILE_SIZE/8; 984bf215546Sopenharmony_ci jit_tex->height = TILE_SIZE/8; 985bf215546Sopenharmony_ci jit_tex->depth = 1; 986bf215546Sopenharmony_ci jit_tex->first_level = 0; 987bf215546Sopenharmony_ci jit_tex->last_level = 0; 988bf215546Sopenharmony_ci jit_tex->mip_offsets[0] = 0; 989bf215546Sopenharmony_ci jit_tex->row_stride[0] = 0; 990bf215546Sopenharmony_ci jit_tex->img_stride[0] = 0; 991bf215546Sopenharmony_ci jit_tex->num_samples = 0; 992bf215546Sopenharmony_ci jit_tex->sample_stride = 0; 993bf215546Sopenharmony_ci } 994bf215546Sopenharmony_ci else { 995bf215546Sopenharmony_ci jit_tex->width = res->width0; 996bf215546Sopenharmony_ci jit_tex->height = res->height0; 997bf215546Sopenharmony_ci jit_tex->depth = res->depth0; 998bf215546Sopenharmony_ci jit_tex->first_level = first_level; 999bf215546Sopenharmony_ci jit_tex->last_level = last_level; 1000bf215546Sopenharmony_ci jit_tex->num_samples = res->nr_samples; 1001bf215546Sopenharmony_ci jit_tex->sample_stride = 0; 1002bf215546Sopenharmony_ci 1003bf215546Sopenharmony_ci if (llvmpipe_resource_is_texture(res)) { 1004bf215546Sopenharmony_ci for (unsigned j = first_level; j <= last_level; j++) { 1005bf215546Sopenharmony_ci jit_tex->mip_offsets[j] = lp_tex->mip_offsets[j]; 1006bf215546Sopenharmony_ci jit_tex->row_stride[j] = lp_tex->row_stride[j]; 1007bf215546Sopenharmony_ci jit_tex->img_stride[j] = lp_tex->img_stride[j]; 1008bf215546Sopenharmony_ci } 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci jit_tex->sample_stride = lp_tex->sample_stride; 1011bf215546Sopenharmony_ci 1012bf215546Sopenharmony_ci if (res->target == PIPE_TEXTURE_1D_ARRAY || 1013bf215546Sopenharmony_ci res->target == PIPE_TEXTURE_2D_ARRAY || 1014bf215546Sopenharmony_ci res->target == PIPE_TEXTURE_CUBE || 1015bf215546Sopenharmony_ci res->target == PIPE_TEXTURE_CUBE_ARRAY || 1016bf215546Sopenharmony_ci (res->target == PIPE_TEXTURE_3D && view->target == PIPE_TEXTURE_2D)) { 1017bf215546Sopenharmony_ci /* 1018bf215546Sopenharmony_ci * For array textures, we don't have first_layer, instead 1019bf215546Sopenharmony_ci * adjust last_layer (stored as depth) plus the mip level 1020bf215546Sopenharmony_ci * offsets (as we have mip-first layout can't just adjust 1021bf215546Sopenharmony_ci * base ptr). XXX For mip levels, could do something 1022bf215546Sopenharmony_ci * similar. 1023bf215546Sopenharmony_ci */ 1024bf215546Sopenharmony_ci jit_tex->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1; 1025bf215546Sopenharmony_ci for (unsigned j = first_level; j <= last_level; j++) { 1026bf215546Sopenharmony_ci jit_tex->mip_offsets[j] += view->u.tex.first_layer * 1027bf215546Sopenharmony_ci lp_tex->img_stride[j]; 1028bf215546Sopenharmony_ci } 1029bf215546Sopenharmony_ci if (view->target == PIPE_TEXTURE_CUBE || 1030bf215546Sopenharmony_ci view->target == PIPE_TEXTURE_CUBE_ARRAY) { 1031bf215546Sopenharmony_ci assert(jit_tex->depth % 6 == 0); 1032bf215546Sopenharmony_ci } 1033bf215546Sopenharmony_ci assert(view->u.tex.first_layer <= view->u.tex.last_layer); 1034bf215546Sopenharmony_ci if (res->target == PIPE_TEXTURE_3D) 1035bf215546Sopenharmony_ci assert(view->u.tex.last_layer < res->depth0); 1036bf215546Sopenharmony_ci else 1037bf215546Sopenharmony_ci assert(view->u.tex.last_layer < res->array_size); 1038bf215546Sopenharmony_ci } 1039bf215546Sopenharmony_ci } 1040bf215546Sopenharmony_ci else { 1041bf215546Sopenharmony_ci /* 1042bf215546Sopenharmony_ci * For buffers, we don't have "offset", instead adjust 1043bf215546Sopenharmony_ci * the size (stored as width) plus the base pointer. 1044bf215546Sopenharmony_ci */ 1045bf215546Sopenharmony_ci const unsigned view_blocksize = 1046bf215546Sopenharmony_ci util_format_get_blocksize(view->format); 1047bf215546Sopenharmony_ci /* probably don't really need to fill that out */ 1048bf215546Sopenharmony_ci jit_tex->mip_offsets[0] = 0; 1049bf215546Sopenharmony_ci jit_tex->row_stride[0] = 0; 1050bf215546Sopenharmony_ci jit_tex->img_stride[0] = 0; 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_ci /* everything specified in number of elements here. */ 1053bf215546Sopenharmony_ci jit_tex->width = view->u.buf.size / view_blocksize; 1054bf215546Sopenharmony_ci jit_tex->base = (uint8_t *)jit_tex->base + view->u.buf.offset; 1055bf215546Sopenharmony_ci /* XXX Unsure if we need to sanitize parameters? */ 1056bf215546Sopenharmony_ci assert(view->u.buf.offset + view->u.buf.size <= res->width0); 1057bf215546Sopenharmony_ci } 1058bf215546Sopenharmony_ci } 1059bf215546Sopenharmony_ci } 1060bf215546Sopenharmony_ci else { 1061bf215546Sopenharmony_ci /* display target texture/surface */ 1062bf215546Sopenharmony_ci jit_tex->base = llvmpipe_resource_map(res, 0, 0, LP_TEX_USAGE_READ); 1063bf215546Sopenharmony_ci jit_tex->row_stride[0] = lp_tex->row_stride[0]; 1064bf215546Sopenharmony_ci jit_tex->img_stride[0] = lp_tex->img_stride[0]; 1065bf215546Sopenharmony_ci jit_tex->mip_offsets[0] = 0; 1066bf215546Sopenharmony_ci jit_tex->width = res->width0; 1067bf215546Sopenharmony_ci jit_tex->height = res->height0; 1068bf215546Sopenharmony_ci jit_tex->depth = res->depth0; 1069bf215546Sopenharmony_ci jit_tex->first_level = jit_tex->last_level = 0; 1070bf215546Sopenharmony_ci jit_tex->num_samples = res->nr_samples; 1071bf215546Sopenharmony_ci jit_tex->sample_stride = 0; 1072bf215546Sopenharmony_ci assert(jit_tex->base); 1073bf215546Sopenharmony_ci } 1074bf215546Sopenharmony_ci } 1075bf215546Sopenharmony_ci else { 1076bf215546Sopenharmony_ci pipe_resource_reference(&setup->fs.current_tex[i], NULL); 1077bf215546Sopenharmony_ci } 1078bf215546Sopenharmony_ci } 1079bf215546Sopenharmony_ci setup->fs.current_tex_num = num; 1080bf215546Sopenharmony_ci 1081bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 1082bf215546Sopenharmony_ci} 1083bf215546Sopenharmony_ci 1084bf215546Sopenharmony_ci 1085bf215546Sopenharmony_ci/** 1086bf215546Sopenharmony_ci * Called during state validation when LP_NEW_SAMPLER is set. 1087bf215546Sopenharmony_ci */ 1088bf215546Sopenharmony_civoid 1089bf215546Sopenharmony_cilp_setup_set_fragment_sampler_state(struct lp_setup_context *setup, 1090bf215546Sopenharmony_ci unsigned num, 1091bf215546Sopenharmony_ci struct pipe_sampler_state **samplers) 1092bf215546Sopenharmony_ci{ 1093bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 1094bf215546Sopenharmony_ci 1095bf215546Sopenharmony_ci assert(num <= PIPE_MAX_SAMPLERS); 1096bf215546Sopenharmony_ci 1097bf215546Sopenharmony_ci for (unsigned i = 0; i < PIPE_MAX_SAMPLERS; i++) { 1098bf215546Sopenharmony_ci const struct pipe_sampler_state *sampler = i < num ? samplers[i] : NULL; 1099bf215546Sopenharmony_ci 1100bf215546Sopenharmony_ci if (sampler) { 1101bf215546Sopenharmony_ci struct lp_jit_sampler *jit_sam; 1102bf215546Sopenharmony_ci jit_sam = &setup->fs.current.jit_context.samplers[i]; 1103bf215546Sopenharmony_ci 1104bf215546Sopenharmony_ci jit_sam->min_lod = sampler->min_lod; 1105bf215546Sopenharmony_ci jit_sam->max_lod = sampler->max_lod; 1106bf215546Sopenharmony_ci jit_sam->lod_bias = sampler->lod_bias; 1107bf215546Sopenharmony_ci jit_sam->max_aniso = sampler->max_anisotropy; 1108bf215546Sopenharmony_ci COPY_4V(jit_sam->border_color, sampler->border_color.f); 1109bf215546Sopenharmony_ci } 1110bf215546Sopenharmony_ci } 1111bf215546Sopenharmony_ci 1112bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 1113bf215546Sopenharmony_ci} 1114bf215546Sopenharmony_ci 1115bf215546Sopenharmony_ci 1116bf215546Sopenharmony_ci/** 1117bf215546Sopenharmony_ci * Is the given texture referenced by any scene? 1118bf215546Sopenharmony_ci * Note: we have to check all scenes including any scenes currently 1119bf215546Sopenharmony_ci * being rendered and the current scene being built. 1120bf215546Sopenharmony_ci */ 1121bf215546Sopenharmony_ciunsigned 1122bf215546Sopenharmony_cilp_setup_is_resource_referenced(const struct lp_setup_context *setup, 1123bf215546Sopenharmony_ci const struct pipe_resource *texture) 1124bf215546Sopenharmony_ci{ 1125bf215546Sopenharmony_ci /* check the render targets */ 1126bf215546Sopenharmony_ci for (unsigned i = 0; i < setup->fb.nr_cbufs; i++) { 1127bf215546Sopenharmony_ci if (setup->fb.cbufs[i] && setup->fb.cbufs[i]->texture == texture) 1128bf215546Sopenharmony_ci return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 1129bf215546Sopenharmony_ci } 1130bf215546Sopenharmony_ci if (setup->fb.zsbuf && setup->fb.zsbuf->texture == texture) { 1131bf215546Sopenharmony_ci return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 1132bf215546Sopenharmony_ci } 1133bf215546Sopenharmony_ci 1134bf215546Sopenharmony_ci /* check resources referenced by active scenes */ 1135bf215546Sopenharmony_ci for (unsigned i = 0; i < setup->num_active_scenes; i++) { 1136bf215546Sopenharmony_ci struct lp_scene *scene = setup->scenes[i]; 1137bf215546Sopenharmony_ci /* check the render targets */ 1138bf215546Sopenharmony_ci for (unsigned j = 0; j < scene->fb.nr_cbufs; j++) { 1139bf215546Sopenharmony_ci if (scene->fb.cbufs[j] && scene->fb.cbufs[j]->texture == texture) 1140bf215546Sopenharmony_ci return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 1141bf215546Sopenharmony_ci } 1142bf215546Sopenharmony_ci if (scene->fb.zsbuf && scene->fb.zsbuf->texture == texture) { 1143bf215546Sopenharmony_ci return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 1144bf215546Sopenharmony_ci } 1145bf215546Sopenharmony_ci 1146bf215546Sopenharmony_ci /* check resources referenced by the scene */ 1147bf215546Sopenharmony_ci unsigned ref = lp_scene_is_resource_referenced(scene, texture); 1148bf215546Sopenharmony_ci if (ref) 1149bf215546Sopenharmony_ci return ref; 1150bf215546Sopenharmony_ci } 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci return LP_UNREFERENCED; 1153bf215546Sopenharmony_ci} 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ci 1156bf215546Sopenharmony_ci/** 1157bf215546Sopenharmony_ci * Called by vbuf code when we're about to draw something. 1158bf215546Sopenharmony_ci * 1159bf215546Sopenharmony_ci * This function stores all dirty state in the current scene's display list 1160bf215546Sopenharmony_ci * memory, via lp_scene_alloc(). We can not pass pointers of mutable state to 1161bf215546Sopenharmony_ci * the JIT functions, as the JIT functions will be called later on, most likely 1162bf215546Sopenharmony_ci * on a different thread. 1163bf215546Sopenharmony_ci * 1164bf215546Sopenharmony_ci * When processing dirty state it is imperative that we don't refer to any 1165bf215546Sopenharmony_ci * pointers previously allocated with lp_scene_alloc() in this function (or any 1166bf215546Sopenharmony_ci * function) as they may belong to a scene freed since then. 1167bf215546Sopenharmony_ci */ 1168bf215546Sopenharmony_cistatic boolean 1169bf215546Sopenharmony_citry_update_scene_state(struct lp_setup_context *setup) 1170bf215546Sopenharmony_ci{ 1171bf215546Sopenharmony_ci static const float fake_const_buf[4]; 1172bf215546Sopenharmony_ci boolean new_scene = (setup->fs.stored == NULL); 1173bf215546Sopenharmony_ci struct lp_scene *scene = setup->scene; 1174bf215546Sopenharmony_ci 1175bf215546Sopenharmony_ci assert(scene); 1176bf215546Sopenharmony_ci 1177bf215546Sopenharmony_ci if (setup->dirty & LP_SETUP_NEW_VIEWPORTS) { 1178bf215546Sopenharmony_ci /* 1179bf215546Sopenharmony_ci * Record new depth range state for changes due to viewport updates. 1180bf215546Sopenharmony_ci * 1181bf215546Sopenharmony_ci * TODO: Collapse the existing viewport and depth range information 1182bf215546Sopenharmony_ci * into one structure, for access by JIT. 1183bf215546Sopenharmony_ci */ 1184bf215546Sopenharmony_ci struct lp_jit_viewport *stored; 1185bf215546Sopenharmony_ci 1186bf215546Sopenharmony_ci stored = (struct lp_jit_viewport *) 1187bf215546Sopenharmony_ci lp_scene_alloc(scene, sizeof setup->viewports); 1188bf215546Sopenharmony_ci 1189bf215546Sopenharmony_ci if (!stored) { 1190bf215546Sopenharmony_ci assert(!new_scene); 1191bf215546Sopenharmony_ci return FALSE; 1192bf215546Sopenharmony_ci } 1193bf215546Sopenharmony_ci 1194bf215546Sopenharmony_ci memcpy(stored, setup->viewports, sizeof setup->viewports); 1195bf215546Sopenharmony_ci 1196bf215546Sopenharmony_ci setup->fs.current.jit_context.viewports = stored; 1197bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 1198bf215546Sopenharmony_ci } 1199bf215546Sopenharmony_ci 1200bf215546Sopenharmony_ci if (setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { 1201bf215546Sopenharmony_ci /* Alloc u8_blend_color (16 x i8) and f_blend_color (4 or 8 x f32) */ 1202bf215546Sopenharmony_ci const unsigned size = 4 * 16 * sizeof(uint8_t) 1203bf215546Sopenharmony_ci + (LP_MAX_VECTOR_LENGTH / 4) * sizeof(float); 1204bf215546Sopenharmony_ci 1205bf215546Sopenharmony_ci uint8_t *stored = 1206bf215546Sopenharmony_ci lp_scene_alloc_aligned(scene, size, LP_MIN_VECTOR_ALIGN); 1207bf215546Sopenharmony_ci 1208bf215546Sopenharmony_ci if (!stored) { 1209bf215546Sopenharmony_ci assert(!new_scene); 1210bf215546Sopenharmony_ci return FALSE; 1211bf215546Sopenharmony_ci } 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci /* Store floating point colour (after ubyte colors (see below)) */ 1214bf215546Sopenharmony_ci float *fstored = (float *) (stored + 4 * 16); 1215bf215546Sopenharmony_ci for (unsigned i = 0; i < (LP_MAX_VECTOR_LENGTH / 4); ++i) { 1216bf215546Sopenharmony_ci fstored[i] = setup->blend_color.current.color[i % 4]; 1217bf215546Sopenharmony_ci } 1218bf215546Sopenharmony_ci 1219bf215546Sopenharmony_ci /* smear each blend color component across 16 ubyte elements */ 1220bf215546Sopenharmony_ci for (unsigned i = 0; i < 4; ++i) { 1221bf215546Sopenharmony_ci uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); 1222bf215546Sopenharmony_ci for (unsigned j = 0; j < 16; ++j) { 1223bf215546Sopenharmony_ci stored[i*16 + j] = c; 1224bf215546Sopenharmony_ci } 1225bf215546Sopenharmony_ci } 1226bf215546Sopenharmony_ci 1227bf215546Sopenharmony_ci setup->blend_color.stored = stored; 1228bf215546Sopenharmony_ci setup->fs.current.jit_context.u8_blend_color = stored; 1229bf215546Sopenharmony_ci setup->fs.current.jit_context.f_blend_color = fstored; 1230bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 1231bf215546Sopenharmony_ci } 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_ci struct llvmpipe_context *llvmpipe = llvmpipe_context(setup->pipe); 1234bf215546Sopenharmony_ci if (llvmpipe->dirty & LP_NEW_FS_CONSTANTS) 1235bf215546Sopenharmony_ci lp_setup_set_fs_constants(llvmpipe->setup, 1236bf215546Sopenharmony_ci ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]), 1237bf215546Sopenharmony_ci llvmpipe->constants[PIPE_SHADER_FRAGMENT]); 1238bf215546Sopenharmony_ci 1239bf215546Sopenharmony_ci if (setup->dirty & LP_SETUP_NEW_CONSTANTS) { 1240bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->constants); ++i) { 1241bf215546Sopenharmony_ci struct pipe_resource *buffer = setup->constants[i].current.buffer; 1242bf215546Sopenharmony_ci const unsigned current_size = MIN2(setup->constants[i].current.buffer_size, 1243bf215546Sopenharmony_ci LP_MAX_TGSI_CONST_BUFFER_SIZE); 1244bf215546Sopenharmony_ci const ubyte *current_data = NULL; 1245bf215546Sopenharmony_ci 1246bf215546Sopenharmony_ci STATIC_ASSERT(DATA_BLOCK_SIZE >= LP_MAX_TGSI_CONST_BUFFER_SIZE); 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ci if (buffer) { 1249bf215546Sopenharmony_ci /* resource buffer */ 1250bf215546Sopenharmony_ci current_data = (ubyte *) llvmpipe_resource_data(buffer); 1251bf215546Sopenharmony_ci } 1252bf215546Sopenharmony_ci else if (setup->constants[i].current.user_buffer) { 1253bf215546Sopenharmony_ci /* user-space buffer */ 1254bf215546Sopenharmony_ci current_data = (ubyte *) setup->constants[i].current.user_buffer; 1255bf215546Sopenharmony_ci } 1256bf215546Sopenharmony_ci 1257bf215546Sopenharmony_ci if (current_data && current_size >= sizeof(float)) { 1258bf215546Sopenharmony_ci current_data += setup->constants[i].current.buffer_offset; 1259bf215546Sopenharmony_ci 1260bf215546Sopenharmony_ci /* TODO: copy only the actually used constants? */ 1261bf215546Sopenharmony_ci 1262bf215546Sopenharmony_ci if (setup->constants[i].stored_size != current_size || 1263bf215546Sopenharmony_ci !setup->constants[i].stored_data || 1264bf215546Sopenharmony_ci memcmp(setup->constants[i].stored_data, 1265bf215546Sopenharmony_ci current_data, 1266bf215546Sopenharmony_ci current_size) != 0) { 1267bf215546Sopenharmony_ci 1268bf215546Sopenharmony_ci void *stored = lp_scene_alloc(scene, current_size); 1269bf215546Sopenharmony_ci if (!stored) { 1270bf215546Sopenharmony_ci assert(!new_scene); 1271bf215546Sopenharmony_ci return FALSE; 1272bf215546Sopenharmony_ci } 1273bf215546Sopenharmony_ci 1274bf215546Sopenharmony_ci memcpy(stored, 1275bf215546Sopenharmony_ci current_data, 1276bf215546Sopenharmony_ci current_size); 1277bf215546Sopenharmony_ci setup->constants[i].stored_size = current_size; 1278bf215546Sopenharmony_ci setup->constants[i].stored_data = stored; 1279bf215546Sopenharmony_ci } 1280bf215546Sopenharmony_ci setup->fs.current.jit_context.constants[i] = 1281bf215546Sopenharmony_ci setup->constants[i].stored_data; 1282bf215546Sopenharmony_ci } 1283bf215546Sopenharmony_ci else { 1284bf215546Sopenharmony_ci setup->constants[i].stored_size = 0; 1285bf215546Sopenharmony_ci setup->constants[i].stored_data = NULL; 1286bf215546Sopenharmony_ci setup->fs.current.jit_context.constants[i] = fake_const_buf; 1287bf215546Sopenharmony_ci } 1288bf215546Sopenharmony_ci 1289bf215546Sopenharmony_ci const int num_constants = 1290bf215546Sopenharmony_ci DIV_ROUND_UP(setup->constants[i].stored_size, 1291bf215546Sopenharmony_ci lp_get_constant_buffer_stride(scene->pipe->screen)); 1292bf215546Sopenharmony_ci setup->fs.current.jit_context.num_constants[i] = num_constants; 1293bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 1294bf215546Sopenharmony_ci } 1295bf215546Sopenharmony_ci } 1296bf215546Sopenharmony_ci 1297bf215546Sopenharmony_ci if (setup->dirty & LP_SETUP_NEW_SSBOS) { 1298bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->ssbos); ++i) { 1299bf215546Sopenharmony_ci struct pipe_resource *buffer = setup->ssbos[i].current.buffer; 1300bf215546Sopenharmony_ci const ubyte *current_data = NULL; 1301bf215546Sopenharmony_ci 1302bf215546Sopenharmony_ci /* resource buffer */ 1303bf215546Sopenharmony_ci if (buffer) 1304bf215546Sopenharmony_ci current_data = (ubyte *) llvmpipe_resource_data(buffer); 1305bf215546Sopenharmony_ci 1306bf215546Sopenharmony_ci if (current_data) { 1307bf215546Sopenharmony_ci current_data += setup->ssbos[i].current.buffer_offset; 1308bf215546Sopenharmony_ci 1309bf215546Sopenharmony_ci setup->fs.current.jit_context.ssbos[i] = 1310bf215546Sopenharmony_ci (const uint32_t *)current_data; 1311bf215546Sopenharmony_ci setup->fs.current.jit_context.num_ssbos[i] = 1312bf215546Sopenharmony_ci setup->ssbos[i].current.buffer_size; 1313bf215546Sopenharmony_ci } else { 1314bf215546Sopenharmony_ci setup->fs.current.jit_context.ssbos[i] = NULL; 1315bf215546Sopenharmony_ci setup->fs.current.jit_context.num_ssbos[i] = 0; 1316bf215546Sopenharmony_ci } 1317bf215546Sopenharmony_ci setup->dirty |= LP_SETUP_NEW_FS; 1318bf215546Sopenharmony_ci } 1319bf215546Sopenharmony_ci } 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci if (setup->dirty & LP_SETUP_NEW_FS) { 1322bf215546Sopenharmony_ci if (!setup->fs.stored || 1323bf215546Sopenharmony_ci memcmp(setup->fs.stored, 1324bf215546Sopenharmony_ci &setup->fs.current, 1325bf215546Sopenharmony_ci sizeof setup->fs.current) != 0) { 1326bf215546Sopenharmony_ci /* The fs state that's been stored in the scene is different from 1327bf215546Sopenharmony_ci * the new, current state. So allocate a new lp_rast_state object 1328bf215546Sopenharmony_ci * and append it to the bin's setup data buffer. 1329bf215546Sopenharmony_ci */ 1330bf215546Sopenharmony_ci struct lp_rast_state *stored = 1331bf215546Sopenharmony_ci (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); 1332bf215546Sopenharmony_ci if (!stored) { 1333bf215546Sopenharmony_ci assert(!new_scene); 1334bf215546Sopenharmony_ci return FALSE; 1335bf215546Sopenharmony_ci } 1336bf215546Sopenharmony_ci 1337bf215546Sopenharmony_ci memcpy(&stored->jit_context, 1338bf215546Sopenharmony_ci &setup->fs.current.jit_context, 1339bf215546Sopenharmony_ci sizeof setup->fs.current.jit_context); 1340bf215546Sopenharmony_ci 1341bf215546Sopenharmony_ci stored->jit_context.aniso_filter_table = 1342bf215546Sopenharmony_ci lp_build_sample_aniso_filter_table(); 1343bf215546Sopenharmony_ci stored->variant = setup->fs.current.variant; 1344bf215546Sopenharmony_ci 1345bf215546Sopenharmony_ci if (!lp_scene_add_frag_shader_reference(scene, 1346bf215546Sopenharmony_ci setup->fs.current.variant)) { 1347bf215546Sopenharmony_ci return FALSE; 1348bf215546Sopenharmony_ci } 1349bf215546Sopenharmony_ci 1350bf215546Sopenharmony_ci setup->fs.stored = stored; 1351bf215546Sopenharmony_ci 1352bf215546Sopenharmony_ci /* The scene now references the textures in the rasterization 1353bf215546Sopenharmony_ci * state record. Note that now. 1354bf215546Sopenharmony_ci */ 1355bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) { 1356bf215546Sopenharmony_ci if (setup->fs.current_tex[i]) { 1357bf215546Sopenharmony_ci if (!lp_scene_add_resource_reference(scene, 1358bf215546Sopenharmony_ci setup->fs.current_tex[i], 1359bf215546Sopenharmony_ci new_scene, false)) { 1360bf215546Sopenharmony_ci assert(!new_scene); 1361bf215546Sopenharmony_ci return FALSE; 1362bf215546Sopenharmony_ci } 1363bf215546Sopenharmony_ci } 1364bf215546Sopenharmony_ci } 1365bf215546Sopenharmony_ci 1366bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->ssbos); i++) { 1367bf215546Sopenharmony_ci if (setup->ssbos[i].current.buffer) { 1368bf215546Sopenharmony_ci if (!lp_scene_add_resource_reference(scene, 1369bf215546Sopenharmony_ci setup->ssbos[i].current.buffer, 1370bf215546Sopenharmony_ci new_scene, setup->ssbo_write_mask & (1 << i))) { 1371bf215546Sopenharmony_ci assert(!new_scene); 1372bf215546Sopenharmony_ci return FALSE; 1373bf215546Sopenharmony_ci } 1374bf215546Sopenharmony_ci } 1375bf215546Sopenharmony_ci } 1376bf215546Sopenharmony_ci 1377bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->images); i++) { 1378bf215546Sopenharmony_ci if (setup->images[i].current.resource) { 1379bf215546Sopenharmony_ci if (!lp_scene_add_resource_reference(scene, 1380bf215546Sopenharmony_ci setup->images[i].current.resource, 1381bf215546Sopenharmony_ci new_scene, 1382bf215546Sopenharmony_ci setup->images[i].current.shader_access & PIPE_IMAGE_ACCESS_WRITE)) { 1383bf215546Sopenharmony_ci assert(!new_scene); 1384bf215546Sopenharmony_ci return FALSE; 1385bf215546Sopenharmony_ci } 1386bf215546Sopenharmony_ci } 1387bf215546Sopenharmony_ci } 1388bf215546Sopenharmony_ci } 1389bf215546Sopenharmony_ci } 1390bf215546Sopenharmony_ci 1391bf215546Sopenharmony_ci if (setup->dirty & LP_SETUP_NEW_SCISSOR) { 1392bf215546Sopenharmony_ci for (unsigned i = 0; i < PIPE_MAX_VIEWPORTS; ++i) { 1393bf215546Sopenharmony_ci setup->draw_regions[i] = setup->framebuffer; 1394bf215546Sopenharmony_ci if (setup->scissor_test) { 1395bf215546Sopenharmony_ci u_rect_possible_intersection(&setup->scissors[i], 1396bf215546Sopenharmony_ci &setup->draw_regions[i]); 1397bf215546Sopenharmony_ci } 1398bf215546Sopenharmony_ci } 1399bf215546Sopenharmony_ci if (setup->permit_linear_rasterizer) { 1400bf215546Sopenharmony_ci /* NOTE: this only takes first vp into account. */ 1401bf215546Sopenharmony_ci boolean need_vp_scissoring = 1402bf215546Sopenharmony_ci !!memcmp(&setup->vpwh, &setup->framebuffer, 1403bf215546Sopenharmony_ci sizeof(setup->framebuffer)); 1404bf215546Sopenharmony_ci 1405bf215546Sopenharmony_ci assert(setup->viewport_index_slot < 0); 1406bf215546Sopenharmony_ci if (need_vp_scissoring) { 1407bf215546Sopenharmony_ci u_rect_possible_intersection(&setup->vpwh, 1408bf215546Sopenharmony_ci &setup->draw_regions[0]); 1409bf215546Sopenharmony_ci } 1410bf215546Sopenharmony_ci } 1411bf215546Sopenharmony_ci else if (setup->point_tri_clip) { 1412bf215546Sopenharmony_ci /* 1413bf215546Sopenharmony_ci * for d3d-style point clipping, we're going to need 1414bf215546Sopenharmony_ci * the fake vp scissor too. Hence do the intersection with vp, 1415bf215546Sopenharmony_ci * but don't indicate this. As above this will only work for first vp 1416bf215546Sopenharmony_ci * which should be ok because we instruct draw to only skip point 1417bf215546Sopenharmony_ci * clipping when there's only one viewport (this works because d3d10 1418bf215546Sopenharmony_ci * points are always single pixel). 1419bf215546Sopenharmony_ci * (Also note that if we have permit_linear_rasterizer this will 1420bf215546Sopenharmony_ci * cause large points to always get vp scissored, regardless the 1421bf215546Sopenharmony_ci * point_tri_clip setting.) 1422bf215546Sopenharmony_ci */ 1423bf215546Sopenharmony_ci boolean need_vp_scissoring = 1424bf215546Sopenharmony_ci !!memcmp(&setup->vpwh, &setup->framebuffer, 1425bf215546Sopenharmony_ci sizeof(setup->framebuffer)); 1426bf215546Sopenharmony_ci if (need_vp_scissoring) { 1427bf215546Sopenharmony_ci u_rect_possible_intersection(&setup->vpwh, 1428bf215546Sopenharmony_ci &setup->draw_regions[0]); 1429bf215546Sopenharmony_ci } 1430bf215546Sopenharmony_ci } 1431bf215546Sopenharmony_ci } 1432bf215546Sopenharmony_ci 1433bf215546Sopenharmony_ci setup->dirty = 0; 1434bf215546Sopenharmony_ci 1435bf215546Sopenharmony_ci assert(setup->fs.stored); 1436bf215546Sopenharmony_ci return TRUE; 1437bf215546Sopenharmony_ci} 1438bf215546Sopenharmony_ci 1439bf215546Sopenharmony_ci 1440bf215546Sopenharmony_ciboolean 1441bf215546Sopenharmony_cilp_setup_update_state(struct lp_setup_context *setup, 1442bf215546Sopenharmony_ci boolean update_scene) 1443bf215546Sopenharmony_ci{ 1444bf215546Sopenharmony_ci /* Some of the 'draw' pipeline stages may have changed some driver state. 1445bf215546Sopenharmony_ci * Make sure we've processed those state changes before anything else. 1446bf215546Sopenharmony_ci * 1447bf215546Sopenharmony_ci * XXX this is the only place where llvmpipe_context is used in the 1448bf215546Sopenharmony_ci * setup code. This may get refactored/changed... 1449bf215546Sopenharmony_ci */ 1450bf215546Sopenharmony_ci { 1451bf215546Sopenharmony_ci struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); 1452bf215546Sopenharmony_ci if (lp->dirty) { 1453bf215546Sopenharmony_ci llvmpipe_update_derived(lp); 1454bf215546Sopenharmony_ci } 1455bf215546Sopenharmony_ci 1456bf215546Sopenharmony_ci if (lp->setup->dirty) { 1457bf215546Sopenharmony_ci llvmpipe_update_setup(lp); 1458bf215546Sopenharmony_ci } 1459bf215546Sopenharmony_ci 1460bf215546Sopenharmony_ci assert(setup->setup.variant); 1461bf215546Sopenharmony_ci 1462bf215546Sopenharmony_ci /* Will probably need to move this somewhere else, just need 1463bf215546Sopenharmony_ci * to know about vertex shader point size attribute. 1464bf215546Sopenharmony_ci */ 1465bf215546Sopenharmony_ci setup->psize_slot = lp->psize_slot; 1466bf215546Sopenharmony_ci setup->viewport_index_slot = lp->viewport_index_slot; 1467bf215546Sopenharmony_ci setup->layer_slot = lp->layer_slot; 1468bf215546Sopenharmony_ci setup->face_slot = lp->face_slot; 1469bf215546Sopenharmony_ci 1470bf215546Sopenharmony_ci assert(lp->dirty == 0); 1471bf215546Sopenharmony_ci 1472bf215546Sopenharmony_ci assert(lp->setup_variant.key.size == 1473bf215546Sopenharmony_ci setup->setup.variant->key.size); 1474bf215546Sopenharmony_ci 1475bf215546Sopenharmony_ci assert(memcmp(&lp->setup_variant.key, 1476bf215546Sopenharmony_ci &setup->setup.variant->key, 1477bf215546Sopenharmony_ci setup->setup.variant->key.size) == 0); 1478bf215546Sopenharmony_ci } 1479bf215546Sopenharmony_ci 1480bf215546Sopenharmony_ci if (update_scene && setup->state != SETUP_ACTIVE) { 1481bf215546Sopenharmony_ci if (!set_scene_state(setup, SETUP_ACTIVE, __FUNCTION__)) 1482bf215546Sopenharmony_ci return FALSE; 1483bf215546Sopenharmony_ci } 1484bf215546Sopenharmony_ci 1485bf215546Sopenharmony_ci /* Only call into update_scene_state() if we already have a 1486bf215546Sopenharmony_ci * scene: 1487bf215546Sopenharmony_ci */ 1488bf215546Sopenharmony_ci if (update_scene && setup->scene) { 1489bf215546Sopenharmony_ci assert(setup->state == SETUP_ACTIVE); 1490bf215546Sopenharmony_ci 1491bf215546Sopenharmony_ci if (try_update_scene_state(setup)) 1492bf215546Sopenharmony_ci return TRUE; 1493bf215546Sopenharmony_ci 1494bf215546Sopenharmony_ci /* Update failed, try to restart the scene. 1495bf215546Sopenharmony_ci * 1496bf215546Sopenharmony_ci * Cannot call lp_setup_flush_and_restart() directly here 1497bf215546Sopenharmony_ci * because of potential recursion. 1498bf215546Sopenharmony_ci */ 1499bf215546Sopenharmony_ci if (!set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__)) 1500bf215546Sopenharmony_ci return FALSE; 1501bf215546Sopenharmony_ci 1502bf215546Sopenharmony_ci if (!set_scene_state(setup, SETUP_ACTIVE, __FUNCTION__)) 1503bf215546Sopenharmony_ci return FALSE; 1504bf215546Sopenharmony_ci 1505bf215546Sopenharmony_ci if (!setup->scene) 1506bf215546Sopenharmony_ci return FALSE; 1507bf215546Sopenharmony_ci 1508bf215546Sopenharmony_ci return try_update_scene_state(setup); 1509bf215546Sopenharmony_ci } 1510bf215546Sopenharmony_ci 1511bf215546Sopenharmony_ci return TRUE; 1512bf215546Sopenharmony_ci} 1513bf215546Sopenharmony_ci 1514bf215546Sopenharmony_ci 1515bf215546Sopenharmony_ci 1516bf215546Sopenharmony_ci/* Only caller is lp_setup_vbuf_destroy() 1517bf215546Sopenharmony_ci */ 1518bf215546Sopenharmony_civoid 1519bf215546Sopenharmony_cilp_setup_destroy(struct lp_setup_context *setup) 1520bf215546Sopenharmony_ci{ 1521bf215546Sopenharmony_ci lp_setup_reset(setup); 1522bf215546Sopenharmony_ci 1523bf215546Sopenharmony_ci util_unreference_framebuffer_state(&setup->fb); 1524bf215546Sopenharmony_ci 1525bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) { 1526bf215546Sopenharmony_ci struct pipe_resource **res_ptr = &setup->fs.current_tex[i]; 1527bf215546Sopenharmony_ci if (*res_ptr) 1528bf215546Sopenharmony_ci llvmpipe_resource_unmap(*res_ptr, 0, 0); 1529bf215546Sopenharmony_ci pipe_resource_reference(res_ptr, NULL); 1530bf215546Sopenharmony_ci } 1531bf215546Sopenharmony_ci 1532bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->constants); i++) { 1533bf215546Sopenharmony_ci pipe_resource_reference(&setup->constants[i].current.buffer, NULL); 1534bf215546Sopenharmony_ci } 1535bf215546Sopenharmony_ci 1536bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(setup->ssbos); i++) { 1537bf215546Sopenharmony_ci pipe_resource_reference(&setup->ssbos[i].current.buffer, NULL); 1538bf215546Sopenharmony_ci } 1539bf215546Sopenharmony_ci 1540bf215546Sopenharmony_ci /* free the scenes in the 'empty' queue */ 1541bf215546Sopenharmony_ci for (unsigned i = 0; i < setup->num_active_scenes; i++) { 1542bf215546Sopenharmony_ci struct lp_scene *scene = setup->scenes[i]; 1543bf215546Sopenharmony_ci 1544bf215546Sopenharmony_ci if (scene->fence) 1545bf215546Sopenharmony_ci lp_fence_wait(scene->fence); 1546bf215546Sopenharmony_ci 1547bf215546Sopenharmony_ci lp_scene_destroy(scene); 1548bf215546Sopenharmony_ci } 1549bf215546Sopenharmony_ci 1550bf215546Sopenharmony_ci LP_DBG(DEBUG_SETUP, "number of scenes used: %d\n", setup->num_active_scenes); 1551bf215546Sopenharmony_ci slab_destroy(&setup->scene_slab); 1552bf215546Sopenharmony_ci 1553bf215546Sopenharmony_ci FREE(setup); 1554bf215546Sopenharmony_ci} 1555bf215546Sopenharmony_ci 1556bf215546Sopenharmony_ci 1557bf215546Sopenharmony_ci/** 1558bf215546Sopenharmony_ci * Create a new primitive tiling engine. Plug it into the backend of 1559bf215546Sopenharmony_ci * the draw module. Currently also creates a rasterizer to use with 1560bf215546Sopenharmony_ci * it. 1561bf215546Sopenharmony_ci */ 1562bf215546Sopenharmony_cistruct lp_setup_context * 1563bf215546Sopenharmony_cilp_setup_create(struct pipe_context *pipe, 1564bf215546Sopenharmony_ci struct draw_context *draw) 1565bf215546Sopenharmony_ci{ 1566bf215546Sopenharmony_ci struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 1567bf215546Sopenharmony_ci struct lp_setup_context *setup = CALLOC_STRUCT(lp_setup_context); 1568bf215546Sopenharmony_ci if (!setup) { 1569bf215546Sopenharmony_ci goto no_setup; 1570bf215546Sopenharmony_ci } 1571bf215546Sopenharmony_ci 1572bf215546Sopenharmony_ci lp_setup_init_vbuf(setup); 1573bf215546Sopenharmony_ci 1574bf215546Sopenharmony_ci /* Used only in update_state(): 1575bf215546Sopenharmony_ci */ 1576bf215546Sopenharmony_ci setup->pipe = pipe; 1577bf215546Sopenharmony_ci 1578bf215546Sopenharmony_ci setup->num_threads = screen->num_threads; 1579bf215546Sopenharmony_ci setup->vbuf = draw_vbuf_stage(draw, &setup->base); 1580bf215546Sopenharmony_ci if (!setup->vbuf) { 1581bf215546Sopenharmony_ci goto no_vbuf; 1582bf215546Sopenharmony_ci } 1583bf215546Sopenharmony_ci 1584bf215546Sopenharmony_ci draw_set_rasterize_stage(draw, setup->vbuf); 1585bf215546Sopenharmony_ci draw_set_render(draw, &setup->base); 1586bf215546Sopenharmony_ci 1587bf215546Sopenharmony_ci slab_create(&setup->scene_slab, 1588bf215546Sopenharmony_ci sizeof(struct lp_scene), 1589bf215546Sopenharmony_ci INITIAL_SCENES); 1590bf215546Sopenharmony_ci /* create just one scene for starting point */ 1591bf215546Sopenharmony_ci setup->scenes[0] = lp_scene_create(setup); 1592bf215546Sopenharmony_ci if (!setup->scenes[0]) { 1593bf215546Sopenharmony_ci goto no_scenes; 1594bf215546Sopenharmony_ci } 1595bf215546Sopenharmony_ci setup->num_active_scenes++; 1596bf215546Sopenharmony_ci 1597bf215546Sopenharmony_ci setup->triangle = first_triangle; 1598bf215546Sopenharmony_ci setup->line = first_line; 1599bf215546Sopenharmony_ci setup->point = first_point; 1600bf215546Sopenharmony_ci 1601bf215546Sopenharmony_ci setup->dirty = ~0; 1602bf215546Sopenharmony_ci 1603bf215546Sopenharmony_ci /* Initialize empty default fb correctly, so the rect is empty */ 1604bf215546Sopenharmony_ci setup->framebuffer.x1 = -1; 1605bf215546Sopenharmony_ci setup->framebuffer.y1 = -1; 1606bf215546Sopenharmony_ci 1607bf215546Sopenharmony_ci return setup; 1608bf215546Sopenharmony_ci 1609bf215546Sopenharmony_cino_scenes: 1610bf215546Sopenharmony_ci for (unsigned i = 0; i < MAX_SCENES; i++) { 1611bf215546Sopenharmony_ci if (setup->scenes[i]) { 1612bf215546Sopenharmony_ci lp_scene_destroy(setup->scenes[i]); 1613bf215546Sopenharmony_ci } 1614bf215546Sopenharmony_ci } 1615bf215546Sopenharmony_ci 1616bf215546Sopenharmony_ci setup->vbuf->destroy(setup->vbuf); 1617bf215546Sopenharmony_cino_vbuf: 1618bf215546Sopenharmony_ci FREE(setup); 1619bf215546Sopenharmony_cino_setup: 1620bf215546Sopenharmony_ci return NULL; 1621bf215546Sopenharmony_ci} 1622bf215546Sopenharmony_ci 1623bf215546Sopenharmony_ci 1624bf215546Sopenharmony_ci/** 1625bf215546Sopenharmony_ci * Put a BeginQuery command into all bins. 1626bf215546Sopenharmony_ci */ 1627bf215546Sopenharmony_civoid 1628bf215546Sopenharmony_cilp_setup_begin_query(struct lp_setup_context *setup, 1629bf215546Sopenharmony_ci struct llvmpipe_query *pq) 1630bf215546Sopenharmony_ci{ 1631bf215546Sopenharmony_ci set_scene_state(setup, SETUP_ACTIVE, "begin_query"); 1632bf215546Sopenharmony_ci 1633bf215546Sopenharmony_ci if (!(pq->type == PIPE_QUERY_OCCLUSION_COUNTER || 1634bf215546Sopenharmony_ci pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || 1635bf215546Sopenharmony_ci pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || 1636bf215546Sopenharmony_ci pq->type == PIPE_QUERY_PIPELINE_STATISTICS || 1637bf215546Sopenharmony_ci pq->type == PIPE_QUERY_TIME_ELAPSED)) 1638bf215546Sopenharmony_ci return; 1639bf215546Sopenharmony_ci 1640bf215546Sopenharmony_ci /* init the query to its beginning state */ 1641bf215546Sopenharmony_ci assert(setup->active_binned_queries < LP_MAX_ACTIVE_BINNED_QUERIES); 1642bf215546Sopenharmony_ci /* exceeding list size so just ignore the query */ 1643bf215546Sopenharmony_ci if (setup->active_binned_queries >= LP_MAX_ACTIVE_BINNED_QUERIES) { 1644bf215546Sopenharmony_ci return; 1645bf215546Sopenharmony_ci } 1646bf215546Sopenharmony_ci assert(setup->active_queries[setup->active_binned_queries] == NULL); 1647bf215546Sopenharmony_ci setup->active_queries[setup->active_binned_queries] = pq; 1648bf215546Sopenharmony_ci setup->active_binned_queries++; 1649bf215546Sopenharmony_ci 1650bf215546Sopenharmony_ci assert(setup->scene); 1651bf215546Sopenharmony_ci if (setup->scene) { 1652bf215546Sopenharmony_ci if (!lp_scene_bin_everywhere(setup->scene, 1653bf215546Sopenharmony_ci LP_RAST_OP_BEGIN_QUERY, 1654bf215546Sopenharmony_ci lp_rast_arg_query(pq))) { 1655bf215546Sopenharmony_ci 1656bf215546Sopenharmony_ci if (!lp_setup_flush_and_restart(setup)) 1657bf215546Sopenharmony_ci return; 1658bf215546Sopenharmony_ci 1659bf215546Sopenharmony_ci if (!lp_scene_bin_everywhere(setup->scene, 1660bf215546Sopenharmony_ci LP_RAST_OP_BEGIN_QUERY, 1661bf215546Sopenharmony_ci lp_rast_arg_query(pq))) { 1662bf215546Sopenharmony_ci return; 1663bf215546Sopenharmony_ci } 1664bf215546Sopenharmony_ci } 1665bf215546Sopenharmony_ci setup->scene->had_queries |= TRUE; 1666bf215546Sopenharmony_ci } 1667bf215546Sopenharmony_ci} 1668bf215546Sopenharmony_ci 1669bf215546Sopenharmony_ci 1670bf215546Sopenharmony_ci/** 1671bf215546Sopenharmony_ci * Put an EndQuery command into all bins. 1672bf215546Sopenharmony_ci */ 1673bf215546Sopenharmony_civoid 1674bf215546Sopenharmony_cilp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) 1675bf215546Sopenharmony_ci{ 1676bf215546Sopenharmony_ci set_scene_state(setup, SETUP_ACTIVE, "end_query"); 1677bf215546Sopenharmony_ci 1678bf215546Sopenharmony_ci assert(setup->scene); 1679bf215546Sopenharmony_ci if (setup->scene) { 1680bf215546Sopenharmony_ci /* pq->fence should be the fence of the *last* scene which 1681bf215546Sopenharmony_ci * contributed to the query result. 1682bf215546Sopenharmony_ci */ 1683bf215546Sopenharmony_ci lp_fence_reference(&pq->fence, setup->scene->fence); 1684bf215546Sopenharmony_ci 1685bf215546Sopenharmony_ci if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || 1686bf215546Sopenharmony_ci pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || 1687bf215546Sopenharmony_ci pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || 1688bf215546Sopenharmony_ci pq->type == PIPE_QUERY_PIPELINE_STATISTICS || 1689bf215546Sopenharmony_ci pq->type == PIPE_QUERY_TIMESTAMP || 1690bf215546Sopenharmony_ci pq->type == PIPE_QUERY_TIME_ELAPSED) { 1691bf215546Sopenharmony_ci if (pq->type == PIPE_QUERY_TIMESTAMP && 1692bf215546Sopenharmony_ci !(setup->scene->tiles_x | setup->scene->tiles_y)) { 1693bf215546Sopenharmony_ci /* 1694bf215546Sopenharmony_ci * If there's a zero width/height framebuffer, there's no bins and 1695bf215546Sopenharmony_ci * hence no rast task is ever run. So fill in something here instead. 1696bf215546Sopenharmony_ci */ 1697bf215546Sopenharmony_ci pq->end[0] = os_time_get_nano(); 1698bf215546Sopenharmony_ci } 1699bf215546Sopenharmony_ci 1700bf215546Sopenharmony_ci if (!lp_scene_bin_everywhere(setup->scene, 1701bf215546Sopenharmony_ci LP_RAST_OP_END_QUERY, 1702bf215546Sopenharmony_ci lp_rast_arg_query(pq))) { 1703bf215546Sopenharmony_ci if (!lp_setup_flush_and_restart(setup)) 1704bf215546Sopenharmony_ci goto fail; 1705bf215546Sopenharmony_ci 1706bf215546Sopenharmony_ci if (!lp_scene_bin_everywhere(setup->scene, 1707bf215546Sopenharmony_ci LP_RAST_OP_END_QUERY, 1708bf215546Sopenharmony_ci lp_rast_arg_query(pq))) { 1709bf215546Sopenharmony_ci goto fail; 1710bf215546Sopenharmony_ci } 1711bf215546Sopenharmony_ci } 1712bf215546Sopenharmony_ci setup->scene->had_queries |= TRUE; 1713bf215546Sopenharmony_ci } 1714bf215546Sopenharmony_ci } 1715bf215546Sopenharmony_ci else { 1716bf215546Sopenharmony_ci struct llvmpipe_screen *screen = llvmpipe_screen(setup->pipe->screen); 1717bf215546Sopenharmony_ci mtx_lock(&screen->rast_mutex); 1718bf215546Sopenharmony_ci lp_rast_fence(screen->rast, &pq->fence); 1719bf215546Sopenharmony_ci mtx_unlock(&screen->rast_mutex); 1720bf215546Sopenharmony_ci } 1721bf215546Sopenharmony_ci 1722bf215546Sopenharmony_cifail: 1723bf215546Sopenharmony_ci /* Need to do this now not earlier since it still needs to be marked as 1724bf215546Sopenharmony_ci * active when binning it would cause a flush. 1725bf215546Sopenharmony_ci */ 1726bf215546Sopenharmony_ci if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || 1727bf215546Sopenharmony_ci pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || 1728bf215546Sopenharmony_ci pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || 1729bf215546Sopenharmony_ci pq->type == PIPE_QUERY_PIPELINE_STATISTICS || 1730bf215546Sopenharmony_ci pq->type == PIPE_QUERY_TIME_ELAPSED) { 1731bf215546Sopenharmony_ci unsigned i; 1732bf215546Sopenharmony_ci 1733bf215546Sopenharmony_ci /* remove from active binned query list */ 1734bf215546Sopenharmony_ci for (i = 0; i < setup->active_binned_queries; i++) { 1735bf215546Sopenharmony_ci if (setup->active_queries[i] == pq) 1736bf215546Sopenharmony_ci break; 1737bf215546Sopenharmony_ci } 1738bf215546Sopenharmony_ci assert(i < setup->active_binned_queries); 1739bf215546Sopenharmony_ci if (i == setup->active_binned_queries) 1740bf215546Sopenharmony_ci return; 1741bf215546Sopenharmony_ci setup->active_binned_queries--; 1742bf215546Sopenharmony_ci setup->active_queries[i] = setup->active_queries[setup->active_binned_queries]; 1743bf215546Sopenharmony_ci setup->active_queries[setup->active_binned_queries] = NULL; 1744bf215546Sopenharmony_ci } 1745bf215546Sopenharmony_ci} 1746bf215546Sopenharmony_ci 1747bf215546Sopenharmony_ci 1748bf215546Sopenharmony_ciboolean 1749bf215546Sopenharmony_cilp_setup_flush_and_restart(struct lp_setup_context *setup) 1750bf215546Sopenharmony_ci{ 1751bf215546Sopenharmony_ci if (0) debug_printf("%s\n", __FUNCTION__); 1752bf215546Sopenharmony_ci 1753bf215546Sopenharmony_ci assert(setup->state == SETUP_ACTIVE); 1754bf215546Sopenharmony_ci 1755bf215546Sopenharmony_ci if (!set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__)) 1756bf215546Sopenharmony_ci return FALSE; 1757bf215546Sopenharmony_ci 1758bf215546Sopenharmony_ci if (!lp_setup_update_state(setup, TRUE)) 1759bf215546Sopenharmony_ci return FALSE; 1760bf215546Sopenharmony_ci 1761bf215546Sopenharmony_ci return TRUE; 1762bf215546Sopenharmony_ci} 1763bf215546Sopenharmony_ci 1764bf215546Sopenharmony_ci 1765bf215546Sopenharmony_civoid 1766bf215546Sopenharmony_cilp_setup_add_scissor_planes(const struct u_rect *scissor, 1767bf215546Sopenharmony_ci struct lp_rast_plane *plane_s, 1768bf215546Sopenharmony_ci boolean s_planes[4], bool multisample) 1769bf215546Sopenharmony_ci{ 1770bf215546Sopenharmony_ci /* 1771bf215546Sopenharmony_ci * When rasterizing scissored tris, use the intersection of the 1772bf215546Sopenharmony_ci * triangle bounding box and the scissor rect to generate the 1773bf215546Sopenharmony_ci * scissor planes. 1774bf215546Sopenharmony_ci * 1775bf215546Sopenharmony_ci * This permits us to cut off the triangle "tails" that are present 1776bf215546Sopenharmony_ci * in the intermediate recursive levels caused when two of the 1777bf215546Sopenharmony_ci * triangles edges don't diverge quickly enough to trivially reject 1778bf215546Sopenharmony_ci * exterior blocks from the triangle. 1779bf215546Sopenharmony_ci * 1780bf215546Sopenharmony_ci * It's not really clear if it's worth worrying about these tails, 1781bf215546Sopenharmony_ci * but since we generate the planes for each scissored tri, it's 1782bf215546Sopenharmony_ci * free to trim them in this case. 1783bf215546Sopenharmony_ci * 1784bf215546Sopenharmony_ci * Note that otherwise, the scissor planes only vary in 'C' value, 1785bf215546Sopenharmony_ci * and even then only on state-changes. Could alternatively store 1786bf215546Sopenharmony_ci * these planes elsewhere. 1787bf215546Sopenharmony_ci * (Or only store the c value together with a bit indicating which 1788bf215546Sopenharmony_ci * scissor edge this is, so rasterization would treat them differently 1789bf215546Sopenharmony_ci * (easier to evaluate) to ordinary planes.) 1790bf215546Sopenharmony_ci */ 1791bf215546Sopenharmony_ci int adj = multisample ? 127 : 0; 1792bf215546Sopenharmony_ci if (s_planes[0]) { 1793bf215546Sopenharmony_ci int x0 = scissor->x0 - 1; 1794bf215546Sopenharmony_ci plane_s->dcdx = ~0U << 8; 1795bf215546Sopenharmony_ci plane_s->dcdy = 0; 1796bf215546Sopenharmony_ci plane_s->c = x0 << 8; 1797bf215546Sopenharmony_ci plane_s->c += adj; 1798bf215546Sopenharmony_ci plane_s->c = -plane_s->c; /* flip sign */ 1799bf215546Sopenharmony_ci plane_s->eo = 1 << 8; 1800bf215546Sopenharmony_ci plane_s++; 1801bf215546Sopenharmony_ci } 1802bf215546Sopenharmony_ci if (s_planes[1]) { 1803bf215546Sopenharmony_ci int x1 = scissor->x1; 1804bf215546Sopenharmony_ci plane_s->dcdx = 1 << 8; 1805bf215546Sopenharmony_ci plane_s->dcdy = 0; 1806bf215546Sopenharmony_ci plane_s->c = x1 << 8; 1807bf215546Sopenharmony_ci plane_s->c += 127 + adj; 1808bf215546Sopenharmony_ci plane_s->eo = 0 << 8; 1809bf215546Sopenharmony_ci plane_s++; 1810bf215546Sopenharmony_ci } 1811bf215546Sopenharmony_ci if (s_planes[2]) { 1812bf215546Sopenharmony_ci int y0 = scissor->y0 - 1; 1813bf215546Sopenharmony_ci plane_s->dcdx = 0; 1814bf215546Sopenharmony_ci plane_s->dcdy = 1 << 8; 1815bf215546Sopenharmony_ci plane_s->c = y0 << 8; 1816bf215546Sopenharmony_ci plane_s->c += adj; 1817bf215546Sopenharmony_ci plane_s->c = -plane_s->c; /* flip sign */ 1818bf215546Sopenharmony_ci plane_s->eo = 1 << 8; 1819bf215546Sopenharmony_ci plane_s++; 1820bf215546Sopenharmony_ci } 1821bf215546Sopenharmony_ci if (s_planes[3]) { 1822bf215546Sopenharmony_ci int y1 = scissor->y1; 1823bf215546Sopenharmony_ci plane_s->dcdx = 0; 1824bf215546Sopenharmony_ci plane_s->dcdy = ~0U << 8; 1825bf215546Sopenharmony_ci plane_s->c = y1 << 8; 1826bf215546Sopenharmony_ci plane_s->c += 127 + adj; 1827bf215546Sopenharmony_ci plane_s->eo = 0; 1828bf215546Sopenharmony_ci plane_s++; 1829bf215546Sopenharmony_ci } 1830bf215546Sopenharmony_ci} 1831