Merge branch 'glsl-to-tgsi'
[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_program_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    if (prog->Instructions) {
392       _mesa_free_instructions(prog->Instructions, prog->NumInstructions);
393    }
394    if (prog->Parameters) {
395       _mesa_free_parameter_list(prog->Parameters);
396    }
397    if (prog->Varying) {
398       _mesa_free_parameter_list(prog->Varying);
399    }
400    if (prog->Attributes) {
401       _mesa_free_parameter_list(prog->Attributes);
402    }
403
404    free(prog);
405 }
406
407
408 /**
409  * Return the gl_program object for a given ID.
410  * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of
411  * casts elsewhere.
412  */
413 struct gl_program *
414 _mesa_lookup_program(struct gl_context *ctx, GLuint id)
415 {
416    if (id)
417       return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
418    else
419       return NULL;
420 }
421
422
423 /**
424  * Reference counting for vertex/fragment programs
425  * This is normally only called from the _mesa_reference_program() macro
426  * when there's a real pointer change.
427  */
428 void
429 _mesa_reference_program_(struct gl_context *ctx,
430                          struct gl_program **ptr,
431                          struct gl_program *prog)
432 {
433 #ifndef NDEBUG
434    assert(ptr);
435    if (*ptr && prog) {
436       /* sanity check */
437       if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB)
438          ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB);
439       else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
440          ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
441                 prog->Target == GL_FRAGMENT_PROGRAM_NV);
442       else if ((*ptr)->Target == MESA_GEOMETRY_PROGRAM)
443          ASSERT(prog->Target == MESA_GEOMETRY_PROGRAM);
444    }
445 #endif
446
447    if (*ptr) {
448       GLboolean deleteFlag;
449
450       /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/
451 #if 0
452       printf("Program %p ID=%u Target=%s  Refcount-- to %d\n",
453              *ptr, (*ptr)->Id,
454              ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" :
455               ((*ptr)->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")),
456              (*ptr)->RefCount - 1);
457 #endif
458       ASSERT((*ptr)->RefCount > 0);
459       (*ptr)->RefCount--;
460
461       deleteFlag = ((*ptr)->RefCount == 0);
462       /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/
463
464       if (deleteFlag) {
465          ASSERT(ctx);
466          ctx->Driver.DeleteProgram(ctx, *ptr);
467       }
468
469       *ptr = NULL;
470    }
471
472    assert(!*ptr);
473    if (prog) {
474       /*_glthread_LOCK_MUTEX(prog->Mutex);*/
475       prog->RefCount++;
476 #if 0
477       printf("Program %p ID=%u Target=%s  Refcount++ to %d\n",
478              prog, prog->Id,
479              (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" :
480               (prog->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")),
481              prog->RefCount);
482 #endif
483       /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/
484    }
485
486    *ptr = prog;
487 }
488
489
490 /**
491  * Return a copy of a program.
492  * XXX Problem here if the program object is actually OO-derivation
493  * made by a device driver.
494  */
495 struct gl_program *
496 _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog)
497 {
498    struct gl_program *clone;
499
500    clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id);
501    if (!clone)
502       return NULL;
503
504    assert(clone->Target == prog->Target);
505    assert(clone->RefCount == 1);
506
507    clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
508    clone->Format = prog->Format;
509    clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
510    if (!clone->Instructions) {
511       _mesa_reference_program(ctx, &clone, NULL);
512       return NULL;
513    }
514    _mesa_copy_instructions(clone->Instructions, prog->Instructions,
515                            prog->NumInstructions);
516    clone->InputsRead = prog->InputsRead;
517    clone->OutputsWritten = prog->OutputsWritten;
518    clone->SamplersUsed = prog->SamplersUsed;
519    clone->ShadowSamplers = prog->ShadowSamplers;
520    memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed));
521
522    if (prog->Parameters)
523       clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
524    memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
525    if (prog->Varying)
526       clone->Varying = _mesa_clone_parameter_list(prog->Varying);
527    if (prog->Attributes)
528       clone->Attributes = _mesa_clone_parameter_list(prog->Attributes);
529    memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
530    clone->IndirectRegisterFiles = prog->IndirectRegisterFiles;
531    clone->NumInstructions = prog->NumInstructions;
532    clone->NumTemporaries = prog->NumTemporaries;
533    clone->NumParameters = prog->NumParameters;
534    clone->NumAttributes = prog->NumAttributes;
535    clone->NumAddressRegs = prog->NumAddressRegs;
536    clone->NumNativeInstructions = prog->NumNativeInstructions;
537    clone->NumNativeTemporaries = prog->NumNativeTemporaries;
538    clone->NumNativeParameters = prog->NumNativeParameters;
539    clone->NumNativeAttributes = prog->NumNativeAttributes;
540    clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
541    clone->NumAluInstructions = prog->NumAluInstructions;
542    clone->NumTexInstructions = prog->NumTexInstructions;
543    clone->NumTexIndirections = prog->NumTexIndirections;
544    clone->NumNativeAluInstructions = prog->NumNativeAluInstructions;
545    clone->NumNativeTexInstructions = prog->NumNativeTexInstructions;
546    clone->NumNativeTexIndirections = prog->NumNativeTexIndirections;
547
548    switch (prog->Target) {
549    case GL_VERTEX_PROGRAM_ARB:
550       {
551          const struct gl_vertex_program *vp
552             = (const struct gl_vertex_program *) prog;
553          struct gl_vertex_program *vpc = (struct gl_vertex_program *) clone;
554          vpc->IsPositionInvariant = vp->IsPositionInvariant;
555          vpc->IsNVProgram = vp->IsNVProgram;
556       }
557       break;
558    case GL_FRAGMENT_PROGRAM_ARB:
559       {
560          const struct gl_fragment_program *fp
561             = (const struct gl_fragment_program *) prog;
562          struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone;
563          fpc->UsesKill = fp->UsesKill;
564          fpc->OriginUpperLeft = fp->OriginUpperLeft;
565          fpc->PixelCenterInteger = fp->PixelCenterInteger;
566       }
567       break;
568    case MESA_GEOMETRY_PROGRAM:
569       {
570          const struct gl_geometry_program *gp
571             = (const struct gl_geometry_program *) prog;
572          struct gl_geometry_program *gpc = (struct gl_geometry_program *) clone;
573          gpc->VerticesOut = gp->VerticesOut;
574          gpc->InputType = gp->InputType;
575          gpc->OutputType = gp->OutputType;
576       }
577       break;
578    default:
579       _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
580    }
581
582    return clone;
583 }
584
585
586 /**
587  * Insert 'count' NOP instructions at 'start' in the given program.
588  * Adjust branch targets accordingly.
589  */
590 GLboolean
591 _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
592 {
593    const GLuint origLen = prog->NumInstructions;
594    const GLuint newLen = origLen + count;
595    struct prog_instruction *newInst;
596    GLuint i;
597
598    /* adjust branches */
599    for (i = 0; i < prog->NumInstructions; i++) {
600       struct prog_instruction *inst = prog->Instructions + i;
601       if (inst->BranchTarget > 0) {
602          if ((GLuint)inst->BranchTarget >= start) {
603             inst->BranchTarget += count;
604          }
605       }
606    }
607
608    /* Alloc storage for new instructions */
609    newInst = _mesa_alloc_instructions(newLen);
610    if (!newInst) {
611       return GL_FALSE;
612    }
613
614    /* Copy 'start' instructions into new instruction buffer */
615    _mesa_copy_instructions(newInst, prog->Instructions, start);
616
617    /* init the new instructions */
618    _mesa_init_instructions(newInst + start, count);
619
620    /* Copy the remaining/tail instructions to new inst buffer */
621    _mesa_copy_instructions(newInst + start + count,
622                            prog->Instructions + start,
623                            origLen - start);
624
625    /* free old instructions */
626    _mesa_free_instructions(prog->Instructions, origLen);
627
628    /* install new instructions */
629    prog->Instructions = newInst;
630    prog->NumInstructions = newLen;
631
632    return GL_TRUE;
633 }
634
635 /**
636  * Delete 'count' instructions at 'start' in the given program.
637  * Adjust branch targets accordingly.
638  */
639 GLboolean
640 _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count)
641 {
642    const GLuint origLen = prog->NumInstructions;
643    const GLuint newLen = origLen - count;
644    struct prog_instruction *newInst;
645    GLuint i;
646
647    /* adjust branches */
648    for (i = 0; i < prog->NumInstructions; i++) {
649       struct prog_instruction *inst = prog->Instructions + i;
650       if (inst->BranchTarget > 0) {
651          if (inst->BranchTarget > (GLint) start) {
652             inst->BranchTarget -= count;
653          }
654       }
655    }
656
657    /* Alloc storage for new instructions */
658    newInst = _mesa_alloc_instructions(newLen);
659    if (!newInst) {
660       return GL_FALSE;
661    }
662
663    /* Copy 'start' instructions into new instruction buffer */
664    _mesa_copy_instructions(newInst, prog->Instructions, start);
665
666    /* Copy the remaining/tail instructions to new inst buffer */
667    _mesa_copy_instructions(newInst + start,
668                            prog->Instructions + start + count,
669                            newLen - start);
670
671    /* free old instructions */
672    _mesa_free_instructions(prog->Instructions, origLen);
673
674    /* install new instructions */
675    prog->Instructions = newInst;
676    prog->NumInstructions = newLen;
677
678    return GL_TRUE;
679 }
680
681
682 /**
683  * Search instructions for registers that match (oldFile, oldIndex),
684  * replacing them with (newFile, newIndex).
685  */
686 static void
687 replace_registers(struct prog_instruction *inst, GLuint numInst,
688                   GLuint oldFile, GLuint oldIndex,
689                   GLuint newFile, GLuint newIndex)
690 {
691    GLuint i, j;
692    for (i = 0; i < numInst; i++) {
693       /* src regs */
694       for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) {
695          if (inst[i].SrcReg[j].File == oldFile &&
696              inst[i].SrcReg[j].Index == oldIndex) {
697             inst[i].SrcReg[j].File = newFile;
698             inst[i].SrcReg[j].Index = newIndex;
699          }
700       }
701       /* dst reg */
702       if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) {
703          inst[i].DstReg.File = newFile;
704          inst[i].DstReg.Index = newIndex;
705       }
706    }
707 }
708
709
710 /**
711  * Search instructions for references to program parameters.  When found,
712  * increment the parameter index by 'offset'.
713  * Used when combining programs.
714  */
715 static void
716 adjust_param_indexes(struct prog_instruction *inst, GLuint numInst,
717                      GLuint offset)
718 {
719    GLuint i, j;
720    for (i = 0; i < numInst; i++) {
721       for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) {
722          GLuint f = inst[i].SrcReg[j].File;
723          if (f == PROGRAM_CONSTANT ||
724              f == PROGRAM_UNIFORM ||
725              f == PROGRAM_STATE_VAR) {
726             inst[i].SrcReg[j].Index += offset;
727          }
728       }
729    }
730 }
731
732
733 /**
734  * Combine two programs into one.  Fix instructions so the outputs of
735  * the first program go to the inputs of the second program.
736  */
737 struct gl_program *
738 _mesa_combine_programs(struct gl_context *ctx,
739                        const struct gl_program *progA,
740                        const struct gl_program *progB)
741 {
742    struct prog_instruction *newInst;
743    struct gl_program *newProg;
744    const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */
745    const GLuint lenB = progB->NumInstructions;
746    const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
747    const GLuint newLength = lenA + lenB;
748    GLboolean usedTemps[MAX_PROGRAM_TEMPS];
749    GLuint firstTemp = 0;
750    GLbitfield inputsB;
751    GLuint i;
752
753    ASSERT(progA->Target == progB->Target);
754
755    newInst = _mesa_alloc_instructions(newLength);
756    if (!newInst)
757       return GL_FALSE;
758
759    _mesa_copy_instructions(newInst, progA->Instructions, lenA);
760    _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB);
761
762    /* adjust branch / instruction addresses for B's instructions */
763    for (i = 0; i < lenB; i++) {
764       newInst[lenA + i].BranchTarget += lenA;
765    }
766
767    newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0);
768    newProg->Instructions = newInst;
769    newProg->NumInstructions = newLength;
770
771    /* find used temp regs (we may need new temps below) */
772    _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY,
773                              usedTemps, MAX_PROGRAM_TEMPS);
774
775    if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
776       struct gl_fragment_program *fprogA, *fprogB, *newFprog;
777       GLbitfield progB_inputsRead = progB->InputsRead;
778       GLint progB_colorFile, progB_colorIndex;
779
780       fprogA = (struct gl_fragment_program *) progA;
781       fprogB = (struct gl_fragment_program *) progB;
782       newFprog = (struct gl_fragment_program *) newProg;
783
784       newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;
785
786       /* We'll do a search and replace for instances
787        * of progB_colorFile/progB_colorIndex below...
788        */
789       progB_colorFile = PROGRAM_INPUT;
790       progB_colorIndex = FRAG_ATTRIB_COL0;
791
792       /*
793        * The fragment program may get color from a state var rather than
794        * a fragment input (vertex output) if it's constant.
795        * See the texenvprogram.c code.
796        * So, search the program's parameter list now to see if the program
797        * gets color from a state var instead of a conventional fragment
798        * input register.
799        */
800       for (i = 0; i < progB->Parameters->NumParameters; i++) {
801          struct gl_program_parameter *p = &progB->Parameters->Parameters[i];
802          if (p->Type == PROGRAM_STATE_VAR &&
803              p->StateIndexes[0] == STATE_INTERNAL &&
804              p->StateIndexes[1] == STATE_CURRENT_ATTRIB &&
805              (int) p->StateIndexes[2] == (int) VERT_ATTRIB_COLOR0) {
806             progB_inputsRead |= FRAG_BIT_COL0;
807             progB_colorFile = PROGRAM_STATE_VAR;
808             progB_colorIndex = i;
809             break;
810          }
811       }
812
813       /* Connect color outputs of fprogA to color inputs of fprogB, via a
814        * new temporary register.
815        */
816       if ((progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) &&
817           (progB_inputsRead & FRAG_BIT_COL0)) {
818          GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS,
819                                                   firstTemp);
820          if (tempReg < 0) {
821             _mesa_problem(ctx, "No free temp regs found in "
822                           "_mesa_combine_programs(), using 31");
823             tempReg = 31;
824          }
825          firstTemp = tempReg + 1;
826
827          /* replace writes to result.color[0] with tempReg */
828          replace_registers(newInst, lenA,
829                            PROGRAM_OUTPUT, FRAG_RESULT_COLOR,
830                            PROGRAM_TEMPORARY, tempReg);
831          /* replace reads from the input color with tempReg */
832          replace_registers(newInst + lenA, lenB,
833                            progB_colorFile, progB_colorIndex, /* search for */
834                            PROGRAM_TEMPORARY, tempReg  /* replace with */ );
835       }
836
837       /* compute combined program's InputsRead */
838       inputsB = progB_inputsRead;
839       if (progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
840          inputsB &= ~(1 << FRAG_ATTRIB_COL0);
841       }
842       newProg->InputsRead = progA->InputsRead | inputsB;
843       newProg->OutputsWritten = progB->OutputsWritten;
844       newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed;
845    }
846    else {
847       /* vertex program */
848       assert(0);      /* XXX todo */
849    }
850
851    /*
852     * Merge parameters (uniforms, constants, etc)
853     */
854    newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters,
855                                                        progB->Parameters);
856
857    adjust_param_indexes(newInst + lenA, lenB, numParamsA);
858
859
860    return newProg;
861 }
862
863
864 /**
865  * Populate the 'used' array with flags indicating which registers (TEMPs,
866  * INPUTs, OUTPUTs, etc, are used by the given program.
867  * \param file  type of register to scan for
868  * \param used  returns true/false flags for in use / free
869  * \param usedSize  size of the 'used' array
870  */
871 void
872 _mesa_find_used_registers(const struct gl_program *prog,
873                           gl_register_file file,
874                           GLboolean used[], GLuint usedSize)
875 {
876    GLuint i, j;
877
878    memset(used, 0, usedSize);
879
880    for (i = 0; i < prog->NumInstructions; i++) {
881       const struct prog_instruction *inst = prog->Instructions + i;
882       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
883
884       if (inst->DstReg.File == file) {
885          ASSERT(inst->DstReg.Index < usedSize);
886          if(inst->DstReg.Index < usedSize)
887             used[inst->DstReg.Index] = GL_TRUE;
888       }
889
890       for (j = 0; j < n; j++) {
891          if (inst->SrcReg[j].File == file) {
892             ASSERT(inst->SrcReg[j].Index < usedSize);
893             if(inst->SrcReg[j].Index < usedSize)
894                used[inst->SrcReg[j].Index] = GL_TRUE;
895          }
896       }
897    }
898 }
899
900
901 /**
902  * Scan the given 'used' register flag array for the first entry
903  * that's >= firstReg.
904  * \param used  vector of flags indicating registers in use (as returned
905  *              by _mesa_find_used_registers())
906  * \param usedSize  size of the 'used' array
907  * \param firstReg  first register to start searching at
908  * \return index of unused register, or -1 if none.
909  */
910 GLint
911 _mesa_find_free_register(const GLboolean used[],
912                          GLuint usedSize, GLuint firstReg)
913 {
914    GLuint i;
915
916    assert(firstReg < usedSize);
917
918    for (i = firstReg; i < usedSize; i++)
919       if (!used[i])
920          return i;
921
922    return -1;
923 }
924
925
926
927 /**
928  * Check if the given register index is valid (doesn't exceed implementation-
929  * dependent limits).
930  * \return GL_TRUE if OK, GL_FALSE if bad index
931  */
932 GLboolean
933 _mesa_valid_register_index(const struct gl_context *ctx,
934                            gl_shader_type shaderType,
935                            gl_register_file file, GLint index)
936 {
937    const struct gl_program_constants *c;
938
939    switch (shaderType) {
940    case MESA_SHADER_VERTEX:
941       c = &ctx->Const.VertexProgram;
942       break;
943    case MESA_SHADER_FRAGMENT:
944       c = &ctx->Const.FragmentProgram;
945       break;
946    case MESA_SHADER_GEOMETRY:
947       c = &ctx->Const.GeometryProgram;
948       break;
949    default:
950       _mesa_problem(ctx,
951                     "unexpected shader type in _mesa_valid_register_index()");
952       return GL_FALSE;
953    }
954
955    switch (file) {
956    case PROGRAM_UNDEFINED:
957       return GL_TRUE;  /* XXX or maybe false? */
958
959    case PROGRAM_TEMPORARY:
960       return index >= 0 && index < c->MaxTemps;
961
962    case PROGRAM_ENV_PARAM:
963       return index >= 0 && index < c->MaxEnvParams;
964
965    case PROGRAM_LOCAL_PARAM:
966       return index >= 0 && index < c->MaxLocalParams;
967
968    case PROGRAM_NAMED_PARAM:
969       return index >= 0 && index < c->MaxParameters;
970
971    case PROGRAM_UNIFORM:
972    case PROGRAM_STATE_VAR:
973       /* aka constant buffer */
974       return index >= 0 && index < c->MaxUniformComponents / 4;
975
976    case PROGRAM_CONSTANT:
977       /* constant buffer w/ possible relative negative addressing */
978       return (index > (int) c->MaxUniformComponents / -4 &&
979               index < c->MaxUniformComponents / 4);
980
981    case PROGRAM_INPUT:
982       if (index < 0)
983          return GL_FALSE;
984
985       switch (shaderType) {
986       case MESA_SHADER_VERTEX:
987          return index < VERT_ATTRIB_GENERIC0 + c->MaxAttribs;
988       case MESA_SHADER_FRAGMENT:
989          return index < FRAG_ATTRIB_VAR0 + ctx->Const.MaxVarying;
990       case MESA_SHADER_GEOMETRY:
991          return index < GEOM_ATTRIB_VAR0 + ctx->Const.MaxVarying;
992       default:
993          return GL_FALSE;
994       }
995
996    case PROGRAM_OUTPUT:
997       if (index < 0)
998          return GL_FALSE;
999
1000       switch (shaderType) {
1001       case MESA_SHADER_VERTEX:
1002          return index < VERT_RESULT_VAR0 + ctx->Const.MaxVarying;
1003       case MESA_SHADER_FRAGMENT:
1004          return index < FRAG_RESULT_DATA0 + ctx->Const.MaxDrawBuffers;
1005       case MESA_SHADER_GEOMETRY:
1006          return index < GEOM_RESULT_VAR0 + ctx->Const.MaxVarying;
1007       default:
1008          return GL_FALSE;
1009       }
1010
1011    case PROGRAM_ADDRESS:
1012       return index >= 0 && index < c->MaxAddressRegs;
1013
1014    default:
1015       _mesa_problem(ctx,
1016                     "unexpected register file in _mesa_valid_register_index()");
1017       return GL_FALSE;
1018    }
1019 }
1020
1021
1022
1023 /**
1024  * "Post-process" a GPU program.  This is intended to be used for debugging.
1025  * Example actions include no-op'ing instructions or changing instruction
1026  * behaviour.
1027  */
1028 void
1029 _mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog)
1030 {
1031    static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
1032    GLuint i;
1033    GLuint whiteSwizzle;
1034    GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters,
1035                                                  (gl_constant_value *) white,
1036                                                  4, &whiteSwizzle);
1037
1038    (void) whiteIndex;
1039
1040    for (i = 0; i < prog->NumInstructions; i++) {
1041       struct prog_instruction *inst = prog->Instructions + i;
1042       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
1043
1044       (void) n;
1045
1046       if (_mesa_is_tex_instruction(inst->Opcode)) {
1047 #if 0
1048          /* replace TEX/TXP/TXB with MOV */
1049          inst->Opcode = OPCODE_MOV;
1050          inst->DstReg.WriteMask = WRITEMASK_XYZW;
1051          inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
1052          inst->SrcReg[0].Negate = NEGATE_NONE;
1053 #endif
1054
1055 #if 0
1056          /* disable shadow texture mode */
1057          inst->TexShadow = 0;
1058 #endif
1059       }
1060
1061       if (inst->Opcode == OPCODE_TXP) {
1062 #if 0
1063          inst->Opcode = OPCODE_MOV;
1064          inst->DstReg.WriteMask = WRITEMASK_XYZW;
1065          inst->SrcReg[0].File = PROGRAM_CONSTANT;
1066          inst->SrcReg[0].Index = whiteIndex;
1067          inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
1068          inst->SrcReg[0].Negate = NEGATE_NONE;
1069 #endif
1070 #if 0
1071          inst->TexShadow = 0;
1072 #endif
1073 #if 0
1074          inst->Opcode = OPCODE_TEX;
1075          inst->TexShadow = 0;
1076 #endif
1077       }
1078
1079    }
1080 }