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