mesa: Convert fixed function fragment program generator to GLSL IR.
[profile/ivi/mesa.git] / src / mesa / program / program.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  6.5.3
4  *
5  * Copyright (C) 1999-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 program.c
27  * Vertex and fragment program support functions.
28  * \author Brian Paul
29  */
30
31
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/hash.h"
35 #include "main/mfeatures.h"
36 #include "program.h"
37 #include "prog_cache.h"
38 #include "prog_parameter.h"
39 #include "prog_instruction.h"
40
41
42 /**
43  * A pointer to this dummy program is put into the hash table when
44  * glGenPrograms is called.
45  */
46 struct gl_program _mesa_DummyProgram;
47
48
49 /**
50  * Init context's vertex/fragment program state
51  */
52 void
53 _mesa_init_program(struct gl_context *ctx)
54 {
55    GLuint i;
56
57    /*
58     * If this assertion fails, we need to increase the field
59     * size for register indexes (see INST_INDEX_BITS).
60     */
61    ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4
62           <= (1 << INST_INDEX_BITS));
63    ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4
64           <= (1 << INST_INDEX_BITS));
65
66    ASSERT(ctx->Const.VertexProgram.MaxTemps <= (1 << INST_INDEX_BITS));
67    ASSERT(ctx->Const.VertexProgram.MaxLocalParams <= (1 << INST_INDEX_BITS));
68    ASSERT(ctx->Const.FragmentProgram.MaxTemps <= (1 << INST_INDEX_BITS));
69    ASSERT(ctx->Const.FragmentProgram.MaxLocalParams <= (1 << INST_INDEX_BITS));
70
71    ASSERT(ctx->Const.VertexProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS);
72    ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS);
73
74    ASSERT(ctx->Const.VertexProgram.MaxAddressOffset <= (1 << INST_INDEX_BITS));
75    ASSERT(ctx->Const.FragmentProgram.MaxAddressOffset <= (1 << INST_INDEX_BITS));
76
77    /* If this fails, increase prog_instruction::TexSrcUnit size */
78    ASSERT(MAX_TEXTURE_UNITS < (1 << 5));
79
80    /* If this fails, increase prog_instruction::TexSrcTarget size */
81    ASSERT(NUM_TEXTURE_TARGETS < (1 << 3));
82
83    ctx->Program.ErrorPos = -1;
84    ctx->Program.ErrorString = _mesa_strdup("");
85
86 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
87    ctx->VertexProgram.Enabled = GL_FALSE;
88 #if FEATURE_es2_glsl
89    ctx->VertexProgram.PointSizeEnabled =
90       (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE;
91 #else
92    ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
93 #endif
94    ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
95    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
96                             ctx->Shared->DefaultVertexProgram);
97    assert(ctx->VertexProgram.Current);
98    for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
99       ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
100       ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
101    }
102    ctx->VertexProgram.Cache = _mesa_new_program_cache();
103 #endif
104
105 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
106    ctx->FragmentProgram.Enabled = GL_FALSE;
107    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
108                             ctx->Shared->DefaultFragmentProgram);
109    assert(ctx->FragmentProgram.Current);
110    ctx->FragmentProgram.Cache = _mesa_new_program_cache();
111 #endif
112
113 #if FEATURE_ARB_geometry_shader4
114    ctx->GeometryProgram.Enabled = GL_FALSE;
115    /* right now by default we don't have a geometry program */
116    _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
117                             NULL);
118    ctx->GeometryProgram.Cache = _mesa_new_program_cache();
119 #endif
120
121    /* XXX probably move this stuff */
122 #if FEATURE_ATI_fragment_shader
123    ctx->ATIFragmentShader.Enabled = GL_FALSE;
124    ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
125    assert(ctx->ATIFragmentShader.Current);
126    ctx->ATIFragmentShader.Current->RefCount++;
127 #endif
128 }
129
130
131 /**
132  * Free a context's vertex/fragment program state
133  */
134 void
135 _mesa_free_program_data(struct gl_context *ctx)
136 {
137 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
138    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
139    _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
140 #endif
141 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
142    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
143    _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache);
144 #endif
145 #if FEATURE_ARB_geometry_shader4
146    _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL);
147    _mesa_delete_program_cache(ctx, ctx->GeometryProgram.Cache);
148 #endif
149    /* XXX probably move this stuff */
150 #if FEATURE_ATI_fragment_shader
151    if (ctx->ATIFragmentShader.Current) {
152       ctx->ATIFragmentShader.Current->RefCount--;
153       if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
154          free(ctx->ATIFragmentShader.Current);
155       }
156    }
157 #endif
158    free((void *) ctx->Program.ErrorString);
159 }
160
161
162 /**
163  * Update the default program objects in the given context to reference those
164  * specified in the shared state and release those referencing the old
165  * shared state.
166  */
167 void
168 _mesa_update_default_objects_program(struct gl_context *ctx)
169 {
170 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
171    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
172                             (struct gl_vertex_program *)
173                             ctx->Shared->DefaultVertexProgram);
174    assert(ctx->VertexProgram.Current);
175 #endif
176
177 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
178    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
179                             (struct gl_fragment_program *)
180                             ctx->Shared->DefaultFragmentProgram);
181    assert(ctx->FragmentProgram.Current);
182 #endif
183
184 #if FEATURE_ARB_geometry_shader4
185    _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
186                             (struct gl_geometry_program *)
187                             ctx->Shared->DefaultGeometryProgram);
188 #endif
189
190    /* XXX probably move this stuff */
191 #if FEATURE_ATI_fragment_shader
192    if (ctx->ATIFragmentShader.Current) {
193       ctx->ATIFragmentShader.Current->RefCount--;
194       if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
195          free(ctx->ATIFragmentShader.Current);
196       }
197    }
198    ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
199    assert(ctx->ATIFragmentShader.Current);
200    ctx->ATIFragmentShader.Current->RefCount++;
201 #endif
202 }
203
204
205 /**
206  * Set the vertex/fragment program error state (position and error string).
207  * This is generally called from within the parsers.
208  */
209 void
210 _mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string)
211 {
212    ctx->Program.ErrorPos = pos;
213    free((void *) ctx->Program.ErrorString);
214    if (!string)
215       string = "";
216    ctx->Program.ErrorString = _mesa_strdup(string);
217 }
218
219
220 /**
221  * Find the line number and column for 'pos' within 'string'.
222  * Return a copy of the line which contains 'pos'.  Free the line with
223  * free().
224  * \param string  the program string
225  * \param pos     the position within the string
226  * \param line    returns the line number corresponding to 'pos'.
227  * \param col     returns the column number corresponding to 'pos'.
228  * \return copy of the line containing 'pos'.
229  */
230 const GLubyte *
231 _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
232                        GLint *line, GLint *col)
233 {
234    const GLubyte *lineStart = string;
235    const GLubyte *p = string;
236    GLubyte *s;
237    int len;
238
239    *line = 1;
240
241    while (p != pos) {
242       if (*p == (GLubyte) '\n') {
243          (*line)++;
244          lineStart = p + 1;
245       }
246       p++;
247    }
248
249    *col = (pos - lineStart) + 1;
250
251    /* return copy of this line */
252    while (*p != 0 && *p != '\n')
253       p++;
254    len = p - lineStart;
255    s = (GLubyte *) malloc(len + 1);
256    memcpy(s, lineStart, len);
257    s[len] = 0;
258
259    return s;
260 }
261
262
263 /**
264  * Initialize a new vertex/fragment program object.
265  */
266 static struct gl_program *
267 _mesa_init_program_struct( struct gl_context *ctx, struct gl_program *prog,
268                            GLenum target, GLuint id)
269 {
270    (void) ctx;
271    if (prog) {
272       GLuint i;
273       memset(prog, 0, sizeof(*prog));
274       prog->Id = id;
275       prog->Target = target;
276       prog->Resident = GL_TRUE;
277       prog->RefCount = 1;
278       prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
279
280       /* default mapping from samplers to texture units */
281       for (i = 0; i < MAX_SAMPLERS; i++)
282          prog->SamplerUnits[i] = i;
283    }
284
285    return prog;
286 }
287
288
289 /**
290  * Initialize a new fragment program object.
291  */
292 struct gl_program *
293 _mesa_init_fragment_program( struct gl_context *ctx, struct gl_fragment_program *prog,
294                              GLenum target, GLuint id)
295 {
296    if (prog)
297       return _mesa_init_program_struct( ctx, &prog->Base, target, id );
298    else
299       return NULL;
300 }
301
302
303 /**
304  * Initialize a new vertex program object.
305  */
306 struct gl_program *
307 _mesa_init_vertex_program( struct gl_context *ctx, struct gl_vertex_program *prog,
308                            GLenum target, GLuint id)
309 {
310    if (prog)
311       return _mesa_init_program_struct( ctx, &prog->Base, target, id );
312    else
313       return NULL;
314 }
315
316
317 /**
318  * Initialize a new geometry program object.
319  */
320 struct gl_program *
321 _mesa_init_geometry_program( struct gl_context *ctx, struct gl_geometry_program *prog,
322                              GLenum target, GLuint id)
323 {
324    if (prog)
325       return _mesa_init_program_struct( ctx, &prog->Base, target, id );
326    else
327       return NULL;
328 }
329
330
331 /**
332  * Allocate and initialize a new fragment/vertex program object but
333  * don't put it into the program hash table.  Called via
334  * ctx->Driver.NewProgram.  May be overridden (ie. replaced) by a
335  * device driver function to implement OO deriviation with additional
336  * types not understood by this function.
337  *
338  * \param ctx  context
339  * \param id   program id/number
340  * \param target  program target/type
341  * \return  pointer to new program object
342  */
343 struct gl_program *
344 _mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id)
345 {
346    struct gl_program *prog;
347    switch (target) {
348    case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
349    case GL_VERTEX_STATE_PROGRAM_NV:
350       prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
351                                        target, id );
352       break;
353    case GL_FRAGMENT_PROGRAM_NV:
354    case GL_FRAGMENT_PROGRAM_ARB:
355       prog =_mesa_init_fragment_program(ctx,
356                                          CALLOC_STRUCT(gl_fragment_program),
357                                          target, id );
358       break;
359    case MESA_GEOMETRY_PROGRAM:
360       prog = _mesa_init_geometry_program(ctx,
361                                          CALLOC_STRUCT(gl_geometry_program),
362                                          target, id);
363       break;
364    default:
365       _mesa_problem(ctx, "bad target in _mesa_new_program");
366       prog = NULL;
367    }
368    return prog;
369 }
370
371
372 /**
373  * Delete a program and remove it from the hash table, ignoring the
374  * reference count.
375  * Called via ctx->Driver.DeleteProgram.  May be wrapped (OO deriviation)
376  * by a device driver function.
377  */
378 void
379 _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
380 {
381    (void) ctx;
382    ASSERT(prog);
383    ASSERT(prog->RefCount==0);
384
385    if (prog == &_mesa_DummyProgram)
386       return;
387
388    if (prog->String)
389       free(prog->String);
390
391    _mesa_free_instructions(prog->Instructions, prog->NumInstructions);
392
393    if (prog->Parameters) {
394       _mesa_free_parameter_list(prog->Parameters);
395    }
396    if (prog->Varying) {
397       _mesa_free_parameter_list(prog->Varying);
398    }
399    if (prog->Attributes) {
400       _mesa_free_parameter_list(prog->Attributes);
401    }
402
403    free(prog);
404 }
405
406
407 /**
408  * Return the gl_program object for a given ID.
409  * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of
410  * casts elsewhere.
411  */
412 struct gl_program *
413 _mesa_lookup_program(struct gl_context *ctx, GLuint id)
414 {
415    if (id)
416       return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
417    else
418       return NULL;
419 }
420
421
422 /**
423  * Reference counting for vertex/fragment programs
424  */
425 void
426 _mesa_reference_program(struct gl_context *ctx,
427                         struct gl_program **ptr,
428                         struct gl_program *prog)
429 {
430    assert(ptr);
431    if (*ptr && prog) {
432       /* sanity check */
433       if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB)
434          ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB);
435       else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
436          ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
437                 prog->Target == GL_FRAGMENT_PROGRAM_NV);
438       else if ((*ptr)->Target == MESA_GEOMETRY_PROGRAM)
439          ASSERT(prog->Target == MESA_GEOMETRY_PROGRAM);
440    }
441    if (*ptr == prog) {
442       return;  /* no change */
443    }
444    if (*ptr) {
445       GLboolean deleteFlag;
446
447       /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/
448 #if 0
449       printf("Program %p ID=%u Target=%s  Refcount-- to %d\n",
450              *ptr, (*ptr)->Id,
451              ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" :
452               ((*ptr)->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")),
453              (*ptr)->RefCount - 1);
454 #endif
455       ASSERT((*ptr)->RefCount > 0);
456       (*ptr)->RefCount--;
457
458       deleteFlag = ((*ptr)->RefCount == 0);
459       /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/
460
461       if (deleteFlag) {
462          ASSERT(ctx);
463          ctx->Driver.DeleteProgram(ctx, *ptr);
464       }
465
466       *ptr = NULL;
467    }
468
469    assert(!*ptr);
470    if (prog) {
471       /*_glthread_LOCK_MUTEX(prog->Mutex);*/
472       prog->RefCount++;
473 #if 0
474       printf("Program %p ID=%u Target=%s  Refcount++ to %d\n",
475              prog, prog->Id,
476              (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" :
477               (prog->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")),
478              prog->RefCount);
479 #endif
480       /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/
481    }
482
483    *ptr = prog;
484 }
485
486
487 /**
488  * Return a copy of a program.
489  * XXX Problem here if the program object is actually OO-derivation
490  * made by a device driver.
491  */
492 struct gl_program *
493 _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog)
494 {
495    struct gl_program *clone;
496
497    clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id);
498    if (!clone)
499       return NULL;
500
501    assert(clone->Target == prog->Target);
502    assert(clone->RefCount == 1);
503
504    clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
505    clone->Format = prog->Format;
506    clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
507    if (!clone->Instructions) {
508       _mesa_reference_program(ctx, &clone, NULL);
509       return NULL;
510    }
511    _mesa_copy_instructions(clone->Instructions, prog->Instructions,
512                            prog->NumInstructions);
513    clone->InputsRead = prog->InputsRead;
514    clone->OutputsWritten = prog->OutputsWritten;
515    clone->SamplersUsed = prog->SamplersUsed;
516    clone->ShadowSamplers = prog->ShadowSamplers;
517    memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed));
518
519    if (prog->Parameters)
520       clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
521    memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
522    if (prog->Varying)
523       clone->Varying = _mesa_clone_parameter_list(prog->Varying);
524    if (prog->Attributes)
525       clone->Attributes = _mesa_clone_parameter_list(prog->Attributes);
526    memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
527    clone->IndirectRegisterFiles = prog->IndirectRegisterFiles;
528    clone->NumInstructions = prog->NumInstructions;
529    clone->NumTemporaries = prog->NumTemporaries;
530    clone->NumParameters = prog->NumParameters;
531    clone->NumAttributes = prog->NumAttributes;
532    clone->NumAddressRegs = prog->NumAddressRegs;
533    clone->NumNativeInstructions = prog->NumNativeInstructions;
534    clone->NumNativeTemporaries = prog->NumNativeTemporaries;
535    clone->NumNativeParameters = prog->NumNativeParameters;
536    clone->NumNativeAttributes = prog->NumNativeAttributes;
537    clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
538    clone->NumAluInstructions = prog->NumAluInstructions;
539    clone->NumTexInstructions = prog->NumTexInstructions;
540    clone->NumTexIndirections = prog->NumTexIndirections;
541    clone->NumNativeAluInstructions = prog->NumNativeAluInstructions;
542    clone->NumNativeTexInstructions = prog->NumNativeTexInstructions;
543    clone->NumNativeTexIndirections = prog->NumNativeTexIndirections;
544
545    switch (prog->Target) {
546    case GL_VERTEX_PROGRAM_ARB:
547       {
548          const struct gl_vertex_program *vp
549             = (const struct gl_vertex_program *) prog;
550          struct gl_vertex_program *vpc = (struct gl_vertex_program *) clone;
551          vpc->IsPositionInvariant = vp->IsPositionInvariant;
552          vpc->IsNVProgram = vp->IsNVProgram;
553       }
554       break;
555    case GL_FRAGMENT_PROGRAM_ARB:
556       {
557          const struct gl_fragment_program *fp
558             = (const struct gl_fragment_program *) prog;
559          struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone;
560          fpc->FogOption = fp->FogOption;
561          fpc->UsesKill = fp->UsesKill;
562          fpc->OriginUpperLeft = fp->OriginUpperLeft;
563          fpc->PixelCenterInteger = fp->PixelCenterInteger;
564       }
565       break;
566    case MESA_GEOMETRY_PROGRAM:
567       {
568          const struct gl_geometry_program *gp
569             = (const struct gl_geometry_program *) prog;
570          struct gl_geometry_program *gpc = (struct gl_geometry_program *) clone;
571          gpc->VerticesOut = gp->VerticesOut;
572          gpc->InputType = gp->InputType;
573          gpc->OutputType = gp->OutputType;
574       }
575       break;
576    default:
577       _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
578    }
579
580    return clone;
581 }
582
583
584 /**
585  * Insert 'count' NOP instructions at 'start' in the given program.
586  * Adjust branch targets accordingly.
587  */
588 GLboolean
589 _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
590 {
591    const GLuint origLen = prog->NumInstructions;
592    const GLuint newLen = origLen + count;
593    struct prog_instruction *newInst;
594    GLuint i;
595
596    /* adjust branches */
597    for (i = 0; i < prog->NumInstructions; i++) {
598       struct prog_instruction *inst = prog->Instructions + i;
599       if (inst->BranchTarget > 0) {
600          if ((GLuint)inst->BranchTarget >= start) {
601             inst->BranchTarget += count;
602          }
603       }
604    }
605
606    /* Alloc storage for new instructions */
607    newInst = _mesa_alloc_instructions(newLen);
608    if (!newInst) {
609       return GL_FALSE;
610    }
611
612    /* Copy 'start' instructions into new instruction buffer */
613    _mesa_copy_instructions(newInst, prog->Instructions, start);
614
615    /* init the new instructions */
616    _mesa_init_instructions(newInst + start, count);
617
618    /* Copy the remaining/tail instructions to new inst buffer */
619    _mesa_copy_instructions(newInst + start + count,
620                            prog->Instructions + start,
621                            origLen - start);
622
623    /* free old instructions */
624    _mesa_free_instructions(prog->Instructions, origLen);
625
626    /* install new instructions */
627    prog->Instructions = newInst;
628    prog->NumInstructions = newLen;
629
630    return GL_TRUE;
631 }
632
633 /**
634  * Delete 'count' instructions at 'start' in the given program.
635  * Adjust branch targets accordingly.
636  */
637 GLboolean
638 _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count)
639 {
640    const GLuint origLen = prog->NumInstructions;
641    const GLuint newLen = origLen - count;
642    struct prog_instruction *newInst;
643    GLuint i;
644
645    /* adjust branches */
646    for (i = 0; i < prog->NumInstructions; i++) {
647       struct prog_instruction *inst = prog->Instructions + i;
648       if (inst->BranchTarget > 0) {
649          if (inst->BranchTarget > (GLint) start) {
650             inst->BranchTarget -= count;
651          }
652       }
653    }
654
655    /* Alloc storage for new instructions */
656    newInst = _mesa_alloc_instructions(newLen);
657    if (!newInst) {
658       return GL_FALSE;
659    }
660
661    /* Copy 'start' instructions into new instruction buffer */
662    _mesa_copy_instructions(newInst, prog->Instructions, start);
663
664    /* Copy the remaining/tail instructions to new inst buffer */
665    _mesa_copy_instructions(newInst + start,
666                            prog->Instructions + start + count,
667                            newLen - start);
668
669    /* free old instructions */
670    _mesa_free_instructions(prog->Instructions, origLen);
671
672    /* install new instructions */
673    prog->Instructions = newInst;
674    prog->NumInstructions = newLen;
675
676    return GL_TRUE;
677 }
678
679
680 /**
681  * Search instructions for registers that match (oldFile, oldIndex),
682  * replacing them with (newFile, newIndex).
683  */
684 static void
685 replace_registers(struct prog_instruction *inst, GLuint numInst,
686                   GLuint oldFile, GLuint oldIndex,
687                   GLuint newFile, GLuint newIndex)
688 {
689    GLuint i, j;
690    for (i = 0; i < numInst; i++) {
691       /* src regs */
692       for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) {
693          if (inst[i].SrcReg[j].File == oldFile &&
694              inst[i].SrcReg[j].Index == oldIndex) {
695             inst[i].SrcReg[j].File = newFile;
696             inst[i].SrcReg[j].Index = newIndex;
697          }
698       }
699       /* dst reg */
700       if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) {
701          inst[i].DstReg.File = newFile;
702          inst[i].DstReg.Index = newIndex;
703       }
704    }
705 }
706
707
708 /**
709  * Search instructions for references to program parameters.  When found,
710  * increment the parameter index by 'offset'.
711  * Used when combining programs.
712  */
713 static void
714 adjust_param_indexes(struct prog_instruction *inst, GLuint numInst,
715                      GLuint offset)
716 {
717    GLuint i, j;
718    for (i = 0; i < numInst; i++) {
719       for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) {
720          GLuint f = inst[i].SrcReg[j].File;
721          if (f == PROGRAM_CONSTANT ||
722              f == PROGRAM_UNIFORM ||
723              f == PROGRAM_STATE_VAR) {
724             inst[i].SrcReg[j].Index += offset;
725          }
726       }
727    }
728 }
729
730
731 /**
732  * Combine two programs into one.  Fix instructions so the outputs of
733  * the first program go to the inputs of the second program.
734  */
735 struct gl_program *
736 _mesa_combine_programs(struct gl_context *ctx,
737                        const struct gl_program *progA,
738                        const struct gl_program *progB)
739 {
740    struct prog_instruction *newInst;
741    struct gl_program *newProg;
742    const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */
743    const GLuint lenB = progB->NumInstructions;
744    const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
745    const GLuint newLength = lenA + lenB;
746    GLboolean usedTemps[MAX_PROGRAM_TEMPS];
747    GLuint firstTemp = 0;
748    GLbitfield inputsB;
749    GLuint i;
750
751    ASSERT(progA->Target == progB->Target);
752
753    newInst = _mesa_alloc_instructions(newLength);
754    if (!newInst)
755       return GL_FALSE;
756
757    _mesa_copy_instructions(newInst, progA->Instructions, lenA);
758    _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB);
759
760    /* adjust branch / instruction addresses for B's instructions */
761    for (i = 0; i < lenB; i++) {
762       newInst[lenA + i].BranchTarget += lenA;
763    }
764
765    newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0);
766    newProg->Instructions = newInst;
767    newProg->NumInstructions = newLength;
768
769    /* find used temp regs (we may need new temps below) */
770    _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY,
771                              usedTemps, MAX_PROGRAM_TEMPS);
772
773    if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
774       struct gl_fragment_program *fprogA, *fprogB, *newFprog;
775       GLbitfield progB_inputsRead = progB->InputsRead;
776       GLint progB_colorFile, progB_colorIndex;
777
778       fprogA = (struct gl_fragment_program *) progA;
779       fprogB = (struct gl_fragment_program *) progB;
780       newFprog = (struct gl_fragment_program *) newProg;
781
782       newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;
783
784       /* We'll do a search and replace for instances
785        * of progB_colorFile/progB_colorIndex below...
786        */
787       progB_colorFile = PROGRAM_INPUT;
788       progB_colorIndex = FRAG_ATTRIB_COL0;
789
790       /*
791        * The fragment program may get color from a state var rather than
792        * a fragment input (vertex output) if it's constant.
793        * See the texenvprogram.c code.
794        * So, search the program's parameter list now to see if the program
795        * gets color from a state var instead of a conventional fragment
796        * input register.
797        */
798       for (i = 0; i < progB->Parameters->NumParameters; i++) {
799          struct gl_program_parameter *p = &progB->Parameters->Parameters[i];
800          if (p->Type == PROGRAM_STATE_VAR &&
801              p->StateIndexes[0] == STATE_INTERNAL &&
802              p->StateIndexes[1] == STATE_CURRENT_ATTRIB &&
803              (int) p->StateIndexes[2] == (int) VERT_ATTRIB_COLOR0) {
804             progB_inputsRead |= FRAG_BIT_COL0;
805             progB_colorFile = PROGRAM_STATE_VAR;
806             progB_colorIndex = i;
807             break;
808          }
809       }
810
811       /* Connect color outputs of fprogA to color inputs of fprogB, via a
812        * new temporary register.
813        */
814       if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) &&
815           (progB_inputsRead & FRAG_BIT_COL0)) {
816          GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS,
817                                                   firstTemp);
818          if (tempReg < 0) {
819             _mesa_problem(ctx, "No free temp regs found in "
820                           "_mesa_combine_programs(), using 31");
821             tempReg = 31;
822          }
823          firstTemp = tempReg + 1;
824
825          /* replace writes to result.color[0] with tempReg */
826          replace_registers(newInst, lenA,
827                            PROGRAM_OUTPUT, FRAG_RESULT_COLOR,
828                            PROGRAM_TEMPORARY, tempReg);
829          /* replace reads from the input color with tempReg */
830          replace_registers(newInst + lenA, lenB,
831                            progB_colorFile, progB_colorIndex, /* search for */
832                            PROGRAM_TEMPORARY, tempReg  /* replace with */ );
833       }
834
835       /* compute combined program's InputsRead */
836       inputsB = progB_inputsRead;
837       if (progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) {
838          inputsB &= ~(1 << FRAG_ATTRIB_COL0);
839       }
840       newProg->InputsRead = progA->InputsRead | inputsB;
841       newProg->OutputsWritten = progB->OutputsWritten;
842       newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed;
843    }
844    else {
845       /* vertex program */
846       assert(0);      /* XXX todo */
847    }
848
849    /*
850     * Merge parameters (uniforms, constants, etc)
851     */
852    newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters,
853                                                        progB->Parameters);
854
855    adjust_param_indexes(newInst + lenA, lenB, numParamsA);
856
857
858    return newProg;
859 }
860
861
862 /**
863  * Populate the 'used' array with flags indicating which registers (TEMPs,
864  * INPUTs, OUTPUTs, etc, are used by the given program.
865  * \param file  type of register to scan for
866  * \param used  returns true/false flags for in use / free
867  * \param usedSize  size of the 'used' array
868  */
869 void
870 _mesa_find_used_registers(const struct gl_program *prog,
871                           gl_register_file file,
872                           GLboolean used[], GLuint usedSize)
873 {
874    GLuint i, j;
875
876    memset(used, 0, usedSize);
877
878    for (i = 0; i < prog->NumInstructions; i++) {
879       const struct prog_instruction *inst = prog->Instructions + i;
880       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
881
882       if (inst->DstReg.File == file) {
883          ASSERT(inst->DstReg.Index < usedSize);
884          if(inst->DstReg.Index < usedSize)
885             used[inst->DstReg.Index] = GL_TRUE;
886       }
887
888       for (j = 0; j < n; j++) {
889          if (inst->SrcReg[j].File == file) {
890             ASSERT(inst->SrcReg[j].Index < usedSize);
891             if(inst->SrcReg[j].Index < usedSize)
892                used[inst->SrcReg[j].Index] = GL_TRUE;
893          }
894       }
895    }
896 }
897
898
899 /**
900  * Scan the given 'used' register flag array for the first entry
901  * that's >= firstReg.
902  * \param used  vector of flags indicating registers in use (as returned
903  *              by _mesa_find_used_registers())
904  * \param usedSize  size of the 'used' array
905  * \param firstReg  first register to start searching at
906  * \return index of unused register, or -1 if none.
907  */
908 GLint
909 _mesa_find_free_register(const GLboolean used[],
910                          GLuint usedSize, GLuint firstReg)
911 {
912    GLuint i;
913
914    assert(firstReg < usedSize);
915
916    for (i = firstReg; i < usedSize; i++)
917       if (!used[i])
918          return i;
919
920    return -1;
921 }
922
923
924
925 /**
926  * Check if the given register index is valid (doesn't exceed implementation-
927  * dependent limits).
928  * \return GL_TRUE if OK, GL_FALSE if bad index
929  */
930 GLboolean
931 _mesa_valid_register_index(const struct gl_context *ctx,
932                            gl_shader_type shaderType,
933                            gl_register_file file, GLint index)
934 {
935    const struct gl_program_constants *c;
936
937    switch (shaderType) {
938    case MESA_SHADER_VERTEX:
939       c = &ctx->Const.VertexProgram;
940       break;
941    case MESA_SHADER_FRAGMENT:
942       c = &ctx->Const.FragmentProgram;
943       break;
944    case MESA_SHADER_GEOMETRY:
945       c = &ctx->Const.GeometryProgram;
946       break;
947    default:
948       _mesa_problem(ctx,
949                     "unexpected shader type in _mesa_valid_register_index()");
950       return GL_FALSE;
951    }
952
953    switch (file) {
954    case PROGRAM_UNDEFINED:
955       return GL_TRUE;  /* XXX or maybe false? */
956
957    case PROGRAM_TEMPORARY:
958       return index >= 0 && index < c->MaxTemps;
959
960    case PROGRAM_ENV_PARAM:
961       return index >= 0 && index < c->MaxEnvParams;
962
963    case PROGRAM_LOCAL_PARAM:
964       return index >= 0 && index < c->MaxLocalParams;
965
966    case PROGRAM_NAMED_PARAM:
967       return index >= 0 && index < c->MaxParameters;
968
969    case PROGRAM_UNIFORM:
970    case PROGRAM_STATE_VAR:
971       /* aka constant buffer */
972       return index >= 0 && index < c->MaxUniformComponents / 4;
973
974    case PROGRAM_CONSTANT:
975       /* constant buffer w/ possible relative negative addressing */
976       return (index > (int) c->MaxUniformComponents / -4 &&
977               index < c->MaxUniformComponents / 4);
978
979    case PROGRAM_INPUT:
980       if (index < 0)
981          return GL_FALSE;
982
983       switch (shaderType) {
984       case MESA_SHADER_VERTEX:
985          return index < VERT_ATTRIB_GENERIC0 + c->MaxAttribs;
986       case MESA_SHADER_FRAGMENT:
987          return index < FRAG_ATTRIB_VAR0 + ctx->Const.MaxVarying;
988       case MESA_SHADER_GEOMETRY:
989          return index < GEOM_ATTRIB_VAR0 + ctx->Const.MaxVarying;
990       default:
991          return GL_FALSE;
992       }
993
994    case PROGRAM_OUTPUT:
995       if (index < 0)
996          return GL_FALSE;
997
998       switch (shaderType) {
999       case MESA_SHADER_VERTEX:
1000          return index < VERT_RESULT_VAR0 + ctx->Const.MaxVarying;
1001       case MESA_SHADER_FRAGMENT:
1002          return index < FRAG_RESULT_DATA0 + ctx->Const.MaxDrawBuffers;
1003       case MESA_SHADER_GEOMETRY:
1004          return index < GEOM_RESULT_VAR0 + ctx->Const.MaxVarying;
1005       default:
1006          return GL_FALSE;
1007       }
1008
1009    case PROGRAM_ADDRESS:
1010       return index >= 0 && index < c->MaxAddressRegs;
1011
1012    default:
1013       _mesa_problem(ctx,
1014                     "unexpected register file in _mesa_valid_register_index()");
1015       return GL_FALSE;
1016    }
1017 }
1018
1019
1020
1021 /**
1022  * "Post-process" a GPU program.  This is intended to be used for debugging.
1023  * Example actions include no-op'ing instructions or changing instruction
1024  * behaviour.
1025  */
1026 void
1027 _mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog)
1028 {
1029    static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
1030    GLuint i;
1031    GLuint whiteSwizzle;
1032    GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters,
1033                                                  white, 4, &whiteSwizzle);
1034
1035    (void) whiteIndex;
1036
1037    for (i = 0; i < prog->NumInstructions; i++) {
1038       struct prog_instruction *inst = prog->Instructions + i;
1039       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
1040
1041       (void) n;
1042
1043       if (_mesa_is_tex_instruction(inst->Opcode)) {
1044 #if 0
1045          /* replace TEX/TXP/TXB with MOV */
1046          inst->Opcode = OPCODE_MOV;
1047          inst->DstReg.WriteMask = WRITEMASK_XYZW;
1048          inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
1049          inst->SrcReg[0].Negate = NEGATE_NONE;
1050 #endif
1051
1052 #if 0
1053          /* disable shadow texture mode */
1054          inst->TexShadow = 0;
1055 #endif
1056       }
1057
1058       if (inst->Opcode == OPCODE_TXP) {
1059 #if 0
1060          inst->Opcode = OPCODE_MOV;
1061          inst->DstReg.WriteMask = WRITEMASK_XYZW;
1062          inst->SrcReg[0].File = PROGRAM_CONSTANT;
1063          inst->SrcReg[0].Index = whiteIndex;
1064          inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
1065          inst->SrcReg[0].Negate = NEGATE_NONE;
1066 #endif
1067 #if 0
1068          inst->TexShadow = 0;
1069 #endif
1070 #if 0
1071          inst->Opcode = OPCODE_TEX;
1072          inst->TexShadow = 0;
1073 #endif
1074       }
1075
1076    }
1077 }