~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/shader/slang/slang_link.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Mesa 3-D graphics library
 
3
 * Version:  6.5.3
 
4
 *
 
5
 * Copyright (C) 2007  Brian Paul   All Rights Reserved.
 
6
 *
 
7
 * Permission is hereby granted, free of charge, to any person obtaining a
 
8
 * copy of this software and associated documentation files (the "Software"),
 
9
 * to deal in the Software without restriction, including without limitation
 
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
11
 * and/or sell copies of the Software, and to permit persons to whom the
 
12
 * Software is furnished to do so, subject to the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice shall be included
 
15
 * in all copies or substantial portions of the Software.
 
16
 *
 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
20
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
21
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 */
 
24
 
 
25
/**
 
26
 * \file slang_link.c
 
27
 * GLSL linker
 
28
 * \author Brian Paul
 
29
 */
 
30
 
 
31
#include "imports.h"
 
32
#include "context.h"
 
33
#include "hash.h"
 
34
#include "macros.h"
 
35
#include "program.h"
 
36
#include "prog_instruction.h"
 
37
#include "prog_parameter.h"
 
38
#include "prog_print.h"
 
39
#include "prog_statevars.h"
 
40
#include "shader_api.h"
 
41
#include "slang_link.h"
 
42
 
 
43
 
 
44
 
 
45
 
 
46
static GLboolean
 
47
link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 
48
{
 
49
   GLuint *map, i, firstVarying, newFile;
 
50
   GLbitfield varsWritten, varsRead;
 
51
 
 
52
   map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
 
53
   if (!map)
 
54
      return GL_FALSE;
 
55
 
 
56
   for (i = 0; i < prog->Varying->NumParameters; i++) {
 
57
      /* see if this varying is in the linked varying list */
 
58
      const struct gl_program_parameter *var
 
59
         = prog->Varying->Parameters + i;
 
60
 
 
61
      GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name);
 
62
      if (j >= 0) {
 
63
         /* already in list, check size */
 
64
         if (var->Size != shProg->Varying->Parameters[j].Size) {
 
65
            /* error */
 
66
            return GL_FALSE;
 
67
         }
 
68
      }
 
69
      else {
 
70
         /* not already in linked list */
 
71
         j = _mesa_add_varying(shProg->Varying, var->Name, var->Size);
 
72
      }
 
73
      ASSERT(j >= 0);
 
74
 
 
75
      map[i] = j;
 
76
   }
 
77
 
 
78
 
 
79
   /* Varying variables are treated like other vertex program outputs
 
80
    * (and like other fragment program inputs).  The position of the
 
81
    * first varying differs for vertex/fragment programs...
 
82
    * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT.
 
83
    */
 
84
   if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
 
85
      firstVarying = VERT_RESULT_VAR0;
 
86
      newFile = PROGRAM_OUTPUT;
 
87
   }
 
88
   else {
 
89
      assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
 
90
      firstVarying = FRAG_ATTRIB_VAR0;
 
91
      newFile = PROGRAM_INPUT;
 
92
   }
 
93
 
 
94
   /* keep track of which varying vars we read and write */
 
95
   varsWritten = varsRead = 0x0;
 
96
 
 
97
   /* OK, now scan the program/shader instructions looking for varying vars,
 
98
    * replacing the old index with the new index.
 
99
    */
 
100
   for (i = 0; i < prog->NumInstructions; i++) {
 
101
      struct prog_instruction *inst = prog->Instructions + i;
 
102
      GLuint j;
 
103
 
 
104
      if (inst->DstReg.File == PROGRAM_VARYING) {
 
105
         inst->DstReg.File = newFile;
 
106
         inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying;
 
107
         varsWritten |= (1 << inst->DstReg.Index);
 
108
      }
 
109
 
 
110
      for (j = 0; j < 3; j++) {
 
111
         if (inst->SrcReg[j].File == PROGRAM_VARYING) {
 
112
            inst->SrcReg[j].File = newFile;
 
113
            inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstVarying;
 
114
            varsRead |= (1 << inst->SrcReg[j].Index);
 
115
         }
 
116
      }
 
117
   }
 
118
 
 
119
   if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
 
120
      prog->OutputsWritten |= varsWritten;
 
