1 /************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include "i915_batch.h" 29 #include "i915_state_inlines.h" 30 #include "i915_context.h" 31 #include "i915_reg.h" 32 #include "i915_state.h" 33 34 #include "util/u_memory.h" 35 #include "util/u_pack_color.h" 36 37 38 /* State that we have chosen to store in the DYNAMIC segment of the 39 * i915 indirect state mechanism. 40 * 41 * Can't cache these in the way we do the static state, as there is no 42 * start/size in the command packet, instead an 'end' value that gets 43 * incremented. 44 * 45 * Additionally, there seems to be a requirement to re-issue the full 46 * (active) state every time a 4kb boundary is crossed. 47 */ 48 49 static inline void set_dynamic(struct i915_context *i915, 50 unsigned offset, 51 const unsigned state) 52 { 53 if (i915->current.dynamic[offset] == state) 54 return; 55 56 i915->current.dynamic[offset] = state; 57 i915->dynamic_dirty |= 1 << offset; 58 i915->hardware_dirty |= I915_HW_DYNAMIC; 59 } 60 61 62 63 static inline void set_dynamic_array(struct i915_context *i915, 64 unsigned offset, 65 const unsigned *src, 66 unsigned dwords) 67 { 68 unsigned i; 69 70 if (!memcmp(src, &i915->current.dynamic[offset], dwords * 4)) 71 return; 72 73 for (i = 0; i < dwords; i++) { 74 i915->current.dynamic[offset + i] = src[i]; 75 i915->dynamic_dirty |= 1 << (offset + i); 76 } 77 78 i915->hardware_dirty |= I915_HW_DYNAMIC; 79 } 80 81 82 83 /*********************************************************************** 84 * Modes4: stencil masks and logicop 85 */ 86 static void upload_MODES4(struct i915_context *i915) 87 { 88 unsigned modes4 = 0; 89 90 /* I915_NEW_STENCIL 91 */ 92 modes4 |= i915->depth_stencil->stencil_modes4; 93 94 /* I915_NEW_BLEND 95 */ 96 modes4 |= i915->blend->modes4; 97 98 set_dynamic(i915, I915_DYNAMIC_MODES4, modes4); 99 } 100 101 const struct i915_tracked_state i915_upload_MODES4 = { 102 "MODES4", 103 upload_MODES4, 104 I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL 105 }; 106 107 108 109 /*********************************************************************** 110 */ 111 static void upload_BFO(struct i915_context *i915) 112 { 113 unsigned bfo[2]; 114 bfo[0] = i915->depth_stencil->bfo[0]; 115 bfo[1] = i915->depth_stencil->bfo[1]; 116 /* I don't get it only allowed to set a ref mask when the enable bit is set? */ 117 if (bfo[0] & BFO_ENABLE_STENCIL_REF) { 118 bfo[0] |= i915->stencil_ref.ref_value[1] << BFO_STENCIL_REF_SHIFT; 119 } 120 121 set_dynamic_array(i915, I915_DYNAMIC_BFO_0, bfo, 2); 122 } 123 124 const struct i915_tracked_state i915_upload_BFO = { 125 "BFO", 126 upload_BFO, 127 I915_NEW_DEPTH_STENCIL 128 }; 129 130 131 132 /*********************************************************************** 133 */ 134 static void upload_BLENDCOLOR(struct i915_context *i915) 135 { 136 unsigned bc[2]; 137 138 memset(bc, 0, sizeof(bc)); 139 140 /* I915_NEW_BLEND 141 */ 142 { 143 const float *color = i915->blend_color.color; 144 145 bc[0] = _3DSTATE_CONST_BLEND_COLOR_CMD; 146 bc[1] = pack_ui32_float4(color[0], 147 color[1], 148 color[2], 149 color[3]); 150 } 151 152 set_dynamic_array(i915, I915_DYNAMIC_BC_0, bc, 2); 153 } 154 155 const struct i915_tracked_state i915_upload_BLENDCOLOR = { 156 "BLENDCOLOR", 157 upload_BLENDCOLOR, 158 I915_NEW_BLEND 159 }; 160 161 162 163 /*********************************************************************** 164 */ 165 static void upload_IAB(struct i915_context *i915) 166 { 167 unsigned iab = i915->blend->iab; 168 169 set_dynamic(i915, I915_DYNAMIC_IAB, iab); 170 } 171 172 const struct i915_tracked_state i915_upload_IAB = { 173 "IAB", 174 upload_IAB, 175 I915_NEW_BLEND 176 }; 177 178 179 180 /*********************************************************************** 181 */ 182 static void upload_DEPTHSCALE(struct i915_context *i915) 183 { 184 set_dynamic_array(i915, I915_DYNAMIC_DEPTHSCALE_0, 185 &i915->rasterizer->ds[0].u, 2); 186 } 187 188 const struct i915_tracked_state i915_upload_DEPTHSCALE = { 189 "DEPTHSCALE", 190 upload_DEPTHSCALE, 191 I915_NEW_RASTERIZER 192 }; 193 194 195 196 /*********************************************************************** 197 * Polygon stipple 198 * 199 * The i915 supports a 4x4 stipple natively, GL wants 32x32. 200 * Fortunately stipple is usually a repeating pattern. 201 * 202 * XXX: does stipple pattern need to be adjusted according to 203 * the window position? 204 * 205 * XXX: possibly need workaround for conform paths test. 206 */ 207 static void upload_STIPPLE(struct i915_context *i915) 208 { 209 unsigned st[2]; 210 211 st[0] = _3DSTATE_STIPPLE; 212 st[1] = 0; 213 214 /* I915_NEW_RASTERIZER 215 */ 216 st[1] |= i915->rasterizer->st; 217 218 /* I915_NEW_STIPPLE 219 */ 220 { 221 const ubyte *mask = (const ubyte *)i915->poly_stipple.stipple; 222 ubyte p[4]; 223 224 p[0] = mask[12] & 0xf; 225 p[1] = mask[8] & 0xf; 226 p[2] = mask[4] & 0xf; 227 p[3] = mask[0] & 0xf; 228 229 /* Not sure what to do about fallbacks, so for now just dont: 230 */ 231 st[1] |= ((p[0] << 0) | 232 (p[1] << 4) | 233 (p[2] << 8) | 234 (p[3] << 12)); 235 } 236 237 set_dynamic_array(i915, I915_DYNAMIC_STP_0, st, 2); 238 } 239 240 const struct i915_tracked_state i915_upload_STIPPLE = { 241 "STIPPLE", 242 upload_STIPPLE, 243 I915_NEW_RASTERIZER | I915_NEW_STIPPLE 244 }; 245 246 247 248 /*********************************************************************** 249 * Scissor enable 250 */ 251 static void upload_SCISSOR_ENABLE( struct i915_context *i915 ) 252 { 253 set_dynamic(i915, I915_DYNAMIC_SC_ENA_0, i915->rasterizer->sc[0]); 254 } 255 256 const struct i915_tracked_state i915_upload_SCISSOR_ENABLE = { 257 "SCISSOR ENABLE", 258 upload_SCISSOR_ENABLE, 259 I915_NEW_RASTERIZER 260 }; 261 262 263 264 /*********************************************************************** 265 * Scissor rect 266 */ 267 static void upload_SCISSOR_RECT(struct i915_context *i915) 268 { 269 unsigned x1 = i915->scissor.minx; 270 unsigned y1 = i915->scissor.miny; 271 unsigned x2 = i915->scissor.maxx - 1; 272 unsigned y2 = i915->scissor.maxy - 1; 273 unsigned sc[3]; 274 275 sc[0] = _3DSTATE_SCISSOR_RECT_0_CMD; 276 sc[1] = (y1 << 16) | (x1 & 0xffff); 277 sc[2] = (y2 << 16) | (x2 & 0xffff); 278 279 set_dynamic_array(i915, I915_DYNAMIC_SC_RECT_0, sc, 3); 280 } 281 282 const struct i915_tracked_state i915_upload_SCISSOR_RECT = { 283 "SCISSOR RECT", 284 upload_SCISSOR_RECT, 285 I915_NEW_SCISSOR 286 }; 287 288 289 290 /*********************************************************************** 291 */ 292 static const struct i915_tracked_state *atoms[] = { 293 &i915_upload_MODES4, 294 &i915_upload_BFO, 295 &i915_upload_BLENDCOLOR, 296 &i915_upload_IAB, 297 &i915_upload_DEPTHSCALE, 298 &i915_upload_STIPPLE, 299 &i915_upload_SCISSOR_ENABLE, 300 &i915_upload_SCISSOR_RECT 301 }; 302 303 /* These will be dynamic indirect state commands, but for now just end 304 * up on the batch buffer with everything else. 305 */ 306 static void update_dynamic(struct i915_context *i915) 307 { 308 int i; 309 310 for (i = 0; i < ARRAY_SIZE(atoms); i++) 311 if (i915->dirty & atoms[i]->dirty) 312 atoms[i]->update(i915); 313 } 314 315 struct i915_tracked_state i915_hw_dynamic = { 316 "dynamic", 317 update_dynamic, 318 ~0 /* all state atoms, because we do internal checking */ 319 }; 320