Home | History | Annotate | Download | only in state_tracker
      1 /**************************************************************************
      2  *
      3  * Copyright 2003 VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28  /*
     29   * Authors:
     30   *   Keith Whitwell <keithw (at) vmware.com>
     31   */
     32 
     33 #include "main/glheader.h"
     34 #include "main/macros.h"
     35 #include "main/enums.h"
     36 #include "main/shaderapi.h"
     37 #include "program/prog_instruction.h"
     38 #include "program/program.h"
     39 
     40 #include "cso_cache/cso_context.h"
     41 #include "draw/draw_context.h"
     42 
     43 #include "st_context.h"
     44 #include "st_debug.h"
     45 #include "st_program.h"
     46 #include "st_mesa_to_tgsi.h"
     47 #include "st_cb_program.h"
     48 #include "st_glsl_to_tgsi.h"
     49 #include "st_atifs_to_tgsi.h"
     50 
     51 
     52 /**
     53  * Called via ctx->Driver.NewProgram() to allocate a new vertex or
     54  * fragment program.
     55  */
     56 static struct gl_program *
     57 st_new_program(struct gl_context *ctx, GLenum target, GLuint id,
     58                bool is_arb_asm)
     59 {
     60    switch (target) {
     61    case GL_VERTEX_PROGRAM_ARB: {
     62       struct st_vertex_program *prog = rzalloc(NULL,
     63                                                struct st_vertex_program);
     64       return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm);
     65    }
     66    case GL_FRAGMENT_PROGRAM_ARB: {
     67       struct st_fragment_program *prog = rzalloc(NULL,
     68                                                  struct st_fragment_program);
     69       return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm);
     70    }
     71    case GL_GEOMETRY_PROGRAM_NV: {
     72       struct st_geometry_program *prog = rzalloc(NULL,
     73                                                  struct st_geometry_program);
     74       return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm);
     75    }
     76    case GL_TESS_CONTROL_PROGRAM_NV: {
     77       struct st_tessctrl_program *prog = rzalloc(NULL,
     78                                                  struct st_tessctrl_program);
     79       return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm);
     80    }
     81    case GL_TESS_EVALUATION_PROGRAM_NV: {
     82       struct st_tesseval_program *prog = rzalloc(NULL,
     83                                                  struct st_tesseval_program);
     84       return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm);
     85    }
     86    case GL_COMPUTE_PROGRAM_NV: {
     87       struct st_compute_program *prog = rzalloc(NULL,
     88                                                 struct st_compute_program);
     89       return _mesa_init_gl_program(&prog->Base, target, id, is_arb_asm);
     90    }
     91    default:
     92       assert(0);
     93       return NULL;
     94    }
     95 }
     96 
     97 
     98 /**
     99  * Called via ctx->Driver.DeleteProgram()
    100  */
    101 static void
    102 st_delete_program(struct gl_context *ctx, struct gl_program *prog)
    103 {
    104    struct st_context *st = st_context(ctx);
    105 
    106    switch( prog->Target ) {
    107    case GL_VERTEX_PROGRAM_ARB:
    108       {
    109          struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
    110          st_release_vp_variants( st, stvp );
    111 
    112          if (stvp->glsl_to_tgsi)
    113             free_glsl_to_tgsi_visitor(stvp->glsl_to_tgsi);
    114       }
    115       break;
    116    case GL_GEOMETRY_PROGRAM_NV:
    117       {
    118          struct st_geometry_program *stgp =
    119             (struct st_geometry_program *) prog;
    120 
    121          st_release_basic_variants(st, stgp->Base.Target, &stgp->variants,
    122                                    &stgp->tgsi);
    123 
    124          if (stgp->glsl_to_tgsi)
    125             free_glsl_to_tgsi_visitor(stgp->glsl_to_tgsi);
    126       }
    127       break;
    128    case GL_FRAGMENT_PROGRAM_ARB:
    129       {
    130          struct st_fragment_program *stfp =
    131             (struct st_fragment_program *) prog;
    132 
    133          st_release_fp_variants(st, stfp);
    134 
    135          if (stfp->glsl_to_tgsi)
    136             free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi);
    137       }
    138       break;
    139    case GL_TESS_CONTROL_PROGRAM_NV:
    140       {
    141          struct st_tessctrl_program *sttcp =
    142             (struct st_tessctrl_program *) prog;
    143 
    144          st_release_basic_variants(st, sttcp->Base.Target, &sttcp->variants,
    145                                    &sttcp->tgsi);
    146 
    147          if (sttcp->glsl_to_tgsi)
    148             free_glsl_to_tgsi_visitor(sttcp->glsl_to_tgsi);
    149       }
    150       break;
    151    case GL_TESS_EVALUATION_PROGRAM_NV:
    152       {
    153          struct st_tesseval_program *sttep =
    154             (struct st_tesseval_program *) prog;
    155 
    156          st_release_basic_variants(st, sttep->Base.Target,
    157                                    &sttep->variants, &sttep->tgsi);
    158 
    159          if (sttep->glsl_to_tgsi)
    160             free_glsl_to_tgsi_visitor(sttep->glsl_to_tgsi);
    161       }
    162       break;
    163    case GL_COMPUTE_PROGRAM_NV:
    164       {
    165          struct st_compute_program *stcp =
    166             (struct st_compute_program *) prog;
    167 
    168          st_release_cp_variants(st, stcp);
    169 
    170          if (stcp->glsl_to_tgsi)
    171             free_glsl_to_tgsi_visitor(stcp->glsl_to_tgsi);
    172       }
    173       break;
    174    default:
    175       assert(0); /* problem */
    176    }
    177 
    178    /* delete base class */
    179    _mesa_delete_program( ctx, prog );
    180 }
    181 
    182 
    183 /**
    184  * Called via ctx->Driver.ProgramStringNotify()
    185  * Called when the program's text/code is changed.  We have to free
    186  * all shader variants and corresponding gallium shaders when this happens.
    187  */
    188 static GLboolean
    189 st_program_string_notify( struct gl_context *ctx,
    190                                            GLenum target,
    191                                            struct gl_program *prog )
    192 {
    193    struct st_context *st = st_context(ctx);
    194    gl_shader_stage stage = _mesa_program_enum_to_shader_stage(target);
    195 
    196    if (target == GL_FRAGMENT_PROGRAM_ARB) {
    197       struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
    198 
    199       st_release_fp_variants(st, stfp);
    200       if (!st_translate_fragment_program(st, stfp))
    201          return false;
    202 
    203       if (st->fp == stfp)
    204 	 st->dirty |= stfp->affected_states;
    205    }
    206    else if (target == GL_GEOMETRY_PROGRAM_NV) {
    207       struct st_geometry_program *stgp = (struct st_geometry_program *) prog;
    208 
    209       st_release_basic_variants(st, stgp->Base.Target, &stgp->variants,
    210                                 &stgp->tgsi);
    211       if (!st_translate_geometry_program(st, stgp))
    212          return false;
    213 
    214       if (st->gp == stgp)
    215 	 st->dirty |= stgp->affected_states;
    216    }
    217    else if (target == GL_VERTEX_PROGRAM_ARB) {
    218       struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
    219 
    220       st_release_vp_variants(st, stvp);
    221       if (!st_translate_vertex_program(st, stvp))
    222          return false;
    223 
    224       if (st->vp == stvp)
    225 	 st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp);
    226    }
    227    else if (target == GL_TESS_CONTROL_PROGRAM_NV) {
    228       struct st_tessctrl_program *sttcp =
    229          (struct st_tessctrl_program *) prog;
    230 
    231       st_release_basic_variants(st, sttcp->Base.Target, &sttcp->variants,
    232                                 &sttcp->tgsi);
    233       if (!st_translate_tessctrl_program(st, sttcp))
    234          return false;
    235 
    236       if (st->tcp == sttcp)
    237          st->dirty |= sttcp->affected_states;
    238    }
    239    else if (target == GL_TESS_EVALUATION_PROGRAM_NV) {
    240       struct st_tesseval_program *sttep =
    241          (struct st_tesseval_program *) prog;
    242 
    243       st_release_basic_variants(st, sttep->Base.Target, &sttep->variants,
    244                                 &sttep->tgsi);
    245       if (!st_translate_tesseval_program(st, sttep))
    246          return false;
    247 
    248       if (st->tep == sttep)
    249          st->dirty |= sttep->affected_states;
    250    }
    251    else if (target == GL_COMPUTE_PROGRAM_NV) {
    252       struct st_compute_program *stcp =
    253          (struct st_compute_program *) prog;
    254 
    255       st_release_cp_variants(st, stcp);
    256       if (!st_translate_compute_program(st, stcp))
    257          return false;
    258 
    259       if (st->cp == stcp)
    260          st->dirty |= stcp->affected_states;
    261    }
    262    else if (target == GL_FRAGMENT_SHADER_ATI) {
    263       assert(prog);
    264 
    265       struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
    266       assert(stfp->ati_fs);
    267       assert(stfp->ati_fs->Program == prog);
    268 
    269       st_init_atifs_prog(ctx, prog);
    270 
    271       st_release_fp_variants(st, stfp);
    272       if (!st_translate_fragment_program(st, stfp))
    273          return false;
    274 
    275       if (st->fp == stfp)
    276          st->dirty |= stfp->affected_states;
    277    }
    278 
    279    if (ST_DEBUG & DEBUG_PRECOMPILE ||
    280        st->shader_has_one_variant[stage])
    281       st_precompile_shader_variant(st, prog);
    282 
    283    return GL_TRUE;
    284 }
    285 
    286 /**
    287  * Called via ctx->Driver.NewATIfs()
    288  * Called in glEndFragmentShaderATI()
    289  */
    290 static struct gl_program *
    291 st_new_ati_fs(struct gl_context *ctx, struct ati_fragment_shader *curProg)
    292 {
    293    struct gl_program *prog = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
    294          curProg->Id, true);
    295    struct st_fragment_program *stfp = (struct st_fragment_program *)prog;
    296    stfp->ati_fs = curProg;
    297    return prog;
    298 }
    299 
    300 /**
    301  * Plug in the program and shader-related device driver functions.
    302  */
    303 void
    304 st_init_program_functions(struct dd_function_table *functions)
    305 {
    306    functions->NewProgram = st_new_program;
    307    functions->DeleteProgram = st_delete_program;
    308    functions->ProgramStringNotify = st_program_string_notify;
    309    functions->NewATIfs = st_new_ati_fs;
    310 
    311    functions->LinkShader = st_link_shader;
    312 }
    313