121
      /*printf("VERT OUTPUTS: 0x%x \n", varsWritten);*/
 
122
   }
 
123
   else {
 
124
      assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
 
125
      prog->InputsRead |= varsRead;
 
126
      /*printf("FRAG INPUTS: 0x%x\n", varsRead);*/
 
127
   }
 
128
 
 
129
   free(map);
 
130
 
 
131
   return GL_TRUE;
 
132
}
 
133
 
 
134
 
 
135
static GLboolean
 
136
is_uniform(GLuint file)
 
137
{
 
138
   return (file == PROGRAM_ENV_PARAM ||
 
139
           file == PROGRAM_STATE_VAR ||
 
140
           file == PROGRAM_NAMED_PARAM ||
 
141
           file == PROGRAM_CONSTANT ||
 
142
           file == PROGRAM_SAMPLER ||
 
143
           file == PROGRAM_UNIFORM);
 
144
}
 
145
 
 
146
 
 
147
static GLboolean
 
148
link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 
149
{
 
150
   GLuint *map, i;
 
151
 
 
152
#if 0
 
153
   printf("================ pre link uniforms ===============\n");
 
154
   _mesa_print_parameter_list(shProg->Uniforms);
 
155
#endif
 
156
 
 
157
   map = (GLuint *) malloc(prog->Parameters->NumParameters * sizeof(GLuint));
 
158
   if (!map)
 
159
      return GL_FALSE;
 
160
 
 
161
   for (i = 0; i < prog->Parameters->NumParameters; /* incr below*/) {
 
162
      /* see if this uniform is in the linked uniform list */
 
163
      const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
 
164
      const GLfloat *pVals = prog->Parameters->ParameterValues[i];
 
165
      GLint j;
 
166
      GLint size;
 
167
 
 
168
      /* sanity check */
 
169
      assert(is_uniform(p->Type));
 
170
 
 
171
      if (p->Name) {
 
172
         j = _mesa_lookup_parameter_index(shProg->Uniforms, -1, p->Name);
 
173
      }
 
174
      else {
 
175
         /*GLuint swizzle;*/
 
176
         ASSERT(p->Type == PROGRAM_CONSTANT);
 
177
         if (_mesa_lookup_parameter_constant(shProg->Uniforms, pVals,
 
178
                                             p->Size, &j, NULL)) {
 
179
            assert(j >= 0);
 
180
         }
 
181
         else {
 
182
            j = -1;
 
183
         }
 
184
      }
 
185
 
 
186
      if (j >= 0) {
 
187
         /* already in list, check size XXX check this */
 
188
#if 0
 
189
         assert(p->Size == shProg->Uniforms->Parameters[j].Size);
 
190
#endif
 
191
      }
 
192
      else {
 
193
         /* not already in linked list */
 
194
         switch (p->Type) {
 
195
         case PROGRAM_ENV_PARAM:
 
196
            j = _mesa_add_named_parameter(shProg->Uniforms, p->Name, pVals);
 
197
            break;
 
198
         case PROGRAM_CONSTANT:
 
199
            j = _mesa_add_named_constant(shProg->Uniforms, p->Name, pVals, p->Size);
 
200
            break;
 
201
         case PROGRAM_STATE_VAR:
 
202
            j = _mesa_add_state_reference(shProg->Uniforms, p->StateIndexes);
 
203
            break;
 
204
         case PROGRAM_UNIFORM:
 
205
            j = _mesa_add_uniform(shProg->Uniforms, p->Name, p->Size, p->DataType);
 
206
            break;
 
207
         case PROGRAM_SAMPLER:
 
208
            j = _mesa_add_sampler(shProg->Uniforms, p->Name, p->DataType);
 
209
            break;
 
210
         default:
 
211
            _mesa_problem(NULL, "bad parameter type in link_uniform_vars()");
 
212
            return GL_FALSE;
 
213
         }
 
214
      }
 
215
 
 
216
      ASSERT(j >= 0);
 
217
 
 
218
      size = p->Size;
 
219
      while (size > 0) {
 
220
         map[i] = j;
 
221
         i++;
 
222
         j++;
 
223
         size -= 4;
 
224
      }
 
225
 
 
226
   }
 
227
 
 
228
#if 0
 
229
   printf("================ post link uniforms ===============\n");
 
230
   _mesa_print_parameter_list(shProg->Uniforms);
 
231
#endif
 
232
 
 
233
#if 0
 
234
   {
 
235
      GLuint i;
 
236
      for (i = 0; i < prog->Parameters->NumParameters; i++) {
 
237
         printf("map[%d] = %d\n", i, map[i]);
 
238
      }
 
239
      _mesa_print_parameter_list(shProg->Uniforms);
 
240
   }
 
241
#endif
 
242
 
 
243
   /* OK, now scan the program/shader instructions looking for uniform vars,
 
244
    * replacing the old index with the new index.
 
245
    */
 
246
   for (i = 0; i < prog->NumInstructions; i++) {
 
247
      struct prog_instruction *inst = prog->Instructions + i;
 
248
      GLuint j;
 
249
 
 
250
      if (is_uniform(inst->DstReg.File)) {
 
251
         inst->DstReg.Index = map[ inst->DstReg.Index ];
 
252
      }
 
253
 
 
254
      for (j = 0; j < 3; j++) {
 
255
         if (is_uniform(inst->SrcReg[j].File)) {
 
256
            inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ];
 
257
         }
 
258
      }
 
259
 
 
260
      if (inst->Opcode == OPCODE_TEX ||
 
261
          inst->Opcode == OPCODE_TXB ||
 
262
          inst->Opcode == OPCODE_TXP) {
 
263
         /*
 
264
         printf("====== remap sampler from %d to %d\n",
 
265
                inst->Sampler, map[ inst->Sampler ]);
 
266
         */
 
267
         inst->Sampler = map[ inst->Sampler ];
 
268
      }
 
269
   }
 
