VirtualBox

Ignore:
Timestamp:
Apr 19, 2010 3:27:01 PM (15 years ago)
Author:
vboxsync
Message:

crOpenGL: update to wine 1.1.43

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/shader.c

    r25949 r28475  
    3333
    3434#include "config.h"
     35#include "wine/port.h"
    3536
    3637#include <math.h>
    3738#include <stdio.h>
     39#include <string.h>
    3840
    3941#include "wined3d_private.h"
    4042
    4143WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
     44WINE_DECLARE_DEBUG_CHANNEL(d3d);
     45
     46static const char *shader_opcode_names[] =
     47{
     48    /* WINED3DSIH_ABS           */ "abs",
     49    /* WINED3DSIH_ADD           */ "add",
     50    /* WINED3DSIH_BEM           */ "bem",
     51    /* WINED3DSIH_BREAK         */ "break",
     52    /* WINED3DSIH_BREAKC        */ "breakc",
     53    /* WINED3DSIH_BREAKP        */ "breakp",
     54    /* WINED3DSIH_CALL          */ "call",
     55    /* WINED3DSIH_CALLNZ        */ "callnz",
     56    /* WINED3DSIH_CMP           */ "cmp",
     57    /* WINED3DSIH_CND           */ "cnd",
     58    /* WINED3DSIH_CRS           */ "crs",
     59    /* WINED3DSIH_CUT           */ "cut",
     60    /* WINED3DSIH_DCL           */ "dcl",
     61    /* WINED3DSIH_DEF           */ "def",
     62    /* WINED3DSIH_DEFB          */ "defb",
     63    /* WINED3DSIH_DEFI          */ "defi",
     64    /* WINED3DSIH_DP2ADD        */ "dp2add",
     65    /* WINED3DSIH_DP3           */ "dp3",
     66    /* WINED3DSIH_DP4           */ "dp4",
     67    /* WINED3DSIH_DST           */ "dst",
     68    /* WINED3DSIH_DSX           */ "dsx",
     69    /* WINED3DSIH_DSY           */ "dsy",
     70    /* WINED3DSIH_ELSE          */ "else",
     71    /* WINED3DSIH_EMIT          */ "emit",
     72    /* WINED3DSIH_ENDIF         */ "endif",
     73    /* WINED3DSIH_ENDLOOP       */ "endloop",
     74    /* WINED3DSIH_ENDREP        */ "endrep",
     75    /* WINED3DSIH_EXP           */ "exp",
     76    /* WINED3DSIH_EXPP          */ "expp",
     77    /* WINED3DSIH_FRC           */ "frc",
     78    /* WINED3DSIH_IADD          */ "iadd",
     79    /* WINED3DSIH_IF            */ "if",
     80    /* WINED3DSIH_IFC           */ "ifc",
     81    /* WINED3DSIH_IGE           */ "ige",
     82    /* WINED3DSIH_LABEL         */ "label",
     83    /* WINED3DSIH_LIT           */ "lit",
     84    /* WINED3DSIH_LOG           */ "log",
     85    /* WINED3DSIH_LOGP          */ "logp",
     86    /* WINED3DSIH_LOOP          */ "loop",
     87    /* WINED3DSIH_LRP           */ "lrp",
     88    /* WINED3DSIH_LT            */ "lt",
     89    /* WINED3DSIH_M3x2          */ "m3x2",
     90    /* WINED3DSIH_M3x3          */ "m3x3",
     91    /* WINED3DSIH_M3x4          */ "m3x4",
     92    /* WINED3DSIH_M4x3          */ "m4x3",
     93    /* WINED3DSIH_M4x4          */ "m4x4",
     94    /* WINED3DSIH_MAD           */ "mad",
     95    /* WINED3DSIH_MAX           */ "max",
     96    /* WINED3DSIH_MIN           */ "min",
     97    /* WINED3DSIH_MOV           */ "mov",
     98    /* WINED3DSIH_MOVA          */ "mova",
     99    /* WINED3DSIH_MUL           */ "mul",
     100    /* WINED3DSIH_NOP           */ "nop",
     101    /* WINED3DSIH_NRM           */ "nrm",
     102    /* WINED3DSIH_PHASE         */ "phase",
     103    /* WINED3DSIH_POW           */ "pow",
     104    /* WINED3DSIH_RCP           */ "rcp",
     105    /* WINED3DSIH_REP           */ "rep",
     106    /* WINED3DSIH_RET           */ "ret",
     107    /* WINED3DSIH_RSQ           */ "rsq",
     108    /* WINED3DSIH_SETP          */ "setp",
     109    /* WINED3DSIH_SGE           */ "sge",
     110    /* WINED3DSIH_SGN           */ "sgn",
     111    /* WINED3DSIH_SINCOS        */ "sincos",
     112    /* WINED3DSIH_SLT           */ "slt",
     113    /* WINED3DSIH_SUB           */ "sub",
     114    /* WINED3DSIH_TEX           */ "texld",
     115    /* WINED3DSIH_TEXBEM        */ "texbem",
     116    /* WINED3DSIH_TEXBEML       */ "texbeml",
     117    /* WINED3DSIH_TEXCOORD      */ "texcrd",
     118    /* WINED3DSIH_TEXDEPTH      */ "texdepth",
     119    /* WINED3DSIH_TEXDP3        */ "texdp3",
     120    /* WINED3DSIH_TEXDP3TEX     */ "texdp3tex",
     121    /* WINED3DSIH_TEXKILL       */ "texkill",
     122    /* WINED3DSIH_TEXLDD        */ "texldd",
     123    /* WINED3DSIH_TEXLDL        */ "texldl",
     124    /* WINED3DSIH_TEXM3x2DEPTH  */ "texm3x2depth",
     125    /* WINED3DSIH_TEXM3x2PAD    */ "texm3x2pad",
     126    /* WINED3DSIH_TEXM3x2TEX    */ "texm3x2tex",
     127    /* WINED3DSIH_TEXM3x3       */ "texm3x3",
     128    /* WINED3DSIH_TEXM3x3DIFF   */ "texm3x3diff",
     129    /* WINED3DSIH_TEXM3x3PAD    */ "texm3x3pad",
     130    /* WINED3DSIH_TEXM3x3SPEC   */ "texm3x3spec",
     131    /* WINED3DSIH_TEXM3x3TEX    */ "texm3x3tex",
     132    /* WINED3DSIH_TEXM3x3VSPEC  */ "texm3x3vspec",
     133    /* WINED3DSIH_TEXREG2AR     */ "texreg2ar",
     134    /* WINED3DSIH_TEXREG2GB     */ "texreg2gb",
     135    /* WINED3DSIH_TEXREG2RGB    */ "texreg2rgb",
     136};
     137
     138static const char *semantic_names[] =
     139{
     140    /* WINED3DDECLUSAGE_POSITION        */ "SV_POSITION",
     141    /* WINED3DDECLUSAGE_BLENDWEIGHT     */ "BLENDWEIGHT",
     142    /* WINED3DDECLUSAGE_BLENDINDICES    */ "BLENDINDICES",
     143    /* WINED3DDECLUSAGE_NORMAL          */ "NORMAL",
     144    /* WINED3DDECLUSAGE_PSIZE           */ "PSIZE",
     145    /* WINED3DDECLUSAGE_TEXCOORD        */ "TEXCOORD",
     146    /* WINED3DDECLUSAGE_TANGENT         */ "TANGENT",
     147    /* WINED3DDECLUSAGE_BINORMAL        */ "BINORMAL",
     148    /* WINED3DDECLUSAGE_TESSFACTOR      */ "TESSFACTOR",
     149    /* WINED3DDECLUSAGE_POSITIONT       */ "POSITIONT",
     150    /* WINED3DDECLUSAGE_COLOR           */ "COLOR",
     151    /* WINED3DDECLUSAGE_FOG             */ "FOG",
     152    /* WINED3DDECLUSAGE_DEPTH           */ "DEPTH",
     153    /* WINED3DDECLUSAGE_SAMPLE          */ "SAMPLE",
     154};
     155
     156static const char *shader_semantic_name_from_usage(WINED3DDECLUSAGE usage)
     157{
     158    if (usage >= sizeof(semantic_names) / sizeof(*semantic_names))
     159    {
     160        FIXME("Unrecognized usage %#x.\n", usage);
     161        return "UNRECOGNIZED";
     162    }
     163
     164    return semantic_names[usage];
     165}
     166
     167static WINED3DDECLUSAGE shader_usage_from_semantic_name(const char *name)
     168{
     169    unsigned int i;
     170
     171    for (i = 0; i < sizeof(semantic_names) / sizeof(*semantic_names); ++i)
     172    {
     173        if (!strcmp(name, semantic_names[i])) return i;
     174    }
     175
     176    return ~0U;
     177}
     178
     179BOOL shader_match_semantic(const char *semantic_name, WINED3DDECLUSAGE usage)
     180{
     181    return !strcmp(semantic_name, shader_semantic_name_from_usage(usage));
     182}
     183
     184static void shader_signature_from_semantic(struct wined3d_shader_signature_element *e,
     185        const struct wined3d_shader_semantic *s)
     186{
     187    e->semantic_name = shader_semantic_name_from_usage(s->usage);
     188    e->semantic_idx = s->usage_idx;
     189    e->sysval_semantic = 0;
     190    e->component_type = 0;
     191    e->register_idx = s->reg.reg.idx;
     192    e->mask = s->reg.write_mask;
     193}
     194
     195static const struct wined3d_shader_frontend *shader_select_frontend(DWORD version_token)
     196{
     197    switch (version_token >> 16)
     198    {
     199        case WINED3D_SM1_VS:
     200        case WINED3D_SM1_PS:
     201            return &sm1_shader_frontend;
     202
     203        case WINED3D_SM4_PS:
     204        case WINED3D_SM4_VS:
     205        case WINED3D_SM4_GS:
     206            return &sm4_shader_frontend;
     207
     208        default:
     209            FIXME("Unrecognised version token %#x\n", version_token);
     210            return NULL;
     211    }
     212}
     213
     214void shader_buffer_clear(struct wined3d_shader_buffer *buffer)
     215{
     216    buffer->buffer[0] = '\0';
     217    buffer->bsize = 0;
     218    buffer->lineNo = 0;
     219    buffer->newline = TRUE;
     220}
     221
     222BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer)
     223{
     224    buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
     225    if (!buffer->buffer)
     226    {
     227        ERR("Failed to allocate shader buffer memory.\n");
     228        return FALSE;
     229    }
     230
     231    shader_buffer_clear(buffer);
     232    return TRUE;
     233}
     234
     235void shader_buffer_free(struct wined3d_shader_buffer *buffer)
     236{
     237    HeapFree(GetProcessHeap(), 0, buffer->buffer);
     238}
     239
     240int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *format, va_list args)
     241{
     242    char *base = buffer->buffer + buffer->bsize;
     243    int rc;
     244
     245    rc = vsnprintf(base, SHADER_PGMSIZE - 1 - buffer->bsize, format, args);
     246
     247    if (rc < 0 /* C89 */ || (unsigned int)rc > SHADER_PGMSIZE - 1 - buffer->bsize /* C99 */)
     248    {
     249        ERR("The buffer allocated for the shader program string "
     250            "is too small at %d bytes.\n", SHADER_PGMSIZE);
     251        buffer->bsize = SHADER_PGMSIZE - 1;
     252        return -1;
     253    }
     254
     255    if (buffer->newline)
     256    {
     257        TRACE("GL HW (%u, %u) : %s", buffer->lineNo + 1, buffer->bsize, base);
     258        buffer->newline = FALSE;
     259    }
     260    else
     261    {
     262        TRACE("%s", base);
     263    }
     264
     265    buffer->bsize += rc;
     266    if (buffer->buffer[buffer->bsize-1] == '\n')
     267    {
     268        ++buffer->lineNo;
     269        buffer->newline = TRUE;
     270    }
     271
     272    return 0;
     273}
     274
     275int shader_addline(struct wined3d_shader_buffer *buffer, const char *format, ...)
     276{
     277    va_list args;
     278    int ret;
     279
     280    va_start(args, format);
     281    ret = shader_vaddline(buffer, format, args);
     282    va_end(args);
     283
     284    return ret;
     285}
     286
     287static void shader_init(struct IWineD3DBaseShaderClass *shader, IWineD3DDeviceImpl *device,
     288        IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
     289{
     290    shader->ref = 1;
     291    shader->device = (IWineD3DDevice *)device;
     292    shader->parent = parent;
     293    shader->parent_ops = parent_ops;
     294    list_init(&shader->linked_programs);
     295    list_add_head(&device->shaders, &shader->shader_list_entry);
     296}
     297
     298/* Convert floating point offset relative to a register file to an absolute
     299 * offset for float constants. */
     300static unsigned int shader_get_float_offset(WINED3DSHADER_PARAM_REGISTER_TYPE register_type, UINT register_idx)
     301{
     302    switch (register_type)
     303    {
     304        case WINED3DSPR_CONST: return register_idx;
     305        case WINED3DSPR_CONST2: return 2048 + register_idx;
     306        case WINED3DSPR_CONST3: return 4096 + register_idx;
     307        case WINED3DSPR_CONST4: return 6144 + register_idx;
     308        default:
     309            FIXME("Unsupported register type: %u.\n", register_type);
     310            return register_idx;
     311    }
     312}
     313
     314static void shader_delete_constant_list(struct list *clist)
     315{
     316    struct local_constant *constant;
     317    struct list *ptr;
     318
     319    ptr = list_head(clist);
     320    while (ptr)
     321    {
     322        constant = LIST_ENTRY(ptr, struct local_constant, entry);
     323        ptr = list_next(clist, ptr);
     324        HeapFree(GetProcessHeap(), 0, constant);
     325    }
     326    list_init(clist);
     327}
     328
     329static inline void set_bitmap_bit(DWORD *bitmap, DWORD bit)
     330{
     331    DWORD idx, shift;
     332    idx = bit >> 5;
     333    shift = bit & 0x1f;
     334    bitmap[idx] |= (1 << shift);
     335}
     336
     337static void shader_record_register_usage(IWineD3DBaseShaderImpl *shader, struct shader_reg_maps *reg_maps,
     338        const struct wined3d_shader_register *reg, enum wined3d_shader_type shader_type)
     339{
     340    switch (reg->type)
     341    {
     342        case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */
     343            if (shader_type == WINED3D_SHADER_TYPE_PIXEL) reg_maps->texcoord |= 1 << reg->idx;
     344            else reg_maps->address |= 1 << reg->idx;
     345            break;
     346
     347        case WINED3DSPR_TEMP:
     348            reg_maps->temporary |= 1 << reg->idx;
     349            break;
     350
     351        case WINED3DSPR_INPUT:
     352            if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
     353            {
     354                if (reg->rel_addr)
     355                {
     356                    /* If relative addressing is used, we must assume that all registers
     357                     * are used. Even if it is a construct like v3[aL], we can't assume
     358                     * that v0, v1 and v2 aren't read because aL can be negative */
     359                    unsigned int i;
     360                    for (i = 0; i < MAX_REG_INPUT; ++i)
     361                    {
     362                        ((IWineD3DPixelShaderImpl *)shader)->input_reg_used[i] = TRUE;
     363                    }
     364                }
     365                else
     366                {
     367                    ((IWineD3DPixelShaderImpl *)shader)->input_reg_used[reg->idx] = TRUE;
     368                }
     369            }
     370            else reg_maps->input_registers |= 1 << reg->idx;
     371            break;
     372
     373        case WINED3DSPR_RASTOUT:
     374            if (reg->idx == 1) reg_maps->fog = 1;
     375            break;
     376
     377        case WINED3DSPR_MISCTYPE:
     378            if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
     379            {
     380                if (reg->idx == 0) reg_maps->vpos = 1;
     381                else if (reg->idx == 1) reg_maps->usesfacing = 1;
     382            }
     383            break;
     384
     385        case WINED3DSPR_CONST:
     386            if (reg->rel_addr)
     387            {
     388                if (shader_type != WINED3D_SHADER_TYPE_PIXEL)
     389                {
     390                    if (reg->idx < ((IWineD3DVertexShaderImpl *)shader)->min_rel_offset)
     391                    {
     392                        ((IWineD3DVertexShaderImpl *)shader)->min_rel_offset = reg->idx;
     393                    }
     394                    if (reg->idx > ((IWineD3DVertexShaderImpl *)shader)->max_rel_offset)
     395                    {
     396                        ((IWineD3DVertexShaderImpl *)shader)->max_rel_offset = reg->idx;
     397                    }
     398                }
     399                reg_maps->usesrelconstF = TRUE;
     400            }
     401            else
     402            {
     403                set_bitmap_bit(reg_maps->constf, reg->idx);
     404            }
     405            break;
     406
     407        case WINED3DSPR_CONSTINT:
     408            reg_maps->integer_constants |= (1 << reg->idx);
     409            break;
     410
     411        case WINED3DSPR_CONSTBOOL:
     412            reg_maps->boolean_constants |= (1 << reg->idx);
     413            break;
     414
     415        case WINED3DSPR_COLOROUT:
     416            reg_maps->highest_render_target = max(reg_maps->highest_render_target, reg->idx);
     417            break;
     418
     419        default:
     420            TRACE("Not recording register of type %#x and idx %u\n", reg->type, reg->idx);
     421            break;
     422    }
     423}
     424
     425static unsigned int get_instr_extra_regcount(enum WINED3D_SHADER_INSTRUCTION_HANDLER instr, unsigned int param)
     426{
     427    switch (instr)
     428    {
     429        case WINED3DSIH_M4x4:
     430        case WINED3DSIH_M3x4:
     431            return param == 1 ? 3 : 0;
     432
     433        case WINED3DSIH_M4x3:
     434        case WINED3DSIH_M3x3:
     435            return param == 1 ? 2 : 0;
     436
     437        case WINED3DSIH_M3x2:
     438            return param == 1 ? 1 : 0;
     439
     440        default:
     441            return 0;
     442    }
     443}
     444
     445/* Note that this does not count the loop register as an address register. */
     446static HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3d_shader_frontend *fe,
     447        struct shader_reg_maps *reg_maps, struct wined3d_shader_signature_element *input_signature,
     448        struct wined3d_shader_signature_element *output_signature, const DWORD *byte_code, DWORD constf_size)
     449{
     450    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface;
     451    unsigned int cur_loop_depth = 0, max_loop_depth = 0;
     452    void *fe_data = shader->baseShader.frontend_data;
     453    struct wined3d_shader_version shader_version;
     454    const DWORD *ptr = byte_code;
     455
     456    memset(reg_maps, 0, sizeof(*reg_maps));
     457
     458    /* get_registers_used() is called on every compile on some 1.x shaders,
     459     * which can result in stacking up a collection of local constants.
     460     * Delete the old constants if existing. */
     461    shader_delete_constant_list(&shader->baseShader.constantsF);
     462    shader_delete_constant_list(&shader->baseShader.constantsB);
     463    shader_delete_constant_list(&shader->baseShader.constantsI);
     464
     465    fe->shader_read_header(fe_data, &ptr, &shader_version);
     466    reg_maps->shader_version = shader_version;
     467
     468    reg_maps->constf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
     469            sizeof(*reg_maps->constf) * ((constf_size + 31) / 32));
     470    if (!reg_maps->constf)
     471    {
     472        ERR("Failed to allocate constant map memory.\n");
     473        return E_OUTOFMEMORY;
     474    }
     475
     476    while (!fe->shader_is_end(fe_data, &ptr))
     477    {
     478        struct wined3d_shader_instruction ins;
     479        const char *comment;
     480        UINT comment_size;
     481        UINT param_size;
     482
     483        /* Skip comments. */
     484        fe->shader_read_comment(&ptr, &comment, &comment_size);
     485        if (comment) continue;
     486
     487        /* Fetch opcode. */
     488        fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
     489
     490        /* Unhandled opcode, and its parameters. */
     491        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
     492        {
     493            TRACE("Skipping unrecognized instruction.\n");
     494            ptr += param_size;
     495            continue;
     496        }
     497
     498        /* Handle declarations. */
     499        if (ins.handler_idx == WINED3DSIH_DCL)
     500        {
     501            struct wined3d_shader_semantic semantic;
     502
     503            fe->shader_read_semantic(&ptr, &semantic);
     504
     505            switch (semantic.reg.reg.type)
     506            {
     507                /* Mark input registers used. */
     508                case WINED3DSPR_INPUT:
     509                    reg_maps->input_registers |= 1 << semantic.reg.reg.idx;
     510                    shader_signature_from_semantic(&input_signature[semantic.reg.reg.idx], &semantic);
     511                    break;
     512
     513                /* Vertex shader: mark 3.0 output registers used, save token. */
     514                case WINED3DSPR_OUTPUT:
     515                    reg_maps->output_registers |= 1 << semantic.reg.reg.idx;
     516                    shader_signature_from_semantic(&output_signature[semantic.reg.reg.idx], &semantic);
     517                    if (semantic.usage == WINED3DDECLUSAGE_FOG) reg_maps->fog = 1;
     518                    break;
     519
     520                /* Save sampler usage token. */
     521                case WINED3DSPR_SAMPLER:
     522                    reg_maps->sampler_type[semantic.reg.reg.idx] = semantic.sampler_type;
     523                    break;
     524
     525                default:
     526                    TRACE("Not recording DCL register type %#x.\n", semantic.reg.reg.type);
     527                    break;
     528            }
     529        }
     530        else if (ins.handler_idx == WINED3DSIH_DEF)
     531        {
     532            struct wined3d_shader_src_param rel_addr;
     533            struct wined3d_shader_dst_param dst;
     534
     535            local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
     536            if (!lconst) return E_OUTOFMEMORY;
     537
     538            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
     539            lconst->idx = dst.reg.idx;
     540
     541            memcpy(lconst->value, ptr, 4 * sizeof(DWORD));
     542            ptr += 4;
     543
     544            /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
     545            if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
     546            {
     547                float *value = (float *)lconst->value;
     548                if (value[0] < -1.0f) value[0] = -1.0f;
     549                else if (value[0] > 1.0f) value[0] = 1.0f;
     550                if (value[1] < -1.0f) value[1] = -1.0f;
     551                else if (value[1] > 1.0f) value[1] = 1.0f;
     552                if (value[2] < -1.0f) value[2] = -1.0f;
     553                else if (value[2] > 1.0f) value[2] = 1.0f;
     554                if (value[3] < -1.0f) value[3] = -1.0f;
     555                else if (value[3] > 1.0f) value[3] = 1.0f;
     556            }
     557
     558            list_add_head(&shader->baseShader.constantsF, &lconst->entry);
     559        }
     560        else if (ins.handler_idx == WINED3DSIH_DEFI)
     561        {
     562            struct wined3d_shader_src_param rel_addr;
     563            struct wined3d_shader_dst_param dst;
     564
     565            local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
     566            if (!lconst) return E_OUTOFMEMORY;
     567
     568            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
     569            lconst->idx = dst.reg.idx;
     570
     571            memcpy(lconst->value, ptr, 4 * sizeof(DWORD));
     572            ptr += 4;
     573
     574            list_add_head(&shader->baseShader.constantsI, &lconst->entry);
     575            reg_maps->local_int_consts |= (1 << dst.reg.idx);
     576        }
     577        else if (ins.handler_idx == WINED3DSIH_DEFB)
     578        {
     579            struct wined3d_shader_src_param rel_addr;
     580            struct wined3d_shader_dst_param dst;
     581
     582            local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
     583            if (!lconst) return E_OUTOFMEMORY;
     584
     585            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
     586            lconst->idx = dst.reg.idx;
     587
     588            memcpy(lconst->value, ptr, sizeof(DWORD));
     589            ++ptr;
     590
     591            list_add_head(&shader->baseShader.constantsB, &lconst->entry);
     592            reg_maps->local_bool_consts |= (1 << dst.reg.idx);
     593        }
     594        /* If there's a loop in the shader. */
     595        else if (ins.handler_idx == WINED3DSIH_LOOP
     596                || ins.handler_idx == WINED3DSIH_REP)
     597        {
     598            struct wined3d_shader_src_param src, rel_addr;
     599
     600            fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr);
     601
     602            /* Rep and Loop always use an integer constant for the control parameters. */
     603            if (ins.handler_idx == WINED3DSIH_REP)
     604            {
     605                reg_maps->integer_constants |= 1 << src.reg.idx;
     606            }
     607            else
     608            {
     609                fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr);
     610                reg_maps->integer_constants |= 1 << src.reg.idx;
     611            }
     612
     613            cur_loop_depth++;
     614            if (cur_loop_depth > max_loop_depth) max_loop_depth = cur_loop_depth;
     615        }
     616        else if (ins.handler_idx == WINED3DSIH_ENDLOOP
     617                || ins.handler_idx == WINED3DSIH_ENDREP)
     618        {
     619            cur_loop_depth--;
     620        }
     621        /* For subroutine prototypes. */
     622        else if (ins.handler_idx == WINED3DSIH_LABEL)
     623        {
     624            struct wined3d_shader_src_param src, rel_addr;
     625
     626            fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr);
     627            reg_maps->labels |= 1 << src.reg.idx;
     628        }
     629        /* Set texture, address, temporary registers. */
     630        else
     631        {
     632            BOOL color0_mov = FALSE;
     633            int i, limit;
     634
     635            /* This will loop over all the registers and try to
     636             * make a bitmask of the ones we're interested in.
     637             *
     638             * Relative addressing tokens are ignored, but that's
     639             * okay, since we'll catch any address registers when
     640             * they are initialized (required by spec). */
     641            if (ins.dst_count)
     642            {
     643                struct wined3d_shader_src_param dst_rel_addr;
     644                struct wined3d_shader_dst_param dst_param;
     645
     646                fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr);
     647
     648                shader_record_register_usage(shader, reg_maps, &dst_param.reg, shader_version.type);
     649
     650                /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
     651                 * is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
     652                 * shaders because TECRDOUT isn't used in them, but future register types might cause issues */
     653                if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX && shader_version.major < 3
     654                        && dst_param.reg.type == WINED3DSPR_TEXCRDOUT)
     655                {
     656                    reg_maps->texcoord_mask[dst_param.reg.idx] |= dst_param.write_mask;
     657                }
     658
     659                if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
     660                {
     661                    IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)shader;
     662
     663                    if (dst_param.reg.type == WINED3DSPR_COLOROUT && dst_param.reg.idx == 0)
     664                    {
     665                    /* Many 2.0 and 3.0 pixel shaders end with a MOV from a temp register to
     666                     * COLOROUT 0. If we know this in advance, the ARB shader backend can skip
     667                     * the mov and perform the sRGB write correction from the source register.
     668                     *
     669                     * However, if the mov is only partial, we can't do this, and if the write
     670                     * comes from an instruction other than MOV it is hard to do as well. If
     671                     * COLOROUT 0 is overwritten partially later, the marker is dropped again. */
     672
     673                        ps->color0_mov = FALSE;
     674                        if (ins.handler_idx == WINED3DSIH_MOV)
     675                        {
     676                            /* Used later when the source register is read. */
     677                            color0_mov = TRUE;
     678                        }
     679                    }
     680                    /* Also drop the MOV marker if the source register is overwritten prior to the shader
     681                     * end
     682                     */
     683                    else if (dst_param.reg.type == WINED3DSPR_TEMP && dst_param.reg.idx == ps->color0_reg)
     684                    {
     685                        ps->color0_mov = FALSE;
     686                    }
     687                }
     688
     689                /* Declare 1.x samplers implicitly, based on the destination reg. number. */
     690                if (shader_version.major == 1
     691                        && (ins.handler_idx == WINED3DSIH_TEX
     692                            || ins.handler_idx == WINED3DSIH_TEXBEM
     693                            || ins.handler_idx == WINED3DSIH_TEXBEML
     694                            || ins.handler_idx == WINED3DSIH_TEXDP3TEX
     695                            || ins.handler_idx == WINED3DSIH_TEXM3x2TEX
     696                            || ins.handler_idx == WINED3DSIH_TEXM3x3SPEC
     697                            || ins.handler_idx == WINED3DSIH_TEXM3x3TEX
     698                            || ins.handler_idx == WINED3DSIH_TEXM3x3VSPEC
     699                            || ins.handler_idx == WINED3DSIH_TEXREG2AR
     700                            || ins.handler_idx == WINED3DSIH_TEXREG2GB
     701                            || ins.handler_idx == WINED3DSIH_TEXREG2RGB))
     702                {
     703                    /* Fake sampler usage, only set reserved bit and type. */
     704                    DWORD sampler_code = dst_param.reg.idx;
     705
     706                    TRACE("Setting fake 2D sampler for 1.x pixelshader.\n");
     707                    reg_maps->sampler_type[sampler_code] = WINED3DSTT_2D;
     708
     709                    /* texbem is only valid with < 1.4 pixel shaders */
     710                    if (ins.handler_idx == WINED3DSIH_TEXBEM
     711                            || ins.handler_idx == WINED3DSIH_TEXBEML)
     712                    {
     713                        reg_maps->bumpmat |= 1 << dst_param.reg.idx;
     714                        if (ins.handler_idx == WINED3DSIH_TEXBEML)
     715                        {
     716                            reg_maps->luminanceparams |= 1 << dst_param.reg.idx;
     717                        }
     718                    }
     719                }
     720                else if (ins.handler_idx == WINED3DSIH_BEM)
     721                {
     722                    reg_maps->bumpmat |= 1 << dst_param.reg.idx;
     723                }
     724            }
     725
     726            if (ins.handler_idx == WINED3DSIH_NRM) reg_maps->usesnrm = 1;
     727            else if (ins.handler_idx == WINED3DSIH_DSY) reg_maps->usesdsy = 1;
     728            else if (ins.handler_idx == WINED3DSIH_DSX) reg_maps->usesdsx = 1;
     729            else if (ins.handler_idx == WINED3DSIH_TEXLDD) reg_maps->usestexldd = 1;
     730            else if (ins.handler_idx == WINED3DSIH_TEXLDL) reg_maps->usestexldl = 1;
     731            else if (ins.handler_idx == WINED3DSIH_MOVA) reg_maps->usesmova = 1;
     732            else if (ins.handler_idx == WINED3DSIH_IFC) reg_maps->usesifc = 1;
     733            else if (ins.handler_idx == WINED3DSIH_CALL) reg_maps->usescall = 1;
     734
     735            limit = ins.src_count + (ins.predicate ? 1 : 0);
     736            for (i = 0; i < limit; ++i)
     737            {
     738                struct wined3d_shader_src_param src_param, src_rel_addr;
     739                unsigned int count;
     740
     741                fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
     742                count = get_instr_extra_regcount(ins.handler_idx, i);
     743
     744                shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type);
     745                while (count)
     746                {
     747                    ++src_param.reg.idx;
     748                    shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type);
     749                    --count;
     750                }
     751
     752                if (color0_mov)
     753                {
     754                    IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)shader;
     755                    if (src_param.reg.type == WINED3DSPR_TEMP
     756                            && src_param.swizzle == WINED3DSP_NOSWIZZLE)
     757                    {
     758                        ps->color0_mov = TRUE;
     759                        ps->color0_reg = src_param.reg.idx;
     760                    }
     761                }
     762            }
     763        }
     764    }
     765    reg_maps->loop_depth = max_loop_depth;
     766
     767    shader->baseShader.functionLength = ((const char *)ptr - (const char *)byte_code);
     768
     769    return WINED3D_OK;
     770}
     771
     772unsigned int shader_find_free_input_register(const struct shader_reg_maps *reg_maps, unsigned int max)
     773{
     774    DWORD map = 1 << max;
     775    map |= map - 1;
     776    map &= reg_maps->shader_version.major < 3 ? ~reg_maps->texcoord : ~reg_maps->input_registers;
     777
     778    return wined3d_log2i(map);
     779}
     780
     781static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semantic,
     782        const struct wined3d_shader_version *shader_version)
     783{
     784    TRACE("dcl");
     785
     786    if (semantic->reg.reg.type == WINED3DSPR_SAMPLER)
     787    {
     788        switch (semantic->sampler_type)
     789        {
     790            case WINED3DSTT_2D: TRACE("_2d"); break;
     791            case WINED3DSTT_CUBE: TRACE("_cube"); break;
     792            case WINED3DSTT_VOLUME: TRACE("_volume"); break;
     793            default: TRACE("_unknown_ttype(0x%08x)", semantic->sampler_type);
     794        }
     795    }
     796    else
     797    {
     798        /* Pixel shaders 3.0 don't have usage semantics. */
     799        if (shader_version->major < 3 && shader_version->type == WINED3D_SHADER_TYPE_PIXEL) return;
     800        else TRACE("_");
     801
     802        switch (semantic->usage)
     803        {
     804            case WINED3DDECLUSAGE_POSITION:
     805                TRACE("position%u", semantic->usage_idx);
     806                break;
     807
     808            case WINED3DDECLUSAGE_BLENDINDICES:
     809                TRACE("blend");
     810                break;
     811
     812            case WINED3DDECLUSAGE_BLENDWEIGHT:
     813                TRACE("weight");
     814                break;
     815
     816            case WINED3DDECLUSAGE_NORMAL:
     817                TRACE("normal%u", semantic->usage_idx);
     818                break;
     819
     820            case WINED3DDECLUSAGE_PSIZE:
     821                TRACE("psize");
     822                break;
     823
     824            case WINED3DDECLUSAGE_COLOR:
     825                if (semantic->usage_idx == 0) TRACE("color");
     826                else TRACE("specular%u", (semantic->usage_idx - 1));
     827                break;
     828
     829            case WINED3DDECLUSAGE_TEXCOORD:
     830                TRACE("texture%u", semantic->usage_idx);
     831                break;
     832
     833            case WINED3DDECLUSAGE_TANGENT:
     834                TRACE("tangent");
     835                break;
     836
     837            case WINED3DDECLUSAGE_BINORMAL:
     838                TRACE("binormal");
     839                break;
     840
     841            case WINED3DDECLUSAGE_TESSFACTOR:
     842                TRACE("tessfactor");
     843                break;
     844
     845            case WINED3DDECLUSAGE_POSITIONT:
     846                TRACE("positionT%u", semantic->usage_idx);
     847                break;
     848
     849            case WINED3DDECLUSAGE_FOG:
     850                TRACE("fog");
     851                break;
     852
     853            case WINED3DDECLUSAGE_DEPTH:
     854                TRACE("depth");
     855                break;
     856
     857            case WINED3DDECLUSAGE_SAMPLE:
     858                TRACE("sample");
     859                break;
     860
     861            default:
     862                FIXME("unknown_semantics(0x%08x)", semantic->usage);
     863        }
     864    }
     865}
     866
     867static void shader_dump_register(const struct wined3d_shader_register *reg,
     868        const struct wined3d_shader_version *shader_version)
     869{
     870    static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"};
     871    static const char * const misctype_reg_names[] = {"vPos", "vFace"};
     872    UINT offset = reg->idx;
     873
     874    switch (reg->type)
     875    {
     876        case WINED3DSPR_TEMP:
     877            TRACE("r");
     878            break;
     879
     880        case WINED3DSPR_INPUT:
     881            TRACE("v");
     882            break;
     883
     884        case WINED3DSPR_CONST:
     885        case WINED3DSPR_CONST2:
     886        case WINED3DSPR_CONST3:
     887        case WINED3DSPR_CONST4:
     888            TRACE("c");
     889            offset = shader_get_float_offset(reg->type, reg->idx);
     890            break;
     891
     892        case WINED3DSPR_TEXTURE: /* vs: case WINED3DSPR_ADDR */
     893            TRACE("%c", shader_version->type == WINED3D_SHADER_TYPE_PIXEL ? 't' : 'a');
     894            break;
     895
     896        case WINED3DSPR_RASTOUT:
     897            TRACE("%s", rastout_reg_names[reg->idx]);
     898            break;
     899
     900        case WINED3DSPR_COLOROUT:
     901            TRACE("oC");
     902            break;
     903
     904        case WINED3DSPR_DEPTHOUT:
     905            TRACE("oDepth");
     906            break;
     907
     908        case WINED3DSPR_ATTROUT:
     909            TRACE("oD");
     910            break;
     911
     912        case WINED3DSPR_TEXCRDOUT:
     913            /* Vertex shaders >= 3.0 use general purpose output registers
     914             * (WINED3DSPR_OUTPUT), which can include an address token. */
     915            if (shader_version->major >= 3) TRACE("o");
     916            else TRACE("oT");
     917            break;
     918
     919        case WINED3DSPR_CONSTINT:
     920            TRACE("i");
     921            break;
     922
     923        case WINED3DSPR_CONSTBOOL:
     924            TRACE("b");
     925            break;
     926
     927        case WINED3DSPR_LABEL:
     928            TRACE("l");
     929            break;
     930
     931        case WINED3DSPR_LOOP:
     932            TRACE("aL");
     933            break;
     934
     935        case WINED3DSPR_SAMPLER:
     936            TRACE("s");
     937            break;
     938
     939        case WINED3DSPR_MISCTYPE:
     940            if (reg->idx > 1) FIXME("Unhandled misctype register %u.\n", reg->idx);
     941            else TRACE("%s", misctype_reg_names[reg->idx]);
     942            break;
     943
     944        case WINED3DSPR_PREDICATE:
     945            TRACE("p");
     946            break;
     947
     948        case WINED3DSPR_IMMCONST:
     949            TRACE("l");
     950            break;
     951
     952        case WINED3DSPR_CONSTBUFFER:
     953            TRACE("cb");
     954            break;
     955
     956        default:
     957            TRACE("unhandled_rtype(%#x)", reg->type);
     958            break;
     959    }
     960
     961    if (reg->type == WINED3DSPR_IMMCONST)
     962    {
     963        TRACE("(");
     964        switch (reg->immconst_type)
     965        {
     966            case WINED3D_IMMCONST_FLOAT:
     967                TRACE("%.8e", *(const float *)reg->immconst_data);
     968                break;
     969
     970            case WINED3D_IMMCONST_FLOAT4:
     971                TRACE("%.8e, %.8e, %.8e, %.8e",
     972                        *(const float *)&reg->immconst_data[0], *(const float *)&reg->immconst_data[1],
     973                        *(const float *)&reg->immconst_data[2], *(const float *)&reg->immconst_data[3]);
     974                break;
     975
     976            default:
     977                TRACE("<unhandled immconst_type %#x>", reg->immconst_type);
     978                break;
     979        }
     980        TRACE(")");
     981    }
     982    else if (reg->type != WINED3DSPR_RASTOUT && reg->type != WINED3DSPR_MISCTYPE)
     983    {
     984        if (reg->array_idx != ~0U)
     985        {
     986            TRACE("%u[%u", offset, reg->array_idx);
     987            if (reg->rel_addr)
     988            {
     989                TRACE(" + ");
     990                shader_dump_src_param(reg->rel_addr, shader_version);
     991            }
     992            TRACE("]");
     993        }
     994        else
     995        {
     996            if (reg->rel_addr)
     997            {
     998                TRACE("[");
     999                shader_dump_src_param(reg->rel_addr, shader_version);
     1000                TRACE(" + ");
     1001            }
     1002            TRACE("%u", offset);
     1003            if (reg->rel_addr) TRACE("]");
     1004        }
     1005    }
     1006}
     1007
     1008void shader_dump_dst_param(const struct wined3d_shader_dst_param *param,
     1009        const struct wined3d_shader_version *shader_version)
     1010{
     1011    DWORD write_mask = param->write_mask;
     1012
     1013    shader_dump_register(&param->reg, shader_version);
     1014
     1015    if (write_mask != WINED3DSP_WRITEMASK_ALL)
     1016    {
     1017        static const char *write_mask_chars = "xyzw";
     1018
     1019        TRACE(".");
     1020        if (write_mask & WINED3DSP_WRITEMASK_0) TRACE("%c", write_mask_chars[0]);
     1021        if (write_mask & WINED3DSP_WRITEMASK_1) TRACE("%c", write_mask_chars[1]);
     1022        if (write_mask & WINED3DSP_WRITEMASK_2) TRACE("%c", write_mask_chars[2]);
     1023        if (write_mask & WINED3DSP_WRITEMASK_3) TRACE("%c", write_mask_chars[3]);
     1024    }
     1025}
     1026
     1027void shader_dump_src_param(const struct wined3d_shader_src_param *param,
     1028        const struct wined3d_shader_version *shader_version)
     1029{
     1030    DWORD src_modifier = param->modifiers;
     1031    DWORD swizzle = param->swizzle;
     1032
     1033    if (src_modifier == WINED3DSPSM_NEG
     1034            || src_modifier == WINED3DSPSM_BIASNEG
     1035            || src_modifier == WINED3DSPSM_SIGNNEG
     1036            || src_modifier == WINED3DSPSM_X2NEG
     1037            || src_modifier == WINED3DSPSM_ABSNEG)
     1038        TRACE("-");
     1039    else if (src_modifier == WINED3DSPSM_COMP)
     1040        TRACE("1-");
     1041    else if (src_modifier == WINED3DSPSM_NOT)
     1042        TRACE("!");
     1043
     1044    if (src_modifier == WINED3DSPSM_ABS || src_modifier == WINED3DSPSM_ABSNEG)
     1045        TRACE("abs(");
     1046
     1047    shader_dump_register(&param->reg, shader_version);
     1048
     1049    if (src_modifier)
     1050    {
     1051        switch (src_modifier)
     1052        {
     1053            case WINED3DSPSM_NONE:    break;
     1054            case WINED3DSPSM_NEG:     break;
     1055            case WINED3DSPSM_NOT:     break;
     1056            case WINED3DSPSM_BIAS:    TRACE("_bias"); break;
     1057            case WINED3DSPSM_BIASNEG: TRACE("_bias"); break;
     1058            case WINED3DSPSM_SIGN:    TRACE("_bx2"); break;
     1059            case WINED3DSPSM_SIGNNEG: TRACE("_bx2"); break;
     1060            case WINED3DSPSM_COMP:    break;
     1061            case WINED3DSPSM_X2:      TRACE("_x2"); break;
     1062            case WINED3DSPSM_X2NEG:   TRACE("_x2"); break;
     1063            case WINED3DSPSM_DZ:      TRACE("_dz"); break;
     1064            case WINED3DSPSM_DW:      TRACE("_dw"); break;
     1065            case WINED3DSPSM_ABSNEG:  TRACE(")"); break;
     1066            case WINED3DSPSM_ABS:     TRACE(")"); break;
     1067            default:                  TRACE("_unknown_modifier(%#x)", src_modifier);
     1068        }
     1069    }
     1070
     1071    if (swizzle != WINED3DSP_NOSWIZZLE)
     1072    {
     1073        static const char *swizzle_chars = "xyzw";
     1074        DWORD swizzle_x = swizzle & 0x03;
     1075        DWORD swizzle_y = (swizzle >> 2) & 0x03;
     1076        DWORD swizzle_z = (swizzle >> 4) & 0x03;
     1077        DWORD swizzle_w = (swizzle >> 6) & 0x03;
     1078
     1079        if (swizzle_x == swizzle_y
     1080                && swizzle_x == swizzle_z
     1081                && swizzle_x == swizzle_w)
     1082        {
     1083            TRACE(".%c", swizzle_chars[swizzle_x]);
     1084        }
     1085        else
     1086        {
     1087            TRACE(".%c%c%c%c", swizzle_chars[swizzle_x], swizzle_chars[swizzle_y],
     1088                    swizzle_chars[swizzle_z], swizzle_chars[swizzle_w]);
     1089        }
     1090    }
     1091}
     1092
     1093/* Shared code in order to generate the bulk of the shader string.
     1094 * NOTE: A description of how to parse tokens can be found on MSDN. */
     1095void shader_generate_main(IWineD3DBaseShader *iface, struct wined3d_shader_buffer *buffer,
     1096        const shader_reg_maps *reg_maps, const DWORD *byte_code, void *backend_ctx)
     1097{
     1098    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface;
     1099    IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)shader->baseShader.device;
     1100    const struct wined3d_shader_frontend *fe = shader->baseShader.frontend;
     1101    void *fe_data = shader->baseShader.frontend_data;
     1102    struct wined3d_shader_src_param src_rel_addr[4];
     1103    struct wined3d_shader_src_param src_param[4];
     1104    struct wined3d_shader_version shader_version;
     1105    struct wined3d_shader_src_param dst_rel_addr;
     1106    struct wined3d_shader_dst_param dst_param;
     1107    struct wined3d_shader_instruction ins;
     1108    struct wined3d_shader_context ctx;
     1109    const DWORD *ptr = byte_code;
     1110    DWORD i;
     1111
     1112    /* Initialize current parsing state. */
     1113    ctx.shader = iface;
     1114    ctx.gl_info = &device->adapter->gl_info;
     1115    ctx.reg_maps = reg_maps;
     1116    ctx.buffer = buffer;
     1117    ctx.backend_data = backend_ctx;
     1118
     1119    ins.ctx = &ctx;
     1120    ins.dst = &dst_param;
     1121    ins.src = src_param;
     1122    shader->baseShader.parse_state.current_row = 0;
     1123
     1124    fe->shader_read_header(fe_data, &ptr, &shader_version);
     1125
     1126    while (!fe->shader_is_end(fe_data, &ptr))
     1127    {
     1128        const char *comment;
     1129        UINT comment_size;
     1130        UINT param_size;
     1131
     1132        /* Skip comment tokens. */
     1133        fe->shader_read_comment(&ptr, &comment, &comment_size);
     1134        if (comment) continue;
     1135
     1136        /* Read opcode. */
     1137        fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
     1138
     1139        /* Unknown opcode and its parameters. */
     1140        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
     1141        {
     1142            TRACE("Skipping unrecognized instruction.\n");
     1143            ptr += param_size;
     1144            continue;
     1145        }
     1146
     1147        /* Nothing to do. */
     1148        if (ins.handler_idx == WINED3DSIH_DCL
     1149                || ins.handler_idx == WINED3DSIH_NOP
     1150                || ins.handler_idx == WINED3DSIH_DEF
     1151                || ins.handler_idx == WINED3DSIH_DEFI
     1152                || ins.handler_idx == WINED3DSIH_DEFB
     1153                || ins.handler_idx == WINED3DSIH_PHASE)
     1154        {
     1155            ptr += param_size;
     1156            continue;
     1157        }
     1158
     1159        /* Destination token */
     1160        if (ins.dst_count) fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr);
     1161
     1162        /* Predication token */
     1163        if (ins.predicate)
     1164        {
     1165            FIXME("Predicates not implemented.\n");
     1166            ins.predicate = *ptr++;
     1167        }
     1168
     1169        /* Other source tokens */
     1170        for (i = 0; i < ins.src_count; ++i)
     1171        {
     1172            fe->shader_read_src_param(fe_data, &ptr, &src_param[i], &src_rel_addr[i]);
     1173        }
     1174
     1175        /* Call appropriate function for output target */
     1176        device->shader_backend->shader_handle_instruction(&ins);
     1177    }
     1178}
     1179
     1180static void shader_dump_ins_modifiers(const struct wined3d_shader_dst_param *dst)
     1181{
     1182    DWORD mmask = dst->modifiers;
     1183
     1184    switch (dst->shift)
     1185    {
     1186        case 0: break;
     1187        case 13: TRACE("_d8"); break;
     1188        case 14: TRACE("_d4"); break;
     1189        case 15: TRACE("_d2"); break;
     1190        case 1: TRACE("_x2"); break;
     1191        case 2: TRACE("_x4"); break;
     1192        case 3: TRACE("_x8"); break;
     1193        default: TRACE("_unhandled_shift(%d)", dst->shift); break;
     1194    }
     1195
     1196    if (mmask & WINED3DSPDM_SATURATE)         TRACE("_sat");
     1197    if (mmask & WINED3DSPDM_PARTIALPRECISION) TRACE("_pp");
     1198    if (mmask & WINED3DSPDM_MSAMPCENTROID)    TRACE("_centroid");
     1199
     1200    mmask &= ~(WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION | WINED3DSPDM_MSAMPCENTROID);
     1201    if (mmask) FIXME("_unrecognized_modifier(%#x)", mmask);
     1202}
     1203
     1204static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe_data, const DWORD *byte_code)
     1205{
     1206    struct wined3d_shader_version shader_version;
     1207    const DWORD *ptr = byte_code;
     1208    const char *type_prefix;
     1209    DWORD i;
     1210
     1211    TRACE("Parsing %p.\n", byte_code);
     1212
     1213    fe->shader_read_header(fe_data, &ptr, &shader_version);
     1214
     1215    switch (shader_version.type)
     1216    {
     1217        case WINED3D_SHADER_TYPE_VERTEX:
     1218            type_prefix = "vs";
     1219            break;
     1220
     1221        case WINED3D_SHADER_TYPE_GEOMETRY:
     1222            type_prefix = "gs";
     1223            break;
     1224
     1225        case WINED3D_SHADER_TYPE_PIXEL:
     1226            type_prefix = "ps";
     1227            break;
     1228
     1229        default:
     1230            FIXME("Unhandled shader type %#x.\n", shader_version.type);
     1231            type_prefix = "unknown";
     1232            break;
     1233    }
     1234
     1235    TRACE("%s_%u_%u\n", type_prefix, shader_version.major, shader_version.minor);
     1236
     1237    while (!fe->shader_is_end(fe_data, &ptr))
     1238    {
     1239        struct wined3d_shader_instruction ins;
     1240        const char *comment;
     1241        UINT comment_size;
     1242        UINT param_size;
     1243
     1244        /* comment */
     1245        fe->shader_read_comment(&ptr, &comment, &comment_size);
     1246        if (comment)
     1247        {
     1248            if (comment_size > 4 && *(const DWORD *)comment == WINEMAKEFOURCC('T', 'E', 'X', 'T'))
     1249            {
     1250                const char *end = comment + comment_size;
     1251                const char *ptr = comment + 4;
     1252                const char *line = ptr;
     1253
     1254                TRACE("// TEXT\n");
     1255                while (ptr != end)
     1256                {
     1257                    if (*ptr == '\n')
     1258                    {
     1259                        UINT len = ptr - line;
     1260                        if (len && *(ptr - 1) == '\r') --len;
     1261                        TRACE("// %s\n", debugstr_an(line, len));
     1262                        line = ++ptr;
     1263                    }
     1264                    else ++ptr;
     1265                }
     1266                if (line != ptr) TRACE("// %s\n", debugstr_an(line, ptr - line));
     1267            }
     1268            else TRACE("// %s\n", debugstr_an(comment, comment_size));
     1269            continue;
     1270        }
     1271
     1272        fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
     1273        if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
     1274        {
     1275            TRACE("Skipping unrecognized instruction.\n");
     1276            ptr += param_size;
     1277            continue;
     1278        }
     1279
     1280        if (ins.handler_idx == WINED3DSIH_DCL)
     1281        {
     1282            struct wined3d_shader_semantic semantic;
     1283
     1284            fe->shader_read_semantic(&ptr, &semantic);
     1285
     1286            shader_dump_decl_usage(&semantic, &shader_version);
     1287            shader_dump_ins_modifiers(&semantic.reg);
     1288            TRACE(" ");
     1289            shader_dump_dst_param(&semantic.reg, &shader_version);
     1290        }
     1291        else if (ins.handler_idx == WINED3DSIH_DEF)
     1292        {
     1293            struct wined3d_shader_src_param rel_addr;
     1294            struct wined3d_shader_dst_param dst;
     1295
     1296            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
     1297
     1298            TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(dst.reg.type, dst.reg.idx),
     1299                    *(const float *)(ptr),
     1300                    *(const float *)(ptr + 1),
     1301                    *(const float *)(ptr + 2),
     1302                    *(const float *)(ptr + 3));
     1303            ptr += 4;
     1304        }
     1305        else if (ins.handler_idx == WINED3DSIH_DEFI)
     1306        {
     1307            struct wined3d_shader_src_param rel_addr;
     1308            struct wined3d_shader_dst_param dst;
     1309
     1310            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
     1311
     1312            TRACE("defi i%u = %d, %d, %d, %d", dst.reg.idx,
     1313                    *(ptr),
     1314                    *(ptr + 1),
     1315                    *(ptr + 2),
     1316                    *(ptr + 3));
     1317            ptr += 4;
     1318        }
     1319        else if (ins.handler_idx == WINED3DSIH_DEFB)
     1320        {
     1321            struct wined3d_shader_src_param rel_addr;
     1322            struct wined3d_shader_dst_param dst;
     1323
     1324            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
     1325
     1326            TRACE("defb b%u = %s", dst.reg.idx, *ptr ? "true" : "false");
     1327            ++ptr;
     1328        }
     1329        else
     1330        {
     1331            struct wined3d_shader_src_param dst_rel_addr, src_rel_addr;
     1332            struct wined3d_shader_dst_param dst_param;
     1333            struct wined3d_shader_src_param src_param;
     1334
     1335            if (ins.dst_count)
     1336            {
     1337                fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr);
     1338            }
     1339
     1340            /* Print out predication source token first - it follows
     1341             * the destination token. */
     1342            if (ins.predicate)
     1343            {
     1344                fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
     1345                TRACE("(");
     1346                shader_dump_src_param(&src_param, &shader_version);
     1347                TRACE(") ");
     1348            }
     1349
     1350            /* PixWin marks instructions with the coissue flag with a '+' */
     1351            if (ins.coissue) TRACE("+");
     1352
     1353            TRACE("%s", shader_opcode_names[ins.handler_idx]);
     1354
     1355            if (ins.handler_idx == WINED3DSIH_IFC
     1356                    || ins.handler_idx == WINED3DSIH_BREAKC)
     1357            {
     1358                switch (ins.flags)
     1359                {
     1360                    case COMPARISON_GT: TRACE("_gt"); break;
     1361                    case COMPARISON_EQ: TRACE("_eq"); break;
     1362                    case COMPARISON_GE: TRACE("_ge"); break;
     1363                    case COMPARISON_LT: TRACE("_lt"); break;
     1364                    case COMPARISON_NE: TRACE("_ne"); break;
     1365                    case COMPARISON_LE: TRACE("_le"); break;
     1366                    default: TRACE("_(%u)", ins.flags);
     1367                }
     1368            }
     1369            else if (ins.handler_idx == WINED3DSIH_TEX
     1370                    && shader_version.major >= 2
     1371                    && (ins.flags & WINED3DSI_TEXLD_PROJECT))
     1372            {
     1373                TRACE("p");
     1374            }
     1375
     1376            /* We already read the destination token, print it. */
     1377            if (ins.dst_count)
     1378            {
     1379                shader_dump_ins_modifiers(&dst_param);
     1380                TRACE(" ");
     1381                shader_dump_dst_param(&dst_param, &shader_version);
     1382            }
     1383
     1384            /* Other source tokens */
     1385            for (i = ins.dst_count; i < (ins.dst_count + ins.src_count); ++i)
     1386            {
     1387                fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
     1388                TRACE(!i ? " " : ", ");
     1389                shader_dump_src_param(&src_param, &shader_version);
     1390            }
     1391        }
     1392        TRACE("\n");
     1393    }
     1394}
     1395
     1396static void shader_cleanup(IWineD3DBaseShader *iface)
     1397{
     1398    IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface;
     1399
     1400    ((IWineD3DDeviceImpl *)shader->baseShader.device)->shader_backend->shader_destroy(iface);
     1401    HeapFree(GetProcessHeap(), 0, shader->baseShader.reg_maps.constf);
     1402    HeapFree(GetProcessHeap(), 0, shader->baseShader.function);
     1403    shader_delete_constant_list(&shader->baseShader.constantsF);
     1404    shader_delete_constant_list(&shader->baseShader.constantsB);
     1405    shader_delete_constant_list(&shader->baseShader.constantsI);
     1406    list_remove(&shader->baseShader.shader_list_entry);
     1407
     1408    if (shader->baseShader.frontend && shader->baseShader.frontend_data)
     1409    {
     1410        shader->baseShader.frontend->shader_free(shader->baseShader.frontend_data);
     1411    }
     1412}
     1413
     1414static void shader_none_handle_instruction(const struct wined3d_shader_instruction *ins) {}
     1415static void shader_none_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) {}
     1416static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {}
     1417static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {}
     1418static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
     1419static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
     1420static void shader_none_load_constants(const struct wined3d_context *context, char usePS, char useVS) {}
     1421static void shader_none_load_np2fixup_constants(IWineD3DDevice *iface, char usePS, char useVS) {}
     1422static void shader_none_destroy(IWineD3DBaseShader *iface) {}
     1423static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
     1424static void shader_none_free(IWineD3DDevice *iface) {}
     1425static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;}
     1426
     1427static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
     1428{
     1429    /* Set the shader caps to 0 for the none shader backend */
     1430    caps->VertexShaderVersion = 0;
     1431    caps->PixelShaderVersion = 0;
     1432    caps->PixelShader1xMaxValue = 0.0f;
     1433}
     1434
     1435static BOOL shader_none_color_fixup_supported(struct color_fixup_desc fixup)
     1436{
     1437    if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
     1438    {
     1439        TRACE("Checking support for fixup:\n");
     1440        dump_color_fixup_desc(fixup);
     1441    }
     1442
     1443    /* Faked to make some apps happy. */
     1444    if (!is_complex_fixup(fixup))
     1445    {
     1446        TRACE("[OK]\n");
     1447        return TRUE;
     1448    }
     1449
     1450    TRACE("[FAILED]\n");
     1451    return FALSE;
     1452}
     1453
     1454const shader_backend_t none_shader_backend = {
     1455    shader_none_handle_instruction,
     1456    shader_none_select,
     1457    shader_none_select_depth_blt,
     1458    shader_none_deselect_depth_blt,
     1459    shader_none_update_float_vertex_constants,
     1460    shader_none_update_float_pixel_constants,
     1461    shader_none_load_constants,
     1462    shader_none_load_np2fixup_constants,
     1463    shader_none_destroy,
     1464    shader_none_alloc,
     1465    shader_none_free,
     1466    shader_none_dirty_const,
     1467    shader_none_get_caps,
     1468    shader_none_color_fixup_supported,
     1469};
    421470
    431471static void shader_get_parent(IWineD3DBaseShaderImpl *shader, IUnknown **parent)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette