12228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/********************************************************** 22228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * Copyright 2008-2009 VMware, Inc. All rights reserved. 32228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * 42228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * Permission is hereby granted, free of charge, to any person 54f0d97057c5c640b25518358886f8c47da9fc052Jean-Michel Trivi * obtaining a copy of this software and associated documentation 62228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * files (the "Software"), to deal in the Software without 72228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * restriction, including without limitation the rights to use, copy, 82228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * modify, merge, publish, distribute, sublicense, and/or sell copies 92228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * of the Software, and to permit persons to whom the Software is 102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * furnished to do so, subject to the following conditions: 112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * 122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * The above copyright notice and this permission notice shall be 132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * included in all copies or substantial portions of the Software. 142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * 152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * SOFTWARE. 232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * 242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **********************************************************/ 252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "util/u_inlines.h" 272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "pipe/p_defines.h" 282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "svga_screen.h" 302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "svga_context.h" 312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "svga_state.h" 322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "svga_cmd.h" 332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "svga_tgsi.h" 342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "svga_debug.h" 352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "svga_hw_reg.h" 372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* 402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * Don't try to send more than 4kb of successive constants. 412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project */ 422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define MAX_CONST_REG_COUNT 256 /**< number of float[4] constants */ 432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** 472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * Convert from PIPE_SHADER_* to SVGA3D_SHADERTYPE_* 482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project */ 492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectstatic int 502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectsvga_shader_type(unsigned shader) 512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{ 522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project assert(PIPE_SHADER_VERTEX + 1 == SVGA3D_SHADERTYPE_VS); 532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project assert(PIPE_SHADER_FRAGMENT + 1 == SVGA3D_SHADERTYPE_PS); 542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project assert(shader <= PIPE_SHADER_FRAGMENT); 552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project return shader + 1; 562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project} 572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** 602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * Check and emit one shader constant register. 612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * \param shader PIPE_SHADER_FRAGMENT or PIPE_SHADER_VERTEX 622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * \param i which float[4] constant to change 632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * \param value the new float[4] value 642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project */ 652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectstatic enum pipe_error 662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectemit_const(struct svga_context *svga, unsigned shader, unsigned i, 672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project const float *value) 682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{ 692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project enum pipe_error ret = PIPE_OK; 702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project assert(shader < PIPE_SHADER_TYPES); 722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project assert(i < SVGA3D_CONSTREG_MAX); 732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project if (memcmp(svga->state.hw_draw.cb[shader][i], value, 752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 4 * sizeof(float)) != 0) { 762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project if (SVGA_DEBUG & DEBUG_CONSTS) 772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project debug_printf("%s %s %u: %f %f %f %f\n", 782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project __FUNCTION__, 792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG", 802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project i, 812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project value[0], 822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project value[1], 832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project value[2], 842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project value[3]); 852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project ret = SVGA3D_SetShaderConst( svga->swc, 872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project i, 882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project svga_shader_type(shader), 892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project SVGA3D_CONST_TYPE_FLOAT, 902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project value ); 912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project if (ret != PIPE_OK) 922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project return ret; 932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project memcpy(svga->state.hw_draw.cb[shader][i], value, 4 * sizeof(float)); 952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project } 962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project return ret; 982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project} 992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 1002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 1012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* 1022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * Check and emit a range of shader constant registers, trying to coalesce 1032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * successive shader constant updates in a single command in order to save 1042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * space on the command buffer. This is a HWv8 feature. 1052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project */ 1062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectstatic enum pipe_error 1072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectemit_const_range(struct svga_context *svga, 1082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project unsigned shader, 1092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project unsigned offset, 1102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project unsigned count, 1112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project const float (*values)[4]) 1122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{ 1132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project unsigned i, j; 1142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project enum pipe_error ret; 1152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 1162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#ifdef DEBUG 1172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project if (offset + count > SVGA3D_CONSTREG_MAX) { 1182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project debug_printf("svga: too many constants (offset + count = %u)\n", 1192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project offset + count); 1202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project } 1213aec97e388e29a1d03f0197b27b893bc6aaf8ac3Jean-Michel Trivi#endif 1223aec97e388e29a1d03f0197b27b893bc6aaf8ac3Jean-Michel Trivi 1232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project if (offset > SVGA3D_CONSTREG_MAX) { 1242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project /* This isn't OK, but if we propagate an error all the way up we'll 1252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * just get into more trouble. 1262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * XXX note that offset is always zero at this time so this is moot. 1272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project */ 128 return PIPE_OK; 129 } 130 131 if (offset + count > SVGA3D_CONSTREG_MAX) { 132 /* Just drop the extra constants for now. 133 * Ideally we should not have allowed the app to create a shader 134 * that exceeds our constant buffer size but there's no way to 135 * express that in gallium at this time. 136 */ 137 count = SVGA3D_CONSTREG_MAX - offset; 138 } 139 140 i = 0; 141 while (i < count) { 142 if (memcmp(svga->state.hw_draw.cb[shader][offset + i], 143 values[i], 144 4 * sizeof(float)) != 0) { 145 /* Found one dirty constant 146 */ 147 if (SVGA_DEBUG & DEBUG_CONSTS) 148 debug_printf("%s %s %d: %f %f %f %f\n", 149 __FUNCTION__, 150 shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG", 151 offset + i, 152 values[i][0], 153 values[i][1], 154 values[i][2], 155 values[i][3]); 156 157 /* Look for more consecutive dirty constants. 158 */ 159 j = i + 1; 160 while (j < count && 161 j < i + MAX_CONST_REG_COUNT && 162 memcmp(svga->state.hw_draw.cb[shader][offset + j], 163 values[j], 164 4 * sizeof(float)) != 0) { 165 166 if (SVGA_DEBUG & DEBUG_CONSTS) 167 debug_printf("%s %s %d: %f %f %f %f\n", 168 __FUNCTION__, 169 shader == PIPE_SHADER_VERTEX ? "VERT" : "FRAG", 170 offset + j, 171 values[j][0], 172 values[j][1], 173 values[j][2], 174 values[j][3]); 175 176 ++j; 177 } 178 179 assert(j >= i + 1); 180 181 /* Send them all together. 182 */ 183 ret = SVGA3D_SetShaderConsts(svga->swc, 184 offset + i, j - i, 185 svga_shader_type(shader), 186 SVGA3D_CONST_TYPE_FLOAT, 187 values + i); 188 if (ret != PIPE_OK) { 189 return ret; 190 } 191 192 /* 193 * Local copy of the hardware state. 194 */ 195 memcpy(svga->state.hw_draw.cb[shader][offset + i], 196 values[i], 197 (j - i) * 4 * sizeof(float)); 198 199 i = j + 1; 200 } else { 201 ++i; 202 } 203 } 204 205 return PIPE_OK; 206} 207 208 209/** 210 * Emit all the constants in a constant buffer for a shader stage. 211 */ 212static enum pipe_error 213emit_consts(struct svga_context *svga, unsigned shader) 214{ 215 struct svga_screen *ss = svga_screen(svga->pipe.screen); 216 struct pipe_transfer *transfer = NULL; 217 unsigned count; 218 const float (*data)[4] = NULL; 219 unsigned i; 220 enum pipe_error ret = PIPE_OK; 221 const unsigned offset = 0; 222 223 assert(shader < PIPE_SHADER_TYPES); 224 225 if (svga->curr.cb[shader] == NULL) 226 goto done; 227 228 count = svga->curr.cb[shader]->width0 / (4 * sizeof(float)); 229 230 data = (const float (*)[4])pipe_buffer_map(&svga->pipe, 231 svga->curr.cb[shader], 232 PIPE_TRANSFER_READ, 233 &transfer); 234 if (data == NULL) { 235 ret = PIPE_ERROR_OUT_OF_MEMORY; 236 goto done; 237 } 238 239 if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) { 240 ret = emit_const_range( svga, shader, offset, count, data ); 241 if (ret != PIPE_OK) { 242 goto done; 243 } 244 } else { 245 for (i = 0; i < count; i++) { 246 ret = emit_const( svga, shader, offset + i, data[i] ); 247 if (ret != PIPE_OK) { 248 goto done; 249 } 250 } 251 } 252 253done: 254 if (data) 255 pipe_buffer_unmap(&svga->pipe, transfer); 256 257 return ret; 258} 259 260 261static enum pipe_error 262emit_fs_consts(struct svga_context *svga, unsigned dirty) 263{ 264 const struct svga_shader_result *result = svga->state.hw_draw.fs; 265 enum pipe_error ret = PIPE_OK; 266 267 ret = emit_consts( svga, PIPE_SHADER_FRAGMENT ); 268 if (ret != PIPE_OK) 269 return ret; 270 271 /* The internally generated fragment shader for xor blending 272 * doesn't have a 'result' struct. It should be fixed to avoid 273 * this special case, but work around it with a NULL check: 274 */ 275 if (result) { 276 const struct svga_fs_compile_key *key = &result->key.fkey; 277 if (key->num_unnormalized_coords) { 278 const unsigned offset = 279 result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1; 280 unsigned i; 281 282 for (i = 0; i < key->num_textures; i++) { 283 if (key->tex[i].unnormalized) { 284 struct pipe_resource *tex = svga->curr.sampler_views[i]->texture; 285 float data[4]; 286 287 data[0] = 1.0f / (float) tex->width0; 288 data[1] = 1.0f / (float) tex->height0; 289 data[2] = 1.0f; 290 data[3] = 1.0f; 291 292 ret = emit_const(svga, 293 PIPE_SHADER_FRAGMENT, 294 key->tex[i].width_height_idx + offset, 295 data); 296 if (ret != PIPE_OK) { 297 return ret; 298 } 299 } 300 } 301 } 302 } 303 304 return PIPE_OK; 305} 306 307 308struct svga_tracked_state svga_hw_fs_constants = 309{ 310 "hw fs params", 311 (SVGA_NEW_FS_CONST_BUFFER | 312 SVGA_NEW_FS_RESULT | 313 SVGA_NEW_TEXTURE_BINDING), 314 emit_fs_consts 315}; 316 317 318 319static enum pipe_error 320emit_vs_consts(struct svga_context *svga, unsigned dirty) 321{ 322 const struct svga_shader_result *result = svga->state.hw_draw.vs; 323 const struct svga_vs_compile_key *key; 324 enum pipe_error ret = PIPE_OK; 325 unsigned offset; 326 327 /* SVGA_NEW_VS_RESULT 328 */ 329 if (result == NULL) 330 return PIPE_OK; 331 332 key = &result->key.vkey; 333 334 /* SVGA_NEW_VS_CONST_BUFFER 335 */ 336 ret = emit_consts( svga, PIPE_SHADER_VERTEX ); 337 if (ret != PIPE_OK) 338 return ret; 339 340 /* offset = number of constants in the VS const buffer */ 341 offset = result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1; 342 343 /* SVGA_NEW_VS_PRESCALE 344 * Put the viewport pre-scale/translate values into the const buffer. 345 */ 346 if (key->need_prescale) { 347 ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++, 348 svga->state.hw_clear.prescale.scale ); 349 if (ret != PIPE_OK) 350 return ret; 351 352 ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++, 353 svga->state.hw_clear.prescale.translate ); 354 if (ret != PIPE_OK) 355 return ret; 356 } 357 358 return PIPE_OK; 359} 360 361 362struct svga_tracked_state svga_hw_vs_constants = 363{ 364 "hw vs params", 365 (SVGA_NEW_PRESCALE | 366 SVGA_NEW_VS_CONST_BUFFER | 367 SVGA_NEW_VS_RESULT), 368 emit_vs_consts 369}; 370