1df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen/* 2df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Copyright © 2012 Intel Corporation 3df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * 4df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Permission is hereby granted, free of charge, to any person obtaining a 5df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * copy of this software and associated documentation files (the "Software"), 6df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * to deal in the Software without restriction, including without limitation 7df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * and/or sell copies of the Software, and to permit persons to whom the 9df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Software is furnished to do so, subject to the following conditions: 10df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * 11df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * The above copyright notice and this permission notice (including the next 12df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * paragraph) shall be included in all copies or substantial portions of the 13df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Software. 14df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * 15df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * IN THE SOFTWARE. 22df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * 23df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Authors: 24df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Jordan Justen <jordan.l.justen@intel.com> 25df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * 26df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen */ 27df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 28df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen#include "main/imports.h" 29df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen#include "main/bufferobj.h" 30df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 31df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen#include "brw_context.h" 32b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke#include "brw_defines.h" 33df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen#include "brw_draw.h" 34df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 35b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke#include "intel_batchbuffer.h" 36b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke 37df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen/** 38dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * Check if the hardware's cut index support can handle the primitive 39dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * restart index value. 40dc501452534e6e004acf3206a581232971c00cd0Jordan Justen */ 41dc501452534e6e004acf3206a581232971c00cd0Jordan Justenstatic bool 42dc501452534e6e004acf3206a581232971c00cd0Jordan Justencan_cut_index_handle_restart_index(struct gl_context *ctx, 43dc501452534e6e004acf3206a581232971c00cd0Jordan Justen const struct _mesa_index_buffer *ib) 44dc501452534e6e004acf3206a581232971c00cd0Jordan Justen{ 45b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke struct intel_context *intel = intel_context(ctx); 46b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke 47b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke /* Haswell supports an arbitrary cut index. */ 48b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke if (intel->is_haswell) 49b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke return true; 50b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke 51dc501452534e6e004acf3206a581232971c00cd0Jordan Justen bool cut_index_will_work; 52dc501452534e6e004acf3206a581232971c00cd0Jordan Justen 53dc501452534e6e004acf3206a581232971c00cd0Jordan Justen switch (ib->type) { 54dc501452534e6e004acf3206a581232971c00cd0Jordan Justen case GL_UNSIGNED_BYTE: 55dc501452534e6e004acf3206a581232971c00cd0Jordan Justen cut_index_will_work = (ctx->Array.RestartIndex & 0xff) == 0xff; 56dc501452534e6e004acf3206a581232971c00cd0Jordan Justen break; 57dc501452534e6e004acf3206a581232971c00cd0Jordan Justen case GL_UNSIGNED_SHORT: 58dc501452534e6e004acf3206a581232971c00cd0Jordan Justen cut_index_will_work = (ctx->Array.RestartIndex & 0xffff) == 0xffff; 59dc501452534e6e004acf3206a581232971c00cd0Jordan Justen break; 60dc501452534e6e004acf3206a581232971c00cd0Jordan Justen case GL_UNSIGNED_INT: 61dc501452534e6e004acf3206a581232971c00cd0Jordan Justen cut_index_will_work = ctx->Array.RestartIndex == 0xffffffff; 62dc501452534e6e004acf3206a581232971c00cd0Jordan Justen break; 63dc501452534e6e004acf3206a581232971c00cd0Jordan Justen default: 64dc501452534e6e004acf3206a581232971c00cd0Jordan Justen cut_index_will_work = false; 65dc501452534e6e004acf3206a581232971c00cd0Jordan Justen assert(0); 66dc501452534e6e004acf3206a581232971c00cd0Jordan Justen } 67dc501452534e6e004acf3206a581232971c00cd0Jordan Justen 68dc501452534e6e004acf3206a581232971c00cd0Jordan Justen return cut_index_will_work; 69dc501452534e6e004acf3206a581232971c00cd0Jordan Justen} 70dc501452534e6e004acf3206a581232971c00cd0Jordan Justen 71dc501452534e6e004acf3206a581232971c00cd0Jordan Justen/** 72dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * Check if the hardware's cut index support can handle the primitive 73dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * restart case. 74dc501452534e6e004acf3206a581232971c00cd0Jordan Justen */ 75dc501452534e6e004acf3206a581232971c00cd0Jordan Justenstatic bool 76dc501452534e6e004acf3206a581232971c00cd0Jordan Justencan_cut_index_handle_prims(struct gl_context *ctx, 77dc501452534e6e004acf3206a581232971c00cd0Jordan Justen const struct _mesa_prim *prim, 78dc501452534e6e004acf3206a581232971c00cd0Jordan Justen GLuint nr_prims, 79dc501452534e6e004acf3206a581232971c00cd0Jordan Justen const struct _mesa_index_buffer *ib) 80dc501452534e6e004acf3206a581232971c00cd0Jordan Justen{ 818aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen struct brw_context *brw = brw_context(ctx); 828aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen 838aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen if (brw->sol.counting_primitives_generated || 848aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen brw->sol.counting_primitives_written) { 858aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen /* Counting primitives generated in hardware is not currently 868aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen * supported, so take the software path. We need to investigate 878aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen * the *_PRIMITIVES_COUNT registers to allow this to be handled 888aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen * entirely in hardware. 898aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen */ 908aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen return false; 918aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen } 928aa78c104a6fa9497cba558b54c41f6f2292bd74Jordan Justen 93dc501452534e6e004acf3206a581232971c00cd0Jordan Justen if (!can_cut_index_handle_restart_index(ctx, ib)) { 94dc501452534e6e004acf3206a581232971c00cd0Jordan Justen /* The primitive restart index can't be handled, so take 95dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * the software path 96dc501452534e6e004acf3206a581232971c00cd0Jordan Justen */ 97dc501452534e6e004acf3206a581232971c00cd0Jordan Justen return false; 98dc501452534e6e004acf3206a581232971c00cd0Jordan Justen } 99dc501452534e6e004acf3206a581232971c00cd0Jordan Justen 100dc501452534e6e004acf3206a581232971c00cd0Jordan Justen for ( ; nr_prims > 0; nr_prims--) { 101dc501452534e6e004acf3206a581232971c00cd0Jordan Justen switch(prim->mode) { 102dc501452534e6e004acf3206a581232971c00cd0Jordan Justen case GL_POINTS: 103dc501452534e6e004acf3206a581232971c00cd0Jordan Justen case GL_LINES: 104dc501452534e6e004acf3206a581232971c00cd0Jordan Justen case GL_LINE_STRIP: 105dc501452534e6e004acf3206a581232971c00cd0Jordan Justen case GL_TRIANGLES: 106dc501452534e6e004acf3206a581232971c00cd0Jordan Justen case GL_TRIANGLE_STRIP: 107dc501452534e6e004acf3206a581232971c00cd0Jordan Justen /* Cut index supports these primitive types */ 108dc501452534e6e004acf3206a581232971c00cd0Jordan Justen break; 109dc501452534e6e004acf3206a581232971c00cd0Jordan Justen default: 110dc501452534e6e004acf3206a581232971c00cd0Jordan Justen /* Cut index does not support these primitive types */ 111dc501452534e6e004acf3206a581232971c00cd0Jordan Justen //case GL_LINE_LOOP: 112dc501452534e6e004acf3206a581232971c00cd0Jordan Justen //case GL_TRIANGLE_FAN: 113dc501452534e6e004acf3206a581232971c00cd0Jordan Justen //case GL_QUADS: 114dc501452534e6e004acf3206a581232971c00cd0Jordan Justen //case GL_QUAD_STRIP: 115dc501452534e6e004acf3206a581232971c00cd0Jordan Justen //case GL_POLYGON: 116dc501452534e6e004acf3206a581232971c00cd0Jordan Justen return false; 117dc501452534e6e004acf3206a581232971c00cd0Jordan Justen } 118dc501452534e6e004acf3206a581232971c00cd0Jordan Justen } 119dc501452534e6e004acf3206a581232971c00cd0Jordan Justen 120dc501452534e6e004acf3206a581232971c00cd0Jordan Justen return true; 121dc501452534e6e004acf3206a581232971c00cd0Jordan Justen} 122dc501452534e6e004acf3206a581232971c00cd0Jordan Justen 123dc501452534e6e004acf3206a581232971c00cd0Jordan Justen/** 124df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * Check if primitive restart is enabled, and if so, handle it properly. 125df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * 126df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * In some cases the support will be handled in software. When available 127df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * hardware will handle primitive restart. 128df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen */ 129df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan JustenGLboolean 130df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justenbrw_handle_primitive_restart(struct gl_context *ctx, 131df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen const struct _mesa_prim *prim, 132df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen GLuint nr_prims, 133df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen const struct _mesa_index_buffer *ib) 134df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen{ 135df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen struct brw_context *brw = brw_context(ctx); 136df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 137df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen /* We only need to handle cases where there is an index buffer. */ 138df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen if (ib == NULL) { 139df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen return GL_FALSE; 140df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen } 141df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 142df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen /* If the driver has requested software handling of primitive restarts, 143df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * then the VBO module has already taken care of things, and we can 144df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * just draw as normal. 145df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen */ 146df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen if (ctx->Const.PrimitiveRestartInSoftware) { 147df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen return GL_FALSE; 148df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen } 149df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 150df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen /* If we have set the in_progress flag, then we are in the middle 151df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * of handling the primitive restart draw. 152df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen */ 153df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen if (brw->prim_restart.in_progress) { 154df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen return GL_FALSE; 155df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen } 156df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 157df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen /* If PrimitiveRestart is not enabled, then we aren't concerned about 158df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * handling this draw. 159df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen */ 160df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen if (!(ctx->Array.PrimitiveRestart)) { 161df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen return GL_FALSE; 162df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen } 163df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 164df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen /* Signal that we are in the process of handling the 165df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen * primitive restart draw 166df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen */ 167df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen brw->prim_restart.in_progress = true; 168df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 169dc501452534e6e004acf3206a581232971c00cd0Jordan Justen if (can_cut_index_handle_prims(ctx, prim, nr_prims, ib)) { 170dc501452534e6e004acf3206a581232971c00cd0Jordan Justen /* Cut index should work for primitive restart, so use it 171dc501452534e6e004acf3206a581232971c00cd0Jordan Justen */ 172dc501452534e6e004acf3206a581232971c00cd0Jordan Justen brw->prim_restart.enable_cut_index = true; 173dc501452534e6e004acf3206a581232971c00cd0Jordan Justen brw_draw_prims(ctx, prim, nr_prims, ib, GL_FALSE, -1, -1, NULL); 174dc501452534e6e004acf3206a581232971c00cd0Jordan Justen brw->prim_restart.enable_cut_index = false; 175dc501452534e6e004acf3206a581232971c00cd0Jordan Justen } else { 176dc501452534e6e004acf3206a581232971c00cd0Jordan Justen /* Not all the primitive draw modes are supported by the cut index, 177dc501452534e6e004acf3206a581232971c00cd0Jordan Justen * so take the software path 178dc501452534e6e004acf3206a581232971c00cd0Jordan Justen */ 179dc501452534e6e004acf3206a581232971c00cd0Jordan Justen vbo_sw_primitive_restart(ctx, prim, nr_prims, ib); 180dc501452534e6e004acf3206a581232971c00cd0Jordan Justen } 181df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 182df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen brw->prim_restart.in_progress = false; 183df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 184df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen /* The primitive restart draw was completed, so return true. */ 185df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen return GL_TRUE; 186df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen} 187df7d1323de08274c816a8e5fab7e99b6f00f4fa3Jordan Justen 188b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunkestatic void 189b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunkehaswell_upload_cut_index(struct brw_context *brw) 190b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke{ 191b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke struct intel_context *intel = &brw->intel; 192b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke struct gl_context *ctx = &intel->ctx; 193b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke 194b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke /* Don't trigger on Ivybridge */ 195b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke if (!intel->is_haswell) 196b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke return; 197b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke 198b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke const unsigned cut_index_setting = 199b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke ctx->Array.PrimitiveRestart ? HSW_CUT_INDEX_ENABLE : 0; 200b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke 201b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke BEGIN_BATCH(2); 202b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke OUT_BATCH(_3DSTATE_VF << 16 | cut_index_setting | (2 - 2)); 203b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke OUT_BATCH(ctx->Array.RestartIndex); 204b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke ADVANCE_BATCH(); 205b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke} 206b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke 207b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunkeconst struct brw_tracked_state haswell_cut_index = { 208b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke .dirty = { 209b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke .mesa = _NEW_TRANSFORM, 210b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke .brw = 0, 211b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke .cache = 0, 212b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke }, 213b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke .emit = haswell_upload_cut_index, 214b922999a404322a1034c4f96c21acae860483bb0Kenneth Graunke}; 215