1 /* 2 * Copyright 2012 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Jordan Justen <jordan.l.justen (at) intel.com> 25 * 26 */ 27 28 #include "main/imports.h" 29 #include "main/bufferobj.h" 30 #include "main/varray.h" 31 #include "vbo/vbo.h" 32 33 #include "brw_context.h" 34 #include "brw_defines.h" 35 #include "brw_draw.h" 36 37 #include "intel_batchbuffer.h" 38 39 /** 40 * Check if the hardware's cut index support can handle the primitive 41 * restart index value (pre-Haswell only). 42 */ 43 static bool 44 can_cut_index_handle_restart_index(struct gl_context *ctx, 45 const struct _mesa_index_buffer *ib) 46 { 47 /* The FixedIndex variant means 0xFF, 0xFFFF, or 0xFFFFFFFF based on 48 * the index buffer type, which corresponds exactly to the hardware. 49 */ 50 if (ctx->Array.PrimitiveRestartFixedIndex) 51 return true; 52 53 bool cut_index_will_work; 54 55 switch (ib->index_size) { 56 case 1: 57 cut_index_will_work = ctx->Array.RestartIndex == 0xff; 58 break; 59 case 2: 60 cut_index_will_work = ctx->Array.RestartIndex == 0xffff; 61 break; 62 case 4: 63 cut_index_will_work = ctx->Array.RestartIndex == 0xffffffff; 64 break; 65 default: 66 unreachable("not reached"); 67 } 68 69 return cut_index_will_work; 70 } 71 72 /** 73 * Check if the hardware's cut index support can handle the primitive 74 * restart case. 75 */ 76 static bool 77 can_cut_index_handle_prims(struct gl_context *ctx, 78 const struct _mesa_prim *prim, 79 GLuint nr_prims, 80 const struct _mesa_index_buffer *ib) 81 { 82 struct brw_context *brw = brw_context(ctx); 83 const struct gen_device_info *devinfo = &brw->screen->devinfo; 84 85 /* Otherwise Haswell can do it all. */ 86 if (devinfo->gen >= 8 || devinfo->is_haswell) 87 return true; 88 89 if (!can_cut_index_handle_restart_index(ctx, ib)) { 90 /* The primitive restart index can't be handled, so take 91 * the software path 92 */ 93 return false; 94 } 95 96 for (unsigned i = 0; i < nr_prims; i++) { 97 switch (prim[i].mode) { 98 case GL_POINTS: 99 case GL_LINES: 100 case GL_LINE_STRIP: 101 case GL_TRIANGLES: 102 case GL_TRIANGLE_STRIP: 103 case GL_LINES_ADJACENCY: 104 case GL_LINE_STRIP_ADJACENCY: 105 case GL_TRIANGLES_ADJACENCY: 106 case GL_TRIANGLE_STRIP_ADJACENCY: 107 /* Cut index supports these primitive types */ 108 break; 109 default: 110 /* Cut index does not support these primitive types */ 111 //case GL_LINE_LOOP: 112 //case GL_TRIANGLE_FAN: 113 //case GL_QUADS: 114 //case GL_QUAD_STRIP: 115 //case GL_POLYGON: 116 return false; 117 } 118 } 119 120 return true; 121 } 122 123 /** 124 * Check if primitive restart is enabled, and if so, handle it properly. 125 * 126 * In some cases the support will be handled in software. When available 127 * hardware will handle primitive restart. 128 */ 129 GLboolean 130 brw_handle_primitive_restart(struct gl_context *ctx, 131 const struct _mesa_prim *prims, 132 GLuint nr_prims, 133 const struct _mesa_index_buffer *ib, 134 struct gl_buffer_object *indirect) 135 { 136 struct brw_context *brw = brw_context(ctx); 137 138 /* We only need to handle cases where there is an index buffer. */ 139 if (ib == NULL) { 140 return GL_FALSE; 141 } 142 143 /* If we have set the in_progress flag, then we are in the middle 144 * of handling the primitive restart draw. 145 */ 146 if (brw->prim_restart.in_progress) { 147 return GL_FALSE; 148 } 149 150 /* If PrimitiveRestart is not enabled, then we aren't concerned about 151 * handling this draw. 152 */ 153 if (!(ctx->Array._PrimitiveRestart)) { 154 return GL_FALSE; 155 } 156 157 /* Signal that we are in the process of handling the 158 * primitive restart draw 159 */ 160 brw->prim_restart.in_progress = true; 161 162 if (can_cut_index_handle_prims(ctx, prims, nr_prims, ib)) { 163 /* Cut index should work for primitive restart, so use it 164 */ 165 brw->prim_restart.enable_cut_index = true; 166 brw_draw_prims(ctx, prims, nr_prims, ib, GL_FALSE, -1, -1, NULL, 0, 167 indirect); 168 brw->prim_restart.enable_cut_index = false; 169 } else { 170 /* Not all the primitive draw modes are supported by the cut index, 171 * so take the software path 172 */ 173 vbo_sw_primitive_restart(ctx, prims, nr_prims, ib, indirect); 174 } 175 176 brw->prim_restart.in_progress = false; 177 178 /* The primitive restart draw was completed, so return true. */ 179 return GL_TRUE; 180 } 181