1 /********************************************************** 2 * Copyright 2008-2009 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26 #include "util/u_inlines.h" 27 #include "util/u_upload_mgr.h" 28 #include "indices/u_indices.h" 29 30 #include "svga_cmd.h" 31 #include "svga_draw.h" 32 #include "svga_draw_private.h" 33 #include "svga_resource_buffer.h" 34 #include "svga_winsys.h" 35 #include "svga_context.h" 36 37 #include "svga_hw_reg.h" 38 39 40 static enum pipe_error 41 translate_indices( struct svga_hwtnl *hwtnl, 42 struct pipe_resource *src, 43 unsigned offset, 44 unsigned nr, 45 unsigned index_size, 46 u_translate_func translate, 47 struct pipe_resource **out_buf ) 48 { 49 struct pipe_context *pipe = &hwtnl->svga->pipe; 50 struct pipe_transfer *src_transfer = NULL; 51 struct pipe_transfer *dst_transfer = NULL; 52 unsigned size = index_size * nr; 53 const void *src_map = NULL; 54 struct pipe_resource *dst = NULL; 55 void *dst_map = NULL; 56 57 dst = pipe_buffer_create( pipe->screen, 58 PIPE_BIND_INDEX_BUFFER, 59 PIPE_USAGE_STATIC, 60 size ); 61 if (dst == NULL) 62 goto fail; 63 64 src_map = pipe_buffer_map( pipe, src, PIPE_TRANSFER_READ, &src_transfer ); 65 if (src_map == NULL) 66 goto fail; 67 68 dst_map = pipe_buffer_map( pipe, dst, PIPE_TRANSFER_WRITE, &dst_transfer ); 69 if (dst_map == NULL) 70 goto fail; 71 72 translate( (const char *)src_map + offset, 73 nr, 74 dst_map ); 75 76 pipe_buffer_unmap( pipe, src_transfer ); 77 pipe_buffer_unmap( pipe, dst_transfer ); 78 79 *out_buf = dst; 80 return PIPE_OK; 81 82 fail: 83 if (src_map) 84 pipe_buffer_unmap( pipe, src_transfer ); 85 86 if (dst_map) 87 pipe_buffer_unmap( pipe, dst_transfer ); 88 89 if (dst) 90 pipe->screen->resource_destroy( pipe->screen, dst ); 91 92 return PIPE_ERROR_OUT_OF_MEMORY; 93 } 94 95 96 97 98 99 enum pipe_error 100 svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl, 101 struct pipe_resource *index_buffer, 102 unsigned index_size, 103 int index_bias, 104 unsigned min_index, 105 unsigned max_index, 106 unsigned prim, 107 unsigned start, 108 unsigned count ) 109 { 110 struct pipe_resource *upload_buffer = NULL; 111 SVGA3dPrimitiveRange range; 112 unsigned hw_prim; 113 unsigned hw_count; 114 unsigned index_offset = start * index_size; 115 enum pipe_error ret = PIPE_OK; 116 117 hw_prim = svga_translate_prim(prim, count, &hw_count); 118 if (hw_count == 0) 119 goto done; 120 121 if (index_buffer && 122 svga_buffer_is_user_buffer(index_buffer)) 123 { 124 assert( index_buffer->width0 >= index_offset + count * index_size ); 125 126 ret = u_upload_buffer( hwtnl->upload_ib, 127 0, 128 index_offset, 129 count * index_size, 130 index_buffer, 131 &index_offset, 132 &upload_buffer); 133 if (ret != PIPE_OK) 134 goto done; 135 136 /* Don't need to worry about refcounting index_buffer as this is 137 * just a stack variable without a counted reference of its own. 138 * The caller holds the reference. 139 */ 140 index_buffer = upload_buffer; 141 } 142 143 range.primType = hw_prim; 144 range.primitiveCount = hw_count; 145 range.indexArray.offset = index_offset; 146 range.indexArray.stride = index_size; 147 range.indexWidth = index_size; 148 range.indexBias = index_bias; 149 150 ret = svga_hwtnl_prim( hwtnl, &range, min_index, max_index, index_buffer ); 151 if (ret != PIPE_OK) 152 goto done; 153 154 done: 155 if (upload_buffer) 156 pipe_resource_reference( &upload_buffer, NULL ); 157 158 return ret; 159 } 160 161 162 163 164 enum pipe_error 165 svga_hwtnl_draw_range_elements( struct svga_hwtnl *hwtnl, 166 struct pipe_resource *index_buffer, 167 unsigned index_size, 168 int index_bias, 169 unsigned min_index, 170 unsigned max_index, 171 unsigned prim, unsigned start, unsigned count) 172 { 173 unsigned gen_prim, gen_size, gen_nr, gen_type; 174 u_translate_func gen_func; 175 enum pipe_error ret = PIPE_OK; 176 177 if (hwtnl->api_fillmode != PIPE_POLYGON_MODE_FILL && 178 prim >= PIPE_PRIM_TRIANGLES) 179 { 180 gen_type = u_unfilled_translator( prim, 181 index_size, 182 count, 183 hwtnl->api_fillmode, 184 &gen_prim, 185 &gen_size, 186 &gen_nr, 187 &gen_func ); 188 } 189 else 190 { 191 gen_type = u_index_translator( svga_hw_prims, 192 prim, 193 index_size, 194 count, 195 hwtnl->api_pv, 196 hwtnl->hw_pv, 197 &gen_prim, 198 &gen_size, 199 &gen_nr, 200 &gen_func ); 201 } 202 203 204 if (gen_type == U_TRANSLATE_MEMCPY) { 205 /* No need for translation, just pass through to hardware: 206 */ 207 return svga_hwtnl_simple_draw_range_elements( hwtnl, index_buffer, 208 index_size, 209 index_bias, 210 min_index, 211 max_index, 212 gen_prim, start, count ); 213 } 214 else { 215 struct pipe_resource *gen_buf = NULL; 216 217 /* Need to allocate a new index buffer and run the translate 218 * func to populate it. Could potentially cache this translated 219 * index buffer with the original to avoid future 220 * re-translations. Not much point if we're just accelerating 221 * GL though, as index buffers are typically used only once 222 * there. 223 */ 224 ret = translate_indices( hwtnl, 225 index_buffer, 226 start * index_size, 227 gen_nr, 228 gen_size, 229 gen_func, 230 &gen_buf ); 231 if (ret != PIPE_OK) 232 goto done; 233 234 ret = svga_hwtnl_simple_draw_range_elements( hwtnl, 235 gen_buf, 236 gen_size, 237 index_bias, 238 min_index, 239 max_index, 240 gen_prim, 241 0, 242 gen_nr ); 243 if (ret != PIPE_OK) 244 goto done; 245 246 done: 247 if (gen_buf) 248 pipe_resource_reference( &gen_buf, NULL ); 249 250 return ret; 251 } 252 } 253 254 255 256 257 258