12861e737e84e4884109b9526ac645194ba892a74Michal Krol/*
22861e737e84e4884109b9526ac645194ba892a74Michal Krol * Mesa 3-D graphics library
3942ee025908a95afc57990c57d6754ca1a626b04Brian * Version:  6.5.3
42861e737e84e4884109b9526ac645194ba892a74Michal Krol *
5942ee025908a95afc57990c57d6754ca1a626b04Brian * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
62861e737e84e4884109b9526ac645194ba892a74Michal Krol *
72861e737e84e4884109b9526ac645194ba892a74Michal Krol * Permission is hereby granted, free of charge, to any person obtaining a
82861e737e84e4884109b9526ac645194ba892a74Michal Krol * copy of this software and associated documentation files (the "Software"),
92861e737e84e4884109b9526ac645194ba892a74Michal Krol * to deal in the Software without restriction, including without limitation
102861e737e84e4884109b9526ac645194ba892a74Michal Krol * the rights to use, copy, modify, merge, publish, distribute, sublicense,
112861e737e84e4884109b9526ac645194ba892a74Michal Krol * and/or sell copies of the Software, and to permit persons to whom the
122861e737e84e4884109b9526ac645194ba892a74Michal Krol * Software is furnished to do so, subject to the following conditions:
132861e737e84e4884109b9526ac645194ba892a74Michal Krol *
142861e737e84e4884109b9526ac645194ba892a74Michal Krol * The above copyright notice and this permission notice shall be included
152861e737e84e4884109b9526ac645194ba892a74Michal Krol * in all copies or substantial portions of the Software.
162861e737e84e4884109b9526ac645194ba892a74Michal Krol *
172861e737e84e4884109b9526ac645194ba892a74Michal Krol * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
182861e737e84e4884109b9526ac645194ba892a74Michal Krol * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
192861e737e84e4884109b9526ac645194ba892a74Michal Krol * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
202861e737e84e4884109b9526ac645194ba892a74Michal Krol * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
212861e737e84e4884109b9526ac645194ba892a74Michal Krol * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
222861e737e84e4884109b9526ac645194ba892a74Michal Krol * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
232861e737e84e4884109b9526ac645194ba892a74Michal Krol */
242861e737e84e4884109b9526ac645194ba892a74Michal Krol
252861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
262861e737e84e4884109b9526ac645194ba892a74Michal Krol * \file program.c
272861e737e84e4884109b9526ac645194ba892a74Michal Krol * Vertex and fragment program support functions.
282861e737e84e4884109b9526ac645194ba892a74Michal Krol * \author Brian Paul
292861e737e84e4884109b9526ac645194ba892a74Michal Krol */
302861e737e84e4884109b9526ac645194ba892a74Michal Krol
312861e737e84e4884109b9526ac645194ba892a74Michal Krol
32101d1a658a614d1e2ec02b1e697f6161291af653José Fonseca#include "main/glheader.h"
33101d1a658a614d1e2ec02b1e697f6161291af653José Fonseca#include "main/context.h"
34101d1a658a614d1e2ec02b1e697f6161291af653José Fonseca#include "main/hash.h"
3521750a2d9d2a4ed69308316b121fd53b0c873aeaVinson Lee#include "main/mfeatures.h"
360560d81ce94d27f2162d77d981468cea1b2bbd8aBrian#include "program.h"
37b26aae67f5fe4194b48a5d3ddf704797b804b58cBrian#include "prog_cache.h"
380560d81ce94d27f2162d77d981468cea1b2bbd8aBrian#include "prog_parameter.h"
390560d81ce94d27f2162d77d981468cea1b2bbd8aBrian#include "prog_instruction.h"
402861e737e84e4884109b9526ac645194ba892a74Michal Krol
412861e737e84e4884109b9526ac645194ba892a74Michal Krol
42942ee025908a95afc57990c57d6754ca1a626b04Brian/**
43942ee025908a95afc57990c57d6754ca1a626b04Brian * A pointer to this dummy program is put into the hash table when
44765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul * glGenPrograms is called.
45765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul */
46122629f27925a9dc50029bebc5079f87f416a7e1Brian Paulstruct gl_program _mesa_DummyProgram;
47765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul
48765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul
492861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
5021841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul * Init context's vertex/fragment program state
512861e737e84e4884109b9526ac645194ba892a74Michal Krol */
522861e737e84e4884109b9526ac645194ba892a74Michal Krolvoid
53f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_program(struct gl_context *ctx)
542861e737e84e4884109b9526ac645194ba892a74Michal Krol{
552861e737e84e4884109b9526ac645194ba892a74Michal Krol   GLuint i;
562861e737e84e4884109b9526ac645194ba892a74Michal Krol
575b2f8dc01300058d43d8043aa897722f39657e93Brian Paul   /*
585b2f8dc01300058d43d8043aa897722f39657e93Brian Paul    * If this assertion fails, we need to increase the field
594567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul    * size for register indexes (see INST_INDEX_BITS).
605b2f8dc01300058d43d8043aa897722f39657e93Brian Paul    */
615b2f8dc01300058d43d8043aa897722f39657e93Brian Paul   ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4
625b2f8dc01300058d43d8043aa897722f39657e93Brian Paul          <= (1 << INST_INDEX_BITS));
635b2f8dc01300058d43d8043aa897722f39657e93Brian Paul   ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4
645b2f8dc01300058d43d8043aa897722f39657e93Brian Paul          <= (1 << INST_INDEX_BITS));
655b2f8dc01300058d43d8043aa897722f39657e93Brian Paul
664567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul   ASSERT(ctx->Const.VertexProgram.MaxTemps <= (1 << INST_INDEX_BITS));
674567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul   ASSERT(ctx->Const.VertexProgram.MaxLocalParams <= (1 << INST_INDEX_BITS));
684567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul   ASSERT(ctx->Const.FragmentProgram.MaxTemps <= (1 << INST_INDEX_BITS));
694567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul   ASSERT(ctx->Const.FragmentProgram.MaxLocalParams <= (1 << INST_INDEX_BITS));
704567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul
714567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul   ASSERT(ctx->Const.VertexProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS);
724567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul   ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS);
734567b479531d2791ad2d6a598c9dd9e3730b0504Brian Paul
748ad821df0a2d49964141f2ea4ef8179f4edc052fBrian Paul   ASSERT(ctx->Const.VertexProgram.MaxAddressOffset <= (1 << INST_INDEX_BITS));
758ad821df0a2d49964141f2ea4ef8179f4edc052fBrian Paul   ASSERT(ctx->Const.FragmentProgram.MaxAddressOffset <= (1 << INST_INDEX_BITS));
768ad821df0a2d49964141f2ea4ef8179f4edc052fBrian Paul
77dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul   /* If this fails, increase prog_instruction::TexSrcUnit size */
78874a2c0b7da62f4dd08dedcec221f55b22e40e95Brian Paul   ASSERT(MAX_TEXTURE_UNITS <= (1 << 5));
79dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul
80dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul   /* If this fails, increase prog_instruction::TexSrcTarget size */
811ab1b15e9d0da1c5215a20770735b5477f5313dfChia-I Wu   ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4));
82dd528f0ec18cfbd6f0a5b23b8cb46a97b96ab965Brian Paul
832861e737e84e4884109b9526ac645194ba892a74Michal Krol   ctx->Program.ErrorPos = -1;
842861e737e84e4884109b9526ac645194ba892a74Michal Krol   ctx->Program.ErrorString = _mesa_strdup("");
852861e737e84e4884109b9526ac645194ba892a74Michal Krol
862861e737e84e4884109b9526ac645194ba892a74Michal Krol#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
872861e737e84e4884109b9526ac645194ba892a74Michal Krol   ctx->VertexProgram.Enabled = GL_FALSE;
88af3d9dba562813ffed71691bffd7faf6665c4487Brian Paul#if FEATURE_es2_glsl
89f67b020a942911f80b7b774c6d64701d1981c608Kristian Høgsberg   ctx->VertexProgram.PointSizeEnabled =
90f67b020a942911f80b7b774c6d64701d1981c608Kristian Høgsberg      (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE;
91af3d9dba562813ffed71691bffd7faf6665c4487Brian Paul#else
922861e737e84e4884109b9526ac645194ba892a74Michal Krol   ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
93af3d9dba562813ffed71691bffd7faf6665c4487Brian Paul#endif
942861e737e84e4884109b9526ac645194ba892a74Michal Krol   ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
95df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
96df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian                            ctx->Shared->DefaultVertexProgram);
972861e737e84e4884109b9526ac645194ba892a74Michal Krol   assert(ctx->VertexProgram.Current);
982861e737e84e4884109b9526ac645194ba892a74Michal Krol   for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
992861e737e84e4884109b9526ac645194ba892a74Michal Krol      ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
1002861e737e84e4884109b9526ac645194ba892a74Michal Krol      ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
1012861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
102b26aae67f5fe4194b48a5d3ddf704797b804b58cBrian   ctx->VertexProgram.Cache = _mesa_new_program_cache();
1032861e737e84e4884109b9526ac645194ba892a74Michal Krol#endif
1042861e737e84e4884109b9526ac645194ba892a74Michal Krol
1052861e737e84e4884109b9526ac645194ba892a74Michal Krol#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
1062861e737e84e4884109b9526ac645194ba892a74Michal Krol   ctx->FragmentProgram.Enabled = GL_FALSE;
107df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
108df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian                            ctx->Shared->DefaultFragmentProgram);
1092861e737e84e4884109b9526ac645194ba892a74Michal Krol   assert(ctx->FragmentProgram.Current);
110b26aae67f5fe4194b48a5d3ddf704797b804b58cBrian   ctx->FragmentProgram.Cache = _mesa_new_program_cache();
1112861e737e84e4884109b9526ac645194ba892a74Michal Krol#endif
1127f752fed993e5e9423abac200dd59141edbada56Dave Airlie
113da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin#if FEATURE_ARB_geometry_shader4
114da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   ctx->GeometryProgram.Enabled = GL_FALSE;
115da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   /* right now by default we don't have a geometry program */
116da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
117da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin                            NULL);
118da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   ctx->GeometryProgram.Cache = _mesa_new_program_cache();
119da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin#endif
120b26aae67f5fe4194b48a5d3ddf704797b804b58cBrian
12163d683091fe3a9600b65ae7ef3b554168b805406Brian Paul   /* XXX probably move this stuff */
1227f752fed993e5e9423abac200dd59141edbada56Dave Airlie#if FEATURE_ATI_fragment_shader
1237f752fed993e5e9423abac200dd59141edbada56Dave Airlie   ctx->ATIFragmentShader.Enabled = GL_FALSE;
124b7eea9a1ce9f3a28b74d77db19dcd859b6638a41Brian Paul   ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
1257f752fed993e5e9423abac200dd59141edbada56Dave Airlie   assert(ctx->ATIFragmentShader.Current);
12663d683091fe3a9600b65ae7ef3b554168b805406Brian Paul   ctx->ATIFragmentShader.Current->RefCount++;
1277f752fed993e5e9423abac200dd59141edbada56Dave Airlie#endif
1282861e737e84e4884109b9526ac645194ba892a74Michal Krol}
1292861e737e84e4884109b9526ac645194ba892a74Michal Krol
1302861e737e84e4884109b9526ac645194ba892a74Michal Krol
1312861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
13221841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul * Free a context's vertex/fragment program state
13321841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul */
13421841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paulvoid
135f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_free_program_data(struct gl_context *ctx)
13621841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul{
13793da673904d4c520d3fbd2210e53777bf1598ac6Roland Scheidegger#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
138df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
1391631a9513d32ddcc5467225ad25d0e7a154af895Brian   _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
14021841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul#endif
14193da673904d4c520d3fbd2210e53777bf1598ac6Roland Scheidegger#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
142df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
1437ec2b0d0d6b6a0f760e55ffdee0bdb385a3e900aEric Anholt   _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache);
14421841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul#endif
145da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin#if FEATURE_ARB_geometry_shader4
146da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL);
147da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   _mesa_delete_program_cache(ctx, ctx->GeometryProgram.Cache);
148da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin#endif
14963d683091fe3a9600b65ae7ef3b554168b805406Brian Paul   /* XXX probably move this stuff */
1507f752fed993e5e9423abac200dd59141edbada56Dave Airlie#if FEATURE_ATI_fragment_shader
1517f752fed993e5e9423abac200dd59141edbada56Dave Airlie   if (ctx->ATIFragmentShader.Current) {
15263d683091fe3a9600b65ae7ef3b554168b805406Brian Paul      ctx->ATIFragmentShader.Current->RefCount--;
15363d683091fe3a9600b65ae7ef3b554168b805406Brian Paul      if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
15432f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg         free(ctx->ATIFragmentShader.Current);
15563d683091fe3a9600b65ae7ef3b554168b805406Brian Paul      }
1567f752fed993e5e9423abac200dd59141edbada56Dave Airlie   }
1577f752fed993e5e9423abac200dd59141edbada56Dave Airlie#endif
15832f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free((void *) ctx->Program.ErrorString);
15921841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul}
16021841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul
16121841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul
1624b654d41da08b3b5475144c027e97a3ae7ab5696Brian/**
1634b654d41da08b3b5475144c027e97a3ae7ab5696Brian * Update the default program objects in the given context to reference those
164d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle * specified in the shared state and release those referencing the old
1654b654d41da08b3b5475144c027e97a3ae7ab5696Brian * shared state.
1664b654d41da08b3b5475144c027e97a3ae7ab5696Brian */
1674b654d41da08b3b5475144c027e97a3ae7ab5696Brianvoid
168f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_update_default_objects_program(struct gl_context *ctx)
1694b654d41da08b3b5475144c027e97a3ae7ab5696Brian{
1704b654d41da08b3b5475144c027e97a3ae7ab5696Brian#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
17157e222d6e5ef5744491d093475e1136aedf81810Brian Paul   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
17257e222d6e5ef5744491d093475e1136aedf81810Brian Paul                            ctx->Shared->DefaultVertexProgram);
1734b654d41da08b3b5475144c027e97a3ae7ab5696Brian   assert(ctx->VertexProgram.Current);
1744b654d41da08b3b5475144c027e97a3ae7ab5696Brian#endif
1754b654d41da08b3b5475144c027e97a3ae7ab5696Brian
1764b654d41da08b3b5475144c027e97a3ae7ab5696Brian#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
17757e222d6e5ef5744491d093475e1136aedf81810Brian Paul   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
17857e222d6e5ef5744491d093475e1136aedf81810Brian Paul                            ctx->Shared->DefaultFragmentProgram);
1794b654d41da08b3b5475144c027e97a3ae7ab5696Brian   assert(ctx->FragmentProgram.Current);
1804b654d41da08b3b5475144c027e97a3ae7ab5696Brian#endif
1814b654d41da08b3b5475144c027e97a3ae7ab5696Brian
182da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin#if FEATURE_ARB_geometry_shader4
183da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
184e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul                      ctx->Shared->DefaultGeometryProgram);
185da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin#endif
186da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin
1874b654d41da08b3b5475144c027e97a3ae7ab5696Brian   /* XXX probably move this stuff */
1884b654d41da08b3b5475144c027e97a3ae7ab5696Brian#if FEATURE_ATI_fragment_shader
1894b654d41da08b3b5475144c027e97a3ae7ab5696Brian   if (ctx->ATIFragmentShader.Current) {
1904b654d41da08b3b5475144c027e97a3ae7ab5696Brian      ctx->ATIFragmentShader.Current->RefCount--;
1914b654d41da08b3b5475144c027e97a3ae7ab5696Brian      if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
19232f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg         free(ctx->ATIFragmentShader.Current);
1934b654d41da08b3b5475144c027e97a3ae7ab5696Brian      }
1944b654d41da08b3b5475144c027e97a3ae7ab5696Brian   }
1954b654d41da08b3b5475144c027e97a3ae7ab5696Brian   ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
1964b654d41da08b3b5475144c027e97a3ae7ab5696Brian   assert(ctx->ATIFragmentShader.Current);
1974b654d41da08b3b5475144c027e97a3ae7ab5696Brian   ctx->ATIFragmentShader.Current->RefCount++;
1984b654d41da08b3b5475144c027e97a3ae7ab5696Brian#endif
1994b654d41da08b3b5475144c027e97a3ae7ab5696Brian}
20021841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul
20121841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul
20221841f0ae5ca9b55ee23ecaa3513e91b6752aa16Brian Paul/**
2032861e737e84e4884109b9526ac645194ba892a74Michal Krol * Set the vertex/fragment program error state (position and error string).
2042861e737e84e4884109b9526ac645194ba892a74Michal Krol * This is generally called from within the parsers.
2052861e737e84e4884109b9526ac645194ba892a74Michal Krol */
2062861e737e84e4884109b9526ac645194ba892a74Michal Krolvoid
207f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string)
2082861e737e84e4884109b9526ac645194ba892a74Michal Krol{
2092861e737e84e4884109b9526ac645194ba892a74Michal Krol   ctx->Program.ErrorPos = pos;
21032f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free((void *) ctx->Program.ErrorString);
2112861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (!string)
2122861e737e84e4884109b9526ac645194ba892a74Michal Krol      string = "";
2132861e737e84e4884109b9526ac645194ba892a74Michal Krol   ctx->Program.ErrorString = _mesa_strdup(string);
2142861e737e84e4884109b9526ac645194ba892a74Michal Krol}
2152861e737e84e4884109b9526ac645194ba892a74Michal Krol
2162861e737e84e4884109b9526ac645194ba892a74Michal Krol
2172861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
2182861e737e84e4884109b9526ac645194ba892a74Michal Krol * Find the line number and column for 'pos' within 'string'.
2192861e737e84e4884109b9526ac645194ba892a74Michal Krol * Return a copy of the line which contains 'pos'.  Free the line with
22032f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg * free().
2212861e737e84e4884109b9526ac645194ba892a74Michal Krol * \param string  the program string
2222861e737e84e4884109b9526ac645194ba892a74Michal Krol * \param pos     the position within the string
2232861e737e84e4884109b9526ac645194ba892a74Michal Krol * \param line    returns the line number corresponding to 'pos'.
2242861e737e84e4884109b9526ac645194ba892a74Michal Krol * \param col     returns the column number corresponding to 'pos'.
2252861e737e84e4884109b9526ac645194ba892a74Michal Krol * \return copy of the line containing 'pos'.
2262861e737e84e4884109b9526ac645194ba892a74Michal Krol */
2272861e737e84e4884109b9526ac645194ba892a74Michal Krolconst GLubyte *
2282861e737e84e4884109b9526ac645194ba892a74Michal Krol_mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
2292861e737e84e4884109b9526ac645194ba892a74Michal Krol                       GLint *line, GLint *col)
2302861e737e84e4884109b9526ac645194ba892a74Michal Krol{
2312861e737e84e4884109b9526ac645194ba892a74Michal Krol   const GLubyte *lineStart = string;
2322861e737e84e4884109b9526ac645194ba892a74Michal Krol   const GLubyte *p = string;
2332861e737e84e4884109b9526ac645194ba892a74Michal Krol   GLubyte *s;
2342861e737e84e4884109b9526ac645194ba892a74Michal Krol   int len;
2352861e737e84e4884109b9526ac645194ba892a74Michal Krol
2362861e737e84e4884109b9526ac645194ba892a74Michal Krol   *line = 1;
2372861e737e84e4884109b9526ac645194ba892a74Michal Krol
2382861e737e84e4884109b9526ac645194ba892a74Michal Krol   while (p != pos) {
2392861e737e84e4884109b9526ac645194ba892a74Michal Krol      if (*p == (GLubyte) '\n') {
2402861e737e84e4884109b9526ac645194ba892a74Michal Krol         (*line)++;
2412861e737e84e4884109b9526ac645194ba892a74Michal Krol         lineStart = p + 1;
2422861e737e84e4884109b9526ac645194ba892a74Michal Krol      }
2432861e737e84e4884109b9526ac645194ba892a74Michal Krol      p++;
2442861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
2452861e737e84e4884109b9526ac645194ba892a74Michal Krol
2462861e737e84e4884109b9526ac645194ba892a74Michal Krol   *col = (pos - lineStart) + 1;
2472861e737e84e4884109b9526ac645194ba892a74Michal Krol
2482861e737e84e4884109b9526ac645194ba892a74Michal Krol   /* return copy of this line */
2492861e737e84e4884109b9526ac645194ba892a74Michal Krol   while (*p != 0 && *p != '\n')
2502861e737e84e4884109b9526ac645194ba892a74Michal Krol      p++;
2512861e737e84e4884109b9526ac645194ba892a74Michal Krol   len = p - lineStart;
25232f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   s = (GLubyte *) malloc(len + 1);
253c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke   memcpy(s, lineStart, len);
2542861e737e84e4884109b9526ac645194ba892a74Michal Krol   s[len] = 0;
2552861e737e84e4884109b9526ac645194ba892a74Michal Krol
2562861e737e84e4884109b9526ac645194ba892a74Michal Krol   return s;
2572861e737e84e4884109b9526ac645194ba892a74Michal Krol}
2582861e737e84e4884109b9526ac645194ba892a74Michal Krol
2592861e737e84e4884109b9526ac645194ba892a74Michal Krol
260765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul/**
261765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul * Initialize a new vertex/fragment program object.
262765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul */
263122629f27925a9dc50029bebc5079f87f416a7e1Brian Paulstatic struct gl_program *
264f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_program_struct( struct gl_context *ctx, struct gl_program *prog,
265765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul                           GLenum target, GLuint id)
2662861e737e84e4884109b9526ac645194ba892a74Michal Krol{
267a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
2682861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (prog) {
2690c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      GLuint i;
2706bf1ea897fa470af58fe8916dff45e2da79634a3Brian Paul      memset(prog, 0, sizeof(*prog));
2712861e737e84e4884109b9526ac645194ba892a74Michal Krol      prog->Id = id;
2722861e737e84e4884109b9526ac645194ba892a74Michal Krol      prog->Target = target;
2732861e737e84e4884109b9526ac645194ba892a74Michal Krol      prog->Resident = GL_TRUE;
2742861e737e84e4884109b9526ac645194ba892a74Michal Krol      prog->RefCount = 1;
275308b85f29f191409e42935a3ccd5c502bdf70608Brian Paul      prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
2760c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul
2770c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      /* default mapping from samplers to texture units */
2780c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      for (i = 0; i < MAX_SAMPLERS; i++)
2790c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         prog->SamplerUnits[i] = i;
2802861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
2812861e737e84e4884109b9526ac645194ba892a74Michal Krol
2822861e737e84e4884109b9526ac645194ba892a74Michal Krol   return prog;
2832861e737e84e4884109b9526ac645194ba892a74Michal Krol}
2842861e737e84e4884109b9526ac645194ba892a74Michal Krol
285765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul
286765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul/**
287765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul * Initialize a new fragment program object.
288765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul */
289122629f27925a9dc50029bebc5079f87f416a7e1Brian Paulstruct gl_program *
290f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_fragment_program( struct gl_context *ctx, struct gl_fragment_program *prog,
291765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul                             GLenum target, GLuint id)
2922861e737e84e4884109b9526ac645194ba892a74Michal Krol{
293d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   if (prog)
2942861e737e84e4884109b9526ac645194ba892a74Michal Krol      return _mesa_init_program_struct( ctx, &prog->Base, target, id );
2952861e737e84e4884109b9526ac645194ba892a74Michal Krol   else
2962861e737e84e4884109b9526ac645194ba892a74Michal Krol      return NULL;
2972861e737e84e4884109b9526ac645194ba892a74Michal Krol}
2982861e737e84e4884109b9526ac645194ba892a74Michal Krol
299765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul
300765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul/**
301765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul * Initialize a new vertex program object.
302765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul */
303122629f27925a9dc50029bebc5079f87f416a7e1Brian Paulstruct gl_program *
304f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_vertex_program( struct gl_context *ctx, struct gl_vertex_program *prog,
305765f1a12c6256282fe175ec92a0d01b45e4322c7Brian Paul                           GLenum target, GLuint id)
3062861e737e84e4884109b9526ac645194ba892a74Michal Krol{
307d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   if (prog)
3082861e737e84e4884109b9526ac645194ba892a74Michal Krol      return _mesa_init_program_struct( ctx, &prog->Base, target, id );
3092861e737e84e4884109b9526ac645194ba892a74Michal Krol   else
3102861e737e84e4884109b9526ac645194ba892a74Michal Krol      return NULL;
3112861e737e84e4884109b9526ac645194ba892a74Michal Krol}
3122861e737e84e4884109b9526ac645194ba892a74Michal Krol
3132861e737e84e4884109b9526ac645194ba892a74Michal Krol
3142861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
315da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin * Initialize a new geometry program object.
316da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin */
317da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusinstruct gl_program *
318f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_init_geometry_program( struct gl_context *ctx, struct gl_geometry_program *prog,
319da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin                             GLenum target, GLuint id)
320da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin{
321da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   if (prog)
322da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin      return _mesa_init_program_struct( ctx, &prog->Base, target, id );
323da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   else
324da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin      return NULL;
325da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin}
326da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin
327da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin
328da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin/**
3292861e737e84e4884109b9526ac645194ba892a74Michal Krol * Allocate and initialize a new fragment/vertex program object but
3302861e737e84e4884109b9526ac645194ba892a74Michal Krol * don't put it into the program hash table.  Called via
3312861e737e84e4884109b9526ac645194ba892a74Michal Krol * ctx->Driver.NewProgram.  May be overridden (ie. replaced) by a
3322861e737e84e4884109b9526ac645194ba892a74Michal Krol * device driver function to implement OO deriviation with additional
3332861e737e84e4884109b9526ac645194ba892a74Michal Krol * types not understood by this function.
334d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle *
3352861e737e84e4884109b9526ac645194ba892a74Michal Krol * \param ctx  context
3362861e737e84e4884109b9526ac645194ba892a74Michal Krol * \param id   program id/number
3372861e737e84e4884109b9526ac645194ba892a74Michal Krol * \param target  program target/type
3382861e737e84e4884109b9526ac645194ba892a74Michal Krol * \return  pointer to new program object
3392861e737e84e4884109b9526ac645194ba892a74Michal Krol */
340122629f27925a9dc50029bebc5079f87f416a7e1Brian Paulstruct gl_program *
341f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id)
3422861e737e84e4884109b9526ac645194ba892a74Michal Krol{
343a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul   struct gl_program *prog;
3442861e737e84e4884109b9526ac645194ba892a74Michal Krol   switch (target) {
3452861e737e84e4884109b9526ac645194ba892a74Michal Krol   case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
346c5af2ed60fa4fe3f33b53a8e252e24cfa490a156Brian Paul   case GL_VERTEX_STATE_PROGRAM_NV:
347a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul      prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
348122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                                       target, id );
349a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul      break;
3502861e737e84e4884109b9526ac645194ba892a74Michal Krol   case GL_FRAGMENT_PROGRAM_NV:
3512861e737e84e4884109b9526ac645194ba892a74Michal Krol   case GL_FRAGMENT_PROGRAM_ARB:
352a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul      prog =_mesa_init_fragment_program(ctx,
353122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                                         CALLOC_STRUCT(gl_fragment_program),
354122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                                         target, id );
355a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul      break;
356da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   case MESA_GEOMETRY_PROGRAM:
357da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin      prog = _mesa_init_geometry_program(ctx,
358da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin                                         CALLOC_STRUCT(gl_geometry_program),
359da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin                                         target, id);
360da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin      break;
3612861e737e84e4884109b9526ac645194ba892a74Michal Krol   default:
3622861e737e84e4884109b9526ac645194ba892a74Michal Krol      _mesa_problem(ctx, "bad target in _mesa_new_program");
363a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul      prog = NULL;
3642861e737e84e4884109b9526ac645194ba892a74Michal Krol   }
365a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul   return prog;
3662861e737e84e4884109b9526ac645194ba892a74Michal Krol}
3672861e737e84e4884109b9526ac645194ba892a74Michal Krol
3682861e737e84e4884109b9526ac645194ba892a74Michal Krol
3692861e737e84e4884109b9526ac645194ba892a74Michal Krol/**
3702861e737e84e4884109b9526ac645194ba892a74Michal Krol * Delete a program and remove it from the hash table, ignoring the
3712861e737e84e4884109b9526ac645194ba892a74Michal Krol * reference count.
3722861e737e84e4884109b9526ac645194ba892a74Michal Krol * Called via ctx->Driver.DeleteProgram.  May be wrapped (OO deriviation)
3732861e737e84e4884109b9526ac645194ba892a74Michal Krol * by a device driver function.
3742861e737e84e4884109b9526ac645194ba892a74Michal Krol */
3752861e737e84e4884109b9526ac645194ba892a74Michal Krolvoid
376f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
3772861e737e84e4884109b9526ac645194ba892a74Michal Krol{
378a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
37957e222d6e5ef5744491d093475e1136aedf81810Brian Paul   ASSERT(prog);
38057e222d6e5ef5744491d093475e1136aedf81810Brian Paul   ASSERT(prog->RefCount==0);
3812861e737e84e4884109b9526ac645194ba892a74Michal Krol
382308b85f29f191409e42935a3ccd5c502bdf70608Brian Paul   if (prog == &_mesa_DummyProgram)
383308b85f29f191409e42935a3ccd5c502bdf70608Brian Paul      return;
384d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
3852861e737e84e4884109b9526ac645194ba892a74Michal Krol   if (prog->String)
38632f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg      free(prog->String);
387de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul
3881e5fd8e480b661c1ab748c2ded587650ea7f3d20Bryan Cain   if (prog->Instructions) {
3891e5fd8e480b661c1ab748c2ded587650ea7f3d20Bryan Cain      _mesa_free_instructions(prog->Instructions, prog->NumInstructions);
3901e5fd8e480b661c1ab748c2ded587650ea7f3d20Bryan Cain   }
39165a51c0d6243f07491578e95b85bc483f923b817Brian Paul   if (prog->Parameters) {
392de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul      _mesa_free_parameter_list(prog->Parameters);
39365a51c0d6243f07491578e95b85bc483f923b817Brian Paul   }
394fe1d01cb398cbcb5b28a0b222845d3865c4d612bBrian
39532f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(prog);
3962861e737e84e4884109b9526ac645194ba892a74Michal Krol}
3972861e737e84e4884109b9526ac645194ba892a74Michal Krol
3982861e737e84e4884109b9526ac645194ba892a74Michal Krol
3994d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul/**
4004d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul * Return the gl_program object for a given ID.
4014d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of
4024d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul * casts elsewhere.
4034d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul */
4044d12a05e6c11ca8d7325503131b2594dfe304164Brian Paulstruct gl_program *
405f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_lookup_program(struct gl_context *ctx, GLuint id)
4064d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul{
4074d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul   if (id)
4084d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul      return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
4094d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul   else
4104d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul      return NULL;
4114d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul}
4124d12a05e6c11ca8d7325503131b2594dfe304164Brian Paul
4132861e737e84e4884109b9526ac645194ba892a74Michal Krol
4143b9b8de9b0bf2f1e69a450360a812090520b2b29Brian Paul/**
415df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian * Reference counting for vertex/fragment programs
416323e4bff799a657632c5777c8be6e306202953afDave Airlie * This is normally only called from the _mesa_reference_program() macro
417323e4bff799a657632c5777c8be6e306202953afDave Airlie * when there's a real pointer change.
418df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian */
419df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrianvoid
420323e4bff799a657632c5777c8be6e306202953afDave Airlie_mesa_reference_program_(struct gl_context *ctx,
421323e4bff799a657632c5777c8be6e306202953afDave Airlie                         struct gl_program **ptr,
422323e4bff799a657632c5777c8be6e306202953afDave Airlie                         struct gl_program *prog)
423df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian{
424323e4bff799a657632c5777c8be6e306202953afDave Airlie#ifndef NDEBUG
425df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   assert(ptr);
426df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   if (*ptr && prog) {
427df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      /* sanity check */
4284bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul      if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB)
4294bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul         ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB);
4304bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul      else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
4314bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul         ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
4324bc39c58eb7fdf3a0be62bed666998a0d1789dcfBrian Paul                prog->Target == GL_FRAGMENT_PROGRAM_NV);
433da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin      else if ((*ptr)->Target == MESA_GEOMETRY_PROGRAM)
434da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin         ASSERT(prog->Target == MESA_GEOMETRY_PROGRAM);
435df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   }
436323e4bff799a657632c5777c8be6e306202953afDave Airlie#endif
437323e4bff799a657632c5777c8be6e306202953afDave Airlie
438df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   if (*ptr) {
439df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      GLboolean deleteFlag;
440df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
441df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/
442b4e75d6c41b2561ca86321fb775ca774c8af44ebBrian Paul#if 0
443a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul      printf("Program %p ID=%u Target=%s  Refcount-- to %d\n",
444a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul             *ptr, (*ptr)->Id,
445da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin             ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" :
446da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin              ((*ptr)->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")),
447a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul             (*ptr)->RefCount - 1);
448df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian#endif
449df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      ASSERT((*ptr)->RefCount > 0);
450df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      (*ptr)->RefCount--;
451df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
452df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      deleteFlag = ((*ptr)->RefCount == 0);
453df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/
454d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
455df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      if (deleteFlag) {
456df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         ASSERT(ctx);
457df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian         ctx->Driver.DeleteProgram(ctx, *ptr);
458df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      }
459df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
460df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      *ptr = NULL;
461df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   }
462df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
463df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   assert(!*ptr);
464df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   if (prog) {
465df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      /*_glthread_LOCK_MUTEX(prog->Mutex);*/
466df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      prog->RefCount++;
467b4e75d6c41b2561ca86321fb775ca774c8af44ebBrian Paul#if 0
468a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul      printf("Program %p ID=%u Target=%s  Refcount++ to %d\n",
469a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul             prog, prog->Id,
470da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin             (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" :
471da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin              (prog->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")),
472a3e86d43e6c99af97c2931c883d552c9714006e8Brian Paul             prog->RefCount);
473df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian#endif
474df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian      /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/
475df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   }
476df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
477df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   *ptr = prog;
478df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian}
479df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
480df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
481df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian/**
482b2a3a8554a114d93691d5350c234d2022c2c2916Brian * Return a copy of a program.
483b2a3a8554a114d93691d5350c234d2022c2c2916Brian * XXX Problem here if the program object is actually OO-derivation
484b2a3a8554a114d93691d5350c234d2022c2c2916Brian * made by a device driver.
485b2a3a8554a114d93691d5350c234d2022c2c2916Brian */
486b2a3a8554a114d93691d5350c234d2022c2c2916Brianstruct gl_program *
487f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog)
488b2a3a8554a114d93691d5350c234d2022c2c2916Brian{
489b2a3a8554a114d93691d5350c234d2022c2c2916Brian   struct gl_program *clone;
490b2a3a8554a114d93691d5350c234d2022c2c2916Brian
4915b6858c023fca9d8eefce78121aabd9aad108e09Brian   clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id);
492b2a3a8554a114d93691d5350c234d2022c2c2916Brian   if (!clone)
493b2a3a8554a114d93691d5350c234d2022c2c2916Brian      return NULL;
494b2a3a8554a114d93691d5350c234d2022c2c2916Brian
495b2a3a8554a114d93691d5350c234d2022c2c2916Brian   assert(clone->Target == prog->Target);
496df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian   assert(clone->RefCount == 1);
497df43fb661b2030d9b833a42dd47b8d7bf58d73aaBrian
498b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
499b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->Format = prog->Format;
500b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
501b2a3a8554a114d93691d5350c234d2022c2c2916Brian   if (!clone->Instructions) {
50257e222d6e5ef5744491d093475e1136aedf81810Brian Paul      _mesa_reference_program(ctx, &clone, NULL);
503b2a3a8554a114d93691d5350c234d2022c2c2916Brian      return NULL;
504b2a3a8554a114d93691d5350c234d2022c2c2916Brian   }
50512229f119d754715e0315846fdd8d6e9213e8edfBrian   _mesa_copy_instructions(clone->Instructions, prog->Instructions,
50612229f119d754715e0315846fdd8d6e9213e8edfBrian                           prog->NumInstructions);
507b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->InputsRead = prog->InputsRead;
508b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->OutputsWritten = prog->OutputsWritten;
5090c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul   clone->SamplersUsed = prog->SamplersUsed;
51082635aad4203d44648dd6e345ec2b5e21ff06510Nicolai Haehnle   clone->ShadowSamplers = prog->ShadowSamplers;
511c9db223f902ce9d7e9f3038e6baac6da7f231b34Brian   memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed));
512c9db223f902ce9d7e9f3038e6baac6da7f231b34Brian
5132e76f0a846b8273843dca701543f1cba70284751Brian   if (prog->Parameters)
5142e76f0a846b8273843dca701543f1cba70284751Brian      clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
515b2a3a8554a114d93691d5350c234d2022c2c2916Brian   memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
516b2a3a8554a114d93691d5350c234d2022c2c2916Brian   memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
51756643096f1eb01eefa1a532ac096b32d23b6b8baBrian Paul   clone->IndirectRegisterFiles = prog->IndirectRegisterFiles;
518b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumInstructions = prog->NumInstructions;
519b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumTemporaries = prog->NumTemporaries;
520b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumParameters = prog->NumParameters;
521b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumAttributes = prog->NumAttributes;
522b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumAddressRegs = prog->NumAddressRegs;
523b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumNativeInstructions = prog->NumNativeInstructions;
524b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumNativeTemporaries = prog->NumNativeTemporaries;
525b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumNativeParameters = prog->NumNativeParameters;
526b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumNativeAttributes = prog->NumNativeAttributes;
527b2a3a8554a114d93691d5350c234d2022c2c2916Brian   clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
52821f99792a916a62fcfae7c208f50f192d4ce5926Brian   clone->NumAluInstructions = prog->NumAluInstructions;
52921f99792a916a62fcfae7c208f50f192d4ce5926Brian   clone->NumTexInstructions = prog->NumTexInstructions;
53021f99792a916a62fcfae7c208f50f192d4ce5926Brian   clone->NumTexIndirections = prog->NumTexIndirections;
53121f99792a916a62fcfae7c208f50f192d4ce5926Brian   clone->NumNativeAluInstructions = prog->NumNativeAluInstructions;
53221f99792a916a62fcfae7c208f50f192d4ce5926Brian   clone->NumNativeTexInstructions = prog->NumNativeTexInstructions;
53321f99792a916a62fcfae7c208f50f192d4ce5926Brian   clone->NumNativeTexIndirections = prog->NumNativeTexIndirections;
534b2a3a8554a114d93691d5350c234d2022c2c2916Brian
535b2a3a8554a114d93691d5350c234d2022c2c2916Brian   switch (prog->Target) {
536b2a3a8554a114d93691d5350c234d2022c2c2916Brian   case GL_VERTEX_PROGRAM_ARB:
537b2a3a8554a114d93691d5350c234d2022c2c2916Brian      {
538e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul         const struct gl_vertex_program *vp = gl_vertex_program_const(prog);
539e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul         struct gl_vertex_program *vpc = gl_vertex_program(clone);
540b2a3a8554a114d93691d5350c234d2022c2c2916Brian         vpc->IsPositionInvariant = vp->IsPositionInvariant;
541736e1ae42fd61f2b9f982b0491ca7daea7e615edNicolai Hähnle         vpc->IsNVProgram = vp->IsNVProgram;
542b2a3a8554a114d93691d5350c234d2022c2c2916Brian      }
543b2a3a8554a114d93691d5350c234d2022c2c2916Brian      break;
544b2a3a8554a114d93691d5350c234d2022c2c2916Brian   case GL_FRAGMENT_PROGRAM_ARB:
545b2a3a8554a114d93691d5350c234d2022c2c2916Brian      {
546e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul         const struct gl_fragment_program *fp = gl_fragment_program_const(prog);
547e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul         struct gl_fragment_program *fpc = gl_fragment_program(clone);
548b2a3a8554a114d93691d5350c234d2022c2c2916Brian         fpc->UsesKill = fp->UsesKill;
5495e310e9f8300a357d6bdaf098c72098518b564f3Paul Berry         fpc->UsesDFdy = fp->UsesDFdy;
550b947b1d433ec5a847a3071c0daac7918924f3f49Brian Paul         fpc->OriginUpperLeft = fp->OriginUpperLeft;
551b947b1d433ec5a847a3071c0daac7918924f3f49Brian Paul         fpc->PixelCenterInteger = fp->PixelCenterInteger;
552b2a3a8554a114d93691d5350c234d2022c2c2916Brian      }
553b2a3a8554a114d93691d5350c234d2022c2c2916Brian      break;
554da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin   case MESA_GEOMETRY_PROGRAM:
555da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin      {
556e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul         const struct gl_geometry_program *gp = gl_geometry_program_const(prog);
557e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul         struct gl_geometry_program *gpc = gl_geometry_program(clone);
558da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin         gpc->VerticesOut = gp->VerticesOut;
559da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin         gpc->InputType = gp->InputType;
560da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin         gpc->OutputType = gp->OutputType;
561da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin      }
562da7bd6a90e1fee5c16327338fd251c0f6be34e36Zack Rusin      break;
563b2a3a8554a114d93691d5350c234d2022c2c2916Brian   default:
564b2a3a8554a114d93691d5350c234d2022c2c2916Brian      _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
565b2a3a8554a114d93691d5350c234d2022c2c2916Brian   }
566b2a3a8554a114d93691d5350c234d2022c2c2916Brian
567b2a3a8554a114d93691d5350c234d2022c2c2916Brian   return clone;
568b2a3a8554a114d93691d5350c234d2022c2c2916Brian}
569b2a3a8554a114d93691d5350c234d2022c2c2916Brian
570b2a3a8554a114d93691d5350c234d2022c2c2916Brian
57119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul/**
57219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul * Insert 'count' NOP instructions at 'start' in the given program.
57319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul * Adjust branch targets accordingly.
57419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul */
57519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian PaulGLboolean
57619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul_mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
57719ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul{
57819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   const GLuint origLen = prog->NumInstructions;
57919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   const GLuint newLen = origLen + count;
58019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   struct prog_instruction *newInst;
58119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   GLuint i;
58219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
58319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   /* adjust branches */
58419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   for (i = 0; i < prog->NumInstructions; i++) {
58519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      struct prog_instruction *inst = prog->Instructions + i;
58619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      if (inst->BranchTarget > 0) {
587457d7218b8e0f0c21ae31564d25b7031b423b0f8José Fonseca         if ((GLuint)inst->BranchTarget >= start) {
58819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul            inst->BranchTarget += count;
58919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul         }
59019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      }
59119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   }
59219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
59319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   /* Alloc storage for new instructions */
59419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   newInst = _mesa_alloc_instructions(newLen);
59519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   if (!newInst) {
59619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul      return GL_FALSE;
59719ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   }
59819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
59919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   /* Copy 'start' instructions into new instruction buffer */
60019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   _mesa_copy_instructions(newInst, prog->Instructions, start);
60119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
60219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   /* init the new instructions */
60319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   _mesa_init_instructions(newInst + start, count);
60419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
60519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   /* Copy the remaining/tail instructions to new inst buffer */
60619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   _mesa_copy_instructions(newInst + start + count,
60719ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                           prog->Instructions + start,
60819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul                           origLen - start);
60919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
61019ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   /* free old instructions */
61119ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   _mesa_free_instructions(prog->Instructions, origLen);
61219ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
61319ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   /* install new instructions */
61419ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   prog->Instructions = newInst;
61519ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   prog->NumInstructions = newLen;
61619ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
61719ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul   return GL_TRUE;
61819ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul}
61919ad9cf7741c641bd83d20485b32d11fe27ca8dfBrian Paul
620b2a3a8554a114d93691d5350c234d2022c2c2916Brian/**
621d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle * Delete 'count' instructions at 'start' in the given program.
622d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle * Adjust branch targets accordingly.
623d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle */
624d8d086c20b5a43353c4980cf234d8329900585f5Nicolai HaehnleGLboolean
625d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count)
626d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle{
627d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   const GLuint origLen = prog->NumInstructions;
628d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   const GLuint newLen = origLen - count;
629d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   struct prog_instruction *newInst;
630d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   GLuint i;
631d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
632d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   /* adjust branches */
633d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   for (i = 0; i < prog->NumInstructions; i++) {
634d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      struct prog_instruction *inst = prog->Instructions + i;
635d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      if (inst->BranchTarget > 0) {
63620fbb24b67dda0679774756e4b6d98c2c66c2c42Brian Paul         if (inst->BranchTarget > (GLint) start) {
637d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle            inst->BranchTarget -= count;
638d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle         }
639d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      }
640d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   }
641d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
642d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   /* Alloc storage for new instructions */
643d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   newInst = _mesa_alloc_instructions(newLen);
644d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   if (!newInst) {
645d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle      return GL_FALSE;
646d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   }
647d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
648d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   /* Copy 'start' instructions into new instruction buffer */
649d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   _mesa_copy_instructions(newInst, prog->Instructions, start);
650d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
651d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   /* Copy the remaining/tail instructions to new inst buffer */
652d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   _mesa_copy_instructions(newInst + start,
653d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle                           prog->Instructions + start + count,
654d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle                           newLen - start);
655d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
656d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   /* free old instructions */
657d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   _mesa_free_instructions(prog->Instructions, origLen);
658d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
659d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   /* install new instructions */
660d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   prog->Instructions = newInst;
661d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   prog->NumInstructions = newLen;
662d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
663d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle   return GL_TRUE;
664d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle}
665d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
666d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle
667d8d086c20b5a43353c4980cf234d8329900585f5Nicolai Haehnle/**
6686ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * Search instructions for registers that match (oldFile, oldIndex),
6696ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * replacing them with (newFile, newIndex).
6706ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul */
6716ca948a303e1af7ae66ea7082af741f6880887f2Brian Paulstatic void
6726ca948a303e1af7ae66ea7082af741f6880887f2Brian Paulreplace_registers(struct prog_instruction *inst, GLuint numInst,
6736ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                  GLuint oldFile, GLuint oldIndex,
6746ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                  GLuint newFile, GLuint newIndex)
6756ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul{
6766ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   GLuint i, j;
6776ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   for (i = 0; i < numInst; i++) {
6780c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      /* src regs */
679b22a00bff4aadd390dd8af6b5b05bd2833ec7f85Brian Paul      for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) {
6806ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         if (inst[i].SrcReg[j].File == oldFile &&
6816ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul             inst[i].SrcReg[j].Index == oldIndex) {
6826ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul            inst[i].SrcReg[j].File = newFile;
6836ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul            inst[i].SrcReg[j].Index = newIndex;
6846ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         }
6856ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      }
6860c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      /* dst reg */
6870c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) {
6880c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         inst[i].DstReg.File = newFile;
6890c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         inst[i].DstReg.Index = newIndex;
6900c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      }
6916ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
6926ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul}
6936ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6946ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
6956ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul/**
6966ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * Search instructions for references to program parameters.  When found,
6976ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * increment the parameter index by 'offset'.
6986ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * Used when combining programs.
6996ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul */
7006ca948a303e1af7ae66ea7082af741f6880887f2Brian Paulstatic void
7016ca948a303e1af7ae66ea7082af741f6880887f2Brian Pauladjust_param_indexes(struct prog_instruction *inst, GLuint numInst,
7026ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                     GLuint offset)
7036ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul{
7046ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   GLuint i, j;
7056ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   for (i = 0; i < numInst; i++) {
706b22a00bff4aadd390dd8af6b5b05bd2833ec7f85Brian Paul      for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) {
7076ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         GLuint f = inst[i].SrcReg[j].File;
7086ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         if (f == PROGRAM_CONSTANT ||
7096ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul             f == PROGRAM_UNIFORM ||
7106ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul             f == PROGRAM_STATE_VAR) {
7116ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul            inst[i].SrcReg[j].Index += offset;
7126ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         }
7136ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      }
7146ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
7156ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul}
7166ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7176ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7186ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul/**
7196ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * Combine two programs into one.  Fix instructions so the outputs of
7206ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * the first program go to the inputs of the second program.
7216ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul */
7226ca948a303e1af7ae66ea7082af741f6880887f2Brian Paulstruct gl_program *
723f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_combine_programs(struct gl_context *ctx,
7240c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul                       const struct gl_program *progA,
7250c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul                       const struct gl_program *progB)
7266ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul{
7276ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   struct prog_instruction *newInst;
7286ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   struct gl_program *newProg;
7296ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */
7306ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   const GLuint lenB = progB->NumInstructions;
7316ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
7326ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   const GLuint newLength = lenA + lenB;
733a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   GLboolean usedTemps[MAX_PROGRAM_TEMPS];
734a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   GLuint firstTemp = 0;
735998f402af5b37aadc6dc8adcc19f7b6428ada007Brian Paul   GLbitfield64 inputsB;
7366ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   GLuint i;
7376ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7386ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   ASSERT(progA->Target == progB->Target);
7396ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7406ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   newInst = _mesa_alloc_instructions(newLength);
7416ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   if (!newInst)
7426ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      return GL_FALSE;
7436ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7446ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   _mesa_copy_instructions(newInst, progA->Instructions, lenA);
7456ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB);
7466ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7476ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   /* adjust branch / instruction addresses for B's instructions */
7486ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   for (i = 0; i < lenB; i++) {
7496ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      newInst[lenA + i].BranchTarget += lenA;
7506ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
7516ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
7526ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0);
7536ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   newProg->Instructions = newInst;
7546ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   newProg->NumInstructions = newLength;
7556ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
756a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   /* find used temp regs (we may need new temps below) */
757a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY,
758a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                             usedTemps, MAX_PROGRAM_TEMPS);
759a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
7606ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
761e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul      const struct gl_fragment_program *fprogA, *fprogB;
762e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul      struct gl_fragment_program *newFprog;
763998f402af5b37aadc6dc8adcc19f7b6428ada007Brian Paul      GLbitfield64 progB_inputsRead = progB->InputsRead;
7645c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      GLint progB_colorFile, progB_colorIndex;
7655c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
766e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul      fprogA = gl_fragment_program_const(progA);
767e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul      fprogB = gl_fragment_program_const(progB);
768e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul      newFprog = gl_fragment_program(newProg);
7690c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul
7700c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;
7715e310e9f8300a357d6bdaf098c72098518b564f3Paul Berry      newFprog->UsesDFdy = fprogA->UsesDFdy || fprogB->UsesDFdy;
7720c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul
7735c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      /* We'll do a search and replace for instances
7745c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       * of progB_colorFile/progB_colorIndex below...
7755c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       */
7765c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      progB_colorFile = PROGRAM_INPUT;
7775c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      progB_colorIndex = FRAG_ATTRIB_COL0;
7785c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
7795c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      /*
7805c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       * The fragment program may get color from a state var rather than
7815c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       * a fragment input (vertex output) if it's constant.
7825c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       * See the texenvprogram.c code.
7835c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       * So, search the program's parameter list now to see if the program
7845c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       * gets color from a state var instead of a conventional fragment
7855c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       * input register.
7865c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul       */
7875c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      for (i = 0; i < progB->Parameters->NumParameters; i++) {
7885c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul         struct gl_program_parameter *p = &progB->Parameters->Parameters[i];
7895c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul         if (p->Type == PROGRAM_STATE_VAR &&
7905c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul             p->StateIndexes[0] == STATE_INTERNAL &&
7915c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul             p->StateIndexes[1] == STATE_CURRENT_ATTRIB &&
792f72e4b306bb26b067b46f2d7561aabeb6f3f4be0Brian Paul             (int) p->StateIndexes[2] == (int) VERT_ATTRIB_COLOR0) {
7935c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul            progB_inputsRead |= FRAG_BIT_COL0;
7945c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul            progB_colorFile = PROGRAM_STATE_VAR;
7955c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul            progB_colorIndex = i;
7965c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul            break;
7975c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul         }
7985c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      }
7995c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul
8000c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      /* Connect color outputs of fprogA to color inputs of fprogB, via a
8010c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul       * new temporary register.
8020c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul       */
80311150e4667ce11b056d98244754ce3f2a79599a6Brian Paul      if ((progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) &&
8045c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul          (progB_inputsRead & FRAG_BIT_COL0)) {
805a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul         GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS,
806a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                                                  firstTemp);
807e469d78d33feff45f16235871ca1a3d483cdc950Brian Paul         if (tempReg < 0) {
8080c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul            _mesa_problem(ctx, "No free temp regs found in "
8090c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul                          "_mesa_combine_programs(), using 31");
8100c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul            tempReg = 31;
8110c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         }
812a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul         firstTemp = tempReg + 1;
813a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
8140c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         /* replace writes to result.color[0] with tempReg */
8150c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         replace_registers(newInst, lenA,
8168d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul                           PROGRAM_OUTPUT, FRAG_RESULT_COLOR,
8170c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul                           PROGRAM_TEMPORARY, tempReg);
8185c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul         /* replace reads from the input color with tempReg */
8196ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         replace_registers(newInst + lenA, lenB,
8205c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul                           progB_colorFile, progB_colorIndex, /* search for */
8215c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul                           PROGRAM_TEMPORARY, tempReg  /* replace with */ );
8226ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      }
8236ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8245c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      /* compute combined program's InputsRead */
8255c4bd76cb65245467d4ba04e893157055d738b2dBrian Paul      inputsB = progB_inputsRead;
82611150e4667ce11b056d98244754ce3f2a79599a6Brian Paul      if (progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
8270c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul         inputsB &= ~(1 << FRAG_ATTRIB_COL0);
8280c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      }
8290c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      newProg->InputsRead = progA->InputsRead | inputsB;
8306ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      newProg->OutputsWritten = progB->OutputsWritten;
8310c78c766e4cb8ffcda44cabfadb8de8e09121034Brian Paul      newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed;
8326ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
8336ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   else {
8346ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      /* vertex program */
8356ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      assert(0);      /* XXX todo */
8366ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
8376ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8386ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   /*
8396ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul    * Merge parameters (uniforms, constants, etc)
8406ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul    */
8416ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters,
8426ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul                                                       progB->Parameters);
8436ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8446ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   adjust_param_indexes(newInst + lenA, lenB, numParamsA);
8456ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8466ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8476ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   return newProg;
8486ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul}
8496ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8506ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8516ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul/**
852a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * Populate the 'used' array with flags indicating which registers (TEMPs,
853a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * INPUTs, OUTPUTs, etc, are used by the given program.
854a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * \param file  type of register to scan for
855a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * \param used  returns true/false flags for in use / free
856a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * \param usedSize  size of the 'used' array
8576ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul */
858a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paulvoid
859a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul_mesa_find_used_registers(const struct gl_program *prog,
860a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                          gl_register_file file,
861a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                          GLboolean used[], GLuint usedSize)
8626ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul{
863a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   GLuint i, j;
8646ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
86526f8fad1456fdc2b352cea9d3b4c32cb5f6ae947Kenneth Graunke   memset(used, 0, usedSize);
8666ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
8676ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   for (i = 0; i < prog->NumInstructions; i++) {
8686ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      const struct prog_instruction *inst = prog->Instructions + i;
8696ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
8706ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
871a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      if (inst->DstReg.File == file) {
872029c1815717ea62bae28e86798c86dfa98cbc8a7Luca Barbieri         ASSERT(inst->DstReg.Index < usedSize);
873029c1815717ea62bae28e86798c86dfa98cbc8a7Luca Barbieri         if(inst->DstReg.Index < usedSize)
874029c1815717ea62bae28e86798c86dfa98cbc8a7Luca Barbieri            used[inst->DstReg.Index] = GL_TRUE;
8755076a4f53a2f34cc9116b45951037f639885c7a1Brian Paul      }
876a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
877a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul      for (j = 0; j < n; j++) {
878a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul         if (inst->SrcReg[j].File == file) {
879029c1815717ea62bae28e86798c86dfa98cbc8a7Luca Barbieri            ASSERT(inst->SrcReg[j].Index < usedSize);
880029c1815717ea62bae28e86798c86dfa98cbc8a7Luca Barbieri            if(inst->SrcReg[j].Index < usedSize)
881029c1815717ea62bae28e86798c86dfa98cbc8a7Luca Barbieri               used[inst->SrcReg[j].Index] = GL_TRUE;
8826ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         }
8836ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      }
8846ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   }
885a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul}
8866ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
887a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
888a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul/**
889a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * Scan the given 'used' register flag array for the first entry
890a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * that's >= firstReg.
891a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * \param used  vector of flags indicating registers in use (as returned
892a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul *              by _mesa_find_used_registers())
893a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * \param usedSize  size of the 'used' array
894a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * \param firstReg  first register to start searching at
895a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul * \return index of unused register, or -1 if none.
896a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul */
897a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian PaulGLint
898a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul_mesa_find_free_register(const GLboolean used[],
899a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul                         GLuint usedSize, GLuint firstReg)
900a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul{
901a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   GLuint i;
902a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
903a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   assert(firstReg < usedSize);
904a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul
905a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul   for (i = firstReg; i < usedSize; i++)
9066ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul      if (!used[i])
9076ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul         return i;
9086ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul
9096ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul   return -1;
9106ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul}
911ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
912ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
913512f840702d58b48607a9dca06dd939256c7afedBrian Paul
914512f840702d58b48607a9dca06dd939256c7afedBrian Paul/**
915512f840702d58b48607a9dca06dd939256c7afedBrian Paul * Check if the given register index is valid (doesn't exceed implementation-
916512f840702d58b48607a9dca06dd939256c7afedBrian Paul * dependent limits).
917512f840702d58b48607a9dca06dd939256c7afedBrian Paul * \return GL_TRUE if OK, GL_FALSE if bad index
918512f840702d58b48607a9dca06dd939256c7afedBrian Paul */
919512f840702d58b48607a9dca06dd939256c7afedBrian PaulGLboolean
920512f840702d58b48607a9dca06dd939256c7afedBrian Paul_mesa_valid_register_index(const struct gl_context *ctx,
921c628fd743ee3c3305e9beac7f0e6efacf6982115Brian Paul                           gl_shader_type shaderType,
922512f840702d58b48607a9dca06dd939256c7afedBrian Paul                           gl_register_file file, GLint index)
923512f840702d58b48607a9dca06dd939256c7afedBrian Paul{
924512f840702d58b48607a9dca06dd939256c7afedBrian Paul   const struct gl_program_constants *c;
925512f840702d58b48607a9dca06dd939256c7afedBrian Paul
926512f840702d58b48607a9dca06dd939256c7afedBrian Paul   switch (shaderType) {
927512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case MESA_SHADER_VERTEX:
928512f840702d58b48607a9dca06dd939256c7afedBrian Paul      c = &ctx->Const.VertexProgram;
929512f840702d58b48607a9dca06dd939256c7afedBrian Paul      break;
930512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case MESA_SHADER_FRAGMENT:
931512f840702d58b48607a9dca06dd939256c7afedBrian Paul      c = &ctx->Const.FragmentProgram;
932512f840702d58b48607a9dca06dd939256c7afedBrian Paul      break;
933512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case MESA_SHADER_GEOMETRY:
934512f840702d58b48607a9dca06dd939256c7afedBrian Paul      c = &ctx->Const.GeometryProgram;
935512f840702d58b48607a9dca06dd939256c7afedBrian Paul      break;
936512f840702d58b48607a9dca06dd939256c7afedBrian Paul   default:
937512f840702d58b48607a9dca06dd939256c7afedBrian Paul      _mesa_problem(ctx,
938512f840702d58b48607a9dca06dd939256c7afedBrian Paul                    "unexpected shader type in _mesa_valid_register_index()");
939512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return GL_FALSE;
940512f840702d58b48607a9dca06dd939256c7afedBrian Paul   }
941512f840702d58b48607a9dca06dd939256c7afedBrian Paul
942512f840702d58b48607a9dca06dd939256c7afedBrian Paul   switch (file) {
943512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_UNDEFINED:
944512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return GL_TRUE;  /* XXX or maybe false? */
945512f840702d58b48607a9dca06dd939256c7afedBrian Paul
946512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_TEMPORARY:
947512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return index >= 0 && index < c->MaxTemps;
948512f840702d58b48607a9dca06dd939256c7afedBrian Paul
949512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_ENV_PARAM:
950512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return index >= 0 && index < c->MaxEnvParams;
951512f840702d58b48607a9dca06dd939256c7afedBrian Paul
952512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_LOCAL_PARAM:
953512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return index >= 0 && index < c->MaxLocalParams;
954512f840702d58b48607a9dca06dd939256c7afedBrian Paul
955512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_NAMED_PARAM:
956512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return index >= 0 && index < c->MaxParameters;
957512f840702d58b48607a9dca06dd939256c7afedBrian Paul
958512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_UNIFORM:
959512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_STATE_VAR:
960512f840702d58b48607a9dca06dd939256c7afedBrian Paul      /* aka constant buffer */
961512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return index >= 0 && index < c->MaxUniformComponents / 4;
962512f840702d58b48607a9dca06dd939256c7afedBrian Paul
963512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_CONSTANT:
964512f840702d58b48607a9dca06dd939256c7afedBrian Paul      /* constant buffer w/ possible relative negative addressing */
965512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return (index > (int) c->MaxUniformComponents / -4 &&
966512f840702d58b48607a9dca06dd939256c7afedBrian Paul              index < c->MaxUniformComponents / 4);
967512f840702d58b48607a9dca06dd939256c7afedBrian Paul
968512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_INPUT:
969512f840702d58b48607a9dca06dd939256c7afedBrian Paul      if (index < 0)
970512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return GL_FALSE;
971512f840702d58b48607a9dca06dd939256c7afedBrian Paul
972512f840702d58b48607a9dca06dd939256c7afedBrian Paul      switch (shaderType) {
973512f840702d58b48607a9dca06dd939256c7afedBrian Paul      case MESA_SHADER_VERTEX:
974512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return index < VERT_ATTRIB_GENERIC0 + c->MaxAttribs;
975512f840702d58b48607a9dca06dd939256c7afedBrian Paul      case MESA_SHADER_FRAGMENT:
976512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return index < FRAG_ATTRIB_VAR0 + ctx->Const.MaxVarying;
977512f840702d58b48607a9dca06dd939256c7afedBrian Paul      case MESA_SHADER_GEOMETRY:
978512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return index < GEOM_ATTRIB_VAR0 + ctx->Const.MaxVarying;
979512f840702d58b48607a9dca06dd939256c7afedBrian Paul      default:
980512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return GL_FALSE;
981512f840702d58b48607a9dca06dd939256c7afedBrian Paul      }
982512f840702d58b48607a9dca06dd939256c7afedBrian Paul
983512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_OUTPUT:
984512f840702d58b48607a9dca06dd939256c7afedBrian Paul      if (index < 0)
985512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return GL_FALSE;
986512f840702d58b48607a9dca06dd939256c7afedBrian Paul
987512f840702d58b48607a9dca06dd939256c7afedBrian Paul      switch (shaderType) {
988512f840702d58b48607a9dca06dd939256c7afedBrian Paul      case MESA_SHADER_VERTEX:
989512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return index < VERT_RESULT_VAR0 + ctx->Const.MaxVarying;
990512f840702d58b48607a9dca06dd939256c7afedBrian Paul      case MESA_SHADER_FRAGMENT:
991512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return index < FRAG_RESULT_DATA0 + ctx->Const.MaxDrawBuffers;
992512f840702d58b48607a9dca06dd939256c7afedBrian Paul      case MESA_SHADER_GEOMETRY:
993512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return index < GEOM_RESULT_VAR0 + ctx->Const.MaxVarying;
994512f840702d58b48607a9dca06dd939256c7afedBrian Paul      default:
995512f840702d58b48607a9dca06dd939256c7afedBrian Paul         return GL_FALSE;
996512f840702d58b48607a9dca06dd939256c7afedBrian Paul      }
997512f840702d58b48607a9dca06dd939256c7afedBrian Paul
998512f840702d58b48607a9dca06dd939256c7afedBrian Paul   case PROGRAM_ADDRESS:
999512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return index >= 0 && index < c->MaxAddressRegs;
1000512f840702d58b48607a9dca06dd939256c7afedBrian Paul
1001512f840702d58b48607a9dca06dd939256c7afedBrian Paul   default:
1002512f840702d58b48607a9dca06dd939256c7afedBrian Paul      _mesa_problem(ctx,
1003512f840702d58b48607a9dca06dd939256c7afedBrian Paul                    "unexpected register file in _mesa_valid_register_index()");
1004512f840702d58b48607a9dca06dd939256c7afedBrian Paul      return GL_FALSE;
1005512f840702d58b48607a9dca06dd939256c7afedBrian Paul   }
1006512f840702d58b48607a9dca06dd939256c7afedBrian Paul}
1007512f840702d58b48607a9dca06dd939256c7afedBrian Paul
1008512f840702d58b48607a9dca06dd939256c7afedBrian Paul
1009512f840702d58b48607a9dca06dd939256c7afedBrian Paul
1010ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul/**
1011ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul * "Post-process" a GPU program.  This is intended to be used for debugging.
1012ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul * Example actions include no-op'ing instructions or changing instruction
1013ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul * behaviour.
1014ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul */
1015ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paulvoid
1016f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog)
1017ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul{
1018ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
1019ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   GLuint i;
1020ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   GLuint whiteSwizzle;
1021ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters,
10226d89abadbcd68bbe9e08f041412549f8dc1fc73cBryan Cain                                                 (gl_constant_value *) white,
10236d89abadbcd68bbe9e08f041412549f8dc1fc73cBryan Cain                                                 4, &whiteSwizzle);
1024ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
1025516d20fd2688fce833b764ca21f1f1772bed0a03Brian Paul   (void) whiteIndex;
1026516d20fd2688fce833b764ca21f1f1772bed0a03Brian Paul
1027ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   for (i = 0; i < prog->NumInstructions; i++) {
1028ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      struct prog_instruction *inst = prog->Instructions + i;
1029ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
1030ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
1031ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      (void) n;
1032ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
1033ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      if (_mesa_is_tex_instruction(inst->Opcode)) {
1034ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#if 0
1035ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         /* replace TEX/TXP/TXB with MOV */
1036ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->Opcode = OPCODE_MOV;
1037ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->DstReg.WriteMask = WRITEMASK_XYZW;
1038ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
1039ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->SrcReg[0].Negate = NEGATE_NONE;
1040ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#endif
1041ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
1042ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#if 0
1043ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         /* disable shadow texture mode */
1044ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->TexShadow = 0;
1045ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#endif
1046ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      }
1047ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
1048ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      if (inst->Opcode == OPCODE_TXP) {
1049ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#if 0
1050ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->Opcode = OPCODE_MOV;
1051ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->DstReg.WriteMask = WRITEMASK_XYZW;
1052ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->SrcReg[0].File = PROGRAM_CONSTANT;
1053ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->SrcReg[0].Index = whiteIndex;
1054ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
1055ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->SrcReg[0].Negate = NEGATE_NONE;
1056ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#endif
1057ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#if 0
1058ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->TexShadow = 0;
1059ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#endif
1060ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#if 0
1061ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->Opcode = OPCODE_TEX;
1062ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul         inst->TexShadow = 0;
1063ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul#endif
1064ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul      }
1065ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul
1066ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul   }
1067ec6ad7ba3ce4fa71620642ddde06cf843d1c8d54Brian Paul}
1068