270
 
 
271
   free(map);
 
272
 
 
273
   return GL_TRUE;
 
274
}
 
275
 
 
276
 
 
277
/**
 
278
 * Resolve binding of generic vertex attributes.
 
279
 * For example, if the vertex shader declared "attribute vec4 foobar" we'll
 
280
 * allocate a generic vertex attribute for "foobar" and plug that value into
 
281
 * the vertex program instructions.
 
282
 */
 
283
static GLboolean
 
284
_slang_resolve_attributes(struct gl_shader_program *shProg,
 
285
                          struct gl_program *prog)
 
286
{
 
287
   GLuint i, j;
 
288
   GLbitfield usedAttributes;
 
289
   GLint size = 4; /* XXX fix */
 
290
 
 
291
   assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
 
292
 
 
293
   if (!shProg->Attributes)
 
294
      shProg->Attributes = _mesa_new_parameter_list();
 
295
 
 
296
   /* Build a bitmask indicating which attribute indexes have been
 
297
    * explicitly bound by the user with glBindAttributeLocation().
 
298
    */
 
299
   usedAttributes = 0x0;
 
300
   for (i = 0; i < shProg->Attributes->NumParameters; i++) {
 
301
      GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0];
 
302
      usedAttributes |= attr;
 
303
   }
 
304
 
 
305
   /*
 
306
    * Scan program for generic attribute references
 
307
    */
 
308
   for (i = 0; i < prog->NumInstructions; i++) {
 
309
      struct prog_instruction *inst = prog->Instructions + i;
 
310
      for (j = 0; j < 3; j++) {
 
311
         if (inst->SrcReg[j].File == PROGRAM_INPUT &&
 
312
             inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
 
313
            /* this is a generic attrib */
 
314
            const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
 
315
            const char *name = prog->Attributes->Parameters[k].Name;
 
316
            /* See if this attrib name is in the program's attribute list
 
317
             * (i.e. was bound by the user).
 
318
             */
 
319
            GLint index = _mesa_lookup_parameter_index(shProg->Attributes,
 
320
                                                          -1, name);
 
321
            GLint attr;
 
322
            if (index >= 0) {
 
323
               /* found, user must have specified a binding */
 
324
               attr = shProg->Attributes->Parameters[index].StateIndexes[0];
 
325
            }
 
326
            else {
 
327
               /* Not found, choose our own attribute number.
 
328
                * Start at 1 since generic attribute 0 always aliases
 
329
                * glVertex/position.
 
330
                */
 
331
               for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {
 
332
                  if (((1 << attr) & usedAttributes) == 0) {
 
333
                     usedAttributes |= (1 << attr);
 
334
                     break;
 
335
                  }
 
336
               }
 
337
               if (attr == MAX_VERTEX_ATTRIBS) {
 
338
                  /* too many!  XXX record error log */
 
339
                  return GL_FALSE;
 
340
               }
 
341
               _mesa_add_attribute(shProg->Attributes, name, size, attr);
 
342
            }
 
343
 
 
344
            inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;
 
345
         }
 
346
      }
 
347
   }
 
