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