draw_pt_vsplit.c revision 3733da31e8b4405b65e1b6ca3b6599ecc5af5fe7
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.9 4 * 5 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. 6 * Copyright (C) 2010 LunarG Inc. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 * DEALINGS IN THE SOFTWARE. 25 */ 26 27#include "util/u_math.h" 28#include "util/u_memory.h" 29 30#include "draw/draw_context.h" 31#include "draw/draw_private.h" 32#include "draw/draw_pt.h" 33 34#define SEGMENT_SIZE 1024 35#define MAP_SIZE 256 36 37struct vsplit_frontend { 38 struct draw_pt_front_end base; 39 struct draw_context *draw; 40 41 unsigned prim; 42 43 struct draw_pt_middle_end *middle; 44 45 unsigned max_vertices; 46 ushort segment_size; 47 48 /* buffers for splitting */ 49 unsigned fetch_elts[SEGMENT_SIZE]; 50 ushort draw_elts[SEGMENT_SIZE]; 51 ushort identity_draw_elts[SEGMENT_SIZE]; 52 53 struct { 54 /* map a fetch element to a draw element */ 55 unsigned fetches[MAP_SIZE]; 56 ushort draws[MAP_SIZE]; 57 boolean has_max_fetch; 58 59 ushort num_fetch_elts; 60 ushort num_draw_elts; 61 } cache; 62}; 63 64 65static void 66vsplit_clear_cache(struct vsplit_frontend *vsplit) 67{ 68 memset(vsplit->cache.fetches, 0xff, sizeof(vsplit->cache.fetches)); 69 vsplit->cache.has_max_fetch = FALSE; 70 vsplit->cache.num_fetch_elts = 0; 71 vsplit->cache.num_draw_elts = 0; 72} 73 74static void 75vsplit_flush_cache(struct vsplit_frontend *vsplit, unsigned flags) 76{ 77 vsplit->middle->run(vsplit->middle, 78 vsplit->fetch_elts, vsplit->cache.num_fetch_elts, 79 vsplit->draw_elts, vsplit->cache.num_draw_elts, flags); 80} 81 82/** 83 * Add a fetch element and add it to the draw elements. 84 */ 85static INLINE void 86vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch) 87{ 88 struct draw_context *draw = vsplit->draw; 89 unsigned hash; 90 91 fetch = MIN2(fetch, draw->pt.max_index); 92 93 hash = fetch % MAP_SIZE; 94 95 if (vsplit->cache.fetches[hash] != fetch) { 96 /* update cache */ 97 vsplit->cache.fetches[hash] = fetch; 98 vsplit->cache.draws[hash] = vsplit->cache.num_fetch_elts; 99 100 /* add fetch */ 101 assert(vsplit->cache.num_fetch_elts < vsplit->segment_size); 102 vsplit->fetch_elts[vsplit->cache.num_fetch_elts++] = fetch; 103 } 104 105 vsplit->draw_elts[vsplit->cache.num_draw_elts++] = vsplit->cache.draws[hash]; 106} 107 108 109/** 110 * Add a fetch element and add it to the draw elements. The fetch element is 111 * in full range (uint). 112 */ 113static INLINE void 114vsplit_add_cache_uint(struct vsplit_frontend *vsplit, unsigned fetch) 115{ 116 /* special care for 0xffffffff */ 117 if (fetch == 0xffffffff && !vsplit->cache.has_max_fetch) { 118 unsigned hash = fetch % MAP_SIZE; 119 vsplit->cache.fetches[hash] = fetch - 1; /* force update */ 120 vsplit->cache.has_max_fetch = TRUE; 121 } 122 123 vsplit_add_cache(vsplit, fetch); 124} 125 126 127#define FUNC vsplit_run_linear 128#include "draw_pt_vsplit_tmp.h" 129 130#define FUNC vsplit_run_ubyte 131#define ELT_TYPE ubyte 132#define ADD_CACHE(vsplit, fetch) vsplit_add_cache(vsplit, fetch) 133#include "draw_pt_vsplit_tmp.h" 134 135#define FUNC vsplit_run_ushort 136#define ELT_TYPE ushort 137#define ADD_CACHE(vsplit, fetch) vsplit_add_cache(vsplit, fetch) 138#include "draw_pt_vsplit_tmp.h" 139 140#define FUNC vsplit_run_uint 141#define ELT_TYPE uint 142#define ADD_CACHE(vsplit, fetch) vsplit_add_cache_uint(vsplit, fetch) 143#include "draw_pt_vsplit_tmp.h" 144 145 146static void vsplit_prepare(struct draw_pt_front_end *frontend, 147 unsigned in_prim, 148 struct draw_pt_middle_end *middle, 149 unsigned opt) 150{ 151 struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; 152 153 switch (vsplit->draw->pt.user.eltSize) { 154 case 0: 155 vsplit->base.run = vsplit_run_linear; 156 break; 157 case 1: 158 vsplit->base.run = vsplit_run_ubyte; 159 break; 160 case 2: 161 vsplit->base.run = vsplit_run_ushort; 162 break; 163 case 4: 164 vsplit->base.run = vsplit_run_uint; 165 break; 166 default: 167 assert(0); 168 break; 169 } 170 171 /* split only */ 172 vsplit->prim = in_prim; 173 174 vsplit->middle = middle; 175 middle->prepare(middle, vsplit->prim, opt, &vsplit->max_vertices); 176 177 vsplit->segment_size = MIN2(SEGMENT_SIZE, vsplit->max_vertices); 178} 179 180 181static void vsplit_finish(struct draw_pt_front_end *frontend) 182{ 183 struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; 184 vsplit->middle->finish(vsplit->middle); 185 vsplit->middle = NULL; 186} 187 188 189static void vsplit_destroy(struct draw_pt_front_end *frontend) 190{ 191 FREE(frontend); 192} 193 194 195struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw) 196{ 197 struct vsplit_frontend *vsplit = CALLOC_STRUCT(vsplit_frontend); 198 ushort i; 199 200 if (!vsplit) 201 return NULL; 202 203 vsplit->base.prepare = vsplit_prepare; 204 vsplit->base.run = NULL; 205 vsplit->base.finish = vsplit_finish; 206 vsplit->base.destroy = vsplit_destroy; 207 vsplit->draw = draw; 208 209 for (i = 0; i < SEGMENT_SIZE; i++) 210 vsplit->identity_draw_elts[i] = i; 211 212 return &vsplit->base; 213} 214