348
   return GL_TRUE;
 
349
}
 
350
 
 
351
 
 
352
/**
 
353
 * Scan program instructions to update the program's InputsRead and
 
354
 * OutputsWritten fields.
 
355
 */
 
356
static void
 
357
_slang_update_inputs_outputs(struct gl_program *prog)
 
358
{
 
359
   GLuint i, j;
 
360
 
 
361
   prog->InputsRead = 0x0;
 
362
   prog->OutputsWritten = 0x0;
 
363
 
 
364
   for (i = 0; i < prog->NumInstructions; i++) {
 
365
      const struct prog_instruction *inst = prog->Instructions + i;
 
366
      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
 
367
      for (j = 0; j < numSrc; j++) {
 
368
         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
 
369
            prog->InputsRead |= 1 << inst->SrcReg[j].Index;
 
370
         }
 
371
      }
 
372
      if (inst->DstReg.File == PROGRAM_OUTPUT) {
 
373
         prog->OutputsWritten |= 1 << inst->DstReg.Index;
 
374
      }
 
375
   }
 
376
}
 
377
 
 
378
 
 
379
/**
 
380
 * Scan a vertex program looking for instances of
 
381
 * (PROGRAM_INPUT, VERT_ATTRIB_GENERIC0 + oldAttrib) and replace with
 
382
 * (PROGRAM_INPUT, VERT_ATTRIB_GENERIC0 + newAttrib).
 
383
 * This is used when the user calls glBindAttribLocation on an already linked
 
384
 * shader program.
 
385
 */
 
386
void
 
387
_slang_remap_attribute(struct gl_program *prog, GLuint oldAttrib, GLuint newAttrib)
 
388
{
 
389
   GLuint i, j;
 
390
 
 
391
   assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
 
392
 
 
393
   for (i = 0; i < prog->NumInstructions; i++) {
 
394
      struct prog_instruction *inst = prog->Instructions + i;
 
395
      for (j = 0; j < 3; j++) {
 
396
         if (inst->SrcReg[j].File == PROGRAM_INPUT) {
 
397
            if (inst->SrcReg[j].Index == VERT_ATTRIB_GENERIC0 + oldAttrib) {
 
398
               inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + newAttrib;
 
399
            }
 
400
         }
 
401
      }
 
402
   }
 
403
 
 
404
   _slang_update_inputs_outputs(prog);
 
405
}
 
406
 
 
407
 
 
408
 
 
409
/**
 
410
 * Scan program for texture instructions, lookup sampler/uniform's value
 
411
 * to determine which texture unit to use.
 
412
 * Also, update the program's TexturesUsed[] array.
 
413
 */
 
414
void
 
415
_slang_resolve_samplers(struct gl_shader_program *shProg,
 
416
                        struct gl_program *prog)
 
417
{
 
418
   GLuint i;
 
419
 
 
420
   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
 
421
      prog->TexturesUsed[i] = 0;
 
422
 
 
423
   for (i = 0; i < prog->NumInstructions; i++) {
 
424
      struct prog_instruction *inst = prog->Instructions + i;
 
425
      if (inst->Opcode == OPCODE_TEX ||
 
426
          inst->Opcode == OPCODE_TXB ||
 
427
          inst->Opcode == OPCODE_TXP) {
 
428
         GLint sampleUnit = (GLint) shProg->Uniforms->ParameterValues[inst->Sampler][0];
 
429
         assert(sampleUnit < MAX_TEXTURE_IMAGE_UNITS);
 
430
         inst->TexSrcUnit = sampleUnit;
 
431
 
 
432
         prog->TexturesUsed[inst->TexSrcUnit] |= (1 << inst->TexSrcTarget);
 
433
      }
 
434
   }
 
435
}
 
