blob: 23b3ace7f30dd2ff571e83f0d96be1ae224fb8fe [file] [log] [blame]
/**********************************************************
* Copyright 2008-2009 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
#include "util/u_memory.h"
#include "svga_tgsi_emit.h"
#include "svga_context.h"
static boolean ps20_input( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
struct src_register reg;
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
switch (semantic.Name) {
case TGSI_SEMANTIC_POSITION:
/* Special case:
*/
reg = src_register( SVGA3DREG_MISCTYPE,
SVGA3DMISCREG_POSITION );
break;
case TGSI_SEMANTIC_COLOR:
reg = src_register( SVGA3DREG_INPUT,
semantic.Index );
break;
case TGSI_SEMANTIC_FOG:
assert(semantic.Index == 0);
reg = src_register( SVGA3DREG_TEXTURE, 0 );
break;
case TGSI_SEMANTIC_GENERIC:
reg = src_register( SVGA3DREG_TEXTURE,
semantic.Index + 1 );
break;
default:
assert(0);
return TRUE;
}
emit->input_map[idx] = reg;
dcl.dst = dst( reg );
dcl.usage = 0;
dcl.index = 0;
dcl.values[0] |= 1<<31;
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
static boolean ps20_output( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3dShaderDestToken reg;
switch (semantic.Name) {
case TGSI_SEMANTIC_COLOR:
if (semantic.Index < PIPE_MAX_COLOR_BUFS) {
unsigned cbuf = semantic.Index;
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_col[cbuf] = emit->output_map[idx];
emit->true_col[cbuf] = dst_register( SVGA3DREG_COLOROUT,
semantic.Index );
}
else {
assert(0);
reg = dst_register( SVGA3DREG_COLOROUT, 0 );
}
break;
case TGSI_SEMANTIC_POSITION:
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_pos = emit->output_map[idx];
emit->true_pos = dst_register( SVGA3DREG_DEPTHOUT,
semantic.Index );
break;
default:
assert(0);
reg = dst_register( SVGA3DREG_COLOROUT, 0 );
break;
}
return TRUE;
}
static boolean vs20_input( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx );
dcl.dst = dst_register( SVGA3DREG_INPUT, idx );
assert(dcl.dst.reserved0);
/* Mesa doesn't provide use with VS input semantics (they're
* actually pretty meaningless), so we just generate some plausible
* ones here. This has to match what we declare in the vdecl code
* in svga_pipe_vertex.c.
*/
if (idx == 0) {
dcl.usage = SVGA3D_DECLUSAGE_POSITION;
dcl.index = 0;
}
else {
dcl.usage = SVGA3D_DECLUSAGE_TEXCOORD;
dcl.index = idx - 1;
}
dcl.values[0] |= 1<<31;
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
static boolean vs20_output( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
/* Don't emit dcl instruction for vs20 inputs
*/
/* Just build the register map table:
*/
switch (semantic.Name) {
case TGSI_SEMANTIC_POSITION:
assert(semantic.Index == 0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_pos = emit->output_map[idx];
emit->true_pos = dst_register( SVGA3DREG_RASTOUT,
SVGA3DRASTOUT_POSITION);
break;
case TGSI_SEMANTIC_PSIZE:
assert(semantic.Index == 0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
emit->nr_hw_temp++ );
emit->temp_psiz = emit->output_map[idx];
emit->true_psiz = dst_register( SVGA3DREG_RASTOUT,
SVGA3DRASTOUT_PSIZE );
break;
case TGSI_SEMANTIC_FOG:
assert(semantic.Index == 0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEXCRDOUT, 0 );
break;
case TGSI_SEMANTIC_COLOR:
/* oD0 */
emit->output_map[idx] = dst_register( SVGA3DREG_ATTROUT,
semantic.Index );
break;
case TGSI_SEMANTIC_GENERIC:
emit->output_map[idx] = dst_register( SVGA3DREG_TEXCRDOUT,
semantic.Index + 1 );
break;
default:
assert(0);
emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, 0 );
return FALSE;
}
return TRUE;
}
static boolean ps20_sampler( struct svga_shader_emitter *emit,
struct tgsi_declaration_semantic semantic,
unsigned idx )
{
SVGA3DOpDclArgs dcl;
SVGA3dShaderInstToken opcode;
opcode = inst_token( SVGA3DOP_DCL );
dcl.values[0] = 0;
dcl.values[1] = 0;
dcl.dst = dst_register( SVGA3DREG_SAMPLER, idx );
dcl.type = svga_tgsi_sampler_type( emit, idx );
return (emit_instruction(emit, opcode) &&
svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
}
boolean svga_translate_decl_sm20( struct svga_shader_emitter *emit,
const struct tgsi_full_declaration *decl )
{
unsigned first = decl->Range.First;
unsigned last = decl->Range.Last;
unsigned semantic = 0;
unsigned semantic_idx = 0;
unsigned idx;
if (decl->Declaration.Semantic) {
semantic = decl->Semantic.Name;
semantic_idx = decl->Semantic.Index;
}
for( idx = first; idx <= last; idx++ ) {
boolean ok;
switch (decl->Declaration.File) {
case TGSI_FILE_SAMPLER:
assert (emit->unit == PIPE_SHADER_FRAGMENT);
ok = ps20_sampler( emit, decl->Semantic, idx );
break;
case TGSI_FILE_INPUT:
if (emit->unit == PIPE_SHADER_VERTEX)
ok = vs20_input( emit, decl->Semantic, idx );
else
ok = ps20_input( emit, decl->Semantic, idx );
break;
case TGSI_FILE_OUTPUT:
if (emit->unit == PIPE_SHADER_VERTEX)
ok = vs20_output( emit, decl->Semantic, idx );
else
ok = ps20_output( emit, decl->Semantic, idx );
break;
default:
/* don't need to declare other vars */
ok = TRUE;
}
if (!ok)
return FALSE;
}
return TRUE;
}