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 "brw_wm.h" 33#include "program/prog_parameter.h" 34#include "program/prog_statevars.h" 35#include "intel_batchbuffer.h" 36 37static void 38gen6_upload_wm_push_constants(struct brw_context *brw) 39{ 40 struct intel_context *intel = &brw->intel; 41 struct gl_context *ctx = &intel->ctx; 42 /* BRW_NEW_FRAGMENT_PROGRAM */ 43 const struct brw_fragment_program *fp = 44 brw_fragment_program_const(brw->fragment_program); 45 46 /* Updates the ParameterValues[i] pointers for all parameters of the 47 * basic type of PROGRAM_STATE_VAR. 48 */ 49 /* XXX: Should this happen somewhere before to get our state flag set? */ 50 _mesa_load_state_parameters(ctx, fp->program.Base.Parameters); 51 52 /* CACHE_NEW_WM_PROG */ 53 if (brw->wm.prog_data->nr_params != 0) { 54 float *constants; 55 unsigned int i; 56 57 constants = brw_state_batch(brw, AUB_TRACE_WM_CONSTANTS, 58 brw->wm.prog_data->nr_params * 59 sizeof(float), 60 32, &brw->wm.push_const_offset); 61 62 for (i = 0; i < brw->wm.prog_data->nr_params; i++) { 63 constants[i] = *brw->wm.prog_data->param[i]; 64 } 65 66 if (0) { 67 printf("WM constants:\n"); 68 for (i = 0; i < brw->wm.prog_data->nr_params; i++) { 69 if ((i & 7) == 0) 70 printf("g%d: ", brw->wm.prog_data->first_curbe_grf + i / 8); 71 printf("%8f ", constants[i]); 72 if ((i & 7) == 7) 73 printf("\n"); 74 } 75 if ((i & 7) != 0) 76 printf("\n"); 77 printf("\n"); 78 } 79 } 80} 81 82const struct brw_tracked_state gen6_wm_push_constants = { 83 .dirty = { 84 .mesa = _NEW_PROGRAM_CONSTANTS, 85 .brw = (BRW_NEW_BATCH | 86 BRW_NEW_FRAGMENT_PROGRAM), 87 .cache = CACHE_NEW_WM_PROG, 88 }, 89 .emit = gen6_upload_wm_push_constants, 90}; 91 92static void 93upload_wm_state(struct brw_context *brw) 94{ 95 struct intel_context *intel = &brw->intel; 96 struct gl_context *ctx = &intel->ctx; 97 const struct brw_fragment_program *fp = 98 brw_fragment_program_const(brw->fragment_program); 99 uint32_t dw2, dw4, dw5, dw6; 100 101 /* _NEW_BUFFERS */ 102 bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; 103 104 /* CACHE_NEW_WM_PROG */ 105 if (brw->wm.prog_data->nr_params == 0) { 106 /* Disable the push constant buffers. */ 107 BEGIN_BATCH(5); 108 OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | (5 - 2)); 109 OUT_BATCH(0); 110 OUT_BATCH(0); 111 OUT_BATCH(0); 112 OUT_BATCH(0); 113 ADVANCE_BATCH(); 114 } else { 115 BEGIN_BATCH(5); 116 OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | 117 GEN6_CONSTANT_BUFFER_0_ENABLE | 118 (5 - 2)); 119 /* Pointer to the WM constant buffer. Covered by the set of 120 * state flags from gen6_upload_wm_push_constants. 121 */ 122 OUT_BATCH(brw->wm.push_const_offset + 123 ALIGN(brw->wm.prog_data->nr_params, 124 brw->wm.prog_data->dispatch_width) / 8 - 1); 125 OUT_BATCH(0); 126 OUT_BATCH(0); 127 OUT_BATCH(0); 128 ADVANCE_BATCH(); 129 } 130 131 dw2 = dw4 = dw5 = dw6 = 0; 132 dw4 |= GEN6_WM_STATISTICS_ENABLE; 133 dw5 |= GEN6_WM_LINE_AA_WIDTH_1_0; 134 dw5 |= GEN6_WM_LINE_END_CAP_AA_WIDTH_0_5; 135 136 /* Use ALT floating point mode for ARB fragment programs, because they 137 * require 0^0 == 1. Even though _CurrentFragmentProgram is used for 138 * rendering, CurrentFragmentProgram is used for this check to 139 * differentiate between the GLSL and non-GLSL cases. 140 */ 141 if (ctx->Shader.CurrentFragmentProgram == NULL) 142 dw2 |= GEN6_WM_FLOATING_POINT_MODE_ALT; 143 144 /* CACHE_NEW_SAMPLER */ 145 dw2 |= (ALIGN(brw->sampler.count, 4) / 4) << GEN6_WM_SAMPLER_COUNT_SHIFT; 146 dw4 |= (brw->wm.prog_data->first_curbe_grf << 147 GEN6_WM_DISPATCH_START_GRF_SHIFT_0); 148 dw4 |= (brw->wm.prog_data->first_curbe_grf_16 << 149 GEN6_WM_DISPATCH_START_GRF_SHIFT_2); 150 151 dw5 |= (brw->max_wm_threads - 1) << GEN6_WM_MAX_THREADS_SHIFT; 152 153 /* CACHE_NEW_WM_PROG */ 154 if (brw->wm.prog_data->dispatch_width == 8) { 155 dw5 |= GEN6_WM_8_DISPATCH_ENABLE; 156 if (brw->wm.prog_data->prog_offset_16) 157 dw5 |= GEN6_WM_16_DISPATCH_ENABLE; 158 } else { 159 dw5 |= GEN6_WM_16_DISPATCH_ENABLE; 160 } 161 162 /* CACHE_NEW_WM_PROG | _NEW_COLOR */ 163 if (brw->wm.prog_data->dual_src_blend && 164 (ctx->Color.BlendEnabled & 1) && 165 ctx->Color.Blend[0]._UsesDualSrc) { 166 dw5 |= GEN6_WM_DUAL_SOURCE_BLEND_ENABLE; 167 } 168 169 /* _NEW_LINE */ 170 if (ctx->Line.StippleFlag) 171 dw5 |= GEN6_WM_LINE_STIPPLE_ENABLE; 172 173 /* _NEW_POLYGON */ 174 if (ctx->Polygon.StippleFlag) 175 dw5 |= GEN6_WM_POLYGON_STIPPLE_ENABLE; 176 177 /* BRW_NEW_FRAGMENT_PROGRAM */ 178 if (fp->program.Base.InputsRead & FRAG_BIT_WPOS) 179 dw5 |= GEN6_WM_USES_SOURCE_DEPTH | GEN6_WM_USES_SOURCE_W; 180 if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) 181 dw5 |= GEN6_WM_COMPUTED_DEPTH; 182 /* CACHE_NEW_WM_PROG */ 183 dw6 |= brw->wm.prog_data->barycentric_interp_modes << 184 GEN6_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; 185 186 /* _NEW_COLOR, _NEW_MULTISAMPLE */ 187 if (fp->program.UsesKill || ctx->Color.AlphaEnabled || 188 ctx->Multisample.SampleAlphaToCoverage) 189 dw5 |= GEN6_WM_KILL_ENABLE; 190 191 if (brw_color_buffer_write_enabled(brw) || 192 dw5 & (GEN6_WM_KILL_ENABLE | GEN6_WM_COMPUTED_DEPTH)) { 193 dw5 |= GEN6_WM_DISPATCH_ENABLE; 194 } 195 196 dw6 |= _mesa_bitcount_64(brw->fragment_program->Base.InputsRead) << 197 GEN6_WM_NUM_SF_OUTPUTS_SHIFT; 198 if (multisampled_fbo) { 199 /* _NEW_MULTISAMPLE */ 200 if (ctx->Multisample.Enabled) 201 dw6 |= GEN6_WM_MSRAST_ON_PATTERN; 202 else 203 dw6 |= GEN6_WM_MSRAST_OFF_PIXEL; 204 dw6 |= GEN6_WM_MSDISPMODE_PERPIXEL; 205 } else { 206 dw6 |= GEN6_WM_MSRAST_OFF_PIXEL; 207 dw6 |= GEN6_WM_MSDISPMODE_PERSAMPLE; 208 } 209 210 BEGIN_BATCH(9); 211 OUT_BATCH(_3DSTATE_WM << 16 | (9 - 2)); 212 OUT_BATCH(brw->wm.prog_offset); 213 OUT_BATCH(dw2); 214 if (brw->wm.prog_data->total_scratch) { 215 OUT_RELOC(brw->wm.scratch_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 216 ffs(brw->wm.prog_data->total_scratch) - 11); 217 } else { 218 OUT_BATCH(0); 219 } 220 OUT_BATCH(dw4); 221 OUT_BATCH(dw5); 222 OUT_BATCH(dw6); 223 OUT_BATCH(0); /* kernel 1 pointer */ 224 /* kernel 2 pointer */ 225 OUT_BATCH(brw->wm.prog_offset + brw->wm.prog_data->prog_offset_16); 226 ADVANCE_BATCH(); 227} 228 229const struct brw_tracked_state gen6_wm_state = { 230 .dirty = { 231 .mesa = (_NEW_LINE | 232 _NEW_COLOR | 233 _NEW_BUFFERS | 234 _NEW_PROGRAM_CONSTANTS | 235 _NEW_POLYGON | 236 _NEW_MULTISAMPLE), 237 .brw = (BRW_NEW_FRAGMENT_PROGRAM | 238 BRW_NEW_BATCH), 239 .cache = (CACHE_NEW_SAMPLER | 240 CACHE_NEW_WM_PROG) 241 }, 242 .emit = upload_wm_state, 243}; 244