436
 
 
437
 
 
438
 
 
439
/** cast wrapper */
 
440
static struct gl_vertex_program *
 
441
vertex_program(struct gl_program *prog)
 
442
{
 
443
   assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
 
444
   return (struct gl_vertex_program *) prog;
 
445
}
 
446
 
 
447
 
 
448
/** cast wrapper */
 
449
static struct gl_fragment_program *
 
450
fragment_program(struct gl_program *prog)
 
451
{
 
452
   assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
 
453
   return (struct gl_fragment_program *) prog;
 
454
}
 
455
 
 
456
 
 
457
/**
 
458
 * Record a linking error.
 
459
 */
 
460
static void
 
461
link_error(struct gl_shader_program *shProg, const char *msg)
 
462
{
 
463
   if (shProg->InfoLog) {
 
464
      _mesa_free(shProg->InfoLog);
 
465
   }
 
466
   shProg->InfoLog = _mesa_strdup(msg);
 
467
   shProg->LinkStatus = GL_FALSE;
 
468
}
 
469
 
 
470
 
 
471
 
 
472
/**
 
473
 * Shader linker.  Currently:
 
474
 *
 
475
 * 1. The last attached vertex shader and fragment shader are linked.
 
476
 * 2. Varying vars in the two shaders are combined so their locations
 
477
 *    agree between the vertex and fragment stages.  They're treated as
 
478
 *    vertex program output attribs and as fragment program input attribs.
 
479
 * 3. Uniform vars (including state references, constants, etc) from the
 
480
 *    vertex and fragment shaders are merged into one group.  Recall that
 
481
 *    GLSL uniforms are shared by all linked shaders.
 
482
 * 4. The vertex and fragment programs are cloned and modified to update
 
483
 *    src/dst register references so they use the new, linked uniform/
 
484
 *    varying storage locations.
 
485
 */
 
486
void
 
487
_slang_link(GLcontext *ctx,
 
488
            GLhandleARB programObj,
 
489
            struct gl_shader_program *shProg)
 
