1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2010-2021 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 THE AUTHORS 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 * Setup/binning code for screen-aligned quads. 30bf215546Sopenharmony_ci */ 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "util/u_math.h" 33bf215546Sopenharmony_ci#include "util/u_memory.h" 34bf215546Sopenharmony_ci#include "lp_perf.h" 35bf215546Sopenharmony_ci#include "lp_setup_context.h" 36bf215546Sopenharmony_ci#include "lp_rast.h" 37bf215546Sopenharmony_ci#include "lp_state_fs.h" 38bf215546Sopenharmony_ci#include "lp_state_setup.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#define NUM_CHANNELS 4 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci#define UNDETERMINED_BLIT -1 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_cistatic inline int 47bf215546Sopenharmony_cisubpixel_snap(float a) 48bf215546Sopenharmony_ci{ 49bf215546Sopenharmony_ci return util_iround(FIXED_ONE * a); 50bf215546Sopenharmony_ci} 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic inline float 54bf215546Sopenharmony_cifixed_to_float(int a) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci return a * (1.0f / FIXED_ONE); 57bf215546Sopenharmony_ci} 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci/** 61bf215546Sopenharmony_ci * Alloc space for a new rectangle plus the input.a0/dadx/dady arrays 62bf215546Sopenharmony_ci * immediately after it. 63bf215546Sopenharmony_ci * The memory is allocated from the per-scene pool, not per-tile. 64bf215546Sopenharmony_ci * \param size returns number of bytes allocated 65bf215546Sopenharmony_ci * \param nr_inputs number of fragment shader inputs 66bf215546Sopenharmony_ci * \return pointer to rectangle space 67bf215546Sopenharmony_ci */ 68bf215546Sopenharmony_cistruct lp_rast_rectangle * 69bf215546Sopenharmony_cilp_setup_alloc_rectangle(struct lp_scene *scene, unsigned nr_inputs) 70bf215546Sopenharmony_ci{ 71bf215546Sopenharmony_ci unsigned input_array_sz = NUM_CHANNELS * (nr_inputs + 1) * sizeof(float); 72bf215546Sopenharmony_ci struct lp_rast_rectangle *rect; 73bf215546Sopenharmony_ci unsigned bytes = sizeof(*rect) + (3 * input_array_sz); 74bf215546Sopenharmony_ci rect = lp_scene_alloc_aligned(scene, bytes, 16); 75bf215546Sopenharmony_ci if (rect == NULL) 76bf215546Sopenharmony_ci return NULL; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci rect->inputs.stride = input_array_sz; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci return rect; 81bf215546Sopenharmony_ci} 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci/** 85bf215546Sopenharmony_ci * The rectangle covers the whole tile- shade whole tile. 86bf215546Sopenharmony_ci * XXX no rectangle/triangle dependencies in this file - share it with 87bf215546Sopenharmony_ci * the same code in lp_setup_tri.c 88bf215546Sopenharmony_ci * \param tx, ty the tile position in tiles, not pixels 89bf215546Sopenharmony_ci */ 90bf215546Sopenharmony_ciboolean 91bf215546Sopenharmony_cilp_setup_whole_tile(struct lp_setup_context *setup, 92bf215546Sopenharmony_ci const struct lp_rast_shader_inputs *inputs, 93bf215546Sopenharmony_ci int tx, int ty, boolean opaque) 94bf215546Sopenharmony_ci{ 95bf215546Sopenharmony_ci struct lp_scene *scene = setup->scene; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci LP_COUNT(nr_fully_covered_64); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci /* if variant is opaque and scissor doesn't effect the tile */ 100bf215546Sopenharmony_ci if (opaque) { 101bf215546Sopenharmony_ci /* Several things prevent this optimization from working: 102bf215546Sopenharmony_ci * - For layered rendering we can't determine if this covers the same 103bf215546Sopenharmony_ci * layer as previous rendering (or in case of clears those actually 104bf215546Sopenharmony_ci * always cover all layers so optimization is impossible). Need to use 105bf215546Sopenharmony_ci * fb_max_layer and not setup->layer_slot to determine this since even 106bf215546Sopenharmony_ci * if there's currently no slot assigned previous rendering could have 107bf215546Sopenharmony_ci * used one. 108bf215546Sopenharmony_ci * - If there were any Begin/End query commands in the scene then those 109bf215546Sopenharmony_ci * would get removed which would be very wrong. Furthermore, if queries 110bf215546Sopenharmony_ci * were just active we also can't do the optimization since to get 111bf215546Sopenharmony_ci * accurate query results we unfortunately need to execute the rendering 112bf215546Sopenharmony_ci * commands. 113bf215546Sopenharmony_ci */ 114bf215546Sopenharmony_ci if (!scene->fb.zsbuf && scene->fb_max_layer == 0 && 115bf215546Sopenharmony_ci !scene->had_queries) { 116bf215546Sopenharmony_ci /* 117bf215546Sopenharmony_ci * All previous rendering will be overwritten so reset the bin. 118bf215546Sopenharmony_ci */ 119bf215546Sopenharmony_ci lp_scene_bin_reset(scene, tx, ty); 120bf215546Sopenharmony_ci } 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci if (inputs->is_blit) { 123bf215546Sopenharmony_ci LP_COUNT(nr_blit_64); 124bf215546Sopenharmony_ci return lp_scene_bin_cmd_with_state(scene, tx, ty, 125bf215546Sopenharmony_ci setup->fs.stored, 126bf215546Sopenharmony_ci LP_RAST_OP_BLIT, 127bf215546Sopenharmony_ci lp_rast_arg_inputs(inputs)); 128bf215546Sopenharmony_ci } else { 129bf215546Sopenharmony_ci LP_COUNT(nr_shade_opaque_64); 130bf215546Sopenharmony_ci return lp_scene_bin_cmd_with_state(scene, tx, ty, 131bf215546Sopenharmony_ci setup->fs.stored, 132bf215546Sopenharmony_ci LP_RAST_OP_SHADE_TILE_OPAQUE, 133bf215546Sopenharmony_ci lp_rast_arg_inputs(inputs)); 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci } else { 136bf215546Sopenharmony_ci LP_COUNT(nr_shade_64); 137bf215546Sopenharmony_ci return lp_scene_bin_cmd_with_state(scene, tx, ty, 138bf215546Sopenharmony_ci setup->fs.stored, 139bf215546Sopenharmony_ci LP_RAST_OP_SHADE_TILE, 140bf215546Sopenharmony_ci lp_rast_arg_inputs(inputs)); 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci} 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ciboolean 146bf215546Sopenharmony_cilp_setup_is_blit(const struct lp_setup_context *setup, 147bf215546Sopenharmony_ci const struct lp_rast_shader_inputs *inputs) 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci const struct lp_fragment_shader_variant *variant = 150bf215546Sopenharmony_ci setup->fs.current.variant; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci if (variant->blit) { 153bf215546Sopenharmony_ci /* 154bf215546Sopenharmony_ci * Detect blits. 155bf215546Sopenharmony_ci */ 156bf215546Sopenharmony_ci const struct lp_jit_texture *texture = 157bf215546Sopenharmony_ci &setup->fs.current.jit_context.textures[0]; 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci /* XXX: dadx vs dady confusion below? 160bf215546Sopenharmony_ci */ 161bf215546Sopenharmony_ci const float dsdx = GET_DADX(inputs)[1][0] * texture->width; 162bf215546Sopenharmony_ci const float dsdy = GET_DADX(inputs)[1][1] * texture->width; 163bf215546Sopenharmony_ci const float dtdx = GET_DADY(inputs)[1][0] * texture->height; 164bf215546Sopenharmony_ci const float dtdy = GET_DADY(inputs)[1][1] * texture->height; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci /* 167bf215546Sopenharmony_ci * We don't need to check s0/t0 tolerances 168bf215546Sopenharmony_ci * as we establish as pre-condition that there is no 169bf215546Sopenharmony_ci * texture filtering. 170bf215546Sopenharmony_ci */ 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci ASSERTED struct lp_sampler_static_state *samp0 = lp_fs_variant_key_sampler_idx(&variant->key, 0); 173bf215546Sopenharmony_ci assert(samp0); 174bf215546Sopenharmony_ci assert(samp0->sampler_state.min_img_filter == PIPE_TEX_FILTER_NEAREST); 175bf215546Sopenharmony_ci assert(samp0->sampler_state.mag_img_filter == PIPE_TEX_FILTER_NEAREST); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci /* 178bf215546Sopenharmony_ci * Check for 1:1 match of texels to dest pixels 179bf215546Sopenharmony_ci */ 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci if (util_is_approx(dsdx, 1.0f, 1.0f/LP_MAX_WIDTH) && 182bf215546Sopenharmony_ci util_is_approx(dsdy, 0.0f, 1.0f/LP_MAX_HEIGHT) && 183bf215546Sopenharmony_ci util_is_approx(dtdx, 0.0f, 1.0f/LP_MAX_WIDTH) && 184bf215546Sopenharmony_ci util_is_approx(dtdy, 1.0f, 1.0f/LP_MAX_HEIGHT)) { 185bf215546Sopenharmony_ci return true; 186bf215546Sopenharmony_ci } else { 187bf215546Sopenharmony_ci#if 0 188bf215546Sopenharmony_ci debug_printf("dsdx = %f\n", dsdx); 189bf215546Sopenharmony_ci debug_printf("dsdy = %f\n", dsdy); 190bf215546Sopenharmony_ci debug_printf("dtdx = %f\n", dtdx); 191bf215546Sopenharmony_ci debug_printf("dtdy = %f\n", dtdy); 192bf215546Sopenharmony_ci debug_printf("\n"); 193bf215546Sopenharmony_ci#endif 194bf215546Sopenharmony_ci return FALSE; 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci return FALSE; 199bf215546Sopenharmony_ci} 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_cistatic inline void 203bf215546Sopenharmony_cipartial(struct lp_setup_context *setup, 204bf215546Sopenharmony_ci const struct lp_rast_rectangle *rect, 205bf215546Sopenharmony_ci boolean opaque, 206bf215546Sopenharmony_ci unsigned ix, unsigned iy, 207bf215546Sopenharmony_ci unsigned mask) // RECT_PLANE_x bits 208bf215546Sopenharmony_ci{ 209bf215546Sopenharmony_ci if (mask == 0) { 210bf215546Sopenharmony_ci assert(rect->box.x0 <= ix * TILE_SIZE); 211bf215546Sopenharmony_ci assert(rect->box.y0 <= iy * TILE_SIZE); 212bf215546Sopenharmony_ci assert(rect->box.x1 >= (ix+1) * TILE_SIZE - 1); 213bf215546Sopenharmony_ci assert(rect->box.y1 >= (iy+1) * TILE_SIZE - 1); 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci lp_setup_whole_tile(setup, &rect->inputs, ix, iy, opaque); 216bf215546Sopenharmony_ci } else { 217bf215546Sopenharmony_ci LP_COUNT(nr_partially_covered_64); 218bf215546Sopenharmony_ci lp_scene_bin_cmd_with_state(setup->scene, 219bf215546Sopenharmony_ci ix, iy, 220bf215546Sopenharmony_ci setup->fs.stored, 221bf215546Sopenharmony_ci LP_RAST_OP_RECTANGLE, 222bf215546Sopenharmony_ci lp_rast_arg_rectangle(rect)); 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci} 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci/** 228bf215546Sopenharmony_ci * Setup/bin a screen-aligned rect. 229bf215546Sopenharmony_ci * We need three corner vertices in order to correctly setup 230bf215546Sopenharmony_ci * interpolated parameters. We *could* get away with just the 231bf215546Sopenharmony_ci * diagonal vertices but it'd cause ugliness elsewhere. 232bf215546Sopenharmony_ci * 233bf215546Sopenharmony_ci * + -------v0 234bf215546Sopenharmony_ci * | | 235bf215546Sopenharmony_ci * v2 ------ v1 236bf215546Sopenharmony_ci * 237bf215546Sopenharmony_ci * By an unfortunate mixup between GL and D3D coordinate spaces, half 238bf215546Sopenharmony_ci * of this file talks about clockwise rectangles (which were CCW in GL 239bf215546Sopenharmony_ci * coordinate space), while the other half prefers to work with D3D 240bf215546Sopenharmony_ci * CCW rectangles. 241bf215546Sopenharmony_ci */ 242bf215546Sopenharmony_cistatic boolean 243bf215546Sopenharmony_citry_rect_cw(struct lp_setup_context *setup, 244bf215546Sopenharmony_ci const float (*v0)[4], 245bf215546Sopenharmony_ci const float (*v1)[4], 246bf215546Sopenharmony_ci const float (*v2)[4], 247bf215546Sopenharmony_ci boolean frontfacing) 248bf215546Sopenharmony_ci{ 249bf215546Sopenharmony_ci const struct lp_fragment_shader_variant *variant = 250bf215546Sopenharmony_ci setup->fs.current.variant; 251bf215546Sopenharmony_ci const struct lp_setup_variant_key *key = &setup->setup.variant->key; 252bf215546Sopenharmony_ci struct lp_scene *scene = setup->scene; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci /* x/y positions in fixed point */ 255bf215546Sopenharmony_ci int x0 = subpixel_snap(v0[0][0] - setup->pixel_offset); 256bf215546Sopenharmony_ci int x1 = subpixel_snap(v1[0][0] - setup->pixel_offset); 257bf215546Sopenharmony_ci int x2 = subpixel_snap(v2[0][0] - setup->pixel_offset); 258bf215546Sopenharmony_ci int y0 = subpixel_snap(v0[0][1] - setup->pixel_offset); 259bf215546Sopenharmony_ci int y1 = subpixel_snap(v1[0][1] - setup->pixel_offset); 260bf215546Sopenharmony_ci int y2 = subpixel_snap(v2[0][1] - setup->pixel_offset); 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci LP_COUNT(nr_rects); 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci /* Cull clockwise rects without overflowing. 265bf215546Sopenharmony_ci */ 266bf215546Sopenharmony_ci const boolean cw = (x2 < x1) ^ (y0 < y2); 267bf215546Sopenharmony_ci if (cw) { 268bf215546Sopenharmony_ci LP_COUNT(nr_culled_rects); 269bf215546Sopenharmony_ci return TRUE; 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci const float (*pv)[4]; 273bf215546Sopenharmony_ci if (setup->flatshade_first) { 274bf215546Sopenharmony_ci pv = v0; 275bf215546Sopenharmony_ci } else { 276bf215546Sopenharmony_ci pv = v2; 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci unsigned viewport_index = 0; 280bf215546Sopenharmony_ci if (setup->viewport_index_slot > 0) { 281bf215546Sopenharmony_ci unsigned *udata = (unsigned*)pv[setup->viewport_index_slot]; 282bf215546Sopenharmony_ci viewport_index = lp_clamp_viewport_idx(*udata); 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci unsigned layer = 0; 286bf215546Sopenharmony_ci if (setup->layer_slot > 0) { 287bf215546Sopenharmony_ci layer = *(unsigned*)pv[setup->layer_slot]; 288bf215546Sopenharmony_ci layer = MIN2(layer, scene->fb_max_layer); 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci /* Bounding rectangle (in pixels) */ 292bf215546Sopenharmony_ci struct u_rect bbox; 293bf215546Sopenharmony_ci { 294bf215546Sopenharmony_ci /* Yes this is necessary to accurately calculate bounding boxes 295bf215546Sopenharmony_ci * with the two fill-conventions we support. GL (normally) ends 296bf215546Sopenharmony_ci * up needing a bottom-left fill convention, which requires 297bf215546Sopenharmony_ci * slightly different rounding. 298bf215546Sopenharmony_ci */ 299bf215546Sopenharmony_ci int adj = (setup->bottom_edge_rule != 0) ? 1 : 0; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci bbox.x0 = (MIN3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER; 302bf215546Sopenharmony_ci bbox.x1 = (MAX3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER; 303bf215546Sopenharmony_ci bbox.y0 = (MIN3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; 304bf215546Sopenharmony_ci bbox.y1 = (MAX3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci /* Inclusive coordinates: 307bf215546Sopenharmony_ci */ 308bf215546Sopenharmony_ci bbox.x1--; 309bf215546Sopenharmony_ci bbox.y1--; 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) { 313bf215546Sopenharmony_ci if (0) debug_printf("no intersection\n"); 314bf215546Sopenharmony_ci LP_COUNT(nr_culled_rects); 315bf215546Sopenharmony_ci return TRUE; 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci u_rect_find_intersection(&setup->draw_regions[viewport_index], &bbox); 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci struct lp_rast_rectangle *rect = 321bf215546Sopenharmony_ci lp_setup_alloc_rectangle(scene, key->num_inputs); 322bf215546Sopenharmony_ci if (!rect) 323bf215546Sopenharmony_ci return FALSE; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci#ifdef DEBUG 326bf215546Sopenharmony_ci rect->v[0][0] = v0[0][0]; 327bf215546Sopenharmony_ci rect->v[0][1] = v0[0][1]; 328bf215546Sopenharmony_ci rect->v[1][0] = v1[0][0]; 329bf215546Sopenharmony_ci rect->v[1][1] = v1[0][1]; 330bf215546Sopenharmony_ci#endif 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci rect->box.x0 = bbox.x0; 333bf215546Sopenharmony_ci rect->box.x1 = bbox.x1; 334bf215546Sopenharmony_ci rect->box.y0 = bbox.y0; 335bf215546Sopenharmony_ci rect->box.y1 = bbox.y1; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci /* Setup parameter interpolants: 338bf215546Sopenharmony_ci */ 339bf215546Sopenharmony_ci setup->setup.variant->jit_function(v0, 340bf215546Sopenharmony_ci v1, 341bf215546Sopenharmony_ci v2, 342bf215546Sopenharmony_ci frontfacing, 343bf215546Sopenharmony_ci GET_A0(&rect->inputs), 344bf215546Sopenharmony_ci GET_DADX(&rect->inputs), 345bf215546Sopenharmony_ci GET_DADY(&rect->inputs), 346bf215546Sopenharmony_ci &setup->setup.variant->key); 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci rect->inputs.frontfacing = frontfacing; 349bf215546Sopenharmony_ci rect->inputs.disable = FALSE; 350bf215546Sopenharmony_ci rect->inputs.is_blit = lp_setup_is_blit(setup, &rect->inputs); 351bf215546Sopenharmony_ci rect->inputs.layer = layer; 352bf215546Sopenharmony_ci rect->inputs.viewport_index = viewport_index; 353bf215546Sopenharmony_ci rect->inputs.view_index = setup->view_index; 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci return lp_setup_bin_rectangle(setup, rect, variant->opaque); 356bf215546Sopenharmony_ci} 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ciboolean 360bf215546Sopenharmony_cilp_setup_bin_rectangle(struct lp_setup_context *setup, 361bf215546Sopenharmony_ci struct lp_rast_rectangle *rect, 362bf215546Sopenharmony_ci boolean opaque) 363bf215546Sopenharmony_ci{ 364bf215546Sopenharmony_ci struct lp_scene *scene = setup->scene; 365bf215546Sopenharmony_ci unsigned left_mask = 0; 366bf215546Sopenharmony_ci unsigned right_mask = 0; 367bf215546Sopenharmony_ci unsigned top_mask = 0; 368bf215546Sopenharmony_ci unsigned bottom_mask = 0; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci /* 371bf215546Sopenharmony_ci * All fields of 'rect' are now set. The remaining code here is 372bf215546Sopenharmony_ci * concerned with binning. 373bf215546Sopenharmony_ci */ 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci /* Convert to inclusive tile coordinates: 376bf215546Sopenharmony_ci */ 377bf215546Sopenharmony_ci const unsigned ix0 = rect->box.x0 / TILE_SIZE; 378bf215546Sopenharmony_ci const unsigned iy0 = rect->box.y0 / TILE_SIZE; 379bf215546Sopenharmony_ci const unsigned ix1 = rect->box.x1 / TILE_SIZE; 380bf215546Sopenharmony_ci const unsigned iy1 = rect->box.y1 / TILE_SIZE; 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci /* 383bf215546Sopenharmony_ci * Clamp to framebuffer size 384bf215546Sopenharmony_ci */ 385bf215546Sopenharmony_ci assert(ix0 == MAX2(ix0, 0)); 386bf215546Sopenharmony_ci assert(iy0 == MAX2(iy0, 0)); 387bf215546Sopenharmony_ci assert(ix1 == MIN2(ix1, scene->tiles_x - 1)); 388bf215546Sopenharmony_ci assert(iy1 == MIN2(iy1, scene->tiles_y - 1)); 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci if (ix0 * TILE_SIZE != rect->box.x0) 391bf215546Sopenharmony_ci left_mask = RECT_PLANE_LEFT; 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci if (ix1 * TILE_SIZE + TILE_SIZE - 1 != rect->box.x1) 394bf215546Sopenharmony_ci right_mask = RECT_PLANE_RIGHT; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci if (iy0 * TILE_SIZE != rect->box.y0) 397bf215546Sopenharmony_ci top_mask = RECT_PLANE_TOP; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci if (iy1 * TILE_SIZE + TILE_SIZE - 1 != rect->box.y1) 400bf215546Sopenharmony_ci bottom_mask = RECT_PLANE_BOTTOM; 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci /* Determine which tile(s) intersect the rectangle's bounding box 403bf215546Sopenharmony_ci */ 404bf215546Sopenharmony_ci if (iy0 == iy1 && ix0 == ix1) { 405bf215546Sopenharmony_ci partial(setup, rect, opaque, ix0, iy0, 406bf215546Sopenharmony_ci (left_mask | right_mask | top_mask | bottom_mask)); 407bf215546Sopenharmony_ci } else if (ix0 == ix1) { 408bf215546Sopenharmony_ci unsigned mask = left_mask | right_mask; 409bf215546Sopenharmony_ci partial(setup, rect, opaque, ix0, iy0, mask | top_mask); 410bf215546Sopenharmony_ci for (unsigned i = iy0 + 1; i < iy1; i++) 411bf215546Sopenharmony_ci partial(setup, rect, opaque, ix0, i, mask); 412bf215546Sopenharmony_ci partial(setup, rect, opaque, ix0, iy1, mask | bottom_mask); 413bf215546Sopenharmony_ci } else if (iy0 == iy1) { 414bf215546Sopenharmony_ci unsigned mask = top_mask | bottom_mask; 415bf215546Sopenharmony_ci partial(setup, rect, opaque, ix0, iy0, mask | left_mask); 416bf215546Sopenharmony_ci for (unsigned i = ix0 + 1; i < ix1; i++) 417bf215546Sopenharmony_ci partial(setup, rect, opaque, i, iy0, mask); 418bf215546Sopenharmony_ci partial(setup, rect, opaque, ix1, iy0, mask | right_mask); 419bf215546Sopenharmony_ci } else { 420bf215546Sopenharmony_ci partial(setup, rect, opaque, ix0, iy0, left_mask | top_mask); 421bf215546Sopenharmony_ci partial(setup, rect, opaque, ix0, iy1, left_mask | bottom_mask); 422bf215546Sopenharmony_ci partial(setup, rect, opaque, ix1, iy0, right_mask | top_mask); 423bf215546Sopenharmony_ci partial(setup, rect, opaque, ix1, iy1, right_mask | bottom_mask); 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci /* Top/Bottom fringes 426bf215546Sopenharmony_ci */ 427bf215546Sopenharmony_ci for (unsigned i = ix0 + 1; i < ix1; i++) { 428bf215546Sopenharmony_ci partial(setup, rect, opaque, i, iy0, top_mask); 429bf215546Sopenharmony_ci partial(setup, rect, opaque, i, iy1, bottom_mask); 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci /* Left/Right fringes 433bf215546Sopenharmony_ci */ 434bf215546Sopenharmony_ci for (unsigned i = iy0 + 1; i < iy1; i++) { 435bf215546Sopenharmony_ci partial(setup, rect, opaque, ix0, i, left_mask); 436bf215546Sopenharmony_ci partial(setup, rect, opaque, ix1, i, right_mask); 437bf215546Sopenharmony_ci } 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci /* Full interior tiles 440bf215546Sopenharmony_ci */ 441bf215546Sopenharmony_ci for (unsigned j = iy0 + 1; j < iy1; j++) { 442bf215546Sopenharmony_ci for (unsigned i = ix0 + 1; i < ix1; i++) { 443bf215546Sopenharmony_ci lp_setup_whole_tile(setup, &rect->inputs, i, j, opaque); 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci /* Catch any out-of-memory which occurred during binning. Do this 449bf215546Sopenharmony_ci * once here rather than checking all the return values throughout. 450bf215546Sopenharmony_ci */ 451bf215546Sopenharmony_ci if (lp_scene_is_oom(scene)) { 452bf215546Sopenharmony_ci /* Disable rasterization of this partially-binned rectangle. 453bf215546Sopenharmony_ci * We'll flush this scene and re-bin the entire rectangle: 454bf215546Sopenharmony_ci */ 455bf215546Sopenharmony_ci rect->inputs.disable = TRUE; 456bf215546Sopenharmony_ci return FALSE; 457bf215546Sopenharmony_ci } 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci return TRUE; 460bf215546Sopenharmony_ci} 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_civoid 464bf215546Sopenharmony_cilp_rect_cw(struct lp_setup_context *setup, 465bf215546Sopenharmony_ci const float (*v0)[4], 466bf215546Sopenharmony_ci const float (*v1)[4], 467bf215546Sopenharmony_ci const float (*v2)[4], 468bf215546Sopenharmony_ci boolean frontfacing) 469bf215546Sopenharmony_ci{ 470bf215546Sopenharmony_ci if (!try_rect_cw(setup, v0, v1, v2, frontfacing)) { 471bf215546Sopenharmony_ci if (!lp_setup_flush_and_restart(setup)) 472bf215546Sopenharmony_ci return; 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci if (!try_rect_cw(setup, v0, v1, v2, frontfacing)) 475bf215546Sopenharmony_ci return; 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci} 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci/** 481bf215546Sopenharmony_ci * Take the six vertices for two triangles and try to determine if they 482bf215546Sopenharmony_ci * form a screen-aligned quad/rectangle. If so, draw the rect directly, 483bf215546Sopenharmony_ci * else, draw as two regular triangles. 484bf215546Sopenharmony_ci */ 485bf215546Sopenharmony_cistatic boolean 486bf215546Sopenharmony_cido_rect_ccw(struct lp_setup_context *setup, 487bf215546Sopenharmony_ci const float (*v0)[4], 488bf215546Sopenharmony_ci const float (*v1)[4], 489bf215546Sopenharmony_ci const float (*v2)[4], 490bf215546Sopenharmony_ci const float (*v3)[4], 491bf215546Sopenharmony_ci const float (*v4)[4], 492bf215546Sopenharmony_ci const float (*v5)[4], 493bf215546Sopenharmony_ci boolean front) 494bf215546Sopenharmony_ci{ 495bf215546Sopenharmony_ci const float (*rv0)[4], (*rv1)[4], (*rv2)[4], (*rv3)[4]; /* rect verts */ 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci#define SAME_POS(A, B) (A[0][0] == B[0][0] && \ 498bf215546Sopenharmony_ci A[0][1] == B[0][1] && \ 499bf215546Sopenharmony_ci A[0][2] == B[0][2] && \ 500bf215546Sopenharmony_ci A[0][3] == B[0][3]) 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci /* Only need to consider CCW orientations. There are nine ways 503bf215546Sopenharmony_ci * that two counter-clockwise triangles can join up: 504bf215546Sopenharmony_ci */ 505bf215546Sopenharmony_ci if (SAME_POS(v0, v3)) { 506bf215546Sopenharmony_ci if (SAME_POS(v2, v4)) { 507bf215546Sopenharmony_ci /* 508bf215546Sopenharmony_ci * v5 v4/v2 509bf215546Sopenharmony_ci * +-----+ 510bf215546Sopenharmony_ci * | / | 511bf215546Sopenharmony_ci * | / | 512bf215546Sopenharmony_ci * | / | 513bf215546Sopenharmony_ci * +-----+ 514bf215546Sopenharmony_ci * v3/v0 v1 515bf215546Sopenharmony_ci */ 516bf215546Sopenharmony_ci rv0 = v5; 517bf215546Sopenharmony_ci rv1 = v0; 518bf215546Sopenharmony_ci rv2 = v1; 519bf215546Sopenharmony_ci rv3 = v2; 520bf215546Sopenharmony_ci } else if (SAME_POS(v1, v5)) { 521bf215546Sopenharmony_ci /* 522bf215546Sopenharmony_ci * v4 v3/v0 523bf215546Sopenharmony_ci * +-----+ 524bf215546Sopenharmony_ci * | / | 525bf215546Sopenharmony_ci * | / | 526bf215546Sopenharmony_ci * | / | 527bf215546Sopenharmony_ci * +-----+ 528bf215546Sopenharmony_ci * v5/v1 v2 529bf215546Sopenharmony_ci */ 530bf215546Sopenharmony_ci rv0 = v4; 531bf215546Sopenharmony_ci rv1 = v1; 532bf215546Sopenharmony_ci rv2 = v2; 533bf215546Sopenharmony_ci rv3 = v0; 534bf215546Sopenharmony_ci } else { 535bf215546Sopenharmony_ci goto emit_triangles; 536bf215546Sopenharmony_ci } 537bf215546Sopenharmony_ci } else if (SAME_POS(v0, v5)) { 538bf215546Sopenharmony_ci if (SAME_POS(v2, v3)) { 539bf215546Sopenharmony_ci /* 540bf215546Sopenharmony_ci * v4 v3/v2 541bf215546Sopenharmony_ci * +-----+ 542bf215546Sopenharmony_ci * | / | 543bf215546Sopenharmony_ci * | / | 544bf215546Sopenharmony_ci * | / | 545bf215546Sopenharmony_ci * +-----+ 546bf215546Sopenharmony_ci * v5/v0 v1 547bf215546Sopenharmony_ci */ 548bf215546Sopenharmony_ci rv0 = v4; 549bf215546Sopenharmony_ci rv1 = v0; 550bf215546Sopenharmony_ci rv2 = v1; 551bf215546Sopenharmony_ci rv3 = v2; 552bf215546Sopenharmony_ci } else if (SAME_POS(v1, v4)) { 553bf215546Sopenharmony_ci /* 554bf215546Sopenharmony_ci * v3 v5/v0 555bf215546Sopenharmony_ci * +-----+ 556bf215546Sopenharmony_ci * | / | 557bf215546Sopenharmony_ci * | / | 558bf215546Sopenharmony_ci * | / | 559bf215546Sopenharmony_ci * +-----+ 560bf215546Sopenharmony_ci * v4/v1 v2 561bf215546Sopenharmony_ci */ 562bf215546Sopenharmony_ci rv0 = v3; 563bf215546Sopenharmony_ci rv1 = v1; 564bf215546Sopenharmony_ci rv2 = v2; 565bf215546Sopenharmony_ci rv3 = v0; 566bf215546Sopenharmony_ci } else { 567bf215546Sopenharmony_ci goto emit_triangles; 568bf215546Sopenharmony_ci } 569bf215546Sopenharmony_ci } else if (SAME_POS(v0, v4)) { 570bf215546Sopenharmony_ci if (SAME_POS(v2, v5)) { 571bf215546Sopenharmony_ci /* 572bf215546Sopenharmony_ci * v3 v5/v2 573bf215546Sopenharmony_ci * +-----+ 574bf215546Sopenharmony_ci * | / | 575bf215546Sopenharmony_ci * | / | 576bf215546Sopenharmony_ci * | / | 577bf215546Sopenharmony_ci * +-----+ 578bf215546Sopenharmony_ci * v4/v0 v1 579bf215546Sopenharmony_ci */ 580bf215546Sopenharmony_ci rv0 = v3; 581bf215546Sopenharmony_ci rv1 = v0; 582bf215546Sopenharmony_ci rv2 = v1; 583bf215546Sopenharmony_ci rv3 = v2; 584bf215546Sopenharmony_ci } else if (SAME_POS(v1, v3)) { 585bf215546Sopenharmony_ci /* 586bf215546Sopenharmony_ci * v5 v4/v0 587bf215546Sopenharmony_ci * +-----+ 588bf215546Sopenharmony_ci * | / | 589bf215546Sopenharmony_ci * | / | 590bf215546Sopenharmony_ci * | / | 591bf215546Sopenharmony_ci * +-----+ 592bf215546Sopenharmony_ci * v3/v1 v2 593bf215546Sopenharmony_ci */ 594bf215546Sopenharmony_ci rv0 = v5; 595bf215546Sopenharmony_ci rv1 = v1; 596bf215546Sopenharmony_ci rv2 = v2; 597bf215546Sopenharmony_ci rv3 = v0; 598bf215546Sopenharmony_ci } else { 599bf215546Sopenharmony_ci goto emit_triangles; 600bf215546Sopenharmony_ci } 601bf215546Sopenharmony_ci } else if (SAME_POS(v2, v3)) { 602bf215546Sopenharmony_ci if (SAME_POS(v1, v4)) { 603bf215546Sopenharmony_ci /* 604bf215546Sopenharmony_ci * v5 v4/v1 605bf215546Sopenharmony_ci * +-----+ 606bf215546Sopenharmony_ci * | / | 607bf215546Sopenharmony_ci * | / | 608bf215546Sopenharmony_ci * | / | 609bf215546Sopenharmony_ci * +-----+ 610bf215546Sopenharmony_ci * v3/v2 v0 611bf215546Sopenharmony_ci */ 612bf215546Sopenharmony_ci rv0 = v5; 613bf215546Sopenharmony_ci rv1 = v2; 614bf215546Sopenharmony_ci rv2 = v0; 615bf215546Sopenharmony_ci rv3 = v1; 616bf215546Sopenharmony_ci } else { 617bf215546Sopenharmony_ci goto emit_triangles; 618bf215546Sopenharmony_ci } 619bf215546Sopenharmony_ci } else if (SAME_POS(v2, v5)) { 620bf215546Sopenharmony_ci if (SAME_POS(v1, v3)) { 621bf215546Sopenharmony_ci /* 622bf215546Sopenharmony_ci * v4 v3/v1 623bf215546Sopenharmony_ci * +-----+ 624bf215546Sopenharmony_ci * | / | 625bf215546Sopenharmony_ci * | / | 626bf215546Sopenharmony_ci * | / | 627bf215546Sopenharmony_ci * +-----+ 628bf215546Sopenharmony_ci * v5/v2 v0 629bf215546Sopenharmony_ci */ 630bf215546Sopenharmony_ci rv0 = v4; 631bf215546Sopenharmony_ci rv1 = v2; 632bf215546Sopenharmony_ci rv2 = v0; 633bf215546Sopenharmony_ci rv3 = v1; 634bf215546Sopenharmony_ci } else { 635bf215546Sopenharmony_ci goto emit_triangles; 636bf215546Sopenharmony_ci } 637bf215546Sopenharmony_ci } else if (SAME_POS(v2, v4)) { 638bf215546Sopenharmony_ci if (SAME_POS(v1, v5)) { 639bf215546Sopenharmony_ci /* 640bf215546Sopenharmony_ci * v3 v5/v1 641bf215546Sopenharmony_ci * +-----+ 642bf215546Sopenharmony_ci * | / | 643bf215546Sopenharmony_ci * | / | 644bf215546Sopenharmony_ci * | / | 645bf215546Sopenharmony_ci * +-----+ 646bf215546Sopenharmony_ci * v4/v2 v0 647bf215546Sopenharmony_ci */ 648bf215546Sopenharmony_ci rv0 = v3; 649bf215546Sopenharmony_ci rv1 = v2; 650bf215546Sopenharmony_ci rv2 = v0; 651bf215546Sopenharmony_ci rv3 = v1; 652bf215546Sopenharmony_ci } else { 653bf215546Sopenharmony_ci goto emit_triangles; 654bf215546Sopenharmony_ci } 655bf215546Sopenharmony_ci } else { 656bf215546Sopenharmony_ci goto emit_triangles; 657bf215546Sopenharmony_ci } 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ci#define SAME_X(A, B) (A[0][0] == B[0][0]) 660bf215546Sopenharmony_ci#define SAME_Y(A, B) (A[0][1] == B[0][1]) 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_ci /* The vertices are now counter clockwise, as such: 663bf215546Sopenharmony_ci * 664bf215546Sopenharmony_ci * rv0 -------rv3 665bf215546Sopenharmony_ci * | | 666bf215546Sopenharmony_ci * rv1 ------ rv2 667bf215546Sopenharmony_ci * 668bf215546Sopenharmony_ci * To render as a rectangle, 669bf215546Sopenharmony_ci * * The X values should be the same at v0, v1 and v2, v3. 670bf215546Sopenharmony_ci * * The Y values should be the same at v0, v3 and v1, v2. 671bf215546Sopenharmony_ci */ 672bf215546Sopenharmony_ci if (SAME_Y(rv0, rv1)) { 673bf215546Sopenharmony_ci const float (*tmp)[4]; 674bf215546Sopenharmony_ci tmp = rv0; 675bf215546Sopenharmony_ci rv0 = rv1; 676bf215546Sopenharmony_ci rv1 = rv2; 677bf215546Sopenharmony_ci rv2 = rv3; 678bf215546Sopenharmony_ci rv3 = tmp; 679bf215546Sopenharmony_ci } 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci if (SAME_X(rv0, rv1) && SAME_X(rv2, rv3) && 682bf215546Sopenharmony_ci SAME_Y(rv0, rv3) && SAME_Y(rv1, rv2)) { 683bf215546Sopenharmony_ci const struct lp_setup_variant_key *key = &setup->setup.variant->key; 684bf215546Sopenharmony_ci const unsigned n = key->num_inputs; 685bf215546Sopenharmony_ci unsigned i, j; 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci /* We have a rectangle. Check that the other attributes are 688bf215546Sopenharmony_ci * coplanar. 689bf215546Sopenharmony_ci */ 690bf215546Sopenharmony_ci for (i = 0; i < n; i++) { 691bf215546Sopenharmony_ci for (j = 0; j < 4; j++) { 692bf215546Sopenharmony_ci if (key->inputs[i].usage_mask & (1<<j)) { 693bf215546Sopenharmony_ci unsigned k = key->inputs[i].src_index; 694bf215546Sopenharmony_ci float dxdx1, dxdx2, dxdy1, dxdy2; 695bf215546Sopenharmony_ci dxdx1 = rv0[k][j] - rv3[k][j]; 696bf215546Sopenharmony_ci dxdx2 = rv1[k][j] - rv2[k][j]; 697bf215546Sopenharmony_ci dxdy1 = rv0[k][j] - rv1[k][j]; 698bf215546Sopenharmony_ci dxdy2 = rv3[k][j] - rv2[k][j]; 699bf215546Sopenharmony_ci if (dxdx1 != dxdx2 || 700bf215546Sopenharmony_ci dxdy1 != dxdy2) { 701bf215546Sopenharmony_ci goto emit_triangles; 702bf215546Sopenharmony_ci } 703bf215546Sopenharmony_ci } 704bf215546Sopenharmony_ci } 705bf215546Sopenharmony_ci } 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci /* Note we're changing to clockwise here. Fix this by reworking 708bf215546Sopenharmony_ci * lp_rect_cw to expect/operate on ccw rects. Note that 709bf215546Sopenharmony_ci * function was previously misnamed. 710bf215546Sopenharmony_ci */ 711bf215546Sopenharmony_ci lp_rect_cw(setup, rv0, rv2, rv1, front); 712bf215546Sopenharmony_ci return TRUE; 713bf215546Sopenharmony_ci } else { 714bf215546Sopenharmony_ci /* setup->quad(setup, rv0, rv1, rv2, rv3); */ 715bf215546Sopenharmony_ci } 716bf215546Sopenharmony_ci 717bf215546Sopenharmony_ciemit_triangles: 718bf215546Sopenharmony_ci return FALSE; 719bf215546Sopenharmony_ci} 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_cienum winding { 723bf215546Sopenharmony_ci WINDING_NONE = 0, 724bf215546Sopenharmony_ci WINDING_CCW, 725bf215546Sopenharmony_ci WINDING_CW 726bf215546Sopenharmony_ci}; 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_ci 729bf215546Sopenharmony_cistatic inline enum winding 730bf215546Sopenharmony_ciwinding(const float (*v0)[4], 731bf215546Sopenharmony_ci const float (*v1)[4], 732bf215546Sopenharmony_ci const float (*v2)[4]) 733bf215546Sopenharmony_ci{ 734bf215546Sopenharmony_ci /* edge vectors e = v0 - v2, f = v1 - v2 */ 735bf215546Sopenharmony_ci const float ex = v0[0][0] - v2[0][0]; 736bf215546Sopenharmony_ci const float ey = v0[0][1] - v2[0][1]; 737bf215546Sopenharmony_ci const float fx = v1[0][0] - v2[0][0]; 738bf215546Sopenharmony_ci const float fy = v1[0][1] - v2[0][1]; 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci /* det = cross(e,f).z */ 741bf215546Sopenharmony_ci const float det = ex * fy - ey * fx; 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci if (det < 0.0f) 744bf215546Sopenharmony_ci return WINDING_CCW; 745bf215546Sopenharmony_ci else if (det > 0.0f) 746bf215546Sopenharmony_ci return WINDING_CW; 747bf215546Sopenharmony_ci else 748bf215546Sopenharmony_ci return WINDING_NONE; 749bf215546Sopenharmony_ci} 750bf215546Sopenharmony_ci 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_cistatic boolean 753bf215546Sopenharmony_cisetup_rect_cw(struct lp_setup_context *setup, 754bf215546Sopenharmony_ci const float (*v0)[4], 755bf215546Sopenharmony_ci const float (*v1)[4], 756bf215546Sopenharmony_ci const float (*v2)[4], 757bf215546Sopenharmony_ci const float (*v3)[4], 758bf215546Sopenharmony_ci const float (*v4)[4], 759bf215546Sopenharmony_ci const float (*v5)[4]) 760bf215546Sopenharmony_ci{ 761bf215546Sopenharmony_ci enum winding winding0 = winding(v0, v1, v2); 762bf215546Sopenharmony_ci enum winding winding1 = winding(v3, v4, v5); 763bf215546Sopenharmony_ci 764bf215546Sopenharmony_ci if (winding0 == WINDING_CW && 765bf215546Sopenharmony_ci winding1 == WINDING_CW) { 766bf215546Sopenharmony_ci return do_rect_ccw(setup, v0, v2, v1, v3, v5, v4, !setup->ccw_is_frontface); 767bf215546Sopenharmony_ci } else if (winding0 == WINDING_CW) { 768bf215546Sopenharmony_ci setup->triangle(setup, v0, v1, v2); 769bf215546Sopenharmony_ci return TRUE; 770bf215546Sopenharmony_ci } else if (winding1 == WINDING_CW) { 771bf215546Sopenharmony_ci setup->triangle(setup, v3, v4, v5); 772bf215546Sopenharmony_ci return TRUE; 773bf215546Sopenharmony_ci } else { 774bf215546Sopenharmony_ci return TRUE; 775bf215546Sopenharmony_ci } 776bf215546Sopenharmony_ci} 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci 779bf215546Sopenharmony_cistatic boolean 780bf215546Sopenharmony_cisetup_rect_ccw(struct lp_setup_context *setup, 781bf215546Sopenharmony_ci const float (*v0)[4], 782bf215546Sopenharmony_ci const float (*v1)[4], 783bf215546Sopenharmony_ci const float (*v2)[4], 784bf215546Sopenharmony_ci const float (*v3)[4], 785bf215546Sopenharmony_ci const float (*v4)[4], 786bf215546Sopenharmony_ci const float (*v5)[4]) 787bf215546Sopenharmony_ci{ 788bf215546Sopenharmony_ci enum winding winding0 = winding(v0, v1, v2); 789bf215546Sopenharmony_ci enum winding winding1 = winding(v3, v4, v5); 790bf215546Sopenharmony_ci 791bf215546Sopenharmony_ci if (winding0 == WINDING_CCW && 792bf215546Sopenharmony_ci winding1 == WINDING_CCW) { 793bf215546Sopenharmony_ci return do_rect_ccw(setup, v0, v1, v2, v3, v4, v5, setup->ccw_is_frontface); 794bf215546Sopenharmony_ci } else if (winding0 == WINDING_CCW) { 795bf215546Sopenharmony_ci setup->triangle(setup, v0, v1, v2); 796bf215546Sopenharmony_ci return TRUE; 797bf215546Sopenharmony_ci } else if (winding1 == WINDING_CCW) { 798bf215546Sopenharmony_ci return FALSE; 799bf215546Sopenharmony_ci setup->triangle(setup, v3, v4, v5); 800bf215546Sopenharmony_ci return TRUE; 801bf215546Sopenharmony_ci } else { 802bf215546Sopenharmony_ci return TRUE; 803bf215546Sopenharmony_ci } 804bf215546Sopenharmony_ci} 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_cistatic boolean 808bf215546Sopenharmony_cisetup_rect_noop(struct lp_setup_context *setup, 809bf215546Sopenharmony_ci const float (*v0)[4], 810bf215546Sopenharmony_ci const float (*v1)[4], 811bf215546Sopenharmony_ci const float (*v2)[4], 812bf215546Sopenharmony_ci const float (*v3)[4], 813bf215546Sopenharmony_ci const float (*v4)[4], 814bf215546Sopenharmony_ci const float (*v5)[4]) 815bf215546Sopenharmony_ci{ 816bf215546Sopenharmony_ci return TRUE; 817bf215546Sopenharmony_ci} 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_cistatic boolean 821bf215546Sopenharmony_cisetup_rect_both(struct lp_setup_context *setup, 822bf215546Sopenharmony_ci const float (*v0)[4], 823bf215546Sopenharmony_ci const float (*v1)[4], 824bf215546Sopenharmony_ci const float (*v2)[4], 825bf215546Sopenharmony_ci const float (*v3)[4], 826bf215546Sopenharmony_ci const float (*v4)[4], 827bf215546Sopenharmony_ci const float (*v5)[4]) 828bf215546Sopenharmony_ci{ 829bf215546Sopenharmony_ci enum winding winding0 = winding(v0, v1, v2); 830bf215546Sopenharmony_ci enum winding winding1 = winding(v3, v4, v5); 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci if (winding0 != winding1) { 833bf215546Sopenharmony_ci /* If we knew that the "front" parameter wasn't going to be 834bf215546Sopenharmony_ci * referenced, could rearrange one of the two triangles such 835bf215546Sopenharmony_ci * that they were both CCW. Aero actually does send mixed 836bf215546Sopenharmony_ci * CW/CCW rectangles under some circumstances, but we catch them 837bf215546Sopenharmony_ci * explicitly. 838bf215546Sopenharmony_ci */ 839bf215546Sopenharmony_ci return FALSE; 840bf215546Sopenharmony_ci } else if (winding0 == WINDING_CCW) { 841bf215546Sopenharmony_ci return do_rect_ccw(setup, v0, v1, v2, v3, v4, v5, setup->ccw_is_frontface); 842bf215546Sopenharmony_ci } else if (winding0 == WINDING_CW) { 843bf215546Sopenharmony_ci return do_rect_ccw(setup, v0, v2, v1, v3, v5, v4, !setup->ccw_is_frontface); 844bf215546Sopenharmony_ci } else { 845bf215546Sopenharmony_ci return TRUE; 846bf215546Sopenharmony_ci } 847bf215546Sopenharmony_ci} 848bf215546Sopenharmony_ci 849bf215546Sopenharmony_ci 850bf215546Sopenharmony_civoid 851bf215546Sopenharmony_cilp_setup_choose_rect(struct lp_setup_context *setup) 852bf215546Sopenharmony_ci{ 853bf215546Sopenharmony_ci if (setup->rasterizer_discard) { 854bf215546Sopenharmony_ci setup->rect = setup_rect_noop; 855bf215546Sopenharmony_ci return; 856bf215546Sopenharmony_ci } 857bf215546Sopenharmony_ci 858bf215546Sopenharmony_ci switch (setup->cullmode) { 859bf215546Sopenharmony_ci case PIPE_FACE_NONE: 860bf215546Sopenharmony_ci setup->rect = setup_rect_both; 861bf215546Sopenharmony_ci break; 862bf215546Sopenharmony_ci case PIPE_FACE_BACK: 863bf215546Sopenharmony_ci setup->rect = setup->ccw_is_frontface ? setup_rect_ccw : setup_rect_cw; 864bf215546Sopenharmony_ci break; 865bf215546Sopenharmony_ci case PIPE_FACE_FRONT: 866bf215546Sopenharmony_ci setup->rect = setup->ccw_is_frontface ? setup_rect_cw : setup_rect_ccw; 867bf215546Sopenharmony_ci break; 868bf215546Sopenharmony_ci default: 869bf215546Sopenharmony_ci setup->rect = setup_rect_noop; 870bf215546Sopenharmony_ci break; 871bf215546Sopenharmony_ci } 872bf215546Sopenharmony_ci} 873