1/* 2 * Copyright © 2009 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 * Eric Anholt <eric@anholt.net> 25 * 26 */ 27 28#include "brw_context.h" 29#include "brw_state.h" 30#include "brw_defines.h" 31#include "brw_util.h" 32#include "intel_batchbuffer.h" 33#include "main/fbobject.h" 34#include "main/framebuffer.h" 35 36bool 37brw_is_drawing_points(const struct brw_context *brw) 38{ 39 /* Determine if the primitives *reaching the SF* are points */ 40 /* _NEW_POLYGON */ 41 if (brw->ctx.Polygon.FrontMode == GL_POINT || 42 brw->ctx.Polygon.BackMode == GL_POINT) { 43 return true; 44 } 45 46 if (brw->gs.base.prog_data) { 47 /* BRW_NEW_GS_PROG_DATA */ 48 return brw_gs_prog_data(brw->gs.base.prog_data)->output_topology == 49 _3DPRIM_POINTLIST; 50 } else if (brw->tes.base.prog_data) { 51 /* BRW_NEW_TES_PROG_DATA */ 52 return brw_tes_prog_data(brw->tes.base.prog_data)->output_topology == 53 BRW_TESS_OUTPUT_TOPOLOGY_POINT; 54 } else { 55 /* BRW_NEW_PRIMITIVE */ 56 return brw->primitive == _3DPRIM_POINTLIST; 57 } 58} 59 60bool 61brw_is_drawing_lines(const struct brw_context *brw) 62{ 63 /* Determine if the primitives *reaching the SF* are points */ 64 /* _NEW_POLYGON */ 65 if (brw->ctx.Polygon.FrontMode == GL_LINE || 66 brw->ctx.Polygon.BackMode == GL_LINE) { 67 return true; 68 } 69 70 if (brw->gs.base.prog_data) { 71 /* BRW_NEW_GS_PROG_DATA */ 72 return brw_gs_prog_data(brw->gs.base.prog_data)->output_topology == 73 _3DPRIM_LINESTRIP; 74 } else if (brw->tes.base.prog_data) { 75 /* BRW_NEW_TES_PROG_DATA */ 76 return brw_tes_prog_data(brw->tes.base.prog_data)->output_topology == 77 BRW_TESS_OUTPUT_TOPOLOGY_LINE; 78 } else { 79 /* BRW_NEW_PRIMITIVE */ 80 switch (brw->primitive) { 81 case _3DPRIM_LINELIST: 82 case _3DPRIM_LINESTRIP: 83 case _3DPRIM_LINELOOP: 84 return true; 85 } 86 } 87 return false; 88} 89 90static void 91upload_clip_state(struct brw_context *brw) 92{ 93 struct gl_context *ctx = &brw->ctx; 94 /* BRW_NEW_META_IN_PROGRESS */ 95 uint32_t dw1 = brw->meta_in_progress ? 0 : GEN6_CLIP_STATISTICS_ENABLE; 96 uint32_t dw2 = 0; 97 98 /* _NEW_BUFFERS */ 99 struct gl_framebuffer *fb = ctx->DrawBuffer; 100 101 /* BRW_NEW_FS_PROG_DATA */ 102 if (brw_wm_prog_data(brw->wm.base.prog_data)->barycentric_interp_modes & 103 BRW_BARYCENTRIC_NONPERSPECTIVE_BITS) { 104 dw2 |= GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; 105 } 106 107 /* BRW_NEW_VS_PROG_DATA */ 108 dw1 |= brw_vue_prog_data(brw->vs.base.prog_data)->cull_distance_mask; 109 110 if (brw->gen >= 7) 111 dw1 |= GEN7_CLIP_EARLY_CULL; 112 113 if (brw->gen == 7) { 114 /* _NEW_POLYGON */ 115 if (ctx->Polygon._FrontBit == _mesa_is_user_fbo(fb)) 116 dw1 |= GEN7_CLIP_WINDING_CCW; 117 118 if (ctx->Polygon.CullFlag) { 119 switch (ctx->Polygon.CullFaceMode) { 120 case GL_FRONT: 121 dw1 |= GEN7_CLIP_CULLMODE_FRONT; 122 break; 123 case GL_BACK: 124 dw1 |= GEN7_CLIP_CULLMODE_BACK; 125 break; 126 case GL_FRONT_AND_BACK: 127 dw1 |= GEN7_CLIP_CULLMODE_BOTH; 128 break; 129 default: 130 unreachable("Should not get here: invalid CullFlag"); 131 } 132 } else { 133 dw1 |= GEN7_CLIP_CULLMODE_NONE; 134 } 135 } 136 137 if (brw->gen < 8 && !ctx->Transform.DepthClamp) 138 dw2 |= GEN6_CLIP_Z_TEST; 139 140 /* _NEW_LIGHT */ 141 if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { 142 dw2 |= 143 (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | 144 (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | 145 (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); 146 } else { 147 dw2 |= 148 (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | 149 (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | 150 (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); 151 } 152 153 /* _NEW_TRANSFORM */ 154 dw2 |= (ctx->Transform.ClipPlanesEnabled << 155 GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT); 156 157 /* Have the hardware use the user clip distance clip test enable bitmask 158 * specified here in 3DSTATE_CLIP rather than the one in 3DSTATE_VS/DS/GS. 159 * We already listen to _NEW_TRANSFORM here, but the other atoms don't 160 * need to other than this. 161 */ 162 if (brw->gen >= 8) 163 dw1 |= GEN8_CLIP_FORCE_USER_CLIP_DISTANCE_BITMASK; 164 165 if (ctx->Transform.ClipDepthMode == GL_ZERO_TO_ONE) 166 dw2 |= GEN6_CLIP_API_D3D; 167 else 168 dw2 |= GEN6_CLIP_API_OGL; 169 170 dw2 |= GEN6_CLIP_GB_TEST; 171 172 /* BRW_NEW_VIEWPORT_COUNT */ 173 const unsigned viewport_count = brw->clip.viewport_count; 174 175 /* BRW_NEW_RASTERIZER_DISCARD */ 176 if (ctx->RasterDiscard) { 177 dw2 |= GEN6_CLIP_MODE_REJECT_ALL; 178 if (brw->gen == 6) { 179 perf_debug("Rasterizer discard is currently implemented via the " 180 "clipper; having the GS not write primitives would " 181 "likely be faster.\n"); 182 } 183 } 184 185 uint32_t enable; 186 if (brw->primitive == _3DPRIM_RECTLIST) 187 enable = 0; 188 else 189 enable = GEN6_CLIP_ENABLE; 190 191 /* _NEW_POLYGON, 192 * BRW_NEW_GEOMETRY_PROGRAM | BRW_NEW_TES_PROG_DATA | BRW_NEW_PRIMITIVE 193 */ 194 if (!brw_is_drawing_points(brw) && !brw_is_drawing_lines(brw)) 195 dw2 |= GEN6_CLIP_XY_TEST; 196 197 BEGIN_BATCH(4); 198 OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); 199 OUT_BATCH(dw1); 200 OUT_BATCH(enable | 201 GEN6_CLIP_MODE_NORMAL | 202 dw2); 203 OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | 204 U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | 205 (_mesa_geometric_layers(fb) > 0 ? 0 : GEN6_CLIP_FORCE_ZERO_RTAINDEX) | 206 ((viewport_count - 1) & GEN6_CLIP_MAX_VP_INDEX_MASK)); 207 ADVANCE_BATCH(); 208} 209 210const struct brw_tracked_state gen6_clip_state = { 211 .dirty = { 212 .mesa = _NEW_BUFFERS | 213 _NEW_LIGHT | 214 _NEW_POLYGON | 215 _NEW_TRANSFORM, 216 .brw = BRW_NEW_BLORP | 217 BRW_NEW_CONTEXT | 218 BRW_NEW_FS_PROG_DATA | 219 BRW_NEW_GS_PROG_DATA | 220 BRW_NEW_VS_PROG_DATA | 221 BRW_NEW_META_IN_PROGRESS | 222 BRW_NEW_PRIMITIVE | 223 BRW_NEW_RASTERIZER_DISCARD | 224 BRW_NEW_TES_PROG_DATA | 225 BRW_NEW_VIEWPORT_COUNT, 226 }, 227 .emit = upload_clip_state, 228}; 229