490
{
 
491
   const struct gl_vertex_program *vertProg;
 
492
   const struct gl_fragment_program *fragProg;
 
493
   GLuint i;
 
494
 
 
495
   _mesa_clear_shader_program_data(ctx, shProg);
 
496
 
 
497
   shProg->Uniforms = _mesa_new_parameter_list();
 
498
   shProg->Varying = _mesa_new_parameter_list();
 
499
 
 
500
   /**
 
501
    * Find attached vertex shader, fragment shader
 
502
    */
 
503
   vertProg = NULL;
 
504
   fragProg = NULL;
 
505
   for (i = 0; i < shProg->NumShaders; i++) {
 
506
      if (shProg->Shaders[i]->Type == GL_VERTEX_SHADER)
 
507
         vertProg = vertex_program(shProg->Shaders[i]->Programs[0]);
 
508
      else if (shProg->Shaders[i]->Type == GL_FRAGMENT_SHADER)
 
509
         fragProg = fragment_program(shProg->Shaders[i]->Programs[0]);
 
510
      else
 
511
         _mesa_problem(ctx, "unexpected shader target in slang_link()");
 
512
   }
 
513
 
 
514
   /*
 
515
    * Make copies of the vertex/fragment programs now since we'll be
 
516
    * changing src/dst registers after merging the uniforms and varying vars.
 
517
    */
 
518
   if (vertProg) {
 
519
      shProg->VertexProgram
 
520
         = vertex_program(_mesa_clone_program(ctx, &vertProg->Base));
 
521
   }
 
522
   else {
 
523
      shProg->VertexProgram = NULL;
 
524
   }
 
525
 
 
526
   if (fragProg) {
 
527
      shProg->FragmentProgram
 
528
         = fragment_program(_mesa_clone_program(ctx, &fragProg->Base));
 
529
   }
 
530
   else {
 
531
      shProg->FragmentProgram = NULL;
 
532
   }
 
533
 
 
534
   if (shProg->VertexProgram)
 
535
      link_varying_vars(shProg, &shProg->VertexProgram->Base);
 
536
   if (shProg->FragmentProgram)
 
537
      link_varying_vars(shProg, &shProg->FragmentProgram->Base);
 
538
 
 
539
   if (shProg->VertexProgram)
 
540
      link_uniform_vars(shProg, &shProg->VertexProgram->Base);
 
541
   if (shProg->FragmentProgram)
 
542
      link_uniform_vars(shProg, &shProg->FragmentProgram->Base);
 
543
 
 
544
   /* The vertex and fragment programs share a common set of uniforms now */
 
545
   if (shProg->VertexProgram) {
 
546
      _mesa_free_parameter_list(shProg->VertexProgram->Base.Parameters);
 
547
      shProg->VertexProgram->Base.Parameters = shProg->Uniforms;
 
548
   }
 
549
   if (shProg->FragmentProgram) {
 
550
      _mesa_free_parameter_list(shProg->FragmentProgram->Base.Parameters);
 
551
      shProg->FragmentProgram->Base.Parameters = shProg->Uniforms;
 
552
   }
 
553
 
 
554
   if (shProg->VertexProgram) {
 
555
      _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
 
556
   }
 
557
   if (shProg->FragmentProgram) {
 
558
      _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
 
559
   }
 
560
 
 
561
   if (shProg->VertexProgram) {
 
562
      if (!_slang_resolve_attributes(shProg, &shProg->VertexProgram->Base)) {
 
563
         /*goto cleanup;*/
 
564
         _mesa_problem(ctx, "_slang_resolve_attributes() failed");
 
565
         return;
 
566
      }
 
567
   }
 
568
 
 
569
   if (shProg->VertexProgram) {
 
570
      _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
 
571
      if (!(shProg->VertexProgram->Base.OutputsWritten & (1 << VERT_RESULT_HPOS))) {
 
572
         /* the vertex program did not compute a vertex position */
 
573
         link_error(shProg,
 
574
                    "gl_Position was not written by vertex shader\n");
 
575
         return;
 
576
      }
 
577
   }
 
578
   if (shProg->FragmentProgram)
 
579
      _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
 
580
 
 
581
   /* Check that all the varying vars needed by the fragment shader are
 
582
    * actually produced by the vertex shader.
 
583
    */
 
584
   if (shProg->FragmentProgram) {
 
585
      const GLbitfield varyingRead
 
586
         = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;
 
587
      const GLbitfield varyingWritten = shProg->VertexProgram ?
 
588
         shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;
 
589
      if ((varyingRead & varyingWritten) != varyingRead) {
 
590
         link_error(shProg,
 
591
          "Fragment program using varying vars not written by vertex shader\n");
 
592
         return;
 
593
      }         
 
594
   }
 
595
 
 
596
 
 
597
   if (fragProg && shProg->FragmentProgram) {
 
598
      /* notify driver that a new fragment program has been compiled/linked */
 
599
      ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
 
600
                                      &shProg->FragmentProgram->Base);
 
601
#if 0
 
602
      printf("************** original fragment program\n");
 
603
      _mesa_print_program(&fragProg->Base);
 
604
      _mesa_print_program_parameters(ctx, &fragProg->Base);
 
605
#endif
 
606
#if 0
 
607
      printf("************** linked fragment prog\n");
 
608
      _mesa_print_program(&shProg->FragmentProgram->Base);
 
609
      _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
 
610
#endif
 
611
   }
 
612
 
 
613
   if (vertProg && shProg->VertexProgram) {
 
614
      /* notify driver that a new vertex program has been compiled/linked */
 
615
      ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
 
616
                                      &shProg->VertexProgram->Base);
 
617
#if 0
 
618
      printf("************** original vertex program\n");
 
619
      _mesa_print_program(&vertProg->Base);
 
620
      _mesa_print_program_parameters(ctx, &vertProg->Base);
 
621
#endif
 
622
#if 0
 
623
      printf("************** linked vertex prog\n");
 
624
      _mesa_print_program(&shProg->VertexProgram->Base);
 
625
      _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
 
626
#endif
 
627
   }
 
628
 
 
629
   shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
 
630
}
 
631