diff options
Diffstat (limited to 'dist/Mesa/src/mesa')
156 files changed, 56790 insertions, 0 deletions
diff --git a/dist/Mesa/src/mesa/drivers/dri/common/xmlpool/sv.po b/dist/Mesa/src/mesa/drivers/dri/common/xmlpool/sv.po new file mode 100644 index 000000000..ba32b2ff1 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/common/xmlpool/sv.po @@ -0,0 +1,226 @@ +# Swedish translation of DRI driver options. +# Copyright (C) Free Software Foundation, Inc. +# This file is distributed under the same license as the Mesa package. +# Daniel Nylander <po@danielnylander.se>, 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: Mesa DRI\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-04-11 23:19+0200\n" +"PO-Revision-Date: 2006-09-18 10:56+0100\n" +"Last-Translator: Daniel Nylander <po@danielnylander.se>\n" +"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: t_options.h:53 +msgid "Debugging" +msgstr "Felsökning" + +#: t_options.h:57 +msgid "Disable 3D acceleration" +msgstr "Inaktivera 3D-accelerering" + +#: t_options.h:62 +msgid "Show performance boxes" +msgstr "Visa prestandarutor" + +#: t_options.h:69 +msgid "Image Quality" +msgstr "Bildkvalitet" + +#: t_options.h:77 +msgid "Texture color depth" +msgstr "Färgdjup för texturer" + +#: t_options.h:78 +msgid "Prefer frame buffer color depth" +msgstr "Föredra färgdjupet för framebuffer" + +#: t_options.h:79 +msgid "Prefer 32 bits per texel" +msgstr "Föredra 32 bitar per texel" + +#: t_options.h:80 +msgid "Prefer 16 bits per texel" +msgstr "Föredra 16 bitar per texel" + +#: t_options.h:81 +msgid "Force 16 bits per texel" +msgstr "Tvinga 16 bitar per texel" + +#: t_options.h:87 +msgid "Initial maximum value for anisotropic texture filtering" +msgstr "Initialt maximalt värde för anisotropisk texturfiltrering" + +#: t_options.h:92 +msgid "Forbid negative texture LOD bias" +msgstr "Förbjud negativ LOD-kompensation för texturer" + +#: t_options.h:97 +msgid "Enable S3TC texture compression even if software support is not available" +msgstr "Aktivera S3TC-texturkomprimering även om programvarustöd saknas" + +#: t_options.h:104 +msgid "Initial color reduction method" +msgstr "Initial färgminskningsmetod" + +#: t_options.h:105 +msgid "Round colors" +msgstr "Avrunda färger" + +#: t_options.h:106 +msgid "Dither colors" +msgstr "Utjämna färger" + +#: t_options.h:114 +msgid "Color rounding method" +msgstr "Färgavrundningsmetod" + +#: t_options.h:115 +msgid "Round color components downward" +msgstr "Avrunda färdkomponenter nedåt" + +#: t_options.h:116 +msgid "Round to nearest color" +msgstr "Avrunda till närmsta färg" + +#: t_options.h:125 +msgid "Color dithering method" +msgstr "Färgutjämningsmetod" + +#: t_options.h:126 +msgid "Horizontal error diffusion" +msgstr "Horisontell felspridning" + +#: t_options.h:127 +msgid "Horizontal error diffusion, reset error at line start" +msgstr "Horisontell felspridning, återställ fel vid radbörjan" + +#: t_options.h:128 +msgid "Ordered 2D color dithering" +msgstr "Ordnad 2D-färgutjämning" + +#: t_options.h:134 +msgid "Floating point depth buffer" +msgstr "Buffert för flytande punktdjup" + +#: t_options.h:140 +msgid "Performance" +msgstr "Prestanda" + +#: t_options.h:148 +msgid "TCL mode (Transformation, Clipping, Lighting)" +msgstr "TCL-läge (Transformation, Clipping, Lighting)" + +#: t_options.h:149 +msgid "Use software TCL pipeline" +msgstr "Använd programvaru-TCL-rörledning" + +#: t_options.h:150 +msgid "Use hardware TCL as first TCL pipeline stage" +msgstr "Använd maskinvaru-TCL som första TCL-rörledningssteg" + +#: t_options.h:151 +msgid "Bypass the TCL pipeline" +msgstr "Kringgå TCL-rörledningen" + +#: t_options.h:152 +msgid "Bypass the TCL pipeline with state-based machine code generated on-the-fly" +msgstr "Kringgå TCL-rörledningen med tillståndsbaserad maskinkod som direktgenereras" + +#: t_options.h:161 +msgid "Method to limit rendering latency" +msgstr "Metod för att begränsa renderingslatens" + +#: t_options.h:162 +msgid "Busy waiting for the graphics hardware" +msgstr "Upptagen med att vänta på grafikhårdvaran" + +#: t_options.h:163 +msgid "Sleep for brief intervals while waiting for the graphics hardware" +msgstr "Sov i korta intervall under väntan på grafikhårdvaran" + +#: t_options.h:164 +msgid "Let the graphics hardware emit a software interrupt and sleep" +msgstr "Låt grafikhårdvaran sända ut ett programvaruavbrott och sov" + +#: t_options.h:174 +msgid "Synchronization with vertical refresh (swap intervals)" +msgstr "Synkronisering med vertikal uppdatering (växlingsintervall)" + +#: t_options.h:175 +msgid "Never synchronize with vertical refresh, ignore application's choice" +msgstr "Synkronisera aldrig med vertikal uppdatering, ignorera programmets val" + +#: t_options.h:176 +msgid "Initial swap interval 0, obey application's choice" +msgstr "Initialt växlingsintervall 0, följ programmets val" + +#: t_options.h:177 +msgid "Initial swap interval 1, obey application's choice" +msgstr "Initialt växlingsintervall 1, följ programmets val" + +#: t_options.h:178 +msgid "Always synchronize with vertical refresh, application chooses the minimum swap interval" +msgstr "Synkronisera alltid med vertikal uppdatering, programmet väljer den minsta växlingsintervallen" + +#: t_options.h:186 +msgid "Use HyperZ to boost performance" +msgstr "Använd HyperZ för att maximera prestandan" + +#: t_options.h:191 +msgid "Number of texture units used" +msgstr "Antal använda texturenheter" + +#: t_options.h:196 +msgid "Support larger textures not guaranteed to fit into graphics memory" +msgstr "Stöd för större texturer är inte garanterat att passa i grafikminnet" + +#: t_options.h:197 +msgid "No" +msgstr "Nej" + +#: t_options.h:198 +msgid "At least 1 texture must fit under worst-case assumptions" +msgstr "Åtminstone en textur måste passa för antaget sämsta förhållande" + +#: t_options.h:199 +msgid "Announce hardware limits" +msgstr "Annonsera hårdvarubegränsningar" + +#: t_options.h:205 +msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" +msgstr "Texturfiltreringskvalitet mot hastighet, även kallad \"brilinear\"-texturfiltrering" + +#: t_options.h:213 +msgid "Used types of texture memory" +msgstr "Använda typer av texturminne" + +#: t_options.h:214 +msgid "All available memory" +msgstr "Allt tillgängligt minne" + +#: t_options.h:215 +msgid "Only card memory (if available)" +msgstr "Endast kortminne (om tillgängligt)" + +#: t_options.h:216 +msgid "Only GART (AGP/PCIE) memory (if available)" +msgstr "Endast GART-minne (AGP/PCIE) (om tillgängligt)" + +#: t_options.h:224 +msgid "Features that are not hardware-accelerated" +msgstr "Funktioner som inte är hårdvaruaccelererade" + +#: t_options.h:228 +msgid "Enable extension GL_ARB_vertex_program" +msgstr "Aktivera tillägget GL_ARB_vertex_program" + +#: t_options.h:233 +msgid "Enable extension GL_NV_vertex_program" +msgstr "Aktivera tillägget GL_NV_vertex_program" + diff --git a/dist/Mesa/src/mesa/drivers/dri/i965/brw_exec_generic.c b/dist/Mesa/src/mesa/drivers/dri/i965/brw_exec_generic.c new file mode 100644 index 000000000..11d1ef76f --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/i965/brw_exec_generic.c @@ -0,0 +1,530 @@ +/************************************************************************** + +Copyright 2004 Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "vtxfmt.h" +#include "dlist.h" +#include "state.h" +#include "light.h" +#include "api_arrayelt.h" +#include "api_noop.h" + +#include "brw_exec.h" + + +/* Versions of all the entrypoints for situations where codegen isn't + * available. + * + * Note: Only one size for each attribute may be active at once. + * Eg. if Color3f is installed/active, then Color4f may not be, even + * if the vertex actually contains 4 color coordinates. This is + * because the 3f version won't otherwise set color[3] to 1.0 -- this + * is the job of the chooser function when switching between Color4f + * and Color3f. + */ +#define ATTRFV( ATTR, N ) \ +static void attrib_##ATTR##_##N( const GLfloat *v ) \ +{ \ + GET_CURRENT_CONTEXT( ctx ); \ + struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec; \ + \ + if ((ATTR) == 0) { \ + GLuint i; \ + \ + if (N>0) exec->vtx.vbptr[0] = v[0]; \ + if (N>1) exec->vtx.vbptr[1] = v[1]; \ + if (N>2) exec->vtx.vbptr[2] = v[2]; \ + if (N>3) exec->vtx.vbptr[3] = v[3]; \ + \ + for (i = N; i < exec->vtx.vertex_size; i++) \ + exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \ + \ + exec->vtx.vbptr += exec->vtx.vertex_size; \ + exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ + \ + if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ + brw_exec_vtx_wrap( exec ); \ + } \ + else { \ + GLfloat *dest = exec->vtx.attrptr[ATTR]; \ + if (N>0) dest[0] = v[0]; \ + if (N>1) dest[1] = v[1]; \ + if (N>2) dest[2] = v[2]; \ + if (N>3) dest[3] = v[3]; \ + } \ +} + +#define INIT(TAB, ATTR) \ + TAB[ATTR][0] = attrib_##ATTR##_1; \ + TAB[ATTR][1] = attrib_##ATTR##_2; \ + TAB[ATTR][2] = attrib_##ATTR##_3; \ + TAB[ATTR][3] = attrib_##ATTR##_4; + + +#define ATTRS( ATTRIB ) \ + ATTRFV( ATTRIB, 1 ) \ + ATTRFV( ATTRIB, 2 ) \ + ATTRFV( ATTRIB, 3 ) \ + ATTRFV( ATTRIB, 4 ) + +ATTRS( 0 ) +ATTRS( 1 ) +ATTRS( 2 ) +ATTRS( 3 ) +ATTRS( 4 ) +ATTRS( 5 ) +ATTRS( 6 ) +ATTRS( 7 ) +ATTRS( 8 ) +ATTRS( 9 ) +ATTRS( 10 ) +ATTRS( 11 ) +ATTRS( 12 ) +ATTRS( 13 ) +ATTRS( 14 ) +ATTRS( 15 ) + +void brw_exec_generic_attr_table_init( brw_attrfv_func (*tab)[4] ) +{ + INIT( tab, 0 ); + INIT( tab, 1 ); + INIT( tab, 2 ); + INIT( tab, 3 ); + INIT( tab, 4 ); + INIT( tab, 5 ); + INIT( tab, 6 ); + INIT( tab, 7 ); + INIT( tab, 8 ); + INIT( tab, 9 ); + INIT( tab, 10 ); + INIT( tab, 11 ); + INIT( tab, 12 ); + INIT( tab, 13 ); + INIT( tab, 14 ); + INIT( tab, 15 ); +} + +/* These can be made efficient with codegen. Further, by adding more + * logic to do_choose(), the double-dispatch for legacy entrypoints + * like glVertex3f() can be removed. + */ +#define DISPATCH_ATTRFV( ATTR, COUNT, P ) \ +do { \ + GET_CURRENT_CONTEXT( ctx ); \ + struct brw_exec_context *exec = IMM_CONTEXT(ctx)->exec; \ + exec->vtx.tabfv[ATTR][COUNT-1]( P ); \ +} while (0) + +#define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V ) +#define DISPATCH_ATTR2FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 2, V ) +#define DISPATCH_ATTR3FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 3, V ) +#define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V ) + +#define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) ) + +#define DISPATCH_ATTR2F( ATTR, S,T ) \ +do { \ + GLfloat v[2]; \ + v[0] = S; v[1] = T; \ + DISPATCH_ATTR2FV( ATTR, v ); \ +} while (0) +#define DISPATCH_ATTR3F( ATTR, S,T,R ) \ +do { \ + GLfloat v[3]; \ + v[0] = S; v[1] = T; v[2] = R; \ + DISPATCH_ATTR3FV( ATTR, v ); \ +} while (0) +#define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) \ +do { \ + GLfloat v[4]; \ + v[0] = S; v[1] = T; v[2] = R; v[3] = Q; \ + DISPATCH_ATTR4FV( ATTR, v ); \ +} while (0) + + +static void GLAPIENTRY brw_Vertex2f( GLfloat x, GLfloat y ) +{ + DISPATCH_ATTR2F( BRW_ATTRIB_POS, x, y ); +} + +static void GLAPIENTRY brw_Vertex2fv( const GLfloat *v ) +{ + DISPATCH_ATTR2FV( BRW_ATTRIB_POS, v ); +} + +static void GLAPIENTRY brw_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( BRW_ATTRIB_POS, x, y, z ); +} + +static void GLAPIENTRY brw_Vertex3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( BRW_ATTRIB_POS, v ); +} + +static void GLAPIENTRY brw_Vertex4f( GLfloat x, GLfloat y, GLfloat z, + GLfloat w ) +{ + DISPATCH_ATTR4F( BRW_ATTRIB_POS, x, y, z, w ); +} + +static void GLAPIENTRY brw_Vertex4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( BRW_ATTRIB_POS, v ); +} + +static void GLAPIENTRY brw_TexCoord1f( GLfloat x ) +{ + DISPATCH_ATTR1F( BRW_ATTRIB_TEX0, x ); +} + +static void GLAPIENTRY brw_TexCoord1fv( const GLfloat *v ) +{ + DISPATCH_ATTR1FV( BRW_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY brw_TexCoord2f( GLfloat x, GLfloat y ) +{ + DISPATCH_ATTR2F( BRW_ATTRIB_TEX0, x, y ); +} + +static void GLAPIENTRY brw_TexCoord2fv( const GLfloat *v ) +{ + DISPATCH_ATTR2FV( BRW_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY brw_TexCoord3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( BRW_ATTRIB_TEX0, x, y, z ); +} + +static void GLAPIENTRY brw_TexCoord3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( BRW_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY brw_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, + GLfloat w ) +{ + DISPATCH_ATTR4F( BRW_ATTRIB_TEX0, x, y, z, w ); +} + +static void GLAPIENTRY brw_TexCoord4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( BRW_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY brw_Normal3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( BRW_ATTRIB_NORMAL, x, y, z ); +} + +static void GLAPIENTRY brw_Normal3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( BRW_ATTRIB_NORMAL, v ); +} + +static void GLAPIENTRY brw_FogCoordfEXT( GLfloat x ) +{ + DISPATCH_ATTR1F( BRW_ATTRIB_FOG, x ); +} + +static void GLAPIENTRY brw_FogCoordfvEXT( const GLfloat *v ) +{ + DISPATCH_ATTR1FV( BRW_ATTRIB_FOG, v ); +} + +static void GLAPIENTRY brw_Color3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( BRW_ATTRIB_COLOR0, x, y, z ); +} + +static void GLAPIENTRY brw_Color3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( BRW_ATTRIB_COLOR0, v ); +} + +static void GLAPIENTRY brw_Color4f( GLfloat x, GLfloat y, GLfloat z, + GLfloat w ) +{ + DISPATCH_ATTR4F( BRW_ATTRIB_COLOR0, x, y, z, w ); +} + +static void GLAPIENTRY brw_Color4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( BRW_ATTRIB_COLOR0, v ); +} + +static void GLAPIENTRY brw_SecondaryColor3fEXT( GLfloat x, GLfloat y, + GLfloat z ) +{ + DISPATCH_ATTR3F( BRW_ATTRIB_COLOR1, x, y, z ); +} + +static void GLAPIENTRY brw_SecondaryColor3fvEXT( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( BRW_ATTRIB_COLOR1, v ); +} + +static void GLAPIENTRY brw_MultiTexCoord1f( GLenum target, GLfloat x ) +{ + GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0; + DISPATCH_ATTR1F( attr, x ); +} + +static void GLAPIENTRY brw_MultiTexCoord1fv( GLenum target, + const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0; + DISPATCH_ATTR1FV( attr, v ); +} + +static void GLAPIENTRY brw_MultiTexCoord2f( GLenum target, GLfloat x, + GLfloat y ) +{ + GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0; + DISPATCH_ATTR2F( attr, x, y ); +} + +static void GLAPIENTRY brw_MultiTexCoord2fv( GLenum target, + const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0; + DISPATCH_ATTR2FV( attr, v ); +} + +static void GLAPIENTRY brw_MultiTexCoord3f( GLenum target, GLfloat x, + GLfloat y, GLfloat z) +{ + GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0; + DISPATCH_ATTR3F( attr, x, y, z ); +} + +static void GLAPIENTRY brw_MultiTexCoord3fv( GLenum target, + const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0; + DISPATCH_ATTR3FV( attr, v ); +} + +static void GLAPIENTRY brw_MultiTexCoord4f( GLenum target, GLfloat x, + GLfloat y, GLfloat z, + GLfloat w ) +{ + GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0; + DISPATCH_ATTR4F( attr, x, y, z, w ); +} + +static void GLAPIENTRY brw_MultiTexCoord4fv( GLenum target, + const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + BRW_ATTRIB_TEX0; + DISPATCH_ATTR4FV( attr, v ); +} + + +static void GLAPIENTRY brw_VertexAttrib1fNV( GLuint index, GLfloat x ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR1F( index, x ); +} + +static void GLAPIENTRY brw_VertexAttrib1fvNV( GLuint index, + const GLfloat *v ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR1FV( index, v ); +} + +static void GLAPIENTRY brw_VertexAttrib2fNV( GLuint index, GLfloat x, + GLfloat y ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR2F( index, x, y ); +} + +static void GLAPIENTRY brw_VertexAttrib2fvNV( GLuint index, + const GLfloat *v ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR2FV( index, v ); +} + +static void GLAPIENTRY brw_VertexAttrib3fNV( GLuint index, GLfloat x, + GLfloat y, GLfloat z ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR3F( index, x, y, z ); +} + +static void GLAPIENTRY brw_VertexAttrib3fvNV( GLuint index, + const GLfloat *v ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR3FV( index, v ); +} + +static void GLAPIENTRY brw_VertexAttrib4fNV( GLuint index, GLfloat x, + GLfloat y, GLfloat z, + GLfloat w ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR4F( index, x, y, z, w ); +} + +static void GLAPIENTRY brw_VertexAttrib4fvNV( GLuint index, + const GLfloat *v ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR4FV( index, v ); +} + + +/* + * XXX adjust index + */ + +static void GLAPIENTRY brw_VertexAttrib1fARB( GLuint index, GLfloat x ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR1F( index, x ); +} + +static void GLAPIENTRY brw_VertexAttrib1fvARB( GLuint index, + const GLfloat *v ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR1FV( index, v ); +} + +static void GLAPIENTRY brw_VertexAttrib2fARB( GLuint index, GLfloat x, + GLfloat y ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR2F( index, x, y ); +} + +static void GLAPIENTRY brw_VertexAttrib2fvARB( GLuint index, + const GLfloat *v ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR2FV( index, v ); +} + +static void GLAPIENTRY brw_VertexAttrib3fARB( GLuint index, GLfloat x, + GLfloat y, GLfloat z ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR3F( index, x, y, z ); +} + +static void GLAPIENTRY brw_VertexAttrib3fvARB( GLuint index, + const GLfloat *v ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR3FV( index, v ); +} + +static void GLAPIENTRY brw_VertexAttrib4fARB( GLuint index, GLfloat x, + GLfloat y, GLfloat z, + GLfloat w ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR4F( index, x, y, z, w ); +} + +static void GLAPIENTRY brw_VertexAttrib4fvARB( GLuint index, + const GLfloat *v ) +{ + if (index >= BRW_ATTRIB_FIRST_MATERIAL) index = ERROR_ATTRIB; + DISPATCH_ATTR4FV( index, v ); +} + + +/* Install the generic versions of the 2nd level dispatch + * functions. Some of these have a codegen alternative. + */ +void brw_exec_vtx_generic_init( struct brw_exec_context *exec ) +{ + GLvertexformat *vfmt = &exec->vtxfmt; + + vfmt->Color3f = brw_Color3f; + vfmt->Color3fv = brw_Color3fv; + vfmt->Color4f = brw_Color4f; + vfmt->Color4fv = brw_Color4fv; + vfmt->FogCoordfEXT = brw_FogCoordfEXT; + vfmt->FogCoordfvEXT = brw_FogCoordfvEXT; + vfmt->MultiTexCoord1fARB = brw_MultiTexCoord1f; + vfmt->MultiTexCoord1fvARB = brw_MultiTexCoord1fv; + vfmt->MultiTexCoord2fARB = brw_MultiTexCoord2f; + vfmt->MultiTexCoord2fvARB = brw_MultiTexCoord2fv; + vfmt->MultiTexCoord3fARB = brw_MultiTexCoord3f; + vfmt->MultiTexCoord3fvARB = brw_MultiTexCoord3fv; + vfmt->MultiTexCoord4fARB = brw_MultiTexCoord4f; + vfmt->MultiTexCoord4fvARB = brw_MultiTexCoord4fv; + vfmt->Normal3f = brw_Normal3f; + vfmt->Normal3fv = brw_Normal3fv; + vfmt->SecondaryColor3fEXT = brw_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = brw_SecondaryColor3fvEXT; + vfmt->TexCoord1f = brw_TexCoord1f; + vfmt->TexCoord1fv = brw_TexCoord1fv; + vfmt->TexCoord2f = brw_TexCoord2f; + vfmt->TexCoord2fv = brw_TexCoord2fv; + vfmt->TexCoord3f = brw_TexCoord3f; + vfmt->TexCoord3fv = brw_TexCoord3fv; + vfmt->TexCoord4f = brw_TexCoord4f; + vfmt->TexCoord4fv = brw_TexCoord4fv; + vfmt->Vertex2f = brw_Vertex2f; + vfmt->Vertex2fv = brw_Vertex2fv; + vfmt->Vertex3f = brw_Vertex3f; + vfmt->Vertex3fv = brw_Vertex3fv; + vfmt->Vertex4f = brw_Vertex4f; + vfmt->Vertex4fv = brw_Vertex4fv; + vfmt->VertexAttrib1fNV = brw_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = brw_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = brw_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = brw_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = brw_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = brw_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = brw_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = brw_VertexAttrib4fvNV; + vfmt->VertexAttrib1fARB = brw_VertexAttrib1fARB; + vfmt->VertexAttrib1fvARB = brw_VertexAttrib1fvARB; + vfmt->VertexAttrib2fARB = brw_VertexAttrib2fARB; + vfmt->VertexAttrib2fvARB = brw_VertexAttrib2fvARB; + vfmt->VertexAttrib3fARB = brw_VertexAttrib3fARB; + vfmt->VertexAttrib3fvARB = brw_VertexAttrib3fvARB; + vfmt->VertexAttrib4fARB = brw_VertexAttrib4fARB; + vfmt->VertexAttrib4fvARB = brw_VertexAttrib4fvARB; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/intel/intel_tex_layout.c b/dist/Mesa/src/mesa/drivers/dri/intel/intel_tex_layout.c new file mode 100644 index 000000000..fcb5cc390 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -0,0 +1,102 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Michel Dänzer <michel@tungstengraphics.com> + */ + +#include "intel_mipmap_tree.h" +#include "intel_tex_layout.h" +#include "macros.h" + + +static int align(int value, int alignment) +{ + return (value + alignment - 1) & ~(alignment - 1); +} + +void i945_miptree_layout_2d( struct intel_mipmap_tree *mt ) +{ + GLint align_h = 2, align_w = 4; + GLuint level; + GLuint x = 0; + GLuint y = 0; + GLuint width = mt->width0; + GLuint height = mt->height0; + + mt->pitch = mt->width0; + + /* May need to adjust pitch to accomodate the placement of + * the 2nd mipmap. This occurs when the alignment + * constraints of mipmap placement push the right edge of the + * 2nd mipmap out past the width of its parent. + */ + if (mt->first_level != mt->last_level) { + GLuint mip1_width = align(minify(mt->width0), align_w) + + minify(minify(mt->width0)); + + if (mip1_width > mt->width0) + mt->pitch = mip1_width; + } + + /* Pitch must be a whole number of dwords, even though we + * express it in texels. + */ + mt->pitch = align(mt->pitch * mt->cpp, 4) / mt->cpp; + mt->total_height = 0; + + for ( level = mt->first_level ; level <= mt->last_level ; level++ ) { + GLuint img_height; + + intel_miptree_set_level_info(mt, level, 1, x, y, width, + height, 1); + + if (mt->compressed) + img_height = MAX2(1, height/4); + else + img_height = align(height, align_h); + + + /* Because the images are packed better, the final offset + * might not be the maximal one: + */ + mt->total_height = MAX2(mt->total_height, y + img_height); + + /* Layout_below: step right after second mipmap. + */ + if (level == mt->first_level + 1) { + x += align(width, align_w); + } + else { + y += img_height; + } + + width = minify(width); + height = minify(height); + } +} diff --git a/dist/Mesa/src/mesa/drivers/dri/intel/intel_tex_layout.h b/dist/Mesa/src/mesa/drivers/dri/intel/intel_tex_layout.h new file mode 100644 index 000000000..1e37f8f52 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/intel/intel_tex_layout.h @@ -0,0 +1,41 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Michel Dänzer <michel@tungstengraphics.com> + */ + +#include "macros.h" + + +static GLuint minify( GLuint d ) +{ + return MAX2(1, d>>1); +} + +extern void i945_miptree_layout_2d( struct intel_mipmap_tree *mt ); diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/Makefile b/dist/Mesa/src/mesa/drivers/dri/nouveau/Makefile new file mode 100644 index 000000000..20d2de5ee --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/Makefile @@ -0,0 +1,53 @@ +# src/mesa/drivers/dri/nouveau/Makefile + +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = nouveau_dri.so + +MINIGLX_SOURCES = + +DRIVER_SOURCES = \ + nouveau_bufferobj.c \ + nouveau_buffers.c \ + nouveau_card.c \ + nouveau_context.c \ + nouveau_driver.c \ + nouveau_fifo.c \ + nouveau_lock.c \ + nouveau_object.c \ + nouveau_screen.c \ + nouveau_span.c \ + nouveau_state.c \ + nouveau_state_cache.c \ + nouveau_shader.c \ + nouveau_shader_0.c \ + nouveau_shader_1.c \ + nouveau_shader_2.c \ + nouveau_tex.c \ + nouveau_swtcl.c \ + nouveau_sync.c \ + nouveau_query.c \ + nv04_state.c \ + nv04_swtcl.c \ + nv10_state.c \ + nv10_swtcl.c \ + nv20_state.c \ + nv20_vertprog.c \ + nv30_state.c \ + nv30_fragprog.c \ + nv30_vertprog.c \ + nv40_fragprog.c \ + nv40_vertprog.c \ + nv50_state.c + +C_SOURCES = \ + $(COMMON_SOURCES) \ + $(DRIVER_SOURCES) + +ASM_SOURCES = + + +include ../Makefile.template + +symlinks: diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c new file mode 100644 index 000000000..684ed7b01 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c @@ -0,0 +1,616 @@ +#include "bufferobj.h" +#include "enums.h" + +#include "nouveau_bufferobj.h" +#include "nouveau_buffers.h" +#include "nouveau_context.h" +#include "nouveau_drm.h" +#include "nouveau_object.h" +#include "nouveau_msg.h" + +#define NOUVEAU_MEM_FREE(mem) do { \ + nouveau_mem_free(ctx, (mem)); \ + (mem) = NULL; \ +} while(0) + +#define DEBUG(fmt,args...) do { \ + if (NOUVEAU_DEBUG & DEBUG_BUFFEROBJ) { \ + fprintf(stderr, "%s: "fmt, __func__, ##args); \ + } \ +} while(0) + +static GLboolean +nouveau_bo_download_from_screen(GLcontext *ctx, GLuint offset, GLuint size, + struct gl_buffer_object *bo) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + nouveau_mem *in_mem; + + DEBUG("bo=%p, offset=%d, size=%d\n", bo, offset, size); + + /* If there's a permanent backing store, blit directly into it */ + if (nbo->cpu_mem) { + if (nbo->cpu_mem != nbo->gpu_mem) { + DEBUG("..cpu_mem\n"); + nouveau_memformat_flat_emit(ctx, nbo->cpu_mem, + nbo->gpu_mem, + offset, offset, size); + } + } else { + DEBUG("..sys_mem\n"); + in_mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_AGP, size, 0); + if (in_mem) { + DEBUG("....via AGP\n"); + /* otherwise, try blitting to faster memory and + * copying from there + */ + nouveau_memformat_flat_emit(ctx, in_mem, nbo->gpu_mem, + 0, offset, size); + nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier, + NvSubMemFormat); + _mesa_memcpy(nbo->cpu_mem_sys + offset, + in_mem->map, size); + NOUVEAU_MEM_FREE(in_mem); + } else { + DEBUG("....direct VRAM copy\n"); + /* worst case, copy directly from vram */ + _mesa_memcpy(nbo->cpu_mem_sys + offset, + nbo->gpu_mem + offset, + size); + } + } + + return GL_TRUE; +} + +static GLboolean +nouveau_bo_upload_to_screen(GLcontext *ctx, GLuint offset, GLuint size, + struct gl_buffer_object *bo) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + nouveau_mem *out_mem; + + DEBUG("bo=%p, offset=%d, size=%d\n", bo, offset, size); + + if (nbo->cpu_mem) { + if (nbo->cpu_mem != nbo->gpu_mem) { + DEBUG("..cpu_mem\n"); + nouveau_memformat_flat_emit(ctx, nbo->gpu_mem, + nbo->cpu_mem, + offset, offset, size); + } + } else { + out_mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_AGP | + NOUVEAU_MEM_MAPPED, + size, 0); + if (out_mem) { + DEBUG("....via AGP\n"); + _mesa_memcpy(out_mem->map, + nbo->cpu_mem_sys + offset, size); + nouveau_memformat_flat_emit(ctx, nbo->gpu_mem, out_mem, + offset, 0, size); + nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier, + NvSubMemFormat); + NOUVEAU_MEM_FREE(out_mem); + } else { + DEBUG("....direct VRAM copy\n"); + _mesa_memcpy(nbo->gpu_mem->map + offset, + nbo->cpu_mem_sys + offset, + size); + } + } + + return GL_TRUE; +} + +GLboolean +nouveau_bo_move_in(GLcontext *ctx, struct gl_buffer_object *bo) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + + DEBUG("bo=%p\n", bo); + + if (bo->OnCard) + return GL_TRUE; + assert(nbo->gpu_mem_flags); + + nbo->gpu_mem = nouveau_mem_alloc(ctx, nbo->gpu_mem_flags | + NOUVEAU_MEM_MAPPED, + bo->Size, 0); + assert(nbo->gpu_mem); + + if (nbo->cpu_mem_flags) { + if ((nbo->cpu_mem_flags|NOUVEAU_MEM_MAPPED) != nbo->gpu_mem->type) { + DEBUG("..need cpu_mem buffer\n"); + + nbo->cpu_mem = nouveau_mem_alloc(ctx, + nbo->cpu_mem_flags | + NOUVEAU_MEM_MAPPED, + bo->Size, 0); + + if (nbo->cpu_mem) { + DEBUG("....alloc ok, kill sys_mem buffer\n"); + _mesa_memcpy(nbo->cpu_mem->map, + nbo->cpu_mem_sys, bo->Size); + FREE(nbo->cpu_mem_sys); + } + } else { + DEBUG("..cpu direct access to GPU buffer\n"); + nbo->cpu_mem = nbo->gpu_mem; + } + } + nouveau_bo_upload_to_screen(ctx, 0, bo->Size, bo); + + bo->OnCard = GL_TRUE; + return GL_TRUE; +} + +GLboolean +nouveau_bo_move_out(GLcontext *ctx, struct gl_buffer_object *bo) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + GLuint nr_dirty; + + DEBUG("bo=%p\n", bo); + if (!bo->OnCard) + return GL_TRUE; + + nr_dirty = nouveau_bo_download_dirty(ctx, bo); + if (nbo->cpu_mem) { + if (nr_dirty && nbo->cpu_mem != nbo->gpu_mem) + nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier, + NvSubMemFormat); + DEBUG("..destroy cpu_mem buffer\n"); + nbo->cpu_mem_sys = malloc(bo->Size); + assert(nbo->cpu_mem_sys); + _mesa_memcpy(nbo->cpu_mem_sys, nbo->cpu_mem->map, bo->Size); + if (nbo->cpu_mem == nbo->gpu_mem) + nbo->cpu_mem = NULL; + else + NOUVEAU_MEM_FREE(nbo->cpu_mem); + } + NOUVEAU_MEM_FREE(nbo->gpu_mem); + + bo->OnCard = GL_FALSE; + return GL_TRUE; +} + +static void +nouveau_bo_choose_storage_method(GLcontext *ctx, GLenum usage, + struct gl_buffer_object *bo) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + GLuint gpu_type = 0; + GLuint cpu_type = 0; + + switch (usage) { + /* Client source, changes often, used by GL many times */ + case GL_DYNAMIC_DRAW_ARB: + gpu_type = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE; + cpu_type = NOUVEAU_MEM_AGP; + break; + /* GL source, changes often, client reads many times */ + case GL_DYNAMIC_READ_ARB: + /* Client source, specified once, used by GL many times */ + case GL_STATIC_DRAW_ARB: + /* GL source, specified once, client reads many times */ + case GL_STATIC_READ_ARB: + /* Client source, specified once, used by GL a few times */ + case GL_STREAM_DRAW_ARB: + /* GL source, specified once, client reads a few times */ + case GL_STREAM_READ_ARB: + /* GL source, changes often, used by GL many times*/ + case GL_DYNAMIC_COPY_ARB: + /* GL source, specified once, used by GL many times */ + case GL_STATIC_COPY_ARB: + /* GL source, specified once, used by GL a few times */ + case GL_STREAM_COPY_ARB: + gpu_type = NOUVEAU_MEM_FB; + break; + default: + assert(0); + } + + nbo->gpu_mem_flags = gpu_type; + nbo->cpu_mem_flags = cpu_type; + nbo->usage = usage; +} + +void +nouveau_bo_init_storage(GLcontext *ctx, GLuint valid_gpu_access, + GLsizeiptrARB size, + const GLvoid *data, + GLenum usage, + struct gl_buffer_object *bo) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + + DEBUG("bo=%p\n", bo); + + /* Free up previous buffers if we can't reuse them */ + if (nbo->usage != usage || + (nbo->gpu_mem && (nbo->gpu_mem->size != size))) { + if (nbo->cpu_mem_sys) + FREE(nbo->cpu_mem_sys); + if (nbo->cpu_mem) { + if (nbo->cpu_mem != nbo->gpu_mem) + NOUVEAU_MEM_FREE(nbo->cpu_mem); + else + nbo->cpu_mem = NULL; + } + if (nbo->gpu_mem) + NOUVEAU_MEM_FREE(nbo->gpu_mem); + + bo->OnCard = GL_FALSE; + nbo->cpu_mem_sys = calloc(1, size); + } + + nouveau_bo_choose_storage_method(ctx, usage, bo); + /* Force off flags that may not be ok for a given buffer */ + nbo->gpu_mem_flags &= valid_gpu_access; + + bo->Usage = usage; + bo->Size = size; + + if (data) { + GLvoid *map = nouveau_bo_map(ctx, GL_WRITE_ONLY_ARB, bo); + _mesa_memcpy(map, data, size); + nouveau_bo_dirty_all(ctx, GL_FALSE, bo); + nouveau_bo_unmap(ctx, bo); + } +} + +void * +nouveau_bo_map(GLcontext *ctx, GLenum access, struct gl_buffer_object *bo) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + + DEBUG("bo=%p, access=%s\n", bo, _mesa_lookup_enum_by_nr(access)); + + if (bo->OnCard && + (access == GL_READ_ONLY_ARB || access == GL_READ_WRITE_ARB)) { + GLuint nr_dirty; + + DEBUG("..on card\n"); + nr_dirty = nouveau_bo_download_dirty(ctx, bo); + + /* nouveau_bo_download_dirty won't wait unless it needs to + * free a temp buffer, which isn't the case if cpu_mem is + * present. + */ + if (nr_dirty && nbo->cpu_mem && nbo->cpu_mem != nbo->gpu_mem) + nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier, + NvSubMemFormat); + } + + if (nbo->cpu_mem) { + DEBUG("..access via cpu_mem\n"); + return nbo->cpu_mem->map; + } else { + DEBUG("..access via cpu_mem_sys\n"); + return nbo->cpu_mem_sys; + } +} + +void +nouveau_bo_unmap(GLcontext *ctx, struct gl_buffer_object *bo) +{ + DEBUG("unmap bo=%p\n", bo); +} + +uint32_t +nouveau_bo_gpu_ref(GLcontext *ctx, struct gl_buffer_object *bo) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + + assert(nbo->mapped == GL_FALSE); + + DEBUG("gpu_ref\n"); + + if (!bo->OnCard) { + nouveau_bo_move_in(ctx, bo); + bo->OnCard = GL_TRUE; + } + nouveau_bo_upload_dirty(ctx, bo); + + return nouveau_mem_gpu_offset_get(ctx, nbo->gpu_mem); +} + +void +nouveau_bo_dirty_linear(GLcontext *ctx, GLboolean on_card, + uint32_t offset, uint32_t size, + struct gl_buffer_object *bo) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + nouveau_bufferobj_dirty *dirty; + uint32_t start = offset; + uint32_t end = offset + size; + int i; + + if (nbo->cpu_mem == nbo->gpu_mem) + return; + + dirty = on_card ? &nbo->gpu_dirty : &nbo->cpu_dirty; + + DEBUG("on_card=%d, offset=%d, size=%d, bo=%p\n", + on_card, offset, size, bo); + + for (i=0; i<dirty->nr_dirty; i++) { + nouveau_bufferobj_region *r = &dirty->dirty[i]; + + /* already dirty */ + if (start >= r->start && end <= r->end) { + DEBUG("..already dirty\n"); + return; + } + + /* add to the end of a region */ + if (start >= r->start && start <= r->end) { + if (end > r->end) { + DEBUG("..extend end of region\n"); + r->end = end; + return; + } + } + + /* add to the start of a region */ + if (start < r->start && end >= r->end) { + DEBUG("..extend start of region\n"); + r->start = start; + /* .. and to the end */ + if (end > r->end) { + DEBUG("....and end\n"); + r->end = end; + } + return; + } + } + + /* new region */ + DEBUG("..new dirty\n"); + dirty->nr_dirty++; + dirty->dirty = realloc(dirty->dirty, + sizeof(nouveau_bufferobj_region) * + dirty->nr_dirty); + dirty->dirty[dirty->nr_dirty - 1].start = start; + dirty->dirty[dirty->nr_dirty - 1].end = end; +} + +void +nouveau_bo_dirty_all(GLcontext *ctx, GLboolean on_card, + struct gl_buffer_object *bo) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + nouveau_bufferobj_dirty *dirty; + + dirty = on_card ? &nbo->gpu_dirty : &nbo->cpu_dirty; + + DEBUG("dirty all\n"); + if (dirty->nr_dirty) { + FREE(dirty->dirty); + dirty->dirty = NULL; + dirty->nr_dirty = 0; + } + + nouveau_bo_dirty_linear(ctx, on_card, 0, bo->Size, bo); +} + +GLuint +nouveau_bo_upload_dirty(GLcontext *ctx, struct gl_buffer_object *bo) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + nouveau_bufferobj_dirty *dirty = &nbo->cpu_dirty; + GLuint nr_dirty; + int i; + + nr_dirty = dirty->nr_dirty; + if (!nr_dirty) { + DEBUG("clean\n"); + return nr_dirty; + } + + for (i=0; i<nr_dirty; i++) { + nouveau_bufferobj_region *r = &dirty->dirty[i]; + + DEBUG("dirty %d: o=0x%08x, s=0x%08x\n", + i, r->start, r->end - r->start); + nouveau_bo_upload_to_screen(ctx, + r->start, r->end - r->start, bo); + } + + FREE(dirty->dirty); + dirty->dirty = NULL; + dirty->nr_dirty = 0; + + return nr_dirty; +} + +GLuint +nouveau_bo_download_dirty(GLcontext *ctx, struct gl_buffer_object *bo) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; + nouveau_bufferobj_dirty *dirty = &nbo->gpu_dirty; + GLuint nr_dirty; + int i; + + nr_dirty = dirty->nr_dirty; + if (nr_dirty) { + DEBUG("clean\n"); + return nr_dirty; + } + + for (i=0; i<nr_dirty; i++) { + nouveau_bufferobj_region *r = &dirty->dirty[i]; + + DEBUG("dirty %d: o=0x%08x, s=0x%08x\n", + i, r->start, r->end - r->start); + nouveau_bo_download_from_screen(ctx, + r->start, + r->end - r->start, bo); + } + + FREE(dirty->dirty); + dirty->dirty = NULL; + dirty->nr_dirty = 0; + + return nr_dirty; +} + +static void +nouveauBindBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj) +{ +} + +static struct gl_buffer_object * +nouveauNewBufferObject(GLcontext *ctx, GLuint buffer, GLenum target) +{ + nouveau_buffer_object *nbo; + + nbo = CALLOC_STRUCT(nouveau_buffer_object_t); + if (nbo) + _mesa_initialize_buffer_object(&nbo->mesa, buffer, target); + DEBUG("bo=%p\n", nbo); + + return nbo ? &nbo->mesa : NULL; +} + +static void +nouveauDeleteBuffer(GLcontext *ctx, struct gl_buffer_object *obj) +{ + nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj; + + if (nbo->gpu_dirty.nr_dirty) + FREE(nbo->gpu_dirty.dirty); + if (nbo->cpu_dirty.nr_dirty) + FREE(nbo->cpu_dirty.dirty); + if (nbo->cpu_mem) nouveau_mem_free(ctx, nbo->cpu_mem); + if (nbo->gpu_mem) nouveau_mem_free(ctx, nbo->gpu_mem); + + _mesa_delete_buffer_object(ctx, obj); +} + +static void +nouveauBufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size, + const GLvoid *data, GLenum usage, + struct gl_buffer_object *obj) +{ + GLuint gpu_flags; + + DEBUG("target=%s, size=%d, data=%p, usage=%s, obj=%p\n", + _mesa_lookup_enum_by_nr(target), + (GLuint)size, data, + _mesa_lookup_enum_by_nr(usage), + obj); + + switch (target) { + case GL_ELEMENT_ARRAY_BUFFER_ARB: + gpu_flags = 0; + break; + default: + gpu_flags = NOUVEAU_BO_VRAM_OK | NOUVEAU_BO_AGP_OK; + break; + } + nouveau_bo_init_storage(ctx, gpu_flags, size, data, usage, obj); +} + +static void +nouveauBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset, + GLsizeiptrARB size, const GLvoid *data, + struct gl_buffer_object *obj) +{ + GLvoid *out; + + DEBUG("target=%s, offset=0x%x, size=%d, data=%p, obj=%p\n", + _mesa_lookup_enum_by_nr(target), + (GLuint)offset, (GLuint)size, data, obj); + + out = nouveau_bo_map(ctx, GL_WRITE_ONLY_ARB, obj); + _mesa_memcpy(out + offset, data, size); + nouveau_bo_dirty_linear(ctx, GL_FALSE, offset, size, obj); + nouveau_bo_unmap(ctx, obj); +} + +static void +nouveauGetBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset, + GLsizeiptrARB size, GLvoid *data, + struct gl_buffer_object *obj) +{ + const GLvoid *in; + + DEBUG("target=%s, offset=0x%x, size=%d, data=%p, obj=%p\n", + _mesa_lookup_enum_by_nr(target), + (GLuint)offset, (GLuint)size, data, obj); + + in = nouveau_bo_map(ctx, GL_READ_ONLY_ARB, obj); + _mesa_memcpy(data, in + offset, size); + nouveau_bo_unmap(ctx, obj); +} + +static void * +nouveauMapBuffer(GLcontext *ctx, GLenum target, GLenum access, + struct gl_buffer_object *obj) +{ + DEBUG("target=%s, access=%s, obj=%p\n", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(access), + obj + ); + + /* Already mapped.. */ + if (obj->Pointer) + return NULL; + + /* Have to pass READ_WRITE here, nouveau_bo_map will only ensure that + * the cpu_mem buffer is up-to-date if we ask for read access. + * + * However, even if the client only asks for write access, we're still + * forced to reupload the entire buffer. So, we need the cpu_mem buffer + * to have the correct data all the time. + */ + obj->Pointer = nouveau_bo_map(ctx, GL_READ_WRITE_ARB, obj); + + /* The GL spec says that a client attempting to write to a bufferobj + * mapped READ_ONLY object may have unpredictable results, possibly + * even program termination. + * + * We're going to use this, and only mark the buffer as dirtied if + * the client asks for write access. + */ + if (target != GL_READ_ONLY_ARB) { + /* We have no way of knowing what was modified by the client, + * so the entire buffer gets dirtied. */ + nouveau_bo_dirty_all(ctx, GL_FALSE, obj); + } + + return obj->Pointer; +} + +static GLboolean +nouveauUnmapBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj) +{ + DEBUG("target=%s, obj=%p\n", _mesa_lookup_enum_by_nr(target), obj); + + assert(obj->Pointer); + + nouveau_bo_unmap(ctx, obj); + obj->Pointer = NULL; + return GL_TRUE; +} + +void +nouveauInitBufferObjects(GLcontext *ctx) +{ + ctx->Driver.BindBuffer = nouveauBindBuffer; + ctx->Driver.NewBufferObject = nouveauNewBufferObject; + ctx->Driver.DeleteBuffer = nouveauDeleteBuffer; + ctx->Driver.BufferData = nouveauBufferData; + ctx->Driver.BufferSubData = nouveauBufferSubData; + ctx->Driver.GetBufferSubData = nouveauGetBufferSubData; + ctx->Driver.MapBuffer = nouveauMapBuffer; + ctx->Driver.UnmapBuffer = nouveauUnmapBuffer; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h new file mode 100644 index 000000000..932450fd8 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h @@ -0,0 +1,77 @@ +#ifndef __NOUVEAU_BUFFEROBJ_H__ +#define __NOUVEAU_BUFFEROBJ_H__ + +#include "mtypes.h" +#include "nouveau_buffers.h" + +#define NOUVEAU_BO_VRAM_OK (NOUVEAU_MEM_FB | NOUVEAU_MEM_FB_ACCEPTABLE) +#define NOUVEAU_BO_AGP_OK (NOUVEAU_MEM_AGP | NOUVEAU_MEM_AGP_ACCEPTABLE) + +typedef struct nouveau_bufferobj_region_t { + uint32_t start; + uint32_t end; +} nouveau_bufferobj_region; + +typedef struct nouveau_bufferobj_dirty_t { + nouveau_bufferobj_region *dirty; + int nr_dirty; +} nouveau_bufferobj_dirty; + +typedef struct nouveau_buffer_object_t { + /* Base class, must be first */ + struct gl_buffer_object mesa; + + GLboolean mapped; + GLenum usage; + + /* Memory used for GPU access to the buffer*/ + GLuint gpu_mem_flags; + nouveau_mem * gpu_mem; + nouveau_bufferobj_dirty gpu_dirty; + + /* Memory used for CPU access to the buffer */ + GLuint cpu_mem_flags; + nouveau_mem * cpu_mem; + GLvoid * cpu_mem_sys; + nouveau_bufferobj_dirty cpu_dirty; +} nouveau_buffer_object; + +extern void +nouveau_bo_init_storage(GLcontext *ctx, GLuint valid_gpu_access, + GLsizeiptrARB size, const GLvoid *data, GLenum usage, + struct gl_buffer_object *bo); + +extern GLboolean +nouveau_bo_move_in(GLcontext *ctx, struct gl_buffer_object *bo); + +extern GLboolean +nouveau_bo_move_out(GLcontext *ctx, struct gl_buffer_object *bo); + +extern void * +nouveau_bo_map(GLcontext *ctx, GLenum usage, struct gl_buffer_object *bo); + +extern void +nouveau_bo_unmap(GLcontext *ctx, struct gl_buffer_object *bo); + +extern uint32_t +nouveau_bo_gpu_ref(GLcontext *ctx, struct gl_buffer_object *bo); + +extern void +nouveau_bo_dirty_linear(GLcontext *ctx, GLboolean on_card, + uint32_t offset, uint32_t size, + struct gl_buffer_object *bo); + +extern void +nouveau_bo_dirty_all(GLcontext *ctx, GLboolean on_card, + struct gl_buffer_object *bo); + +extern GLuint +nouveau_bo_upload_dirty(GLcontext *ctx, struct gl_buffer_object *bo); + +extern GLuint +nouveau_bo_download_dirty(GLcontext *ctx, struct gl_buffer_object *bo); + +extern void +nouveauInitBufferObjects(GLcontext *ctx); + +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_buffers.c new file mode 100644 index 000000000..b54f68f40 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_buffers.c @@ -0,0 +1,434 @@ +#include "utils.h" +#include "framebuffer.h" +#include "renderbuffer.h" +#include "fbobject.h" + +#include "nouveau_context.h" +#include "nouveau_buffers.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" +#include "nouveau_msg.h" + +#define MAX_MEMFMT_LENGTH 32768 + +/* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */ +GLboolean +nouveau_memformat_flat_emit(GLcontext *ctx, + nouveau_mem *dst, nouveau_mem *src, + GLuint dst_offset, GLuint src_offset, + GLuint size) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + uint32_t src_handle, dst_handle; + GLuint count; + + if (src_offset + size > src->size) { + MESSAGE("src out of nouveau_mem bounds\n"); + return GL_FALSE; + } + if (dst_offset + size > dst->size) { + MESSAGE("dst out of nouveau_mem bounds\n"); + return GL_FALSE; + } + + src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP; + dst_handle = (dst->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP; + src_offset += nouveau_mem_gpu_offset_get(ctx, src); + dst_offset += nouveau_mem_gpu_offset_get(ctx, dst); + + BEGIN_RING_SIZE(NvSubMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2); + OUT_RING (src_handle); + OUT_RING (dst_handle); + + count = (size / MAX_MEMFMT_LENGTH) + ((size % MAX_MEMFMT_LENGTH) ? 1 : 0); + + while (count--) { + GLuint length = (size > MAX_MEMFMT_LENGTH) ? MAX_MEMFMT_LENGTH : size; + + BEGIN_RING_SIZE(NvSubMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + OUT_RING (src_offset); + OUT_RING (dst_offset); + OUT_RING (0); /* pitch in */ + OUT_RING (0); /* pitch out */ + OUT_RING (length); /* line length */ + OUT_RING (1); /* number of lines */ + OUT_RING ((1 << 8) /* dst_inc */ | (1 << 0) /* src_inc */); + OUT_RING (0); /* buffer notify? */ + FIRE_RING(); + + src_offset += length; + dst_offset += length; + size -= length; + } + + return GL_TRUE; +} + +void +nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + drm_nouveau_mem_free_t memf; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, "%s: type=0x%x, offset=0x%x, size=0x%x\n", + __func__, mem->type, (GLuint)mem->offset, (GLuint)mem->size); + } + + if (mem->map) + drmUnmap(mem->map, mem->size); + memf.flags = mem->type; + memf.region_offset = mem->offset; + drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf, sizeof(memf)); + FREE(mem); +} + +nouveau_mem * +nouveau_mem_alloc(GLcontext *ctx, int type, GLuint size, GLuint align) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + drm_nouveau_mem_alloc_t mema; + nouveau_mem *mem; + int ret; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, "%s: requested: type=0x%x, size=0x%x, align=0x%x\n", + __func__, type, (GLuint)size, align); + } + + mem = CALLOC(sizeof(nouveau_mem)); + if (!mem) + return NULL; + + mema.flags = type; + mema.size = mem->size = size; + mema.alignment = align; + mem->map = NULL; + ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC, + &mema, sizeof(mema)); + if (ret) { + FREE(mem); + return NULL; + } + mem->offset = mema.region_offset; + mem->type = mema.flags; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n", + __func__, mem->type, (GLuint)mem->offset, (GLuint)mem->size); + } + + if (type & NOUVEAU_MEM_MAPPED) + ret = drmMap(nmesa->driFd, mem->offset, mem->size, &mem->map); + if (ret) { + mem->map = NULL; + nouveau_mem_free(ctx, mem); + mem = NULL; + } + + return mem; +} + +uint32_t +nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (mem->type & NOUVEAU_MEM_FB) + return (uint32_t)mem->offset - nmesa->vram_phys; + else if (mem->type & NOUVEAU_MEM_AGP) + return (uint32_t)mem->offset - nmesa->agp_phys; + else + return 0xDEADF00D; +} + +static GLboolean +nouveau_renderbuffer_pixelformat(nouveau_renderbuffer *nrb, + GLenum internalFormat) +{ + nrb->mesa.InternalFormat = internalFormat; + + /*TODO: We probably want to extend this a bit, and maybe make + * card-specific? + */ + switch (internalFormat) { + case GL_RGBA: + case GL_RGBA8: + nrb->mesa._BaseFormat = GL_RGBA; + nrb->mesa._ActualFormat= GL_RGBA8; + nrb->mesa.DataType = GL_UNSIGNED_BYTE; + nrb->mesa.RedBits = 8; + nrb->mesa.GreenBits = 8; + nrb->mesa.BlueBits = 8; + nrb->mesa.AlphaBits = 8; + nrb->cpp = 4; + break; + case GL_RGB: + case GL_RGB5: + nrb->mesa._BaseFormat = GL_RGB; + nrb->mesa._ActualFormat= GL_RGB5; + nrb->mesa.DataType = GL_UNSIGNED_BYTE; + nrb->mesa.RedBits = 5; + nrb->mesa.GreenBits = 6; + nrb->mesa.BlueBits = 5; + nrb->mesa.AlphaBits = 0; + nrb->cpp = 2; + break; + case GL_DEPTH_COMPONENT16: + nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT; + nrb->mesa._ActualFormat= GL_DEPTH_COMPONENT16; + nrb->mesa.DataType = GL_UNSIGNED_SHORT; + nrb->mesa.DepthBits = 16; + nrb->cpp = 2; + break; + case GL_DEPTH_COMPONENT24: + nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT; + nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT; + nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; + nrb->mesa.DepthBits = 24; + nrb->cpp = 4; + break; + case GL_STENCIL_INDEX8_EXT: + nrb->mesa._BaseFormat = GL_STENCIL_INDEX; + nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT; + nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; + nrb->mesa.StencilBits = 8; + nrb->cpp = 4; + break; + case GL_DEPTH24_STENCIL8_EXT: + nrb->mesa._BaseFormat = GL_DEPTH_STENCIL_EXT; + nrb->mesa._ActualFormat= GL_DEPTH24_STENCIL8_EXT; + nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; + nrb->mesa.DepthBits = 24; + nrb->mesa.StencilBits = 8; + nrb->cpp = 4; + break; + default: + return GL_FALSE; + break; + } + + return GL_TRUE; +} + +static GLboolean +nouveau_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, + GLuint height) +{ + nouveau_renderbuffer *nrb = (nouveau_renderbuffer*)rb; + + if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) { + fprintf(stderr, "%s: unknown internalFormat\n", __func__); + return GL_FALSE; + } + + /* If this buffer isn't statically alloc'd, we may need to ask the + * drm for more memory */ + if (!nrb->dPriv && (rb->Width != width || rb->Height != height)) { + GLuint pitch; + + /* align pitches to 64 bytes */ + pitch = ((width * nrb->cpp) + 63) & ~63; + + if (nrb->mem) + nouveau_mem_free(ctx, nrb->mem); + nrb->mem = nouveau_mem_alloc(ctx, + NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED, + pitch*height, + 0); + if (!nrb->mem) + return GL_FALSE; + + /* update nouveau_renderbuffer info */ + nrb->offset = nouveau_mem_gpu_offset_get(ctx, nrb->mem); + nrb->pitch = pitch; + } + + rb->Width = width; + rb->Height = height; + rb->InternalFormat = internalFormat; + return GL_TRUE; +} + +static void +nouveau_renderbuffer_delete(struct gl_renderbuffer *rb) +{ + GET_CURRENT_CONTEXT(ctx); + nouveau_renderbuffer *nrb = (nouveau_renderbuffer*)rb; + + if (nrb->mem) + nouveau_mem_free(ctx, nrb->mem); + FREE(nrb); +} + +nouveau_renderbuffer * +nouveau_renderbuffer_new(GLenum internalFormat, GLvoid *map, + GLuint offset, GLuint pitch, + __DRIdrawablePrivate *dPriv) +{ + nouveau_renderbuffer *nrb; + + nrb = CALLOC_STRUCT(nouveau_renderbuffer_t); + if (nrb) { + _mesa_init_renderbuffer(&nrb->mesa, 0); + + nouveau_renderbuffer_pixelformat(nrb, internalFormat); + + nrb->mesa.AllocStorage = nouveau_renderbuffer_storage; + nrb->mesa.Delete = nouveau_renderbuffer_delete; + + nrb->dPriv = dPriv; + nrb->offset = offset; + nrb->pitch = pitch; + nrb->map = map; + } + + return nrb; +} + +static void +nouveau_cliprects_drawable_set(nouveauContextPtr nmesa, + nouveau_renderbuffer *nrb) +{ + __DRIdrawablePrivate *dPriv = nrb->dPriv; + + nmesa->numClipRects = dPriv->numClipRects; + nmesa->pClipRects = dPriv->pClipRects; + nmesa->drawX = dPriv->x; + nmesa->drawY = dPriv->y; +} + +static void +nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa, + nouveau_renderbuffer *nrb) +{ + nmesa->numClipRects = 1; + nmesa->pClipRects = &nmesa->osClipRect; + nmesa->osClipRect.x1 = 0; + nmesa->osClipRect.y1 = 0; + nmesa->osClipRect.x2 = nrb->mesa.Width; + nmesa->osClipRect.y2 = nrb->mesa.Height; + nmesa->drawX = 0; + nmesa->drawY = 0; +} + +void +nouveau_window_moved(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_renderbuffer *nrb; + + nrb = (nouveau_renderbuffer *)ctx->DrawBuffer->_ColorDrawBuffers[0][0]; + if (!nrb) + return; + + if (!nrb->dPriv) + nouveau_cliprects_renderbuffer_set(nmesa, nrb); + else + nouveau_cliprects_drawable_set(nmesa, nrb); + + /* Viewport depends on window size/position, nouveauCalcViewport + * will take care of calling the hw-specific WindowMoved + */ + ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, + ctx->Viewport.Width, ctx->Viewport.Height); + /* Scissor depends on window position */ + ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); +} + +GLboolean +nouveau_build_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_renderbuffer *color[MAX_DRAW_BUFFERS]; + nouveau_renderbuffer *depth; + + _mesa_update_framebuffer(ctx); + _mesa_update_draw_buffer_bounds(ctx); + + color[0] = (nouveau_renderbuffer *)fb->_ColorDrawBuffers[0][0]; + if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) + depth = (nouveau_renderbuffer *)fb->_DepthBuffer->Wrapped; + else + depth = (nouveau_renderbuffer *)fb->_DepthBuffer; + + if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth)) + return GL_FALSE; + nouveau_window_moved(ctx); + + return GL_TRUE; +} + +static void +nouveauDrawBuffer(GLcontext *ctx, GLenum buffer) +{ + nouveau_build_framebuffer(ctx, ctx->DrawBuffer); +} + +static struct gl_framebuffer * +nouveauNewFramebuffer(GLcontext *ctx, GLuint name) +{ + return _mesa_new_framebuffer(ctx, name); +} + +static struct gl_renderbuffer * +nouveauNewRenderbuffer(GLcontext *ctx, GLuint name) +{ + nouveau_renderbuffer *nrb; + + nrb = CALLOC_STRUCT(nouveau_renderbuffer_t); + if (nrb) { + _mesa_init_renderbuffer(&nrb->mesa, name); + + nrb->mesa.AllocStorage = nouveau_renderbuffer_storage; + nrb->mesa.Delete = nouveau_renderbuffer_delete; + } + return &nrb->mesa; +} + +static void +nouveauBindFramebuffer(GLcontext *ctx, GLenum target, struct gl_framebuffer *fb) +{ + nouveau_build_framebuffer(ctx, fb); +} + +static void +nouveauFramebufferRenderbuffer(GLcontext *ctx, + struct gl_framebuffer *fb, + GLenum attachment, + struct gl_renderbuffer *rb) +{ + _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); + nouveau_build_framebuffer(ctx, fb); +} + +static void +nouveauRenderTexture(GLcontext *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att) +{ +} + +static void +nouveauFinishRenderTexture(GLcontext *ctx, + struct gl_renderbuffer_attachment *att) +{ +} + +void +nouveauInitBufferFuncs(struct dd_function_table *func) +{ + func->DrawBuffer = nouveauDrawBuffer; + + func->NewFramebuffer = nouveauNewFramebuffer; + func->NewRenderbuffer = nouveauNewRenderbuffer; + func->BindFramebuffer = nouveauBindFramebuffer; + func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer; + func->RenderTexture = nouveauRenderTexture; + func->FinishRenderTexture = nouveauFinishRenderTexture; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_buffers.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_buffers.h new file mode 100644 index 000000000..d86455184 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_buffers.h @@ -0,0 +1,48 @@ +#ifndef __NOUVEAU_BUFFERS_H__ +#define __NOUVEAU_BUFFERS_H__ + +#include <stdint.h> +#include "mtypes.h" +#include "utils.h" +#include "renderbuffer.h" + +typedef struct nouveau_mem_t { + int type; + uint64_t offset; + uint64_t size; + void* map; +} nouveau_mem; + +extern nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, int type, + GLuint size, GLuint align); +extern void nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem); +extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem); + +extern GLboolean nouveau_memformat_flat_emit(GLcontext *ctx, + nouveau_mem *dst, + nouveau_mem *src, + GLuint dst_offset, + GLuint src_offset, + GLuint size); + +typedef struct nouveau_renderbuffer_t { + struct gl_renderbuffer mesa; /* must be first! */ + __DRIdrawablePrivate *dPriv; + + nouveau_mem *mem; + void * map; + + int cpp; + uint32_t offset; + uint32_t pitch; +} nouveau_renderbuffer; + +extern nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat, + GLvoid *map, GLuint offset, GLuint pitch, __DRIdrawablePrivate *dPriv); +extern void nouveau_window_moved(GLcontext *ctx); +extern GLboolean nouveau_build_framebuffer(GLcontext *, struct gl_framebuffer *); +extern nouveau_renderbuffer *nouveau_current_draw_buffer(GLcontext *ctx); + +extern void nouveauInitBufferFuncs(struct dd_function_table *func); + +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card.c new file mode 100644 index 000000000..91f12f0d7 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card.c @@ -0,0 +1,17 @@ + +#include "nouveau_card.h" +#include "nouveau_reg.h" +#include "nouveau_drm.h" +#include "nouveau_card_list.h" + + +nouveau_card* nouveau_card_lookup(uint32_t device_id) +{ + int i; + for(i=0;i<sizeof(nouveau_card_list)/sizeof(nouveau_card)-1;i++) + if (nouveau_card_list[i].id==(device_id&0xffff)) + return &(nouveau_card_list[i]); + return NULL; +} + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card.h new file mode 100644 index 000000000..8a4c5f224 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card.h @@ -0,0 +1,49 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#ifndef __NOUVEAU_CARD_H__ +#define __NOUVEAU_CARD_H__ + +#include "dri_util.h" +#include "drm.h" +#include "nouveau_drm.h" + +typedef struct nouveau_card_t { + uint16_t id; /* last 4 digits of pci id, last digit is always 0 */ + char* name; /* the user-friendly card name */ + uint32_t class_3d; /* the object class this card uses for 3D */ + uint32_t type; /* the major card family */ + uint32_t flags; +} +nouveau_card; + +#define NV_HAS_LMA 0x00000001 + +extern nouveau_card* nouveau_card_lookup(uint32_t device_id); + +#endif + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card_list.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card_list.h new file mode 100644 index 000000000..8ec5c4a18 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_card_list.h @@ -0,0 +1,232 @@ +static nouveau_card nouveau_card_list[]={ +{0x0008, "EDGE 3D", 0, NV_03, 0}, +{0x0009, "EDGE 3D", 0, NV_03, 0}, +{0x0010, "Mutara V08", 0, NV_03, 0}, +{0x0020, "RIVA TNT", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x0028, "RIVA TNT2/TNT2 Pro", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x0029, "RIVA TNT2 Ultra", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x002A, "Riva TnT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x002B, "Riva TnT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x002C, "Vanta/Vanta LT", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x002D, "RIVA TNT2 Model 64/Model 64 Pro", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x002E, "Vanta", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x002F, "Vanta", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x0040, "GeForce 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0041, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0042, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0043, "NV40.3", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0044, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0045, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0046, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0047, "GeForce 6800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0048, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0049, "NV40GL", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x004D, "Quadro FX 4000", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x004E, "Quadro FX 4000", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0090, "GeForce 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0091, "GeForce 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0092, "GeForce 7800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0093, "GeForce 7800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0098, "GeForce Go 7800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0099, "GE Force Go 7800 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x009D, "Quadro FX4500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00A0, "Aladdin TNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x00C0, "GeForce 6800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00C1, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00C2, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00C3, "Geforce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00C8, "GeForce Go 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00C9, "GeForce Go 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00CC, "Quadro FX Go1400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00CD, "Quadro FX 3450/4000 SDI", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00CE, "Quadro FX 1400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F0, "GeForce 6800/GeForce 6800 Ultra", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F1, "GeForce 6600/GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F2, "GeForce 6600/GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F3, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F4, "GeForce 6600 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F5, "GeForce 7800 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F6, "GeForce 6600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F8, "Quadro FX 3400/4400", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00F9, "GeForce 6800 Ultra/GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x00FA, "GeForce PCX 5750", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x00FB, "GeForce PCX 5900", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x00FC, "Quadro FX 330/GeForce PCX 5300", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0}, +{0x00FD, "Quadro FX 330/Quadro NVS280", NV30_TCL_PRIMITIVE_3D|0x0600, NV_30, 0}, +{0x00FE, "Quadro FX 1300", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x00FF, "GeForce PCX 4300", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0100, "GeForce 256 SDR", NV10_TCL_PRIMITIVE_3D, NV_10, 0}, +{0x0101, "GeForce 256 DDR", NV10_TCL_PRIMITIVE_3D, NV_10, 0}, +{0x0103, "Quadro", NV10_TCL_PRIMITIVE_3D, NV_10, 0}, +{0x0110, "GeForce2 MX/MX 400", NV11_TCL_PRIMITIVE_3D, NV_11, 0}, +{0x0111, "GeForce2 MX 100 DDR/200 DDR", NV11_TCL_PRIMITIVE_3D, NV_11, 0}, +{0x0112, "GeForce2 Go", NV11_TCL_PRIMITIVE_3D, NV_11, 0}, +{0x0113, "Quadro2 MXR/EX/Go", NV11_TCL_PRIMITIVE_3D, NV_11, 0}, +{0x0140, "GeForce 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0141, "GeForce 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0142, "GeForce 6600 PCIe", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0144, "GeForce Go 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0145, "GeForce 6610 XL", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0146, "Geforce Go 6600TE/6200TE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0148, "GeForce Go 6600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0149, "GeForce Go 6600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x014A, "Quadro NVS 440", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x014C, "Quadro FX 550", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x014D, "Quadro FX 550", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x014E, "Quadro FX 540", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x014F, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0150, "GeForce2 GTS/Pro", NV11_TCL_PRIMITIVE_3D, NV_15, 0}, +{0x0151, "GeForce2 Ti", NV11_TCL_PRIMITIVE_3D, NV_15, 0}, +{0x0152, "GeForce2 Ultra, Bladerunner", NV11_TCL_PRIMITIVE_3D, NV_15, 0}, +{0x0153, "Quadro2 Pro", NV11_TCL_PRIMITIVE_3D, NV_15, 0}, +{0x0161, "GeForce 6200 TurboCache(TM)", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0162, "GeForce 6200 SE TurboCache (TM)", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0163, "GeForce 6200 LE", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0164, "GeForce Go 6200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0165, "Quadro NVS 285", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0166, "GeForce Go 6400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0167, "GeForce Go 6200 TurboCache", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0168, "GeForce Go 6200 TurboCache", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0170, "GeForce4 MX 460", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0171, "GeForce4 MX 440", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0172, "GeForce4 MX 420", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0173, "GeForce4 MX 440-SE", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0174, "GeForce4 440 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0175, "GeForce4 420 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0176, "GeForce4 420 Go 32M", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0177, "GeForce4 460 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0178, "Quadro4 550 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0179, "GeForce4 420 Go 32M", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x017A, "Quadro4 200/400 NVS", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x017B, "Quadro4 550 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x017C, "Quadro4 500 GoGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x017D, "GeForce4 410 Go 16M", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0181, "GeForce4 MX 440 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0182, "GeForce4 MX 440SE AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0183, "GeForce4 MX 420 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0185, "GeForce4 MX 4000 AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0186, "GeForce4 448 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0187, "GeForce4 488 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0188, "Quadro4 580 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x018A, "Quadro4 NVS AGP 8x", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x018B, "Quadro4 380 XGL", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x018C, "Quadro NVS 50 PCI", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x018D, "GeForce4 448 Go", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0191, "GeForce 8800 GTX", NV30_TCL_PRIMITIVE_3D|0x5000, NV_50, 0}, +{0x0193, "GeForce 8800 GTS", NV30_TCL_PRIMITIVE_3D|0x5000, NV_50, 0}, +{0x01A0, "GeForce2 MX Integrated Graphics", NV11_TCL_PRIMITIVE_3D, NV_11, 0}, +{0x01D1, "GeForce 7300 LE", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x01D6, "GeForce Go 7200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x01D7, "Quadro NVS 110M / GeForce Go 7300", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x01D8, "GeForce Go 7400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x01DA, "Quadro NVS 110M", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x01DF, "GeForce 7300 GS", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x01F0, "GeForce4 MX - nForce GPU", NV17_TCL_PRIMITIVE_3D, NV_17, 0}, +{0x0200, "GeForce3", NV20_TCL_PRIMITIVE_3D, NV_20, 0}, +{0x0201, "GeForce3 Ti 200", NV20_TCL_PRIMITIVE_3D, NV_20, 0}, +{0x0202, "GeForce3 Ti 500", NV20_TCL_PRIMITIVE_3D, NV_20, 0}, +{0x0203, "Quadro DCC", NV20_TCL_PRIMITIVE_3D, NV_20, 0}, +{0x0211, "GeForce 6800", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0212, "GeForce 6800 LE", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0215, "GeForce 6800 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0218, "GeForce 6800 XT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0221, "GeForce 6200", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0240, "GeForce 6150", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0242, "GeForce 6100", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0244, "Geforce 6150 Go", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0250, "GeForce4 Ti 4600", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0251, "GeForce4 Ti 4400", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0252, "GeForce4 Ti", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0253, "GeForce4 Ti 4200", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0258, "Quadro4 900 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0259, "Quadro4 750 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x025B, "Quadro4 700 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0280, "GeForce4 Ti 4800", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0281, "GeForce4 Ti 4200 AGP 8x", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0282, "GeForce4 Ti 4800 SE", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0286, "GeForce4 Ti 4200 Go AGP 8x", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0288, "Quadro4 980 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0289, "Quadro4 780 XGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x028C, "Quadro4 700 GoGL", NV20_TCL_PRIMITIVE_3D|0x0500, NV_25, 0}, +{0x0290, "GeForce 7900 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0291, "GeForce 7900 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0292, "GeForce 7900 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0298, "GeForce Go 7900 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0299, "GeForce Go 7900 GTX", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x029A, "Quadro FX 2500M", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x029B, "Quadro FX 1500M", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x029C, "Quadro FX 5500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x029D, "Quadro FX 3500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x029E, "Quadro FX 1500", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x029F, "Quadro FX 4500 X2", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x02A0, "XGPU", NV20_TCL_PRIMITIVE_3D, NV_20, 0}, +{0x02E1, "GeForce 7600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0300, "GeForce FX", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0301, "GeForce FX 5800 Ultra", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0302, "GeForce FX 5800", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0308, "Quadro FX 2000", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0309, "Quadro FX 1000", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0311, "GeForce FX 5600 Ultra", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0312, "GeForce FX 5600", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0313, "NV31", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0314, "GeForce FX 5600XT", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0316, "NV31M", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0317, "NV31M Pro", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x031A, "GeForce FX Go5600", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x031B, "GeForce FX Go5650", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x031C, "NVIDIA Quadro FX Go700", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x031D, "NV31GLM", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x031E, "NV31GLM Pro", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x031F, "NV31GLM Pro", NV30_TCL_PRIMITIVE_3D|0x0300, NV_30, 0}, +{0x0320, "GeForce FX 5200", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0321, "GeForce FX 5200 Ultra", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0322, "GeForce FX 5200", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0323, "GeForce FX 5200LE", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0324, "GeForce FX Go5200", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0325, "GeForce FX Go5250", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0326, "GeForce FX 5500", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0327, "GeForce FX 5100", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0328, "GeForce FX Go5200 32M/64M", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0329, "GeForce FX Go5200", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x032A, "Quadro NVS 280 PCI", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x032B, "Quadro FX 500/600 PCI", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x032C, "GeForce FX Go 5300", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x032D, "GeForce FX Go5100", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x032F, "NV34GL", NV30_TCL_PRIMITIVE_3D|0x0600, NV_34, 0}, +{0x0330, "GeForce FX 5900 Ultra", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0331, "GeForce FX 5900", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0332, "GeForce FX 5900XT", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0333, "GeForce FX 5950 Ultra", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0334, "GeForce FX 5900ZT", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0338, "Quadro FX 3000", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x033F, "Quadro FX 700", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0341, "GeForce FX 5700 Ultra", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0342, "GeForce FX 5700", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0343, "GeForce FX 5700LE", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0344, "GeForce FX 5700VE", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0345, "NV36.5", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0347, "GeForce FX Go5700", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0348, "GeForce FX Go5700", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0349, "NV36M Pro", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x034B, "NV36MAP", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x034C, "Quadro FX Go1000", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x034E, "Quadro FX 1100", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x034F, "NV36GL", NV30_TCL_PRIMITIVE_3D|0x0400, NV_30, 0}, +{0x0391, "GeForce 7600 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0392, "GeForce 7600 GS", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0393, "GeForce 7300 GT", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x0398, "GeForce Go 7600", NV30_TCL_PRIMITIVE_3D|0x4000, NV_40, 0}, +{0x03D0, "GeForce 6100 nForce 430", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x03D1, "GeForce 6100 nForce 405", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x03D2, "GeForce 6100 nForce 400", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x03D5, "GeForce 6100 nForce 420", NV30_TCL_PRIMITIVE_3D|0x4400, NV_44, 0}, +{0x0008, "NV1", 0, NV_03, 0}, +{0x0009, "DAC64", 0, NV_03, 0}, +{0x0018, "Riva128", 0, NV_03, 0}, +{0x0019, "Riva128ZX", 0, NV_03, 0}, +{0x0020, "TNT", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x0028, "TNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x0029, "UTNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x002C, "VTNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +{0x00A0, "ITNT2", NV04_DX5_TEXTURED_TRIANGLE, NV_04, 0}, +}; diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_context.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_context.c new file mode 100644 index 000000000..8e11eb613 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -0,0 +1,378 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "glheader.h" +#include "context.h" +#include "simple_list.h" +#include "imports.h" +#include "matrix.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "framebuffer.h" + +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" +#include "tnl/t_vp_build.h" + +#include "drivers/common/driverfuncs.h" + +#include "nouveau_context.h" +#include "nouveau_driver.h" +//#include "nouveau_state.h" +#include "nouveau_span.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_tex.h" +#include "nouveau_msg.h" +#include "nouveau_reg.h" +#include "nouveau_lock.h" +#include "nouveau_query.h" +#include "nv04_swtcl.h" +#include "nv10_swtcl.h" + +#include "vblank.h" +#include "utils.h" +#include "texmem.h" +#include "xmlpool.h" /* for symbolic values of enum-type options */ + +#ifndef NOUVEAU_DEBUG +int NOUVEAU_DEBUG = 0; +#endif + +static const struct dri_debug_control debug_control[] = +{ + { "shaders" , DEBUG_SHADERS }, + { "mem" , DEBUG_MEM }, + { "bufferobj" , DEBUG_BUFFEROBJ }, + { NULL , 0 } +}; + +#define need_GL_ARB_vertex_program +#define need_GL_ARB_occlusion_query +#include "extension_helper.h" + +const struct dri_extension common_extensions[] = +{ + { NULL, 0 } +}; + +const struct dri_extension nv10_extensions[] = +{ + { NULL, 0 } +}; + +const struct dri_extension nv20_extensions[] = +{ + { NULL, 0 } +}; + +const struct dri_extension nv30_extensions[] = +{ + { "GL_ARB_fragment_program", NULL }, + { NULL, 0 } +}; + +const struct dri_extension nv40_extensions[] = +{ + /* ARB_vp can be moved to nv20/30 once the shader backend has been + * written for those cards. + */ + { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, + { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions}, + { NULL, 0 } +}; + +const struct dri_extension nv50_extensions[] = +{ + { NULL, 0 } +}; + +/* Create the device specific context. + */ +GLboolean nouveauCreateContext( const __GLcontextModes *glVisual, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate ) +{ + GLcontext *ctx, *shareCtx; + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + struct dd_function_table functions; + nouveauContextPtr nmesa; + nouveauScreenPtr screen; + + /* Allocate the context */ + nmesa = (nouveauContextPtr) CALLOC( sizeof(*nmesa) ); + if ( !nmesa ) + return GL_FALSE; + + nmesa->driContext = driContextPriv; + nmesa->driScreen = sPriv; + nmesa->driDrawable = NULL; + nmesa->hHWContext = driContextPriv->hHWContext; + nmesa->driHwLock = &sPriv->pSAREA->lock; + nmesa->driFd = sPriv->fd; + + nmesa->screen = (nouveauScreenPtr)(sPriv->private); + screen=nmesa->screen; + + /* Create the hardware context */ + if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_PHYSICAL, + &nmesa->vram_phys)) + return GL_FALSE; + if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_FB_SIZE, + &nmesa->vram_size)) + return GL_FALSE; + if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_PHYSICAL, + &nmesa->agp_phys)) + return GL_FALSE; + if (!nouveauDRMGetParam(nmesa, NOUVEAU_GETPARAM_AGP_SIZE, + &nmesa->agp_size)) + return GL_FALSE; + if (!nouveauFifoInit(nmesa)) + return GL_FALSE; + nouveauObjectInit(nmesa); + + + /* Init default driver functions then plug in our nouveau-specific functions + * (the texture functions are especially important) + */ + _mesa_init_driver_functions( &functions ); + nouveauDriverInitFunctions( &functions ); + nouveauTexInitFunctions( &functions ); + + /* Allocate the Mesa context */ + if (sharedContextPrivate) + shareCtx = ((nouveauContextPtr) sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + nmesa->glCtx = _mesa_create_context(glVisual, shareCtx, + &functions, (void *) nmesa); + if (!nmesa->glCtx) { + FREE(nmesa); + return GL_FALSE; + } + driContextPriv->driverPrivate = nmesa; + ctx = nmesa->glCtx; + + /* Parse configuration files */ + driParseConfigFiles (&nmesa->optionCache, &screen->optionCache, + screen->driScreen->myNum, "nouveau"); + + nmesa->sarea = (drm_nouveau_sarea_t *)((char *)sPriv->pSAREA + + screen->sarea_priv_offset); + + /* Enable any supported extensions */ + driInitExtensions(ctx, common_extensions, GL_TRUE); + if (nmesa->screen->card->type >= NV_10) + driInitExtensions(ctx, nv10_extensions, GL_FALSE); + if (nmesa->screen->card->type >= NV_20) + driInitExtensions(ctx, nv20_extensions, GL_FALSE); + if (nmesa->screen->card->type >= NV_30) + driInitExtensions(ctx, nv30_extensions, GL_FALSE); + if (nmesa->screen->card->type >= NV_40) + driInitExtensions(ctx, nv40_extensions, GL_FALSE); + if (nmesa->screen->card->type >= NV_50) + driInitExtensions(ctx, nv50_extensions, GL_FALSE); + + nmesa->current_primitive = -1; + + nouveauShaderInitFuncs(ctx); + /* Install Mesa's fixed-function texenv shader support */ + if (nmesa->screen->card->type >= NV_40) + ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; + + /* Initialize the swrast */ + _swrast_CreateContext( ctx ); + _vbo_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + + _math_matrix_ctr(&nmesa->viewport); + + nouveauDDInitStateFuncs( ctx ); + nouveauSpanInitFunctions( ctx ); + nouveauDDInitState( nmesa ); + switch(nmesa->screen->card->type) + { + case NV_03: + //nv03TriInitFunctions( ctx ); + break; + case NV_04: + case NV_05: + nv04TriInitFunctions( ctx ); + break; + case NV_10: + case NV_20: + case NV_30: + case NV_40: + case NV_44: + case NV_50: + default: + nv10TriInitFunctions( ctx ); + break; + } + + nouveauInitBufferObjects(ctx); + if (!nouveauSyncInitFuncs(ctx)) + return GL_FALSE; + nouveauQueryInitFuncs(ctx); + nmesa->hw_func.InitCard(nmesa); + nouveauInitState(ctx); + + driContextPriv->driverPrivate = (void *)nmesa; + + NOUVEAU_DEBUG = driParseDebugString( getenv( "NOUVEAU_DEBUG" ), + debug_control ); + + if (driQueryOptionb(&nmesa->optionCache, "no_rast")) { + fprintf(stderr, "disabling 3D acceleration\n"); + FALLBACK(nmesa, NOUVEAU_FALLBACK_DISABLE, 1); + } + + return GL_TRUE; +} + +/* Destroy the device specific context. */ +void nouveauDestroyContext( __DRIcontextPrivate *driContextPriv ) +{ + nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate; + + assert(nmesa); + if ( nmesa ) { + /* free the option cache */ + driDestroyOptionCache (&nmesa->optionCache); + + FREE( nmesa ); + } + +} + + +/* Force the context `c' to be the current context and associate with it + * buffer `b'. + */ +GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv ) +{ + if ( driContextPriv ) { + nouveauContextPtr nmesa = (nouveauContextPtr) driContextPriv->driverPrivate; + struct gl_framebuffer *draw_fb = + (struct gl_framebuffer*)driDrawPriv->driverPrivate; + struct gl_framebuffer *read_fb = + (struct gl_framebuffer*)driReadPriv->driverPrivate; + + driDrawableInitVBlank(driDrawPriv, nmesa->vblank_flags, &nmesa->vblank_seq ); + nmesa->driDrawable = driDrawPriv; + + _mesa_resize_framebuffer(nmesa->glCtx, draw_fb, + driDrawPriv->w, driDrawPriv->h); + if (draw_fb != read_fb) { + _mesa_resize_framebuffer(nmesa->glCtx, draw_fb, + driReadPriv->w, + driReadPriv->h); + } + _mesa_make_current(nmesa->glCtx, draw_fb, read_fb); + + nouveau_build_framebuffer(nmesa->glCtx, + driDrawPriv->driverPrivate); + } else { + _mesa_make_current( NULL, NULL, NULL ); + } + + return GL_TRUE; +} + + +/* Force the context `c' to be unbound from its buffer. + */ +GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv ) +{ + return GL_TRUE; +} + +static void nouveauDoSwapBuffers(nouveauContextPtr nmesa, + __DRIdrawablePrivate *dPriv) +{ + struct gl_framebuffer *fb; + nouveau_renderbuffer *src, *dst; + drm_clip_rect_t *box; + int nbox, i; + + fb = (struct gl_framebuffer *)dPriv->driverPrivate; + dst = (nouveau_renderbuffer*) + fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + src = (nouveau_renderbuffer*) + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer; + +#ifdef ALLOW_MULTI_SUBCHANNEL + LOCK_HARDWARE(nmesa); + nbox = dPriv->numClipRects; + box = dPriv->pClipRects; + + if (nbox) { + BEGIN_RING_SIZE(NvSubCtxSurf2D, + NV10_CONTEXT_SURFACES_2D_FORMAT, 4); + if (src->mesa._ActualFormat == GL_RGBA8) + OUT_RING (6); /* X8R8G8B8 */ + else + OUT_RING (4); /* R5G6B5 */ + OUT_RING ((dst->pitch << 16) | src->pitch); + OUT_RING (src->offset); + OUT_RING (dst->offset); + } + + for (i=0; i<nbox; i++, box++) { + BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_POINT, 3); + OUT_RING (((box->y1 - dPriv->y) << 16) | + (box->x1 - dPriv->x)); + OUT_RING ((box->y1 << 16) | box->x1); + OUT_RING (((box->y2 - box->y1) << 16) | + (box->x2 - box->x1)); + } + FIRE_RING(); + + UNLOCK_HARDWARE(nmesa); +#endif +} + +void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv) +{ + if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { + nouveauContextPtr nmesa = dPriv->driContextPriv->driverPrivate; + + if (nmesa->glCtx->Visual.doubleBufferMode) { + _mesa_notifySwapBuffers(nmesa->glCtx); + nouveauDoSwapBuffers(nmesa, dPriv); + } + + } +} + +void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv, + int x, int y, int w, int h) +{ +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h new file mode 100644 index 000000000..87e4479da --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -0,0 +1,236 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + + +#ifndef __NOUVEAU_CONTEXT_H__ +#define __NOUVEAU_CONTEXT_H__ + +#include "dri_util.h" +#include "drm.h" +#include "nouveau_drm.h" + +#include "mtypes.h" +#include "tnl/t_vertex.h" + +#include "nouveau_screen.h" +#include "nouveau_state_cache.h" +#include "nouveau_buffers.h" +#include "nouveau_shader.h" +#include "nouveau_sync.h" + +#include "xmlconfig.h" + +typedef struct nouveau_fifo_t{ + int channel; + u_int32_t* buffer; + u_int32_t* mmio; + u_int32_t put_base; + u_int32_t current; + u_int32_t put; + u_int32_t free; + u_int32_t max; +} +nouveau_fifo; + +#define TAG(x) nouveau##x +#include "tnl_dd/t_dd_vertex.h" +#undef TAG + +/* Subpixel offsets for window coordinates (triangles): */ +#define SUBPIXEL_X (0.0F) +#define SUBPIXEL_Y (0.125F) + +struct nouveau_context; + +typedef void (*nouveau_tri_func)( struct nouveau_context*, + nouveauVertex *, + nouveauVertex *, + nouveauVertex * ); + +typedef void (*nouveau_line_func)( struct nouveau_context*, + nouveauVertex *, + nouveauVertex * ); + +typedef void (*nouveau_point_func)( struct nouveau_context*, + nouveauVertex * ); + +typedef struct nouveau_hw_func_t { + /* Initialise any card-specific non-GL related state */ + GLboolean (*InitCard)(struct nouveau_context *); + /* Update buffer offset/pitch/format */ + GLboolean (*BindBuffers)(struct nouveau_context *, int num_color, + nouveau_renderbuffer **color, + nouveau_renderbuffer *depth); + /* Update anything that depends on the window position/size */ + void (*WindowMoved)(struct nouveau_context *); +} nouveau_hw_func; + +typedef struct nouveau_context { + /* Mesa context */ + GLcontext *glCtx; + + /* The per-context fifo */ + nouveau_fifo fifo; + + /* The read-only regs */ + volatile unsigned char* mmio; + + /* Physical addresses of AGP/VRAM apertures */ + uint64_t vram_phys; + uint64_t vram_size; + uint64_t agp_phys; + uint64_t agp_size; + + /* Channel synchronisation */ + nouveau_notifier *syncNotifier; + + /* ARB_occlusion_query / EXT_timer_query */ + GLuint query_object_max; + GLboolean * query_alloc; + nouveau_notifier *queryNotifier; + + /* Additional hw-specific functions */ + nouveau_hw_func hw_func; + + /* FIXME : do we want to put all state into a separate struct ? */ + /* State for tris */ + GLuint color_offset; + GLuint specular_offset; + + /* Vertex state */ + GLuint vertex_size; + GLubyte *verts; + struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; + GLuint vertex_attr_count; + + /* Color buffer clear value */ + uint32_t clear_color_value; + + /* Depth/stencil clear value */ + uint32_t clear_value; + + /* Light state */ + GLboolean lighting_enabled; + uint32_t enabled_lights; + + /* Cached state */ + nouveau_state_cache state_cache; + + /* The drawing fallbacks */ + GLuint Fallback; + nouveau_tri_func draw_tri; + nouveau_line_func draw_line; + nouveau_point_func draw_point; + + /* Cliprects information */ + GLuint numClipRects; + drm_clip_rect_t *pClipRects; + drm_clip_rect_t osClipRect; + GLuint drawX, drawY; + + /* The rendering context information */ + GLenum current_primitive; /* the current primitive enum */ + DECLARE_RENDERINPUTS(render_inputs_bitset); /* the current render inputs */ + + /* Shader state */ + nvsFunc VPfunc; + nvsFunc FPfunc; + nouveauShader *current_fragprog; + nouveauShader *current_vertprog; + nouveauShader *passthrough_vp; + nouveauShader *passthrough_fp; + + nouveauScreenRec *screen; + drm_nouveau_sarea_t *sarea; + + __DRIcontextPrivate *driContext; /* DRI context */ + __DRIscreenPrivate *driScreen; /* DRI screen */ + __DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */ + GLint lastStamp; + + drm_context_t hHWContext; + drm_hw_lock_t *driHwLock; + int driFd; + + /* Configuration cache */ + driOptionCache optionCache; + + /* vblank stuff */ + uint32_t vblank_flags; + uint32_t vblank_seq; + + GLuint new_state; + GLuint new_render_state; + GLuint render_index; + GLmatrix viewport; + GLfloat depth_scale; + +}nouveauContextRec, *nouveauContextPtr; + + +#define NOUVEAU_CONTEXT(ctx) ((nouveauContextPtr)(ctx->DriverCtx)) + +/* Flags for software fallback cases: */ +#define NOUVEAU_FALLBACK_TEXTURE 0x0001 +#define NOUVEAU_FALLBACK_DRAW_BUFFER 0x0002 +#define NOUVEAU_FALLBACK_READ_BUFFER 0x0004 +#define NOUVEAU_FALLBACK_STENCIL 0x0008 +#define NOUVEAU_FALLBACK_RENDER_MODE 0x0010 +#define NOUVEAU_FALLBACK_LOGICOP 0x0020 +#define NOUVEAU_FALLBACK_SEP_SPECULAR 0x0040 +#define NOUVEAU_FALLBACK_BLEND_EQ 0x0080 +#define NOUVEAU_FALLBACK_BLEND_FUNC 0x0100 +#define NOUVEAU_FALLBACK_PROJTEX 0x0200 +#define NOUVEAU_FALLBACK_DISABLE 0x0400 + + +extern GLboolean nouveauCreateContext( const __GLcontextModes *glVisual, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate ); + +extern void nouveauDestroyContext( __DRIcontextPrivate * ); + +extern GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv ); + +extern GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv ); + +extern void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv); + +extern void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv, + int x, int y, int w, int h); + +/* Debugging utils: */ +extern int NOUVEAU_DEBUG; + +#define DEBUG_SHADERS 0x00000001 +#define DEBUG_MEM 0x00000002 +#define DEBUG_BUFFEROBJ 0x00000004 + +#endif /* __NOUVEAU_CONTEXT_H__ */ + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h new file mode 100644 index 000000000..c9b2d5900 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_ctrlreg.h @@ -0,0 +1,44 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin, Sylvain Munaut +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + + + +#define NV03_STATUS 0x004006b0 +#define NV04_STATUS 0x00400700 + +#define NV03_FIFO_REGS_SIZE 0x10000 +# define NV03_FIFO_REGS_DMAPUT 0x00000040 +# define NV03_FIFO_REGS_DMAGET 0x00000044 + +/* Fifo commands. These are not regs, neither masks */ +#define NV03_FIFO_CMD_JUMP 0x20000000 +#define NV03_FIFO_CMD_JUMP_OFFSET_MASK 0x1ffffffc +#define NV03_FIFO_CMD_REWIND (NV03_FIFO_CMD_JUMP | (0 & NV03_FIFO_CMD_JUMP_OFFSET_MASK)) + + +#define NONINC_METHOD 0x40000000 + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_dri.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_dri.h new file mode 100644 index 000000000..ce3c3fb9c --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_dri.h @@ -0,0 +1,28 @@ +#ifndef _NOUVEAU_DRI_ +#define _NOUVEAU_DRI_ + +#include "xf86drm.h" +#include "drm.h" +#include "nouveau_drm.h" + +typedef struct { + uint32_t device_id; /**< \brief PCI device ID */ + uint32_t width; /**< \brief width in pixels of display */ + uint32_t height; /**< \brief height in scanlines of display */ + uint32_t depth; /**< \brief depth of display (8, 15, 16, 24) */ + uint32_t bpp; /**< \brief bit depth of display (8, 16, 24, 32) */ + + uint32_t bus_type; /**< \brief ths bus type */ + uint32_t bus_mode; /**< \brief bus mode (used for AGP, maybe also for PCI-E ?) */ + + uint32_t front_offset; /**< \brief front buffer offset */ + uint32_t front_pitch; /**< \brief front buffer pitch */ + uint32_t back_offset; /**< \brief private back buffer offset */ + uint32_t back_pitch; /**< \brief private back buffer pitch */ + uint32_t depth_offset; /**< \brief private depth buffer offset */ + uint32_t depth_pitch; /**< \brief private depth buffer pitch */ + +} NOUVEAUDRIRec, *NOUVEAUDRIPtr; + +#endif + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_driver.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_driver.c new file mode 100644 index 000000000..00956aa8f --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_driver.c @@ -0,0 +1,146 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "nouveau_context.h" +//#include "nouveau_state.h" +#include "nouveau_lock.h" +#include "nouveau_fifo.h" +#include "nouveau_driver.h" +#include "swrast/swrast.h" + +#include "context.h" +#include "framebuffer.h" + +#include "utils.h" + +/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */ +GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa, + unsigned int param, + uint64_t* value) +{ + drm_nouveau_getparam_t getp; + + getp.param = param; + if (!value || drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_GETPARAM, + &getp, sizeof(getp))) + return GL_FALSE; + *value = getp.value; + return GL_TRUE; +} + +/* Wrapper for DRM_NOUVEAU_GETPARAM ioctl */ +GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa, + unsigned int param, + uint64_t value) +{ + drm_nouveau_setparam_t setp; + + setp.param = param; + setp.value = value; + if (drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_SETPARAM, &setp, + sizeof(setp))) + return GL_FALSE; + return GL_TRUE; +} + +/* Return the width and height of the current color buffer */ +static void nouveauGetBufferSize( GLframebuffer *buffer, + GLuint *width, GLuint *height ) +{ + GET_CURRENT_CONTEXT(ctx); + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + LOCK_HARDWARE( nmesa ); + *width = nmesa->driDrawable->w; + *height = nmesa->driDrawable->h; + UNLOCK_HARDWARE( nmesa ); +} + +/* glGetString */ +static const GLubyte *nouveauGetString( GLcontext *ctx, GLenum name ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + static char buffer[128]; + const char * card_name = "Unknown"; + GLuint agp_mode = 0; + + switch ( name ) { + case GL_VENDOR: + return (GLubyte *)DRIVER_AUTHOR; + + case GL_RENDERER: + card_name=nmesa->screen->card->name; + + switch(nmesa->screen->bus_type) + { + case NV_PCI: + case NV_PCIE: + default: + agp_mode=0; + break; + case NV_AGP: + agp_mode=nmesa->screen->agp_mode; + break; + } + driGetRendererString( buffer, card_name, DRIVER_DATE, + agp_mode ); + return (GLubyte *)buffer; + default: + return NULL; + } +} + +/* glFlush */ +static void nouveauFlush( GLcontext *ctx ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + FIRE_RING(); +} + +/* glFinish */ +static void nouveauFinish( GLcontext *ctx ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveauFlush( ctx ); + nouveauWaitForIdle( nmesa ); +} + +/* glClear */ +static void nouveauClear( GLcontext *ctx, GLbitfield mask ) +{ + // XXX we really should do something here... +} + +void nouveauDriverInitFunctions( struct dd_function_table *functions ) +{ + functions->GetBufferSize = nouveauGetBufferSize; + functions->ResizeBuffers = _mesa_resize_framebuffer; + functions->GetString = nouveauGetString; + functions->Flush = nouveauFlush; + functions->Finish = nouveauFinish; + functions->Clear = nouveauClear; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_driver.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_driver.h new file mode 100644 index 000000000..6164012b5 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_driver.h @@ -0,0 +1,42 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + + +#ifndef __NOUVEAU_DRIVER_H__ +#define __NOUVEAU_DRIVER_H__ + +#define DRIVER_DATE "20060219" +#define DRIVER_AUTHOR "Stephane Marchesin" + +extern void nouveauDriverInitFunctions( struct dd_function_table *functions ); +extern GLboolean nouveauDRMGetParam(nouveauContextPtr nmesa, unsigned int param, + uint64_t *value); +extern GLboolean nouveauDRMSetParam(nouveauContextPtr nmesa, unsigned int param, + uint64_t value); + +#endif /* __NOUVEAU_DRIVER_H__ */ + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_fifo.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_fifo.c new file mode 100644 index 000000000..bd2b2eddd --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_fifo.c @@ -0,0 +1,142 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#include "vblank.h" +#include <errno.h> +#include "mtypes.h" +#include "macros.h" +#include "dd.h" +#include "swrast/swrast.h" +#include "nouveau_context.h" +#include "nouveau_msg.h" +#include "nouveau_fifo.h" +#include "nouveau_lock.h" +#include "nouveau_object.h" +#include "nouveau_sync.h" + +#ifdef NOUVEAU_RING_DEBUG +int nouveau_fifo_remaining=0; +#endif + + +#define RING_SKIPS 8 + +void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size) +{ +#ifdef NOUVEAU_RING_DEBUG + return; +#endif + u_int32_t fifo_get; + while(nmesa->fifo.free < size+1) { + fifo_get = NV_FIFO_READ_GET(); + + if(nmesa->fifo.put >= fifo_get) { + nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current; + if(nmesa->fifo.free < size+1) { + OUT_RING(NV03_FIFO_CMD_JUMP | nmesa->fifo.put_base); + if(fifo_get <= RING_SKIPS) { + if(nmesa->fifo.put <= RING_SKIPS) /* corner case - will be idle */ + NV_FIFO_WRITE_PUT(RING_SKIPS + 1); + do { fifo_get = NV_FIFO_READ_GET(); } + while(fifo_get <= RING_SKIPS); + } + NV_FIFO_WRITE_PUT(RING_SKIPS); + nmesa->fifo.current = nmesa->fifo.put = RING_SKIPS; + nmesa->fifo.free = fifo_get - (RING_SKIPS + 1); + } + } else + nmesa->fifo.free = fifo_get - nmesa->fifo.current - 1; + } +} + +/* + * Wait for the channel to be idle + */ +void nouveauWaitForIdleLocked(nouveauContextPtr nmesa) +{ + /* Wait for FIFO idle */ + FIRE_RING(); + while(RING_AHEAD()>0); + + /* Wait on notifier to indicate all commands in the channel have + * been completed. + */ + nouveau_notifier_wait_nop(nmesa->glCtx, nmesa->syncNotifier, NvSub3D); +} + +void nouveauWaitForIdle(nouveauContextPtr nmesa) +{ + LOCK_HARDWARE(nmesa); + nouveauWaitForIdleLocked(nmesa); + UNLOCK_HARDWARE(nmesa); +} + +// here we call the fifo initialization ioctl and fill in stuff accordingly +GLboolean nouveauFifoInit(nouveauContextPtr nmesa) +{ + drm_nouveau_fifo_alloc_t fifo_init; + int i; + +#ifdef NOUVEAU_RING_DEBUG + return GL_TRUE; +#endif + + int ret; + ret=drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_FIFO_ALLOC, &fifo_init, sizeof(fifo_init)); + if (ret) { + FATAL("Fifo initialization ioctl failed (returned %d)\n",ret); + return GL_FALSE; + } + + ret = drmMap(nmesa->driFd, fifo_init.cmdbuf, fifo_init.cmdbuf_size, &nmesa->fifo.buffer); + if (ret) { + FATAL("Unable to map the fifo (returned %d)\n",ret); + return GL_FALSE; + } + ret = drmMap(nmesa->driFd, fifo_init.ctrl, fifo_init.ctrl_size, &nmesa->fifo.mmio); + if (ret) { + FATAL("Unable to map the control regs (returned %d)\n",ret); + return GL_FALSE; + } + + /* Setup our initial FIFO tracking params */ + nmesa->fifo.channel = fifo_init.channel; + nmesa->fifo.put_base = fifo_init.put_base; + nmesa->fifo.current = 0; + nmesa->fifo.put = 0; + nmesa->fifo.max = (fifo_init.cmdbuf_size >> 2) - 1; + nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current; + + for (i=0; i<RING_SKIPS; i++) + OUT_RING(0); + nmesa->fifo.free -= RING_SKIPS; + + MESSAGE("Fifo init ok. Using context %d\n", fifo_init.channel); + return GL_TRUE; +} + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_fifo.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_fifo.h new file mode 100644 index 000000000..23325dcea --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_fifo.h @@ -0,0 +1,195 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + + +#ifndef __NOUVEAU_FIFO_H__ +#define __NOUVEAU_FIFO_H__ + +#include "nouveau_context.h" +#include "nouveau_ctrlreg.h" +#include "nouveau_state_cache.h" + +//#define NOUVEAU_RING_TRACE +//#define NOUVEAU_RING_DEBUG +//#define NOUVEAU_STATE_CACHE_DISABLE + +#ifndef NOUVEAU_RING_TRACE +#define NOUVEAU_RING_TRACE 0 +#else +#undef NOUVEAU_RING_TRACE +#define NOUVEAU_RING_TRACE 1 +#endif + +#define NV_READ(reg) *(volatile u_int32_t *)(nmesa->mmio + (reg)) + +#define NV_FIFO_READ(reg) *(volatile u_int32_t *)(nmesa->fifo.mmio + (reg/4)) +#define NV_FIFO_WRITE(reg,value) *(volatile u_int32_t *)(nmesa->fifo.mmio + (reg/4)) = value; +#define NV_FIFO_READ_GET() ((NV_FIFO_READ(NV03_FIFO_REGS_DMAGET) - nmesa->fifo.put_base) >> 2) +#define NV_FIFO_WRITE_PUT(val) do { \ + if (NOUVEAU_RING_TRACE) {\ + printf("FIRE_RING : 0x%08x\n", nmesa->fifo.current << 2); \ + fflush(stdout); \ + sleep(1); \ + } \ + NV_FIFO_WRITE(NV03_FIFO_REGS_DMAPUT, ((val)<<2) + nmesa->fifo.put_base); \ +} while(0) + +/* + * Ring/fifo interface + * + * - Begin a ring section with BEGIN_RING_SIZE (if you know the full size in advance) + * - Output stuff to the ring with either OUT_RINGp (outputs a raw mem chunk), OUT_RING (1 uint32_t) or OUT_RINGf (1 float) + * - RING_AVAILABLE returns the available fifo (in uint32_ts) + * - RING_AHEAD returns how much ahead of the last submission point we are + * - FIRE_RING fires whatever we have that wasn't fired before + * - WAIT_RING waits for size (in uint32_ts) to be available in the fifo + */ + +/* Enable for ring debugging. Prints out writes to the ring buffer + * but does not actually write to it. + */ +#ifdef NOUVEAU_RING_DEBUG + +extern int nouveau_fifo_remaining; + +#define OUT_RINGp(ptr,sz) do { \ +uint32_t* p=(uint32_t*)(ptr); \ +int i; printf("OUT_RINGp: (size 0x%x dwords)\n",sz); for(i=0;i<sz;i++) printf(" 0x%08x %f\n", *(p+i), *((float*)(p+i))); \ +nouveau_fifo_remaining-=sz; \ +}while(0) + +#define OUT_RING(n) do { \ + printf("OUT_RINGn: 0x%08x (%s)\n", n, __func__); \ + nouveau_fifo_remaining--; \ +}while(0) + +#define OUT_RINGf(n) do { \ + printf("OUT_RINGf: %.04f (%s)\n", n, __func__); \ + nouveau_fifo_remaining--; \ +}while(0) + +#define BEGIN_RING_SIZE(subchannel,tag,size) do { \ + if (nouveau_fifo_remaining!=0) \ + printf("RING ERROR : remaining %d\n",nouveau_fifo_remaining); \ + nouveau_state_cache_flush(nmesa); \ + if (nmesa->fifo.free <= (size)) \ + WAIT_RING(nmesa,(size)); \ + OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \ + nmesa->fifo.free -= ((size) + 1); \ + nouveau_fifo_remaining=size; \ +}while(0) + +#else + +#define OUT_RINGp(ptr,sz) do{ \ + if (NOUVEAU_RING_TRACE) { \ + uint32_t* p=(uint32_t*)(ptr); \ + int i; printf("OUT_RINGp: (size 0x%x dwords) (%s)\n",sz, __func__); for(i=0;i<sz;i++) printf(" [0x%08x] 0x%08x %f\n", (nmesa->fifo.current+i) << 2, *(p+i), *((float*)(p+i))); \ + } \ + memcpy(nmesa->fifo.buffer+nmesa->fifo.current,ptr,(sz)*4); \ + nmesa->fifo.current+=(sz); \ +}while(0) + +#define OUT_RING(n) do { \ +if (NOUVEAU_RING_TRACE) \ + printf("OUT_RINGn: [0x%08x] 0x%08x (%s)\n", nmesa->fifo.current << 2, n, __func__); \ +nmesa->fifo.buffer[nmesa->fifo.current++]=(n); \ +}while(0) + +#define OUT_RINGf(n) do { \ +if (NOUVEAU_RING_TRACE) \ + printf("OUT_RINGf: [0x%08x] %.04f (%s)\n", nmesa->fifo.current << 2, n, __func__); \ +*((float*)(nmesa->fifo.buffer+nmesa->fifo.current++))=(n); \ +}while(0) + +#define BEGIN_RING_SIZE(subchannel,tag,size) do { \ + nouveau_state_cache_flush(nmesa); \ + if (nmesa->fifo.free <= (size)) \ + WAIT_RING(nmesa,(size)); \ + OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \ + nmesa->fifo.free -= ((size) + 1); \ +}while(0) + +#endif + +extern void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size); +extern void nouveau_state_cache_flush(nouveauContextPtr nmesa); +extern void nouveau_state_cache_init(nouveauContextPtr nmesa); + +#ifdef NOUVEAU_STATE_CACHE_DISABLE +#define BEGIN_RING_CACHE(subc,tag,size) BEGIN_RING_SIZE((subc), (tag), (size)) +#define OUT_RING_CACHE(n) OUT_RING((n)) +#define OUT_RING_CACHEf(n) OUT_RINGf((n)) +#define OUT_RING_CACHEp(ptr, sz) OUT_RINGp((ptr), (sz)) +#else +#define BEGIN_RING_CACHE(subchannel,tag,size) do { \ + nmesa->state_cache.dirty=1; \ + nmesa->state_cache.current_pos=((tag)/4); \ +}while(0) + +#define OUT_RING_CACHE(n) do { \ + if (nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value!=(n)) { \ + nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \ + nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \ + nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value=(n); \ + } \ + nmesa->state_cache.current_pos++; \ +}while(0) + +#define OUT_RING_CACHEf(n) do { \ + if ((*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))!=(n)){ \ + nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \ + nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \ + (*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))=(n);\ + } \ + nmesa->state_cache.current_pos++; \ +}while(0) + +#define OUT_RING_CACHEp(ptr,sz) do { \ +uint32_t* p=(uint32_t*)(ptr); \ +int i; for(i=0;i<sz;i++) OUT_RING_CACHE(*(p+i)); \ +}while(0) +#endif + +#define RING_AVAILABLE() (nmesa->fifo.free-1) + +#define RING_AHEAD() ((nmesa->fifo.put<=nmesa->fifo.current)?(nmesa->fifo.current-nmesa->fifo.put):nmesa->fifo.max-nmesa->fifo.put+nmesa->fifo.current) + +#define FIRE_RING() do { \ + if (nmesa->fifo.current!=nmesa->fifo.put) { \ + nmesa->fifo.put=nmesa->fifo.current; \ + NV_FIFO_WRITE_PUT(nmesa->fifo.put); \ + } \ +}while(0) + +extern void nouveauWaitForIdle(nouveauContextPtr nmesa); +extern void nouveauWaitForIdleLocked(nouveauContextPtr nmesa); +extern GLboolean nouveauFifoInit(nouveauContextPtr nmesa); + +#endif /* __NOUVEAU_FIFO_H__ */ + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_lock.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_lock.c new file mode 100644 index 000000000..c119d14dd --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_lock.c @@ -0,0 +1,81 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#include "nouveau_context.h" +#include "nouveau_lock.h" + +#include "drirenderbuffer.h" +#include "framebuffer.h" + + +/* Update the hardware state. This is called if another context has + * grabbed the hardware lock, which includes the X server. This + * function also updates the driver's window state after the X server + * moves, resizes or restacks a window -- the change will be reflected + * in the drawable position and clip rects. Since the X server grabs + * the hardware lock when it changes the window state, this routine will + * automatically be called after such a change. + */ +void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags ) +{ + __DRIdrawablePrivate *dPriv = nmesa->driDrawable; + __DRIscreenPrivate *sPriv = nmesa->driScreen; + drm_nouveau_sarea_t *sarea = nmesa->sarea; + + drmGetLock( nmesa->driFd, nmesa->hHWContext, flags ); + + /* The window might have moved, so we might need to get new clip + * rects. + * + * NOTE: This releases and regrabs the hw lock to allow the X server + * to respond to the DRI protocol request for new drawable info. + * Since the hardware state depends on having the latest drawable + * clip rects, all state checking must be done _after_ this call. + */ + DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv ); + + /* If timestamps don't match, the window has been changed */ + if (nmesa->lastStamp != dPriv->lastStamp) { + struct gl_framebuffer *fb = (struct gl_framebuffer *)dPriv->driverPrivate; + + /* _mesa_resize_framebuffer will take care of calling the renderbuffer's + * AllocStorage function if we need more memory to hold it */ + if (fb->Width != dPriv->w || fb->Height != dPriv->h) { + _mesa_resize_framebuffer(nmesa->glCtx, fb, dPriv->w, dPriv->h); + /* resize buffers, will call nouveau_window_moved */ + nouveau_build_framebuffer(nmesa->glCtx, fb); + } else { + nouveau_window_moved(nmesa->glCtx); + } + + nmesa->lastStamp = dPriv->lastStamp; + } + + nmesa->numClipRects = dPriv->numClipRects; + nmesa->pClipRects = dPriv->pClipRects; + +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_lock.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_lock.h new file mode 100644 index 000000000..38bb00142 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_lock.h @@ -0,0 +1,69 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#ifndef __NOUVEAU_LOCK_H__ +#define __NOUVEAU_LOCK_H__ + +#include "nouveau_context.h" + +extern void nouveauGetLock( nouveauContextPtr nmesa, GLuint flags ); + +/* + * !!! We may want to separate locks from locks with validation. This + * could be used to improve performance for those things commands that + * do not do any drawing !!! + */ + +/* Lock the hardware and validate our state. + */ +#define LOCK_HARDWARE( nmesa ) \ + do { \ + char __ret = 0; \ + DEBUG_CHECK_LOCK(); \ + DRM_CAS( nmesa->driHwLock, nmesa->hHWContext, \ + (DRM_LOCK_HELD | nmesa->hHWContext), __ret ); \ + if ( __ret ) \ + nouveauGetLock( nmesa, 0 ); \ + DEBUG_LOCK(); \ + } while (0) + +/* Unlock the hardware. + */ +#define UNLOCK_HARDWARE( nmesa ) \ + do { \ + DRM_UNLOCK( nmesa->driFd, \ + nmesa->driHwLock, \ + nmesa->hHWContext ); \ + DEBUG_RESET(); \ + } while (0) + +#define DEBUG_LOCK() +#define DEBUG_RESET() +#define DEBUG_CHECK_LOCK() + + +#endif /* __NOUVEAU_LOCK_H__ */ diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_msg.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_msg.h new file mode 100644 index 000000000..5dea2189c --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_msg.h @@ -0,0 +1,67 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. +Copyright 2006 Stephane Marchesin. All Rights Reserved + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Nicolai Haehnle <prefect_@gmx.net> + */ + + +#ifndef __NOUVEAU_MSG_H__ +#define __NOUVEAU_MSG_H__ + +#define WARN_ONCE(a, ...) do {\ + static int warn##__LINE__=1;\ + if(warn##__LINE__){\ + fprintf(stderr, "*********************************WARN_ONCE*********************************\n");\ + fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__);\ + fprintf(stderr, a, ## __VA_ARGS__);\ + fprintf(stderr, "***************************************************************************\n");\ + warn##__LINE__=0;\ + } \ + }while(0) + +#define MESSAGE(a, ...) do{\ + fprintf(stderr, "************************************INFO***********************************\n");\ + fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__); \ + fprintf(stderr, a, ## __VA_ARGS__);\ + fprintf(stderr, "***************************************************************************\n");\ + }while(0) + +#define FATAL(a, ...) do{\ + fprintf(stderr, "***********************************FATAL***********************************\n");\ + fprintf(stderr, "File %s function %s line %d\n", __FILE__, __FUNCTION__, __LINE__); \ + fprintf(stderr, a, ## __VA_ARGS__);\ + fprintf(stderr, "***************************************************************************\n");\ + }while(0) + +#endif /* __NOUVEAU_MSG_H__ */ + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_object.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_object.c new file mode 100644 index 000000000..b71acff43 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_object.c @@ -0,0 +1,117 @@ + +#include "nouveau_fifo.h" +#include "nouveau_object.h" +#include "nouveau_reg.h" + + +GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, + uint32_t handle, int class) +{ + drm_nouveau_object_init_t cto; + int ret; + + cto.channel = nmesa->fifo.channel; + cto.handle = handle; + cto.class = class; + ret = drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_OBJECT_INIT, &cto, sizeof(cto)); + + return ret == 0; +} + +GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa, + uint32_t handle, + int class, + uint32_t offset, + uint32_t size, + int target, + int access) +{ + drm_nouveau_dma_object_init_t dma; + int ret; + + dma.channel = nmesa->fifo.channel; + dma.class = class; + dma.handle = handle; + dma.target = target; + dma.access = access; + dma.offset = offset; + dma.size = size; + ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_DMA_OBJECT_INIT, + &dma, sizeof(dma)); + return ret == 0; +} + +GLboolean nouveauCreateDmaObjectFromMem(nouveauContextPtr nmesa, + uint32_t handle, int class, + nouveau_mem *mem, + int access) +{ + uint32_t offset = mem->offset; + int target = mem->type & (NOUVEAU_MEM_FB | NOUVEAU_MEM_AGP); + + if (!target) + return GL_FALSE; + + if (target & NOUVEAU_MEM_FB) + offset -= nmesa->vram_phys; + else if (target & NOUVEAU_MEM_AGP) + offset -= nmesa->agp_phys; + + return nouveauCreateDmaObject(nmesa, handle, class, + offset, mem->size, + target, access); +} + +void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle) +{ + BEGIN_RING_SIZE(subchannel, 0, 1); + OUT_RING(handle); +} + +void nouveauObjectInit(nouveauContextPtr nmesa) +{ +#ifdef NOUVEAU_RING_DEBUG + return; +#endif + +/* We need to know vram size.. and AGP size (and even if the card is AGP..) */ + nouveauCreateDmaObject( nmesa, NvDmaFB, NV_DMA_IN_MEMORY, + 0, nmesa->vram_size, + NOUVEAU_MEM_FB, + NOUVEAU_MEM_ACCESS_RW); + nouveauCreateDmaObject( nmesa, NvDmaAGP, NV_DMA_IN_MEMORY, + 0, nmesa->agp_size, + NOUVEAU_MEM_AGP, + NOUVEAU_MEM_ACCESS_RW); + + nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d); + if (nmesa->screen->card->type>=NV_10) { + nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV10_CONTEXT_SURFACES_2D); + nouveauCreateContextObject(nmesa, NvImageBlit, NV10_IMAGE_BLIT); + } else { + nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D); + nouveauCreateContextObject(nmesa, NvCtxSurf3D, NV04_CONTEXT_SURFACES_3D); + nouveauCreateContextObject(nmesa, NvImageBlit, NV_IMAGE_BLIT); + } + nouveauCreateContextObject(nmesa, NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT); + +#ifdef ALLOW_MULTI_SUBCHANNEL + nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf2D, NvCtxSurf2D); + BEGIN_RING_SIZE(NvSubCtxSurf2D, NV10_CONTEXT_SURFACES_2D_SET_DMA_IN_MEMORY0, 2); + OUT_RING(NvDmaFB); + OUT_RING(NvDmaFB); + + nouveauObjectOnSubchannel(nmesa, NvSubImageBlit, NvImageBlit); + BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_CONTEXT_SURFACES_2D, 1); + OUT_RING(NvCtxSurf2D); + BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_OPERATION, 1); + OUT_RING(3); /* SRCCOPY */ + + nouveauObjectOnSubchannel(nmesa, NvSubMemFormat, NvMemFormat); +#endif + + nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D); +} + + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_object.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_object.h new file mode 100644 index 000000000..0be9b4309 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_object.h @@ -0,0 +1,47 @@ +#ifndef __NOUVEAU_OBJECT_H__ +#define __NOUVEAU_OBJECT_H__ + +#include "nouveau_context.h" + +#define ALLOW_MULTI_SUBCHANNEL + +void nouveauObjectInit(nouveauContextPtr nmesa); + +enum DMAObjects { + Nv3D = 0x80000019, + NvCtxSurf2D = 0x80000020, + NvImageBlit = 0x80000021, + NvMemFormat = 0x80000022, + NvCtxSurf3D = 0x80000023, + NvDmaFB = 0xD0FB0001, + NvDmaAGP = 0xD0AA0001, + NvSyncNotify = 0xD0000001, + NvQueryNotify = 0xD0000002 +}; + +enum DMASubchannel { + NvSubCtxSurf2D = 0, + NvSubImageBlit = 1, + NvSubMemFormat = 2, + NvSubCtxSurf3D = 3, + NvSub3D = 7, +}; + +extern void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle); + +extern GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, + uint32_t handle, int class); +extern GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa, + uint32_t handle, + int class, + uint32_t offset, + uint32_t size, + int target, + int access); +extern GLboolean nouveauCreateDmaObjectFromMem(nouveauContextPtr nmesa, + uint32_t handle, + int class, + nouveau_mem *mem, + int access); + +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_query.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_query.c new file mode 100644 index 000000000..de3f5b037 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_query.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* GL_ARB_occlusion_query support for NV20/30/40 */ + +#include "mtypes.h" + +#include "nouveau_fifo.h" +#include "nouveau_msg.h" +#include "nouveau_object.h" +#include "nouveau_reg.h" +#include "nouveau_sync.h" +#include "nouveau_query.h" + +static struct gl_query_object * +nouveauNewQueryObject(GLcontext *ctx, GLuint id) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_query_object *nq; + int i; + + for (i=0; i<nmesa->query_object_max; i++) + if (nmesa->query_alloc[i] == GL_FALSE) + break; + if (i==nmesa->query_object_max) + return NULL; + + nq = CALLOC_STRUCT(nouveau_query_object_t); + if (nq) { + nq->notifier_id = i; + + nq->mesa.Id = id; + nq->mesa.Result = 0; + nq->mesa.Active = GL_FALSE; + nq->mesa.Ready = GL_TRUE; + } + + return (struct gl_query_object *)nq; +} + +static void +nouveauBeginQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_query_object *nq = (nouveau_query_object *)q; + + nouveau_notifier_reset(nmesa->queryNotifier, nq->notifier_id); + + switch (nmesa->screen->card->type) { + case NV_20: + BEGIN_RING_CACHE(NvSub3D, 0x17c8, 1); + OUT_RING_CACHE (1); + BEGIN_RING_CACHE(NvSub3D, 0x17cc, 1); + OUT_RING_CACHE (1); + break; + case NV_30: + case NV_40: + case NV_44: + /* I don't think this is OCC_QUERY enable, but it *is* needed to make + * the SET_OBJECT7 notifier block work with STORE_RESULT. + * + * Also, this appears to reset the pixel pass counter */ + BEGIN_RING_SIZE(NvSub3D, + NV30_TCL_PRIMITIVE_3D_OCC_QUERY_OR_COLOR_BUFF_ENABLE, + 1); + OUT_RING (1); + /* Probably OCC_QUERY_ENABLE */ + BEGIN_RING_CACHE(NvSub3D, 0x17cc, 1); + OUT_RING_CACHE (1); + break; + default: + WARN_ONCE("no support for this card\n"); + break; + } +} + +static void +nouveauUpdateQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_query_object *nq = (nouveau_query_object *)q; + int status; + + status = nouveau_notifier_status(nmesa->queryNotifier, + nq->notifier_id); + + q->Ready = (status == NV_NOTIFY_STATE_STATUS_COMPLETED); + if (q->Ready) + q->Result = nouveau_notifier_return_val(nmesa->queryNotifier, + nq->notifier_id); +} + +static void +nouveauWaitQueryResult(GLcontext *ctx, GLenum target, struct gl_query_object *q) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_query_object *nq = (nouveau_query_object *)q; + + nouveau_notifier_wait_status(nmesa->queryNotifier, nq->notifier_id, + NV_NOTIFY_STATE_STATUS_COMPLETED, 0); + nouveauUpdateQuery(ctx, target, q); +} + +static void +nouveauEndQuery(GLcontext *ctx, GLenum target, struct gl_query_object *q) +{ + nouveau_query_object *nq = (nouveau_query_object *)q; + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + switch (nmesa->screen->card->type) { + case NV_20: + BEGIN_RING_SIZE(NvSub3D, 0x17d0, 1); + OUT_RING (0x01000000 | nq->notifier_id*32); + break; + case NV_30: + case NV_40: + case NV_44: + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STORE_RESULT, 1); + OUT_RING (0x01000000 | nq->notifier_id*32); + break; + default: + WARN_ONCE("no support for this card\n"); + break; + } + FIRE_RING(); + + /*XXX: wait for query to complete, mesa doesn't give the driver + * an interface to query the status of a query object so + * this has to stall the channel. + */ + nouveauWaitQueryResult(ctx, target, q); + + BEGIN_RING_CACHE(NvSub3D, 0x17cc, 1); + OUT_RING_CACHE (0); +} + +void +nouveauQueryInitFuncs(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (nmesa->screen->card->type < NV_20) + return; + + nmesa->query_object_max = (0x4000 / 32); + nmesa->queryNotifier = + nouveau_notifier_new(ctx, NvQueryNotify, + nmesa->query_object_max); + nmesa->query_alloc = calloc(nmesa->query_object_max, sizeof(GLboolean)); + + switch (nmesa->screen->card->type) { + case NV_20: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SET_OBJECT8, 1); + OUT_RING_CACHE (NvQueryNotify); + break; + case NV_30: + case NV_40: + case NV_44: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT7, 1); + OUT_RING_CACHE (NvQueryNotify); + break; + default: + break; + }; + + ctx->Driver.NewQueryObject = nouveauNewQueryObject; + ctx->Driver.BeginQuery = nouveauBeginQuery; + ctx->Driver.EndQuery = nouveauEndQuery; +#if 0 + ctx->Driver.UpdateQuery = nouveauUpdateQuery; + ctx->Driver.WaitQueryResult = nouveauWaitQueryResult; +#endif +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_query.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_query.h new file mode 100644 index 000000000..3ded41417 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_query.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __NOUVEAU_QUERY_H__ +#define __NOUVEAU_QUERY_H__ + +typedef struct nouveau_query_object_t { + struct gl_query_object mesa; + + int notifier_id; +} nouveau_query_object; + +extern void nouveauQueryInitFuncs(GLcontext *ctx); +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_reg.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_reg.h new file mode 100644 index 000000000..8758b538c --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_reg.h @@ -0,0 +1,1505 @@ +/* + Autogenerated file, do not edit ! + +************************************************************************** + + Copyright (C) 2006 : + Dmitry Baryshkov, + Laurent Carlier, + Matthieu Castet, + Dawid Gajownik, + Jeremy Kolb, + Stephane Loeuillet, + Patrice Mandin, + Stephane Marchesin, + Serge Martin, + Sylvain Munaut, + Ben Skeggs, + Erik Waling, + koala_br, + sturmflut. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +************************************************************************** + + Created from objects.c rev. 1.398 +*/ + +#ifndef _NOUVEAU_REG_H +#define _NOUVEAU_REG_H + +/****************************************** +Object NV01_CONTEXT_CLIP_RECTANGLE used on: NV03 NV04 NV10 NV15 NV20 NV40 G70 +*/ +#define NV01_CONTEXT_CLIP_RECTANGLE 0x00000019 +# define NV01_CONTEXT_CLIP_RECTANGLE_SET_POINT 0x00000300 /* Parameters: x y */ +# define NV01_CONTEXT_CLIP_RECTANGLE_SET_SIZE 0x00000304 /* Parameters: width height */ + +/****************************************** +Object NV_MEMORY_TO_MEMORY_FORMAT used on: NV04 NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 +# define NV_MEMORY_TO_MEMORY_FORMAT_NOP 0x00000100 +# define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 +# define NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY 0x00000180 +# define NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN 0x00000184 +# define NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_OUT 0x00000188 +# define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c +# define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT 0x00000310 +# define NV_MEMORY_TO_MEMORY_FORMAT_PITCH_IN 0x00000314 +# define NV_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT 0x00000318 +# define NV_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN 0x0000031c +# define NV_MEMORY_TO_MEMORY_FORMAT_LINE_COUNT 0x00000320 +# define NV_MEMORY_TO_MEMORY_FORMAT_FORMAT 0x00000324 /* Parameters: src_inc dst_inc */ +# define NV_MEMORY_TO_MEMORY_FORMAT_BUF_NOTIFY 0x00000328 + +/****************************************** +Object NV03_PRIMITIVE_RASTER_OP used on: NV03 NV04 NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV03_PRIMITIVE_RASTER_OP 0x00000043 +# define NV03_PRIMITIVE_RASTER_OP_NOTIFY 0x00000100 +# define NV03_PRIMITIVE_RASTER_OP_DMA_NOTIFY 0x00000180 +# define NV03_PRIMITIVE_RASTER_OP_LOGIC_OP 0x00000300 /* Parameters: logic_op */ + +/****************************************** +Object NV04_GDI_RECTANGLE_TEXT used on: NV04 NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV04_GDI_RECTANGLE_TEXT 0x0000004a +# define NV04_GDI_RECTANGLE_TEXT_SET_DMA_NOTIFY 0x00000180 +# define NV04_GDI_RECTANGLE_TEXT_PATTERN 0x00000188 +# define NV04_GDI_RECTANGLE_TEXT_ROP5 0x0000018c +# define NV04_GDI_RECTANGLE_TEXT_SURFACE 0x00000198 +# define NV04_GDI_RECTANGLE_TEXT_OPERATION 0x000002fc +# define NV04_GDI_RECTANGLE_TEXT_FORMAT 0x00000300 +# define NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL1_TL 0x000005f4 /* Parameters: left top */ +# define NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL1_BR 0x000005f8 /* Parameters: right bottom */ +# define NV04_GDI_RECTANGLE_TEXT_FILL_VALUE 0x000005fc +# define NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL2_TL 0x00000600 /* Parameters: left top */ +# define NV04_GDI_RECTANGLE_TEXT_BLOCK_LEVEL2_BR 0x00000604 /* Parameters: right bottom */ + +/****************************************** +Object NV04_SWIZZLED_SURFACE used on: NV04 NV10 NV15 +*/ +#define NV04_SWIZZLED_SURFACE 0x00000052 +# define NV04_SWIZZLED_SURFACE_DMA_NOTIFY 0x00000180 +# define NV04_SWIZZLED_SURFACE_DMA_IMAGE 0x00000184 +# define NV04_SWIZZLED_SURFACE_FORMAT 0x00000300 /* Parameters: log2(height) log2(width) color */ +# define NV04_SWIZZLED_SURFACE_OFFSET 0x00000304 + +/****************************************** +Object NV04_CONTEXT_SURFACES_3D used on: NV04 +*/ +#define NV04_CONTEXT_SURFACES_3D 0x00000053 +# define NV04_CONTEXT_SURFACES_3D_DMA_NOTIFY 0x00000180 +# define NV04_CONTEXT_SURFACES_3D_DMA_COLOR 0x00000184 +# define NV04_CONTEXT_SURFACES_3D_DMA_ZETA 0x00000188 +# define NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL 0x000002f8 /* Parameters: x width */ +# define NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL 0x000002fc /* Parameters: y height */ +# define NV04_CONTEXT_SURFACES_3D_FORMAT 0x00000300 /* Parameters: color type width height */ +# define NV04_CONTEXT_SURFACES_3D_CLIP_SIZE 0x00000304 /* Parameters: width height */ +# define NV04_CONTEXT_SURFACES_3D_PITCH 0x00000308 /* Parameters: color zeta */ +# define NV04_CONTEXT_SURFACES_3D_OFFSET_COLOR 0x0000030c +# define NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA 0x00000310 + +/****************************************** +Object NV04_DX5_TEXTURED_TRIANGLE used on: NV04 +*/ +#define NV04_DX5_TEXTURED_TRIANGLE 0x00000054 +# define NV04_DX5_TEXTURED_TRIANGLE_NOP 0x00000100 +# define NV04_DX5_TEXTURED_TRIANGLE_NOTIFY 0x00000104 +# define NV04_DX5_TEXTURED_TRIANGLE_DMA_NOTIFY 0x00000180 +# define NV04_DX5_TEXTURED_TRIANGLE_DMA_1 0x00000184 +# define NV04_DX5_TEXTURED_TRIANGLE_DMA_2 0x00000188 +# define NV04_DX5_TEXTURED_TRIANGLE_SURFACE 0x0000018c +# define NV04_DX5_TEXTURED_TRIANGLE_COLOR_KEY 0x00000300 +# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_OFFSET 0x00000304 +# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_FORMAT 0x00000308 /* Parameters: color mipmaps log(u) log(v) wrap_s wrap_t */ +# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_FILTER 0x0000030c /* Parameters: magfilter minfilter lodbias */ +# define NV04_DX5_TEXTURED_TRIANGLE_BLEND 0x00000310 /* Parameters: texture benable dst src */ +# define NV04_DX5_TEXTURED_TRIANGLE_CONTROL 0x00000314 /* Parameters: alpharef alphafunc alphaenable zenable zwrite zfunc cullmode */ +# define NV04_DX5_TEXTURED_TRIANGLE_FOG_COLOR 0x00000318 +# define NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX( d) (0x00000400 + d * 0x0020) +# define NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SY( d) (0x00000404 + d * 0x0020) +# define NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SZ( d) (0x00000408 + d * 0x0020) +# define NV04_DX5_TEXTURED_TRIANGLE_INV_W( d) (0x0000040c + d * 0x0020) +# define NV04_DX5_TEXTURED_TRIANGLE_COLOR( d) (0x00000410 + d * 0x0020) +# define NV04_DX5_TEXTURED_TRIANGLE_SPECULAR( d) (0x00000414 + d * 0x0020) +# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_S( d) (0x00000418 + d * 0x0020) +# define NV04_DX5_TEXTURED_TRIANGLE_TEXTURE_T( d) (0x0000041c + d * 0x0020) +# define NV04_DX5_TEXTURED_TRIANGLE_DRAW 0x00000600 /* Parameters: v0 v1 v2 v3 v4 v5 */ + +/****************************************** +Object NV04_DX6_MULTITEX_TRIANGLE used on: NV04 NV10 NV15 +*/ +#define NV04_DX6_MULTITEX_TRIANGLE 0x00000055 +# define NV04_DX6_MULTITEX_TRIANGLE_NOP 0x00000100 +# define NV04_DX6_MULTITEX_TRIANGLE_NOTIFY 0x00000104 +# define NV04_DX6_MULTITEX_TRIANGLE_DMA_NOTIFY 0x00000180 +# define NV04_DX6_MULTITEX_TRIANGLE_DMA_1 0x00000184 +# define NV04_DX6_MULTITEX_TRIANGLE_DMA_2 0x00000188 +# define NV04_DX6_MULTITEX_TRIANGLE_SURFACE 0x0000018c +# define NV04_DX6_MULTITEX_TRIANGLE_OFFSET0 0x00000308 +# define NV04_DX6_MULTITEX_TRIANGLE_OFFSET1 0x0000030c +# define NV04_DX6_MULTITEX_TRIANGLE_FORMAT0 0x00000310 /* Parameters: color mipmaps log(u) log(v) wrap_s wrap_t */ +# define NV04_DX6_MULTITEX_TRIANGLE_FORMAT1 0x00000314 /* Parameters: color mipmaps log(u) log(v) wrap_s wrap_t */ +# define NV04_DX6_MULTITEX_TRIANGLE_FILTER0 0x00000318 /* Parameters: magfilter minfilter lodbias */ +# define NV04_DX6_MULTITEX_TRIANGLE_FILTER1 0x0000031c /* Parameters: magfilter minfilter lodbias */ +# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA 0x00000320 +# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR 0x00000324 +# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA 0x0000032c +# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR 0x00000330 +# define NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR 0x00000334 +# define NV04_DX6_MULTITEX_TRIANGLE_BLEND 0x00000338 /* Parameters: benable dst src */ +# define NV04_DX6_MULTITEX_TRIANGLE_CONTROL0 0x0000033c /* Parameters: red_write green_write blue_write alpha_write alpha_write stencil_write alpharef alphafunc alphaenable zenable zwrite zfunc cullmode */ +# define NV04_DX6_MULTITEX_TRIANGLE_CONTROL1 0x00000340 /* Parameters: stencil_enable stencil_mask_write stencil_mask_read stencilref stencilfunc */ +# define NV04_DX6_MULTITEX_TRIANGLE_CONTROL2 0x00000344 /* Parameters: stencil_fail stencil_zfail stencil_zpass */ +# define NV04_DX6_MULTITEX_TRIANGLE_FOG_COLOR 0x00000348 +# define NV04_DX6_MULTITEX_TRIANGLE_TLVERTEX_SX( d) (0x00000400 + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_TLVERTEX_SY( d) (0x00000404 + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_TLVERTEX_SZ( d) (0x00000408 + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_INV_W( d) (0x0000040c + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_COLOR( d) (0x00000410 + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_SPECULAR( d) (0x00000414 + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_TEXTURE0_S( d) (0x00000418 + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_TEXTURE0_T( d) (0x0000041c + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_TEXTURE1_S( d) (0x00000420 + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_TEXTURE1_T( d) (0x00000424 + d * 0x0028) +# define NV04_DX6_MULTITEX_TRIANGLE_DRAW 0x00000540 /* Parameters: v0 v1 v2 v3 v4 v5 */ + +/****************************************** +Object NV04_COLOR_KEY used on: NV04 NV10 NV15 NV20 NV40 +*/ +#define NV04_COLOR_KEY 0x00000057 +# define NV04_COLOR_KEY_SET_DMA_NOTIFY 0x00000180 +# define NV04_COLOR_KEY_FORMAT 0x00000300 +# define NV04_COLOR_KEY_VALUE 0x00000304 + +/****************************************** +Object NV04_SOLID_LINE used on: NV04 +*/ +#define NV04_SOLID_LINE 0x0000005c +# define NV04_SOLID_LINE_CLIP_RECTANGLE 0x00000184 +# define NV04_SOLID_LINE_PATTERN 0x00000188 +# define NV04_SOLID_LINE_ROP 0x0000018c +# define NV04_SOLID_LINE_SURFACE 0x00000198 +# define NV04_SOLID_LINE_OPERATION 0x000002fc +# define NV04_SOLID_LINE_COLOR_FORMAT 0x00000300 +# define NV04_SOLID_LINE_COLOR_VALUE 0x00000304 +# define NV04_SOLID_LINE_START 0x00000400 /* Parameters: x y */ +# define NV04_SOLID_LINE_END 0x00000400 /* Parameters: x y */ + +/****************************************** +Object NV04_UNK005E used on: NV04 +*/ +#define NV04_UNK005E 0x0000005e +# define NV04_UNK005E_SET_SURFACE 0x00000198 +# define NV04_UNK005E_UNK02fc 0x000002fc +# define NV04_UNK005E_UNK0300 0x00000300 +# define NV04_UNK005E_COUNTER 0x00000304 + +/****************************************** +Object NV05_SCALED_IMAGE_FROM_MEMORY used on: NV04 +*/ +#define NV05_SCALED_IMAGE_FROM_MEMORY 0x00000063 +# define NV05_SCALED_IMAGE_FROM_MEMORY_SURFACE 0x00000198 +# define NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION 0x000002fc +# define NV05_SCALED_IMAGE_FROM_MEMORY_OPERATION 0x00000304 + +/****************************************** +Object NV04_SCALED_IMAGE_FROM_MEMORY used on: NV04 +*/ +#define NV04_SCALED_IMAGE_FROM_MEMORY 0x00000077 +# define NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY 0x00000180 +# define NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE 0x00000184 +# define NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE 0x00000198 +# define NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT 0x00000300 +# define NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION 0x00000304 +# define NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POS 0x00000308 /* Parameters: x y */ +# define NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE 0x0000030c /* Parameters: width height */ +# define NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POS 0x00000310 /* Parameters: x y */ +# define NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE 0x00000314 /* Parameters: width height */ +# define NV04_SCALED_IMAGE_FROM_MEMORY_DU_DX 0x00000318 /* Parameters: int frac*0x100000 */ +# define NV04_SCALED_IMAGE_FROM_MEMORY_DV_DY 0x0000031c /* Parameters: int frac*0x100000 */ +# define NV04_SCALED_IMAGE_FROM_MEMORY_SIZE 0x00000400 /* Parameters: width height */ +# define NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT 0x00000404 /* Parameters: pitch origin filter */ +# define NV04_SCALED_IMAGE_FROM_MEMORY_OFFSET 0x00000408 +# define NV04_SCALED_IMAGE_FROM_MEMORY_POINT 0x0000040c /* Parameters: u_int u_frac*0x10 v_int v_frac*0x10 */ + +/****************************************** +Object NV_IMAGE_FROM_CPU used on: NV04 +*/ +#define NV_IMAGE_FROM_CPU 0x00000061 +# define NV_IMAGE_FROM_CPU_DMA_NOTIFY 0x00000180 +# define NV_IMAGE_FROM_CPU_CLIP_RECTANGLE 0x00000188 +# define NV_IMAGE_FROM_CPU_PATTERN 0x0000018c +# define NV_IMAGE_FROM_CPU_ROP 0x00000190 +# define NV_IMAGE_FROM_CPU_SURFACE 0x0000019c +# define NV_IMAGE_FROM_CPU_OPERATION 0x000002fc +# define NV_IMAGE_FROM_CPU_FORMAT 0x00000300 + +/****************************************** +Object NV05_IMAGE_FROM_CPU used on: NV04 +*/ +#define NV05_IMAGE_FROM_CPU 0x00000065 +# define NV05_IMAGE_FROM_CPU_DMA_NOTIFY 0x00000180 +# define NV05_IMAGE_FROM_CPU_CLIP_RECTANGLE 0x00000188 +# define NV05_IMAGE_FROM_CPU_PATTERN 0x0000018c +# define NV05_IMAGE_FROM_CPU_ROP 0x00000190 +# define NV05_IMAGE_FROM_CPU_SURFACE 0x0000019c +# define NV05_IMAGE_FROM_CPU_OPERATION 0x000002fc +# define NV05_IMAGE_FROM_CPU_FORMAT 0x00000300 +# define NV05_IMAGE_FROM_CPU_POINT 0x00000304 /* Parameters: x y */ +# define NV05_IMAGE_FROM_CPU_SIZE_OUT 0x00000308 /* Parameters: x y */ +# define NV05_IMAGE_FROM_CPU_SIZE_IN 0x0000030c /* Parameters: x y */ +# define NV05_IMAGE_FROM_CPU_COLOR( d) (0x00000400 + d * 0x0004) + +/****************************************** +Object NV_IMAGE_BLIT used on: NV04 NV10 NV15 NV20 NV40 +*/ +#define NV_IMAGE_BLIT 0x0000005f +# define NV_IMAGE_BLIT_DMA_NOTIFY 0x00000180 +# define NV_IMAGE_BLIT_COLOR_KEY 0x00000184 +# define NV_IMAGE_BLIT_CLIP_RECTANGLE 0x00000188 +# define NV_IMAGE_BLIT_PATTERN 0x0000018c +# define NV_IMAGE_BLIT_ROP5 0x00000190 +# define NV_IMAGE_BLIT_SURFACE 0x0000019c +# define NV_IMAGE_BLIT_OPERATION 0x000002fc +# define NV_IMAGE_BLIT_POINT_IN 0x00000300 /* Parameters: x y */ +# define NV_IMAGE_BLIT_POINT_OUT 0x00000304 /* Parameters: x y */ +# define NV_IMAGE_BLIT_SIZE 0x00000308 /* Parameters: width height */ + +/****************************************** +Object NV10_TCL_PRIMITIVE_3D used on: NV10 +*/ +#define NV10_TCL_PRIMITIVE_3D 0x00000056 + +/****************************************** +Object NV17_TCL_PRIMITIVE_3D used on: NV15 +*/ +#define NV17_TCL_PRIMITIVE_3D 0x00000099 + +/****************************************** +Object NV11_TCL_PRIMITIVE_3D used on: NV15 +*/ +#define NV11_TCL_PRIMITIVE_3D 0x00000096 +# define NV10_TCL_PRIMITIVE_3D_NOP 0x00000100 +# define NV10_TCL_PRIMITIVE_3D_NOTIFY 0x00000104 +# define NV10_TCL_PRIMITIVE_3D_SET_DMA_NOTIFY 0x00000180 +# define NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY0 0x00000184 +# define NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY1 0x00000188 +# define NV10_TCL_PRIMITIVE_3D_SET_DISPLAY_LIST 0x0000018c +# define NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY2 0x00000194 +# define NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY3 0x00000198 +# define NV17_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY4 0x000001ac +# define NV17_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY5 0x000001b0 +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ 0x00000200 /* Parameters: width x */ +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_VERT 0x00000204 /* Parameters: height y */ +# define NV10_TCL_PRIMITIVE_3D_BUFFER_FORMAT 0x00000208 /* Parameters: type color */ +# define NV10_TCL_PRIMITIVE_3D_BUFFER_PITCH 0x0000020c /* Parameters: depth/stencil buffer pitch color buffer pitch */ +# define NV10_TCL_PRIMITIVE_3D_COLOR_OFFSET 0x00000210 +# define NV10_TCL_PRIMITIVE_3D_DEPTH_OFFSET 0x00000214 +# define NV10_TCL_PRIMITIVE_3D_TX_OFFSET(d) (0x00000218 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_TX_FORMAT(d) (0x00000220 + d * 0x0004) /* Parameters: wrap_t wrap_s log2(height) log2(width) lod npot format cube_map */ +# define NV10_TCL_PRIMITIVE_3D_TX_ENABLE(d) (0x00000228 + d * 0x0004) /* Parameters: enable anisotropy */ +# define NV10_TCL_PRIMITIVE_3D_TX_NPOT_PITCH(d) (0x00000230 + d * 0x0004) /* Parameters: pitch */ +# define NV10_TCL_PRIMITIVE_3D_TX_NPOT_SIZE(d) (0x00000240 + d * 0x0004) /* Parameters: width height */ +# define NV10_TCL_PRIMITIVE_3D_TX_FILTER(d) (0x00000248 + d * 0x0004) /* Parameters: mag_filter min_filter */ +# define NV10_TCL_PRIMITIVE_3D_TX_PALETTE_OFFSET(d) (0x00000250 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_TX_MATRIX_ENABLE(d) (0x000003e0 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_TX_MATRIX(x,y) (0x00000540 + y * 0x0010 + x * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_RC_IN_ALPHA(d) (0x00000260 + d * 0x0004) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV10_TCL_PRIMITIVE_3D_RC_IN_RGB(d) (0x00000268 + d * 0x0004) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV10_TCL_PRIMITIVE_3D_RC_OUT_ALPHA(d) (0x00000278 + d * 0x0004) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */ +# define NV10_TCL_PRIMITIVE_3D_RC_OUT_RGB(d) (0x00000280 + d * 0x0004) /* Parameters: rc1_tx_units_enabled rc1_rc_enabled scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */ +# define NV10_TCL_PRIMITIVE_3D_RC_COLOR0 0x00000270 /* Parameters: a r g b */ +# define NV10_TCL_PRIMITIVE_3D_RC_COLOR1 0x00000274 /* Parameters: a r g b */ +# define NV10_TCL_PRIMITIVE_3D_RC_FINAL0 0x00000288 /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV10_TCL_PRIMITIVE_3D_RC_FINAL1 0x0000028c /* Parameters: vare_mapping vare_component_usage vare_input varf_mapping varf_component_usage varf_input varg_mapping varg_component_usage varg_input color_sum_clamp */ +# define NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL 0x00000294 /* Parameters: local_viewer color_control */ +# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_ENABLE 0x00000298 /* Parameters: specular diffuse ambient emission */ +# define NV10_TCL_PRIMITIVE_3D_FOG_MODE 0x0000029c +# define NV10_TCL_PRIMITIVE_3D_FOG_COORD_DIST 0x000002a0 +# define NV10_TCL_PRIMITIVE_3D_FOG_ENABLE 0x000002a4 +# define NV10_TCL_PRIMITIVE_3D_FOG_COLOR 0x000002a8 /* Parameters: a b g r */ +# define NV17_TCL_PRIMITIVE_3D_COLOR_MASK_ENABLE 0x000002bc +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(d) (0x000002c0 + d * 0x0004) /* Parameters: x2 x1 */ +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(d) (0x000002e0 + d * 0x0004) /* Parameters: y2 y1 */ +# define NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE 0x00000300 +# define NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE 0x00000304 +# define NV10_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE 0x00000308 +# define NV10_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE 0x0000030c +# define NV10_TCL_PRIMITIVE_3D_DITHER_ENABLE 0x00000310 +# define NV10_TCL_PRIMITIVE_3D_LIGHTING_ENABLE 0x00000314 +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE 0x00000318 +# define NV10_TCL_PRIMITIVE_3D_POINT_SMOOTH_ENABLE 0x0000031c +# define NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE 0x00000320 +# define NV10_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE 0x00000324 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_WEIGHT_ENABLE 0x00000328 +# define NV10_TCL_PRIMITIVE_3D_STENCIL_ENABLE 0x0000032c +# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000330 +# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000334 +# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000338 +# define NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC 0x0000033c +# define NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF 0x00000340 +# define NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC 0x00000344 +# define NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_DST 0x00000348 +# define NV10_TCL_PRIMITIVE_3D_BLEND_COLOR 0x0000034c /* Parameters: a r g b */ +# define NV10_TCL_PRIMITIVE_3D_BLEND_EQUATION 0x00000350 +# define NV10_TCL_PRIMITIVE_3D_DEPTH_FUNC 0x00000354 +# define NV10_TCL_PRIMITIVE_3D_COLOR_MASK 0x00000358 /* Parameters: a r g b */ +# define NV10_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE 0x0000035c +# define NV10_TCL_PRIMITIVE_3D_STENCIL_MASK 0x00000360 +# define NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC 0x00000364 +# define NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_REF 0x00000368 +# define NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_MASK 0x0000036c +# define NV10_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL 0x00000370 +# define NV10_TCL_PRIMITIVE_3D_STENCIL_OP_ZFAIL 0x00000374 +# define NV10_TCL_PRIMITIVE_3D_STENCIL_OP_ZPASS 0x00000378 +# define NV10_TCL_PRIMITIVE_3D_SHADE_MODEL 0x0000037c +# define NV10_TCL_PRIMITIVE_3D_LINE_WIDTH 0x00000380 +# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR 0x00000384 +# define NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS 0x00000388 +# define NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT 0x0000038c +# define NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK 0x00000390 +# define NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR 0x00000394 +# define NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_FAR 0x00000398 +# define NV10_TCL_PRIMITIVE_3D_CULL_FACE 0x0000039c +# define NV10_TCL_PRIMITIVE_3D_FRONT_FACE 0x000003a0 +# define NV10_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE 0x000003a4 +# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_R 0x000003a8 +# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_G 0x000003ac +# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_B 0x000003b0 +# define NV10_TCL_PRIMITIVE_3D_COLOR_MATERIAL_A 0x000003b4 +# define NV10_TCL_PRIMITIVE_3D_COLOR_CONTROL 0x000003b8 /* Parameters: color_control */ +# define NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS 0x000003bc /* Parameters: light 7 light 6 light 5 light 4 light 3 light 2 light 1 light 0 */ +# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE( d) (0x000003c0 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_VIEW_MATRIX_ENABLE 0x000003e8 /* Parameters: projection modelview0 modelview1 */ +# define NV10_TCL_PRIMITIVE_3D_POINT_SIZE 0x000003ec +# define NV10_TCL_PRIMITIVE_3D_MODELVIEW0_MATRIX( d) (0x00000400 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_MODELVIEW1_MATRIX( d) (0x00000440 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_INVERSE_MODELVIEW0_MATRIX( d) (0x00000480 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_INVERSE_MODELVIEW1_MATRIX( d) (0x000004c0 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_PROJECTION_MATRIX( d) (0x00000500 + d * 0x0004) +# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_A(d) (0x00000600 + d * 0x0010) +# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_B(d) (0x00000604 + d * 0x0010) +# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_C(d) (0x00000608 + d * 0x0010) +# define NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_D(d) (0x0000060c + d * 0x0010) +# define NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT 0x00000680 +# define NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR 0x00000684 +# define NV10_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC 0x00000688 +# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_A 0x000006a0 +# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_B 0x000006a4 +# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_C 0x000006a8 +# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_D 0x000006ac +# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_E 0x000006b0 +# define NV10_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_F 0x000006b4 +# define NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x000006c4 +# define NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x000006c8 +# define NV10_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x000006cc +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_X 0x000006e8 +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_Y 0x000006ec +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_Z 0x000006f0 +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_W 0x000006f4 +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_A 0x000006f8 +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_B 0x000006fc +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_C 0x00000700 +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_D 0x00000704 +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_E 0x00000708 +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_F 0x0000070c +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_G 0x00000710 +# define NV10_TCL_PRIMITIVE_3D_POINT_PARAMETER_H 0x00000714 +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(d) (0x00000800 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(d) (0x00000804 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(d) (0x00000808 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(d) (0x0000080c + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(d) (0x00000810 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(d) (0x00000814 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(d) (0x00000818 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(d) (0x0000081c + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(d) (0x00000820 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_X(d) (0x00000828 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Y(d) (0x0000082c + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Z(d) (0x00000830 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_X(d) (0x00000834 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Y(d) (0x00000838 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Z(d) (0x0000083c + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(d) (0x00000840 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_EXPONENT(d) (0x00000844 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_B(d) (0x00000848 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(d) (0x0000084c + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Y(d) (0x00000850 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Z(d) (0x00000854 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_C(d) (0x00000858 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(d) (0x0000085c + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_Y(d) (0x00000860 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_Z(d) (0x00000864 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(d) (0x00000868 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(d) (0x0000086c + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(d) (0x00000870 + d * 0x0080) +# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X 0x00000c00 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Y 0x00000c04 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Z 0x00000c08 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_4F_X 0x00000c18 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Y 0x00000c1c +# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Z 0x00000c20 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_POS_4F_W 0x00000c24 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X 0x00000c30 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Y 0x00000c34 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Z 0x00000c38 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_XY 0x00000c40 /* Parameters: y x */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_Z 0x00000c44 /* Parameters: z */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R 0x00000c50 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_G 0x00000c54 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_B 0x00000c58 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4F_A 0x00000c5c +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_3F_R 0x00000c60 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_3F_G 0x00000c64 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_3F_B 0x00000c68 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL_4I 0x00000c6c /* Parameters: a b g r */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R 0x00000c80 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_G 0x00000c84 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_B 0x00000c88 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_COL2_3I 0x00000c8c /* Parameters: a b g r */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S 0x00000c90 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_T 0x00000c94 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_2I 0x00000c98 /* Parameters: t s */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S 0x00000ca0 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_T 0x00000ca4 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_R 0x00000ca8 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_Q 0x00000cac +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_ST 0x00000cb0 /* Parameters: t s */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_RQ 0x00000cb4 /* Parameters: q r */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S 0x00000cb8 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_T 0x00000cbc +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_2I 0x00000cc0 /* Parameters: t s */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S 0x00000cc8 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_T 0x00000ccc +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_R 0x00000cd0 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_Q 0x00000cd4 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_ST 0x00000cd8 /* Parameters: t s */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_RQ 0x00000cdc /* Parameters: q r */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_FOG_1F 0x00000ce0 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_WGH_1F 0x00000ce4 +# define NV10_TCL_PRIMITIVE_3D_EDGEFLAG_ENABLE 0x00000cec +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ATTR( d) (0x00000d04 + d * 0x0008) /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_VALIDATE 0x00000cf0 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_POS 0x00000d00 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_POS 0x00000d04 /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_COL 0x00000d08 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_COL 0x00000d0c /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_COL2 0x00000d10 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_COL2 0x00000d14 /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_TX0 0x00000d18 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_TX0 0x00000d1c /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_TX1 0x00000d20 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_TX1 0x00000d24 /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_NOR 0x00000d28 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_NOR 0x00000d2c /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_WGH 0x00000d30 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_WGH 0x00000d34 /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_OFFSET_FOG 0x00000d38 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_FORMAT_FOG 0x00000d3c /* Parameters: stride fields type */ +# define NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE 0x00000d40 +# define NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP 0x00000d44 +# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH 0x00000d5c /* Parameters: pitch */ +# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_OFFSET 0x00000d60 +# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_FILL_VALUE 0x00000d68 +# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_CLEAR_ENABLE 0x00000d6c +# define NV10_TCL_PRIMITIVE_3D_BEGIN_END 0x00000dfc +# define NV10_TCL_PRIMITIVE_3D_INDEX_DATA 0x00000e00 /* Parameters: index1 index0 */ +# define NV10_TCL_PRIMITIVE_3D_VERTEX_BUFFER_BEGIN_END 0x000013fc +# define NV10_TCL_PRIMITIVE_3D_VERTEX_BUFFER_DRAW_ARRAYS 0x00001400 /* Parameters: count-1 first */ +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_X 0x00001638 +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_Y 0x0000163c +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_Z 0x00001640 +# define NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_W 0x00001644 +# define NV17_TCL_PRIMITIVE_3D_LMA_DEPTH_ENABLE 0x00001658 +# define NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_DATA 0x00001800 + +/****************************************** +Object NV10_IMAGE_FROM_CPU used on: NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV10_IMAGE_FROM_CPU 0x0000008a +# define NV10_IMAGE_FROM_CPU_SET_DMA_NOTIFY 0x00000180 +# define NV10_IMAGE_FROM_CPU_SET_CONTEXT_CLIP_RECTANGLE 0x00000188 +# define NV10_IMAGE_FROM_CPU_SET_IMAGE_PATTERN 0x0000018c +# define NV10_IMAGE_FROM_CPU_SET_RASTER_OP 0x00000190 +# define NV10_IMAGE_FROM_CPU_SET_CONTEXT_SURFACES_2D 0x0000019c +# define NV10_IMAGE_FROM_CPU_OPERATION 0x000002fc +# define NV10_IMAGE_FROM_CPU_FORMAT 0x00000300 +# define NV10_IMAGE_FROM_CPU_POINT 0x00000304 /* Parameters: x y */ +# define NV10_IMAGE_FROM_CPU_SIZE_OUT 0x00000308 /* Parameters: width height */ +# define NV10_IMAGE_FROM_CPU_SIZE_IN 0x0000030c /* Parameters: width height */ +# define NV10_IMAGE_FROM_CPU_HLINE 0x00000400 + +/****************************************** +Object NV10_PRIMITIVE_2D used on: NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV10_PRIMITIVE_2D 0x0000007b +# define NV10_PRIMITIVE_2D_SET_DMA_NOTIFY 0x00000180 +# define NV10_PRIMITIVE_2D_SET_SURFACE 0x00000184 +# define NV10_PRIMITIVE_2D_SET_FORMAT 0x00000300 +# define NV10_PRIMITIVE_2D_SET_POINT 0x00000304 /* Parameters: x y */ +# define NV10_PRIMITIVE_2D_SET_SIZE 0x00000308 /* Parameters: width height */ +# define NV10_PRIMITIVE_2D_SET_CLIP_HORIZ 0x0000030c /* Parameters: width x */ +# define NV10_PRIMITIVE_2D_SET_CLIP_VERT 0x00000310 /* Parameters: height y */ +# define NV10_PRIMITIVE_2D_SET_DATA( d) (0x00000400 + d * 0x0004) + +/****************************************** +Object NV10_IMAGE_BLIT used on: NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV10_IMAGE_BLIT 0x0000009f +# define NV10_IMAGE_BLIT_NOP 0x00000100 +# define NV10_IMAGE_BLIT_NOTIFY 0x00000104 +# define NV10_IMAGE_BLIT_SET_DMA_NOTIFY 0x00000180 +# define NV10_IMAGE_BLIT_SET_CONTEXT_CLIP_RECTANGLE 0x00000188 +# define NV10_IMAGE_BLIT_SET_IMAGE_PATTERN 0x0000018c +# define NV10_IMAGE_BLIT_SET_RASTER_OP 0x00000190 +# define NV10_IMAGE_BLIT_SET_CONTEXT_SURFACES_2D 0x0000019c +# define NV10_IMAGE_BLIT_SET_OPERATION 0x000002fc +# define NV10_IMAGE_BLIT_SET_POINT 0x00000300 /* Parameters: x y */ +# define NV10_IMAGE_BLIT_SET_PITCH 0x00000304 /* Parameters: skip */ +# define NV10_IMAGE_BLIT_SET_SIZE 0x00000308 /* Parameters: width height */ + +/****************************************** +Object NV10_VIDEO_DISPLAY used on: NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV10_VIDEO_DISPLAY 0x0000007c +# define NV10_VIDEO_DISPLAY_COUNTER 0x00000050 +# define NV10_VIDEO_DISPLAY_SET_DMA_FROM_MEMORY 0x00000180 +# define NV10_VIDEO_DISPLAY_SET_DMA_IN_MEMORY0 0x00000184 +# define NV10_VIDEO_DISPLAY_SET_DMA_IN_MEMORY1 0x00000188 +# define NV10_VIDEO_DISPLAY_SET_OBJECT3 0x0000019c +# define NV10_VIDEO_DISPLAY_SIZE 0x000002f8 /* Parameters: height width */ +# define NV10_VIDEO_DISPLAY_OFFSET 0x00000300 + +/****************************************** +Object NV10_UNK0072 used on: NV10 NV15 NV20 NV40 G70 +*/ +#define NV10_UNK0072 0x00000072 +# define NV10_UNK0072_COUNTER 0x00000050 +# define NV40_UNK0072_SET_OBJECT 0x00000060 +# define NV10_UNK0072_SET_DMA_NOTIFY 0x00000180 + +/****************************************** +Object NV10_SCALED_IMAGE_FROM_MEMORY used on: NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV10_SCALED_IMAGE_FROM_MEMORY 0x00000089 +# define NV10_SCALED_IMAGE_FROM_MEMORY_COUNTER 0x00000050 +# define NV10_SCALED_IMAGE_FROM_MEMORY_SET_DMA_IN_MEMORY 0x00000184 +# define NV10_SCALED_IMAGE_FROM_MEMORY_SET_RASTER_OP 0x0000018c +# define NV10_SCALED_IMAGE_FROM_MEMORY_SET_IMAGE_PATTERN 0x00000188 +# define NV10_SCALED_IMAGE_FROM_MEMORY_SET_SURFACE 0x00000198 +# define NV10_SCALED_IMAGE_FROM_MEMORY_OPERATION 0x00000304 +# define NV10_SCALED_IMAGE_FROM_MEMORY_CLIP_POS 0x00000308 /* Parameters: x y */ +# define NV10_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE 0x0000030c /* Parameters: width height */ +# define NV10_SCALED_IMAGE_FROM_MEMORY_OUT_POS 0x00000310 /* Parameters: x y */ +# define NV10_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE 0x00000314 /* Parameters: width height */ +# define NV10_SCALED_IMAGE_FROM_MEMORY_SIZE 0x00000400 /* Parameters: width height */ +# define NV10_SCALED_IMAGE_FROM_MEMORY_FORMAT 0x00000404 /* Parameters: pitch */ +# define NV10_SCALED_IMAGE_FROM_MEMORY_OFFSET 0x00000408 +# define NV10_SCALED_IMAGE_FROM_MEMORY_POINT 0x0000040c /* Parameters: u_int u_frac*0x10 v_int v_frac*0x10 */ + +/****************************************** +Object NV10_CONTEXT_SURFACES_2D used on: NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV10_CONTEXT_SURFACES_2D 0x00000062 +# define NV10_CONTEXT_SURFACES_2D_SET_DMA_NOTIFY 0x00000180 +# define NV10_CONTEXT_SURFACES_2D_SET_DMA_IN_MEMORY0 0x00000184 +# define NV10_CONTEXT_SURFACES_2D_SET_DMA_IN_MEMORY1 0x00000188 +# define NV10_CONTEXT_SURFACES_2D_FORMAT 0x00000300 /* Parameters: color type width height */ +# define NV10_CONTEXT_SURFACES_2D_PITCH 0x00000304 /* Parameters: src dst */ +# define NV10_CONTEXT_SURFACES_2D_OFFSET_SRC 0x00000308 +# define NV10_CONTEXT_SURFACES_2D_OFFSET_DST 0x0000030c + +/****************************************** +Object NV04_CONTEXT_SURFACES_2D used on: NV04 NV10 NV15 +*/ +#define NV04_CONTEXT_SURFACES_2D 0x00000042 +# define NV04_CONTEXT_SURFACES_2D_NOTIFY 0x00000104 +# define NV04_CONTEXT_SURFACES_2D_SET_DMA_NOTIFY 0x00000180 +# define NV04_CONTEXT_SURFACES_2D_SET_DMA_IMAGE_SRC 0x00000184 +# define NV04_CONTEXT_SURFACES_2D_SET_DMA_IMAGE_DST 0x00000188 +# define NV04_CONTEXT_SURFACES_2D_FORMAT 0x00000300 +# define NV04_CONTEXT_SURFACES_2D_PITCH 0x00000304 /* Parameters: src dst */ +# define NV04_CONTEXT_SURFACES_2D_OFFSET_SRC 0x00000308 +# define NV04_CONTEXT_SURFACES_2D_OFFSET_DST 0x0000030c + +/****************************************** +Object NV04_IMAGE_PATTERN used on: NV04 NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV04_IMAGE_PATTERN 0x00000044 +# define NV04_IMAGE_PATTERN_COLOR_FORMAT 0x00000300 +# define NV04_IMAGE_PATTERN_MONO_FORMAT 0x00000304 +# define NV04_IMAGE_PATTERN_SELECT 0x0000030c +# define NV04_IMAGE_PATTERN_MONOCHROME_SHAPE 0x00000308 +# define NV04_IMAGE_PATTERN_MONOCHROME_COLOR0 0x00000310 +# define NV04_IMAGE_PATTERN_MONOCHROME_COLOR1 0x00000314 +# define NV04_IMAGE_PATTERN_MONOCHROME_PATTERN0 0x00000318 +# define NV04_IMAGE_PATTERN_MONOCHROME_PATTERN1 0x0000031c + +/****************************************** +Object NV20_SWIZZLED_SURFACE used on: NV20 NV30 NV40 G70 +*/ +#define NV20_SWIZZLED_SURFACE 0x0000009e +# define NV20_SWIZZLED_SURFACE_SET_OBJECT0 0x00000180 +# define NV20_SWIZZLED_SURFACE_SET_OBJECT1 0x00000184 +# define NV20_SWIZZLED_SURFACE_FORMAT 0x00000300 /* Parameters: log2(height) log2(width) color */ +# define NV20_SWIZZLED_SURFACE_OFFSET 0x00000304 + +/****************************************** +Object NV20_TCL_PRIMITIVE_3D used on: NV20 +*/ +#define NV20_TCL_PRIMITIVE_3D 0x00000097 +# define NV20_TCL_PRIMITIVE_3D_NOP 0x00000100 +# define NV20_TCL_PRIMITIVE_3D_NOTIFY 0x00000104 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT0 0x00000180 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT1 0x00000184 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT2 0x00000188 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT3 0x00000194 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT4 0x00000198 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT5 0x0000019c +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT6 0x000001a0 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT7 0x000001a4 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT8 0x000001a8 +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT9 0x000001ac +# define NV20_TCL_PRIMITIVE_3D_SET_OBJECT10 0x000001b0 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ 0x00000200 /* Parameters: width x */ +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_VERT 0x00000204 /* Parameters: height y */ +# define NV20_TCL_PRIMITIVE_3D_BUFFER_FORMAT 0x00000208 /* Parameters: type color */ +# define NV20_TCL_PRIMITIVE_3D_BUFFER_PITCH 0x0000020c /* Parameters: depth/stencil buffer pitch color buffer pitch */ +# define NV20_TCL_PRIMITIVE_3D_COLOR_OFFSET 0x00000210 +# define NV20_TCL_PRIMITIVE_3D_DEPTH_OFFSET 0x00000214 +# define NV20_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH 0x0000022c /* Parameters: pitch */ +# define NV20_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_OFFSET 0x00000230 +# define NV20_TCL_PRIMITIVE_3D_LIGHT_CONTROL 0x00000294 +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_CONTROL 0x00000298 /* Parameters: back_specular back_ambient back_diffuse back_emission front_specular front_ambient front_diffuse front_emission */ +# define NV20_TCL_PRIMITIVE_3D_FOG_MODE 0x0000029c +# define NV20_TCL_PRIMITIVE_3D_FOG_COORD_DIST 0x000002a0 +# define NV20_TCL_PRIMITIVE_3D_FOG_ENABLE 0x000002a4 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(d) (0x000002c0 + d * 0x0004) /* Parameters: x2 x1 */ +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(d) (0x000002e0 + d * 0x0004) /* Parameters: y2 y1 */ +# define NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE 0x00000300 +# define NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE 0x00000304 +# define NV20_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE 0x00000308 +# define NV20_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE 0x0000030c +# define NV20_TCL_PRIMITIVE_3D_DITHER_ENABLE 0x00000310 +# define NV20_TCL_PRIMITIVE_3D_LIGHTING_ENABLE 0x00000314 +# define NV20_TCL_PRIMITIVE_3D_POINT_SMOOTH_ENABLE 0x0000031c +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE 0x00000318 +# define NV20_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE 0x00000320 +# define NV20_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE 0x00000324 +# define NV20_TCL_PRIMITIVE_3D_STENCIL_ENABLE 0x0000032c +# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000330 +# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000334 +# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000338 +# define NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC 0x0000033c +# define NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF 0x00000340 +# define NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC 0x00000344 +# define NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_DST 0x00000348 +# define NV20_TCL_PRIMITIVE_3D_BLEND_COLOR 0x0000034c /* Parameters: a r g b */ +# define NV20_TCL_PRIMITIVE_3D_BLEND_EQUATION 0x00000350 +# define NV20_TCL_PRIMITIVE_3D_DEPTH_FUNC 0x00000354 +# define NV20_TCL_PRIMITIVE_3D_COLOR_MASK 0x00000358 /* Parameters: a r g b */ +# define NV20_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE 0x0000035c +# define NV20_TCL_PRIMITIVE_3D_STENCIL_MASK 0x00000360 +# define NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC 0x00000364 +# define NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_REF 0x00000368 +# define NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_MASK 0x0000036c +# define NV20_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL 0x00000370 +# define NV20_TCL_PRIMITIVE_3D_STENCIL_OP_ZFAIL 0x00000374 +# define NV20_TCL_PRIMITIVE_3D_STENCIL_OP_ZPASS 0x00000378 +# define NV20_TCL_PRIMITIVE_3D_SHADE_MODEL 0x0000037c +# define NV20_TCL_PRIMITIVE_3D_LINE_WIDTH 0x00000380 +# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR 0x00000384 +# define NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS 0x00000388 +# define NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT 0x0000038c +# define NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK 0x00000390 +# define NV20_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR 0x00000394 +# define NV20_TCL_PRIMITIVE_3D_DEPTH_RANGE_FAR 0x00000398 +# define NV20_TCL_PRIMITIVE_3D_CULL_FACE 0x0000039c +# define NV20_TCL_PRIMITIVE_3D_FRONT_FACE 0x000003a0 +# define NV20_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE 0x000003a4 +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_R 0x000003a8 +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_G 0x000003ac +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_B 0x000003b0 +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_A 0x000003b4 +# define NV20_TCL_PRIMITIVE_3D_SEPARATE_SPECULAR_ENABLE 0x000003b8 +# define NV20_TCL_PRIMITIVE_3D_ENABLED_LIGHTS 0x000003bc /* Parameters: light 7 light 6 light 5 light 4 light 3 light 2 light 1 light 0 */ +# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(d) (0x000003c0 + d * 0x0004) +# define NV20_TCL_PRIMITIVE_3D_TX_MATRIX_ENABLE(d) (0x00000420 + d * 0x0004) +# define NV20_TCL_PRIMITIVE_3D_POINT_SIZE 0x0000043c +# define NV20_TCL_PRIMITIVE_3D_MODELVIEW_MATRIX( d) (0x00000480 + d * 0x0004) +# define NV20_TCL_PRIMITIVE_3D_INVERSE_MODELVIEW_MATRIX( d) (0x00000580 + d * 0x0004) +# define NV20_TCL_PRIMITIVE_3D_PROJECTION_MATRIX( d) (0x00000680 + d * 0x0004) +# define NV20_TCL_PRIMITIVE_3D_TX_MATRIX(x,y) (0x000006c0 + y * 0x0010 + x * 0x0004) +# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_A(d) (0x00000840 + d * 0x0010) +# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_B(d) (0x00000844 + d * 0x0010) +# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_C(d) (0x00000848 + d * 0x0010) +# define NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_D(d) (0x0000084c + d * 0x0010) +# define NV20_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT 0x000009c0 +# define NV20_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR 0x000009c4 +# define NV20_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC 0x000009c8 +# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_A 0x000009e0 +# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_B 0x000009e4 +# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_C 0x000009e8 +# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_D 0x000009ec +# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_E 0x000009f0 +# define NV20_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_F 0x000009f4 +# define NV20_TCL_PRIMITIVE_3D_POINT_SPRITE 0x00000a1c /* Parameters: coord_replace r_mode enable */ +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_OX 0x00000a20 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_OY 0x00000a24 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_DEPTH_AVG_S 0x00000a28 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_UNKNOWN_A 0x00000a2c +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_A 0x00000a30 +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_B 0x00000a34 +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_C 0x00000a38 +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_D 0x00000a3c +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_E 0x00000a40 +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_F 0x00000a44 +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_G 0x00000a48 +# define NV20_TCL_PRIMITIVE_3D_POINT_PARAMETER_H 0x00000a4c +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_PX_DIV2 0x00000af0 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_PY_DIV2 0x00000af4 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_DEPTH_HALF_S 0x00000af8 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_UNKNOWN_B 0x00000afc +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0 0x00000b00 +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST1 0x00000b04 +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST2 0x00000b08 +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST3 0x00000b0c +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_X 0x00000b80 +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_Y 0x00000b84 +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_Z 0x00000b88 +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_W 0x00000b8c +# define NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID 0x00001ea4 +# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x00000a10 +# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x00000a14 +# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x00000a18 +# define NV20_TCL_PRIMITIVE_3D_TX_OFFSET(d) (0x00001b00 + d * 0x0040) +# define NV20_TCL_PRIMITIVE_3D_TX_FORMAT(d) (0x00001b04 + d * 0x0040) /* Parameters: log2(height) log2(width) lod format cube_map */ +# define NV20_TCL_PRIMITIVE_3D_TX_WRAP(d) (0x00001b08 + d * 0x0040) /* Parameters: wrap_s wrap_t wrap_r */ +# define NV20_TCL_PRIMITIVE_3D_TX_ENABLE(d) (0x00001b0c + d * 0x0040) /* Parameters: enable anisotropy */ +# define NV20_TCL_PRIMITIVE_3D_TX_NPOT_PITCH(d) (0x00001b10 + d * 0x0040) /* Parameters: pitch */ +# define NV20_TCL_PRIMITIVE_3D_TX_FILTER(d) (0x00001b14 + d * 0x0040) /* Parameters: mag_filter min_filter */ +# define NV20_TCL_PRIMITIVE_3D_TX_NPOT_SIZE(d) (0x00001b1c + d * 0x0040) /* Parameters: width height */ +# define NV20_TCL_PRIMITIVE_3D_TX_PALETTE_OFFSET(d) (0x00001b20 + d * 0x0040) +# define NV20_TCL_PRIMITIVE_3D_RC_ENABLE 0x00001e60 /* Parameters: number of rc enabled */ +# define NV20_TCL_PRIMITIVE_3D_TX_SHADER_OP 0x00001e70 /* Parameters: op0 op1 op2 op3 */ +# define NV20_TCL_PRIMITIVE_3D_TX_SHADER_CULL_MODE 0x000017f8 /* Parameters: cull0 cull1 cull2 cull3 */ +# define NV20_TCL_PRIMITIVE_3D_TX_SHADER_PREVIOUS 0x00001e78 /* Parameters: prev2 prev3 */ +# define NV20_TCL_PRIMITIVE_3D_RC_COLOR0 0x00001e20 /* Parameters: a r g b */ +# define NV20_TCL_PRIMITIVE_3D_RC_COLOR1 0x00001e24 /* Parameters: a r g b */ +# define NV20_TCL_PRIMITIVE_3D_RC_FINAL0 0x00000288 /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV20_TCL_PRIMITIVE_3D_RC_FINAL1 0x0000028c /* Parameters: vare_mapping vare_component_usage vare_input varf_mapping varf_component_usage varf_input varg_mapping varg_component_usage varg_input color_sum_clamp */ +# define NV20_TCL_PRIMITIVE_3D_RC_IN_ALPHA(d) (0x00000260 + d * 0x0004) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV20_TCL_PRIMITIVE_3D_RC_IN_RGB(d) (0x00000ac0 + d * 0x0004) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV20_TCL_PRIMITIVE_3D_RC_CONSTANT_COLOR0(d) (0x00000a60 + d * 0x0004) /* Parameters: a r g b */ +# define NV20_TCL_PRIMITIVE_3D_RC_CONSTANT_COLOR1(d) (0x00000a80 + d * 0x0004) /* Parameters: a r g b */ +# define NV20_TCL_PRIMITIVE_3D_RC_OUT_ALPHA(d) (0x00000aa0 + d * 0x0004) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */ +# define NV20_TCL_PRIMITIVE_3D_RC_OUT_RGB(d) (0x00001e40 + d * 0x0004) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */ +# define NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(d) (0x0000105c + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_Y(d) (0x00001060 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_Z(d) (0x00001064 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_X(d) (0x00001028 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Y(d) (0x0000102c + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Z(d) (0x00001030 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_X(d) (0x00001034 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Y(d) (0x00001038 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Z(d) (0x0000103c + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(d) (0x00001000 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(d) (0x00001004 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(d) (0x00001008 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(d) (0x0000100c + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(d) (0x00001010 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(d) (0x00001014 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(d) (0x00001018 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(d) (0x0000101c + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(d) (0x00001020 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_BACK_SIDE_PRODUCT_AMBIENT(d) (0x00000c00 + d * 0x0040) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_BACK_SIDE_PRODUCT_DIFFUSE(d) (0x00000c0c + d * 0x0040) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_BACK_SIDE_PRODUCT_SPECULAR(d) (0x00000c18 + d * 0x0040) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(d) (0x00001068 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(d) (0x0000106c + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(d) (0x00001070 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(d) (0x00001040 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_EXPONENT(d) (0x00001044 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_B(d) (0x00001048 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(d) (0x0000104c + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Y(d) (0x00001050 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Z(d) (0x00001054 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_C(d) (0x00001058 + d * 0x0080) +# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_A 0x00001e28 +# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_B 0x00001e2c +# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_C 0x00001e30 +# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_D 0x00001e34 +# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_E 0x00001e38 +# define NV20_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_F 0x00001e3c +# define NV20_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE 0x0000147c +# define NV20_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(d) (0x00001480 + d * 0x0004) +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X 0x00001500 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Y 0x00001504 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Z 0x00001508 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4F_X 0x00001518 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Y 0x0000151c +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Z 0x00001520 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4F_W 0x00001524 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4I_XY 0x00001528 /* Parameters: y x */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_POS_4I_ZW 0x0000152c /* Parameters: w z */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X 0x00001530 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Y 0x00001534 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Z 0x00001538 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_XY 0x00001540 /* Parameters: y x */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_Z 0x00001544 /* Parameters: z */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R 0x00001550 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4F_G 0x00001554 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4F_B 0x00001558 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4F_A 0x0000155c +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_3F_R 0x00001560 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_3F_G 0x00001564 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_3F_B 0x00001568 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL_4I 0x0000156c /* Parameters: a b g r */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R 0x00001580 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_G 0x00001584 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_B 0x00001588 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_COL2_3I 0x0000158c /* Parameters: a b g r */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S 0x00001590 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_T 0x00001594 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_2I 0x00001598 /* Parameters: t s */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S 0x000015a0 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_T 0x000015a4 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_R 0x000015a8 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_Q 0x000015ac +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_ST 0x000015b0 /* Parameters: t s */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_RQ 0x000015b4 /* Parameters: q r */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S 0x000015b8 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_T 0x000015bc +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_2I 0x000015c0 /* Parameters: t s */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S 0x000015c8 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_T 0x000015cc +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_R 0x000015d0 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_Q 0x000015d4 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_ST 0x000015d8 /* Parameters: t s */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_RQ 0x000015dc /* Parameters: q r */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_S 0x000015e0 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_T 0x000015e4 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_2I 0x000015e8 /* Parameters: t s */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_S 0x000015f0 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_T 0x000015f4 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_R 0x000015f8 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_Q 0x000015fc +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_ST 0x00001600 /* Parameters: t s */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_RQ 0x00001604 /* Parameters: q r */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_S 0x00001608 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_T 0x0000160c +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_2I 0x00001610 /* Parameters: t s */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_S 0x00001620 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_T 0x00001624 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_R 0x00001628 +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_Q 0x0000162c +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_ST 0x00001630 /* Parameters: t s */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_RQ 0x00001634 /* Parameters: q r */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_FOG_1F 0x00001698 +# define NV20_TCL_PRIMITIVE_3D_EDGE_FLAG 0x000016bc +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR0_POS 0x00001720 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR1_WGH 0x00001724 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR2_NOR 0x00001728 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR3_COL 0x0000172c /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR4_COL2 0x00001730 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR5_FOG 0x00001734 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR6 0x00001738 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR7 0x0000173c /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR8_TX0 0x00001740 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR9_TX1 0x00001744 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR10_TX2 0x00001748 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR11_TX3 0x0000174c /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR12_TX4 0x00001750 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR13_TX5 0x00001754 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR14_TX6 0x00001758 /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VB_POINTER_ATTR15_TX7 0x0000175c /* Parameters: enabled? offset */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR( d) (0x00001760 + d * 0x0004) +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR0_POS 0x00001760 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR1_WGH 0x00001764 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR2_NOR 0x00001768 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR3_COL 0x0000176c /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR4_COL2 0x00001770 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR5_FOG 0x00001774 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR6 0x00001778 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR7 0x0000177c /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR8_TX0 0x00001780 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR9_TX1 0x00001784 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR10_TX2 0x00001788 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR11_TX3 0x0000178c /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR12_TX4 0x00001790 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR13_TX5 0x00001794 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR14_TX6 0x00001798 /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR15_TX7 0x0000179c /* Parameters: stride fields type */ +# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x000017a0 +# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x000017a4 +# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x000017a8 +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_A 0x000017ac +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_R 0x000017b0 +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_G 0x000017b4 +# define NV20_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_B 0x000017b8 +# define NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE 0x000017bc +# define NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP 0x000017c0 +# define NV20_TCL_PRIMITIVE_3D_LIGHT_MODEL_TWO_SIDE_ENABLE 0x000017c4 +# define NV20_TCL_PRIMITIVE_3D_BEGIN_END 0x000017fc +# define NV20_TCL_PRIMITIVE_3D_SCISSOR_X2_X1 0x00001c30 /* Parameters: x2 x1 */ +# define NV20_TCL_PRIMITIVE_3D_SCISSOR_Y2_Y1 0x00001c50 /* Parameters: y2 y1 */ +# define NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH 0x00001d8c +# define NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB 0x00001d90 +# define NV20_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS 0x00001d94 /* Parameters: clear color a clear color b clear color g clear color r clear depth clear stencil */ +# define NV20_TCL_PRIMITIVE_3D_INDEX_DATA 0x00001800 /* Parameters: index1 index0 */ +# define NV20_TCL_PRIMITIVE_3D_VB_VERTEX_BATCH 0x00001810 /* Parameters: count_vertices offset_vertices */ +# define NV20_TCL_PRIMITIVE_3D_VERTEX_DATA 0x00001818 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_X 0x00001f00 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_Y 0x00001f04 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_Z 0x00001f08 +# define NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_W 0x00001f0c + +/****************************************** +Object NV30_TCL_PRIMITIVE_3D used on: NV30 NV40 G70 +*/ +#define NV30_TCL_PRIMITIVE_3D 0x00000097 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT0 0x00000180 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT1 0x00000184 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT2 0x00000188 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT3 0x0000018c +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT4 0x00000194 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT5 0x00000198 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT6 0x000001a4 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT7 0x000001a8 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT8 0x000001ac +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT9 0x000001b4 +# define NV30_TCL_PRIMITIVE_3D_SET_OBJECT10 0x000001b8 +# define NV30_TCL_PRIMITIVE_3D_SET_VB_SRC0_OBJECT 0x0000019c +# define NV30_TCL_PRIMITIVE_3D_SET_VB_SRC1_OBJECT 0x000001a0 +# define NV30_TCL_PRIMITIVE_3D_BUFFER0_PITCH 0x0000020c /* Parameters: depth/stencil buffer pitch color0 buffer pitch */ +# define NV30_TCL_PRIMITIVE_3D_COLOR0_OFFSET 0x00000210 +# define NV30_TCL_PRIMITIVE_3D_DEPTH_OFFSET 0x00000214 +# define NV30_TCL_PRIMITIVE_3D_COLOR1_OFFSET 0x00000218 +# define NV30_TCL_PRIMITIVE_3D_BUFFER1_PITCH 0x0000021c /* Parameters: color1 buffer pitch */ +# define NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH 0x0000022c /* Parameters: pitch */ +# define NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_OFFSET 0x00000230 +# define NV30_TCL_PRIMITIVE_3D_TX_MATRIX_ENABLE(d) (0x00000240 + d * 0x0004) +# define NV30_TCL_PRIMITIVE_3D_BUFFER2_PITCH 0x00000280 +# define NV30_TCL_PRIMITIVE_3D_BUFFER3_PITCH 0x00000284 +# define NV30_TCL_PRIMITIVE_3D_BUFFER2_OFFSET 0x00000288 +# define NV30_TCL_PRIMITIVE_3D_BUFFER3_OFFSET 0x0000028c +# define NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE 0x00000300 +# define NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE 0x00000304 +# define NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC 0x00000308 +# define NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF 0x0000030c +# define NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE 0x00000310 +# define NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC 0x00000314 +# define NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_DST 0x00000318 +# define NV30_TCL_PRIMITIVE_3D_BLEND_COLOR 0x0000031c /* Parameters: a r g b */ +# define NV30_TCL_PRIMITIVE_3D_BLEND_EQUATION 0x00000320 +# define NV30_TCL_PRIMITIVE_3D_COLOR_MASK 0x00000324 /* Parameters: a r g b */ +# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE 0x00000328 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK 0x0000032c +# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC 0x00000330 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_REF 0x00000334 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_MASK 0x00000338 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL 0x0000033c +# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_ZFAIL 0x00000340 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_ZPASS 0x00000344 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE 0x00000348 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK 0x0000034c +# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC 0x00000350 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_REF 0x00000354 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_MASK 0x00000358 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL 0x0000035c +# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_ZFAIL 0x00000360 +# define NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_ZPASS 0x00000364 +# define NV30_TCL_PRIMITIVE_3D_SHADE_MODEL 0x00000368 +# define NV30_TCL_PRIMITIVE_3D_FOG_ENABLE 0x0000036c +# define NV30_TCL_PRIMITIVE_3D_FOG_COLOR 0x00000370 +# define NV40_TCL_PRIMITIVE_3D_COLOR_MASK_BUFFER123 0x00000370 /* Parameters: buffer3 b buffer3 g buffer3 r buffer3 a buffer2 b buffer2 g buffer2 r buffer2 a buffer1 b buffer1 g buffer1 r buffer1 a */ +# define NV30_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE 0x0000037c +# define NV30_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR 0x00000394 +# define NV30_TCL_PRIMITIVE_3D_DEPTH_RANGE_FAR 0x00000398 +# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_R 0x000003a0 +# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_G 0x000003a4 +# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_B 0x000003a8 +# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_FRONT_A 0x000003b4 +# define NV30_TCL_PRIMITIVE_3D_LINE_WIDTH_SMOOTH 0x000003b8 +# define NV30_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE 0x000003bc +# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(d) (0x00000400 + d * 0x0004) +# define NV30_TCL_PRIMITIVE_3D_MODELVIEW_MATRIX( d) (0x00000480 + d * 0x0004) +# define NV30_TCL_PRIMITIVE_3D_INVERSE_MODELVIEW_MATRIX( d) (0x00000580 + d * 0x0004) +# define NV30_TCL_PRIMITIVE_3D_PROJECTION_MATRIX( d) (0x00000680 + d * 0x0004) +# define NV30_TCL_PRIMITIVE_3D_TX_MATRIX(x,y) (0x000006c0 + y * 0x0010 + x * 0x0004) +# define NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM 0x000008e4 +# define NV30_TCL_PRIMITIVE_3D_FOG_COORD_DIST 0x000008c8 +# define NV30_TCL_PRIMITIVE_3D_FOG_MODE 0x000008cc +# define NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT 0x000008d0 +# define NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR 0x000008d4 +# define NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC 0x000008d8 +# define NV30_TCL_PRIMITIVE_3D_RC_COLOR0 0x000008ec /* Parameters: a r g b */ +# define NV30_TCL_PRIMITIVE_3D_RC_COLOR1 0x000008f0 /* Parameters: a r g b */ +# define NV30_TCL_PRIMITIVE_3D_RC_FINAL0 0x000008f4 /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV30_TCL_PRIMITIVE_3D_RC_FINAL1 0x000008f8 /* Parameters: vare_mapping vare_component_usage vare_input varf_mapping varf_component_usage varf_input varg_mapping varg_component_usage varg_input color_sum_clamp */ +# define NV30_TCL_PRIMITIVE_3D_RC_ENABLE 0x000008fc /* Parameters: number of rc enabled */ +# define NV30_TCL_PRIMITIVE_3D_RC_IN_ALPHA(d) (0x00000900 + d * 0x0020) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV30_TCL_PRIMITIVE_3D_RC_IN_RGB(d) (0x00000904 + d * 0x0020) /* Parameters: vara_mapping vara_component_usage vara_input varb_mapping varb_component_usage varb_input varc_mapping varc_component_usage varc_input vard_mapping vard_component_usage vard_input */ +# define NV30_TCL_PRIMITIVE_3D_RC_CONSTANT_COLOR0(d) (0x00000908 + d * 0x0020) /* Parameters: a r g b */ +# define NV30_TCL_PRIMITIVE_3D_RC_CONSTANT_COLOR1(d) (0x0000090c + d * 0x0020) /* Parameters: a r g b */ +# define NV30_TCL_PRIMITIVE_3D_RC_OUT_ALPHA(d) (0x00000910 + d * 0x0020) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */ +# define NV30_TCL_PRIMITIVE_3D_RC_OUT_RGB(d) (0x00000914 + d * 0x0020) /* Parameters: scale bias mux_sum ab_dot_product cd_dot_product sum_output ab_output cd_output */ +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0 0x00000200 /* Parameters: width x_offset */ +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM1 0x00000204 /* Parameters: height y_offset */ +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0 0x000002c0 /* Parameters: width x_offset */ +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS1 0x000002c4 /* Parameters: height y_offset */ +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0 0x00000a00 /* Parameters: width x_offset */ +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_1 0x00000a04 /* Parameters: height y_offset */ +# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x00000a10 +# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x00000a14 +# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x00000a18 +# define NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS 0x000008c0 /* Parameters: width x_offset */ +# define NV30_TCL_PRIMITIVE_3D_SCISSOR_HEIGHT_YPOS 0x000008c4 /* Parameters: height y_offset */ +# define NV30_TCL_PRIMITIVE_3D_POINT_SPRITE 0x00001ee8 /* Parameters: coord_replace r_mode enable */ +# define NV30_TCL_PRIMITIVE_3D_POINT_SIZE 0x00001ee0 +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_A 0x00001ec0 +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_B 0x00001ec4 +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_C 0x00001ec8 +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_D 0x00001ecc +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_E 0x00001ed0 +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_F 0x00001ed4 +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_G 0x00001ed8 +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETER_H 0x00001edc +# define NV30_TCL_PRIMITIVE_3D_POINT_PARAMETERS_ENABLE 0x00001ee4 +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX 0x00000a20 +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OY 0x00000a24 +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_NPF_DIV2 0x00000a28 +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_UNK0_0x0 0x00000a2c +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_PX_DIV2 0x00000a30 +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_PY_DIV2 0x00000a34 +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_FMN_DIV2 0x00000a38 +# define NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_UNK1_0x0 0x00000a3c +# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000a60 +# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000a64 +# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000a68 +# define NV30_TCL_PRIMITIVE_3D_DEPTH_FUNC 0x00000a6c +# define NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE 0x00000a70 +# define NV30_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE 0x00000a74 +# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR 0x00000a78 +# define NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS 0x00000a7c +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0 0x00000b80 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST1 0x00000b84 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST2 0x00000b88 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST3 0x00000b8c +# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_R 0x000017b0 +# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_G 0x000017b4 +# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_B 0x000017b8 +# define NV30_TCL_PRIMITIVE_3D_COLOR_MATERIAL_BACK_A 0x000017c0 +# define NV30_TCL_PRIMITIVE_3D_OCC_QUERY_OR_COLOR_BUFF_ENABLE 0x000017c8 +# define NV30_TCL_PRIMITIVE_3D_STORE_RESULT 0x00001800 +# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_A(d) (0x00000e00 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_B(d) (0x00000e04 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_C(d) (0x00000e08 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_D(d) (0x00000e0c + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(d) (0x00001000 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(d) (0x00001004 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(d) (0x00001008 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(d) (0x0000100c + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(d) (0x00001010 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(d) (0x00001014 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(d) (0x00001018 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(d) (0x0000101c + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(d) (0x00001020 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_X(d) (0x00001028 + d * 0x0080) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Y(d) (0x0000102c + d * 0x0080) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_HALF_VECTOR_Z(d) (0x00001030 + d * 0x0080) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_X(d) (0x00001034 + d * 0x0080) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Y(d) (0x00001038 + d * 0x0080) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_DIRECTION_Z(d) (0x0000103c + d * 0x0080) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(d) (0x00001228 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(d) (0x0000122c + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(d) (0x00001230 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(d) (0x00001200 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_EXPONENT(d) (0x00001204 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_B(d) (0x00001208 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(d) (0x0000120c + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Y(d) (0x00001210 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_Z(d) (0x00001214 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_C(d) (0x00001218 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(d) (0x0000121c + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_Y(d) (0x00001220 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_Z(d) (0x00001224 + d * 0x0040) +# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_A 0x00001400 +# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_B 0x00001404 +# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_C 0x00001408 +# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_D 0x0000140c +# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_E 0x00001410 +# define NV30_TCL_PRIMITIVE_3D_FRONT_MATERIAL_SHININESS_F 0x00001414 +# define NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS 0x00001420 /* Parameters: light 7 light 6 light 5 light 4 light 3 light 2 light 1 light 0 */ +# define NV30_TCL_PRIMITIVE_3D_UNK1D6C_OFFSET 0x00001d6c +# define NV30_TCL_PRIMITIVE_3D_UNK1D70_VALUE 0x00001d70 +# define NV30_TCL_PRIMITIVE_3D_LINE_STIPPLE_ENABLE 0x00001db4 +# define NV30_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN 0x00001db8 /* Parameters: factor pattern */ +# define NV30_TCL_PRIMITIVE_3D_BEGIN_END 0x00001808 +# define NV30_TCL_PRIMITIVE_3D_CULL_FACE 0x00001830 +# define NV30_TCL_PRIMITIVE_3D_FRONT_FACE 0x00001834 +# define NV30_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE 0x00001838 +# define NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE 0x0000183c +# define NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH 0x00001d8c +# define NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB 0x00001d90 /* Parameters: a r g b */ +# define NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS 0x00001d94 +# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_A 0x00001e20 +# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_B 0x00001e24 +# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_C 0x00001e28 +# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_D 0x00001e2c +# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_E 0x00001e30 +# define NV30_TCL_PRIMITIVE_3D_BACK_MATERIAL_SHININESS_F 0x00001e34 +# define NV30_TCL_PRIMITIVE_3D_DO_VERTICES 0x00001dac +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID 0x00001e9c +# define NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID 0x00001ea0 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID 0x00001efc +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P0_X 0x00001f00 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P0_Y 0x00001f04 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P0_Z 0x00001f08 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P0_W 0x00001f0c +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P1_X 0x00001f10 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P1_Y 0x00001f14 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P1_Z 0x00001f18 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P1_W 0x00001f1c +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P2_X 0x00001f20 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P2_Y 0x00001f24 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P2_Z 0x00001f28 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P2_W 0x00001f2c +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P3_X 0x00001f30 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P3_Y 0x00001f34 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P3_Z 0x00001f38 +# define NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_P3_W 0x00001f3c +# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_3X(d) (0x00001500 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_3Y(d) (0x00001504 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_3Z(d) (0x00001508 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_3W(d) (0x0000150c + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_4X(d) (0x00001c00 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_4Y(d) (0x00001c04 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_4Z(d) (0x00001c08 + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_VTX_ATTR_4W(d) (0x00001c0c + d * 0x0010) +# define NV30_TCL_PRIMITIVE_3D_VB_POINTER_ATTR(d) (0x00001680 + d * 0x0004) /* Parameters: source: offset */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_XY 0x00000a90 /* Parameters: y x */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_Z 0x00000a94 /* Parameters: z */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S 0x000018c0 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_T 0x000018c4 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S 0x000018c8 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_T 0x000018cc +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_S 0x000018d0 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_T 0x000018d4 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_S 0x000018d8 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_T 0x000018dc +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_2I 0x00001920 /* Parameters: t s */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_2I 0x00001924 /* Parameters: t s */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_2I 0x00001928 /* Parameters: t s */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_2I 0x0000192c /* Parameters: t s */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_COL_4I 0x0000194c /* Parameters: a b g r */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_COL2_3I 0x00001950 /* Parameters: a b g r */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_ST 0x000019c0 /* Parameters: t s */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_RQ 0x000019c4 /* Parameters: q r */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_ST 0x000019c8 /* Parameters: t s */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_RQ 0x000019cc /* Parameters: q r */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_ST 0x000019d0 /* Parameters: t s */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_RQ 0x000019d4 /* Parameters: q r */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_ST 0x000019d8 /* Parameters: t s */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_RQ 0x000019dc /* Parameters: q r */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_FOG_1F 0x00001e54 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0 0x00001718 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR( d) (0x00001740 + d * 0x0004) +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR0_POS 0x00001740 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR1_WGH 0x00001744 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR2_NOR 0x00001748 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR3_COL 0x0000174c /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR4_COL2 0x00001750 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR5_FOG 0x00001754 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR6 0x00001758 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR7 0x0000175c /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR8_TX0 0x00001760 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR9_TX1 0x00001764 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR10_TX2 0x00001768 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR11_TX3 0x0000176c /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR12_TX4 0x00001770 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR13_TX5 0x00001774 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR14_TX6 0x00001778 /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR15_TX7 0x0000177c /* Parameters: stride fields type */ +# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x000017a0 +# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x000017a4 +# define NV30_TCL_PRIMITIVE_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x000017a8 +# define NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM 0x000008e4 +# define NV30_TCL_PRIMITIVE_3D_TX_ADDRESS_UNIT(d) (0x00001a00 + d * 0x0020) +# define NV30_TCL_PRIMITIVE_3D_TX_FORMAT_UNIT(d) (0x00001a04 + d * 0x0020) /* Parameters: mipmap type format ncomp cubic */ +# define NV30_TCL_PRIMITIVE_3D_TX_WRAP_UNIT(d) (0x00001a08 + d * 0x0020) /* Parameters: wrap_s wrap_t wrap_r */ +# define NV30_TCL_PRIMITIVE_3D_TX_ENABLE_UNIT(d) (0x00001a0c + d * 0x0020) /* Parameters: nv40_enable nv30_enable anisotropy */ +# define NV30_TCL_PRIMITIVE_3D_TX_SWIZZLE_UNIT(d) (0x00001a10 + d * 0x0020) +# define NV30_TCL_PRIMITIVE_3D_TX_FILTER_UNIT(d) (0x00001a14 + d * 0x0020) /* Parameters: filter_min filter_mag */ +# define NV30_TCL_PRIMITIVE_3D_TX_XY_DIM_UNIT(d) (0x00001a18 + d * 0x0020) /* Parameters: width height */ +# define NV30_TCL_PRIMITIVE_3D_TX_UNK07_UNIT(d) (0x00001a1c + d * 0x0020) +# define NV30_TCL_PRIMITIVE_3D_TX_DEPTH_UNIT(d) (0x00001840 + d * 0x0004) /* Parameters: depth NPOT pitch */ +# define NV30_TCL_PRIMITIVE_3D_VB_VERTEX_BATCH 0x00001814 /* Parameters: count_vertices offset_vertices */ +# define NV30_TCL_PRIMITIVE_3D_VB_ELEMENT_U16 0x0000180c /* Parameters: 1: 0: */ +# define NV30_TCL_PRIMITIVE_3D_VB_ELEMENT_U32 0x00001810 +# define NV30_TCL_PRIMITIVE_3D_VERTEX_DATA 0x00001818 +# define NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE 0x00000374 +# define NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP 0x00000378 +# define NV30_TCL_PRIMITIVE_3D_SET_DISPLAY_LIST_MEM_OFFSET 0x0000181c +# define NV30_TCL_PRIMITIVE_3D_EXECUTE_DISPLAY_LIST 0x00001824 /* Parameters: length start offset */ +# define NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT 0x00001828 +# define NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK 0x0000182c +# define NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE 0x0000147c +# define NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN( d) (0x00001480 + d * 0x0004) +# define NV30_TCL_PRIMITIVE_3D_SET_CLIPPING_PLANES 0x00001478 +# define NV30_TCL_PRIMITIVE_3D_VP_IN_REG 0x00001ff0 /* Parameters: vertex pos weight normal primary color secondary color fogcoord texture coords 0 texture ccords 1 texture coords 2 texture coords 3 texture coords 4 texture coords 5 texture coords 6 texture coords 7 */ +# define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG 0x00001ff4 /* Parameters: primary color secondary color backface primary color backface secondary color fogcoord pointsize clip plane 0 clip plane 1 clip plane 2 clip plane 3 clip plane 4 clip plane 5 texture coords 0 texture coords 1 texture coords 2 texture coords 3 texture coords 4 texture coords 5 texture coords 6 texture coords 7 */ + +/****************************************** +Object NV30_CLEAR_BUFFER used on: NV30 NV40 G70 +*/ +#define NV30_CLEAR_BUFFER 0x00000066 +# define NV30_CLEAR_BUFFER_SET_DMA_NOTIFY 0x00000180 +# define NV30_CLEAR_BUFFER_SET_IMAGE_PATTERN 0x00000188 +# define NV30_CLEAR_BUFFER_SET_RASTER_OP 0x0000018c +# define NV30_CLEAR_BUFFER_SET_CONTEXT_SURFACE_2D 0x00000198 +# define NV30_CLEAR_BUFFER_UNK002fc 0x000002fc + +/****************************************** +Object NV50_TCL_PRIMITIVE_3D used on: +*/ +#define NV50_TCL_PRIMITIVE_3D 0x00000097 +# define NV50_TCL_PRIMITIVE_3D_SET_OBJECT_0( d) (0x00000180 + d * 0x0004) +# define NV50_TCL_PRIMITIVE_3D_SET_OBJECT_1( d) (0x000001c0 + d * 0x0004) +# define NV50_TCL_PRIMITIVE_3D_VERTEX_FOG_1F 0x00000314 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_2F_X 0x00000380 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_2F_Y 0x00000384 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_S 0x000003c0 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_2F_T 0x000003c4 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_S 0x000003c8 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_2F_T 0x000003cc +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_S 0x000003d0 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_2F_T 0x000003d4 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_S 0x000003d8 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_2F_T 0x000003dc +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_3F_X 0x00000400 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Y 0x00000404 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_3F_Z 0x00000408 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_X 0x00000420 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Y 0x00000424 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3F_Z 0x00000428 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_3F_R 0x00000430 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_3F_G 0x00000434 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_3F_B 0x00000438 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_R 0x00000440 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_G 0x00000444 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL2_3F_B 0x00000448 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4F_X 0x00000500 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Y 0x00000504 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4F_Z 0x00000508 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4F_W 0x0000050c +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4F_R 0x00000530 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4F_G 0x00000534 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4F_B 0x00000538 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4F_A 0x0000053c +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_S 0x00000580 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_T 0x00000584 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_R 0x00000588 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4F_Q 0x0000058c +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_S 0x00000590 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_T 0x00000594 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_R 0x00000598 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4F_Q 0x0000059c +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_S 0x000005a0 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_T 0x000005a4 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_R 0x000005a8 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4F_Q 0x000005ac +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_S 0x000005b0 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_T 0x000005b4 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_R 0x000005b8 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4F_Q 0x000005bc +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_2I 0x000006a0 /* Parameters: t s */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_2I 0x000006a4 /* Parameters: t s */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_2I 0x000006a8 /* Parameters: t s */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_2I 0x000006ac /* Parameters: t s */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4I_XY 0x00000700 /* Parameters: y x */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_POS_4I_ZW 0x00000704 /* Parameters: w z */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_ST 0x00000740 /* Parameters: t s */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX0_4I_RQ 0x00000744 /* Parameters: q r */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_ST 0x00000748 /* Parameters: t s */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX1_4I_RQ 0x0000074c /* Parameters: q r */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_ST 0x00000750 /* Parameters: t s */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX2_4I_RQ 0x00000754 /* Parameters: q r */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_ST 0x00000758 /* Parameters: t s */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_TX3_4I_RQ 0x0000075c /* Parameters: q r */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_XY 0x00000790 /* Parameters: y x */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_NOR_3I_Z 0x00000794 /* Parameters: z */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL_4I 0x0000088c /* Parameters: a b g r */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_COL2_3I 0x00000890 /* Parameters: a b g r */ +# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK0_X 0x00000a00 +# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK0_Y 0x00000a04 +# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK0_Z 0x00000a08 +# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK1_X 0x00000a0c +# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK1_Y 0x00000a10 +# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_UNK1_Z 0x00000a14 +# define NV50_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR 0x00000c08 +# define NV50_TCL_PRIMITIVE_3D_DEPTH_RANGE_FAR 0x00000c0c +# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(d) (0x00000d00 + d * 0x0008) /* Parameters: x2 x1 */ +# define NV50_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(d) (0x00000d04 + d * 0x0008) /* Parameters: y2 y1 */ +# define NV50_TCL_PRIMITIVE_3D_VERTEX_BUFFER_FIRST 0x00000d74 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_BUFFER_COUNT 0x00000d78 +# define NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_R 0x00000d80 +# define NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_G 0x00000d84 +# define NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_B 0x00000d88 +# define NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_A 0x00000d8c +# define NV50_TCL_PRIMITIVE_3D_CLEAR_DEPTH 0x00000d90 +# define NV50_TCL_PRIMITIVE_3D_CLEAR_STENCIL 0x00000da0 +# define NV50_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT 0x00000dac +# define NV50_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK 0x00000db0 +# define NV50_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE 0x00000db4 +# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000dc0 +# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000dc4 +# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000dc8 +# define NV50_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS 0x00000e04 /* Parameters: w x */ +# define NV50_TCL_PRIMITIVE_3D_SCISSOR_HEIGHT_YPOS 0x00000e08 /* Parameters: h y */ +# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID 0x00000f00 +# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_X 0x00000f04 +# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_Y 0x00000f08 +# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_Z 0x00000f0c +# define NV50_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_W 0x00000f10 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_REF 0x00000f54 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK 0x00000f58 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_MASK 0x00000f5c +# define NV50_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE 0x000012cc +# define NV50_TCL_PRIMITIVE_3D_SHADE_MODEL 0x000012d4 +# define NV50_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE 0x000012e8 +# define NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE 0x000012ec +# define NV50_TCL_PRIMITIVE_3D_DEPTH_FUNC 0x0000130c +# define NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF 0x00001310 +# define NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC 0x00001314 +# define NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_R 0x0000131c +# define NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_G 0x00001320 +# define NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_B 0x00001324 +# define NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_A 0x00001328 +# define NV50_TCL_PRIMITIVE_3D_BLEND_EQUATION_RGB 0x00001340 +# define NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC_RGB 0x00001344 +# define NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_DST_RGB 0x00001348 +# define NV50_TCL_PRIMITIVE_3D_BLEND_EQUATION_ALPHA 0x0000134c +# define NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC_ALPHA 0x00001350 +# define NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_DST_ALPHA 0x00001358 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE 0x00001380 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL 0x00001384 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_ZFAIL 0x00001388 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_ZPASS 0x0000138c +# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC 0x00001390 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_REF 0x00001394 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK 0x00001398 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_MASK 0x0000139c +# define NV50_TCL_PRIMITIVE_3D_LINE_WIDTH 0x000013b0 +# define NV50_TCL_PRIMITIVE_3D_POINT_SIZE 0x00001518 +# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR 0x0000156c +# define NV50_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE 0x00001570 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE 0x00001594 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL 0x00001598 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_ZFAIL 0x0000159c +# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_ZPASS 0x000015a0 +# define NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC 0x000015a4 +# define NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS 0x000015bc +# define NV50_TCL_PRIMITIVE_3D_VERTEX_BEGIN 0x000015dc +# define NV50_TCL_PRIMITIVE_3D_VERTEX_END 0x000015e0 +# define NV50_TCL_PRIMITIVE_3D_VERTEX_DATA 0x00001640 +# define NV50_TCL_PRIMITIVE_3D_LINE_STIPPLE_ENABLE 0x0000166c +# define NV50_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN 0x00001680 /* Parameters: pattern factor */ +# define NV50_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE 0x0000168c +# define NV50_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN( d) (0x00001700 + d * 0x0004) +# define NV50_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE 0x00001918 +# define NV50_TCL_PRIMITIVE_3D_FRONT_FACE 0x0000191c +# define NV50_TCL_PRIMITIVE_3D_CULL_FACE 0x00001920 +# define NV50_TCL_PRIMITIVE_3D_LOGIC_OP_ENABLE 0x000019c4 +# define NV50_TCL_PRIMITIVE_3D_LOGIC_OP_OP 0x000019c8 +# define NV50_TCL_PRIMITIVE_3D_CLEAR_BUFFERS 0x000019d0 /* Parameters: color stencil depth */ +# define NV50_TCL_PRIMITIVE_3D_COLOR_MASK( d) (0x00001a00 + d * 0x0004) /* Parameters: a b g r */ + +/****************************************** +Object NV_DMA_FROM_MEMORY used on: NV03 NV04 NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV_DMA_FROM_MEMORY 0x00000002 + +/****************************************** +Object NV_DMA_TO_MEMORY used on: NV03 NV04 NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV_DMA_TO_MEMORY 0x00000003 + +/****************************************** +Object NV_DMA_IN_MEMORY used on: NV03 NV04 NV10 NV15 NV20 NV30 NV40 G70 +*/ +#define NV_DMA_IN_MEMORY 0x0000003d + +/****************************************** +Object NvType0046 used on: NV04 +*/ +#define NvType0046 0x00000046 +# define NvType0046_DMA_NOTIFY 0x00000180 +# define NvType0046_DMA_MEM_1 0x00000184 +# define NvType0046_DMA_MEM_2 0x00000188 +# define NvType0046_DMA_3 0x0000018c +# define NvType0046_DMA_4 0x00000190 +# define NvType0046_OBJ_5 0x00000194 +# define NvType0046_OBJ_6 0x00000198 +# define NvType0046_PITCH1 0x00000304 +# define NvType0046_PITCH2 0x0000030c +# define NvType0046_SIZE 0x00000340 /* Parameters: width height */ +# define NvType0046_WIDTH 0x00000344 /* Parameters: visible_width blank_width */ +# define NvType0046_HSYNC 0x00000348 /* Parameters: hsync_start hsync_len */ +# define NvType0046_HEIGHT 0x0000034c /* Parameters: visible_height blank_height */ +# define NvType0046_VSYNC 0x00000350 /* Parameters: vsync_start vsync_len */ +# define NvType0046_FULL_SIZE 0x00000354 /* Parameters: full_width full_height */ +# define NvType0046_PIXEL_CLK 0x00000358 +# define NvType0046_FLAGS 0x0000035c /* Parameters: doublescan -hsync -vsync depth */ + +/****************************************** +Object NvType0047 used on: NV04 +*/ +#define NvType0047 0x00000047 +# define NvType0047_DMA_NOTIFY 0x00000180 +# define NvType0047_UNK19C 0x0000019c +# define NvType0047_UNK1A0 0x000001a0 + +/****************************************** +Object NvType0049 used on: NV04 +*/ +#define NvType0049 0x00000049 +# define NvType0049_DMA_NOTIFY 0x00000180 +# define NvType0049_DMA_MEM_1 0x00000184 +# define NvType0049_DMA_MEM_2 0x00000188 + +/****************************************** +Object NvType004D used on: NV04 +*/ +#define NvType004D 0x0000004d +# define NvType004D_DMA_NOTIFY 0x00000180 +# define NvType004D_DMA_MEM_1 0x00000184 +# define NvType004D_DMA_MEM_2 0x00000188 +# define NvType004D_DMA_MEM_3 0x0000018c +# define NvType004D_DMA_MEM_4 0x00000190 + +#endif /* _NOUVEAU_REG_H */ diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_screen.c new file mode 100644 index 000000000..7a4b9f1cd --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_screen.c @@ -0,0 +1,382 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "glheader.h" +#include "imports.h" +#include "mtypes.h" +#include "framebuffer.h" +#include "renderbuffer.h" + +#include "nouveau_context.h" +#include "nouveau_screen.h" +#include "nouveau_object.h" +#include "nouveau_span.h" + +#include "utils.h" +#include "context.h" +#include "vblank.h" +#include "drirenderbuffer.h" + +#include "GL/internal/dri_interface.h" + +#include "xmlpool.h" + +PUBLIC const char __driConfigOptions[] = +DRI_CONF_BEGIN + DRI_CONF_SECTION_DEBUG + DRI_CONF_NO_RAST(false) + DRI_CONF_SECTION_END +DRI_CONF_END; +static const GLuint __driNConfigOptions = 1; + +extern const struct dri_extension common_extensions[]; +extern const struct dri_extension nv10_extensions[]; +extern const struct dri_extension nv20_extensions[]; +extern const struct dri_extension nv30_extensions[]; +extern const struct dri_extension nv40_extensions[]; +extern const struct dri_extension nv50_extensions[]; + +static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv) +{ + nouveauScreenPtr screen; + NOUVEAUDRIPtr dri_priv=(NOUVEAUDRIPtr)sPriv->pDevPriv; + + /* allocate screen */ + screen = (nouveauScreenPtr) CALLOC( sizeof(*screen) ); + if ( !screen ) { + __driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__); + return NULL; + } + + screen->card=nouveau_card_lookup(dri_priv->device_id); + if (!screen->card) { + __driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n", + __func__, dri_priv->device_id >> 16, dri_priv->device_id & 0xFFFF); + FREE(screen); + return NULL; + } + + /* parse information in __driConfigOptions */ + driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions); + + screen->fbFormat = dri_priv->bpp / 8; + screen->frontOffset = dri_priv->front_offset; + screen->frontPitch = dri_priv->front_pitch; + screen->backOffset = dri_priv->back_offset; + screen->backPitch = dri_priv->back_pitch; + screen->depthOffset = dri_priv->depth_offset; + screen->depthPitch = dri_priv->depth_pitch; + + screen->driScreen = sPriv; + return screen; +} + +static void +nouveauDestroyScreen(__DRIscreenPrivate *sPriv) +{ + nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private; + + if (!screen) return; + + /* free all option information */ + driDestroyOptionInfo (&screen->optionCache); + + FREE(screen); + sPriv->private = NULL; +} + +static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv) +{ + sPriv->private = (void *) nouveauCreateScreen( sPriv ); + if ( !sPriv->private ) { + nouveauDestroyScreen( sPriv ); + return GL_FALSE; + } + + return GL_TRUE; +} + +/** + * Create the Mesa framebuffer and renderbuffers for a given window/drawable. + * + * \todo This function (and its interface) will need to be updated to support + * pbuffers. + */ +static GLboolean +nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap) +{ + nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private; + nouveau_renderbuffer *nrb; + struct gl_framebuffer *fb; + const GLboolean swAccum = mesaVis->accumRedBits > 0; + const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24; + GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5; + + if (isPixmap) + return GL_FALSE; /* not implemented */ + + fb = _mesa_create_framebuffer(mesaVis); + if (!fb) + return GL_FALSE; + + /* Front buffer */ + nrb = nouveau_renderbuffer_new(color_format, + driScrnPriv->pFB + screen->frontOffset, + screen->frontOffset, + screen->frontPitch * screen->fbFormat, + driDrawPriv); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa); + + if (0 /* unified buffers if we choose to support them.. */) { + } else { + if (mesaVis->doubleBufferMode) { + nrb = nouveau_renderbuffer_new(color_format, NULL, + 0, 0, + NULL); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa); + } + + if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { + nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL, + 0, 0, + NULL); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa); + } else if (mesaVis->depthBits == 24) { + nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL, + 0, 0, + NULL); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); + } else if (mesaVis->depthBits == 16) { + nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL, + 0, 0, + NULL); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); + } + } + + _mesa_add_soft_renderbuffers(fb, + GL_FALSE, /* color */ + GL_FALSE, /* depth */ + swStencil, + swAccum, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */); + + driDrawPriv->driverPrivate = (void *) fb; + return (driDrawPriv->driverPrivate != NULL); +} + + +static void +nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); +} + +static int +nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo) +{ + return -1; +} + +static const struct __DriverAPIRec nouveauAPI = { + .InitDriver = nouveauInitDriver, + .DestroyScreen = nouveauDestroyScreen, + .CreateContext = nouveauCreateContext, + .DestroyContext = nouveauDestroyContext, + .CreateBuffer = nouveauCreateBuffer, + .DestroyBuffer = nouveauDestroyBuffer, + .SwapBuffers = nouveauSwapBuffers, + .MakeCurrent = nouveauMakeCurrent, + .UnbindContext = nouveauUnbindContext, + .GetSwapInfo = nouveauGetSwapInfo, + .GetMSC = driGetMSC32, + .WaitForMSC = driWaitForMSC32, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL, + .CopySubBuffer = nouveauCopySubBuffer +}; + + +static __GLcontextModes * +nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer ) +{ + __GLcontextModes * modes; + __GLcontextModes * m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + int i; + + static const struct { + GLenum format; + GLenum type; + } fb_format_array[] = { + { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 }, + { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, + { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV }, + }; + + /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't + * support pageflipping at all. + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + }; + + u_int8_t depth_bits_array[4] = { 0, 16, 24, 24 }; + u_int8_t stencil_bits_array[4] = { 0, 0, 0, 8 }; + + depth_buffer_factor = 4; + back_buffer_factor = (have_back_buffer) ? 3 : 1; + + num_modes = ((pixel_bits==16) ? 1 : 2) * + depth_buffer_factor * back_buffer_factor * 4; + modes = (*dri_interface->createContextModes)(num_modes, + sizeof(__GLcontextModes)); + m = modes; + + for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) { + if (!driFillInModes(&m, fb_format_array[i].format, + fb_format_array[i].type, + depth_bits_array, + stencil_bits_array, + depth_buffer_factor, + back_buffer_modes, + back_buffer_factor, + GLX_TRUE_COLOR)) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + if (!driFillInModes(&m, fb_format_array[i].format, + fb_format_array[i].type, + depth_bits_array, + stencil_bits_array, + depth_buffer_factor, + back_buffer_modes, + back_buffer_factor, + GLX_DIRECT_COLOR)) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + } + + return modes; +} + + +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. + */ +PUBLIC +void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, + const __GLcontextModes * modes, + const __DRIversion * ddx_version, + const __DRIversion * dri_version, + const __DRIversion * drm_version, + const __DRIframebuffer * frame_buffer, + drmAddress pSAREA, int fd, + int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes) + +{ + __DRIscreenPrivate *psp; + static const __DRIversion ddx_expected = { 1, 2, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; +#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 6 +#error nouveau_drm.h version doesn't match expected version +#endif + dri_interface = interface; + + if (!driCheckDriDdxDrmVersions2("nouveau", + dri_version, & dri_expected, + ddx_version, & ddx_expected, + drm_version, & drm_expected)) { + return NULL; + } + + // temporary lock step versioning + if (drm_expected.patch!=drm_version->patch) { + __driUtilMessage("%s: wrong DRM version, expected %d, got %d\n", + __func__, + drm_expected.patch, drm_version->patch); + return NULL; + } + + psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, + ddx_version, dri_version, drm_version, + frame_buffer, pSAREA, fd, + internal_api_version, &nouveauAPI); + if ( psp != NULL ) { + NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv; + + *driver_modes = nouveauFillInModes(dri_priv->bpp, + (dri_priv->bpp == 16) ? 16 : 24, + (dri_priv->bpp == 16) ? 0 : 8, + 1 + ); + + /* Calling driInitExtensions here, with a NULL context pointer, does not actually + * enable the extensions. It just makes sure that all the dispatch offsets for all + * the extensions that *might* be enables are known. This is needed because the + * dispatch offsets need to be known when _mesa_context_create is called, but we can't + * enable the extensions until we have a context pointer. + * + * Hello chicken. Hello egg. How are you two today? + */ + driInitExtensions( NULL, common_extensions, GL_FALSE ); + driInitExtensions( NULL, nv10_extensions, GL_FALSE ); + driInitExtensions( NULL, nv10_extensions, GL_FALSE ); + driInitExtensions( NULL, nv30_extensions, GL_FALSE ); + driInitExtensions( NULL, nv40_extensions, GL_FALSE ); + driInitExtensions( NULL, nv50_extensions, GL_FALSE ); + } + + return (void *) psp; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_screen.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_screen.h new file mode 100644 index 000000000..decdafa86 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_screen.h @@ -0,0 +1,61 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#ifndef __NOUVEAU_SCREEN_H__ +#define __NOUVEAU_SCREEN_H__ + +#include "xmlconfig.h" + +#include "nouveau_dri.h" +#include "nouveau_card.h" + +typedef struct { + nouveau_card* card; + u_int32_t bus_type; + u_int32_t agp_mode; + + GLint fbFormat; + + GLuint frontOffset; + GLuint frontPitch; + GLuint backOffset; + GLuint backPitch; + + GLuint depthOffset; + GLuint depthPitch; + GLuint spanOffset; + + __DRIscreenPrivate *driScreen; + unsigned int sarea_priv_offset; + + /* Configuration cache with default values for all contexts */ + driOptionCache optionCache; + +} nouveauScreenRec, *nouveauScreenPtr; + + +#endif /* __NOUVEAU_SCREEN_H__ */ diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader.c new file mode 100644 index 000000000..b6837c5de --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader.c @@ -0,0 +1,833 @@ +/* + * Copyright (C) 2006 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* + * Authors: + * Ben Skeggs <darktama@iinet.net.au> + */ + +#include "glheader.h" +#include "macros.h" +#include "enums.h" +#include "extensions.h" + +#include "shader/program.h" +#include "shader/prog_instruction.h" +/*#include "shader/arbprogparse.h"*/ +#include "tnl/tnl.h" + +#include "nouveau_context.h" +#include "nouveau_shader.h" + +/***************************************************************************** + * Mesa entry points + */ +static void +nouveauBindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog) +{ + NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog); +} + +static struct gl_program * +nouveauNewProgram(GLcontext *ctx, GLenum target, GLuint id) +{ + nouveauShader *nvs; + + NVSDBG("target=%s, id=%d\n", _mesa_lookup_enum_by_nr(target), id); + + nvs = CALLOC_STRUCT(_nouveauShader); + NVSDBG("prog=%p\n", nvs); + switch (target) { + case GL_VERTEX_PROGRAM_ARB: + return _mesa_init_vertex_program(ctx, &nvs->mesa.vp, target, id); + case GL_FRAGMENT_PROGRAM_ARB: + return _mesa_init_fragment_program(ctx, &nvs->mesa.fp, target, id); + default: + _mesa_problem(ctx, "Unsupported shader target"); + break; + } + + FREE(nvs); + return NULL; +} + +static void +nouveauDeleteProgram(GLcontext *ctx, struct gl_program *prog) +{ + nouveauShader *nvs = (nouveauShader *)prog; + + NVSDBG("prog=%p\n", prog); + + if (nvs->translated) + FREE(nvs->program); + _mesa_delete_program(ctx, prog); +} + +static void +nouveauProgramStringNotify(GLcontext *ctx, GLenum target, + struct gl_program *prog) +{ + nouveauShader *nvs = (nouveauShader *)prog; + + NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog); + + if (nvs->translated) + FREE(nvs->program); + + nvs->error = GL_FALSE; + nvs->translated = GL_FALSE; + + _tnl_program_string(ctx, target, prog); +} + +static GLboolean +nouveauIsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog) +{ + nouveauShader *nvs = (nouveauShader *)prog; + + NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target), prog); + + return nvs->translated; +} + +GLboolean +nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + struct gl_program_parameter_list *plist; + int i; + + NVSDBG("prog=%p\n", nvs); + + /* Translate to HW format now if necessary */ + if (!nvs->translated) { + /* Mesa ASM shader -> nouveauShader */ + if (!nouveau_shader_pass0(ctx, nvs)) + return GL_FALSE; + /* Basic dead code elimination + register usage info */ + if (!nouveau_shader_pass1(nvs)) + return GL_FALSE; + /* nouveauShader -> HW bytecode, HW register alloc */ + if (!nouveau_shader_pass2(nvs)) + return GL_FALSE; + assert(nvs->translated); + assert(nvs->program); + } + + /* Update state parameters */ + plist = nvs->mesa.vp.Base.Parameters; + _mesa_load_state_parameters(ctx, plist); + for (i=0; i<nvs->param_high; i++) { + if (!nvs->params[i].in_use) + continue; + + if (!nvs->on_hardware) { + /* if we've been kicked off the hardware there's no guarantee our + * consts are still there.. reupload them all + */ + nvs->func->UpdateConst(ctx, nvs, i); + } else if (nvs->params[i].source_val) { + /* update any changed state parameters */ + if (!TEST_EQ_4V(nvs->params[i].val, nvs->params[i].source_val)) + nvs->func->UpdateConst(ctx, nvs, i); + } + } + + /* Upload program to hardware, this must come after state param update + * as >=NV30 fragprogs inline consts into the bytecode. + */ + if (!nvs->on_hardware) { + nouveauShader **current; + + if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB) + current = &nmesa->current_vertprog; + else + current = &nmesa->current_fragprog; + if (*current) (*current)->on_hardware = 0; + + nvs->func->UploadToHW(ctx, nvs); + nvs->on_hardware = 1; + + *current = nvs; + } + + return GL_TRUE; +} + +nouveauShader * +nvsBuildTextShader(GLcontext *ctx, GLenum target, const char *text) +{ + nouveauShader *nvs; + + nvs = CALLOC_STRUCT(_nouveauShader); + if (!nvs) + return NULL; + + if (target == GL_VERTEX_PROGRAM_ARB) { + _mesa_init_vertex_program(ctx, &nvs->mesa.vp, GL_VERTEX_PROGRAM_ARB, 0); + _mesa_parse_arb_vertex_program(ctx, + GL_VERTEX_PROGRAM_ARB, + text, + strlen(text), + &nvs->mesa.vp); + } else if (target == GL_FRAGMENT_PROGRAM_ARB) { + _mesa_init_fragment_program(ctx, &nvs->mesa.fp, GL_FRAGMENT_PROGRAM_ARB, 0); + _mesa_parse_arb_fragment_program(ctx, + GL_FRAGMENT_PROGRAM_ARB, + text, + strlen(text), + &nvs->mesa.fp); + } + + nouveau_shader_pass0(ctx, nvs); + nouveau_shader_pass1(nvs); + nouveau_shader_pass2(nvs); + + return nvs; +} + +static void +nvsBuildPassthroughVP(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + const char *vp_text = + "!!ARBvp1.0\n" + "OPTION ARB_position_invariant;" + "" + "MOV result.color, vertex.color;\n" + "MOV result.texcoord[0], vertex.texcoord[0];\n" + "MOV result.texcoord[1], vertex.texcoord[1];\n" + "MOV result.texcoord[2], vertex.texcoord[2];\n" + "MOV result.texcoord[3], vertex.texcoord[3];\n" + "MOV result.texcoord[4], vertex.texcoord[4];\n" + "MOV result.texcoord[5], vertex.texcoord[5];\n" + "MOV result.texcoord[6], vertex.texcoord[6];\n" + "MOV result.texcoord[7], vertex.texcoord[7];\n" + "END"; + + nmesa->passthrough_vp = nvsBuildTextShader(ctx, + GL_VERTEX_PROGRAM_ARB, + vp_text); +} + +static void +nvsBuildPassthroughFP(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + const char *fp_text = + "!!ARBfp1.0\n" + "MOV result.color, fragment.color;\n" + "END"; + + nmesa->passthrough_fp = nvsBuildTextShader(ctx, + GL_FRAGMENT_PROGRAM_ARB, + fp_text); +} + +void +nouveauShaderInitFuncs(GLcontext * ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + switch (nmesa->screen->card->type) { + case NV_20: + NV20VPInitShaderFuncs(&nmesa->VPfunc); + break; + case NV_30: + NV30VPInitShaderFuncs(&nmesa->VPfunc); + NV30FPInitShaderFuncs(&nmesa->FPfunc); + break; + case NV_40: + case NV_44: + NV40VPInitShaderFuncs(&nmesa->VPfunc); + NV40FPInitShaderFuncs(&nmesa->FPfunc); + break; + case NV_50: + default: + return; + } + + /* Build a vertex program that simply passes through all attribs. + * Needed to do swtcl on nv40 + */ + if (nmesa->screen->card->type >= NV_40) + nvsBuildPassthroughVP(ctx); + + /* Needed on NV30, even when using swtcl, if you want to get colours */ + if (nmesa->screen->card->type >= NV_30) + nvsBuildPassthroughFP(ctx); + + ctx->Const.VertexProgram.MaxNativeInstructions = nmesa->VPfunc.MaxInst; + ctx->Const.VertexProgram.MaxNativeAluInstructions = nmesa->VPfunc.MaxInst; + ctx->Const.VertexProgram.MaxNativeTexInstructions = nmesa->VPfunc.MaxInst; + ctx->Const.VertexProgram.MaxNativeTexIndirections = + ctx->Const.VertexProgram.MaxNativeTexInstructions; + ctx->Const.VertexProgram.MaxNativeAttribs = nmesa->VPfunc.MaxAttrib; + ctx->Const.VertexProgram.MaxNativeTemps = nmesa->VPfunc.MaxTemp; + ctx->Const.VertexProgram.MaxNativeAddressRegs = nmesa->VPfunc.MaxAddress; + ctx->Const.VertexProgram.MaxNativeParameters = nmesa->VPfunc.MaxConst; + + if (nmesa->screen->card->type >= NV_30) { + ctx->Const.FragmentProgram.MaxNativeInstructions = nmesa->FPfunc.MaxInst; + ctx->Const.FragmentProgram.MaxNativeAluInstructions = nmesa->FPfunc.MaxInst; + ctx->Const.FragmentProgram.MaxNativeTexInstructions = nmesa->FPfunc.MaxInst; + ctx->Const.FragmentProgram.MaxNativeTexIndirections = + ctx->Const.FragmentProgram.MaxNativeTexInstructions; + ctx->Const.FragmentProgram.MaxNativeAttribs = nmesa->FPfunc.MaxAttrib; + ctx->Const.FragmentProgram.MaxNativeTemps = nmesa->FPfunc.MaxTemp; + ctx->Const.FragmentProgram.MaxNativeAddressRegs = nmesa->FPfunc.MaxAddress; + ctx->Const.FragmentProgram.MaxNativeParameters = nmesa->FPfunc.MaxConst; + } + + ctx->Driver.NewProgram = nouveauNewProgram; + ctx->Driver.BindProgram = nouveauBindProgram; + ctx->Driver.DeleteProgram = nouveauDeleteProgram; + ctx->Driver.ProgramStringNotify = nouveauProgramStringNotify; + ctx->Driver.IsProgramNative = nouveauIsProgramNative; +} + + +/***************************************************************************** + * Disassembly support structs + */ +#define CHECK_RANGE(idx, arr) ((idx)<sizeof(_##arr)/sizeof(const char *)) \ + ? _##arr[(idx)] : #arr"_OOB" + +#define NODS (1<<0) +#define BRANCH_TR (1<<1) +#define BRANCH_EL (1<<2) +#define BRANCH_EN (1<<3) +#define BRANCH_RE (1<<4) +#define BRANCH_ALL (BRANCH_TR|BRANCH_EL|BRANCH_EN) +#define COUNT_INC (1<<4) +#define COUNT_IND (1<<5) +#define COUNT_NUM (1<<6) +#define COUNT_ALL (COUNT_INC|COUNT_IND|COUNT_NUM) +#define TI_UNIT (1<<7) +struct _opcode_info +{ + const char *name; + int numsrc; + int flags; +}; + +static struct _opcode_info ops[] = { + [NVS_OP_ABS] = {"ABS", 1, 0}, + [NVS_OP_ADD] = {"ADD", 2, 0}, + [NVS_OP_ARA] = {"ARA", 1, 0}, + [NVS_OP_ARL] = {"ARL", 1, 0}, + [NVS_OP_ARR] = {"ARR", 1, 0}, + [NVS_OP_BRA] = {"BRA", 0, NODS | BRANCH_TR}, + [NVS_OP_BRK] = {"BRK", 0, NODS}, + [NVS_OP_CAL] = {"CAL", 0, NODS | BRANCH_TR}, + [NVS_OP_CMP] = {"CMP", 2, 0}, + [NVS_OP_COS] = {"COS", 1, 0}, + [NVS_OP_DIV] = {"DIV", 2, 0}, + [NVS_OP_DDX] = {"DDX", 1, 0}, + [NVS_OP_DDY] = {"DDY", 1, 0}, + [NVS_OP_DP2] = {"DP2", 2, 0}, + [NVS_OP_DP2A] = {"DP2A", 3, 0}, + [NVS_OP_DP3] = {"DP3", 2, 0}, + [NVS_OP_DP4] = {"DP4", 2, 0}, + [NVS_OP_DPH] = {"DPH", 2, 0}, + [NVS_OP_DST] = {"DST", 2, 0}, + [NVS_OP_EX2] = {"EX2", 1, 0}, + [NVS_OP_EXP] = {"EXP", 1, 0}, + [NVS_OP_FLR] = {"FLR", 1, 0}, + [NVS_OP_FRC] = {"FRC", 1, 0}, + [NVS_OP_IF] = {"IF", 0, NODS | BRANCH_EL | BRANCH_EN}, + [NVS_OP_KIL] = {"KIL", 1, 0}, + [NVS_OP_LG2] = {"LG2", 1, 0}, + [NVS_OP_LIT] = {"LIT", 1, 0}, + [NVS_OP_LOG] = {"LOG", 1, 0}, + [NVS_OP_LOOP] = {"LOOP", 0, NODS | COUNT_ALL | BRANCH_EN}, + [NVS_OP_LRP] = {"LRP", 3, 0}, + [NVS_OP_MAD] = {"MAD", 3, 0}, + [NVS_OP_MAX] = {"MAX", 2, 0}, + [NVS_OP_MIN] = {"MIN", 2, 0}, + [NVS_OP_MOV] = {"MOV", 1, 0}, + [NVS_OP_MUL] = {"MUL", 2, 0}, + [NVS_OP_NRM] = {"NRM", 1, 0}, + [NVS_OP_PK2H] = {"PK2H", 1, 0}, + [NVS_OP_PK2US] = {"PK2US", 1, 0}, + [NVS_OP_PK4B] = {"PK4B", 1, 0}, + [NVS_OP_PK4UB] = {"PK4UB", 1, 0}, + [NVS_OP_POW] = {"POW", 2, 0}, + [NVS_OP_POPA] = {"POPA", 0, 0}, + [NVS_OP_PUSHA] = {"PUSHA", 1, NODS}, + [NVS_OP_RCC] = {"RCC", 1, 0}, + [NVS_OP_RCP] = {"RCP", 1, 0}, + [NVS_OP_REP] = {"REP", 0, NODS | BRANCH_EN | COUNT_NUM}, + [NVS_OP_RET] = {"RET", 0, NODS}, + [NVS_OP_RFL] = {"RFL", 1, 0}, + [NVS_OP_RSQ] = {"RSQ", 1, 0}, + [NVS_OP_SCS] = {"SCS", 1, 0}, + [NVS_OP_SEQ] = {"SEQ", 2, 0}, + [NVS_OP_SFL] = {"SFL", 2, 0}, + [NVS_OP_SGE] = {"SGE", 2, 0}, + [NVS_OP_SGT] = {"SGT", 2, 0}, + [NVS_OP_SIN] = {"SIN", 1, 0}, + [NVS_OP_SLE] = {"SLE", 2, 0}, + [NVS_OP_SLT] = {"SLT", 2, 0}, + [NVS_OP_SNE] = {"SNE", 2, 0}, + [NVS_OP_SSG] = {"SSG", 1, 0}, + [NVS_OP_STR] = {"STR", 2, 0}, + [NVS_OP_SUB] = {"SUB", 2, 0}, + [NVS_OP_TEX] = {"TEX", 1, TI_UNIT}, + [NVS_OP_TXB] = {"TXB", 1, TI_UNIT}, + [NVS_OP_TXD] = {"TXD", 3, TI_UNIT}, + [NVS_OP_TXL] = {"TXL", 1, TI_UNIT}, + [NVS_OP_TXP] = {"TXP", 1, TI_UNIT}, + [NVS_OP_UP2H] = {"UP2H", 1, 0}, + [NVS_OP_UP2US] = {"UP2US", 1, 0}, + [NVS_OP_UP4B] = {"UP4B", 1, 0}, + [NVS_OP_UP4UB] = {"UP4UB", 1, 0}, + [NVS_OP_X2D] = {"X2D", 3, 0}, + [NVS_OP_XPD] = {"XPD", 2, 0}, + [NVS_OP_NOP] = {"NOP", 0, NODS}, +}; + +static struct _opcode_info * +_get_op_info(int op) +{ + if (op >= (sizeof(ops) / sizeof(struct _opcode_info))) + return NULL; + if (ops[op].name == NULL) + return NULL; + return &ops[op]; +} + +static const char *_SFR_STRING[] = { + [NVS_FR_POSITION] = "position", + [NVS_FR_WEIGHT] = "weight", + [NVS_FR_NORMAL] = "normal", + [NVS_FR_COL0] = "color", + [NVS_FR_COL1] = "color.secondary", + [NVS_FR_BFC0] = "bfc", + [NVS_FR_BFC1] = "bfc.secondary", + [NVS_FR_FOGCOORD] = "fogcoord", + [NVS_FR_POINTSZ] = "pointsize", + [NVS_FR_TEXCOORD0] = "texcoord[0]", + [NVS_FR_TEXCOORD1] = "texcoord[1]", + [NVS_FR_TEXCOORD2] = "texcoord[2]", + [NVS_FR_TEXCOORD3] = "texcoord[3]", + [NVS_FR_TEXCOORD4] = "texcoord[4]", + [NVS_FR_TEXCOORD5] = "texcoord[5]", + [NVS_FR_TEXCOORD6] = "texcoord[6]", + [NVS_FR_TEXCOORD7] = "texcoord[7]", + [NVS_FR_FRAGDATA0] = "data[0]", + [NVS_FR_FRAGDATA1] = "data[1]", + [NVS_FR_FRAGDATA2] = "data[2]", + [NVS_FR_FRAGDATA3] = "data[3]", + [NVS_FR_CLIP0] = "clip_plane[0]", + [NVS_FR_CLIP1] = "clip_plane[1]", + [NVS_FR_CLIP2] = "clip_plane[2]", + [NVS_FR_CLIP3] = "clip_plane[3]", + [NVS_FR_CLIP4] = "clip_plane[4]", + [NVS_FR_CLIP5] = "clip_plane[5]", + [NVS_FR_CLIP6] = "clip_plane[6]", + [NVS_FR_FACING] = "facing", +}; + +#define SFR_STRING(idx) CHECK_RANGE((idx), SFR_STRING) + +static const char *_SWZ_STRING[] = { + [NVS_SWZ_X] = "x", + [NVS_SWZ_Y] = "y", + [NVS_SWZ_Z] = "z", + [NVS_SWZ_W] = "w" +}; + +#define SWZ_STRING(idx) CHECK_RANGE((idx), SWZ_STRING) + +static const char *_NVS_PREC_STRING[] = { + [NVS_PREC_FLOAT32] = "R", + [NVS_PREC_FLOAT16] = "H", + [NVS_PREC_FIXED12] = "X", + [NVS_PREC_UNKNOWN] = "?" +}; + +#define NVS_PREC_STRING(idx) CHECK_RANGE((idx), NVS_PREC_STRING) + +static const char *_NVS_COND_STRING[] = { + [NVS_COND_FL] = "FL", + [NVS_COND_LT] = "LT", + [NVS_COND_EQ] = "EQ", + [NVS_COND_LE] = "LE", + [NVS_COND_GT] = "GT", + [NVS_COND_NE] = "NE", + [NVS_COND_GE] = "GE", + [NVS_COND_TR] = "TR", + [NVS_COND_UNKNOWN] = "??" +}; + +#define NVS_COND_STRING(idx) CHECK_RANGE((idx), NVS_COND_STRING) + +/***************************************************************************** + * ShaderFragment dumping + */ +static void +nvsDumpIndent(int lvl) +{ + while (lvl--) + printf(" "); +} + +static void +nvsDumpSwizzle(nvsSwzComp *swz) +{ + printf(".%s%s%s%s", + SWZ_STRING(swz[0]), + SWZ_STRING(swz[1]), SWZ_STRING(swz[2]), SWZ_STRING(swz[3]) + ); +} + +static void +nvsDumpReg(nvsInstruction * inst, nvsRegister * reg) +{ + if (reg->negate) + printf("-"); + if (reg->abs) + printf("abs("); + + switch (reg->file) { + case NVS_FILE_TEMP: + printf("R%d", reg->index); + nvsDumpSwizzle(reg->swizzle); + break; + case NVS_FILE_ATTRIB: + printf("attrib.%s", SFR_STRING(reg->index)); + nvsDumpSwizzle(reg->swizzle); + break; + case NVS_FILE_ADDRESS: + printf("A%d", reg->index); + break; + case NVS_FILE_CONST: + if (reg->indexed) + printf("const[A%d.%s + %d]", + reg->addr_reg, SWZ_STRING(reg->addr_comp), reg->index); + else + printf("const[%d]", reg->index); + nvsDumpSwizzle(reg->swizzle); + break; + default: + printf("UNKNOWN_FILE"); + break; + } + + if (reg->abs) + printf(")"); +} + +static void +nvsDumpInstruction(nvsInstruction * inst, int slot, int lvl) +{ + struct _opcode_info *opr = &ops[inst->op]; + int i; + + nvsDumpIndent(lvl); + printf("%s ", opr->name); + + if (!opr->flags & NODS) { + switch (inst->dest.file) { + case NVS_FILE_RESULT: + printf("result.%s", SFR_STRING(inst->dest.index)); + break; + case NVS_FILE_TEMP: + printf("R%d", inst->dest.index); + break; + case NVS_FILE_ADDRESS: + printf("A%d", inst->dest.index); + break; + default: + printf("UNKNOWN_DST_FILE"); + break; + } + + if (inst->mask != SMASK_ALL) { + printf("."); + if (inst->mask & SMASK_X) + printf("x"); + if (inst->mask & SMASK_Y) + printf("y"); + if (inst->mask & SMASK_Z) + printf("z"); + if (inst->mask & SMASK_W) + printf("w"); + } + + if (opr->numsrc) + printf(", "); + } + + for (i = 0; i < opr->numsrc; i++) { + nvsDumpReg(inst, &inst->src[i]); + if (i != opr->numsrc - 1) + printf(", "); + } + if (opr->flags & TI_UNIT) + printf(", texture[%d]", inst->tex_unit); + + printf("\n"); +} + +void +nvsDumpFragmentList(nvsFragmentHeader *f, int lvl) +{ + while (f) { + switch (f->type) { + case NVS_INSTRUCTION: + nvsDumpInstruction((nvsInstruction*)f, 0, lvl); + break; + default: + fprintf(stderr, "%s: Only NVS_INSTRUCTION fragments can be in" + "nvsFragmentList!\n", __func__); + return; + } + f = f->next; + } +} + +/***************************************************************************** + * HW shader disassembly + */ +static void +nvsDisasmHWShaderOp(nvsFunc * shader, int merged) +{ + struct _opcode_info *opi; + nvsOpcode op; + nvsRegFile file; + nvsSwzComp swz[4]; + int i; + + op = shader->GetOpcode(shader, merged); + opi = _get_op_info(op); + if (!opi) { + printf("NO OPINFO!"); + return; + } + + printf("%s", opi->name); + if (shader->GetPrecision && + (!(opi->flags & BRANCH_ALL)) && (!(opi->flags * NODS)) && + (op != NVS_OP_NOP)) + printf("%s", NVS_PREC_STRING(shader->GetPrecision(shader))); + if (shader->SupportsConditional && shader->SupportsConditional(shader)) { + if (shader->GetConditionUpdate(shader)) { + printf("C%d", shader->GetCondRegID(shader)); + } + } + if (shader->GetSaturate && shader->GetSaturate(shader)) + printf("_SAT"); + + if (!(opi->flags & NODS)) { + int mask = shader->GetDestMask(shader, merged); + + switch (shader->GetDestFile(shader, merged)) { + case NVS_FILE_ADDRESS: + printf(" A%d", shader->GetDestID(shader, merged)); + break; + case NVS_FILE_TEMP: + printf(" R%d", shader->GetDestID(shader, merged)); + break; + case NVS_FILE_RESULT: + printf(" result.%s", (SFR_STRING(shader->GetDestID(shader, merged)))); + break; + default: + printf(" BAD_RESULT_FILE"); + break; + } + + if (mask != SMASK_ALL) { + printf("."); + if (mask & SMASK_X) printf("x"); + if (mask & SMASK_Y) printf("y"); + if (mask & SMASK_Z) printf("z"); + if (mask & SMASK_W) printf("w"); + } + } + + if (shader->SupportsConditional && shader->SupportsConditional(shader) && + shader->GetConditionTest(shader)) { + shader->GetCondRegSwizzle(shader, swz); + + printf(" (%s%d.%s%s%s%s)", + NVS_COND_STRING(shader->GetCondition(shader)), + shader->GetCondRegID(shader), + SWZ_STRING(swz[NVS_SWZ_X]), + SWZ_STRING(swz[NVS_SWZ_Y]), + SWZ_STRING(swz[NVS_SWZ_Z]), + SWZ_STRING(swz[NVS_SWZ_W]) + ); + } + + /* looping */ + if (opi->flags & COUNT_ALL) { + printf(" { "); + if (opi->flags & COUNT_NUM) { + printf("%d", shader->GetLoopCount(shader)); + } + if (opi->flags & COUNT_IND) { + printf(", %d", shader->GetLoopInitial(shader)); + } + if (opi->flags & COUNT_INC) { + printf(", %d", shader->GetLoopIncrement(shader)); + } + printf(" }"); + } + + /* branching */ + if (opi->flags & BRANCH_TR) + printf(" %d", shader->GetBranch(shader)); + if (opi->flags & BRANCH_EL) + printf(" ELSE %d", shader->GetBranchElse(shader)); + if (opi->flags & BRANCH_EN) + printf(" END %d", shader->GetBranchEnd(shader)); + + if (!(opi->flags & NODS) && opi->numsrc) + printf(","); + printf(" "); + + for (i = 0; i < opi->numsrc; i++) { + if (shader->GetSourceAbs(shader, merged, i)) + printf("abs("); + if (shader->GetSourceNegate(shader, merged, i)) + printf("-"); + + file = shader->GetSourceFile(shader, merged, i); + switch (file) { + case NVS_FILE_TEMP: + printf("R%d", shader->GetSourceID(shader, merged, i)); + break; + case NVS_FILE_CONST: + if (shader->GetSourceIndexed(shader, merged, i)) { + printf("c[A%d.%s + 0x%x]", + shader->GetRelAddressRegID(shader), + SWZ_STRING(shader->GetRelAddressSwizzle(shader)), + shader->GetSourceID(shader, merged, i) + ); + } else { + float val[4]; + + if (shader->GetSourceConstVal) { + shader->GetSourceConstVal(shader, merged, i, val); + printf("{ %.02f, %.02f, %.02f, %.02f }", + val[0], val[1], val[2], val[3]); + } else { + printf("c[0x%x]", shader->GetSourceID(shader, merged, i)); + } + } + break; + case NVS_FILE_ATTRIB: + if (shader->GetSourceIndexed(shader, merged, i)) { + printf("attrib[A%d.%s + %d]", + shader->GetRelAddressRegID(shader), + SWZ_STRING(shader->GetRelAddressSwizzle(shader)), + shader->GetSourceID(shader, merged, i) + ); + } + else { + printf("attrib.%s", + SFR_STRING(shader->GetSourceID(shader, merged, i)) + ); + } + break; + case NVS_FILE_ADDRESS: + printf("A%d", shader->GetRelAddressRegID(shader)); + break; + default: + printf("UNKNOWN_SRC_FILE"); + break; + } + + shader->GetSourceSwizzle(shader, merged, i, swz); + if (file != NVS_FILE_ADDRESS && + (swz[NVS_SWZ_X] != NVS_SWZ_X || swz[NVS_SWZ_Y] != NVS_SWZ_Y || + swz[NVS_SWZ_Z] != NVS_SWZ_Z || swz[NVS_SWZ_W] != NVS_SWZ_W)) { + printf(".%s%s%s%s", SWZ_STRING(swz[NVS_SWZ_X]), + SWZ_STRING(swz[NVS_SWZ_Y]), + SWZ_STRING(swz[NVS_SWZ_Z]), + SWZ_STRING(swz[NVS_SWZ_W])); + } + + if (shader->GetSourceAbs(shader, merged, i)) + printf(")"); + if (shader->GetSourceScale) { + int scale = shader->GetSourceScale(shader, merged, i); + if (scale > 1) + printf("{scaled %dx}", scale); + } + if (i < (opi->numsrc - 1)) + printf(", "); + } + + if (shader->IsLastInst(shader)) + printf(" + END"); +} + +void +nvsDisasmHWShader(nvsPtr nvs) +{ + nvsFunc *shader = nvs->func; + unsigned int iaddr = 0; + + if (!nvs->program) { + fprintf(stderr, "No HW program present"); + return; + } + + shader->inst = nvs->program; + while (1) { + if (shader->inst >= (nvs->program + nvs->program_size)) { + fprintf(stderr, "Reached end of program, but HW inst has no END"); + break; + } + + printf("\t0x%08x:\n", shader->inst[0]); + printf("\t0x%08x:\n", shader->inst[1]); + printf("\t0x%08x:\n", shader->inst[2]); + printf("\t0x%08x:", shader->inst[3]); + + printf("\n\t\tINST %d.0: ", iaddr); + nvsDisasmHWShaderOp(shader, 0); + if (shader->HasMergedInst(shader)) { + printf("\n\t\tINST %d.1: ", iaddr); + nvsDisasmHWShaderOp(shader, 1); + } + printf("\n"); + + if (shader->IsLastInst(shader)) + break; + + shader->inst += shader->GetOffsetNext(shader); + iaddr++; + } + + printf("\n"); +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader.h new file mode 100644 index 000000000..7125a2ae8 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader.h @@ -0,0 +1,454 @@ +#ifndef __SHADER_COMMON_H__ +#define __SHADER_COMMON_H__ + +#include "mtypes.h" +#include "bufferobj.h" + +#define NVSDBG(fmt, args...) do { \ + if (NOUVEAU_DEBUG & DEBUG_SHADERS) { \ + fprintf(stderr, "%s: "fmt, __func__, ##args); \ + } \ +} while(0) + +typedef struct _nvsFunc nvsFunc; + +#define NVS_MAX_TEMPS 32 +#define NVS_MAX_ATTRIBS 16 +#define NVS_MAX_CONSTS 256 +#define NVS_MAX_ADDRESS 2 +#define NVS_MAX_INSNS 4096 + +typedef struct _nvs_fragment_header { + struct _nvs_fragment_header *parent; + struct _nvs_fragment_header *prev; + struct _nvs_fragment_header *next; + enum { + NVS_INSTRUCTION, + NVS_BRANCH, + NVS_LOOP, + NVS_SUBROUTINE + } type; +} nvsFragmentHeader; + +typedef union { + struct { + GLboolean uses_kil; + GLuint num_regs; + } NV30FP; + struct { + uint32_t vp_in_reg; + uint32_t vp_out_reg; + uint32_t clip_enables; + } NV30VP; +} nvsCardPriv; + +typedef struct _nouveauShader { + union { + struct gl_vertex_program vp; + struct gl_fragment_program fp; + } mesa; + GLcontext *ctx; + nvsFunc *func; + + /* State of the final program */ + GLboolean error; + GLboolean translated; + GLboolean on_hardware; + unsigned int *program; + unsigned int program_size; + unsigned int program_alloc_size; + unsigned int program_start_id; + unsigned int program_current; + struct gl_buffer_object *program_buffer; + int inst_count; + + nvsCardPriv card_priv; + int vp_attrib_map[NVS_MAX_ATTRIBS]; + + struct { + GLboolean in_use; + + GLfloat *source_val; /* NULL if invariant */ + float val[4]; + /* Hardware-specific tracking, currently only nv30_fragprog + * makes use of it. + */ + int *hw_index; + int hw_index_cnt; + } params[NVS_MAX_CONSTS]; + int param_high; + + /* Pass-private data */ + void *pass_rec; + + nvsFragmentHeader *program_tree; +} nouveauShader, *nvsPtr; + +typedef enum { + NVS_FILE_NONE, + NVS_FILE_TEMP, + NVS_FILE_ATTRIB, + NVS_FILE_CONST, + NVS_FILE_RESULT, + NVS_FILE_ADDRESS, + NVS_FILE_UNKNOWN +} nvsRegFile; + +typedef enum { + NVS_OP_UNKNOWN = 0, + NVS_OP_NOP, + NVS_OP_ABS, NVS_OP_ADD, NVS_OP_ARA, NVS_OP_ARL, NVS_OP_ARR, + NVS_OP_BRA, NVS_OP_BRK, + NVS_OP_CAL, NVS_OP_CMP, NVS_OP_COS, + NVS_OP_DDX, NVS_OP_DDY, NVS_OP_DIV, NVS_OP_DP2, NVS_OP_DP2A, NVS_OP_DP3, + NVS_OP_DP4, NVS_OP_DPH, NVS_OP_DST, + NVS_OP_EX2, NVS_OP_EXP, + NVS_OP_FLR, NVS_OP_FRC, + NVS_OP_IF, + NVS_OP_KIL, + NVS_OP_LG2, NVS_OP_LIT, NVS_OP_LOG, NVS_OP_LOOP, NVS_OP_LRP, + NVS_OP_MAD, NVS_OP_MAX, NVS_OP_MIN, NVS_OP_MOV, NVS_OP_MUL, + NVS_OP_NRM, + NVS_OP_PK2H, NVS_OP_PK2US, NVS_OP_PK4B, NVS_OP_PK4UB, NVS_OP_POW, + NVS_OP_POPA, NVS_OP_PUSHA, + NVS_OP_RCC, NVS_OP_RCP, NVS_OP_REP, NVS_OP_RET, NVS_OP_RFL, NVS_OP_RSQ, + NVS_OP_SCS, NVS_OP_SEQ, NVS_OP_SFL, NVS_OP_SGE, NVS_OP_SGT, NVS_OP_SIN, + NVS_OP_SLE, NVS_OP_SLT, NVS_OP_SNE, NVS_OP_SSG, NVS_OP_STR, NVS_OP_SUB, + NVS_OP_SWZ, + NVS_OP_TEX, NVS_OP_TXB, NVS_OP_TXD, NVS_OP_TXL, NVS_OP_TXP, + NVS_OP_UP2H, NVS_OP_UP2US, NVS_OP_UP4B, NVS_OP_UP4UB, + NVS_OP_X2D, NVS_OP_XPD, + NVS_OP_EMUL +} nvsOpcode; + +typedef enum { + NVS_PREC_FLOAT32, + NVS_PREC_FLOAT16, + NVS_PREC_FIXED12, + NVS_PREC_UNKNOWN +} nvsPrecision; + +typedef enum { + NVS_SWZ_X = 0, + NVS_SWZ_Y = 1, + NVS_SWZ_Z = 2, + NVS_SWZ_W = 3 +} nvsSwzComp; + +typedef enum { + NVS_FR_POSITION = 0, + NVS_FR_WEIGHT = 1, + NVS_FR_NORMAL = 2, + NVS_FR_COL0 = 3, + NVS_FR_COL1 = 4, + NVS_FR_FOGCOORD = 5, + NVS_FR_TEXCOORD0 = 8, + NVS_FR_TEXCOORD1 = 9, + NVS_FR_TEXCOORD2 = 10, + NVS_FR_TEXCOORD3 = 11, + NVS_FR_TEXCOORD4 = 12, + NVS_FR_TEXCOORD5 = 13, + NVS_FR_TEXCOORD6 = 14, + NVS_FR_TEXCOORD7 = 15, + NVS_FR_BFC0 = 16, + NVS_FR_BFC1 = 17, + NVS_FR_POINTSZ = 18, + NVS_FR_FRAGDATA0 = 19, + NVS_FR_FRAGDATA1 = 20, + NVS_FR_FRAGDATA2 = 21, + NVS_FR_FRAGDATA3 = 22, + NVS_FR_CLIP0 = 23, + NVS_FR_CLIP1 = 24, + NVS_FR_CLIP2 = 25, + NVS_FR_CLIP3 = 26, + NVS_FR_CLIP4 = 27, + NVS_FR_CLIP5 = 28, + NVS_FR_CLIP6 = 29, + NVS_FR_FACING = 30, + NVS_FR_UNKNOWN +} nvsFixedReg; + +typedef enum { + NVS_COND_FL, NVS_COND_LT, NVS_COND_EQ, NVS_COND_LE, NVS_COND_GT, + NVS_COND_NE, NVS_COND_GE, NVS_COND_TR, NVS_COND_UN, + NVS_COND_UNKNOWN +} nvsCond; + +typedef struct { + nvsRegFile file; + unsigned int index; + + unsigned int indexed; + unsigned int addr_reg; + nvsSwzComp addr_comp; + + nvsSwzComp swizzle[4]; + int negate; + int abs; +} nvsRegister; + +static const nvsRegister nvr_unused = { + .file = NVS_FILE_ATTRIB, + .index = 0, + .indexed = 0, + .addr_reg = 0, + .addr_comp = NVS_SWZ_X, + .swizzle = {NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W}, + .negate = 0, + .abs = 0, +}; + +typedef enum { + NVS_TEX_TARGET_1D, + NVS_TEX_TARGET_2D, + NVS_TEX_TARGET_3D, + NVS_TEX_TARGET_CUBE, + NVS_TEX_TARGET_RECT, + NVS_TEX_TARGET_UNKNOWN = 0 +} nvsTexTarget; + +typedef enum { + NVS_SCALE_1X = 0, + NVS_SCALE_2X = 1, + NVS_SCALE_4X = 2, + NVS_SCALE_8X = 3, + NVS_SCALE_INV_2X = 5, + NVS_SCALE_INV_4X = 6, + NVS_SCALE_INV_8X = 7, +} nvsScale; + +/* Arith/TEX instructions */ +typedef struct nvs_instruction { + nvsFragmentHeader header; + + nvsOpcode op; + unsigned int saturate; + + nvsRegister dest; + unsigned int mask; + nvsScale dest_scale; + + nvsRegister src[3]; + + unsigned int tex_unit; + nvsTexTarget tex_target; + + nvsCond cond; + nvsSwzComp cond_swizzle[4]; + int cond_reg; + int cond_test; + int cond_update; +} nvsInstruction; + +/* BRA, CAL, IF */ +typedef struct nvs_branch { + nvsFragmentHeader header; + + nvsOpcode op; + + nvsCond cond; + nvsSwzComp cond_swizzle[4]; + int cond_test; + + nvsFragmentHeader *target_head; + nvsFragmentHeader *target_tail; + nvsFragmentHeader *else_head; + nvsFragmentHeader *else_tail; +} nvsBranch; + +/* LOOP+ENDLOOP */ +typedef struct { + nvsFragmentHeader header; + + int count; + int initial; + int increment; + + nvsFragmentHeader *insn_head; + nvsFragmentHeader *insn_tail; +} nvsLoop; + +/* label+following instructions */ +typedef struct nvs_subroutine { + nvsFragmentHeader header; + + char * label; + nvsFragmentHeader *insn_head; + nvsFragmentHeader *insn_tail; +} nvsSubroutine; + +#define SMASK_X (1<<0) +#define SMASK_Y (1<<1) +#define SMASK_Z (1<<2) +#define SMASK_W (1<<3) +#define SMASK_ALL (SMASK_X|SMASK_Y|SMASK_Z|SMASK_W) + +#define SPOS_ADDRESS 3 +struct _op_xlat { + unsigned int NV; + nvsOpcode SOP; + int srcpos[3]; +}; +#define MOD_OPCODE(t,hw,sop,s0,s1,s2) do { \ + t[hw].NV = hw; \ + t[hw].SOP = sop; \ + t[hw].srcpos[0] = s0; \ + t[hw].srcpos[1] = s1; \ + t[hw].srcpos[2] = s2; \ +} while(0) + +extern unsigned int NVVP_TX_VOP_COUNT; +extern unsigned int NVVP_TX_NVS_OP_COUNT; +extern struct _op_xlat NVVP_TX_VOP[]; +extern struct _op_xlat NVVP_TX_SOP[]; + +extern unsigned int NVFP_TX_AOP_COUNT; +extern unsigned int NVFP_TX_BOP_COUNT; +extern struct _op_xlat NVFP_TX_AOP[]; +extern struct _op_xlat NVFP_TX_BOP[]; + +extern void NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz); +extern nvsSwzComp NV20VP_TX_SWIZZLE[4]; + +#define SCAP_SRC_ABS (1<<0) + +struct _nvsFunc { + nvsCardPriv *card_priv; + + unsigned int MaxInst; + unsigned int MaxAttrib; + unsigned int MaxTemp; + unsigned int MaxAddress; + unsigned int MaxConst; + unsigned int caps; + + unsigned int *inst; + void (*UploadToHW) (GLcontext *, nouveauShader *); + void (*UpdateConst) (GLcontext *, nouveauShader *, int); + + struct _op_xlat*(*GetOPTXRec) (nvsFunc *, int merged); + struct _op_xlat*(*GetOPTXFromSOP) (nvsOpcode, int *id); + + void (*InitInstruction) (nvsFunc *); + int (*SupportsOpcode) (nvsFunc *, nvsOpcode); + int (*SupportsResultScale) (nvsFunc *, nvsScale); + void (*SetOpcode) (nvsFunc *, unsigned int opcode, + int slot); + void (*SetCCUpdate) (nvsFunc *); + void (*SetCondition) (nvsFunc *, int on, nvsCond, int reg, + nvsSwzComp *swizzle); + void (*SetResult) (nvsFunc *, nvsRegister *, + unsigned int mask, int slot); + void (*SetResultScale) (nvsFunc *, nvsScale); + void (*SetSource) (nvsFunc *, nvsRegister *, int pos); + void (*SetTexImageUnit) (nvsFunc *, int unit); + void (*SetSaturate) (nvsFunc *); + void (*SetLastInst) (nvsFunc *); + + void (*SetBranchTarget) (nvsFunc *, int addr); + void (*SetBranchElse) (nvsFunc *, int addr); + void (*SetBranchEnd) (nvsFunc *, int addr); + void (*SetLoopParams) (nvsFunc *, int cnt, int init, int inc); + + int (*HasMergedInst) (nvsFunc *); + int (*IsLastInst) (nvsFunc *); + int (*GetOffsetNext) (nvsFunc *); + + int (*GetOpcodeSlot) (nvsFunc *, int merged); + unsigned int (*GetOpcodeHW) (nvsFunc *, int slot); + nvsOpcode (*GetOpcode) (nvsFunc *, int merged); + + nvsPrecision (*GetPrecision) (nvsFunc *); + int (*GetSaturate) (nvsFunc *); + + nvsRegFile (*GetDestFile) (nvsFunc *, int merged); + unsigned int (*GetDestID) (nvsFunc *, int merged); + unsigned int (*GetDestMask) (nvsFunc *, int merged); + + unsigned int (*GetSourceHW) (nvsFunc *, int merged, int pos); + nvsRegFile (*GetSourceFile) (nvsFunc *, int merged, int pos); + int (*GetSourceID) (nvsFunc *, int merged, int pos); + int (*GetTexImageUnit) (nvsFunc *); + int (*GetSourceNegate) (nvsFunc *, int merged, int pos); + int (*GetSourceAbs) (nvsFunc *, int merged, int pos); + void (*GetSourceSwizzle) (nvsFunc *, int merged, int pos, + nvsSwzComp *swz); + int (*GetSourceIndexed) (nvsFunc *, int merged, int pos); + void (*GetSourceConstVal) (nvsFunc *, int merged, int pos, + float *val); + int (*GetSourceScale) (nvsFunc *, int merged, int pos); + + int (*GetRelAddressRegID) (nvsFunc *); + nvsSwzComp (*GetRelAddressSwizzle) (nvsFunc *); + + int (*SupportsConditional) (nvsFunc *); + int (*GetConditionUpdate) (nvsFunc *); + int (*GetConditionTest) (nvsFunc *); + nvsCond (*GetCondition) (nvsFunc *); + void (*GetCondRegSwizzle) (nvsFunc *, nvsSwzComp *swz); + int (*GetCondRegID) (nvsFunc *); + int (*GetBranch) (nvsFunc *); + int (*GetBranchElse) (nvsFunc *); + int (*GetBranchEnd) (nvsFunc *); + + int (*GetLoopCount) (nvsFunc *); + int (*GetLoopInitial) (nvsFunc *); + int (*GetLoopIncrement) (nvsFunc *); +}; + +static inline nvsRegister +nvsNegate(nvsRegister reg) +{ + reg.negate = !reg.negate; + return reg; +} + +static inline nvsRegister +nvsAbs(nvsRegister reg) +{ + reg.abs = 1; + return reg; +} + +static inline nvsRegister +nvsSwizzle(nvsRegister reg, nvsSwzComp x, nvsSwzComp y, + nvsSwzComp z, nvsSwzComp w) +{ + nvsSwzComp sc[4] = { x, y, z, w }; + nvsSwzComp oc[4]; + int i; + + for (i=0;i<4;i++) + oc[i] = reg.swizzle[i]; + for (i=0;i<4;i++) + reg.swizzle[i] = oc[sc[i]]; + return reg; +} + +#define nvsProgramError(nvs,fmt,args...) do { \ + fprintf(stderr, "nvsProgramError (%s): "fmt, __func__, ##args); \ + (nvs)->error = GL_TRUE; \ + (nvs)->translated = GL_FALSE; \ +} while(0) + +extern GLboolean nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs); +extern void nvsDisasmHWShader(nvsPtr); +extern void nvsDumpFragmentList(nvsFragmentHeader *f, int lvl); +extern nouveauShader *nvsBuildTextShader(GLcontext *ctx, GLenum target, + const char *text); + +extern void NV20VPInitShaderFuncs(nvsFunc *); +extern void NV30VPInitShaderFuncs(nvsFunc *); +extern void NV40VPInitShaderFuncs(nvsFunc *); + +extern void NV30FPInitShaderFuncs(nvsFunc *); +extern void NV40FPInitShaderFuncs(nvsFunc *); + +extern void nouveauShaderInitFuncs(GLcontext *ctx); + +extern GLboolean nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs); +extern GLboolean nouveau_shader_pass1(nvsPtr nvs); +extern GLboolean nouveau_shader_pass2(nvsPtr nvs); + +#endif + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c new file mode 100644 index 000000000..8c203cc66 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c @@ -0,0 +1,1050 @@ +/* + * Copyright (C) 2006 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* + * Authors: + * Ben Skeggs <darktama@iinet.net.au> + */ + +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "shader/prog_instruction.h" +#include "shader/prog_parameter.h" +#include "shader/prog_statevars.h" +#include "shader/programopt.h" + +#include "nouveau_context.h" +#include "nouveau_shader.h" +#include "nouveau_msg.h" + +static nvsFixedReg _tx_mesa_vp_dst_reg[VERT_RESULT_MAX] = { + NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD, + NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, + NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7, + NVS_FR_POINTSZ, NVS_FR_BFC0, NVS_FR_BFC1, NVS_FR_UNKNOWN /* EDGE */ +}; + +static nvsFixedReg _tx_mesa_fp_dst_reg[FRAG_RESULT_MAX] = { + NVS_FR_FRAGDATA0 /* COLR */, NVS_FR_FRAGDATA0 /* COLH */, + NVS_FR_UNKNOWN /* DEPR */ +}; + +static nvsFixedReg _tx_mesa_fp_src_reg[FRAG_ATTRIB_MAX] = { + NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD, + NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, + NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7 +}; + +static nvsSwzComp _tx_mesa_swizzle[4] = { + NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W +}; + +static nvsOpcode _tx_mesa_opcode[] = { + [OPCODE_ABS] = NVS_OP_ABS, [OPCODE_ADD] = NVS_OP_ADD, + [OPCODE_ARA] = NVS_OP_ARA, [OPCODE_ARL] = NVS_OP_ARL, + [OPCODE_ARL_NV] = NVS_OP_ARL, [OPCODE_ARR] = NVS_OP_ARR, + [OPCODE_CMP] = NVS_OP_CMP, [OPCODE_COS] = NVS_OP_COS, + [OPCODE_DDX] = NVS_OP_DDX, [OPCODE_DDY] = NVS_OP_DDY, + [OPCODE_DP3] = NVS_OP_DP3, [OPCODE_DP4] = NVS_OP_DP4, + [OPCODE_DPH] = NVS_OP_DPH, [OPCODE_DST] = NVS_OP_DST, + [OPCODE_EX2] = NVS_OP_EX2, [OPCODE_EXP] = NVS_OP_EXP, + [OPCODE_FLR] = NVS_OP_FLR, [OPCODE_FRC] = NVS_OP_FRC, + [OPCODE_KIL] = NVS_OP_EMUL, [OPCODE_KIL_NV] = NVS_OP_KIL, + [OPCODE_LG2] = NVS_OP_LG2, [OPCODE_LIT] = NVS_OP_LIT, + [OPCODE_LOG] = NVS_OP_LOG, + [OPCODE_LRP] = NVS_OP_LRP, + [OPCODE_MAD] = NVS_OP_MAD, [OPCODE_MAX] = NVS_OP_MAX, + [OPCODE_MIN] = NVS_OP_MIN, [OPCODE_MOV] = NVS_OP_MOV, + [OPCODE_MUL] = NVS_OP_MUL, + [OPCODE_PK2H] = NVS_OP_PK2H, [OPCODE_PK2US] = NVS_OP_PK2US, + [OPCODE_PK4B] = NVS_OP_PK4B, [OPCODE_PK4UB] = NVS_OP_PK4UB, + [OPCODE_POW] = NVS_OP_POW, [OPCODE_POPA] = NVS_OP_POPA, + [OPCODE_PUSHA] = NVS_OP_PUSHA, + [OPCODE_RCC] = NVS_OP_RCC, [OPCODE_RCP] = NVS_OP_RCP, + [OPCODE_RFL] = NVS_OP_RFL, [OPCODE_RSQ] = NVS_OP_RSQ, + [OPCODE_SCS] = NVS_OP_SCS, [OPCODE_SEQ] = NVS_OP_SEQ, + [OPCODE_SFL] = NVS_OP_SFL, [OPCODE_SGE] = NVS_OP_SGE, + [OPCODE_SGT] = NVS_OP_SGT, [OPCODE_SIN] = NVS_OP_SIN, + [OPCODE_SLE] = NVS_OP_SLE, [OPCODE_SLT] = NVS_OP_SLT, + [OPCODE_SNE] = NVS_OP_SNE, [OPCODE_SSG] = NVS_OP_SSG, + [OPCODE_STR] = NVS_OP_STR, [OPCODE_SUB] = NVS_OP_SUB, + [OPCODE_SWZ] = NVS_OP_MOV, + [OPCODE_TEX] = NVS_OP_TEX, [OPCODE_TXB] = NVS_OP_TXB, + [OPCODE_TXD] = NVS_OP_TXD, + [OPCODE_TXL] = NVS_OP_TXL, [OPCODE_TXP] = NVS_OP_TXP, + [OPCODE_TXP_NV] = NVS_OP_TXP, + [OPCODE_UP2H] = NVS_OP_UP2H, [OPCODE_UP2US] = NVS_OP_UP2US, + [OPCODE_UP4B] = NVS_OP_UP4B, [OPCODE_UP4UB] = NVS_OP_UP4UB, + [OPCODE_X2D] = NVS_OP_X2D, + [OPCODE_XPD] = NVS_OP_XPD +}; + +static nvsCond _tx_mesa_condmask[] = { + NVS_COND_TR, /* workaround mesa not filling a valid value */ + NVS_COND_GT, NVS_COND_LT, NVS_COND_UN, NVS_COND_GE, + NVS_COND_LE, NVS_COND_NE, NVS_COND_NE, NVS_COND_TR, NVS_COND_FL +}; + +struct pass0_rec { + int nvs_ipos; + int next_temp; + + int mesa_const_base; + int mesa_const_last; + + int swzconst_done; + int swzconst_id; + nvsRegister const_half; +}; + +#define X NVS_SWZ_X +#define Y NVS_SWZ_Y +#define Z NVS_SWZ_Z +#define W NVS_SWZ_W + +#define FILL_CONDITION_FLAGS(fragment) do { \ + (fragment)->cond = \ + pass0_make_condmask(inst->DstReg.CondMask); \ + if ((fragment)->cond != NVS_COND_TR) \ + (fragment)->cond_test = 1; \ + (fragment)->cond_reg = inst->CondDst; \ + pass0_make_swizzle((fragment)->cond_swizzle, inst->DstReg.CondSwizzle);\ +} while(0) + +#define ARITH(op,dest,mask,sat,s0,s1,s2) do { \ + nvsinst = pass0_emit(nvs, parent, fpos, (op), \ + (dest), (mask), (sat), (s0), (s1), (s2));\ + FILL_CONDITION_FLAGS(nvsinst); \ +} while(0) + +#define ARITHu(op,dest,mask,sat,s0,s1,s2) do { \ + nvsinst = pass0_emit(nvs, parent, fpos, (op), \ + (dest), (mask), (sat), (s0), (s1), (s2));\ +} while(0) + +static void +pass0_append_fragment(nvsFragmentHeader *parent, + nvsFragmentHeader *fragment, + int pos) +{ + nvsFragmentHeader **head, **tail; + assert(parent && fragment); + + switch (parent->type) { + case NVS_BRANCH: + if (pos == 0) { + head = &((nvsBranch *)parent)->target_head; + tail = &((nvsBranch *)parent)->target_tail; + } else { + head = &((nvsBranch *)parent)->else_head; + tail = &((nvsBranch *)parent)->else_tail; + } + break; + case NVS_LOOP: + head = &((nvsLoop *)parent)->insn_head; + tail = &((nvsLoop *)parent)->insn_tail; + break; + case NVS_SUBROUTINE: + head = &((nvsSubroutine *)parent)->insn_head; + tail = &((nvsSubroutine *)parent)->insn_tail; + break; + default: + assert(0); + break; + } + + fragment->parent = parent; + fragment->prev = *tail; + fragment->next = NULL; + if (!(*head)) + *head = fragment; + else + (*tail)->next = fragment; + *tail = fragment; + +} + +static nvsSubroutine * +pass0_create_subroutine(nouveauShader *nvs, const char *label) +{ + nvsSubroutine *sub; + + sub = CALLOC_STRUCT(nvs_subroutine); + if (sub) { + sub->header.type = NVS_SUBROUTINE; + sub->label = strdup(label); + if (!nvs->program_tree) + nvs->program_tree = &sub->header; + else + pass0_append_fragment(nvs->program_tree, + &sub->header, 0); + } + + return sub; +} + +static void +pass0_make_reg(nouveauShader *nvs, nvsRegister *reg, + nvsRegFile file, unsigned int index) +{ + struct pass0_rec *rec = nvs->pass_rec; + + /* defaults */ + *reg = nvr_unused; + /* -1 == quick-and-dirty temp alloc */ + if (file == NVS_FILE_TEMP && index == -1) { + index = rec->next_temp++; + assert(index < NVS_MAX_TEMPS); + } + reg->file = file; + reg->index = index; +} + +static void +pass0_make_swizzle(nvsSwzComp *swz, unsigned int mesa) +{ + int i; + + for (i=0;i<4;i++) + swz[i] = _tx_mesa_swizzle[GET_SWZ(mesa, i)]; +} + +static nvsOpcode +pass0_make_opcode(enum prog_opcode op) +{ + if (op > MAX_OPCODE) + return NVS_OP_UNKNOWN; + return _tx_mesa_opcode[op]; +} + +static nvsCond +pass0_make_condmask(GLuint mesa) +{ + if (mesa > COND_FL) + return NVS_COND_UNKNOWN; + return _tx_mesa_condmask[mesa]; +} + +static unsigned int +pass0_make_mask(GLuint mesa_mask) +{ + unsigned int mask = 0; + + if (mesa_mask & WRITEMASK_X) mask |= SMASK_X; + if (mesa_mask & WRITEMASK_Y) mask |= SMASK_Y; + if (mesa_mask & WRITEMASK_Z) mask |= SMASK_Z; + if (mesa_mask & WRITEMASK_W) mask |= SMASK_W; + + return mask; +} + +static GLboolean +pass0_opcode_is_tex(enum prog_opcode op) +{ + switch (op) { + case OPCODE_TEX: + case OPCODE_TXB: + case OPCODE_TXD: + case OPCODE_TXL: + case OPCODE_TXP: + return GL_TRUE; + default: + break; + } + + return GL_FALSE; +} + +static nvsTexTarget +pass0_make_tex_target(GLuint mesa) +{ + switch (mesa) { + case TEXTURE_1D_INDEX: return NVS_TEX_TARGET_1D; + case TEXTURE_2D_INDEX: return NVS_TEX_TARGET_2D; + case TEXTURE_3D_INDEX: return NVS_TEX_TARGET_3D; + case TEXTURE_CUBE_INDEX: return NVS_TEX_TARGET_CUBE; + case TEXTURE_RECT_INDEX: return NVS_TEX_TARGET_RECT; + default: + return NVS_TEX_TARGET_UNKNOWN; + } +} + +static void +pass0_make_dst_reg(nvsPtr nvs, nvsRegister *reg, + struct prog_dst_register *dst) +{ + struct gl_program *mesa = (struct gl_program*)&nvs->mesa.vp; + nvsFixedReg sfr; + + switch (dst->File) { + case PROGRAM_OUTPUT: + if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { + sfr = (dst->Index < VERT_RESULT_MAX) ? + _tx_mesa_vp_dst_reg[dst->Index] : + NVS_FR_UNKNOWN; + } else { + sfr = (dst->Index < FRAG_RESULT_MAX) ? + _tx_mesa_fp_dst_reg[dst->Index] : + NVS_FR_UNKNOWN; + } + pass0_make_reg(nvs, reg, NVS_FILE_RESULT, sfr); + break; + case PROGRAM_TEMPORARY: + pass0_make_reg(nvs, reg, NVS_FILE_TEMP, dst->Index); + break; + case PROGRAM_ADDRESS: + pass0_make_reg(nvs, reg, NVS_FILE_ADDRESS, dst->Index); + break; + default: + fprintf(stderr, "Unknown dest file %d\n", dst->File); + assert(0); + } +} + +static void +pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src) +{ + struct pass0_rec *rec = nvs->pass_rec; + struct gl_program *mesa = (struct gl_program *)&nvs->mesa.vp.Base; + int i; + + *reg = nvr_unused; + + switch (src->File) { + case PROGRAM_INPUT: + reg->file = NVS_FILE_ATTRIB; + if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { + for (i=0; i<NVS_MAX_ATTRIBS; i++) { + if (nvs->vp_attrib_map[i] == src->Index) { + reg->index = i; + break; + } + } + if (i==NVS_MAX_ATTRIBS) + reg->index = NVS_FR_UNKNOWN; + } else { + reg->index = (src->Index < FRAG_ATTRIB_MAX) ? + _tx_mesa_fp_src_reg[src->Index] : + NVS_FR_UNKNOWN; + } + break; + case PROGRAM_STATE_VAR: + case PROGRAM_NAMED_PARAM: + case PROGRAM_CONSTANT: + reg->file = NVS_FILE_CONST; + reg->index = src->Index + rec->mesa_const_base; + reg->indexed = src->RelAddr; + if (reg->indexed) { + reg->addr_reg = 0; + reg->addr_comp = NVS_SWZ_X; + } + break; + case PROGRAM_TEMPORARY: + reg->file = NVS_FILE_TEMP; + reg->index = src->Index; + break; + default: + fprintf(stderr, "Unknown source type %d\n", src->File); + assert(0); + } + + /* per-component negate handled elsewhere */ + reg->negate = src->NegateBase != 0; + reg->abs = src->Abs; + pass0_make_swizzle(reg->swizzle, src->Swizzle); +} + +static nvsInstruction * +pass0_emit(nouveauShader *nvs, nvsFragmentHeader *parent, int fpos, + nvsOpcode op, nvsRegister dst, + unsigned int mask, int saturate, + nvsRegister src0, nvsRegister src1, nvsRegister src2) +{ + nvsInstruction *sif; + + sif = CALLOC_STRUCT(nvs_instruction); + if (!sif) + return NULL; + + /* Seems mesa doesn't explicitly 0 this.. */ + if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB) + saturate = 0; + + sif->op = op; + sif->saturate = saturate; + sif->dest = dst; + sif->mask = mask; + sif->dest_scale = NVS_SCALE_1X; + sif->src[0] = src0; + sif->src[1] = src1; + sif->src[2] = src2; + sif->cond = COND_TR; + sif->cond_reg = 0; + sif->cond_test = 0; + sif->cond_update= 0; + pass0_make_swizzle(sif->cond_swizzle, SWIZZLE_NOOP); + pass0_append_fragment(parent, &sif->header, fpos); + + return sif; +} + +static void +pass0_fixup_swizzle(nvsPtr nvs, nvsFragmentHeader *parent, int fpos, + struct prog_src_register *src, + unsigned int sm1, + unsigned int sm2) +{ + static const float sc[4] = { 1.0, 0.0, -1.0, 0.0 }; + struct pass0_rec *rec = nvs->pass_rec; + int fixup_1, fixup_2; + nvsInstruction *nvsinst; + nvsRegister sr, dr = nvr_unused; + nvsRegister sm1const, sm2const; + + if (!rec->swzconst_done) { + struct gl_program *prog = &nvs->mesa.vp.Base; + GLuint swizzle; + rec->swzconst_id = _mesa_add_unnamed_constant(prog->Parameters, + sc, 4, &swizzle); + /* XXX what about swizzle? */ + rec->swzconst_done = 1; + COPY_4V(nvs->params[rec->swzconst_id].val, sc); + } + + fixup_1 = (sm1 != MAKE_SWIZZLE4(0,0,0,0) && + sm2 != MAKE_SWIZZLE4(2,2,2,2)); + fixup_2 = (sm2 != MAKE_SWIZZLE4(2,2,2,2)); + + if (src->File != PROGRAM_TEMPORARY && src->File != PROGRAM_INPUT) { + /* We can't use more than one const in an instruction, + * so move the const into a temp, and swizzle from there. + * + * TODO: should just emit the swizzled const, instead of + * swizzling it in the shader.. would need to reswizzle + * any state params when they change however.. + */ + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + pass0_make_src_reg(nvs, &sr, src); + ARITHu(NVS_OP_MOV, dr, SMASK_ALL, 0, + sr, nvr_unused, nvr_unused); + pass0_make_reg(nvs, &sr, NVS_FILE_TEMP, dr.index); + } else { + if (fixup_1) + src->NegateBase = 0; + pass0_make_src_reg(nvs, &sr, src); + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + } + + pass0_make_reg(nvs, &sm1const, NVS_FILE_CONST, rec->swzconst_id); + pass0_make_swizzle(sm1const.swizzle, sm1); + if (fixup_1 && fixup_2) { + /* Any combination with SWIZZLE_ONE */ + pass0_make_reg(nvs, &sm2const, + NVS_FILE_CONST, rec->swzconst_id); + pass0_make_swizzle(sm2const.swizzle, sm2); + ARITHu(NVS_OP_MAD, dr, SMASK_ALL, 0, sr, sm1const, sm2const); + } else { + /* SWIZZLE_ZERO || arbitrary negate */ + ARITHu(NVS_OP_MUL, dr, SMASK_ALL, 0, sr, sm1const, nvr_unused); + } + + src->File = PROGRAM_TEMPORARY; + src->Index = dr.index; + src->Swizzle = SWIZZLE_NOOP; +} + +#define SET_SWZ(fs, cp, c) fs = (fs & ~(0x7<<(cp*3))) | (c<<(cp*3)) +static void +pass0_check_sources(nvsPtr nvs, nvsFragmentHeader *parent, int fpos, + struct prog_instruction *inst) +{ + unsigned int insrc = -1, constsrc = -1; + int i; + + for (i=0;i<_mesa_num_inst_src_regs(inst->Opcode);i++) { + struct prog_src_register *src = &inst->SrcReg[i]; + unsigned int sm_1 = 0, sm_2 = 0; + nvsRegister sr, dr; + int do_mov = 0, c; + + /* Build up swizzle masks as if we were going to use + * "MAD new, src, const1, const2" to support arbitrary negation + * and SWIZZLE_ZERO/SWIZZLE_ONE. + */ + for (c=0;c<4;c++) { + if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ZERO) { + SET_SWZ(sm_1, c, SWIZZLE_Y); /* 0.0 */ + SET_SWZ(sm_2, c, SWIZZLE_Y); + SET_SWZ(src->Swizzle, c, SWIZZLE_X); + } else if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ONE) { + SET_SWZ(sm_1, c, SWIZZLE_Y); + if (src->NegateBase & (1<<c)) + SET_SWZ(sm_2, c, SWIZZLE_Z); /* -1.0 */ + else + SET_SWZ(sm_2, c, SWIZZLE_X); /* 1.0 */ + SET_SWZ(src->Swizzle, c, SWIZZLE_X); + } else { + if (src->NegateBase & (1<<c)) + SET_SWZ(sm_1, c, SWIZZLE_Z); /* -[xyzw] */ + else + SET_SWZ(sm_1, c, SWIZZLE_X); /*[xyzw]*/ + SET_SWZ(sm_2, c, SWIZZLE_Y); + } + } + + /* Unless we're multiplying by 1.0 or -1.0 on all components, + * and we're adding nothing to any component we have to + * emulate the swizzle. + */ + if ((sm_1 != MAKE_SWIZZLE4(0,0,0,0) && + sm_1 != MAKE_SWIZZLE4(2,2,2,2)) || + sm_2 != MAKE_SWIZZLE4(1,1,1,1)) { + pass0_fixup_swizzle(nvs, parent, fpos, src, sm_1, sm_2); + /* The source is definitely in a temp now, so don't + * bother checking for multiple ATTRIB/CONST regs. + */ + continue; + } + + /* HW can't use more than one ATTRIB or PARAM in a single + * instruction */ + switch (src->File) { + case PROGRAM_INPUT: + if (insrc != -1 && insrc != src->Index) + do_mov = 1; + else insrc = src->Index; + break; + case PROGRAM_STATE_VAR: + if (constsrc != -1 && constsrc != src->Index) + do_mov = 1; + else constsrc = src->Index; + break; + default: + break; + } + + /* Emit any extra ATTRIB/CONST to a temp, and modify the Mesa + * instruction to point at the temp. + */ + if (do_mov) { + pass0_make_src_reg(nvs, &sr, src); + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + pass0_emit(nvs, parent, fpos, NVS_OP_MOV, + dr, SMASK_ALL, 0, + sr, nvr_unused, nvr_unused); + + src->File = PROGRAM_TEMPORARY; + src->Index = dr.index; + src->Swizzle= SWIZZLE_NOOP; + } + } +} + +static GLboolean +pass0_emulate_instruction(nouveauShader *nvs, + nvsFragmentHeader *parent, int fpos, + struct prog_instruction *inst) +{ + nvsFunc *shader = nvs->func; + nvsRegister src[3], dest, temp; + nvsInstruction *nvsinst; + unsigned int mask = pass0_make_mask(inst->DstReg.WriteMask); + int i, sat; + + sat = (inst->SaturateMode == SATURATE_ZERO_ONE); + + /* Build all the "real" regs for the instruction */ + for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) + pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); + if (inst->Opcode != OPCODE_KIL) + pass0_make_dst_reg(nvs, &dest, &inst->DstReg); + + switch (inst->Opcode) { + case OPCODE_ABS: + if (shader->caps & SCAP_SRC_ABS) + ARITH(NVS_OP_MOV, dest, mask, sat, + nvsAbs(src[0]), nvr_unused, nvr_unused); + else + ARITH(NVS_OP_MAX, dest, mask, sat, + src[0], nvsNegate(src[0]), nvr_unused); + break; + case OPCODE_CMP: + /*XXX: this will clobber CC0... */ + ARITH (NVS_OP_MOV, dest, mask, sat, + src[2], nvr_unused, nvr_unused); + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + ARITHu(NVS_OP_MOV, temp, SMASK_ALL, 0, + src[0], nvr_unused, nvr_unused); + nvsinst->cond_update = 1; + nvsinst->cond_reg = 0; + ARITH (NVS_OP_MOV, dest, mask, sat, + src[1], nvr_unused, nvr_unused); + nvsinst->cond = COND_LT; + nvsinst->cond_reg = 0; + nvsinst->cond_test = 1; + break; + case OPCODE_DPH: + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + ARITHu(NVS_OP_DP3, temp, SMASK_X, 0, + src[0], src[1], nvr_unused); + ARITH (NVS_OP_ADD, dest, mask, sat, + nvsSwizzle(temp, X, X, X, X), + nvsSwizzle(src[1], W, W, W, W), + nvr_unused); + break; + case OPCODE_KIL: + /* This is only in ARB shaders, so we don't have to worry + * about clobbering a CC reg as they aren't supported anyway. + *XXX: might have to worry with GLSL however... + */ + /* MOVC0 temp, src */ + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + ARITHu(NVS_OP_MOV, temp, SMASK_ALL, 0, + src[0], nvr_unused, nvr_unused); + nvsinst->cond_update = 1; + nvsinst->cond_reg = 0; + /* KIL_NV (LT0.xyzw) temp */ + ARITHu(NVS_OP_KIL, nvr_unused, 0, 0, + nvr_unused, nvr_unused, nvr_unused); + nvsinst->cond = COND_LT; + nvsinst->cond_reg = 0; + nvsinst->cond_test = 1; + pass0_make_swizzle(nvsinst->cond_swizzle, SWIZZLE_NOOP); + break; + case OPCODE_LRP: + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + ARITHu(NVS_OP_MAD, temp, mask, 0, + nvsNegate(src[0]), src[2], src[2]); + ARITH (NVS_OP_MAD, dest, mask, sat, src[0], src[1], temp); + break; + case OPCODE_POW: + if (shader->SupportsOpcode(shader, NVS_OP_LG2) && + shader->SupportsOpcode(shader, NVS_OP_EX2)) { + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + /* LG2 temp.x, src0.c */ + ARITHu(NVS_OP_LG2, temp, SMASK_X, 0, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, nvr_unused); + /* MUL temp.x, temp.x, src1.c */ + ARITHu(NVS_OP_MUL, temp, SMASK_X, 0, + nvsSwizzle(temp, X, X, X, X), + nvsSwizzle(src[1], X, X, X, X), + nvr_unused); + /* EX2 dest, temp.x */ + ARITH (NVS_OP_EX2, dest, mask, sat, + nvsSwizzle(temp, X, X, X, X), + nvr_unused, nvr_unused); + } else { + /* can we use EXP/LOG instead of EX2/LG2?? */ + fprintf(stderr, "Implement POW for NV20 vtxprog!\n"); + return GL_FALSE; + } + break; + case OPCODE_RSQ: + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + ARITHu(NVS_OP_LG2, temp, SMASK_X, 0, + nvsAbs(nvsSwizzle(src[0], X, X, X, X)), + nvr_unused, nvr_unused); + nvsinst->dest_scale = NVS_SCALE_INV_2X; + ARITH (NVS_OP_EX2, dest, mask, sat, + nvsNegate(nvsSwizzle(temp, X, X, X, X)), + nvr_unused, nvr_unused); + break; + case OPCODE_SCS: + if (mask & SMASK_X) + ARITH(NVS_OP_COS, dest, SMASK_X, sat, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, nvr_unused); + if (mask & SMASK_Y) + ARITH(NVS_OP_SIN, dest, SMASK_Y, sat, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, nvr_unused); + break; + case OPCODE_SUB: + ARITH(NVS_OP_ADD, dest, mask, sat, + src[0], nvsNegate(src[1]), nvr_unused); + break; + case OPCODE_XPD: + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + ARITHu(NVS_OP_MUL, temp, SMASK_ALL, 0, + nvsSwizzle(src[0], Z, X, Y, Y), + nvsSwizzle(src[1], Y, Z, X, X), + nvr_unused); + ARITH (NVS_OP_MAD, dest, (mask & ~SMASK_W), sat, + nvsSwizzle(src[0], Y, Z, X, X), + nvsSwizzle(src[1], Z, X, Y, Y), + nvsNegate(temp)); + break; + default: + WARN_ONCE("hw doesn't support opcode \"%s\"," + "and no emulation found\n", + _mesa_opcode_string(inst->Opcode)); + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean +pass0_translate_arith(nouveauShader *nvs, struct gl_program *prog, + int ipos, int fpos, + nvsFragmentHeader *parent) +{ + struct prog_instruction *inst = &prog->Instructions[ipos]; + nvsFunc *shader = nvs->func; + nvsInstruction *nvsinst; + GLboolean ret; + + /* Deal with multiple ATTRIB/PARAM in a single instruction */ + pass0_check_sources(nvs, parent, fpos, inst); + + /* Now it's safe to do the prog_instruction->nvsInstruction + * conversion + */ + if (shader->SupportsOpcode(shader, + pass0_make_opcode(inst->Opcode))) { + nvsRegister src[3], dest; + int i; + + for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) + pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); + pass0_make_dst_reg(nvs, &dest, &inst->DstReg); + + ARITH(pass0_make_opcode(inst->Opcode), dest, + pass0_make_mask(inst->DstReg.WriteMask), + (inst->SaturateMode != SATURATE_OFF), + src[0], src[1], src[2]); + nvsinst->tex_unit = inst->TexSrcUnit; + if (pass0_opcode_is_tex(inst->Opcode)) + nvsinst->tex_target = + pass0_make_tex_target(inst->TexSrcTarget); + else + nvsinst->tex_target = NVS_TEX_TARGET_UNKNOWN; + + ret = GL_TRUE; + } else + ret = pass0_emulate_instruction(nvs, parent, fpos, inst); + + return ret; +} + +static GLboolean +pass0_translate_instructions(nouveauShader *nvs, int ipos, int fpos, + nvsFragmentHeader *parent) +{ + struct gl_program *prog = (struct gl_program *)&nvs->mesa.vp; + + while (1) { + struct prog_instruction *inst = &prog->Instructions[ipos]; + + switch (inst->Opcode) { + case OPCODE_END: + return GL_TRUE; + case OPCODE_BRA: + case OPCODE_CAL: + case OPCODE_RET: + //case OPCODE_LOOP: + //case OPCODE_ENDLOOP: + //case OPCODE_IF: + //case OPCODE_ELSE: + //case OPCODE_ENDIF: + WARN_ONCE("branch ops unimplemented\n"); + return GL_FALSE; + break; + default: + if (!pass0_translate_arith(nvs, prog, + ipos, fpos, parent)) + return GL_FALSE; + break; + } + + ipos++; + } + + return GL_TRUE; +} + +static void +pass0_build_attrib_map(nouveauShader *nvs, struct gl_vertex_program *vp) +{ + GLuint inputs_read = vp->Base.InputsRead; + GLuint input_alloc = ~0xFFFF; + int i; + + for (i=0; i<NVS_MAX_ATTRIBS; i++) + nvs->vp_attrib_map[i] = -1; + + while (inputs_read) { + int in = ffs(inputs_read) - 1; + int hw; + inputs_read &= ~(1<<in); + + if (vp->IsNVProgram) { + /* NVvp: must alias */ + if (in >= VERT_ATTRIB_GENERIC0) + hw = in - VERT_ATTRIB_GENERIC0; + else + hw = in; + } else { + /* ARBvp: may alias (but we won't) + * GL2.0: must not alias + */ + if (in >= VERT_ATTRIB_GENERIC0) + hw = ffs(~input_alloc) - 1; + else + hw = in; + input_alloc |= (1<<hw); + } + + nvs->vp_attrib_map[hw] = in; + } + + if (NOUVEAU_DEBUG & DEBUG_SHADERS) { + printf("vtxprog attrib map:\n"); + for (i=0; i<NVS_MAX_ATTRIBS; i++) { + printf(" hw:%d = attrib:%d\n", + i, nvs->vp_attrib_map[i]); + } + } +} + +static void +pass0_vp_insert_ff_clip_planes(GLcontext *ctx, nouveauShader *nvs) +{ + struct gl_program *prog = &nvs->mesa.vp.Base; + nvsFragmentHeader *parent = nvs->program_tree; + nvsInstruction *nvsinst; + GLuint fpos = 0; + nvsRegister opos, epos, eqn, mv[4]; + gl_state_index tokens[STATE_LENGTH] + = { STATE_MODELVIEW_MATRIX, 0, 0, 0, 0 }; + GLint id; + int i; + + /* modelview transform */ + pass0_make_reg(nvs, &opos, NVS_FILE_ATTRIB, NVS_FR_POSITION); + pass0_make_reg(nvs, &epos, NVS_FILE_TEMP , -1); + for (i=0; i<4; i++) { + tokens[2] = tokens[3] = i; + id = _mesa_add_state_reference(prog->Parameters, tokens); + pass0_make_reg(nvs, &mv[i], NVS_FILE_CONST, id); + } + ARITHu(NVS_OP_DP4, epos, SMASK_X, 0, opos, mv[0], nvr_unused); + ARITHu(NVS_OP_DP4, epos, SMASK_Y, 0, opos, mv[1], nvr_unused); + ARITHu(NVS_OP_DP4, epos, SMASK_Z, 0, opos, mv[2], nvr_unused); + ARITHu(NVS_OP_DP4, epos, SMASK_W, 0, opos, mv[3], nvr_unused); + + /* Emit code to emulate fixed-function glClipPlane */ + for (i=0; i<6; i++) { + GLuint clipmask = SMASK_X; + nvsRegister clip; + + if (!(ctx->Transform.ClipPlanesEnabled & (1<<i))) + continue; + + /* Point a const at a user clipping plane */ + tokens[0] = STATE_CLIPPLANE; + tokens[1] = i; + id = _mesa_add_state_reference(prog->Parameters, tokens); + pass0_make_reg(nvs, &eqn , NVS_FILE_CONST , id); + pass0_make_reg(nvs, &clip, NVS_FILE_RESULT, NVS_FR_CLIP0 + i); + + /*XXX: something else needs to take care of modifying the + * instructions to write to the correct hw clip register. + */ + switch (i) { + case 0: case 3: clipmask = SMASK_Y; break; + case 1: case 4: clipmask = SMASK_Z; break; + case 2: case 5: clipmask = SMASK_W; break; + } + + /* Emit transform */ + ARITHu(NVS_OP_DP4, clip, clipmask, 0, epos, eqn, nvr_unused); + } +} + +static void +pass0_rebase_mesa_consts(nouveauShader *nvs) +{ + struct pass0_rec *rec = nvs->pass_rec; + struct gl_program *prog = &nvs->mesa.vp.Base; + struct prog_instruction *inst = prog->Instructions; + int i; + + /*XXX: not a good idea, params->hw_index is malloc'd */ + memset(nvs->params, 0x00, sizeof(nvs->params)); + + /* When doing relative addressing on constants, the hardware needs us + * to fill the "const id" field with a positive value. Determine the + * most negative index that is used so that all accesses to a + * mesa-provided constant can be rebased to a positive index. + */ + while (inst->Opcode != OPCODE_END) { + for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) { + struct prog_src_register *src = &inst->SrcReg[i]; + + switch (src->File) { + case PROGRAM_STATE_VAR: + case PROGRAM_CONSTANT: + case PROGRAM_NAMED_PARAM: + if (src->RelAddr && src->Index < 0) { + int base = src->Index * -1; + if (rec->mesa_const_base < base) + rec->mesa_const_base = base; + } + break; + default: + break; + } + } + + inst++; + } +} + +static GLboolean +pass0_resolve_mesa_consts(nouveauShader *nvs) +{ + struct pass0_rec *rec = nvs->pass_rec; + struct gl_program *prog = &nvs->mesa.vp.Base; + struct gl_program_parameter_list *plist = prog->Parameters; + int i; + + /* Init all const tracking/alloc info from the parameter list, rather + * than doing it as we translate the program. Otherwise: + * 1) we can't get at the correct constant info when relative + * addressing is being used due to src->Index not pointing + * at the exact const; + * 2) as we add extra consts to the program, mesa will call realloc() + * and we get invalid pointers to the const data. + */ + rec->mesa_const_last = plist->NumParameters + rec->mesa_const_base; + nvs->param_high = rec->mesa_const_last; + for (i=0; i<plist->NumParameters; i++) { + int hw = rec->mesa_const_base + i; + + if (hw > NVS_MAX_CONSTS) { + nvsProgramError(nvs, "hw = %d > NVS_MAX_CONSTS!\n", hw); + return GL_FALSE; + } + + switch (plist->Parameters[i].Type) { + case PROGRAM_NAMED_PARAM: + case PROGRAM_STATE_VAR: + nvs->params[hw].in_use = GL_TRUE; + nvs->params[hw].source_val = plist->ParameterValues[i]; + COPY_4V(nvs->params[hw].val, plist->ParameterValues[i]); + break; + case PROGRAM_CONSTANT: + nvs->params[hw].in_use = GL_TRUE; + nvs->params[hw].source_val = NULL; + COPY_4V(nvs->params[hw].val, plist->ParameterValues[i]); + break; + default: + nvsProgramError(nvs, "hit bad type=%d on param %d\n", + plist->Parameters[i].Type, i); + return GL_FALSE; + } + } + + return GL_TRUE; +} + +GLboolean +nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + struct gl_program *prog = (struct gl_program*)nvs; + struct gl_vertex_program *vp = (struct gl_vertex_program *)prog; + struct gl_fragment_program *fp = (struct gl_fragment_program *)prog; + struct pass0_rec *rec; + int ret = GL_FALSE; + + NVSDBG("start: nvs=%p\n", nvs); + + /* Previously detected an error, and haven't recieved new program + * string, so fail immediately. + */ + if (nvs->error) { + NVSDBG("failed previous compile attempt, not retrying\n"); + return GL_FALSE; + } + + rec = CALLOC_STRUCT(pass0_rec); + if (!rec) + return GL_FALSE; + + rec->next_temp = prog->NumTemporaries; + nvs->pass_rec = rec; + + nvs->program_tree = (nvsFragmentHeader*) + pass0_create_subroutine(nvs, "program body"); + if (!nvs->program_tree) { + FREE(rec); + return GL_FALSE; + } + + switch (prog->Target) { + case GL_VERTEX_PROGRAM_ARB: + nvs->func = &nmesa->VPfunc; + + if (vp->IsPositionInvariant) + _mesa_insert_mvp_code(ctx, vp); + pass0_rebase_mesa_consts(nvs); + + if (!prog->String && ctx->Transform.ClipPlanesEnabled) + pass0_vp_insert_ff_clip_planes(ctx, nvs); + + pass0_build_attrib_map(nvs, vp); + break; + case GL_FRAGMENT_PROGRAM_ARB: + nvs->func = &nmesa->FPfunc; + + if (fp->FogOption != GL_NONE) + _mesa_append_fog_code(ctx, fp); + pass0_rebase_mesa_consts(nvs); + break; + default: + fprintf(stderr, "Unknown program type %d", prog->Target); + FREE(rec); + /* DESTROY TREE!! */ + return GL_FALSE; + } + nvs->func->card_priv = &nvs->card_priv; + + ret = pass0_translate_instructions(nvs, 0, 0, nvs->program_tree); + if (ret) + ret = pass0_resolve_mesa_consts(nvs); + + /*XXX: if (!ret) DESTROY TREE!!! */ + + FREE(rec); + return ret; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c new file mode 100644 index 000000000..78c1401f7 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c @@ -0,0 +1,16 @@ +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "nouveau_context.h" +#include "nouveau_shader.h" + +GLboolean +nouveau_shader_pass1(nvsPtr nvs) +{ + NVSDBG("start: nvs=%p\n", nvs); + + return GL_TRUE; +} + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c new file mode 100644 index 000000000..cd27daca8 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2006 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* + * Authors: + * Ben Skeggs <darktama@iinet.net.au> + */ + +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "shader/prog_parameter.h" +#include "shader/prog_print.h" + +#include "nouveau_context.h" +#include "nouveau_shader.h" +#include "nouveau_msg.h" + +struct pass2_rec { + /* Map nvsRegister temp ID onto hw temp ID */ + unsigned int temps[NVS_MAX_TEMPS]; + /* Track free hw registers */ + unsigned int hw_temps[NVS_MAX_TEMPS]; +}; + +static int +pass2_alloc_hw_temp(nvsPtr nvs) +{ + struct pass2_rec *rec = nvs->pass_rec; + int i; + + for (i=0; i<nvs->func->MaxTemp; i++) { + /* This is a *horrible* hack.. R0 is both temp0 and result.color + * in NV30/40 fragprogs, we can use R0 as a temp before result + * is written however.. + */ + if (nvs->mesa.vp.Base.Target == GL_FRAGMENT_PROGRAM_ARB && i==0) + continue; + if (rec->hw_temps[i] == 0) { + rec->hw_temps[i] = 1; + return i; + } + } + + return -1; +} + +static nvsRegister +pass2_mangle_reg(nvsPtr nvs, nvsInstruction *inst, nvsRegister reg) +{ + struct pass2_rec *rec = nvs->pass_rec; + + if (reg.file == NVS_FILE_TEMP) { + if (rec->temps[reg.index] == -1) + rec->temps[reg.index] = pass2_alloc_hw_temp(nvs); + reg.index = rec->temps[reg.index]; + } + + return reg; +} + +static void +pass2_add_instruction(nvsPtr nvs, nvsInstruction *inst, + struct _op_xlat *op, int slot) +{ + nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, + NVS_SWZ_Z, NVS_SWZ_W }; + nvsFunc *shader = nvs->func; + nvsRegister reg; + int i; + + shader->SetOpcode(shader, op->NV, slot); + if (inst->saturate ) shader->SetSaturate(shader); + if (inst->cond_update ) shader->SetCCUpdate(shader); + if (inst->cond_test ) shader->SetCondition(shader, 1, inst->cond, + inst->cond_reg, + inst->cond_swizzle); + else shader->SetCondition(shader, 0, NVS_COND_TR, + 0, + default_swz); + switch (inst->op) { + case NVS_OP_TEX: + case NVS_OP_TXB: + case NVS_OP_TXL: + case NVS_OP_TXP: + case NVS_OP_TXD: + shader->SetTexImageUnit(shader, inst->tex_unit); + break; + default: + break; + } + + for (i = 0; i < 3; i++) { + if (op->srcpos[i] != -1) { + reg = pass2_mangle_reg(nvs, inst, inst->src[i]); + + shader->SetSource(shader, ®, op->srcpos[i]); + + if (reg.file == NVS_FILE_CONST && + shader->GetSourceConstVal) { + int idx_slot = + nvs->params[reg.index].hw_index_cnt++; + nvs->params[reg.index].hw_index = realloc( + nvs->params[reg.index].hw_index, + sizeof(int) * idx_slot+1); + nvs->params[reg.index].hw_index[idx_slot] = + nvs->program_current + 4; + } + } + } + + reg = pass2_mangle_reg(nvs, inst, inst->dest); + shader->SetResult(shader, ®, inst->mask, slot); + + if (inst->dest_scale != NVS_SCALE_1X) { + shader->SetResultScale(shader, inst->dest_scale); + } +} + +static int +pass2_assemble_instruction(nvsPtr nvs, nvsInstruction *inst, int last) +{ + nvsFunc *shader = nvs->func; + struct _op_xlat *op; + unsigned int hw_inst[8]; + int slot; + int instsz; + int i; + + shader->inst = hw_inst; + + /* Assemble this instruction */ + if (!(op = shader->GetOPTXFromSOP(inst->op, &slot))) + return 0; + shader->InitInstruction(shader); + pass2_add_instruction(nvs, inst, op, slot); + if (last) + shader->SetLastInst(shader); + + instsz = shader->GetOffsetNext(nvs->func); + if (nvs->program_size + instsz >= nvs->program_alloc_size) { + nvs->program_alloc_size *= 2; + nvs->program = realloc(nvs->program, + nvs->program_alloc_size * + sizeof(uint32_t)); + } + + for (i=0; i<instsz; i++) + nvs->program[nvs->program_current++] = hw_inst[i]; + nvs->program_size = nvs->program_current; + return 1; +} + +static GLboolean +pass2_translate(nvsPtr nvs, nvsFragmentHeader *f) +{ + nvsFunc *shader = nvs->func; + GLboolean last; + + while (f) { + last = (f == ((nvsSubroutine*)nvs->program_tree)->insn_tail); + + switch (f->type) { + case NVS_INSTRUCTION: + if (!pass2_assemble_instruction(nvs, + (nvsInstruction *)f, + last)) + return GL_FALSE; + break; + default: + WARN_ONCE("Unimplemented fragment type\n"); + return GL_FALSE; + } + + f = f->next; + } + + return GL_TRUE; +} + +/* Translate program into hardware format */ +GLboolean +nouveau_shader_pass2(nvsPtr nvs) +{ + struct pass2_rec *rec; + int i; + + NVSDBG("start: nvs=%p\n", nvs); + + rec = calloc(1, sizeof(struct pass2_rec)); + for (i=0; i<NVS_MAX_TEMPS; i++) + rec->temps[i] = -1; + nvs->pass_rec = rec; + + /* Start off with allocating 4 uint32_t's for each inst, will be grown + * if necessary.. + */ + nvs->program_alloc_size = nvs->mesa.vp.Base.NumInstructions * 4; + nvs->program = calloc(nvs->program_alloc_size, sizeof(uint32_t)); + nvs->program_size = 0; + nvs->program_current = 0; + + if (!pass2_translate(nvs, + ((nvsSubroutine*)nvs->program_tree)->insn_head)) { + free(nvs->program); + nvs->program = NULL; + return GL_FALSE; + } + + /* Shrink allocated memory to only what we need */ + nvs->program = realloc(nvs->program, + nvs->program_size * sizeof(uint32_t)); + nvs->program_alloc_size = nvs->program_size; + + nvs->translated = 1; + nvs->on_hardware = 0; + + if (NOUVEAU_DEBUG & DEBUG_SHADERS) { + fflush(stdout); fflush(stderr); + fprintf(stderr, "-----------MESA PROGRAM target=%s, id=0x%x\n", + _mesa_lookup_enum_by_nr( + nvs->mesa.vp.Base.Target), + nvs->mesa.vp.Base.Id); + fflush(stdout); fflush(stderr); + _mesa_print_program(&nvs->mesa.vp.Base); + fflush(stdout); fflush(stderr); + fprintf(stderr, "^^^^^^^^^^^^^^^^MESA PROGRAM\n"); + fflush(stdout); fflush(stderr); + fprintf(stderr, "----------------NV PROGRAM\n"); + fflush(stdout); fflush(stderr); + nvsDisasmHWShader(nvs); + fflush(stdout); fflush(stderr); + fprintf(stderr, "^^^^^^^^^^^^^^^^NV PROGRAM\n"); + fflush(stdout); fflush(stderr); + } + + return GL_TRUE; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_span.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_span.c new file mode 100644 index 000000000..74dec66af --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_span.c @@ -0,0 +1,125 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#include "nouveau_context.h" +#include "nouveau_span.h" +#include "nouveau_fifo.h" +#include "nouveau_lock.h" + +#include "swrast/swrast.h" + +#define HAVE_HW_DEPTH_SPANS 0 +#define HAVE_HW_DEPTH_PIXELS 0 +#define HAVE_HW_STENCIL_SPANS 0 +#define HAVE_HW_STENCIL_PIXELS 0 + +#define HW_CLIPLOOP() \ + do { \ + int _nc = nmesa->numClipRects; \ + while ( _nc-- ) { \ + int minx = nmesa->pClipRects[_nc].x1 - nmesa->drawX; \ + int miny = nmesa->pClipRects[_nc].y1 - nmesa->drawY; \ + int maxx = nmesa->pClipRects[_nc].x2 - nmesa->drawX; \ + int maxy = nmesa->pClipRects[_nc].y2 - nmesa->drawY; + +#define LOCAL_VARS \ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); \ + nouveau_renderbuffer *nrb = (nouveau_renderbuffer *)rb; \ + GLuint height = nrb->mesa.Height; \ + GLubyte *map = (GLubyte *)(nrb->map ? nrb->map : nrb->mem->map) + \ + (nmesa->drawY * nrb->pitch) + (nmesa->drawX * nrb->cpp); \ + GLuint p; \ + (void) p; + +#define Y_FLIP( _y ) (height - _y - 1) + +#define HW_LOCK() + +#define HW_UNLOCK() + + + +/* ================================================================ + * Color buffers + */ + +/* RGB565 */ +#define SPANTMP_PIXEL_FMT GL_RGB +#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5 + +#define TAG(x) nouveau##x##_RGB565 +#define TAG2(x,y) nouveau##x##_RGB565##y +#define GET_PTR(X,Y) (map + (Y)*nrb->pitch + (X)*nrb->cpp) +#include "spantmp2.h" + + +/* ARGB8888 */ +#define SPANTMP_PIXEL_FMT GL_BGRA +#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV + +#define TAG(x) nouveau##x##_ARGB8888 +#define TAG2(x,y) nouveau##x##_ARGB8888##y +#define GET_PTR(X,Y) (map + (Y)*nrb->pitch + (X)*nrb->cpp) +#include "spantmp2.h" + +static void +nouveauSpanRenderStart( GLcontext *ctx ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + FIRE_RING(); + LOCK_HARDWARE(nmesa); + nouveauWaitForIdleLocked( nmesa ); +} + +static void +nouveauSpanRenderFinish( GLcontext *ctx ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + _swrast_flush( ctx ); + nouveauWaitForIdleLocked( nmesa ); + UNLOCK_HARDWARE( nmesa ); +} + +void nouveauSpanInitFunctions( GLcontext *ctx ) +{ + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); + swdd->SpanRenderStart = nouveauSpanRenderStart; + swdd->SpanRenderFinish = nouveauSpanRenderFinish; +} + + +/** + * Plug in the Get/Put routines for the given driRenderbuffer. + */ +void +nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis) +{ + if (nrb->mesa._ActualFormat == GL_RGBA8) + nouveauInitPointers_ARGB8888(&nrb->mesa); + else if (nrb->mesa._ActualFormat == GL_RGB5) + nouveauInitPointers_RGB565(&nrb->mesa); +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_span.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_span.h new file mode 100644 index 000000000..bc39ecd17 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_span.h @@ -0,0 +1,39 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + + +#ifndef __NOUVEAU_SPAN_H__ +#define __NOUVEAU_SPAN_H__ + +#include "drirenderbuffer.h" +#include "nouveau_buffers.h" + +extern void nouveauSpanInitFunctions( GLcontext *ctx ); +extern void nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis); + +#endif /* __NOUVEAU_SPAN_H__ */ + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state.c new file mode 100644 index 000000000..e9fd188d7 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state.c @@ -0,0 +1,345 @@ +/************************************************************************** + +Copyright 2006 Jeremy Kolb +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "nouveau_context.h" +#include "nouveau_state.h" +#include "nouveau_swtcl.h" +#include "nouveau_fifo.h" + +#include "swrast/swrast.h" +#include "tnl/tnl.h" +#include "swrast_setup/swrast_setup.h" + +#include "tnl/t_pipeline.h" + +#include "mtypes.h" +#include "colormac.h" + +static __inline__ GLuint nouveauPackColor(GLuint format, + GLubyte r, GLubyte g, + GLubyte b, GLubyte a) +{ + switch (format) { + case 2: + return PACK_COLOR_565( r, g, b ); + case 4: + return PACK_COLOR_8888( r, g, b, a); + default: + fprintf(stderr, "unknown format %d\n", (int)format); + return 0; + } +} + +static void nouveauCalcViewport(GLcontext *ctx) +{ + /* Calculate the Viewport Matrix */ + + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + const GLfloat *v = ctx->Viewport._WindowMap.m; + GLfloat *m = nmesa->viewport.m; + GLfloat xoffset = nmesa->drawX, yoffset = nmesa->drawY; + + nmesa->depth_scale = 1.0 / ctx->DrawBuffer->_DepthMaxF; + + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + xoffset + SUBPIXEL_X; + m[MAT_SY] = - v[MAT_SY]; + m[MAT_TY] = v[MAT_TY] + yoffset + SUBPIXEL_Y; + m[MAT_SZ] = v[MAT_SZ] * nmesa->depth_scale; + m[MAT_TZ] = v[MAT_TZ] * nmesa->depth_scale; + + nmesa->hw_func.WindowMoved(nmesa); +} + +static void nouveauViewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + /* + * Need to send (at least on an nv35 the following: + * cons = 4 (this may be bytes per pixel) + * + * The viewport: + * 445 0x0000bee0 {size: 0x0 channel: 0x1 cmd: 0x00009ee0} <-- VIEWPORT_SETUP/HEADER ? + * 446 0x00000000 {size: 0x0 channel: 0x0 cmd: 0x00000000} <-- x * cons + * 447 0x00000c80 {size: 0x0 channel: 0x0 cmd: 0x00000c80} <-- (height + x) * cons + * 448 0x00000000 {size: 0x0 channel: 0x0 cmd: 0x00000000} <-- y * cons + * 449 0x00000960 {size: 0x0 channel: 0x0 cmd: 0x00000960} <-- (width + y) * cons + * 44a 0x00082a00 {size: 0x2 channel: 0x1 cmd: 0x00000a00} <-- VIEWPORT_DIMS + * 44b 0x04000000 <-- (Width_from_glViewport << 16) | x + * 44c 0x03000000 <-- (Height_from_glViewport << 16) | (win_height - height - y) + * + */ + + nouveauCalcViewport(ctx); +} + +static void nouveauDepthRange(GLcontext *ctx, GLclampd near, GLclampd far) +{ + nouveauCalcViewport(ctx); +} + +static void nouveauDDUpdateHWState(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + int new_state = nmesa->new_state; + + if ( new_state || nmesa->new_render_state & _NEW_TEXTURE ) + { + nmesa->new_state = 0; + + /* Update the various parts of the context's state. + */ + /* + if ( new_state & NOUVEAU_NEW_ALPHA ) + nouveauUpdateAlphaMode( ctx ); + + if ( new_state & NOUVEAU_NEW_DEPTH ) + nouveauUpdateZMode( ctx ); + + if ( new_state & NOUVEAU_NEW_FOG ) + nouveauUpdateFogAttrib( ctx ); + + if ( new_state & NOUVEAU_NEW_CLIP ) + nouveauUpdateClipping( ctx ); + + if ( new_state & NOUVEAU_NEW_CULL ) + nouveauUpdateCull( ctx ); + + if ( new_state & NOUVEAU_NEW_MASKS ) + nouveauUpdateMasks( ctx ); + + if ( new_state & NOUVEAU_NEW_WINDOW ) + nouveauUpdateWindow( ctx ); + + if ( nmesa->new_render_state & _NEW_TEXTURE ) { + nouveauUpdateTextureState( ctx ); + }*/ + } +} + +static void nouveauDDInvalidateState(GLcontext *ctx, GLuint new_state) +{ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + NOUVEAU_CONTEXT(ctx)->new_render_state |= new_state; +} + +/* Initialize the context's hardware state. */ +void nouveauDDInitState(nouveauContextPtr nmesa) +{ + uint32_t type = nmesa->screen->card->type; + switch(type) + { + case NV_03: + /* Unimplemented */ + break; + case NV_04: + case NV_05: + nv04InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver); + break; + case NV_10: + nv10InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver); + break; + case NV_20: + nv20InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver); + break; + case NV_30: + case NV_40: + case NV_44: + nv30InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver); + break; + case NV_50: + nv50InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver); + break; + default: + break; + } + nouveau_state_cache_init(nmesa); +} + +/* Initialize the driver's state functions */ +void nouveauDDInitStateFuncs(GLcontext *ctx) +{ + ctx->Driver.UpdateState = nouveauDDInvalidateState; + + ctx->Driver.ClearIndex = NULL; + ctx->Driver.ClearColor = NULL; //nouveauDDClearColor; + ctx->Driver.ClearStencil = NULL; //nouveauDDClearStencil; + ctx->Driver.DrawBuffer = NULL; //nouveauDDDrawBuffer; + ctx->Driver.ReadBuffer = NULL; //nouveauDDReadBuffer; + + ctx->Driver.IndexMask = NULL; + ctx->Driver.ColorMask = NULL; //nouveauDDColorMask; + ctx->Driver.AlphaFunc = NULL; //nouveauDDAlphaFunc; + ctx->Driver.BlendEquationSeparate = NULL; //nouveauDDBlendEquationSeparate; + ctx->Driver.BlendFuncSeparate = NULL; //nouveauDDBlendFuncSeparate; + ctx->Driver.ClearDepth = NULL; //nouveauDDClearDepth; + ctx->Driver.CullFace = NULL; //nouveauDDCullFace; + ctx->Driver.FrontFace = NULL; //nouveauDDFrontFace; + ctx->Driver.DepthFunc = NULL; //nouveauDDDepthFunc; + ctx->Driver.DepthMask = NULL; //nouveauDDDepthMask; + ctx->Driver.Enable = NULL; //nouveauDDEnable; + ctx->Driver.Fogfv = NULL; //nouveauDDFogfv; + ctx->Driver.Hint = NULL; + ctx->Driver.Lightfv = NULL; + ctx->Driver.LightModelfv = NULL; //nouveauDDLightModelfv; + ctx->Driver.LogicOpcode = NULL; //nouveauDDLogicOpCode; + ctx->Driver.PolygonMode = NULL; + ctx->Driver.PolygonStipple = NULL; //nouveauDDPolygonStipple; + ctx->Driver.RenderMode = NULL; //nouveauDDRenderMode; + ctx->Driver.Scissor = NULL; //nouveauDDScissor; + ctx->Driver.ShadeModel = NULL; //nouveauDDShadeModel; + ctx->Driver.StencilFuncSeparate = NULL; //nouveauDDStencilFuncSeparate; + ctx->Driver.StencilMaskSeparate = NULL; //nouveauDDStencilMaskSeparate; + ctx->Driver.StencilOpSeparate = NULL; //nouveauDDStencilOpSeparate; + + ctx->Driver.DepthRange = nouveauDepthRange; + ctx->Driver.Viewport = nouveauViewport; + + /* Pixel path fallbacks. + */ + ctx->Driver.Accum = _swrast_Accum; + ctx->Driver.Bitmap = _swrast_Bitmap; + ctx->Driver.CopyPixels = _swrast_CopyPixels; + ctx->Driver.DrawPixels = _swrast_DrawPixels; + ctx->Driver.ReadPixels = _swrast_ReadPixels; + + /* Swrast hooks for imaging extensions: + */ + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; +} + +#define STATE_INIT(a) if (ctx->Driver.a) ctx->Driver.a + +void nouveauInitState(GLcontext *ctx) +{ + /* + * Mesa should do this for us: + */ + + STATE_INIT(AlphaFunc)( ctx, + ctx->Color.AlphaFunc, + ctx->Color.AlphaRef); + + STATE_INIT(BlendColor)( ctx, + ctx->Color.BlendColor ); + + STATE_INIT(BlendEquationSeparate)( ctx, + ctx->Color.BlendEquationRGB, + ctx->Color.BlendEquationA); + + STATE_INIT(BlendFuncSeparate)( ctx, + ctx->Color.BlendSrcRGB, + ctx->Color.BlendDstRGB, + ctx->Color.BlendSrcA, + ctx->Color.BlendDstA); + + STATE_INIT(ClearColor)( ctx, ctx->Color.ClearColor); + STATE_INIT(ClearDepth)( ctx, ctx->Depth.Clear); + STATE_INIT(ClearStencil)( ctx, ctx->Stencil.Clear); + + STATE_INIT(ColorMask)( ctx, + ctx->Color.ColorMask[RCOMP], + ctx->Color.ColorMask[GCOMP], + ctx->Color.ColorMask[BCOMP], + ctx->Color.ColorMask[ACOMP]); + + STATE_INIT(CullFace)( ctx, ctx->Polygon.CullFaceMode ); + STATE_INIT(DepthFunc)( ctx, ctx->Depth.Func ); + STATE_INIT(DepthMask)( ctx, ctx->Depth.Mask ); + + STATE_INIT(Enable)( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled ); + STATE_INIT(Enable)( ctx, GL_BLEND, ctx->Color.BlendEnabled ); + STATE_INIT(Enable)( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled ); + STATE_INIT(Enable)( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled ); + STATE_INIT(Enable)( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag ); + STATE_INIT(Enable)( ctx, GL_DEPTH_TEST, ctx->Depth.Test ); + STATE_INIT(Enable)( ctx, GL_DITHER, ctx->Color.DitherFlag ); + STATE_INIT(Enable)( ctx, GL_FOG, ctx->Fog.Enabled ); + STATE_INIT(Enable)( ctx, GL_LIGHTING, ctx->Light.Enabled ); + STATE_INIT(Enable)( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag ); + STATE_INIT(Enable)( ctx, GL_LINE_STIPPLE, ctx->Line.StippleFlag ); + STATE_INIT(Enable)( ctx, GL_POINT_SMOOTH, ctx->Point.SmoothFlag ); + STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_FILL, ctx->Polygon.OffsetFill); + STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_LINE, ctx->Polygon.OffsetLine); + STATE_INIT(Enable)( ctx, GL_POLYGON_OFFSET_POINT, ctx->Polygon.OffsetPoint); + STATE_INIT(Enable)( ctx, GL_POLYGON_SMOOTH, ctx->Polygon.SmoothFlag ); + STATE_INIT(Enable)( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag ); + STATE_INIT(Enable)( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled ); + STATE_INIT(Enable)( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled ); + STATE_INIT(Enable)( ctx, GL_TEXTURE_1D, GL_FALSE ); + STATE_INIT(Enable)( ctx, GL_TEXTURE_2D, GL_FALSE ); + STATE_INIT(Enable)( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE ); + STATE_INIT(Enable)( ctx, GL_TEXTURE_3D, GL_FALSE ); + STATE_INIT(Enable)( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE ); + + STATE_INIT(Fogfv)( ctx, GL_FOG_COLOR, ctx->Fog.Color ); + STATE_INIT(Fogfv)( ctx, GL_FOG_MODE, 0 ); + STATE_INIT(Fogfv)( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); + STATE_INIT(Fogfv)( ctx, GL_FOG_START, &ctx->Fog.Start ); + STATE_INIT(Fogfv)( ctx, GL_FOG_END, &ctx->Fog.End ); + + STATE_INIT(FrontFace)( ctx, ctx->Polygon.FrontFace ); + + { + GLfloat f = (GLfloat)ctx->Light.Model.ColorControl; + STATE_INIT(LightModelfv)( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f ); + } + + STATE_INIT(LineStipple)( ctx, ctx->Line.StippleFactor, ctx->Line.StipplePattern ); + STATE_INIT(LineWidth)( ctx, ctx->Line.Width ); + STATE_INIT(LogicOpcode)( ctx, ctx->Color.LogicOp ); + STATE_INIT(PointSize)( ctx, ctx->Point.Size ); + STATE_INIT(PolygonMode)( ctx, GL_FRONT, ctx->Polygon.FrontMode ); + STATE_INIT(PolygonMode)( ctx, GL_BACK, ctx->Polygon.BackMode ); + STATE_INIT(PolygonOffset)( ctx, + ctx->Polygon.OffsetFactor, + ctx->Polygon.OffsetUnits ); + STATE_INIT(PolygonStipple)( ctx, (const GLubyte *)ctx->PolygonStipple ); + STATE_INIT(ShadeModel)( ctx, ctx->Light.ShadeModel ); + STATE_INIT(StencilFuncSeparate)( ctx, GL_FRONT, + ctx->Stencil.Function[0], + ctx->Stencil.Ref[0], + ctx->Stencil.ValueMask[0] ); + STATE_INIT(StencilFuncSeparate)( ctx, GL_BACK, + ctx->Stencil.Function[1], + ctx->Stencil.Ref[1], + ctx->Stencil.ValueMask[1] ); + STATE_INIT(StencilMaskSeparate)( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] ); + STATE_INIT(StencilMaskSeparate)( ctx, GL_BACK, ctx->Stencil.WriteMask[1] ); + STATE_INIT(StencilOpSeparate)( ctx, GL_FRONT, + ctx->Stencil.FailFunc[0], + ctx->Stencil.ZFailFunc[0], + ctx->Stencil.ZPassFunc[0]); + STATE_INIT(StencilOpSeparate)( ctx, GL_BACK, + ctx->Stencil.FailFunc[1], + ctx->Stencil.ZFailFunc[1], + ctx->Stencil.ZPassFunc[1]); +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state.h new file mode 100644 index 000000000..dbac71760 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state.h @@ -0,0 +1,50 @@ +/************************************************************************** + +Copyright 2006 Jeremy Kolb +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef __NOUVEAU_STATE_H__ +#define __NOUVEAU_STATE_H__ + +#include "nouveau_context.h" + +extern void nouveauDDInitState(nouveauContextPtr nmesa); +extern void nouveauDDInitStateFuncs(GLcontext *ctx); + +extern void nv04InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); +extern void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); +extern void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); +extern void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); +extern void nv50InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); + +extern void nouveauInitState(GLcontext *ctx); + +/* +extern void nouveauDDUpdateState(GLcontext *ctx); +extern void nouveauDDUpdateHWState(GLcontext *ctx); + +extern void nouveauEmitHwStateLocked(nouveauContextPtr nmesa); +*/ +#endif + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state_cache.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state_cache.c new file mode 100644 index 000000000..cb4b9d302 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state_cache.c @@ -0,0 +1,69 @@ + +#include "nouveau_state_cache.h" +#include "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" + +#define BEGIN_RING_NOFLUSH(subchannel,tag,size) do { \ + if (nmesa->fifo.free <= (size)) \ + WAIT_RING(nmesa,(size)); \ + OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \ + nmesa->fifo.free -= ((size) + 1); \ +}while(0) + +// flush all the dirty state +void nouveau_state_cache_flush(nouveauContextPtr nmesa) +{ + int i=0; + int run=0; + + // fast-path no state changes + if (!nmesa->state_cache.dirty) + return; + nmesa->state_cache.dirty=0; + + do + { + // jump to a dirty state + while((nmesa->state_cache.hdirty[i/NOUVEAU_STATE_CACHE_HIER_SIZE]==0)&&(i<NOUVEAU_STATE_CACHE_ENTRIES)) + i=(i&~(NOUVEAU_STATE_CACHE_HIER_SIZE-1))+NOUVEAU_STATE_CACHE_HIER_SIZE; + while((nmesa->state_cache.atoms[i].dirty==0)&&(i<NOUVEAU_STATE_CACHE_ENTRIES)) + i++; + + // figure out a run of dirty values + run=0; + while((nmesa->state_cache.atoms[i+run].dirty)&&(i+run<NOUVEAU_STATE_CACHE_ENTRIES)) + run++; + + // output everything as a single run + if (run>0) { + int j; + + BEGIN_RING_NOFLUSH(NvSub3D, i*4, run); + for(j=0;j<run;j++) + { + OUT_RING(nmesa->state_cache.atoms[i+j].value); + nmesa->state_cache.atoms[i+j].dirty=0; + if ((i+j)%NOUVEAU_STATE_CACHE_HIER_SIZE==0) + nmesa->state_cache.hdirty[(i+j)/NOUVEAU_STATE_CACHE_HIER_SIZE-1]=0; + } + i+=run; + } + } + while(i<NOUVEAU_STATE_CACHE_ENTRIES); + nmesa->state_cache.hdirty[NOUVEAU_STATE_CACHE_HIER_SIZE/NOUVEAU_STATE_CACHE_HIER_SIZE-1]=0; +} + + +// inits the state cache +void nouveau_state_cache_init(nouveauContextPtr nmesa) +{ + int i; + for(i=0;i<NOUVEAU_STATE_CACHE_ENTRIES;i++) + { + nmesa->state_cache.atoms[i].dirty=0; + nmesa->state_cache.atoms[i].value=0xDEADBEEF; // nvidia cards like beef + } + nmesa->state_cache.dirty=0; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state_cache.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state_cache.h new file mode 100644 index 000000000..5f9d42645 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state_cache.h @@ -0,0 +1,29 @@ + +#ifndef __NOUVEAU_STATE_CACHE_H__ +#define __NOUVEAU_STATE_CACHE_H__ + +#include "mtypes.h" + +#define NOUVEAU_STATE_CACHE_ENTRIES 2048 +// size of a dirty requests block +// you can play with that and tune the value to increase/decrease performance +// but keep it a power of 2 ! +#define NOUVEAU_STATE_CACHE_HIER_SIZE 32 + +typedef struct nouveau_state_atom_t{ + uint32_t value; + uint32_t dirty; +}nouveau_state_atom; + +typedef struct nouveau_state_cache_t{ + nouveau_state_atom atoms[NOUVEAU_STATE_CACHE_ENTRIES]; + uint32_t current_pos; + // hierarchical dirty flags + uint8_t hdirty[NOUVEAU_STATE_CACHE_ENTRIES/NOUVEAU_STATE_CACHE_HIER_SIZE]; + // master dirty flag + uint8_t dirty; +}nouveau_state_cache; + + +#endif + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_swtcl.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_swtcl.c new file mode 100644 index 000000000..8a013bd99 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_swtcl.c @@ -0,0 +1,127 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* Common software TCL code */ + +#include "nouveau_context.h" +#include "nouveau_swtcl.h" +#include "nv10_swtcl.h" +#include "nouveau_span.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" + +/* Common tri functions */ + +/* The fallbacks */ +void nouveau_fallback_tri(struct nouveau_context *nmesa, + nouveauVertex *v0, + nouveauVertex *v1, + nouveauVertex *v2) +{ + GLcontext *ctx = nmesa->glCtx; + SWvertex v[3]; + _swsetup_Translate(ctx, v0, &v[0]); + _swsetup_Translate(ctx, v1, &v[1]); + _swsetup_Translate(ctx, v2, &v[2]); + _swrast_Triangle(ctx, &v[0], &v[1], &v[2]); +} + + +void nouveau_fallback_line(struct nouveau_context *nmesa, + nouveauVertex *v0, + nouveauVertex *v1) +{ + GLcontext *ctx = nmesa->glCtx; + SWvertex v[2]; + _swsetup_Translate(ctx, v0, &v[0]); + _swsetup_Translate(ctx, v1, &v[1]); + _swrast_Line(ctx, &v[0], &v[1]); +} + + +void nouveau_fallback_point(struct nouveau_context *nmesa, + nouveauVertex *v0) +{ + GLcontext *ctx = nmesa->glCtx; + SWvertex v[1]; + _swsetup_Translate(ctx, v0, &v[0]); + _swrast_Point(ctx, &v[0]); +} + +void nouveauFallback(struct nouveau_context *nmesa, GLuint bit, GLboolean mode) +{ + GLcontext *ctx = nmesa->glCtx; + GLuint oldfallback = nmesa->Fallback; + + if (mode) { + nmesa->Fallback |= bit; + if (oldfallback == 0) { + if (nmesa->screen->card->type<NV_10) { + //nv04FinishPrimitive(nmesa); + } else { + //nv10FinishPrimitive(nmesa); + } + + _swsetup_Wakeup(ctx); + nmesa->render_index = ~0; + } + } + else { + nmesa->Fallback &= ~bit; + if (oldfallback == bit) { + _swrast_flush( ctx ); + + if (nmesa->screen->card->type<NV_10) { + nv04TriInitFunctions(ctx); + } else { + nv10TriInitFunctions(ctx); + } + + _tnl_invalidate_vertex_state( ctx, ~0 ); + _tnl_invalidate_vertices( ctx, ~0 ); + _tnl_install_attrs( ctx, + nmesa->vertex_attrs, + nmesa->vertex_attr_count, + nmesa->viewport.m, 0 ); + } + } +} + + +void nouveauRunPipeline( GLcontext *ctx ) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + + if (nmesa->new_state) { + nmesa->new_render_state |= nmesa->new_state; + } + + _tnl_run_pipeline( ctx ); +} + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_swtcl.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_swtcl.h new file mode 100644 index 000000000..ba4d8725a --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_swtcl.h @@ -0,0 +1,55 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + + +#ifndef __NOUVEAU_SWTCL_H__ +#define __NOUVEAU_SWTCL_H__ + +#include "nouveau_context.h" + +extern void nouveau_fallback_tri(struct nouveau_context *nmesa, + nouveauVertex *v0, + nouveauVertex *v1, + nouveauVertex *v2); + +extern void nouveau_fallback_line(struct nouveau_context *nmesa, + nouveauVertex *v0, + nouveauVertex *v1); + +extern void nouveau_fallback_point(struct nouveau_context *nmesa, + nouveauVertex *v0); + +extern void nouveauFallback(struct nouveau_context *nmesa, GLuint bit, GLboolean mode); + +extern void nouveauRunPipeline( GLcontext *ctx ); + +extern void nouveauTriInitFunctions( GLcontext *ctx ); + + +#endif /* __NOUVEAU_SWTCL_H__ */ + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_sync.c new file mode 100644 index 000000000..30e669626 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_sync.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "vblank.h" /* for DO_USLEEP */ + +#include "nouveau_context.h" +#include "nouveau_buffers.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" +#include "nouveau_msg.h" +#include "nouveau_sync.h" + +nouveau_notifier * +nouveau_notifier_new(GLcontext *ctx, GLuint handle, GLuint count) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_notifier *notifier; + +#ifdef NOUVEAU_RING_DEBUG + return NULL; +#endif + + notifier = CALLOC_STRUCT(nouveau_notifier_t); + if (!notifier) + return NULL; + + notifier->mem = nouveau_mem_alloc(ctx, + NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED, + count * NV_NOTIFIER_SIZE, + 0); + if (!notifier->mem) { + FREE(notifier); + return NULL; + } + + if (!nouveauCreateDmaObjectFromMem(nmesa, handle, NV_DMA_IN_MEMORY, + notifier->mem, + NOUVEAU_MEM_ACCESS_RW)) { + nouveau_mem_free(ctx, notifier->mem); + FREE(notifier); + return NULL; + } + + notifier->handle = handle; + return notifier; +} + +void +nouveau_notifier_destroy(GLcontext *ctx, nouveau_notifier *notifier) +{ + /*XXX: free DMA object.. */ + nouveau_mem_free(ctx, notifier->mem); + FREE(notifier); +} + +void +nouveau_notifier_reset(nouveau_notifier *notifier, GLuint id) +{ + volatile GLuint *n = notifier->mem->map + (id * NV_NOTIFIER_SIZE); + +#ifdef NOUVEAU_RING_DEBUG + return; +#endif + + n[NV_NOTIFY_TIME_0 /4] = 0x00000000; + n[NV_NOTIFY_TIME_1 /4] = 0x00000000; + n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000; + n[NV_NOTIFY_STATE /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS << + NV_NOTIFY_STATE_STATUS_SHIFT); +} + +GLuint +nouveau_notifier_status(nouveau_notifier *notifier, GLuint id) +{ + volatile GLuint *n = notifier->mem->map + (id * NV_NOTIFIER_SIZE); + + return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT; +} + +GLuint +nouveau_notifier_return_val(nouveau_notifier *notifier, GLuint id) +{ + volatile GLuint *n = notifier->mem->map + (id * NV_NOTIFIER_SIZE); + + return n[NV_NOTIFY_RETURN_VALUE/4]; +} + +GLboolean +nouveau_notifier_wait_status(nouveau_notifier *notifier, GLuint id, + GLuint status, GLuint timeout) +{ + volatile GLuint *n = notifier->mem->map + (id * NV_NOTIFIER_SIZE); + unsigned int time = 0; + +#ifdef NOUVEAU_RING_DEBUG + return GL_TRUE; +#endif + + while (time <= timeout) { + if (n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK) { + MESSAGE("Notifier returned error: 0x%04x\n", + n[NV_NOTIFY_STATE/4] & + NV_NOTIFY_STATE_ERROR_CODE_MASK); + return GL_FALSE; + } + + if (((n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_STATUS_MASK) >> + NV_NOTIFY_STATE_STATUS_SHIFT) == status) + return GL_TRUE; + + if (timeout) { + DO_USLEEP(1); + time++; + } + } + + MESSAGE("Notifier timed out\n"); + return GL_FALSE; +} + +void +nouveau_notifier_wait_nop(GLcontext *ctx, nouveau_notifier *notifier, + GLuint subc) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLboolean ret; + + nouveau_notifier_reset(notifier, 0); + + BEGIN_RING_SIZE(subc, NV_NOTIFY, 1); + OUT_RING (NV_NOTIFY_STYLE_WRITE_ONLY); + BEGIN_RING_SIZE(subc, NV_NOP, 1); + OUT_RING (0); + FIRE_RING(); + + ret = nouveau_notifier_wait_status(notifier, 0, + NV_NOTIFY_STATE_STATUS_COMPLETED, + 0 /* no timeout */); + if (ret == GL_FALSE) MESSAGE("wait on notifier failed\n"); +} + +GLboolean nouveauSyncInitFuncs(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + +#ifdef NOUVEAU_RING_DEBUG + return GL_TRUE; +#endif + + nmesa->syncNotifier = nouveau_notifier_new(ctx, NvSyncNotify, 1); + if (!nmesa->syncNotifier) { + MESSAGE("Failed to create channel sync notifier\n"); + return GL_FALSE; + } + + /* 0x180 is SET_DMA_NOTIFY, should be correct for all supported 3D + * object classes + */ + BEGIN_RING_CACHE(NvSub3D, 0x180, 1); + OUT_RING_CACHE (NvSyncNotify); +#ifdef ALLOW_MULTI_SUBCHANNEL + BEGIN_RING_SIZE(NvSubMemFormat, + NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); + OUT_RING (NvSyncNotify); +#endif + + return GL_TRUE; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_sync.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_sync.h new file mode 100644 index 000000000..019d5f662 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_sync.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __NOUVEAU_SYNC_H__ +#define __NOUVEAU_SYNC_H__ + +#include "nouveau_buffers.h" + +#define NV_NOTIFIER_SIZE 32 +#define NV_NOTIFY_TIME_0 0x00000000 +#define NV_NOTIFY_TIME_1 0x00000004 +#define NV_NOTIFY_RETURN_VALUE 0x00000008 +#define NV_NOTIFY_STATE 0x0000000C +#define NV_NOTIFY_STATE_STATUS_MASK 0xFF000000 +#define NV_NOTIFY_STATE_STATUS_SHIFT 24 +#define NV_NOTIFY_STATE_STATUS_COMPLETED 0x00 +#define NV_NOTIFY_STATE_STATUS_IN_PROCESS 0x01 +#define NV_NOTIFY_STATE_ERROR_CODE_MASK 0x0000FFFF +#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT 0 + +/* Methods that (hopefully) all objects have */ +#define NV_NOP 0x00000100 +#define NV_NOTIFY 0x00000104 +#define NV_NOTIFY_STYLE_WRITE_ONLY 0 + +typedef struct nouveau_notifier_t { + GLuint handle; + nouveau_mem *mem; +} nouveau_notifier; + +extern nouveau_notifier *nouveau_notifier_new(GLcontext *, GLuint handle, + GLuint count); +extern void nouveau_notifier_destroy(GLcontext *, nouveau_notifier *); +extern void nouveau_notifier_reset(nouveau_notifier *, GLuint id); +extern GLuint nouveau_notifier_status(nouveau_notifier *, GLuint id); +extern GLuint nouveau_notifier_return_val(nouveau_notifier *, GLuint id); +extern GLboolean nouveau_notifier_wait_status(nouveau_notifier *r, GLuint id, + GLuint status, GLuint timeout); +extern void nouveau_notifier_wait_nop(GLcontext *ctx, + nouveau_notifier *, GLuint subc); + +extern GLboolean nouveauSyncInitFuncs(GLcontext *ctx); +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_tex.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_tex.c new file mode 100644 index 000000000..0a8d27966 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_tex.c @@ -0,0 +1,49 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#include "nouveau_tex.h" + +// XXX needs some love +void nouveauTexInitFunctions( struct dd_function_table *functions ) +{ +/* + functions->TexEnv = nouveauTexEnv; + functions->ChooseTextureFormat = nouveauChooseTextureFormat; + functions->TexImage1D = nouveauTexImage1D; + functions->TexSubImage1D = nouveauTexSubImage1D; + functions->TexImage2D = nouveauTexImage2D; + functions->TexSubImage2D = nouveauTexSubImage2D; + functions->TexParameter = nouveauTexParameter; + functions->BindTexture = nouveauBindTexture; + functions->NewTextureObject = nouveauNewTextureObject; + functions->DeleteTexture = nouveauDeleteTexture; + functions->IsTextureResident = driIsTextureResident; + + driInitTextureFormats(); +*/ +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_tex.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_tex.h new file mode 100644 index 000000000..7ac71f830 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nouveau_tex.h @@ -0,0 +1,38 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + +#ifndef __NOUVEAU_TEX_H__ +#define __NOUVEAU_TEX_H__ + +#include <errno.h> +#include "mtypes.h" +#include "macros.h" +#include "dd.h" + +extern void nouveauTexInitFunctions( struct dd_function_table *functions ); + +#endif /* __NOUVEAU_TEX_H__ */ diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_state.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_state.c new file mode 100644 index 000000000..25df3d2a6 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_state.c @@ -0,0 +1,540 @@ +/************************************************************************** + +Copyright 2007 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" +#include "nouveau_msg.h" + +#include "tnl/t_pipeline.h" + +#include "mtypes.h" +#include "colormac.h" + +static uint32_t nv04_compare_func(GLuint f) +{ + switch ( f ) { + case GL_NEVER: return 1; + case GL_LESS: return 2; + case GL_EQUAL: return 3; + case GL_LEQUAL: return 4; + case GL_GREATER: return 5; + case GL_NOTEQUAL: return 6; + case GL_GEQUAL: return 7; + case GL_ALWAYS: return 8; + } + WARN_ONCE("Unable to find the function\n"); + return 0; +} + +static uint32_t nv04_blend_func(GLuint f) +{ + switch ( f ) { + case GL_ZERO: return 0x1; + case GL_ONE: return 0x2; + case GL_SRC_COLOR: return 0x3; + case GL_ONE_MINUS_SRC_COLOR: return 0x4; + case GL_SRC_ALPHA: return 0x5; + case GL_ONE_MINUS_SRC_ALPHA: return 0x6; + case GL_DST_ALPHA: return 0x7; + case GL_ONE_MINUS_DST_ALPHA: return 0x8; + case GL_DST_COLOR: return 0x9; + case GL_ONE_MINUS_DST_COLOR: return 0xA; + case GL_SRC_ALPHA_SATURATE: return 0xB; + } + WARN_ONCE("Unable to find the function 0x%x\n",f); + return 0; +} + +static void nv04_emit_control(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + uint32_t control,cull; + GLubyte alpha_ref; + + CLAMPED_FLOAT_TO_UBYTE(alpha_ref, ctx->Color.AlphaRef); + control=alpha_ref; + control|=(nv04_compare_func(ctx->Color.AlphaFunc)<<8); + control|=(ctx->Color.AlphaEnabled<<12); + control|=(1<<13); + control|=(ctx->Depth.Test<<14); + control|=(nv04_compare_func(ctx->Depth.Func)<<16); + if ((ctx->Polygon.CullFlag)&&(ctx->Polygon.CullFaceMode!=GL_FRONT_AND_BACK)) + { + if ((ctx->Polygon.FrontFace==GL_CW)&&(ctx->Polygon.CullFaceMode==GL_FRONT)) + cull=2; + if ((ctx->Polygon.FrontFace==GL_CW)&&(ctx->Polygon.CullFaceMode==GL_BACK)) + cull=3; + if ((ctx->Polygon.FrontFace==GL_CCW)&&(ctx->Polygon.CullFaceMode==GL_FRONT)) + cull=3; + if ((ctx->Polygon.FrontFace==GL_CCW)&&(ctx->Polygon.CullFaceMode==GL_BACK)) + cull=2; + } + else + if (ctx->Polygon.CullFaceMode==GL_FRONT_AND_BACK) + cull=0; + else + cull=1; + control|=(cull<<20); + control|=(ctx->Color.DitherFlag<<22); + if ((ctx->Depth.Test)&&(ctx->Depth.Mask)) + control|=(1<<24); + + control|=(1<<30); // integer zbuffer format + + BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1); + OUT_RING_CACHE(control); +} + +static void nv04_emit_blend(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + uint32_t blend; + + blend=0x4; // texture MODULATE_ALPHA + blend|=0x20; // alpha is MSB + switch(ctx->Light.ShadeModel) { + case GL_SMOOTH:blend|=(1<<6);break; + case GL_FLAT: blend|=(2<<6);break; + default:break; + } + if (ctx->Hint.PerspectiveCorrection!=GL_FASTEST) + blend|=(1<<8); + blend|=(ctx->Fog.Enabled<<16); + blend|=(ctx->Color.BlendEnabled<<20); + blend|=(nv04_blend_func(ctx->Color.BlendSrcRGB)<<24); + blend|=(nv04_blend_func(ctx->Color.BlendDstRGB)<<28); + + BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1); + OUT_RING_CACHE(blend); +} + +static void nv04_emit_fog_color(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte c[4]; + c[0] = FLOAT_TO_UBYTE( ctx->Fog.Color[0] ); + c[1] = FLOAT_TO_UBYTE( ctx->Fog.Color[1] ); + c[2] = FLOAT_TO_UBYTE( ctx->Fog.Color[2] ); + c[3] = FLOAT_TO_UBYTE( ctx->Fog.Color[3] ); + BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_FOG_COLOR, 1); + OUT_RING_CACHE(PACK_COLOR_8888_REV(c[0],c[1],c[2],c[3])); +} + +static void nv04AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + nv04_emit_control(ctx); +} + +static void nv04BlendColor(GLcontext *ctx, const GLfloat color[4]) +{ + nv04_emit_blend(ctx); +} + +static void nv04BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA) +{ + nv04_emit_blend(ctx); +} + + +static void nv04BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + nv04_emit_blend(ctx); +} + +static void nv04Clear(GLcontext *ctx, GLbitfield mask) +{ + /* TODO */ +} + +static void nv04ClearColor(GLcontext *ctx, const GLfloat color[4]) +{ + /* TODO */ +} + +static void nv04ClearDepth(GLcontext *ctx, GLclampd d) +{ + /* TODO */ +} + +static void nv04ClearStencil(GLcontext *ctx, GLint s) +{ + /* TODO */ +} + +static void nv04ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation) +{ + /* TODO */ +} + +static void nv04ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask, + GLboolean bmask, GLboolean amask ) +{ + /* TODO */ +} + +static void nv04ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode) +{ + /* TODO I need love */ +} + +static void nv04CullFace(GLcontext *ctx, GLenum mode) +{ + nv04_emit_control(ctx); +} + +static void nv04FrontFace(GLcontext *ctx, GLenum mode) +{ + /* TODO */ +} + +static void nv04DepthFunc(GLcontext *ctx, GLenum func) +{ + nv04_emit_control(ctx); +} + +static void nv04DepthMask(GLcontext *ctx, GLboolean flag) +{ + /* TODO */ +} + +static void nv04DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) +{ + /* TODO */ +} + +/** Specify the current buffer for writing */ +//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer ); +/** Specify the buffers for writing for fragment programs*/ +//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers ); + +static void nv04Enable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + switch(cap) + { + case GL_ALPHA_TEST: + nv04_emit_control(ctx); + break; +// case GL_AUTO_NORMAL: + case GL_BLEND: + nv04_emit_blend(ctx); + break; +// case GL_CLIP_PLANE0: +// case GL_CLIP_PLANE1: +// case GL_CLIP_PLANE2: +// case GL_CLIP_PLANE3: +// case GL_CLIP_PLANE4: +// case GL_CLIP_PLANE5: +// case GL_COLOR_LOGIC_OP: +// case GL_COLOR_MATERIAL: +// case GL_COLOR_SUM_EXT: +// case GL_COLOR_TABLE: +// case GL_CONVOLUTION_1D: +// case GL_CONVOLUTION_2D: + case GL_CULL_FACE: + nv04_emit_control(ctx); + break; + case GL_DEPTH_TEST: + nv04_emit_control(ctx); + break; + case GL_DITHER: + nv04_emit_control(ctx); + break; + case GL_FOG: + nv04_emit_blend(ctx); + nv04_emit_fog_color(ctx); + break; +// case GL_HISTOGRAM: +// case GL_INDEX_LOGIC_OP: +// case GL_LIGHT0: +// case GL_LIGHT1: +// case GL_LIGHT2: +// case GL_LIGHT3: +// case GL_LIGHT4: +// case GL_LIGHT5: +// case GL_LIGHT6: +// case GL_LIGHT7: +// case GL_LIGHTING: +// case GL_LINE_SMOOTH: +// case GL_LINE_STIPPLE: +// case GL_MAP1_COLOR_4: +// case GL_MAP1_INDEX: +// case GL_MAP1_NORMAL: +// case GL_MAP1_TEXTURE_COORD_1: +// case GL_MAP1_TEXTURE_COORD_2: +// case GL_MAP1_TEXTURE_COORD_3: +// case GL_MAP1_TEXTURE_COORD_4: +// case GL_MAP1_VERTEX_3: +// case GL_MAP1_VERTEX_4: +// case GL_MAP2_COLOR_4: +// case GL_MAP2_INDEX: +// case GL_MAP2_NORMAL: +// case GL_MAP2_TEXTURE_COORD_1: +// case GL_MAP2_TEXTURE_COORD_2: +// case GL_MAP2_TEXTURE_COORD_3: +// case GL_MAP2_TEXTURE_COORD_4: +// case GL_MAP2_VERTEX_3: +// case GL_MAP2_VERTEX_4: +// case GL_MINMAX: +// case GL_NORMALIZE: +// case GL_POINT_SMOOTH: +// case GL_POLYGON_OFFSET_POINT: +// case GL_POLYGON_OFFSET_LINE: +// case GL_POLYGON_OFFSET_FILL: +// case GL_POLYGON_SMOOTH: +// case GL_POLYGON_STIPPLE: +// case GL_POST_COLOR_MATRIX_COLOR_TABLE: +// case GL_POST_CONVOLUTION_COLOR_TABLE: +// case GL_RESCALE_NORMAL: +// case GL_SCISSOR_TEST: +// case GL_SEPARABLE_2D: +// case GL_STENCIL_TEST: +// case GL_TEXTURE_GEN_Q: +// case GL_TEXTURE_GEN_R: +// case GL_TEXTURE_GEN_S: +// case GL_TEXTURE_GEN_T: +// case GL_TEXTURE_1D: +// case GL_TEXTURE_2D: +// case GL_TEXTURE_3D: + } +} + +static void nv04Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + nv04_emit_blend(ctx); + nv04_emit_fog_color(ctx); +} + +static void nv04Hint(GLcontext *ctx, GLenum target, GLenum mode) +{ + switch(target) + { + case GL_PERSPECTIVE_CORRECTION_HINT:nv04_emit_blend(ctx);break; + default:break; + } +} + +static void nv04LineStipple(GLcontext *ctx, GLint factor, GLushort pattern ) +{ + /* TODO not even in your dreams */ +} + +static void nv04LineWidth(GLcontext *ctx, GLfloat width) +{ + /* TODO */ +} + +static void nv04LogicOpcode(GLcontext *ctx, GLenum opcode) +{ + /* TODO */ +} + +static void nv04PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + /* TODO */ +} + +static void nv04PointSize(GLcontext *ctx, GLfloat size) +{ + /* TODO */ +} + +static void nv04PolygonMode(GLcontext *ctx, GLenum face, GLenum mode) +{ + /* TODO */ +} + +/** Set the scale and units used to calculate depth values */ +static void nv04PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units) +{ + /* TODO */ +} + +/** Set the polygon stippling pattern */ +static void nv04PolygonStipple(GLcontext *ctx, const GLubyte *mask ) +{ + /* TODO */ +} + +/* Specifies the current buffer for reading */ +void (*ReadBuffer)( GLcontext *ctx, GLenum buffer ); +/** Set rasterization mode */ +void (*RenderMode)(GLcontext *ctx, GLenum mode ); + +/** Define the scissor box */ +static void nv04Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + /* TODO */ +} + +/** Select flat or smooth shading */ +static void nv04ShadeModel(GLcontext *ctx, GLenum mode) +{ + nv04_emit_blend(ctx); +} + +/** OpenGL 2.0 two-sided StencilFunc */ +static void nv04StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, + GLint ref, GLuint mask) +{ + /* TODO */ +} + +/** OpenGL 2.0 two-sided StencilMask */ +static void nv04StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) +{ + /* TODO */ +} + +/** OpenGL 2.0 two-sided StencilOp */ +static void nv04StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, + GLenum zfail, GLenum zpass) +{ + /* TODO */ +} + +/** Control the generation of texture coordinates */ +void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname, + const GLfloat *params); +/** Set texture environment parameters */ +void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *param); +/** Set texture parameters */ +void (*TexParameter)(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params); + +/* Update anything that depends on the window position/size */ +static void nv04WindowMoved(nouveauContextPtr nmesa) +{ +} + +/* Initialise any card-specific non-GL related state */ +static GLboolean nv04InitCard(nouveauContextPtr nmesa) +{ + nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D); + nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf3D, NvCtxSurf3D); + + BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_DMA_NOTIFY, 3); + OUT_RING(NvDmaFB); + OUT_RING(NvDmaFB); + OUT_RING(NvDmaFB); + BEGIN_RING_SIZE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_SURFACE, 1); + OUT_RING(NvCtxSurf3D); + return GL_TRUE; +} + +/* Update buffer offset/pitch/format */ +static GLboolean nv04BindBuffers(nouveauContextPtr nmesa, int num_color, + nouveau_renderbuffer **color, + nouveau_renderbuffer *depth) +{ + GLuint x, y, w, h; + uint32_t depth_pitch=(depth?depth->pitch:0+15)&~15+16; + if (depth_pitch<256) depth_pitch=256; + + w = color[0]->mesa.Width; + h = color[0]->mesa.Height; + x = nmesa->drawX; + y = nmesa->drawY; + + BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_FORMAT, 1); + if (color[0]->mesa._ActualFormat == GL_RGBA8) + OUT_RING(0x108/*A8R8G8B8*/); + else + OUT_RING(0x103/*R5G6B5*/); + + /* FIXME pitches have to be aligned ! */ + BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_PITCH, 2); + OUT_RING(color[0]->pitch|(depth_pitch<<16)); + OUT_RING(color[0]->offset); + if (depth) { + BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1); + OUT_RING(depth->offset); + } + +// BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL, 2); +// OUT_RING((w<<16)|x); +// OUT_RING((h<<16)|y); + + + /* FIXME not sure... */ +/* BEGIN_RING_SIZE(NvSubCtxSurf3D, NV04_CONTEXT_SURFACES_3D_CLIP_SIZE, 1); + OUT_RING((h<<16)|w);*/ + + return GL_TRUE; +} + +void nv04InitStateFuncs(GLcontext *ctx, struct dd_function_table *func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + func->AlphaFunc = nv04AlphaFunc; + func->BlendColor = nv04BlendColor; + func->BlendEquationSeparate = nv04BlendEquationSeparate; + func->BlendFuncSeparate = nv04BlendFuncSeparate; + func->Clear = nv04Clear; + func->ClearColor = nv04ClearColor; + func->ClearDepth = nv04ClearDepth; + func->ClearStencil = nv04ClearStencil; + func->ClipPlane = nv04ClipPlane; + func->ColorMask = nv04ColorMask; + func->ColorMaterial = nv04ColorMaterial; + func->CullFace = nv04CullFace; + func->FrontFace = nv04FrontFace; + func->DepthFunc = nv04DepthFunc; + func->DepthMask = nv04DepthMask; + func->DepthRange = nv04DepthRange; + func->Enable = nv04Enable; + func->Fogfv = nv04Fogfv; + func->Hint = nv04Hint; +/* func->Lightfv = nv04Lightfv;*/ +/* func->LightModelfv = nv04LightModelfv; */ + func->LineStipple = nv04LineStipple; /* Not for NV04 */ + func->LineWidth = nv04LineWidth; + func->LogicOpcode = nv04LogicOpcode; + func->PointParameterfv = nv04PointParameterfv; + func->PointSize = nv04PointSize; + func->PolygonMode = nv04PolygonMode; + func->PolygonOffset = nv04PolygonOffset; + func->PolygonStipple = nv04PolygonStipple; /* Not for NV04 */ +/* func->ReadBuffer = nv04ReadBuffer;*/ +/* func->RenderMode = nv04RenderMode;*/ + func->Scissor = nv04Scissor; + func->ShadeModel = nv04ShadeModel; + func->StencilFuncSeparate = nv04StencilFuncSeparate; + func->StencilMaskSeparate = nv04StencilMaskSeparate; + func->StencilOpSeparate = nv04StencilOpSeparate; +/* func->TexGen = nv04TexGen;*/ +/* func->TexParameter = nv04TexParameter;*/ +/* func->TextureMatrix = nv04TextureMatrix;*/ + + nmesa->hw_func.InitCard = nv04InitCard; + nmesa->hw_func.BindBuffers = nv04BindBuffers; + nmesa->hw_func.WindowMoved = nv04WindowMoved; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_swtcl.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_swtcl.c new file mode 100644 index 000000000..cb072e0bd --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_swtcl.c @@ -0,0 +1,619 @@ +/* + * Copyright 2007 Stephane Marchesin. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* Software TCL for NV04, NV05, NV06 */ + +#include <stdio.h> +#include <math.h> + +#include "glheader.h" +#include "context.h" +#include "mtypes.h" +#include "macros.h" +#include "colormac.h" +#include "enums.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "nouveau_swtcl.h" +#include "nv04_swtcl.h" +#include "nouveau_context.h" +#include "nouveau_span.h" +#include "nouveau_reg.h" +#include "nouveau_tex.h" +#include "nouveau_fifo.h" +#include "nouveau_msg.h" +#include "nouveau_object.h" + +static void nv04RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ); +static void nv04RenderPrimitive( GLcontext *ctx, GLenum prim ); +static void nv04ResetLineStipple( GLcontext *ctx ); + + +static inline void nv04_2triangles(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2,nouveauVertex* v3,nouveauVertex* v4,nouveauVertex* v5) +{ + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49); + OUT_RINGp(v0,8); + OUT_RINGp(v1,8); + OUT_RINGp(v2,8); + OUT_RINGp(v3,8); + OUT_RINGp(v4,8); + OUT_RINGp(v5,8); + OUT_RING(0xFEDCBA); +} + +static inline void nv04_1triangle(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2) +{ + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25); + OUT_RINGp(v0,8); + OUT_RINGp(v1,8); + OUT_RINGp(v2,8); + OUT_RING(0xFED); +} + +static inline void nv04_1quad(struct nouveau_context *nmesa,nouveauVertex* v0,nouveauVertex* v1,nouveauVertex* v2,nouveauVertex* v3) +{ + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33); + OUT_RINGp(v0,8); + OUT_RINGp(v1,8); + OUT_RINGp(v2,8); + OUT_RINGp(v3,8); + OUT_RING(0xFECEDC); +} + +static inline void nv04_render_points(GLcontext *ctx,GLuint first,GLuint last) +{ + WARN_ONCE("Unimplemented\n"); +} + +static inline void nv04_render_line(GLcontext *ctx,GLuint v1,GLuint v2) +{ + WARN_ONCE("Unimplemented\n"); +} + +static inline void nv04_render_triangle(GLcontext *ctx,GLuint v1,GLuint v2,GLuint v3) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + + nv04_1triangle(nmesa, + (nouveauVertex*)(vertptr+v1*vertsize), + (nouveauVertex*)(vertptr+v2*vertsize), + (nouveauVertex*)(vertptr+v3*vertsize) + ); +} + +static inline void nv04_render_quad(GLcontext *ctx,GLuint v1,GLuint v2,GLuint v3,GLuint v4) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + + nv04_1quad(nmesa, + (nouveauVertex*)(vertptr+v1*vertsize), + (nouveauVertex*)(vertptr+v2*vertsize), + (nouveauVertex*)(vertptr+v3*vertsize), + (nouveauVertex*)(vertptr+v4*vertsize) + ); +} + +/**********************************************************************/ +/* Render unclipped begin/end objects */ +/**********************************************************************/ + +static void nv04_render_points_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + // erm +} + +static void nv04_render_lines_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + // umm +} + +static void nv04_render_line_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + // yeah +} + +static void nv04_render_line_loop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + // right +} + +static void nv04_render_triangles_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + int i; + + for(i=start;i<count-5;i+=6) + nv04_2triangles(nmesa, + (nouveauVertex*)(vertptr+(i+0)*vertsize), + (nouveauVertex*)(vertptr+(i+1)*vertsize), + (nouveauVertex*)(vertptr+(i+2)*vertsize), + (nouveauVertex*)(vertptr+(i+3)*vertsize), + (nouveauVertex*)(vertptr+(i+4)*vertsize), + (nouveauVertex*)(vertptr+(i+5)*vertsize) + ); + if (i!=count) + { + nv04_1triangle(nmesa, + (nouveauVertex*)(vertptr+(i+0)*vertsize), + (nouveauVertex*)(vertptr+(i+1)*vertsize), + (nouveauVertex*)(vertptr+(i+2)*vertsize) + ); + i+=3; + } + if (i!=count) + printf("oops\n"); +} + +static void nv04_render_tri_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC}; + int i,j; + + for(i=start;i<count;i+=14) + { + int numvert=MIN2(16,count-i); + int numtri=numvert-2; + if (numvert<3) + break; + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert*8); + for(j=0;j<numvert;j++) + OUT_RINGp((nouveauVertex*)(vertptr+(i+j)*vertsize),8); + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2); + for(j=0;j<numtri/2;j++) + OUT_RING(striptbl[j]); + if (numtri%2) + OUT_RING(striptbl[numtri/2]&0xFFF); + } +} + +static void nv04_render_tri_fan_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0}; + int i,j; + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8); + OUT_RINGp((nouveauVertex*)(vertptr+start*vertsize),8); + + for(i=start+1;i<count;i+=14) + { + int numvert=MIN2(15,count-i); + int numtri=numvert-1; + if (numvert<3) + break; + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert*8); + + for(j=0;j<numvert;j++) + OUT_RINGp((nouveauVertex*)(vertptr+(i+j)*vertsize),8); + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2); + for(j=0;j<numtri/2;j++) + OUT_RING(fantbl[j]); + if (numtri%2) + OUT_RING(fantbl[numtri/2]&0xFFF); + } +} + +static void nv04_render_quads_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + int i; + + for(i=start;i<count;i+=4) + nv04_1quad(nmesa, + (nouveauVertex*)(vertptr+(i+0)*vertsize), + (nouveauVertex*)(vertptr+(i+1)*vertsize), + (nouveauVertex*)(vertptr+(i+2)*vertsize), + (nouveauVertex*)(vertptr+(i+3)*vertsize) + ); +} + +static void nv04_render_noop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ +} + +static void (*nv04_render_tab_verts[GL_POLYGON+2])(GLcontext *, + GLuint, + GLuint, + GLuint) = +{ + nv04_render_points_verts, + nv04_render_lines_verts, + nv04_render_line_loop_verts, + nv04_render_line_strip_verts, + nv04_render_triangles_verts, + nv04_render_tri_strip_verts, + nv04_render_tri_fan_verts, + nv04_render_quads_verts, + nv04_render_tri_strip_verts, //nv04_render_quad_strip_verts + nv04_render_tri_fan_verts, //nv04_render_poly_verts + nv04_render_noop_verts, +}; + + +static void nv04_render_points_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + // erm +} + +static void nv04_render_lines_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + // umm +} + +static void nv04_render_line_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + // yeah +} + +static void nv04_render_line_loop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + // right +} + +static void nv04_render_triangles_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; + int i; + + for(i=start;i<count-5;i+=6) + nv04_2triangles(nmesa, + (nouveauVertex*)(vertptr+elt[i+0]*vertsize), + (nouveauVertex*)(vertptr+elt[i+1]*vertsize), + (nouveauVertex*)(vertptr+elt[i+2]*vertsize), + (nouveauVertex*)(vertptr+elt[i+3]*vertsize), + (nouveauVertex*)(vertptr+elt[i+4]*vertsize), + (nouveauVertex*)(vertptr+elt[i+5]*vertsize) + ); + if (i!=count) + { + nv04_1triangle(nmesa, + (nouveauVertex*)(vertptr+elt[i+0]*vertsize), + (nouveauVertex*)(vertptr+elt[i+1]*vertsize), + (nouveauVertex*)(vertptr+elt[i+2]*vertsize) + ); + i+=3; + } + if (i!=count) + printf("oops\n"); +} + +static void nv04_render_tri_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC}; + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; + int i,j; + + for(i=start;i<count;i+=14) + { + int numvert=MIN2(16,count-i); + int numtri=numvert-2; + if (numvert<3) + break; + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert*8); + for(j=0;j<numvert;j++) + OUT_RINGp((nouveauVertex*)(vertptr+elt[i+j]*vertsize),8); + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2); + for(j=0;j<numtri/2;j++) + OUT_RING(striptbl[j]); + if (numtri%2) + OUT_RING(striptbl[numtri/2]&0xFFF); + } +} + +static void nv04_render_tri_fan_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0}; + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; + int i,j; + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8); + OUT_RINGp((nouveauVertex*)(vertptr+elt[start]*vertsize),8); + + for(i=start+1;i<count;i+=14) + { + int numvert=MIN2(15,count-i); + int numtri=numvert-2; + if (numvert<3) + break; + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert*8); + + for(j=0;j<numvert;j++) + OUT_RINGp((nouveauVertex*)(vertptr+elt[i+j]*vertsize),8); + + BEGIN_RING_SIZE(NvSub3D,NV04_DX5_TEXTURED_TRIANGLE_DRAW|NONINC_METHOD,(numtri+1)/2); + for(j=0;j<numtri/2;j++) + OUT_RING(fantbl[j]); + if (numtri%2) + OUT_RING(fantbl[numtri/2]&0xFFF); + } +} + +static void nv04_render_quads_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; + int i; + + for(i=start;i<count;i+=4) + nv04_1quad(nmesa, + (nouveauVertex*)(vertptr+elt[i+0]*vertsize), + (nouveauVertex*)(vertptr+elt[i+1]*vertsize), + (nouveauVertex*)(vertptr+elt[i+2]*vertsize), + (nouveauVertex*)(vertptr+elt[i+3]*vertsize) + ); +} + +static void nv04_render_noop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ +} + +static void (*nv04_render_tab_elts[GL_POLYGON+2])(GLcontext *, + GLuint, + GLuint, + GLuint) = +{ + nv04_render_points_elts, + nv04_render_lines_elts, + nv04_render_line_loop_elts, + nv04_render_line_strip_elts, + nv04_render_triangles_elts, + nv04_render_tri_strip_elts, + nv04_render_tri_fan_elts, + nv04_render_quads_elts, + nv04_render_tri_strip_elts, // nv04_render_quad_strip_elts, + nv04_render_tri_fan_elts, // nv04_render_poly_elts, + nv04_render_noop_elts, +}; + + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + + +#define EMIT_ATTR( ATTR, STYLE ) \ +do { \ + nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = (ATTR); \ + nmesa->vertex_attrs[nmesa->vertex_attr_count].format = (STYLE); \ + nmesa->vertex_attr_count++; \ +} while (0) + +#define EMIT_PAD( N ) \ +do { \ + nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = 0; \ + nmesa->vertex_attrs[nmesa->vertex_attr_count].format = EMIT_PAD; \ + nmesa->vertex_attrs[nmesa->vertex_attr_count].offset = (N); \ + nmesa->vertex_attr_count++; \ +} while (0) + +static void nv04_render_clipped_line(GLcontext *ctx,GLuint ii,GLuint jj) +{ +} + +static void nv04_render_clipped_poly(GLcontext *ctx,const GLuint *elts,GLuint n) +{ +} + +static void nv04ChooseRenderState(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + tnl->Driver.Render.PrimTabVerts = nv04_render_tab_verts; + tnl->Driver.Render.PrimTabElts = nv04_render_tab_elts; + tnl->Driver.Render.ClippedLine = nv04_render_clipped_line; + tnl->Driver.Render.ClippedPolygon = nv04_render_clipped_poly; + tnl->Driver.Render.Points = nv04_render_points; + tnl->Driver.Render.Line = nv04_render_line; + tnl->Driver.Render.Triangle = nv04_render_triangle; + tnl->Driver.Render.Quad = nv04_render_quad; +} + + + +static inline void nv04OutputVertexFormat(struct nouveau_context* nmesa) +{ + GLcontext* ctx=nmesa->glCtx; + DECLARE_RENDERINPUTS(index); + + /* + * Tell t_vertex about the vertex format + */ + nmesa->vertex_attr_count = 0; + RENDERINPUTS_COPY(index, nmesa->render_inputs_bitset); + + // SX SY SZ INVW + // FIXME : we use W instead of INVW, but since W=1 it doesn't matter + if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_POS)) + EMIT_ATTR(_TNL_ATTRIB_POS,EMIT_4F_VIEWPORT); + else + EMIT_PAD(4*sizeof(float)); + + // COLOR + if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_COLOR0)) + EMIT_ATTR(_TNL_ATTRIB_COLOR0,EMIT_4UB_4F_ABGR); + else + EMIT_PAD(4); + + // SPECULAR + if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_COLOR1)) + EMIT_ATTR(_TNL_ATTRIB_COLOR1,EMIT_4UB_4F_ABGR); + else + EMIT_PAD(4); + + // TEXTURE + if (RENDERINPUTS_TEST(index, _TNL_ATTRIB_TEX0)) + EMIT_ATTR(_TNL_ATTRIB_TEX0,EMIT_2F); + else + EMIT_PAD(2*sizeof(float)); + + nmesa->vertex_size=_tnl_install_attrs( ctx, + nmesa->vertex_attrs, + nmesa->vertex_attr_count, + nmesa->viewport.m, 0 ); +} + + +static void nv04ChooseVertexState( GLcontext *ctx ) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + DECLARE_RENDERINPUTS(index); + + RENDERINPUTS_COPY(index, tnl->render_inputs_bitset); + if (!RENDERINPUTS_EQUAL(index, nmesa->render_inputs_bitset)) + { + RENDERINPUTS_COPY(nmesa->render_inputs_bitset, index); + nv04OutputVertexFormat(nmesa); + } +} + + +/**********************************************************************/ +/* High level hooks for t_vb_render.c */ +/**********************************************************************/ + + +static void nv04RenderStart(GLcontext *ctx) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + + if (nmesa->new_state) { + nmesa->new_render_state |= nmesa->new_state; + } + + if (nmesa->new_render_state) { + nv04ChooseVertexState(ctx); + nv04ChooseRenderState(ctx); + nmesa->new_render_state = 0; + } +} + +static void nv04RenderFinish(GLcontext *ctx) +{ +} + + +/* System to flush dma and emit state changes based on the rasterized + * primitive. + */ +void nv04RasterPrimitive(GLcontext *ctx, + GLenum glprim, + GLuint hwprim) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + + assert (!nmesa->new_state); + + if (hwprim != nmesa->current_primitive) + { + nmesa->current_primitive=hwprim; + + } +} + +static const GLuint hw_prim[GL_POLYGON+1] = { + GL_POINTS+1, + GL_LINES+1, + GL_LINE_STRIP+1, + GL_LINE_LOOP+1, + GL_TRIANGLES+1, + GL_TRIANGLE_STRIP+1, + GL_TRIANGLE_FAN+1, + GL_QUADS+1, + GL_QUAD_STRIP+1, + GL_POLYGON+1 +}; + +/* Callback for mesa: + */ +static void nv04RenderPrimitive( GLcontext *ctx, GLuint prim ) +{ + nv04RasterPrimitive( ctx, prim, hw_prim[prim] ); +} + +static void nv04ResetLineStipple( GLcontext *ctx ) +{ + /* FIXME do something here */ + WARN_ONCE("Unimplemented nv04ResetLineStipple\n"); +} + + +/**********************************************************************/ +/* Initialization. */ +/**********************************************************************/ + +void nv04TriInitFunctions(GLcontext *ctx) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + tnl->Driver.RunPipeline = nouveauRunPipeline; + tnl->Driver.Render.Start = nv04RenderStart; + tnl->Driver.Render.Finish = nv04RenderFinish; + tnl->Driver.Render.PrimitiveNotify = nv04RenderPrimitive; + tnl->Driver.Render.ResetLineStipple = nv04ResetLineStipple; + tnl->Driver.Render.BuildVertices = _tnl_build_vertices; + tnl->Driver.Render.CopyPV = _tnl_copy_pv; + tnl->Driver.Render.Interp = _tnl_interp; + + _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 32 ); + + nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf; +} + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_swtcl.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_swtcl.h new file mode 100644 index 000000000..42dde5383 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv04_swtcl.h @@ -0,0 +1,12 @@ +#ifndef __NV04_SWTCL_H__ +#define __NV04_SWTCL_H__ + +#include "mtypes.h" + +extern void nv04Fallback( GLcontext *ctx, GLuint bit, GLboolean mode ); +extern void nv04FinishPrimitive(struct nouveau_context *nmesa); +extern void nv04TriInitFunctions(GLcontext *ctx); +#define FALLBACK( nmesa, bit, mode ) nouveauFallback( nmesa->glCtx, bit, mode ) + +#endif /* __NV04_SWTCL_H__ */ + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_state.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_state.c new file mode 100644 index 000000000..5f304ccab --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_state.c @@ -0,0 +1,798 @@ +/************************************************************************** + +Copyright 2006 Nouveau +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" + +#include "tnl/t_pipeline.h" + +#include "mtypes.h" +#include "colormac.h" + +static void nv10ViewportScale(nouveauContextPtr nmesa) +{ + GLcontext *ctx = nmesa->glCtx; + GLuint w = ctx->Viewport.Width; + GLuint h = ctx->Viewport.Height; + + GLfloat max_depth = (ctx->Viewport.Near + ctx->Viewport.Far) * 0.5; +/* if (ctx->DrawBuffer) { + switch (ctx->DrawBuffer->_DepthBuffer->DepthBits) { + case 16: + max_depth *= 32767.0; + break; + case 24: + max_depth *= 16777215.0; + break; + } + } else {*/ + /* Default to 24 bits range */ + max_depth *= 16777215.0; +/* }*/ + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_SCALE_X, 4); + OUT_RING_CACHEf ((((GLfloat) w) * 0.5) - 2048.0); + OUT_RING_CACHEf ((((GLfloat) h) * 0.5) - 2048.0); + OUT_RING_CACHEf (max_depth); + OUT_RING_CACHEf (0.0); +} + +static void nv10AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte ubRef; + CLAMPED_FLOAT_TO_UBYTE(ubRef, ref); + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2); + OUT_RING_CACHE(func); + OUT_RING_CACHE(ubRef); +} + +static void nv10BlendColor(GLcontext *ctx, const GLfloat color[4]) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte cf[4]; + + CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]); + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_COLOR, 1); + OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0])); +} + +static void nv10BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + assert( modeRGB == modeA ); + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1); + OUT_RING_CACHE(modeRGB); +} + + +static void nv10BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + assert( sfactorRGB == sfactorA ); + assert( dfactorRGB == dfactorA ); + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2); + OUT_RING_CACHE(sfactorRGB); + OUT_RING_CACHE(dfactorRGB); +} + +static void nv10Clear(GLcontext *ctx, GLbitfield mask) +{ + /* TODO */ +} + +static void nv10ClearColor(GLcontext *ctx, const GLfloat color[4]) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte c[4]; + UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color); + nmesa->clear_color_value = PACK_COLOR_8888(c[3],c[0],c[1],c[2]); +} + +static void nv10ClearDepth(GLcontext *ctx, GLclampd d) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + +/* switch (ctx->DrawBuffer->_DepthBuffer->DepthBits) { + case 16: + nmesa->clear_value = (uint32_t)(d*0x7FFF); + break; + case 24:*/ + nmesa->clear_value = ((nmesa->clear_value&0x000000FF) | + (((uint32_t)(d*0xFFFFFF))<<8)); +/* break; + }*/ +} + +static void nv10ClearStencil(GLcontext *ctx, GLint s) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + +/* if (ctx->DrawBuffer->_DepthBuffer->DepthBits == 24) {*/ + nmesa->clear_value = ((nmesa->clear_value&0xFFFFFF00)| + (s&0x000000FF)); +/* }*/ +} + +static void nv10ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4); + OUT_RING_CACHEf(equation[0]); + OUT_RING_CACHEf(equation[1]); + OUT_RING_CACHEf(equation[2]); + OUT_RING_CACHEf(equation[3]); +} + +static void nv10ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask, + GLboolean bmask, GLboolean amask ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_MASK, 1); + OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0)); +} + +static void nv10ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode) +{ + /* TODO I need love */ +} + +static void nv10CullFace(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE, 1); + OUT_RING_CACHE(mode); +} + +static void nv10FrontFace(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FRONT_FACE, 1); + OUT_RING_CACHE(mode); +} + +static void nv10DepthFunc(GLcontext *ctx, GLenum func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1); + OUT_RING_CACHE(func); +} + +static void nv10DepthMask(GLcontext *ctx, GLboolean flag) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1); + OUT_RING_CACHE(flag); +} + +static void nv10DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + GLfloat depth_scale = 16777216.0; + if (ctx->DrawBuffer->_DepthBuffer->DepthBits == 16) { + depth_scale = 32768.0; + } + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2); + OUT_RING_CACHEf(nearval * depth_scale); + OUT_RING_CACHEf(farval * depth_scale); + + nv10ViewportScale(nmesa); +} + +/** Specify the current buffer for writing */ +//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer ); +/** Specify the buffers for writing for fragment programs*/ +//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers ); + +static void nv10Enable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + switch(cap) + { + case GL_ALPHA_TEST: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_AUTO_NORMAL: + case GL_BLEND: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1); + OUT_RING_CACHE(state); + break; + case GL_COLOR_LOGIC_OP: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_COLOR_MATERIAL: +// case GL_COLOR_SUM_EXT: +// case GL_COLOR_TABLE: +// case GL_CONVOLUTION_1D: +// case GL_CONVOLUTION_2D: + case GL_CULL_FACE: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_DEPTH_TEST: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_DITHER: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_FOG: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FOG_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_HISTOGRAM: +// case GL_INDEX_LOGIC_OP: + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + { + uint32_t mask=1<<(2*(cap-GL_LIGHT0)); + nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state)); + if (nmesa->lighting_enabled) + { + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1); + OUT_RING_CACHE(nmesa->enabled_lights); + } + break; + } + case GL_LIGHTING: + nmesa->lighting_enabled=state; + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1); + if (nmesa->lighting_enabled) + OUT_RING_CACHE(nmesa->enabled_lights); + else + OUT_RING_CACHE(0x0); + break; + case GL_LINE_SMOOTH: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_LINE_STIPPLE: +// case GL_MAP1_COLOR_4: +// case GL_MAP1_INDEX: +// case GL_MAP1_NORMAL: +// case GL_MAP1_TEXTURE_COORD_1: +// case GL_MAP1_TEXTURE_COORD_2: +// case GL_MAP1_TEXTURE_COORD_3: +// case GL_MAP1_TEXTURE_COORD_4: +// case GL_MAP1_VERTEX_3: +// case GL_MAP1_VERTEX_4: +// case GL_MAP2_COLOR_4: +// case GL_MAP2_INDEX: +// case GL_MAP2_NORMAL: +// case GL_MAP2_TEXTURE_COORD_1: +// case GL_MAP2_TEXTURE_COORD_2: +// case GL_MAP2_TEXTURE_COORD_3: +// case GL_MAP2_TEXTURE_COORD_4: +// case GL_MAP2_VERTEX_3: +// case GL_MAP2_VERTEX_4: +// case GL_MINMAX: + case GL_NORMALIZE: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_POINT_SMOOTH: + case GL_POLYGON_OFFSET_POINT: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_OFFSET_LINE: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_OFFSET_FILL: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_SMOOTH: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_POLYGON_STIPPLE: +// case GL_POST_COLOR_MATRIX_COLOR_TABLE: +// case GL_POST_CONVOLUTION_COLOR_TABLE: +// case GL_RESCALE_NORMAL: +// case GL_SCISSOR_TEST: +// case GL_SEPARABLE_2D: + case GL_STENCIL_TEST: + // TODO BACK and FRONT ? + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_TEXTURE_GEN_Q: +// case GL_TEXTURE_GEN_R: +// case GL_TEXTURE_GEN_S: +// case GL_TEXTURE_GEN_T: +// case GL_TEXTURE_1D: +// case GL_TEXTURE_2D: +// case GL_TEXTURE_3D: + } +} + +static void nv10Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + switch(pname) + { + case GL_FOG_MODE: + //BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_FOG_MODE, 1); + //OUT_RING_CACHE (params); + break; + /* TODO: unsure about the rest.*/ + default: + break; + } + +} + +static void nv10Hint(GLcontext *ctx, GLenum target, GLenum mode) +{ + /* TODO I need love (fog and line_smooth hints) */ +} + +// void (*IndexMask)(GLcontext *ctx, GLuint mask); + +enum { + SPOTLIGHT_NO_UPDATE, + SPOTLIGHT_UPDATE_EXPONENT, + SPOTLIGHT_UPDATE_DIRECTION, + SPOTLIGHT_UPDATE_ALL +}; + +static void nv10Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLint p = light - GL_LIGHT0; + struct gl_light *l = &ctx->Light.Light[p]; + int spotlight_update = SPOTLIGHT_NO_UPDATE; + + switch(pname) + { + case GL_AMBIENT: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_DIFFUSE: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_SPECULAR: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_POSITION: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_SPOT_DIRECTION: + spotlight_update = SPOTLIGHT_UPDATE_DIRECTION; + break; + case GL_SPOT_EXPONENT: + spotlight_update = SPOTLIGHT_UPDATE_EXPONENT; + break; + case GL_SPOT_CUTOFF: + spotlight_update = SPOTLIGHT_UPDATE_ALL; + break; + case GL_CONSTANT_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + case GL_LINEAR_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + case GL_QUADRATIC_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + default: + break; + } + + switch(spotlight_update) { + case SPOTLIGHT_UPDATE_DIRECTION: + { + GLfloat x,y,z; + GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0); + x = spot_light_coef_a * l->_NormDirection[0]; + y = spot_light_coef_a * l->_NormDirection[1]; + z = spot_light_coef_a * l->_NormDirection[2]; + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3); + OUT_RING_CACHEf(x); + OUT_RING_CACHEf(y); + OUT_RING_CACHEf(z); + } + break; + case SPOTLIGHT_UPDATE_EXPONENT: + { + GLfloat cc,lc,qc; + cc = 1.0; /* FIXME: These need to be correctly computed */ + lc = 0.0; + qc = 2.0; + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3); + OUT_RING_CACHEf(cc); + OUT_RING_CACHEf(lc); + OUT_RING_CACHEf(qc); + } + break; + case SPOTLIGHT_UPDATE_ALL: + { + GLfloat cc,lc,qc, x,y,z, c; + GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0); + cc = 1.0; /* FIXME: These need to be correctly computed */ + lc = 0.0; + qc = 2.0; + x = spot_light_coef_a * l->_NormDirection[0]; + y = spot_light_coef_a * l->_NormDirection[1]; + z = spot_light_coef_a * l->_NormDirection[2]; + c = spot_light_coef_a + 1.0; + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7); + OUT_RING_CACHEf(cc); + OUT_RING_CACHEf(lc); + OUT_RING_CACHEf(qc); + OUT_RING_CACHEf(x); + OUT_RING_CACHEf(y); + OUT_RING_CACHEf(z); + OUT_RING_CACHEf(c); + } + break; + default: + break; + } +} + +/** Set the lighting model parameters */ +static void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params); + + +static void nv10LineStipple(GLcontext *ctx, GLint factor, GLushort pattern ) +{ + /* Not for NV10 */ +} + +static void nv10LineWidth(GLcontext *ctx, GLfloat width) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_LINE_WIDTH, 1); + OUT_RING_CACHE(((int) (width * 8.0)) & -4); +} + +static void nv10LogicOpcode(GLcontext *ctx, GLenum opcode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1); + OUT_RING_CACHE(opcode); +} + +static void nv10PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + /*TODO: not sure what goes here. */ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + +} + +static void nv10PointSize(GLcontext *ctx, GLfloat size) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POINT_SIZE, 1); + OUT_RING_CACHE(((int) (size * 8.0)) & -4); +} + +static void nv10PolygonMode(GLcontext *ctx, GLenum face, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1); + OUT_RING_CACHE(mode); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1); + OUT_RING_CACHE(mode); + } +} + +/** Set the scale and units used to calculate depth values */ +static void nv10PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2); + OUT_RING_CACHEf(factor); + OUT_RING_CACHEf(units); +} + +/** Set the polygon stippling pattern */ +static void nv10PolygonStipple(GLcontext *ctx, const GLubyte *mask ) +{ + /* Not for NV10 */ +} + +/* Specifies the current buffer for reading */ +void (*ReadBuffer)( GLcontext *ctx, GLenum buffer ); +/** Set rasterization mode */ +void (*RenderMode)(GLcontext *ctx, GLenum mode ); + +/** Define the scissor box */ +static void nv10Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ +} + +/** Select flat or smooth shading */ +static void nv10ShadeModel(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_SHADE_MODEL, 1); + OUT_RING_CACHE(mode); +} + +/** OpenGL 2.0 two-sided StencilFunc */ +static void nv10StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, + GLint ref, GLuint mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + /* NV10 do not have separate FRONT and BACK stencils */ + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC, 3); + OUT_RING_CACHE(func); + OUT_RING_CACHE(ref); + OUT_RING_CACHE(mask); +} + +/** OpenGL 2.0 two-sided StencilMask */ +static void nv10StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + /* NV10 do not have separate FRONT and BACK stencils */ + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_MASK, 1); + OUT_RING_CACHE(mask); +} + +/** OpenGL 2.0 two-sided StencilOp */ +static void nv10StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, + GLenum zfail, GLenum zpass) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + /* NV10 do not have separate FRONT and BACK stencils */ + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL, 3); + OUT_RING_CACHE(fail); + OUT_RING_CACHE(zfail); + OUT_RING_CACHE(zpass); +} + +/** Control the generation of texture coordinates */ +void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname, + const GLfloat *params); +/** Set texture environment parameters */ +void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *param); +/** Set texture parameters */ +void (*TexParameter)(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params); + +static void nv10TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16); + /*XXX: This SHOULD work.*/ + OUT_RING_CACHEp(mat->m, 16); +} + +/* Update anything that depends on the window position/size */ +static void nv10WindowMoved(nouveauContextPtr nmesa) +{ + GLcontext *ctx = nmesa->glCtx; + GLfloat *v = nmesa->viewport.m; + GLuint w = ctx->Viewport.Width; + GLuint h = ctx->Viewport.Height; + GLuint x = ctx->Viewport.X + nmesa->drawX; + GLuint y = ctx->Viewport.Y + nmesa->drawY; + int i; + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2); + OUT_RING_CACHE((w << 16) | x); + OUT_RING_CACHE((h << 16) | y); + + /* something to do with clears, possibly doesn't belong here */ + BEGIN_RING_SIZE(NvSub3D, 0x02b4, 1); + OUT_RING(0); + + BEGIN_RING_CACHE(NvSub3D, + NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 1); + OUT_RING_CACHE(((w+x-1) << 16) | x | 0x08000800); + BEGIN_RING_CACHE(NvSub3D, + NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(0), 1); + OUT_RING_CACHE(((h+y-1) << 16) | y | 0x08000800); + for (i=1; i<8; i++) { + BEGIN_RING_CACHE(NvSub3D, + NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 1); + OUT_RING_CACHE(0); + BEGIN_RING_CACHE(NvSub3D, + NV10_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(i), 1); + OUT_RING_CACHE(0); + } + + nv10ViewportScale(nmesa); +} + +/* Initialise any card-specific non-GL related state */ +static GLboolean nv10InitCard(nouveauContextPtr nmesa) +{ + nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D); + + BEGIN_RING_SIZE(NvSub3D, NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY0, 2); + OUT_RING(NvDmaFB); /* 184 dma_in_memory0 */ + OUT_RING(NvDmaFB); /* 188 dma_in_memory1 */ + BEGIN_RING_SIZE(NvSub3D, NV10_TCL_PRIMITIVE_3D_SET_DMA_IN_MEMORY2, 2); + OUT_RING(NvDmaFB); /* 194 dma_in_memory2 */ + OUT_RING(NvDmaFB); /* 198 dma_in_memory3 */ + + BEGIN_RING_SIZE(NvSub3D, 0x0290, 1); + OUT_RING(0x00100001); + BEGIN_RING_SIZE(NvSub3D, 0x03f4, 1); + OUT_RING(0); + + /* not for nv10, only for >= nv11 */ + if ((nmesa->screen->card->id>>4) >= 0x11) { + BEGIN_RING_SIZE(NvSub3D, 0x120, 3); + OUT_RING(0); + OUT_RING(1); + OUT_RING(2); + } + + return GL_TRUE; +} + +/* Update buffer offset/pitch/format */ +static GLboolean nv10BindBuffers(nouveauContextPtr nmesa, int num_color, + nouveau_renderbuffer **color, + nouveau_renderbuffer *depth) +{ + GLuint x, y, w, h; + GLuint pitch, format, depth_pitch; + + w = color[0]->mesa.Width; + h = color[0]->mesa.Height; + x = nmesa->drawX; + y = nmesa->drawY; + + if (num_color != 1) + return GL_FALSE; + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 6); + OUT_RING_CACHE((w << 16) | x); + OUT_RING_CACHE((h << 16) | y); + depth_pitch = (depth ? depth->pitch : color[0]->pitch); + pitch = (depth_pitch<<16) | color[0]->pitch; + format = 0x108; + if (color[0]->mesa._ActualFormat != GL_RGBA8) { + format = 0x103; /* R5G6B5 color buffer */ + } + OUT_RING_CACHE(format); + OUT_RING_CACHE(pitch); + OUT_RING_CACHE(color[0]->offset); + OUT_RING_CACHE(depth ? depth->offset : color[0]->offset); + + /* Always set to bottom left of buffer */ + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_X, 4); + OUT_RING_CACHEf (0.0); + OUT_RING_CACHEf ((GLfloat) h); + OUT_RING_CACHEf (0.0); + OUT_RING_CACHEf (0.0); + + return GL_TRUE; +} + +void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + func->AlphaFunc = nv10AlphaFunc; + func->BlendColor = nv10BlendColor; + func->BlendEquationSeparate = nv10BlendEquationSeparate; + func->BlendFuncSeparate = nv10BlendFuncSeparate; + func->Clear = nv10Clear; + func->ClearColor = nv10ClearColor; + func->ClearDepth = nv10ClearDepth; + func->ClearStencil = nv10ClearStencil; + func->ClipPlane = nv10ClipPlane; + func->ColorMask = nv10ColorMask; + func->ColorMaterial = nv10ColorMaterial; + func->CullFace = nv10CullFace; + func->FrontFace = nv10FrontFace; + func->DepthFunc = nv10DepthFunc; + func->DepthMask = nv10DepthMask; + func->DepthRange = nv10DepthRange; + func->Enable = nv10Enable; + func->Fogfv = nv10Fogfv; + func->Hint = nv10Hint; + func->Lightfv = nv10Lightfv; +/* func->LightModelfv = nv10LightModelfv; */ + func->LineStipple = nv10LineStipple; /* Not for NV10 */ + func->LineWidth = nv10LineWidth; + func->LogicOpcode = nv10LogicOpcode; + func->PointParameterfv = nv10PointParameterfv; + func->PointSize = nv10PointSize; + func->PolygonMode = nv10PolygonMode; + func->PolygonOffset = nv10PolygonOffset; + func->PolygonStipple = nv10PolygonStipple; /* Not for NV10 */ +/* func->ReadBuffer = nv10ReadBuffer;*/ +/* func->RenderMode = nv10RenderMode;*/ + func->Scissor = nv10Scissor; + func->ShadeModel = nv10ShadeModel; + func->StencilFuncSeparate = nv10StencilFuncSeparate; + func->StencilMaskSeparate = nv10StencilMaskSeparate; + func->StencilOpSeparate = nv10StencilOpSeparate; +/* func->TexGen = nv10TexGen;*/ +/* func->TexParameter = nv10TexParameter;*/ + func->TextureMatrix = nv10TextureMatrix; + + nmesa->hw_func.InitCard = nv10InitCard; + nmesa->hw_func.BindBuffers = nv10BindBuffers; + nmesa->hw_func.WindowMoved = nv10WindowMoved; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_swtcl.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_swtcl.c new file mode 100644 index 000000000..3bc84d862 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_swtcl.c @@ -0,0 +1,656 @@ +/* + * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2006 Stephane Marchesin. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* Software TCL for NV10, NV20, NV30, NV40, NV50 */ + +#include <stdio.h> +#include <math.h> + +#include "glheader.h" +#include "context.h" +#include "mtypes.h" +#include "macros.h" +#include "colormac.h" +#include "enums.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "nouveau_swtcl.h" +#include "nv10_swtcl.h" +#include "nouveau_context.h" +#include "nouveau_span.h" +#include "nouveau_reg.h" +#include "nouveau_tex.h" +#include "nouveau_fifo.h" +#include "nouveau_msg.h" +#include "nouveau_object.h" + +static void nv10RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ); +static void nv10RenderPrimitive( GLcontext *ctx, GLenum prim ); +static void nv10ResetLineStipple( GLcontext *ctx ); + + + +static inline void nv10StartPrimitive(struct nouveau_context* nmesa,uint32_t primitive,uint32_t size) +{ + if (nmesa->screen->card->type==NV_10) + BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_BEGIN_END,1); + else if (nmesa->screen->card->type==NV_20) + BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_BEGIN_END,1); + else + BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_BEGIN_END,1); + OUT_RING(primitive); + + if (nmesa->screen->card->type==NV_10) + BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_DATA|NONINC_METHOD,size); + else if (nmesa->screen->card->type==NV_20) + BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_VERTEX_DATA|NONINC_METHOD,size); + else + BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_DATA|NONINC_METHOD,size); +} + +inline void nv10FinishPrimitive(struct nouveau_context *nmesa) +{ + if (nmesa->screen->card->type==NV_10) + BEGIN_RING_SIZE(NvSub3D,NV10_TCL_PRIMITIVE_3D_BEGIN_END,1); + else if (nmesa->screen->card->type==NV_20) + BEGIN_RING_SIZE(NvSub3D,NV20_TCL_PRIMITIVE_3D_BEGIN_END,1); + else + BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_BEGIN_END,1); + OUT_RING(0x0); + FIRE_RING(); +} + + +static inline void nv10ExtendPrimitive(struct nouveau_context* nmesa, int size) +{ + /* make sure there's enough room. if not, wait */ + if (RING_AVAILABLE()<size) + { + WAIT_RING(nmesa,size); + } +} + +/**********************************************************************/ +/* Render unclipped begin/end objects */ +/**********************************************************************/ + +static inline void nv10_render_generic_primitive_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags,GLuint prim) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + GLuint size_dword = vertsize*(count-start)/4; + + nv10ExtendPrimitive(nmesa, size_dword); + nv10StartPrimitive(nmesa,prim+1,size_dword); + OUT_RINGp((nouveauVertex*)(vertptr+(start*vertsize)),size_dword); + nv10FinishPrimitive(nmesa); +} + +static void nv10_render_points_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_POINTS); +} + +static void nv10_render_lines_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINES); +} + +static void nv10_render_line_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINE_STRIP); +} + +static void nv10_render_line_loop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_LINE_LOOP); +} + +static void nv10_render_triangles_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLES); +} + +static void nv10_render_tri_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLE_STRIP); +} + +static void nv10_render_tri_fan_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_TRIANGLE_FAN); +} + +static void nv10_render_quads_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_QUADS); +} + +static void nv10_render_quad_strip_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_QUAD_STRIP); +} + +static void nv10_render_poly_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_verts(ctx,start,count,flags,GL_POLYGON); +} + +static void nv10_render_noop_verts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ +} + +static void (*nv10_render_tab_verts[GL_POLYGON+2])(GLcontext *, + GLuint, + GLuint, + GLuint) = +{ + nv10_render_points_verts, + nv10_render_lines_verts, + nv10_render_line_loop_verts, + nv10_render_line_strip_verts, + nv10_render_triangles_verts, + nv10_render_tri_strip_verts, + nv10_render_tri_fan_verts, + nv10_render_quads_verts, + nv10_render_quad_strip_verts, + nv10_render_poly_verts, + nv10_render_noop_verts, +}; + + +static inline void nv10_render_generic_primitive_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags,GLuint prim) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + GLuint size_dword = vertsize*(count-start)/4; + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; + GLuint j; + + nv10ExtendPrimitive(nmesa, size_dword); + nv10StartPrimitive(nmesa,prim+1,size_dword); + for (j=start; j<count; j++ ) { + OUT_RINGp((nouveauVertex*)(vertptr+(elt[j]*vertsize)),vertsize/4); + } + nv10FinishPrimitive(nmesa); +} + +static void nv10_render_points_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_POINTS); +} + +static void nv10_render_lines_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINES); +} + +static void nv10_render_line_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINE_STRIP); +} + +static void nv10_render_line_loop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_LINE_LOOP); +} + +static void nv10_render_triangles_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLES); +} + +static void nv10_render_tri_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLE_STRIP); +} + +static void nv10_render_tri_fan_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_TRIANGLE_FAN); +} + +static void nv10_render_quads_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_QUADS); +} + +static void nv10_render_quad_strip_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_QUAD_STRIP); +} + +static void nv10_render_poly_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ + nv10_render_generic_primitive_elts(ctx,start,count,flags,GL_POLYGON); +} + +static void nv10_render_noop_elts(GLcontext *ctx,GLuint start,GLuint count,GLuint flags) +{ +} + +static void (*nv10_render_tab_elts[GL_POLYGON+2])(GLcontext *, + GLuint, + GLuint, + GLuint) = +{ + nv10_render_points_elts, + nv10_render_lines_elts, + nv10_render_line_loop_elts, + nv10_render_line_strip_elts, + nv10_render_triangles_elts, + nv10_render_tri_strip_elts, + nv10_render_tri_fan_elts, + nv10_render_quads_elts, + nv10_render_quad_strip_elts, + nv10_render_poly_elts, + nv10_render_noop_elts, +}; + + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + + +#define EMIT_ATTR( ATTR, STYLE ) \ +do { \ + nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = (ATTR); \ + nmesa->vertex_attrs[nmesa->vertex_attr_count].format = (STYLE); \ + nmesa->vertex_attr_count++; \ +} while (0) + +static void nv10_render_clipped_line(GLcontext *ctx,GLuint ii,GLuint jj) +{ + +} + +static void nv10_render_clipped_poly(GLcontext *ctx,const GLuint *elts,GLuint n) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + nv10_render_generic_primitive_elts( ctx, 0, n, PRIM_BEGIN|PRIM_END,GL_POLYGON ); + VB->Elts = tmp; +} + +static inline void nv10_render_points(GLcontext *ctx,GLuint first,GLuint last) +{ + WARN_ONCE("Unimplemented\n"); +} + +static inline void nv10_render_line(GLcontext *ctx,GLuint v1,GLuint v2) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + GLuint size_dword = vertsize*(2)/4; + + /* OUT_RINGp wants size in DWORDS */ + vertsize >>= 2; + + nv10ExtendPrimitive(nmesa, size_dword); + nv10StartPrimitive(nmesa,GL_LINES+1,size_dword); + OUT_RINGp((nouveauVertex*)(vertptr+(v1*vertsize)),vertsize); + OUT_RINGp((nouveauVertex*)(vertptr+(v2*vertsize)),vertsize); + nv10FinishPrimitive(nmesa); +} + +static inline void nv10_render_triangle(GLcontext *ctx,GLuint v1,GLuint v2,GLuint v3) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + GLuint size_dword = vertsize*(3)/4; + + /* OUT_RINGp wants size in DWORDS */ + vertsize >>= 2; + + nv10ExtendPrimitive(nmesa, size_dword); + nv10StartPrimitive(nmesa,GL_TRIANGLES+1,size_dword); + OUT_RINGp((nouveauVertex*)(vertptr+(v1*vertsize)),vertsize); + OUT_RINGp((nouveauVertex*)(vertptr+(v2*vertsize)),vertsize); + OUT_RINGp((nouveauVertex*)(vertptr+(v3*vertsize)),vertsize); + nv10FinishPrimitive(nmesa); +} + +static inline void nv10_render_quad(GLcontext *ctx,GLuint v1,GLuint v2,GLuint v3,GLuint v4) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte *vertptr = (GLubyte *)nmesa->verts; + GLuint vertsize = nmesa->vertex_size; + GLuint size_dword = vertsize*(4)/4; + + /* OUT_RINGp wants size in DWORDS */ + vertsize >>= 2; + + nv10ExtendPrimitive(nmesa, size_dword); + nv10StartPrimitive(nmesa,GL_QUADS+1,size_dword); + OUT_RINGp((nouveauVertex*)(vertptr+(v1*vertsize)),vertsize); + OUT_RINGp((nouveauVertex*)(vertptr+(v2*vertsize)),vertsize); + OUT_RINGp((nouveauVertex*)(vertptr+(v3*vertsize)),vertsize); + OUT_RINGp((nouveauVertex*)(vertptr+(v4*vertsize)),vertsize); + nv10FinishPrimitive(nmesa); +} + + + +static void nv10ChooseRenderState(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + + tnl->Driver.Render.PrimTabVerts = nv10_render_tab_verts; + tnl->Driver.Render.PrimTabElts = nv10_render_tab_elts; + tnl->Driver.Render.ClippedLine = nv10_render_clipped_line; + tnl->Driver.Render.ClippedPolygon = nv10_render_clipped_poly; + tnl->Driver.Render.Points = nv10_render_points; + tnl->Driver.Render.Line = nv10_render_line; + tnl->Driver.Render.Triangle = nv10_render_triangle; + tnl->Driver.Render.Quad = nv10_render_quad; +} + + + +static inline void nv10OutputVertexFormat(struct nouveau_context* nmesa) +{ + GLcontext* ctx=nmesa->glCtx; + TNLcontext *tnl = TNL_CONTEXT(ctx); + DECLARE_RENDERINPUTS(index); + struct vertex_buffer *VB = &tnl->vb; + int attr_size[16]; + int default_attr_size[8]={3,3,3,4,3,1,4,4}; + int i; + int slots=0; + int total_size=0; + /* t_vertex_generic dereferences a NULL pointer if we + * pass NULL as the vp transform... + */ + const GLfloat ident_vp[16] = { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 + }; + + nmesa->vertex_attr_count = 0; + RENDERINPUTS_COPY(index, nmesa->render_inputs_bitset); + + /* + * Determine attribute sizes + */ + for(i=0;i<8;i++) + { + if (RENDERINPUTS_TEST(index, i)) + attr_size[i]=default_attr_size[i]; + else + attr_size[i]=0; + } + for(i=8;i<16;i++) + { + if (RENDERINPUTS_TEST(index, i)) + attr_size[i]=VB->TexCoordPtr[i-8]->size; + else + attr_size[i]=0; + } + + /* + * Tell t_vertex about the vertex format + */ + for(i=0;i<16;i++) + { + if (RENDERINPUTS_TEST(index, i)) + { + slots=i+1; + if (i==_TNL_ATTRIB_POS) + { + /* special-case POS */ + EMIT_ATTR(_TNL_ATTRIB_POS,EMIT_3F_VIEWPORT); + } + else + { + switch(attr_size[i]) + { + case 1: + EMIT_ATTR(i,EMIT_1F); + break; + case 2: + EMIT_ATTR(i,EMIT_2F); + break; + case 3: + EMIT_ATTR(i,EMIT_3F); + break; + case 4: + EMIT_ATTR(i,EMIT_4F); + break; + } + } + if (i==_TNL_ATTRIB_COLOR0) + nmesa->color_offset=total_size; + if (i==_TNL_ATTRIB_COLOR1) + nmesa->specular_offset=total_size; + total_size+=attr_size[i]; + } + } + + nmesa->vertex_size=_tnl_install_attrs( ctx, + nmesa->vertex_attrs, + nmesa->vertex_attr_count, + ident_vp, 0 ); + assert(nmesa->vertex_size==total_size*4); + + /* + * Tell the hardware about the vertex format + */ + if (nmesa->screen->card->type==NV_10) { + int size; + +#define NV_VERTEX_ATTRIBUTE_TYPE_FLOAT 2 + +#define NV10_SET_VERTEX_ATTRIB(i,j) \ + do { \ + size = attr_size[j] << 4; \ + size |= (attr_size[j]*4) << 8; \ + size |= NV_VERTEX_ATTRIBUTE_TYPE_FLOAT; \ + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VERTEX_ATTR(i),1); \ + OUT_RING_CACHE(size); \ + } while (0) + + NV10_SET_VERTEX_ATTRIB(0, _TNL_ATTRIB_POS); + NV10_SET_VERTEX_ATTRIB(1, _TNL_ATTRIB_COLOR0); + NV10_SET_VERTEX_ATTRIB(2, _TNL_ATTRIB_COLOR1); + NV10_SET_VERTEX_ATTRIB(3, _TNL_ATTRIB_TEX0); + NV10_SET_VERTEX_ATTRIB(4, _TNL_ATTRIB_TEX1); + NV10_SET_VERTEX_ATTRIB(5, _TNL_ATTRIB_NORMAL); + NV10_SET_VERTEX_ATTRIB(6, _TNL_ATTRIB_WEIGHT); + NV10_SET_VERTEX_ATTRIB(7, _TNL_ATTRIB_FOG); + + BEGIN_RING_CACHE(NvSub3D, NV10_TCL_PRIMITIVE_3D_VERTEX_ARRAY_VALIDATE,1); + OUT_RING_CACHE(0); + } else if (nmesa->screen->card->type==NV_20) { + for(i=0;i<16;i++) + { + int size=attr_size[i]; + BEGIN_RING_CACHE(NvSub3D,NV20_TCL_PRIMITIVE_3D_VERTEX_ATTR(i),1); + OUT_RING_CACHE(NV_VERTEX_ATTRIBUTE_TYPE_FLOAT|(size*0x10)); + } + } else { + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DO_VERTICES, 1); + OUT_RING(0); + BEGIN_RING_CACHE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_ATTR0_POS,slots); + for(i=0;i<slots;i++) + { + int size=attr_size[i]; + OUT_RING_CACHE(NV_VERTEX_ATTRIBUTE_TYPE_FLOAT|(size*0x10)); + } + // FIXME this is probably not needed + BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1); + OUT_RING(0); + BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1); + OUT_RING(0); + BEGIN_RING_SIZE(NvSub3D,NV30_TCL_PRIMITIVE_3D_VERTEX_UNK_0,1); + OUT_RING(0); + } +} + + +static void nv10ChooseVertexState( GLcontext *ctx ) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + DECLARE_RENDERINPUTS(index); + + RENDERINPUTS_COPY(index, tnl->render_inputs_bitset); + if (!RENDERINPUTS_EQUAL(index, nmesa->render_inputs_bitset)) + { + RENDERINPUTS_COPY(nmesa->render_inputs_bitset, index); + nv10OutputVertexFormat(nmesa); + } + + if (nmesa->screen->card->type == NV_30) { + nouveauShader *fp; + + if (ctx->FragmentProgram.Enabled) { + fp = (nouveauShader *) ctx->FragmentProgram.Current; + nvsUpdateShader(ctx, fp); + } else + nvsUpdateShader(ctx, nmesa->passthrough_fp); + } + + if (nmesa->screen->card->type >= NV_40) { + /* Ensure passthrough shader is being used, and mvp matrix + * is up to date + */ + nvsUpdateShader(ctx, nmesa->passthrough_vp); + + /* Update texenv shader / user fragprog */ + nvsUpdateShader(ctx, (nouveauShader*)ctx->FragmentProgram._Current); + } +} + + +/**********************************************************************/ +/* High level hooks for t_vb_render.c */ +/**********************************************************************/ + + +static void nv10RenderStart(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + + if (nmesa->new_state) { + nmesa->new_render_state |= nmesa->new_state; + } + + if (nmesa->new_render_state) { + nv10ChooseVertexState(ctx); + nv10ChooseRenderState(ctx); + nmesa->new_render_state = 0; + } +} + +static void nv10RenderFinish(GLcontext *ctx) +{ +} + + +/* System to flush dma and emit state changes based on the rasterized + * primitive. + */ +void nv10RasterPrimitive(GLcontext *ctx, + GLenum glprim, + GLuint hwprim) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + + assert (!nmesa->new_state); + + if (hwprim != nmesa->current_primitive) + { + nmesa->current_primitive=hwprim; + + } +} + +static const GLuint hw_prim[GL_POLYGON+1] = { + GL_POINTS+1, + GL_LINES+1, + GL_LINE_STRIP+1, + GL_LINE_LOOP+1, + GL_TRIANGLES+1, + GL_TRIANGLE_STRIP+1, + GL_TRIANGLE_FAN+1, + GL_QUADS+1, + GL_QUAD_STRIP+1, + GL_POLYGON+1 +}; + +/* Callback for mesa: + */ +static void nv10RenderPrimitive( GLcontext *ctx, GLuint prim ) +{ + nv10RasterPrimitive( ctx, prim, hw_prim[prim] ); +} + +static void nv10ResetLineStipple( GLcontext *ctx ) +{ + /* FIXME do something here */ + WARN_ONCE("Unimplemented nv10ResetLineStipple\n"); +} + + +/**********************************************************************/ +/* Initialization. */ +/**********************************************************************/ + +void nv10TriInitFunctions(GLcontext *ctx) +{ + struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + tnl->Driver.RunPipeline = nouveauRunPipeline; + tnl->Driver.Render.Start = nv10RenderStart; + tnl->Driver.Render.Finish = nv10RenderFinish; + tnl->Driver.Render.PrimitiveNotify = nv10RenderPrimitive; + tnl->Driver.Render.ResetLineStipple = nv10ResetLineStipple; + tnl->Driver.Render.BuildVertices = _tnl_build_vertices; + tnl->Driver.Render.CopyPV = _tnl_copy_pv; + tnl->Driver.Render.Interp = _tnl_interp; + + _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, + 64 * sizeof(GLfloat) ); + + nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf; +} + + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_swtcl.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_swtcl.h new file mode 100644 index 000000000..7c854addd --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv10_swtcl.h @@ -0,0 +1,40 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + + + +#ifndef __NV10_SWTCL_H__ +#define __NV10_SWTCL_H__ + +#include "mtypes.h" + +extern void nv10Fallback( GLcontext *ctx, GLuint bit, GLboolean mode ); +extern void nv10FinishPrimitive(struct nouveau_context *nmesa); +extern void nv10TriInitFunctions(GLcontext *ctx); +#define FALLBACK( nmesa, bit, mode ) nouveauFallback( nmesa->glCtx, bit, mode ) + +#endif /* __NV10_SWTCL_H__ */ + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_shader.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_shader.h new file mode 100644 index 000000000..7d2e29db6 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_shader.h @@ -0,0 +1,121 @@ +/* NV20_TCL_PRIMITIVE_3D_0x0B00 */ +#define NV20_VP_INST_0B00 0x00000000 /* always 0? */ +#define NV20_VP_INST0_KNOWN 0 + +/* NV20_TCL_PRIMITIVE_3D_0x0B04 */ +#define NV20_VP_INST_SCA_OPCODE_SHIFT 25 +#define NV20_VP_INST_SCA_OPCODE_MASK (0x0F << 25) +#define NV20_VP_INST_OPCODE_RCP 0x2 +#define NV20_VP_INST_OPCODE_RCC 0x3 +#define NV20_VP_INST_OPCODE_RSQ 0x4 +#define NV20_VP_INST_OPCODE_EXP 0x5 +#define NV20_VP_INST_OPCODE_LOG 0x6 +#define NV20_VP_INST_OPCODE_LIT 0x7 +#define NV20_VP_INST_VEC_OPCODE_SHIFT 21 +#define NV20_VP_INST_VEC_OPCODE_MASK (0x0F << 21) +#define NV20_VP_INST_OPCODE_NOP 0x0 /* guess */ +#define NV20_VP_INST_OPCODE_MOV 0x1 +#define NV20_VP_INST_OPCODE_MUL 0x2 +#define NV20_VP_INST_OPCODE_ADD 0x3 +#define NV20_VP_INST_OPCODE_MAD 0x4 +#define NV20_VP_INST_OPCODE_DP3 0x5 +#define NV20_VP_INST_OPCODE_DPH 0x6 +#define NV20_VP_INST_OPCODE_DP4 0x7 +#define NV20_VP_INST_OPCODE_DST 0x8 +#define NV20_VP_INST_OPCODE_MIN 0x9 +#define NV20_VP_INST_OPCODE_MAX 0xA +#define NV20_VP_INST_OPCODE_SLT 0xB +#define NV20_VP_INST_OPCODE_SGE 0xC +#define NV20_VP_INST_OPCODE_ARL 0xD +#define NV20_VP_INST_CONST_SRC_SHIFT 13 +#define NV20_VP_INST_CONST_SRC_MASK (0xFF << 13) +#define NV20_VP_INST_INPUT_SRC_SHIFT 9 +#define NV20_VP_INST_INPUT_SRC_MASK (0xF << 9) /* guess */ +#define NV20_VP_INST_INPUT_SRC_POS 0 +#define NV20_VP_INST_INPUT_SRC_COL0 3 +#define NV20_VP_INST_INPUT_SRC_COL1 4 +#define NV20_VP_INST_INPUT_SRC_TC(n) (9+n) +#define NV20_VP_INST_SRC0H_SHIFT 0 +#define NV20_VP_INST_SRC0H_MASK (0x1FF << 0) +#define NV20_VP_INST1_KNOWN ( \ + NV20_VP_INST_OPCODE_MASK | \ + NV20_VP_INST_CONST_SRC_MASK | \ + NV20_VP_INST_INPUT_SRC_MASK | \ + NV20_VP_INST_SRC0H_MASK \ + ) + +/* NV20_TCL_PRIMITIVE_3D_0x0B08 */ +#define NV20_VP_INST_SRC0L_SHIFT 26 +#define NV20_VP_INST_SRC0L_MASK (0x3F <<26) +#define NV20_VP_INST_SRC1_SHIFT 11 +#define NV20_VP_INST_SRC1_MASK (0x7FFF<<11) +#define NV20_VP_INST_SRC2H_SHIFT 0 +#define NV20_VP_INST_SRC2H_MASK (0x7FF << 0) + +/* NV20_TCL_PRIMITIVE_3D_0x0B0C */ +#define NV20_VP_INST_SRC2L_SHIFT 28 +#define NV20_VP_INST_SRC2L_MASK (0x0F <<28) +#define NV20_VP_INST_VTEMP_WRITEMASK_SHIFT 24 +#define NV20_VP_INST_VTEMP_WRITEMASK_MASK (0x0F <<24) +# define NV20_VP_INST_TEMP_WRITEMASK_X (1<<27) +# define NV20_VP_INST_TEMP_WRITEMASK_Y (1<<26) +# define NV20_VP_INST_TEMP_WRITEMASK_Z (1<<25) +# define NV20_VP_INST_TEMP_WRITEMASK_W (1<<24) +#define NV20_VP_INST_DEST_TEMP_ID_SHIFT 20 +#define NV20_VP_INST_DEST_TEMP_ID_MASK (0x0F <<20) +#define NV20_VP_INST_STEMP_WRITEMASK_SHIFT 16 +#define NV20_VP_INST_STEMP_WRITEMASK_MASK (0x0F <<16) +# define NV20_VP_INST_STEMP_WRITEMASK_X (1<<19) +# define NV20_VP_INST_STEMP_WRITEMASK_Y (1<<18) +# define NV20_VP_INST_STEMP_WRITEMASK_Z (1<<17) +# define NV20_VP_INST_STEMP_WRITEMASK_W (1<<16) +#define NV20_VP_INST_DEST_WRITEMASK_SHIFT 12 +#define NV20_VP_INST_DEST_WRITEMASK_MASK (0x0F <<12) +# define NV20_VP_INST_DEST_WRITEMASK_X (1<<15) +# define NV20_VP_INST_DEST_WRITEMASK_Y (1<<14) +# define NV20_VP_INST_DEST_WRITEMASK_Z (1<<13) +# define NV20_VP_INST_DEST_WRITEMASK_W (1<<12) +#define NV20_VP_INST_DEST_SHIFT 3 +#define NV20_VP_INST_DEST_MASK (0xF << 3) /* guess */ +#define NV20_VP_INST_DEST_POS 0 +#define NV20_VP_INST_DEST_COL0 3 +#define NV20_VP_INST_DEST_COL1 4 +#define NV20_VP_INST_DEST_TC(n) (9+n) +#define NV20_VP_INST_INDEX_CONST (1<<1) +#define NV20_VP_INST3_KNOWN ( \ + NV20_VP_INST_SRC2L_MASK | \ + NV20_VP_INST_TEMP_WRITEMASK_MASK | \ + NV20_VP_INST_DEST_TEMP_ID_MASK | \ + NV20_VP_INST_STEMP_WRITEMASK_MASK | \ + NV20_VP_INST_DEST_WRITEMASK_MASK | \ + NV20_VP_INST_DEST_MASK | \ + NV20_VP_INST_INDEX_CONST \ + ) + +/* Useful to split the source selection regs into their pieces */ +#define NV20_VP_SRC0_HIGH_SHIFT 6 +#define NV20_VP_SRC0_HIGH_MASK 0x00007FC0 +#define NV20_VP_SRC0_LOW_MASK 0x0000003F +#define NV20_VP_SRC2_HIGH_SHIFT 4 +#define NV20_VP_SRC2_HIGH_MASK 0x00007FF0 +#define NV20_VP_SRC2_LOW_MASK 0x0000000F + +#define NV20_VP_SRC_REG_NEGATE (1<<14) +#define NV20_VP_SRC_REG_SWZ_X_SHIFT 12 +#define NV20_VP_SRC_REG_SWZ_X_MASK (0x03 <<12) +#define NV20_VP_SRC_REG_SWZ_Y_SHIFT 10 +#define NV20_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10) +#define NV20_VP_SRC_REG_SWZ_Z_SHIFT 8 +#define NV20_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8) +#define NV20_VP_SRC_REG_SWZ_W_SHIFT 6 +#define NV20_VP_SRC_REG_SWZ_W_MASK (0x03 << 6) +#define NV20_VP_SRC_REG_SWZ_ALL_SHIFT 6 +#define NV20_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6) +#define NV20_VP_SRC_REG_TEMP_ID_SHIFT 2 +#define NV20_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0) +#define NV20_VP_SRC_REG_TYPE_SHIFT 0 +#define NV20_VP_SRC_REG_TYPE_MASK (0x03 << 0) +#define NV20_VP_SRC_REG_TYPE_TEMP 1 +#define NV20_VP_SRC_REG_TYPE_INPUT 2 +#define NV20_VP_SRC_REG_TYPE_CONST 3 /* guess */ + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_state.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_state.c new file mode 100644 index 000000000..3d8d83a86 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_state.c @@ -0,0 +1,824 @@ +/************************************************************************** + +Copyright 2006 Nouveau +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" + +#include "tnl/t_pipeline.h" + +#include "mtypes.h" +#include "colormac.h" + +static void nv20AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte ubRef; + CLAMPED_FLOAT_TO_UBYTE(ubRef, ref); + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2); + OUT_RING_CACHE(func); + OUT_RING_CACHE(ubRef); +} + +static void nv20BlendColor(GLcontext *ctx, const GLfloat color[4]) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte cf[4]; + + CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]); + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_COLOR, 1); + OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0])); +} + +static void nv20BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1); + OUT_RING_CACHE((modeA<<16) | modeRGB); +} + + +static void nv20BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2); + OUT_RING_CACHE((sfactorA<<16) | sfactorRGB); + OUT_RING_CACHE((dfactorA<<16) | dfactorRGB); +} + +static void nv20Clear(GLcontext *ctx, GLbitfield mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLuint hw_bufs = 0; + + if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) + hw_bufs |= 0xf0; + if (mask & (BUFFER_BIT_DEPTH)) + hw_bufs |= 0x03; + + if (hw_bufs) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS, 1); + OUT_RING_CACHE(hw_bufs); + } +} + +static void nv20ClearColor(GLcontext *ctx, const GLfloat color[4]) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte c[4]; + UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB, 1); + OUT_RING_CACHE(PACK_COLOR_8888(c[3],c[0],c[1],c[2])); +} + +static void nv20ClearDepth(GLcontext *ctx, GLclampd d) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nmesa->clear_value=((nmesa->clear_value&0x000000FF)|(((uint32_t)(d*0xFFFFFF))<<8)); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1); + OUT_RING_CACHE(nmesa->clear_value); +} + +/* we're don't support indexed buffers + void (*ClearIndex)(GLcontext *ctx, GLuint index) + */ + +static void nv20ClearStencil(GLcontext *ctx, GLint s) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nmesa->clear_value=((nmesa->clear_value&0xFFFFFF00)|(s&0x000000FF)); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1); + OUT_RING_CACHE(nmesa->clear_value); +} + +static void nv20ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4); + OUT_RING_CACHEf(equation[0]); + OUT_RING_CACHEf(equation[1]); + OUT_RING_CACHEf(equation[2]); + OUT_RING_CACHEf(equation[3]); +} + +static void nv20ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask, + GLboolean bmask, GLboolean amask ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_MASK, 1); + OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0)); +} + +static void nv20ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode) +{ + // TODO I need love +} + +static void nv20CullFace(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CULL_FACE, 1); + OUT_RING_CACHE(mode); +} + +static void nv20FrontFace(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FRONT_FACE, 1); + OUT_RING_CACHE(mode); +} + +static void nv20DepthFunc(GLcontext *ctx, GLenum func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1); + OUT_RING_CACHE(func); +} + +static void nv20DepthMask(GLcontext *ctx, GLboolean flag) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1); + OUT_RING_CACHE(flag); +} + +static void nv20DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2); + OUT_RING_CACHEf(nearval); + OUT_RING_CACHEf(farval); +} + +/** Specify the current buffer for writing */ +//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer ); +/** Specify the buffers for writing for fragment programs*/ +//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers ); + +static void nv20Enable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + switch(cap) + { + case GL_ALPHA_TEST: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_AUTO_NORMAL: + case GL_BLEND: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1); + OUT_RING_CACHE(state); + break; + case GL_COLOR_LOGIC_OP: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_COLOR_MATERIAL: +// case GL_COLOR_SUM_EXT: +// case GL_COLOR_TABLE: +// case GL_CONVOLUTION_1D: +// case GL_CONVOLUTION_2D: + case GL_CULL_FACE: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_DEPTH_TEST: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_DITHER: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_FOG: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FOG_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_HISTOGRAM: +// case GL_INDEX_LOGIC_OP: + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + { + uint32_t mask=0x11<<(2*(cap-GL_LIGHT0)); + nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state)); + if (nmesa->lighting_enabled) + { + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1); + OUT_RING_CACHE(nmesa->enabled_lights); + } + break; + } + case GL_LIGHTING: + nmesa->lighting_enabled=state; + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1); + if (nmesa->lighting_enabled) + OUT_RING_CACHE(nmesa->enabled_lights); + else + OUT_RING_CACHE(0x0); + break; + case GL_LINE_SMOOTH: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_LINE_STIPPLE: +// case GL_MAP1_COLOR_4: +// case GL_MAP1_INDEX: +// case GL_MAP1_NORMAL: +// case GL_MAP1_TEXTURE_COORD_1: +// case GL_MAP1_TEXTURE_COORD_2: +// case GL_MAP1_TEXTURE_COORD_3: +// case GL_MAP1_TEXTURE_COORD_4: +// case GL_MAP1_VERTEX_3: +// case GL_MAP1_VERTEX_4: +// case GL_MAP2_COLOR_4: +// case GL_MAP2_INDEX: +// case GL_MAP2_NORMAL: +// case GL_MAP2_TEXTURE_COORD_1: +// case GL_MAP2_TEXTURE_COORD_2: +// case GL_MAP2_TEXTURE_COORD_3: +// case GL_MAP2_TEXTURE_COORD_4: +// case GL_MAP2_VERTEX_3: +// case GL_MAP2_VERTEX_4: +// case GL_MINMAX: + case GL_NORMALIZE: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_POINT_SMOOTH: + case GL_POLYGON_OFFSET_POINT: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_OFFSET_LINE: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_OFFSET_FILL: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_SMOOTH: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_STIPPLE: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_POST_COLOR_MATRIX_COLOR_TABLE: +// case GL_POST_CONVOLUTION_COLOR_TABLE: +// case GL_RESCALE_NORMAL: + case GL_SCISSOR_TEST: + /* No enable bit, nv20Scissor will adjust to max range */ + ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); + break; +// case GL_SEPARABLE_2D: + case GL_STENCIL_TEST: + // TODO BACK and FRONT ? + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_TEXTURE_GEN_Q: +// case GL_TEXTURE_GEN_R: +// case GL_TEXTURE_GEN_S: +// case GL_TEXTURE_GEN_T: +// case GL_TEXTURE_1D: +// case GL_TEXTURE_2D: +// case GL_TEXTURE_3D: + } +} + +static void nv20Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + switch(pname) + { + case GL_FOG_MODE: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_FOG_MODE, 1); + //OUT_RING_CACHE (params); + break; + /* TODO: unsure about the rest.*/ + default: + break; + } + +} + +static void nv20Hint(GLcontext *ctx, GLenum target, GLenum mode) +{ + // TODO I need love (fog and line_smooth hints) +} + +// void (*IndexMask)(GLcontext *ctx, GLuint mask); + +enum { + SPOTLIGHT_NO_UPDATE, + SPOTLIGHT_UPDATE_EXPONENT, + SPOTLIGHT_UPDATE_DIRECTION, + SPOTLIGHT_UPDATE_ALL +}; + +static void nv20Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLint p = light - GL_LIGHT0; + struct gl_light *l = &ctx->Light.Light[p]; + int spotlight_update = SPOTLIGHT_NO_UPDATE; + + /* not sure where the fourth param value goes...*/ + switch(pname) + { + case GL_AMBIENT: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_DIFFUSE: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_SPECULAR: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_POSITION: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_SPOT_DIRECTION: + spotlight_update = SPOTLIGHT_UPDATE_DIRECTION; + break; + case GL_SPOT_EXPONENT: + spotlight_update = SPOTLIGHT_UPDATE_EXPONENT; + break; + case GL_SPOT_CUTOFF: + spotlight_update = SPOTLIGHT_UPDATE_ALL; + break; + case GL_CONSTANT_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + case GL_LINEAR_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + case GL_QUADRATIC_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + default: + break; + } + + switch(spotlight_update) { + case SPOTLIGHT_UPDATE_DIRECTION: + { + GLfloat x,y,z; + GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0); + x = spot_light_coef_a * l->_NormDirection[0]; + y = spot_light_coef_a * l->_NormDirection[1]; + z = spot_light_coef_a * l->_NormDirection[2]; + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3); + OUT_RING_CACHEf(x); + OUT_RING_CACHEf(y); + OUT_RING_CACHEf(z); + } + break; + case SPOTLIGHT_UPDATE_EXPONENT: + { + GLfloat cc,lc,qc; + cc = 1.0; /* FIXME: These need to be correctly computed */ + lc = 0.0; + qc = 2.0; + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3); + OUT_RING_CACHEf(cc); + OUT_RING_CACHEf(lc); + OUT_RING_CACHEf(qc); + } + break; + case SPOTLIGHT_UPDATE_ALL: + { + GLfloat cc,lc,qc, x,y,z, c; + GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0); + cc = 1.0; /* FIXME: These need to be correctly computed */ + lc = 0.0; + qc = 2.0; + x = spot_light_coef_a * l->_NormDirection[0]; + y = spot_light_coef_a * l->_NormDirection[1]; + z = spot_light_coef_a * l->_NormDirection[2]; + c = spot_light_coef_a + 1.0; + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7); + OUT_RING_CACHEf(cc); + OUT_RING_CACHEf(lc); + OUT_RING_CACHEf(qc); + OUT_RING_CACHEf(x); + OUT_RING_CACHEf(y); + OUT_RING_CACHEf(z); + OUT_RING_CACHEf(c); + } + break; + default: + break; + } +} + +/** Set the lighting model parameters */ +static void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params); + + +static void nv20LineStipple(GLcontext *ctx, GLint factor, GLushort pattern ) +{ +/* nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1); + OUT_RING_CACHE((pattern << 16) | factor);*/ +} + +static void nv20LineWidth(GLcontext *ctx, GLfloat width) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LINE_WIDTH, 1); + OUT_RING_CACHEf(width); +} + +static void nv20LogicOpcode(GLcontext *ctx, GLenum opcode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1); + OUT_RING_CACHE(opcode); +} + +static void nv20PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + /*TODO: not sure what goes here. */ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + +} + +/** Specify the diameter of rasterized points */ +static void nv20PointSize(GLcontext *ctx, GLfloat size) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POINT_SIZE, 1); + OUT_RING_CACHEf(size); +} + +/** Select a polygon rasterization mode */ +static void nv20PolygonMode(GLcontext *ctx, GLenum face, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1); + OUT_RING_CACHE(mode); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1); + OUT_RING_CACHE(mode); + } +} + +/** Set the scale and units used to calculate depth values */ +static void nv20PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2); + OUT_RING_CACHEf(factor); + OUT_RING_CACHEf(units); +} + +/** Set the polygon stippling pattern */ +static void nv20PolygonStipple(GLcontext *ctx, const GLubyte *mask ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 32); + OUT_RING_CACHEp(mask, 32); +} + +/* Specifies the current buffer for reading */ +void (*ReadBuffer)( GLcontext *ctx, GLenum buffer ); +/** Set rasterization mode */ +void (*RenderMode)(GLcontext *ctx, GLenum mode ); + +/** Define the scissor box */ +static void nv20Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + /* There's no scissor enable bit, so adjust the scissor to cover the + * maximum draw buffer bounds + */ + if (!ctx->Scissor.Enabled) { + x = y = 0; + w = h = 4095; + } else { + x += nmesa->drawX; + y += nmesa->drawY; + } + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SCISSOR_X2_X1, 1); + OUT_RING_CACHE((w << 16) | x ); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SCISSOR_Y2_Y1, 1); + OUT_RING_CACHE((h << 16) | y ); + +} + +/** Select flat or smooth shading */ +static void nv20ShadeModel(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SHADE_MODEL, 1); + OUT_RING_CACHE(mode); +} + +/** OpenGL 2.0 two-sided StencilFunc */ +static void nv20StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, + GLint ref, GLuint mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_FUNC_FUNC, 3); + OUT_RING_CACHE(func); + OUT_RING_CACHE(ref); + OUT_RING_CACHE(mask); +} + +/** OpenGL 2.0 two-sided StencilMask */ +static void nv20StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_MASK, 1); + OUT_RING_CACHE(mask); +} + +/** OpenGL 2.0 two-sided StencilOp */ +static void nv20StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, + GLenum zfail, GLenum zpass) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_STENCIL_OP_FAIL, 1); + OUT_RING_CACHE(fail); + OUT_RING_CACHE(zfail); + OUT_RING_CACHE(zpass); +} + +/** Control the generation of texture coordinates */ +void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname, + const GLfloat *params); +/** Set texture environment parameters */ +void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *param); +/** Set texture parameters */ +void (*TexParameter)(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params); + +static void nv20TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16); + /*XXX: This SHOULD work.*/ + OUT_RING_CACHEp(mat->m, 16); +} + +/* Update anything that depends on the window position/size */ +static void nv20WindowMoved(nouveauContextPtr nmesa) +{ + GLcontext *ctx = nmesa->glCtx; + GLfloat *v = nmesa->viewport.m; + GLuint w = ctx->Viewport.Width; + GLuint h = ctx->Viewport.Height; + GLuint x = ctx->Viewport.X + nmesa->drawX; + GLuint y = ctx->Viewport.Y + nmesa->drawY; + int i; + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 2); + OUT_RING_CACHE((w << 16) | x); + OUT_RING_CACHE((h << 16) | y); + + BEGIN_RING_SIZE(NvSub3D, 0x02b4, 1); + OUT_RING(0); + + BEGIN_RING_CACHE(NvSub3D, + NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 1); + OUT_RING_CACHE((4095 << 16) | 0); + BEGIN_RING_CACHE(NvSub3D, + NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(0), 1); + OUT_RING_CACHE((4095 << 16) | 0); + for (i=1; i<8; i++) { + BEGIN_RING_CACHE(NvSub3D, + NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 1); + OUT_RING_CACHE(0); + BEGIN_RING_CACHE(NvSub3D, + NV20_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_VERT(i), 1); + OUT_RING_CACHE(0); + } + + ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); + + /* TODO: recalc viewport scale coefs */ +} + +/* Initialise any card-specific non-GL related state */ +static GLboolean nv20InitCard(nouveauContextPtr nmesa) +{ + nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D); + + BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SET_OBJECT1, 2); + OUT_RING(NvDmaFB); /* 184 dma_object1 */ + OUT_RING(NvDmaFB); /* 188 dma_object2 */ + BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SET_OBJECT3, 2); + OUT_RING(NvDmaFB); /* 194 dma_object3 */ + OUT_RING(NvDmaFB); /* 198 dma_object4 */ + BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_SET_OBJECT8, 1); + OUT_RING(NvDmaFB); /* 1a8 dma_object8 */ + + BEGIN_RING_SIZE(NvSub3D, 0x17e0, 3); + OUT_RINGf(0.0); + OUT_RINGf(0.0); + OUT_RINGf(1.0); + + BEGIN_RING_SIZE(NvSub3D, 0x1e6c, 1); + OUT_RING(0x0db6); + BEGIN_RING_SIZE(NvSub3D, 0x0290, 1); + OUT_RING(0x00100001); + BEGIN_RING_SIZE(NvSub3D, 0x09fc, 1); + OUT_RING(0); + BEGIN_RING_SIZE(NvSub3D, 0x1d80, 1); + OUT_RING(1); + BEGIN_RING_SIZE(NvSub3D, 0x09f8, 1); + OUT_RING(4); + + BEGIN_RING_SIZE(NvSub3D, 0x17ec, 3); + OUT_RINGf(0.0); + OUT_RINGf(1.0); + OUT_RINGf(0.0); + + BEGIN_RING_SIZE(NvSub3D, 0x1d88, 1); + OUT_RING(3); + + /* FIXME: More dma objects to setup ? */ + + BEGIN_RING_SIZE(NvSub3D, 0x1e98, 1); + OUT_RING(0); + + BEGIN_RING_SIZE(NvSub3D, 0x120, 3); + OUT_RING(0); + OUT_RING(1); + OUT_RING(2); + + return GL_TRUE; +} + +/* Update buffer offset/pitch/format */ +static GLboolean nv20BindBuffers(nouveauContextPtr nmesa, int num_color, + nouveau_renderbuffer **color, + nouveau_renderbuffer *depth) +{ + GLuint x, y, w, h; + GLuint pitch, format, depth_pitch; + + w = color[0]->mesa.Width; + h = color[0]->mesa.Height; + x = nmesa->drawX; + y = nmesa->drawY; + + if (num_color != 1) + return GL_FALSE; + + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VIEWPORT_HORIZ, 6); + OUT_RING_CACHE((w << 16) | x); + OUT_RING_CACHE((h << 16) | y); + depth_pitch = (depth ? depth->pitch : color[0]->pitch); + pitch = (depth_pitch<<16) | color[0]->pitch; + format = 0x128; + if (color[0]->mesa._ActualFormat != GL_RGBA8) { + format = 0x123; /* R5G6B5 color buffer */ + } + OUT_RING_CACHE(format); + OUT_RING_CACHE(pitch); + OUT_RING_CACHE(color[0]->offset); + OUT_RING_CACHE(depth ? depth->offset : color[0]->offset); + + if (depth) { + BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH, 2); + /* TODO: use a different buffer */ + OUT_RING(depth->pitch); + OUT_RING(depth->offset); + } + + /* Always set to bottom left of buffer */ + BEGIN_RING_CACHE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VIEWPORT_ORIGIN_X, 4); + OUT_RING_CACHEf (0.0); + OUT_RING_CACHEf ((GLfloat) h); + OUT_RING_CACHEf (0.0); + OUT_RING_CACHEf (0.0); + + return GL_TRUE; +} + +void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + func->AlphaFunc = nv20AlphaFunc; + func->BlendColor = nv20BlendColor; + func->BlendEquationSeparate = nv20BlendEquationSeparate; + func->BlendFuncSeparate = nv20BlendFuncSeparate; + func->Clear = nv20Clear; + func->ClearColor = nv20ClearColor; + func->ClearDepth = nv20ClearDepth; + func->ClearStencil = nv20ClearStencil; + func->ClipPlane = nv20ClipPlane; + func->ColorMask = nv20ColorMask; + func->ColorMaterial = nv20ColorMaterial; + func->CullFace = nv20CullFace; + func->FrontFace = nv20FrontFace; + func->DepthFunc = nv20DepthFunc; + func->DepthMask = nv20DepthMask; + func->DepthRange = nv20DepthRange; + func->Enable = nv20Enable; + func->Fogfv = nv20Fogfv; + func->Hint = nv20Hint; + func->Lightfv = nv20Lightfv; +/* func->LightModelfv = nv20LightModelfv; */ + func->LineStipple = nv20LineStipple; + func->LineWidth = nv20LineWidth; + func->LogicOpcode = nv20LogicOpcode; + func->PointParameterfv = nv20PointParameterfv; + func->PointSize = nv20PointSize; + func->PolygonMode = nv20PolygonMode; + func->PolygonOffset = nv20PolygonOffset; + func->PolygonStipple = nv20PolygonStipple; +/* func->ReadBuffer = nv20ReadBuffer;*/ +/* func->RenderMode = nv20RenderMode;*/ + func->Scissor = nv20Scissor; + func->ShadeModel = nv20ShadeModel; + func->StencilFuncSeparate = nv20StencilFuncSeparate; + func->StencilMaskSeparate = nv20StencilMaskSeparate; + func->StencilOpSeparate = nv20StencilOpSeparate; +/* func->TexGen = nv20TexGen;*/ +/* func->TexParameter = nv20TexParameter;*/ + func->TextureMatrix = nv20TextureMatrix; + + nmesa->hw_func.InitCard = nv20InitCard; + nmesa->hw_func.BindBuffers = nv20BindBuffers; + nmesa->hw_func.WindowMoved = nv20WindowMoved; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_vertprog.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_vertprog.c new file mode 100644 index 000000000..60cfcd705 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv20_vertprog.c @@ -0,0 +1,447 @@ +#include "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" + +#include "nouveau_shader.h" +#include "nv20_shader.h" + +unsigned int NVVP_TX_VOP_COUNT = 16; +unsigned int NVVP_TX_NVS_OP_COUNT = 16; +struct _op_xlat NVVP_TX_VOP[32]; +struct _op_xlat NVVP_TX_SOP[32]; + +nvsSwzComp NV20VP_TX_SWIZZLE[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W }; + +/***************************************************************************** + * Support routines + */ +static void +NV20VPUploadToHW(GLcontext *ctx, nouveauShader *nvs) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + int i; + + /* XXX: missing a way to say what insn we're uploading from, and possible + * the program start position (if NV20 has one) */ + for (i=0; i<nvs->program_size; i+=4) { + BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, 4); + OUT_RING(nvs->program[i + 0]); + OUT_RING(nvs->program[i + 1]); + OUT_RING(nvs->program[i + 2]); + OUT_RING(nvs->program[i + 3]); + } +} + +static void +NV20VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + /* Worth checking if the value *actually* changed? Mesa doesn't tell us this + * as far as I know.. + */ + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID, 1); + OUT_RING (id); + BEGIN_RING_SIZE(NvSub3D, NV20_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_X, 4); + OUT_RINGf(nvs->params[id].source_val[0]); + OUT_RINGf(nvs->params[id].source_val[1]); + OUT_RINGf(nvs->params[id].source_val[2]); + OUT_RINGf(nvs->params[id].source_val[3]); +} + +/***************************************************************************** + * Assembly routines + */ + +/***************************************************************************** + * Disassembly routines + */ +void +NV20VPTXSwizzle(int hwswz, nvsSwzComp *swz) +{ + swz[NVS_SWZ_X] = NV20VP_TX_SWIZZLE[(hwswz & 0xC0) >> 6]; + swz[NVS_SWZ_Y] = NV20VP_TX_SWIZZLE[(hwswz & 0x30) >> 4]; + swz[NVS_SWZ_Z] = NV20VP_TX_SWIZZLE[(hwswz & 0x0C) >> 2]; + swz[NVS_SWZ_W] = NV20VP_TX_SWIZZLE[(hwswz & 0x03) >> 0]; +} + +static int +NV20VPHasMergedInst(nvsFunc * shader) +{ + if (shader->GetOpcodeHW(shader, 0) != NV20_VP_INST_OPCODE_NOP && + shader->GetOpcodeHW(shader, 1) != NV20_VP_INST_OPCODE_NOP) + printf + ("\n\n*****both opcode fields have values - PLEASE REPORT*****\n"); + return 0; +} + +static int +NV20VPIsLastInst(nvsFunc * shader) +{ + return ((shader->inst[3] & (1 << 0)) ? 1 : 0); +} + +static int +NV20VPGetOffsetNext(nvsFunc * shader) +{ + return 4; +} + +static struct _op_xlat * +NV20VPGetOPTXRec(nvsFunc * shader, int merged) +{ + struct _op_xlat *opr; + int op; + + if (shader->GetOpcodeSlot(shader, merged)) { + opr = NVVP_TX_SOP; + op = shader->GetOpcodeHW(shader, 1); + if (op >= NVVP_TX_NVS_OP_COUNT) + return NULL; + } + else { + opr = NVVP_TX_VOP; + op = shader->GetOpcodeHW(shader, 0); + if (op >= NVVP_TX_VOP_COUNT) + return NULL; + } + + if (opr[op].SOP == NVS_OP_UNKNOWN) + return NULL; + return &opr[op]; +} + +static struct _op_xlat * +NV20VPGetOPTXFromSOP(nvsOpcode sop, int *id) +{ + int i; + + for (i=0;i<NVVP_TX_VOP_COUNT;i++) { + if (NVVP_TX_VOP[i].SOP == sop) { + if (id) *id = 0; + return &NVVP_TX_VOP[i]; + } + } + + for (i=0;i<NVVP_TX_NVS_OP_COUNT;i++) { + if (NVVP_TX_SOP[i].SOP == sop) { + if (id) *id = 1; + return &NVVP_TX_SOP[i]; + } + } + + return NULL; +} + +static int +NV20VPGetOpcodeSlot(nvsFunc * shader, int merged) +{ + if (shader->HasMergedInst(shader)) + return merged; + if (shader->GetOpcodeHW(shader, 0) == NV20_VP_INST_OPCODE_NOP) + return 1; + return 0; +} + +static nvsOpcode +NV20VPGetOpcode(nvsFunc * shader, int merged) +{ + struct _op_xlat *opr; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr) + return NVS_OP_UNKNOWN; + + return opr->SOP; +} + +static nvsOpcode +NV20VPGetOpcodeHW(nvsFunc * shader, int slot) +{ + if (slot) + return (shader->inst[1] & NV20_VP_INST_SCA_OPCODE_MASK) + >> NV20_VP_INST_SCA_OPCODE_SHIFT; + return (shader->inst[1] & NV20_VP_INST_VEC_OPCODE_MASK) + >> NV20_VP_INST_VEC_OPCODE_SHIFT; +} + +static nvsRegFile +NV20VPGetDestFile(nvsFunc * shader, int merged) +{ + switch (shader->GetOpcode(shader, merged)) { + case NVS_OP_ARL: + return NVS_FILE_ADDRESS; + default: + /*FIXME: This probably isn't correct.. */ + if ((shader->inst[3] & NV20_VP_INST_DEST_WRITEMASK_MASK) == 0) + return NVS_FILE_TEMP; + return NVS_FILE_RESULT; + } +} + +static unsigned int +NV20VPGetDestID(nvsFunc * shader, int merged) +{ + int id; + + switch (shader->GetDestFile(shader, merged)) { + case NVS_FILE_RESULT: + id = ((shader->inst[3] & NV20_VP_INST_DEST_MASK) + >> NV20_VP_INST_DEST_SHIFT); + switch (id) { + case NV20_VP_INST_DEST_POS : return NVS_FR_POSITION; + case NV20_VP_INST_DEST_COL0 : return NVS_FR_COL0; + case NV20_VP_INST_DEST_COL1 : return NVS_FR_COL1; + case NV20_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0; + case NV20_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1; + case NV20_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2; + case NV20_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3; + default: + return -1; + } + case NVS_FILE_ADDRESS: + return 0; + case NVS_FILE_TEMP: + id = ((shader->inst[3] & NV20_VP_INST_DEST_TEMP_ID_MASK) + >> NV20_VP_INST_DEST_TEMP_ID_SHIFT); + return id; + default: + return -1; + } +} + +static unsigned int +NV20VPGetDestMask(nvsFunc * shader, int merged) +{ + int hwmask, mask = 0; + + /* Special handling for ARL - hardware only supports a + * 1-component address reg + */ + if (shader->GetOpcode(shader, merged) == NVS_OP_ARL) + return SMASK_X; + + if (shader->GetDestFile(shader, merged) == NVS_FILE_RESULT) + hwmask = (shader->inst[3] & NV20_VP_INST_DEST_WRITEMASK_MASK) + >> NV20_VP_INST_DEST_WRITEMASK_SHIFT; + else if (shader->GetOpcodeSlot(shader, merged)) + hwmask = (shader->inst[3] & NV20_VP_INST_STEMP_WRITEMASK_MASK) + >> NV20_VP_INST_STEMP_WRITEMASK_SHIFT; + else + hwmask = (shader->inst[3] & NV20_VP_INST_VTEMP_WRITEMASK_MASK) + >> NV20_VP_INST_VTEMP_WRITEMASK_SHIFT; + + if (hwmask & (1 << 3)) mask |= SMASK_X; + if (hwmask & (1 << 2)) mask |= SMASK_Y; + if (hwmask & (1 << 1)) mask |= SMASK_Z; + if (hwmask & (1 << 0)) mask |= SMASK_W; + + return mask; +} + +static unsigned int +NV20VPGetSourceHW(nvsFunc * shader, int merged, int pos) +{ + struct _op_xlat *opr; + unsigned int src; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr) + return -1; + + switch (opr->srcpos[pos]) { + case 0: + src = ((shader->inst[1] & NV20_VP_INST_SRC0H_MASK) + >> NV20_VP_INST_SRC0H_SHIFT) + << NV20_VP_SRC0_HIGH_SHIFT; + src |= ((shader->inst[2] & NV20_VP_INST_SRC0L_MASK) + >> NV20_VP_INST_SRC0L_SHIFT); + break; + case 1: + src = ((shader->inst[2] & NV20_VP_INST_SRC1_MASK) + >> NV20_VP_INST_SRC1_SHIFT); + break; + case 2: + src = ((shader->inst[2] & NV20_VP_INST_SRC2H_MASK) + >> NV20_VP_INST_SRC2H_SHIFT) + << NV20_VP_SRC2_HIGH_SHIFT; + src |= ((shader->inst[3] & NV20_VP_INST_SRC2L_MASK) + >> NV20_VP_INST_SRC2L_SHIFT); + break; + default: + src = -1; + } + + return src; +} + +static nvsRegFile +NV20VPGetSourceFile(nvsFunc * shader, int merged, int pos) +{ + unsigned int src; + struct _op_xlat *opr; + int file; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr || opr->srcpos[pos] == -1) + return -1; + + switch (opr->srcpos[pos]) { + case SPOS_ADDRESS: + return NVS_FILE_ADDRESS; + default: + src = NV20VPGetSourceHW(shader, merged, pos); + file = (src & NV20_VP_SRC_REG_TYPE_MASK) >> NV20_VP_SRC_REG_TYPE_SHIFT; + + switch (file) { + case NV20_VP_SRC_REG_TYPE_TEMP : return NVS_FILE_TEMP; + case NV20_VP_SRC_REG_TYPE_INPUT: return NVS_FILE_ATTRIB; + case NV20_VP_SRC_REG_TYPE_CONST: return NVS_FILE_CONST; + default: + return NVS_FILE_UNKNOWN; + } + } +} + +static int +NV20VPGetSourceID(nvsFunc * shader, int merged, int pos) +{ + unsigned int src; + + switch (shader->GetSourceFile(shader, merged, pos)) { + case NVS_FILE_TEMP: + src = shader->GetSourceHW(shader, merged, pos); + return ((src & NV20_VP_SRC_REG_TEMP_ID_MASK) >> + NV20_VP_SRC_REG_TEMP_ID_SHIFT); + case NVS_FILE_CONST: + return ((shader->inst[1] & NV20_VP_INST_CONST_SRC_MASK) + >> NV20_VP_INST_CONST_SRC_SHIFT); + case NVS_FILE_ATTRIB: + src = ((shader->inst[1] & NV20_VP_INST_INPUT_SRC_MASK) + >> NV20_VP_INST_INPUT_SRC_SHIFT); + switch (src) { + case NV20_VP_INST_INPUT_SRC_POS : return NVS_FR_POSITION; + case NV20_VP_INST_INPUT_SRC_COL0 : return NVS_FR_COL0; + case NV20_VP_INST_INPUT_SRC_COL1 : return NVS_FR_COL1; + case NV20_VP_INST_INPUT_SRC_TC(0): return NVS_FR_TEXCOORD0; + case NV20_VP_INST_INPUT_SRC_TC(1): return NVS_FR_TEXCOORD1; + case NV20_VP_INST_INPUT_SRC_TC(2): return NVS_FR_TEXCOORD2; + case NV20_VP_INST_INPUT_SRC_TC(3): return NVS_FR_TEXCOORD3; + default: + return NVS_FR_UNKNOWN; + } + default: + return -1; + } +} + +static int +NV20VPGetSourceNegate(nvsFunc * shader, int merged, int pos) +{ + unsigned int src; + + src = shader->GetSourceHW(shader, merged, pos); + + return ((src & NV20_VP_SRC_REG_NEGATE) ? 1 : 0); +} + +static int +NV20VPGetSourceAbs(nvsFunc * shader, int merged, int pos) +{ + /* NV20 can't do ABS on sources? Appears to be emulated with + * MAX reg, reg, -reg + */ + return 0; +} + +static void +NV20VPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz) +{ + unsigned int src; + int swzbits; + + src = shader->GetSourceHW(shader, merged, pos); + swzbits = + (src & NV20_VP_SRC_REG_SWZ_ALL_MASK) >> NV20_VP_SRC_REG_SWZ_ALL_SHIFT; + return NV20VPTXSwizzle(swzbits, swz); +} + +static int +NV20VPGetSourceIndexed(nvsFunc * shader, int merged, int pos) +{ + /* I don't think NV20 can index into attribs, at least no GL + * extension is exposed that will allow it. + */ + if (shader->GetSourceFile(shader, merged, pos) != NVS_FILE_CONST) + return 0; + if (shader->inst[3] & NV20_VP_INST_INDEX_CONST) + return 1; + return 0; +} + +static int +NV20VPGetAddressRegID(nvsFunc * shader) +{ + /* Only 1 address reg */ + return 0; +} + +static nvsSwzComp +NV20VPGetAddressRegSwizzle(nvsFunc * shader) +{ + /* Only A0.x available */ + return NVS_SWZ_X; +} + +void +NV20VPInitShaderFuncs(nvsFunc * shader) +{ + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MOV, NVS_OP_MOV, 0, -1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MUL, NVS_OP_MUL, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_ADD, NVS_OP_ADD, 0, 2, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MAD, NVS_OP_MAD, 0, 1, 2); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DP3, NVS_OP_DP3, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DPH, NVS_OP_DPH, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DP4, NVS_OP_DP4, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_DST, NVS_OP_DST, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MIN, NVS_OP_MIN, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_MAX, NVS_OP_MAX, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_SLT, NVS_OP_SLT, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_SGE, NVS_OP_SGE, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV20_VP_INST_OPCODE_ARL, NVS_OP_ARL, 0, -1, -1); + + MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RCP, NVS_OP_RCP, 2, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RCC, NVS_OP_RCC, 2, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_RSQ, NVS_OP_RSQ, 2, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_EXP, NVS_OP_EXP, 2, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_LOG, NVS_OP_LOG, 2, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV20_VP_INST_OPCODE_LIT, NVS_OP_LIT, 2, -1, -1); + + shader->UploadToHW = NV20VPUploadToHW; + shader->UpdateConst = NV20VPUpdateConst; + + shader->GetOPTXRec = NV20VPGetOPTXRec; + shader->GetOPTXFromSOP = NV20VPGetOPTXFromSOP; + + shader->HasMergedInst = NV20VPHasMergedInst; + shader->IsLastInst = NV20VPIsLastInst; + shader->GetOffsetNext = NV20VPGetOffsetNext; + shader->GetOpcodeSlot = NV20VPGetOpcodeSlot; + shader->GetOpcode = NV20VPGetOpcode; + shader->GetOpcodeHW = NV20VPGetOpcodeHW; + shader->GetDestFile = NV20VPGetDestFile; + shader->GetDestID = NV20VPGetDestID; + shader->GetDestMask = NV20VPGetDestMask; + shader->GetSourceHW = NV20VPGetSourceHW; + shader->GetSourceFile = NV20VPGetSourceFile; + shader->GetSourceID = NV20VPGetSourceID; + shader->GetSourceNegate = NV20VPGetSourceNegate; + shader->GetSourceAbs = NV20VPGetSourceAbs; + shader->GetSourceSwizzle = NV20VPGetSourceSwizzle; + shader->GetSourceIndexed = NV20VPGetSourceIndexed; + shader->GetRelAddressRegID = NV20VPGetAddressRegID; + shader->GetRelAddressSwizzle = NV20VPGetAddressRegSwizzle; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_fragprog.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_fragprog.c new file mode 100644 index 000000000..e32452361 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_fragprog.c @@ -0,0 +1,742 @@ +#include <stdint.h> + +#include "glheader.h" +#include "macros.h" + +#include "nouveau_context.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" +#include "nouveau_drm.h" +#include "nouveau_shader.h" +#include "nouveau_object.h" +#include "nouveau_msg.h" +#include "nouveau_bufferobj.h" +#include "nv30_shader.h" + +unsigned int NVFP_TX_AOP_COUNT = 64; +struct _op_xlat NVFP_TX_AOP[64]; + +/******************************************************************************* + * Support routines + */ + +static void +NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nvsCardPriv *priv = &nvs->card_priv; + uint32_t offset; + + if (!nvs->program_buffer) + nvs->program_buffer = ctx->Driver.NewBufferObject(ctx, 0, + GL_ARRAY_BUFFER_ARB); + + /* Should use STATIC_DRAW_ARB if shader doesn't use changable params */ + nouveau_bo_init_storage(ctx, NOUVEAU_BO_VRAM_OK, + nvs->program_size * sizeof(uint32_t), + (const GLvoid *)nvs->program, + GL_DYNAMIC_DRAW_ARB, + nvs->program_buffer); + + offset = nouveau_bo_gpu_ref(ctx, nvs->program_buffer); + + /* Not using state cache here, updated programs at the same address don't + * seem to take effect unless the ACTIVE_PROGRAM method is called again. + * HW caches the program somewhere? + */ + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1); + OUT_RING (offset | 1); + if (nmesa->screen->card->type == NV_30) { + BEGIN_RING_SIZE(NvSub3D, + 0x1d60 /*NV30_TCL_PRIMITIVE_3D_FP_CONTROL*/, 1); + OUT_RING ((priv->NV30FP.uses_kil << 7)); + BEGIN_RING_SIZE(NvSub3D, 0x1450, 1); + OUT_RING (priv->NV30FP.num_regs << 16); + } else { + BEGIN_RING_SIZE(NvSub3D, + 0x1d60 /*NV30_TCL_PRIMITIVE_3D_FP_CONTROL*/, 1); + OUT_RING ((priv->NV30FP.uses_kil << 7) | + (priv->NV30FP.num_regs << 24)); + } +} + +static void +NV30FPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id) +{ + uint32_t *new = nvs->params[id].source_val ? + (uint32_t*)nvs->params[id].source_val : (uint32_t*)nvs->params[id].val; + uint32_t *current; + int i; + + for (i=0; i<nvs->params[id].hw_index_cnt; i++) { + current = nvs->program + nvs->params[id].hw_index[i]; + COPY_4V(current, new); + } + nvs->on_hardware = 0; +} + +/******************************************************************************* + * Assembly helpers + */ +static struct _op_xlat * +NV30FPGetOPTXFromSOP(nvsOpcode op, int *id) +{ + int i; + + for (i=0; i<NVFP_TX_AOP_COUNT; i++) { + if (NVFP_TX_AOP[i].SOP == op) { + if (id) *id = 0; + return &NVFP_TX_AOP[i]; + } + } + + return NULL; +} + +static int +NV30FPSupportsOpcode(nvsFunc *shader, nvsOpcode op) +{ + if (shader->GetOPTXFromSOP(op, NULL)) + return 1; + return 0; +} + +static void +NV30FPSetOpcode(nvsFunc *shader, unsigned int opcode, int slot) +{ + if (opcode == NV30_FP_OP_OPCODE_KIL) + shader->card_priv->NV30FP.uses_kil = GL_TRUE; + shader->inst[0] &= ~NV30_FP_OP_OPCODE_MASK; + shader->inst[0] |= (opcode << NV30_FP_OP_OPCODE_SHIFT); +} + +static void +NV30FPSetCCUpdate(nvsFunc *shader) +{ + shader->inst[0] |= NV30_FP_OP_COND_WRITE_ENABLE; +} + +static void +NV30FPSetCondition(nvsFunc *shader, int on, nvsCond cond, int reg, + nvsSwzComp *swz) +{ + nvsSwzComp default_swz[4] = { NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W }; + unsigned int hwcond; + + /* cond masking is always enabled */ + if (!on) { + cond = NVS_COND_TR; + reg = 0; + swz = default_swz; + } + + switch (cond) { + case NVS_COND_TR: hwcond = NV30_FP_OP_COND_TR; break; + case NVS_COND_FL: hwcond = NV30_FP_OP_COND_FL; break; + case NVS_COND_LT: hwcond = NV30_FP_OP_COND_LT; break; + case NVS_COND_GT: hwcond = NV30_FP_OP_COND_GT; break; + case NVS_COND_LE: hwcond = NV30_FP_OP_COND_LE; break; + case NVS_COND_GE: hwcond = NV30_FP_OP_COND_GE; break; + case NVS_COND_EQ: hwcond = NV30_FP_OP_COND_EQ; break; + case NVS_COND_NE: hwcond = NV30_FP_OP_COND_NE; break; + default: + WARN_ONCE("unknown fp condmask=%d\n", cond); + hwcond = NV30_FP_OP_COND_TR; + break; + } + + shader->inst[1] &= ~NV30_FP_OP_COND_MASK; + shader->inst[1] |= (hwcond << NV30_FP_OP_COND_SHIFT); + + shader->inst[1] &= ~NV30_FP_OP_COND_SWZ_ALL_MASK; + shader->inst[1] |= (swz[NVS_SWZ_X] << NV30_FP_OP_COND_SWZ_X_SHIFT); + shader->inst[1] |= (swz[NVS_SWZ_Y] << NV30_FP_OP_COND_SWZ_Y_SHIFT); + shader->inst[1] |= (swz[NVS_SWZ_Z] << NV30_FP_OP_COND_SWZ_Z_SHIFT); + shader->inst[1] |= (swz[NVS_SWZ_W] << NV30_FP_OP_COND_SWZ_W_SHIFT); +} + +static void +NV30FPSetHighReg(nvsFunc *shader, int id) +{ + if (shader->card_priv->NV30FP.num_regs < (id+1)) { + if (id == 0) + id = 1; /* necessary? */ + shader->card_priv->NV30FP.num_regs = (id+1); + } +} + +static void +NV30FPSetResult(nvsFunc *shader, nvsRegister *reg, unsigned int mask, int slot) +{ + unsigned int hwreg; + + if (mask & SMASK_X) shader->inst[0] |= NV30_FP_OP_OUT_X; + if (mask & SMASK_Y) shader->inst[0] |= NV30_FP_OP_OUT_Y; + if (mask & SMASK_Z) shader->inst[0] |= NV30_FP_OP_OUT_Z; + if (mask & SMASK_W) shader->inst[0] |= NV30_FP_OP_OUT_W; + + if (reg->file == NVS_FILE_RESULT) { + hwreg = 0; /* FIXME: this is only fragment.color */ + /* This is *not* correct, I have no idea what it is either */ + shader->inst[0] |= NV30_FP_OP_UNK0_7; + } else { + shader->inst[0] &= ~NV30_FP_OP_UNK0_7; + hwreg = reg->index; + } + NV30FPSetHighReg(shader, hwreg); + shader->inst[0] &= ~NV30_FP_OP_OUT_REG_SHIFT; + shader->inst[0] |= (hwreg << NV30_FP_OP_OUT_REG_SHIFT); +} + +static void +NV30FPSetSource(nvsFunc *shader, nvsRegister *reg, int pos) +{ + unsigned int hwsrc = 0; + + switch (reg->file) { + case NVS_FILE_TEMP: + hwsrc |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT); + hwsrc |= (reg->index << NV30_FP_REG_SRC_SHIFT); + NV30FPSetHighReg(shader, reg->index); + break; + case NVS_FILE_ATTRIB: + { + unsigned int hwin; + + switch (reg->index) { + case NVS_FR_POSITION : hwin = NV30_FP_OP_INPUT_SRC_POSITION; break; + case NVS_FR_COL0 : hwin = NV30_FP_OP_INPUT_SRC_COL0; break; + case NVS_FR_COL1 : hwin = NV30_FP_OP_INPUT_SRC_COL1; break; + case NVS_FR_FOGCOORD : hwin = NV30_FP_OP_INPUT_SRC_FOGC; break; + case NVS_FR_TEXCOORD0: hwin = NV30_FP_OP_INPUT_SRC_TC(0); break; + case NVS_FR_TEXCOORD1: hwin = NV30_FP_OP_INPUT_SRC_TC(1); break; + case NVS_FR_TEXCOORD2: hwin = NV30_FP_OP_INPUT_SRC_TC(2); break; + case NVS_FR_TEXCOORD3: hwin = NV30_FP_OP_INPUT_SRC_TC(3); break; + case NVS_FR_TEXCOORD4: hwin = NV30_FP_OP_INPUT_SRC_TC(4); break; + case NVS_FR_TEXCOORD5: hwin = NV30_FP_OP_INPUT_SRC_TC(5); break; + case NVS_FR_TEXCOORD6: hwin = NV30_FP_OP_INPUT_SRC_TC(6); break; + case NVS_FR_TEXCOORD7: hwin = NV30_FP_OP_INPUT_SRC_TC(7); break; + default: + WARN_ONCE("unknown fp input %d\n", reg->index); + hwin = NV30_FP_OP_INPUT_SRC_COL0; + break; + } + shader->inst[0] &= ~NV30_FP_OP_INPUT_SRC_MASK; + shader->inst[0] |= (hwin << NV30_FP_OP_INPUT_SRC_SHIFT); + hwsrc |= (hwin << NV30_FP_REG_SRC_SHIFT); + } + hwsrc |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT); + break; + case NVS_FILE_CONST: + /* consts are inlined after the inst */ + hwsrc |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT); + break; + default: + assert(0); + break; + } + + if (reg->negate) + hwsrc |= NV30_FP_REG_NEGATE; + if (reg->abs) + shader->inst[1] |= (1 << (29+pos)); + hwsrc |= (reg->swizzle[NVS_SWZ_X] << NV30_FP_REG_SWZ_X_SHIFT); + hwsrc |= (reg->swizzle[NVS_SWZ_Y] << NV30_FP_REG_SWZ_Y_SHIFT); + hwsrc |= (reg->swizzle[NVS_SWZ_Z] << NV30_FP_REG_SWZ_Z_SHIFT); + hwsrc |= (reg->swizzle[NVS_SWZ_W] << NV30_FP_REG_SWZ_W_SHIFT); + + shader->inst[pos+1] &= ~NV30_FP_REG_ALL_MASK; + shader->inst[pos+1] |= hwsrc; +} + +static void +NV30FPSetTexImageUnit(nvsFunc *shader, int unit) +{ + shader->inst[0] &= ~NV30_FP_OP_TEX_UNIT_SHIFT; + shader->inst[0] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT); +} + +static void +NV30FPSetSaturate(nvsFunc *shader) +{ + shader->inst[0] |= NV30_FP_OP_OUT_SAT; +} + +static void +NV30FPInitInstruction(nvsFunc *shader) +{ + unsigned int hwsrc; + + shader->inst[0] = 0; + + hwsrc = (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT) | + (NVS_SWZ_X << NV30_FP_REG_SWZ_X_SHIFT) | + (NVS_SWZ_Y << NV30_FP_REG_SWZ_Y_SHIFT) | + (NVS_SWZ_Z << NV30_FP_REG_SWZ_Z_SHIFT) | + (NVS_SWZ_W << NV30_FP_REG_SWZ_W_SHIFT); + shader->inst[1] = hwsrc; + shader->inst[2] = hwsrc; + shader->inst[3] = hwsrc; +} + +static void +NV30FPSetLastInst(nvsFunc *shader) +{ + shader->inst[0] |= 1; +} + +/******************************************************************************* + * Disassembly helpers + */ +static struct _op_xlat * +NV30FPGetOPTXRec(nvsFunc * shader, int merged) +{ + int op; + + op = shader->GetOpcodeHW(shader, 0); + if (op > NVFP_TX_AOP_COUNT) + return NULL; + if (NVFP_TX_AOP[op].SOP == NVS_OP_UNKNOWN) + return NULL; + return &NVFP_TX_AOP[op]; +} + +static int +NV30FPHasMergedInst(nvsFunc * shader) +{ + return 0; +} + +static int +NV30FPIsLastInst(nvsFunc * shader) +{ + return ((shader->inst[0] & NV30_FP_OP_PROGRAM_END) ? 1 : 0); +} + +static int +NV30FPGetOffsetNext(nvsFunc * shader) +{ + int i; + + for (i = 0; i < 3; i++) + if (shader->GetSourceFile(shader, 0, i) == NVS_FILE_CONST) + return 8; + return 4; +} + +static nvsOpcode +NV30FPGetOpcode(nvsFunc * shader, int merged) +{ + struct _op_xlat *opr; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr) + return NVS_OP_UNKNOWN; + + return opr->SOP; +} + +static unsigned int +NV30FPGetOpcodeHW(nvsFunc * shader, int slot) +{ + int op; + + op = (shader->inst[0] & NV30_FP_OP_OPCODE_MASK) >> NV30_FP_OP_OPCODE_SHIFT; + + return op; +} + +static nvsRegFile +NV30FPGetDestFile(nvsFunc * shader, int merged) +{ + /* Result regs overlap temporary regs */ + return NVS_FILE_TEMP; +} + +static unsigned int +NV30FPGetDestID(nvsFunc * shader, int merged) +{ + int id; + + switch (shader->GetDestFile(shader, merged)) { + case NVS_FILE_TEMP: + id = ((shader->inst[0] & NV30_FP_OP_OUT_REG_MASK) + >> NV30_FP_OP_OUT_REG_SHIFT); + return id; + default: + return -1; + } +} + +static unsigned int +NV30FPGetDestMask(nvsFunc * shader, int merged) +{ + unsigned int mask = 0; + + if (shader->inst[0] & NV30_FP_OP_OUT_X) mask |= SMASK_X; + if (shader->inst[0] & NV30_FP_OP_OUT_Y) mask |= SMASK_Y; + if (shader->inst[0] & NV30_FP_OP_OUT_Z) mask |= SMASK_Z; + if (shader->inst[0] & NV30_FP_OP_OUT_W) mask |= SMASK_W; + + return mask; +} + +static unsigned int +NV30FPGetSourceHW(nvsFunc * shader, int merged, int pos) +{ + struct _op_xlat *opr; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr || opr->srcpos[pos] == -1) + return -1; + + return shader->inst[opr->srcpos[pos] + 1]; +} + +static nvsRegFile +NV30FPGetSourceFile(nvsFunc * shader, int merged, int pos) +{ + unsigned int src; + struct _op_xlat *opr; + int file; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr || opr->srcpos[pos] == -1) + return NVS_FILE_UNKNOWN; + + switch (opr->srcpos[pos]) { + case SPOS_ADDRESS: return NVS_FILE_ADDRESS; + default: + src = shader->GetSourceHW(shader, merged, pos); + file = (src & NV30_FP_REG_TYPE_MASK) >> NV30_FP_REG_TYPE_SHIFT; + + switch (file) { + case NV30_FP_REG_TYPE_TEMP : return NVS_FILE_TEMP; + case NV30_FP_REG_TYPE_INPUT: return NVS_FILE_ATTRIB; + case NV30_FP_REG_TYPE_CONST: return NVS_FILE_CONST; + default: + return NVS_FILE_UNKNOWN; + } + } +} + +static int +NV30FPGetSourceID(nvsFunc * shader, int merged, int pos) +{ + switch (shader->GetSourceFile(shader, merged, pos)) { + case NVS_FILE_ATTRIB: + switch ((shader->inst[0] & NV30_FP_OP_INPUT_SRC_MASK) + >> NV30_FP_OP_INPUT_SRC_SHIFT) { + case NV30_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION; + case NV30_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0; + case NV30_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1; + case NV30_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD; + case NV30_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0; + case NV30_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1; + case NV30_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2; + case NV30_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3; + case NV30_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4; + case NV30_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5; + case NV30_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6; + case NV30_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7; + default: + return -1; + } + break; + case NVS_FILE_TEMP: + { + unsigned int src; + + src = shader->GetSourceHW(shader, merged, pos); + return ((src & NV30_FP_REG_SRC_MASK) >> NV30_FP_REG_SRC_SHIFT); + } + case NVS_FILE_CONST: /* inlined into fragprog */ + default: + return -1; + } +} + +static int +NV30FPGetTexImageUnit(nvsFunc *shader) +{ + return ((shader->inst[0] & NV30_FP_OP_TEX_UNIT_MASK) + >> NV30_FP_OP_TEX_UNIT_SHIFT); +} + +static int +NV30FPGetSourceNegate(nvsFunc * shader, int merged, int pos) +{ + unsigned int src; + + src = shader->GetSourceHW(shader, merged, pos); + + if (src == -1) + return -1; + return ((src & NV30_FP_REG_NEGATE) ? 1 : 0); +} + +static int +NV30FPGetSourceAbs(nvsFunc * shader, int merged, int pos) +{ + struct _op_xlat *opr; + static unsigned int abspos[3] = { + NV30_FP_OP_OUT_ABS, + (1 << 30), /* guess */ + (1 << 31) /* guess */ + }; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr || opr->srcpos[pos] == -1) + return -1; + + return ((shader->inst[1] & abspos[opr->srcpos[pos]]) ? 1 : 0); +} + +nvsSwzComp NV30FP_TX_SWIZZLE[4] = {NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W }; + +static void +NV30FPTXSwizzle(int hwswz, nvsSwzComp *swz) +{ + swz[NVS_SWZ_W] = NV30FP_TX_SWIZZLE[(hwswz & 0xC0) >> 6]; + swz[NVS_SWZ_Z] = NV30FP_TX_SWIZZLE[(hwswz & 0x30) >> 4]; + swz[NVS_SWZ_Y] = NV30FP_TX_SWIZZLE[(hwswz & 0x0C) >> 2]; + swz[NVS_SWZ_X] = NV30FP_TX_SWIZZLE[(hwswz & 0x03) >> 0]; +} + +static void +NV30FPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz) +{ + unsigned int src; + int swzbits; + + src = shader->GetSourceHW(shader, merged, pos); + swzbits = (src & NV30_FP_REG_SWZ_ALL_MASK) >> NV30_FP_REG_SWZ_ALL_SHIFT; + NV30FPTXSwizzle(swzbits, swz); +} + +static int +NV30FPGetSourceIndexed(nvsFunc * shader, int merged, int pos) +{ + switch (shader->GetSourceFile(shader, merged, pos)) { + case NVS_FILE_ATTRIB: + return ((shader->inst[3] & NV30_FP_OP_INDEX_INPUT) ? 1 : 0); + default: + return 0; + } +} + +static void +NV30FPGetSourceConstVal(nvsFunc * shader, int merged, int pos, float *val) +{ + val[0] = *(float *) &(shader->inst[4]); + val[1] = *(float *) &(shader->inst[5]); + val[2] = *(float *) &(shader->inst[6]); + val[3] = *(float *) &(shader->inst[7]); +} + +static int +NV30FPGetSourceScale(nvsFunc * shader, int merged, int pos) +{ +/*FIXME: is this per-source, only for a specific source, or all sources??*/ + return (1 << ((shader->inst[2] & NV30_FP_OP_SRC_SCALE_MASK) + >> NV30_FP_OP_SRC_SCALE_SHIFT)); +} + +static int +NV30FPGetAddressRegID(nvsFunc * shader) +{ + return 0; +} + +static nvsSwzComp +NV30FPGetAddressRegSwizzle(nvsFunc * shader) +{ + return NVS_SWZ_X; +} + +static int +NV30FPSupportsConditional(nvsFunc * shader) +{ + /*FIXME: Is this true of all ops? */ + return 1; +} + +static int +NV30FPGetConditionUpdate(nvsFunc * shader) +{ + return ((shader->inst[0] & NV30_FP_OP_COND_WRITE_ENABLE) ? 1 : 0); +} + +static int +NV30FPGetConditionTest(nvsFunc * shader) +{ + /*FIXME: always? */ + return 1; +} + +static nvsCond +NV30FPGetCondition(nvsFunc * shader) +{ + int cond; + + cond = ((shader->inst[1] & NV30_FP_OP_COND_MASK) + >> NV30_FP_OP_COND_SHIFT); + + switch (cond) { + case NV30_FP_OP_COND_FL: return NVS_COND_FL; + case NV30_FP_OP_COND_LT: return NVS_COND_LT; + case NV30_FP_OP_COND_EQ: return NVS_COND_EQ; + case NV30_FP_OP_COND_LE: return NVS_COND_LE; + case NV30_FP_OP_COND_GT: return NVS_COND_GT; + case NV30_FP_OP_COND_NE: return NVS_COND_NE; + case NV30_FP_OP_COND_GE: return NVS_COND_GE; + case NV30_FP_OP_COND_TR: return NVS_COND_TR; + default: + return NVS_COND_UNKNOWN; + } +} + +static void +NV30FPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz) +{ + int swzbits; + + swzbits = (shader->inst[1] & NV30_FP_OP_COND_SWZ_ALL_MASK) + >> NV30_FP_OP_COND_SWZ_ALL_SHIFT; + NV30FPTXSwizzle(swzbits, swz); +} + +static int +NV30FPGetCondRegID(nvsFunc * shader) +{ + return 0; +} + +static nvsPrecision +NV30FPGetPrecision(nvsFunc * shader) +{ + int p; + + p = (shader->inst[0] & NV30_FP_OP_PRECISION_MASK) + >> NV30_FP_OP_PRECISION_SHIFT; + + switch (p) { + case NV30_FP_PRECISION_FP32: return NVS_PREC_FLOAT32; + case NV30_FP_PRECISION_FP16: return NVS_PREC_FLOAT16; + case NV30_FP_PRECISION_FX12: return NVS_PREC_FIXED12; + default: + return NVS_PREC_UNKNOWN; + } +} + +static int +NV30FPGetSaturate(nvsFunc * shader) +{ + return ((shader->inst[0] & NV30_FP_OP_OUT_SAT) ? 1 : 0); +} + +/******************************************************************************* + * Init + */ +void +NV30FPInitShaderFuncs(nvsFunc * shader) +{ + /* These are probably bogus, I made them up... */ + shader->MaxInst = 1024; + shader->MaxAttrib = 16; + shader->MaxTemp = 32; + shader->MaxAddress = 1; + shader->MaxConst = 256; + shader->caps = SCAP_SRC_ABS; + + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MOV, NVS_OP_MOV, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MUL, NVS_OP_MUL, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_ADD, NVS_OP_ADD, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MAD, NVS_OP_MAD, 0, 1, 2); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DP3, NVS_OP_DP3, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DP4, NVS_OP_DP4, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DST, NVS_OP_DST, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MIN, NVS_OP_MIN, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_MAX, NVS_OP_MAX, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SLT, NVS_OP_SLT, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SGE, NVS_OP_SGE, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_FRC, NVS_OP_FRC, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_FLR, NVS_OP_FLR, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TEX, NVS_OP_TEX, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXD, NVS_OP_TXD, 0, 1, 2); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXP, NVS_OP_TXP, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_TXB, NVS_OP_TXB, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SEQ, NVS_OP_SEQ, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SGT, NVS_OP_SGT, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SLE, NVS_OP_SLE, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SNE, NVS_OP_SNE, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RCP, NVS_OP_RCP, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LG2, NVS_OP_LG2, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_EX2, NVS_OP_EX2, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_COS, NVS_OP_COS, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_SIN, NVS_OP_SIN, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_NOP, NVS_OP_NOP, -1, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DDX, NVS_OP_DDX, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_DDY, NVS_OP_DDY, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_KIL, NVS_OP_KIL, -1, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK4B, NVS_OP_PK4B, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP4B, NVS_OP_UP4B, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK2H, NVS_OP_PK2H, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP2H, NVS_OP_UP2H, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK4UB, NVS_OP_PK4UB, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP4UB, NVS_OP_UP4UB, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_PK2US, NVS_OP_PK2US, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_UP2US, NVS_OP_UP2US, 0, -1, -1); + /*FIXME: Haven't confirmed the source positions for the below opcodes */ + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LIT, NVS_OP_LIT, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_LRP, NVS_OP_LRP, 0, 1, 2); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_POW, NVS_OP_POW, 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RSQ, NVS_OP_RSQ, 0, -1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV30_FP_OP_OPCODE_RFL, NVS_OP_RFL, 0, 1, -1); + + shader->GetOPTXRec = NV30FPGetOPTXRec; + shader->GetOPTXFromSOP = NV30FPGetOPTXFromSOP; + + shader->UploadToHW = NV30FPUploadToHW; + shader->UpdateConst = NV30FPUpdateConst; + + shader->InitInstruction = NV30FPInitInstruction; + shader->SupportsOpcode = NV30FPSupportsOpcode; + shader->SetOpcode = NV30FPSetOpcode; + shader->SetCCUpdate = NV30FPSetCCUpdate; + shader->SetCondition = NV30FPSetCondition; + shader->SetResult = NV30FPSetResult; + shader->SetSource = NV30FPSetSource; + shader->SetTexImageUnit = NV30FPSetTexImageUnit; + shader->SetSaturate = NV30FPSetSaturate; + shader->SetLastInst = NV30FPSetLastInst; + + shader->HasMergedInst = NV30FPHasMergedInst; + shader->IsLastInst = NV30FPIsLastInst; + shader->GetOffsetNext = NV30FPGetOffsetNext; + shader->GetOpcode = NV30FPGetOpcode; + shader->GetOpcodeHW = NV30FPGetOpcodeHW; + shader->GetDestFile = NV30FPGetDestFile; + shader->GetDestID = NV30FPGetDestID; + shader->GetDestMask = NV30FPGetDestMask; + shader->GetSourceHW = NV30FPGetSourceHW; + shader->GetSourceFile = NV30FPGetSourceFile; + shader->GetSourceID = NV30FPGetSourceID; + shader->GetTexImageUnit = NV30FPGetTexImageUnit; + shader->GetSourceNegate = NV30FPGetSourceNegate; + shader->GetSourceAbs = NV30FPGetSourceAbs; + shader->GetSourceSwizzle = NV30FPGetSourceSwizzle; + shader->GetSourceIndexed = NV30FPGetSourceIndexed; + shader->GetSourceConstVal = NV30FPGetSourceConstVal; + shader->GetSourceScale = NV30FPGetSourceScale; + shader->GetRelAddressRegID = NV30FPGetAddressRegID; + shader->GetRelAddressSwizzle = NV30FPGetAddressRegSwizzle; + shader->GetPrecision = NV30FPGetPrecision; + shader->GetSaturate = NV30FPGetSaturate; + shader->SupportsConditional = NV30FPSupportsConditional; + shader->GetConditionUpdate = NV30FPGetConditionUpdate; + shader->GetConditionTest = NV30FPGetConditionTest; + shader->GetCondition = NV30FPGetCondition; + shader->GetCondRegSwizzle = NV30FPGetCondRegSwizzle; + shader->GetCondRegID = NV30FPGetCondRegID; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_shader.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_shader.h new file mode 100644 index 000000000..7a027dd42 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_shader.h @@ -0,0 +1,379 @@ +#ifndef __NV30_SHADER_H__ +#define __NV30_SHADER_H__ + +/* Vertex programs instruction set + * + * 128bit opcodes, split into 4 32-bit ones for ease of use. + * + * Non-native instructions + * ABS - MOV + NV40_VP_INST0_DEST_ABS + * POW - EX2 + MUL + LG2 + * SUB - ADD, second source negated + * SWZ - MOV + * XPD - + * + * Register access + * - Only one INPUT can be accessed per-instruction (move extras into TEMPs) + * - Only one CONST can be accessed per-instruction (move extras into TEMPs) + * + * Relative Addressing + * According to the value returned for MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB + * there are only two address registers available. The destination in the ARL + * instruction is set to TEMP <n> (The temp isn't actually written). + * + * When using vanilla ARB_v_p, the proprietary driver will squish both the available + * ADDRESS regs into the first hardware reg in the X and Y components. + * + * To use an address reg as an index into consts, the CONST_SRC is set to + * (const_base + offset) and INDEX_CONST is set. + * + * To access the second address reg use ADDR_REG_SELECT_1. A particular component + * of the address regs is selected with ADDR_SWZ. + * + * Only one address register can be accessed per instruction. + * + * Conditional execution (see NV_vertex_program{2,3} for details) + * Conditional execution of an instruction is enabled by setting COND_TEST_ENABLE, and + * selecting the condition which will allow the test to pass with COND_{FL,LT,...}. + * It is possible to swizzle the values in the condition register, which allows for + * testing against an individual component. + * + * Branching + * The BRA/CAL instructions seem to follow a slightly different opcode layout. The + * destination instruction ID (IADDR) overlaps a source field. Instruction ID's seem to + * be numbered based on the UPLOAD_FROM_ID FIFO command, and is incremented automatically + * on each UPLOAD_INST FIFO command. + * + * Conditional branching is achieved by using the condition tests described above. + * There doesn't appear to be dedicated looping instructions, but this can be done + * using a temp reg + conditional branching. + * + * Subroutines may be uploaded before the main program itself, but the first executed + * instruction is determined by the PROGRAM_START_ID FIFO command. + * + */ + +/* DWORD 0 */ +#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24) +#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */ +#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */ +#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */ +#define NV30_VP_INST_OUT_RESULT (1 << 20) +#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16 +#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16) +#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15) +#define NV30_VP_INST_COND_TEST_ENABLE (1<<14) +#define NV30_VP_INST_COND_SHIFT 11 +#define NV30_VP_INST_COND_MASK (0x07 << 11) +# define NV30_VP_INST_COND_FL 0 /* guess */ +# define NV30_VP_INST_COND_LT 1 +# define NV30_VP_INST_COND_EQ 2 +# define NV30_VP_INST_COND_LE 3 +# define NV30_VP_INST_COND_GT 4 +# define NV30_VP_INST_COND_NE 5 +# define NV30_VP_INST_COND_GE 6 +# define NV30_VP_INST_COND_TR 7 /* guess */ +#define NV30_VP_INST_COND_SWZ_X_SHIFT 9 +#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9) +#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7 +#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7) +#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5 +#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5) +#define NV30_VP_INST_COND_SWZ_W_SHIFT 3 +#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3) +#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3 +#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3) +#define NV30_VP_INST_ADDR_SWZ_SHIFT 1 +#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1) +#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0 +#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0) + +/* DWORD 1 */ +#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28 +#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28) +# define NV30_VP_INST_OP_NOP 0x00 +# define NV30_VP_INST_OP_RCP 0x02 +# define NV30_VP_INST_OP_RCC 0x03 +# define NV30_VP_INST_OP_RSQ 0x04 +# define NV30_VP_INST_OP_EXP 0x05 +# define NV30_VP_INST_OP_LOG 0x06 +# define NV30_VP_INST_OP_LIT 0x07 +# define NV30_VP_INST_OP_BRA 0x09 +# define NV30_VP_INST_OP_CAL 0x0B +# define NV30_VP_INST_OP_RET 0x0C +# define NV30_VP_INST_OP_LG2 0x0D +# define NV30_VP_INST_OP_EX2 0x0E +# define NV30_VP_INST_OP_SIN 0x0F +# define NV30_VP_INST_OP_COS 0x10 +#define NV30_VP_INST_VEC_OPCODE_SHIFT 23 +#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23) +# define NV30_VP_INST_OP_NOPV 0x00 +# define NV30_VP_INST_OP_MOV 0x01 +# define NV30_VP_INST_OP_MUL 0x02 +# define NV30_VP_INST_OP_ADD 0x03 +# define NV30_VP_INST_OP_MAD 0x04 +# define NV30_VP_INST_OP_DP3 0x05 +# define NV30_VP_INST_OP_DP4 0x07 +# define NV30_VP_INST_OP_DPH 0x06 +# define NV30_VP_INST_OP_DST 0x08 +# define NV30_VP_INST_OP_MIN 0x09 +# define NV30_VP_INST_OP_MAX 0x0A +# define NV30_VP_INST_OP_SLT 0x0B +# define NV30_VP_INST_OP_SGE 0x0C +# define NV30_VP_INST_OP_ARL 0x0D +# define NV30_VP_INST_OP_FRC 0x0E +# define NV30_VP_INST_OP_FLR 0x0F +# define NV30_VP_INST_OP_SEQ 0x10 +# define NV30_VP_INST_OP_SFL 0x11 +# define NV30_VP_INST_OP_SGT 0x12 +# define NV30_VP_INST_OP_SLE 0x13 +# define NV30_VP_INST_OP_SNE 0x14 +# define NV30_VP_INST_OP_STR 0x15 +# define NV30_VP_INST_OP_SSG 0x16 +# define NV30_VP_INST_OP_ARR 0x17 +# define NV30_VP_INST_OP_ARA 0x18 +#define NV30_VP_INST_CONST_SRC_SHIFT 14 +#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14) +#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/ +#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/ +# define NV30_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */ +# define NV30_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */ +# define NV30_VP_INST_IN_NORMAL 2 +# define NV30_VP_INST_IN_COL0 3 /* Should probably confirm them all though */ +# define NV30_VP_INST_IN_COL1 4 +# define NV30_VP_INST_IN_FOGC 5 +# define NV30_VP_INST_IN_TC0 8 +# define NV30_VP_INST_IN_TC(n) (8+n) +#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/ +#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/ + +/* DWORD 2 */ +#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/ +#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /*NV20*/ +#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/ +#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/ +#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/ +#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /*NV20*/ +#define NV30_VP_INST_IADDR_SHIFT 2 +#define NV30_VP_INST_IADDR_MASK (0xFF << 2) /* guess */ + +/* DWORD 3 */ +#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/ +#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/ +#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24 +#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24) +#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20 +#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20) +#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16 +#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16) +#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/ +#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/ +#define NV30_VP_INST_DEST_ID_SHIFT 2 +#define NV30_VP_INST_DEST_ID_MASK (0x0F << 2) +# define NV30_VP_INST_DEST_POS 0 +# define NV30_VP_INST_DEST_COL0 3 +# define NV30_VP_INST_DEST_COL1 4 +# define NV30_VP_INST_DEST_TC(n) (8+n) + +/* Source-register definition - matches NV20 exactly */ +#define NV30_VP_SRC_REG_NEGATE (1<<14) +#define NV30_VP_SRC_REG_SWZ_X_SHIFT 12 +#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12) +#define NV30_VP_SRC_REG_SWZ_Y_SHIFT 10 +#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10) +#define NV30_VP_SRC_REG_SWZ_Z_SHIFT 8 +#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8) +#define NV30_VP_SRC_REG_SWZ_W_SHIFT 6 +#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6) +#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6 +#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6) +#define NV30_VP_SRC_REG_TEMP_ID_SHIFT 2 +#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0) +#define NV30_VP_SRC_REG_TYPE_SHIFT 0 +#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0) +#define NV30_VP_SRC_REG_TYPE_TEMP 1 +#define NV30_VP_SRC_REG_TYPE_INPUT 2 +#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */ + +/* + * Each fragment program opcode appears to be comprised of 4 32-bit values. + * + * 0 - Opcode, output reg/mask, ATTRIB source + * 1 - Source 0 + * 2 - Source 1 + * 3 - Source 2 + * + * There appears to be no special difference between result regs and temp regs. + * result.color == R0.xyzw + * result.depth == R1.z + * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0 + * otherwise it is set to 1. + * + * Constants are inserted directly after the instruction that uses them. + * + * It appears that it's not possible to use two input registers in one + * instruction as the input sourcing is done in the instruction dword + * and not the source selection dwords. As such instructions such as: + * + * ADD result.color, fragment.color, fragment.texcoord[0]; + * + * must be split into two MOV's and then an ADD (nvidia does this) but + * I'm not sure why it's not just one MOV and then source the second input + * in the ADD instruction.. + * + * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary + * negation requires multiplication with a const. + * + * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE + * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO + * is implemented simply by not writing to the relevant components of the destination. + * + * Conditional execution + * TODO + * + * Non-native instructions: + * LIT + * LRP - MAD+MAD + * SUB - ADD, negate second source + * RSQ - LG2 + EX2 + * POW - LG2 + MUL + EX2 + * SCS - COS + SIN + * XPD + */ + +//== Opcode / Destination selection == +#define NV30_FP_OP_PROGRAM_END (1 << 0) +#define NV30_FP_OP_OUT_REG_SHIFT 1 +#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */ +/* Needs to be set when writing outputs to get expected result.. */ +#define NV30_FP_OP_UNK0_7 (1 << 7) +#define NV30_FP_OP_COND_WRITE_ENABLE (1 << 8) +#define NV30_FP_OP_OUTMASK_SHIFT 9 +#define NV30_FP_OP_OUTMASK_MASK (0xF << 9) +# define NV30_FP_OP_OUT_X (1<<9) +# define NV30_FP_OP_OUT_Y (1<<10) +# define NV30_FP_OP_OUT_Z (1<<11) +# define NV30_FP_OP_OUT_W (1<<12) +/* Uncertain about these, especially the input_src values.. it's possible that + * they can be dynamically changed. + */ +#define NV30_FP_OP_INPUT_SRC_SHIFT 13 +#define NV30_FP_OP_INPUT_SRC_MASK (15 << 13) +# define NV30_FP_OP_INPUT_SRC_POSITION 0x0 +# define NV30_FP_OP_INPUT_SRC_COL0 0x1 +# define NV30_FP_OP_INPUT_SRC_COL1 0x2 +# define NV30_FP_OP_INPUT_SRC_FOGC 0x3 +# define NV30_FP_OP_INPUT_SRC_TC0 0x4 +# define NV30_FP_OP_INPUT_SRC_TC(n) (0x4 + n) +#define NV30_FP_OP_TEX_UNIT_SHIFT 17 +#define NV30_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */ +#define NV30_FP_OP_PRECISION_SHIFT 22 +#define NV30_FP_OP_PRECISION_MASK (3 << 22) +# define NV30_FP_PRECISION_FP32 0 +# define NV30_FP_PRECISION_FP16 1 +# define NV30_FP_PRECISION_FX12 2 +#define NV30_FP_OP_OPCODE_SHIFT 24 +#define NV30_FP_OP_OPCODE_MASK (0x3F << 24) +# define NV30_FP_OP_OPCODE_NOP 0x00 +# define NV30_FP_OP_OPCODE_MOV 0x01 +# define NV30_FP_OP_OPCODE_MUL 0x02 +# define NV30_FP_OP_OPCODE_ADD 0x03 +# define NV30_FP_OP_OPCODE_MAD 0x04 +# define NV30_FP_OP_OPCODE_DP3 0x05 +# define NV30_FP_OP_OPCODE_DP4 0x06 +# define NV30_FP_OP_OPCODE_DST 0x07 +# define NV30_FP_OP_OPCODE_MIN 0x08 +# define NV30_FP_OP_OPCODE_MAX 0x09 +# define NV30_FP_OP_OPCODE_SLT 0x0A +# define NV30_FP_OP_OPCODE_SGE 0x0B +# define NV30_FP_OP_OPCODE_SLE 0x0C +# define NV30_FP_OP_OPCODE_SGT 0x0D +# define NV30_FP_OP_OPCODE_SNE 0x0E +# define NV30_FP_OP_OPCODE_SEQ 0x0F +# define NV30_FP_OP_OPCODE_FRC 0x10 +# define NV30_FP_OP_OPCODE_FLR 0x11 +# define NV30_FP_OP_OPCODE_KIL 0x12 +# define NV30_FP_OP_OPCODE_PK4B 0x13 +# define NV30_FP_OP_OPCODE_UP4B 0x14 +# define NV30_FP_OP_OPCODE_DDX 0x15 /* can only write XY */ +# define NV30_FP_OP_OPCODE_DDY 0x16 /* can only write XY */ +# define NV30_FP_OP_OPCODE_TEX 0x17 +# define NV30_FP_OP_OPCODE_TXP 0x18 +# define NV30_FP_OP_OPCODE_TXD 0x19 +# define NV30_FP_OP_OPCODE_RCP 0x1A +# define NV30_FP_OP_OPCODE_RSQ 0x1B +# define NV30_FP_OP_OPCODE_EX2 0x1C +# define NV30_FP_OP_OPCODE_LG2 0x1D +# define NV30_FP_OP_OPCODE_LIT 0x1E +# define NV30_FP_OP_OPCODE_LRP 0x1F +# define NV30_FP_OP_OPCODE_COS 0x22 +# define NV30_FP_OP_OPCODE_SIN 0x23 +# define NV30_FP_OP_OPCODE_PK2H 0x24 +# define NV30_FP_OP_OPCODE_UP2H 0x25 +# define NV30_FP_OP_OPCODE_POW 0x26 +# define NV30_FP_OP_OPCODE_PK4UB 0x27 +# define NV30_FP_OP_OPCODE_UP4UB 0x28 +# define NV30_FP_OP_OPCODE_PK2US 0x29 +# define NV30_FP_OP_OPCODE_UP2US 0x2A +# define NV30_FP_OP_OPCODE_DP2A 0x2E +# define NV30_FP_OP_OPCODE_TXB 0x31 +# define NV30_FP_OP_OPCODE_RFL 0x36 +#define NV30_FP_OP_OUT_SAT (1 << 31) + +/* high order bits of SRC0 */ +#define NV30_FP_OP_OUT_ABS (1 << 29) +#define NV30_FP_OP_COND_SWZ_W_SHIFT 27 +#define NV30_FP_OP_COND_SWZ_W_MASK (3 << 27) +#define NV30_FP_OP_COND_SWZ_Z_SHIFT 25 +#define NV30_FP_OP_COND_SWZ_Z_MASK (3 << 25) +#define NV30_FP_OP_COND_SWZ_Y_SHIFT 23 +#define NV30_FP_OP_COND_SWZ_Y_MASK (3 << 23) +#define NV30_FP_OP_COND_SWZ_X_SHIFT 21 +#define NV30_FP_OP_COND_SWZ_X_MASK (3 << 21) +#define NV30_FP_OP_COND_SWZ_ALL_SHIFT 21 +#define NV30_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21) +#define NV30_FP_OP_COND_SHIFT 18 +#define NV30_FP_OP_COND_MASK (0x07 << 18) +# define NV30_FP_OP_COND_FL 0 +# define NV30_FP_OP_COND_LT 1 +# define NV30_FP_OP_COND_EQ 2 +# define NV30_FP_OP_COND_LE 3 +# define NV30_FP_OP_COND_GT 4 +# define NV30_FP_OP_COND_NE 5 +# define NV30_FP_OP_COND_GE 6 +# define NV30_FP_OP_COND_TR 7 + +/* high order bits of SRC1 */ +#define NV30_FP_OP_SRC_SCALE_SHIFT 28 +#define NV30_FP_OP_SRC_SCALE_MASK (3 << 28) + +/* high order bits of SRC2 */ +#define NV30_FP_OP_INDEX_INPUT (1 << 30) + +//== Register selection == +#define NV30_FP_REG_ALL_MASK (0x1FFFF<<0) +#define NV30_FP_REG_TYPE_SHIFT 0 +#define NV30_FP_REG_TYPE_MASK (3 << 0) +# define NV30_FP_REG_TYPE_TEMP 0 +# define NV30_FP_REG_TYPE_INPUT 1 +# define NV30_FP_REG_TYPE_CONST 2 +#define NV30_FP_REG_SRC_SHIFT 2 /* uncertain */ +#define NV30_FP_REG_SRC_MASK (31 << 2) +#define NV30_FP_REG_UNK_0 (1 << 8) +#define NV30_FP_REG_SWZ_ALL_SHIFT 9 +#define NV30_FP_REG_SWZ_ALL_MASK (255 << 9) +#define NV30_FP_REG_SWZ_X_SHIFT 9 +#define NV30_FP_REG_SWZ_X_MASK (3 << 9) +#define NV30_FP_REG_SWZ_Y_SHIFT 11 +#define NV30_FP_REG_SWZ_Y_MASK (3 << 11) +#define NV30_FP_REG_SWZ_Z_SHIFT 13 +#define NV30_FP_REG_SWZ_Z_MASK (3 << 13) +#define NV30_FP_REG_SWZ_W_SHIFT 15 +#define NV30_FP_REG_SWZ_W_MASK (3 << 15) +# define NV30_FP_SWIZZLE_X 0 +# define NV30_FP_SWIZZLE_Y 1 +# define NV30_FP_SWIZZLE_Z 2 +# define NV30_FP_SWIZZLE_W 3 +#define NV30_FP_REG_NEGATE (1 << 17) + +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_state.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_state.c new file mode 100644 index 000000000..ad21fa273 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_state.c @@ -0,0 +1,980 @@ +/************************************************************************** + +Copyright 2006 Nouveau +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" +#include "nouveau_state.h" + +#include "tnl/t_pipeline.h" + +#include "mtypes.h" +#include "colormac.h" + +#define NOUVEAU_CARD_USING_SHADERS (nmesa->screen->card->type >= NV_40) + +static void nv30AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte ubRef; + CLAMPED_FLOAT_TO_UBYTE(ubRef, ref); + + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2); + OUT_RING_CACHE(func); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC */ + OUT_RING_CACHE(ubRef); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF */ +} + +static void nv30BlendColor(GLcontext *ctx, const GLfloat color[4]) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte cf[4]; + + CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]); + + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_COLOR, 1); + OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0])); +} + +static void nv30BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1); + OUT_RING_CACHE((modeA<<16) | modeRGB); +} + + +static void nv30BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2); + OUT_RING_CACHE((sfactorA<<16) | sfactorRGB); + OUT_RING_CACHE((dfactorA<<16) | dfactorRGB); +} + +static void nv30Clear(GLcontext *ctx, GLbitfield mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLuint hw_bufs = 0; + + if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) + hw_bufs |= 0xf0; + if (mask & (BUFFER_BIT_DEPTH)) + hw_bufs |= 0x03; + + if (hw_bufs) { + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS, 1); + OUT_RING(hw_bufs); + } +} + +static void nv30ClearColor(GLcontext *ctx, const GLfloat color[4]) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte c[4]; + UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB, 1); + OUT_RING_CACHE(PACK_COLOR_8888(c[3],c[0],c[1],c[2])); +} + +static void nv30ClearDepth(GLcontext *ctx, GLclampd d) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nmesa->clear_value=((nmesa->clear_value&0x000000FF)|(((uint32_t)(d*0xFFFFFF))<<8)); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1); + OUT_RING_CACHE(nmesa->clear_value); +} + +/* we're don't support indexed buffers + void (*ClearIndex)(GLcontext *ctx, GLuint index) + */ + +static void nv30ClearStencil(GLcontext *ctx, GLint s) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nmesa->clear_value=((nmesa->clear_value&0xFFFFFF00)|(s&0x000000FF)); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1); + OUT_RING_CACHE(nmesa->clear_value); +} + +static void nv30ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (NOUVEAU_CARD_USING_SHADERS) + return; + + plane -= GL_CLIP_PLANE0; + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4); + OUT_RING_CACHEf(equation[0]); + OUT_RING_CACHEf(equation[1]); + OUT_RING_CACHEf(equation[2]); + OUT_RING_CACHEf(equation[3]); +} + +static void nv30ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask, + GLboolean bmask, GLboolean amask ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_MASK, 1); + OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0)); +} + +static void nv30ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode) +{ + // TODO I need love +} + +static void nv30CullFace(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE, 1); + OUT_RING_CACHE(mode); +} + +static void nv30FrontFace(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FRONT_FACE, 1); + OUT_RING_CACHE(mode); +} + +static void nv30DepthFunc(GLcontext *ctx, GLenum func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1); + OUT_RING_CACHE(func); +} + +static void nv30DepthMask(GLcontext *ctx, GLboolean flag) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1); + OUT_RING_CACHE(flag); +} + +static void nv30DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2); + OUT_RING_CACHEf(nearval); + OUT_RING_CACHEf(farval); +} + +/** Specify the current buffer for writing */ +//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer ); +/** Specify the buffers for writing for fragment programs*/ +//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers ); + +static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + switch(cap) + { + case GL_ALPHA_TEST: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_AUTO_NORMAL: + case GL_BLEND: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + if (NOUVEAU_CARD_USING_SHADERS) { + nouveauShader *nvs = (nouveauShader *)ctx->VertexProgram._Current; + if (nvs) + nvs->translated = GL_FALSE; + } else { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1); + OUT_RING_CACHE(state); + } + break; + case GL_COLOR_LOGIC_OP: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_COLOR_MATERIAL: +// case GL_COLOR_SUM_EXT: +// case GL_COLOR_TABLE: +// case GL_CONVOLUTION_1D: +// case GL_CONVOLUTION_2D: + case GL_CULL_FACE: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_DEPTH_TEST: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_DITHER: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_FOG: + if (NOUVEAU_CARD_USING_SHADERS) + break; + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_HISTOGRAM: +// case GL_INDEX_LOGIC_OP: + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + { + uint32_t mask=0x11<<(2*(cap-GL_LIGHT0)); + + if (NOUVEAU_CARD_USING_SHADERS) + break; + + nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state)); + if (nmesa->lighting_enabled) + { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1); + OUT_RING_CACHE(nmesa->enabled_lights); + } + break; + } + case GL_LIGHTING: + if (NOUVEAU_CARD_USING_SHADERS) + break; + + nmesa->lighting_enabled=state; + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1); + if (nmesa->lighting_enabled) + OUT_RING_CACHE(nmesa->enabled_lights); + else + OUT_RING_CACHE(0x0); + break; +// case GL_LINE_SMOOTH: +// case GL_LINE_STIPPLE: +// case GL_MAP1_COLOR_4: +// case GL_MAP1_INDEX: +// case GL_MAP1_NORMAL: +// case GL_MAP1_TEXTURE_COORD_1: +// case GL_MAP1_TEXTURE_COORD_2: +// case GL_MAP1_TEXTURE_COORD_3: +// case GL_MAP1_TEXTURE_COORD_4: +// case GL_MAP1_VERTEX_3: +// case GL_MAP1_VERTEX_4: +// case GL_MAP2_COLOR_4: +// case GL_MAP2_INDEX: +// case GL_MAP2_NORMAL: +// case GL_MAP2_TEXTURE_COORD_1: +// case GL_MAP2_TEXTURE_COORD_2: +// case GL_MAP2_TEXTURE_COORD_3: +// case GL_MAP2_TEXTURE_COORD_4: +// case GL_MAP2_VERTEX_3: +// case GL_MAP2_VERTEX_4: +// case GL_MINMAX: + case GL_NORMALIZE: + if (nmesa->screen->card->type != NV_44) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1); + OUT_RING_CACHE(state); + } + break; +// case GL_POINT_SMOOTH: + case GL_POLYGON_OFFSET_POINT: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_OFFSET_LINE: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_OFFSET_FILL: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_SMOOTH: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_STIPPLE: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_POST_COLOR_MATRIX_COLOR_TABLE: +// case GL_POST_CONVOLUTION_COLOR_TABLE: +// case GL_RESCALE_NORMAL: + case GL_SCISSOR_TEST: + /* No enable bit, nv30Scissor will adjust to max range */ + ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); + break; +// case GL_SEPARABLE_2D: + case GL_STENCIL_TEST: + // TODO BACK and FRONT ? + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1); + OUT_RING_CACHE(state); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_TEXTURE_GEN_Q: +// case GL_TEXTURE_GEN_R: +// case GL_TEXTURE_GEN_S: +// case GL_TEXTURE_GEN_T: +// case GL_TEXTURE_1D: +// case GL_TEXTURE_2D: +// case GL_TEXTURE_3D: + } +} + +static void nv30Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (NOUVEAU_CARD_USING_SHADERS) + return; + + switch(pname) + { + case GL_FOG_MODE: + { + int mode = 0; + /* The modes are different in GL and the card. */ + switch(ctx->Fog.Mode) + { + case GL_LINEAR: + mode = 0x804; + break; + case GL_EXP: + mode = 0x802; + break; + case GL_EXP2: + mode = 0x803; + break; + } + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_MODE, 1); + OUT_RING_CACHE (mode); + break; + } + case GL_FOG_COLOR: + { + GLubyte c[4]; + UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,params); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_COLOR, 1); + /* nvidia ignores the alpha channel */ + OUT_RING_CACHE(PACK_COLOR_8888_REV(c[0],c[1],c[2],c[3])); + break; + } + case GL_FOG_DENSITY: + case GL_FOG_START: + case GL_FOG_END: + { + GLfloat f=0., c=0.; + switch(ctx->Fog.Mode) + { + case GL_LINEAR: + f = -1.0/(ctx->Fog.End - ctx->Fog.Start); + c = ctx->Fog.Start/(ctx->Fog.End - ctx->Fog.Start) + 2.001953; + break; + case GL_EXP: + f = -0.090168*ctx->Fog.Density; + c = 1.5; + case GL_EXP2: + f = -0.212330*ctx->Fog.Density; + c = 1.5; + } + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR, 1); + OUT_RING_CACHE(f); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT, 1); + OUT_RING_CACHE(c); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC, 1); + OUT_RING_CACHE(0); /* Is this always the same? */ + break; + } +// case GL_FOG_COORD_SRC: + default: + break; + } +} + +static void nv30Hint(GLcontext *ctx, GLenum target, GLenum mode) +{ + // TODO I need love (fog and line_smooth hints) +} + +// void (*IndexMask)(GLcontext *ctx, GLuint mask); + +enum { + SPOTLIGHT_NO_UPDATE, + SPOTLIGHT_UPDATE_EXPONENT, + SPOTLIGHT_UPDATE_DIRECTION, + SPOTLIGHT_UPDATE_ALL +}; + +static void nv30Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLint p = light - GL_LIGHT0; + struct gl_light *l = &ctx->Light.Light[p]; + int spotlight_update = SPOTLIGHT_NO_UPDATE; + + if (NOUVEAU_CARD_USING_SHADERS) + return; + + /* not sure where the fourth param value goes...*/ + switch(pname) + { + case GL_AMBIENT: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_DIFFUSE: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_SPECULAR: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_POSITION: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3); + OUT_RING_CACHEf(params[0]); + OUT_RING_CACHEf(params[1]); + OUT_RING_CACHEf(params[2]); + break; + case GL_SPOT_DIRECTION: + spotlight_update = SPOTLIGHT_UPDATE_DIRECTION; + break; + case GL_SPOT_EXPONENT: + spotlight_update = SPOTLIGHT_UPDATE_EXPONENT; + break; + case GL_SPOT_CUTOFF: + spotlight_update = SPOTLIGHT_UPDATE_ALL; + break; + case GL_CONSTANT_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + case GL_LINEAR_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + case GL_QUADRATIC_ATTENUATION: + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1); + OUT_RING_CACHEf(*params); + break; + default: + break; + } + + switch(spotlight_update) { + case SPOTLIGHT_UPDATE_DIRECTION: + { + GLfloat x,y,z; + GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0); + x = spot_light_coef_a * l->_NormDirection[0]; + y = spot_light_coef_a * l->_NormDirection[1]; + z = spot_light_coef_a * l->_NormDirection[2]; + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3); + OUT_RING_CACHEf(x); + OUT_RING_CACHEf(y); + OUT_RING_CACHEf(z); + } + break; + case SPOTLIGHT_UPDATE_EXPONENT: + { + GLfloat cc,lc,qc; + cc = 1.0; /* FIXME: These need to be correctly computed */ + lc = 0.0; + qc = 2.0; + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3); + OUT_RING_CACHEf(cc); + OUT_RING_CACHEf(lc); + OUT_RING_CACHEf(qc); + } + break; + case SPOTLIGHT_UPDATE_ALL: + { + GLfloat cc,lc,qc, x,y,z, c; + GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0); + cc = 1.0; /* FIXME: These need to be correctly computed */ + lc = 0.0; + qc = 2.0; + x = spot_light_coef_a * l->_NormDirection[0]; + y = spot_light_coef_a * l->_NormDirection[1]; + z = spot_light_coef_a * l->_NormDirection[2]; + c = spot_light_coef_a + 1.0; + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7); + OUT_RING_CACHEf(cc); + OUT_RING_CACHEf(lc); + OUT_RING_CACHEf(qc); + OUT_RING_CACHEf(x); + OUT_RING_CACHEf(y); + OUT_RING_CACHEf(z); + OUT_RING_CACHEf(c); + } + break; + default: + break; + } +} + +/** Set the lighting model parameters */ +void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params); + + +static void nv30LineStipple(GLcontext *ctx, GLint factor, GLushort pattern ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1); + OUT_RING_CACHE((pattern << 16) | factor); +} + +static void nv30LineWidth(GLcontext *ctx, GLfloat width) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte ubWidth; + + ubWidth = (GLubyte)(width * 8.0) & 0xFF; + + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LINE_WIDTH_SMOOTH, 1); + OUT_RING_CACHE(ubWidth); +} + +static void nv30LogicOpcode(GLcontext *ctx, GLenum opcode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1); + OUT_RING_CACHE(opcode); +} + +static void nv30PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + /*TODO: not sure what goes here. */ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + +} + +/** Specify the diameter of rasterized points */ +static void nv30PointSize(GLcontext *ctx, GLfloat size) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POINT_SIZE, 1); + OUT_RING_CACHEf(size); +} + +/** Select a polygon rasterization mode */ +static void nv30PolygonMode(GLcontext *ctx, GLenum face, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1); + OUT_RING_CACHE(mode); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1); + OUT_RING_CACHE(mode); + } +} + +/** Set the scale and units used to calculate depth values */ +static void nv30PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2); + OUT_RING_CACHEf(factor); + + /* Looks like we always multiply units by 2.0... according to the dumps.*/ + OUT_RING_CACHEf(units * 2.0); +} + +/** Set the polygon stippling pattern */ +static void nv30PolygonStipple(GLcontext *ctx, const GLubyte *mask ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 32); + OUT_RING_CACHEp(mask, 32); +} + +/* Specifies the current buffer for reading */ +void (*ReadBuffer)( GLcontext *ctx, GLenum buffer ); +/** Set rasterization mode */ +void (*RenderMode)(GLcontext *ctx, GLenum mode ); + +/** Define the scissor box */ +static void nv30Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + /* There's no scissor enable bit, so adjust the scissor to cover the + * maximum draw buffer bounds + */ + if (!ctx->Scissor.Enabled) { + x = y = 0; + w = h = 4095; + } else { + x += nmesa->drawX; + y += nmesa->drawY; + } + + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2); + OUT_RING_CACHE(((w) << 16) | x); + OUT_RING_CACHE(((h) << 16) | y); +} + +/** Select flat or smooth shading */ +static void nv30ShadeModel(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SHADE_MODEL, 1); + OUT_RING_CACHE(mode); +} + +/** OpenGL 2.0 two-sided StencilFunc */ +static void nv30StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, + GLint ref, GLuint mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC, 3); + OUT_RING_CACHE(func); + OUT_RING_CACHE(ref); + OUT_RING_CACHE(mask); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC, 3); + OUT_RING_CACHE(func); + OUT_RING_CACHE(ref); + OUT_RING_CACHE(mask); + } +} + +/** OpenGL 2.0 two-sided StencilMask */ +static void nv30StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK, 1); + OUT_RING_CACHE(mask); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK, 1); + OUT_RING_CACHE(mask); + } +} + +/** OpenGL 2.0 two-sided StencilOp */ +static void nv30StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, + GLenum zfail, GLenum zpass) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL, 3); + OUT_RING_CACHE(fail); + OUT_RING_CACHE(zfail); + OUT_RING_CACHE(zpass); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL, 3); + OUT_RING_CACHE(fail); + OUT_RING_CACHE(zfail); + OUT_RING_CACHE(zpass); + } +} + +/** Control the generation of texture coordinates */ +void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname, + const GLfloat *params); +/** Set texture environment parameters */ +void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *param); +/** Set texture parameters */ +void (*TexParameter)(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params); + +static void nv30TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (!NOUVEAU_CARD_USING_SHADERS) { + BEGIN_RING_CACHE(NvSub3D, + NV30_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16); + /*XXX: This SHOULD work.*/ + OUT_RING_CACHEp(mat->m, 16); + } +} + +static void nv30WindowMoved(nouveauContextPtr nmesa) +{ + GLcontext *ctx = nmesa->glCtx; + GLfloat *v = nmesa->viewport.m; + GLuint w = ctx->Viewport.Width; + GLuint h = ctx->Viewport.Height; + GLuint x = ctx->Viewport.X + nmesa->drawX; + GLuint y = ctx->Viewport.Y + nmesa->drawY; + + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2); + OUT_RING_CACHE((w << 16) | x); + OUT_RING_CACHE((h << 16) | y); + /* something to do with clears, possibly doesn't belong here */ + BEGIN_RING_CACHE(NvSub3D, + NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2); + OUT_RING_CACHE(((w+x) << 16) | x); + OUT_RING_CACHE(((h+y) << 16) | y); + /* viewport transform */ + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8); + OUT_RING_CACHEf (v[MAT_TX]); + OUT_RING_CACHEf (v[MAT_TY]); + OUT_RING_CACHEf (v[MAT_TZ]); + OUT_RING_CACHEf (0.0); + OUT_RING_CACHEf (v[MAT_SX]); + OUT_RING_CACHEf (v[MAT_SY]); + OUT_RING_CACHEf (v[MAT_SZ]); + OUT_RING_CACHEf (0.0); + + ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); +} + +static GLboolean nv30InitCard(nouveauContextPtr nmesa) +{ + int i; + nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D); + + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 3); + OUT_RING(NvDmaFB); + OUT_RING(NvDmaAGP); + OUT_RING(NvDmaFB); + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1); + OUT_RING(NvDmaFB); + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2); + OUT_RING(NvDmaFB); + OUT_RING(NvDmaFB); + BEGIN_RING_SIZE(NvSub3D, 0x1b0, 1); /* SET_OBJECT8B*/ + OUT_RING(NvDmaFB); + + for(i = 0x2c8; i <= 0x2fc; i += 4) + { + BEGIN_RING_SIZE(NvSub3D, i, 1); + OUT_RING(0x0); + } + + BEGIN_RING_SIZE(NvSub3D, 0x0220, 1); + OUT_RING(1); + + BEGIN_RING_SIZE(NvSub3D, 0x03b0, 1); + OUT_RING(0x00100000); + BEGIN_RING_SIZE(NvSub3D, 0x1454, 1); + OUT_RING(0); + BEGIN_RING_SIZE(NvSub3D, 0x1d80, 1); + OUT_RING(3); + + /* NEW */ + BEGIN_RING_SIZE(NvSub3D, 0x1e98, 1); + OUT_RING(0); + BEGIN_RING_SIZE(NvSub3D, 0x17e0, 3); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0x3f800000); + BEGIN_RING_SIZE(NvSub3D, 0x1f80, 16); + OUT_RING(0); OUT_RING(0); OUT_RING(0); OUT_RING(0); + OUT_RING(0); OUT_RING(0); OUT_RING(0); OUT_RING(0); + OUT_RING(0x0000ffff); + OUT_RING(0); OUT_RING(0); OUT_RING(0); OUT_RING(0); + OUT_RING(0); OUT_RING(0); OUT_RING(0); +/* + BEGIN_RING_SIZE(NvSub3D, 0x100, 2); + OUT_RING(0); + OUT_RING(0); +*/ + BEGIN_RING_SIZE(NvSub3D, 0x120, 3); + OUT_RING(0); + OUT_RING(1); + OUT_RING(2); + + BEGIN_RING_SIZE(NvSub3D, 0x1d88, 1); + OUT_RING(0x00001200); + + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_RC_ENABLE, 1); + OUT_RING (0); + + return GL_TRUE; +} + +static GLboolean nv40InitCard(nouveauContextPtr nmesa) +{ + nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D); + + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 2); + OUT_RING(NvDmaFB); + OUT_RING(NvDmaFB); + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1); + OUT_RING(NvDmaFB); + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2); + OUT_RING(NvDmaFB); + OUT_RING(NvDmaFB); + BEGIN_RING_SIZE(NvSub3D, 0x0220, 1); + OUT_RING(1); + + BEGIN_RING_SIZE(NvSub3D, 0x1ea4, 3); + OUT_RING(0x00000010); + OUT_RING(0x01000100); + OUT_RING(0xff800006); + BEGIN_RING_SIZE(NvSub3D, 0x1fc4, 1); + OUT_RING(0x06144321); + BEGIN_RING_SIZE(NvSub3D, 0x1fc8, 2); + OUT_RING(0xedcba987); + OUT_RING(0x00000021); + BEGIN_RING_SIZE(NvSub3D, 0x1fd0, 1); + OUT_RING(0x00171615); + BEGIN_RING_SIZE(NvSub3D, 0x1fd4, 1); + OUT_RING(0x001b1a19); + + BEGIN_RING_SIZE(NvSub3D, 0x1ef8, 1); + OUT_RING(0x0020ffff); + BEGIN_RING_SIZE(NvSub3D, 0x1d64, 1); + OUT_RING(0x00d30000); + BEGIN_RING_SIZE(NvSub3D, 0x1e94, 1); + OUT_RING(0x00000001); + + return GL_TRUE; +} + +static GLboolean nv30BindBuffers(nouveauContextPtr nmesa, int num_color, + nouveau_renderbuffer **color, + nouveau_renderbuffer *depth) +{ + GLuint x, y, w, h; + + w = color[0]->mesa.Width; + h = color[0]->mesa.Height; + x = nmesa->drawX; + y = nmesa->drawY; + + if (num_color != 1) + return GL_FALSE; + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 5); + OUT_RING (((w+x)<<16)|x); + OUT_RING (((h+y)<<16)|y); + if (color[0]->mesa._ActualFormat == GL_RGBA8) + OUT_RING (0x148); + else + OUT_RING (0x143); + if (nmesa->screen->card->type >= NV_40) + OUT_RING (color[0]->pitch); + else + OUT_RING (color[0]->pitch | (depth ? (depth->pitch << 16): 0)); + OUT_RING (color[0]->offset); + + if (depth) { + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_OFFSET, 1); + OUT_RING (depth->offset); + if (nmesa->screen->card->type >= NV_40) { + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH, 1); + OUT_RING (depth->pitch); + } + } + + return GL_TRUE; +} + +void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + func->AlphaFunc = nv30AlphaFunc; + func->BlendColor = nv30BlendColor; + func->BlendEquationSeparate = nv30BlendEquationSeparate; + func->BlendFuncSeparate = nv30BlendFuncSeparate; + func->Clear = nv30Clear; + func->ClearColor = nv30ClearColor; + func->ClearDepth = nv30ClearDepth; + func->ClearStencil = nv30ClearStencil; + func->ClipPlane = nv30ClipPlane; + func->ColorMask = nv30ColorMask; + func->ColorMaterial = nv30ColorMaterial; + func->CullFace = nv30CullFace; + func->FrontFace = nv30FrontFace; + func->DepthFunc = nv30DepthFunc; + func->DepthMask = nv30DepthMask; + func->DepthRange = nv30DepthRange; + func->Enable = nv30Enable; + func->Fogfv = nv30Fogfv; + func->Hint = nv30Hint; + func->Lightfv = nv30Lightfv; +/* func->LightModelfv = nv30LightModelfv; */ + func->LineStipple = nv30LineStipple; + func->LineWidth = nv30LineWidth; + func->LogicOpcode = nv30LogicOpcode; + func->PointParameterfv = nv30PointParameterfv; + func->PointSize = nv30PointSize; + func->PolygonMode = nv30PolygonMode; + func->PolygonOffset = nv30PolygonOffset; + func->PolygonStipple = nv30PolygonStipple; +#if 0 + func->ReadBuffer = nv30ReadBuffer; + func->RenderMode = nv30RenderMode; +#endif + func->Scissor = nv30Scissor; + func->ShadeModel = nv30ShadeModel; + func->StencilFuncSeparate = nv30StencilFuncSeparate; + func->StencilMaskSeparate = nv30StencilMaskSeparate; + func->StencilOpSeparate = nv30StencilOpSeparate; +#if 0 + func->TexGen = nv30TexGen; + func->TexParameter = nv30TexParameter; +#endif + func->TextureMatrix = nv30TextureMatrix; + + + if (nmesa->screen->card->type >= NV_40) + nmesa->hw_func.InitCard = nv40InitCard; + else + nmesa->hw_func.InitCard = nv30InitCard; + nmesa->hw_func.BindBuffers = nv30BindBuffers; + nmesa->hw_func.WindowMoved = nv30WindowMoved; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_vertprog.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_vertprog.c new file mode 100644 index 000000000..d023e8439 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv30_vertprog.c @@ -0,0 +1,367 @@ +#include "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" + +#include "nouveau_shader.h" +#include "nv30_shader.h" + +/***************************************************************************** + * Support routines + */ +static void +NV30VPUploadToHW(GLcontext *ctx, nouveauShader *nvs) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + int i; + + /* We can do better here and keep more than one VP on the hardware, and + * switch between them with PROGRAM_START_ID.. + */ + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID, 1); + OUT_RING(0); + for (i=0; i<nvs->program_size; i+=4) { + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, 4); + OUT_RING(nvs->program[i + 0]); + OUT_RING(nvs->program[i + 1]); + OUT_RING(nvs->program[i + 2]); + OUT_RING(nvs->program[i + 3]); + } + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID, 1); + OUT_RING(0); + + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_IN_REG, 2); + OUT_RING(nvs->card_priv.NV30VP.vp_in_reg); + OUT_RING(nvs->card_priv.NV30VP.vp_out_reg); + + BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_CLIPPING_PLANES, 1); + OUT_RING_CACHE (nvs->card_priv.NV30VP.clip_enables); +} + +static void +NV30VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLfloat *val; + + val = nvs->params[id].source_val ? + nvs->params[id].source_val : nvs->params[id].val; + + BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID, 5); + OUT_RING (id); + OUT_RINGp(val, 4); +} + +/***************************************************************************** + * Assembly routines + */ +static void +NV30VPSetBranchTarget(nvsFunc *shader, int addr) +{ + shader->inst[2] &= ~NV30_VP_INST_IADDR_MASK; + shader->inst[2] |= (addr << NV30_VP_INST_IADDR_SHIFT); +} + +/***************************************************************************** + * Disassembly routines + */ +static unsigned int +NV30VPGetOpcodeHW(nvsFunc * shader, int slot) +{ + int op; + + if (slot) { + op = (shader->inst[1] & NV30_VP_INST_SCA_OPCODEL_MASK) + >> NV30_VP_INST_SCA_OPCODEL_SHIFT; + op |= ((shader->inst[0] & NV30_VP_INST_SCA_OPCODEH_MASK) + >> NV30_VP_INST_SCA_OPCODEH_SHIFT) << 4; + } + else { + op = (shader->inst[1] & NV30_VP_INST_VEC_OPCODE_MASK) + >> NV30_VP_INST_VEC_OPCODE_SHIFT; + } + + return op; +} + +static nvsRegFile +NV30VPGetDestFile(nvsFunc * shader, int merged) +{ + switch (shader->GetOpcode(shader, merged)) { + case NVS_OP_ARL: + case NVS_OP_ARR: + case NVS_OP_ARA: + return NVS_FILE_ADDRESS; + default: + /*FIXME: This probably isn't correct.. */ + if ((shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK) != 0) + return NVS_FILE_RESULT; + if ((shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK) != 0) + return NVS_FILE_RESULT; + return NVS_FILE_TEMP; + } +} + +static unsigned int +NV30VPGetDestID(nvsFunc * shader, int merged) +{ + int id; + + switch (shader->GetDestFile(shader, merged)) { + case NVS_FILE_RESULT: + id = ((shader->inst[3] & NV30_VP_INST_DEST_ID_MASK) + >> NV30_VP_INST_DEST_ID_SHIFT); + switch (id) { + case NV30_VP_INST_DEST_POS : return NVS_FR_POSITION; + case NV30_VP_INST_DEST_COL0 : return NVS_FR_COL0; + case NV30_VP_INST_DEST_COL1 : return NVS_FR_COL1; + case NV30_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0; + case NV30_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1; + case NV30_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2; + case NV30_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3; + case NV30_VP_INST_DEST_TC(4): return NVS_FR_TEXCOORD4; + case NV30_VP_INST_DEST_TC(5): return NVS_FR_TEXCOORD5; + case NV30_VP_INST_DEST_TC(6): return NVS_FR_TEXCOORD6; + case NV30_VP_INST_DEST_TC(7): return NVS_FR_TEXCOORD7; + default: + return -1; + } + case NVS_FILE_ADDRESS: + case NVS_FILE_TEMP: + return (shader->inst[0] & NV30_VP_INST_DEST_TEMP_ID_MASK) + >> NV30_VP_INST_DEST_TEMP_ID_SHIFT; + default: + return -1; + } +} + +static unsigned int +NV30VPGetDestMask(nvsFunc * shader, int merged) +{ + int hwmask, mask = 0; + + if (shader->GetDestFile(shader, merged) == NVS_FILE_RESULT) + if (shader->GetOpcodeSlot(shader, merged)) + hwmask = (shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK) + >> NV30_VP_INST_SDEST_WRITEMASK_SHIFT; + else + hwmask = (shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK) + >> NV30_VP_INST_VDEST_WRITEMASK_SHIFT; + else if (shader->GetOpcodeSlot(shader, merged)) + hwmask = (shader->inst[3] & NV30_VP_INST_STEMP_WRITEMASK_MASK) + >> NV30_VP_INST_STEMP_WRITEMASK_SHIFT; + else + hwmask = (shader->inst[3] & NV30_VP_INST_VTEMP_WRITEMASK_MASK) + >> NV30_VP_INST_VTEMP_WRITEMASK_SHIFT; + + if (hwmask & (1 << 3)) mask |= SMASK_X; + if (hwmask & (1 << 2)) mask |= SMASK_Y; + if (hwmask & (1 << 1)) mask |= SMASK_Z; + if (hwmask & (1 << 0)) mask |= SMASK_W; + + return mask; +} + +static int +NV30VPGetSourceID(nvsFunc * shader, int merged, int pos) +{ + unsigned int src; + + switch (shader->GetSourceFile(shader, merged, pos)) { + case NVS_FILE_TEMP: + src = shader->GetSourceHW(shader, merged, pos); + return ((src & NV30_VP_SRC_REG_TEMP_ID_MASK) >> + NV30_VP_SRC_REG_TEMP_ID_SHIFT); + case NVS_FILE_CONST: + return ((shader->inst[1] & NV30_VP_INST_CONST_SRC_MASK) + >> NV30_VP_INST_CONST_SRC_SHIFT); + case NVS_FILE_ATTRIB: + src = ((shader->inst[1] & NV30_VP_INST_INPUT_SRC_MASK) + >> NV30_VP_INST_INPUT_SRC_SHIFT); + switch (src) { + case NV30_VP_INST_IN_POS : return NVS_FR_POSITION; + case NV30_VP_INST_IN_COL0 : return NVS_FR_COL0; + case NV30_VP_INST_IN_COL1 : return NVS_FR_COL1; + case NV30_VP_INST_IN_TC(0): return NVS_FR_TEXCOORD0; + case NV30_VP_INST_IN_TC(1): return NVS_FR_TEXCOORD1; + case NV30_VP_INST_IN_TC(2): return NVS_FR_TEXCOORD2; + case NV30_VP_INST_IN_TC(3): return NVS_FR_TEXCOORD3; + case NV30_VP_INST_IN_TC(4): return NVS_FR_TEXCOORD4; + case NV30_VP_INST_IN_TC(5): return NVS_FR_TEXCOORD5; + case NV30_VP_INST_IN_TC(6): return NVS_FR_TEXCOORD6; + case NV30_VP_INST_IN_TC(7): return NVS_FR_TEXCOORD7; + default: + return NVS_FR_UNKNOWN; + } + default: + return -1; + } +} + +static int +NV30VPGetSourceAbs(nvsFunc * shader, int merged, int pos) +{ + struct _op_xlat *opr; + static unsigned int abspos[3] = { + NV30_VP_INST_SRC0_ABS, + NV30_VP_INST_SRC1_ABS, + NV30_VP_INST_SRC2_ABS, + }; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr || opr->srcpos[pos] == -1 || opr->srcpos[pos] > 2) + return 0; + + return ((shader->inst[0] & abspos[opr->srcpos[pos]]) ? 1 : 0); +} + +static int +NV30VPGetRelAddressRegID(nvsFunc * shader) +{ + return ((shader->inst[0] & NV30_VP_INST_ADDR_REG_SELECT_1) ? 1 : 0); +} + +static nvsSwzComp +NV30VPGetRelAddressSwizzle(nvsFunc * shader) +{ + nvsSwzComp swz; + + swz = NV20VP_TX_SWIZZLE[(shader->inst[0] & NV30_VP_INST_ADDR_SWZ_MASK) + >> NV30_VP_INST_ADDR_SWZ_SHIFT]; + return swz; +} + +static int +NV30VPSupportsConditional(nvsFunc * shader) +{ + /*FIXME: Is this true of all ops? */ + return 1; +} + +static int +NV30VPGetConditionUpdate(nvsFunc * shader) +{ + return ((shader->inst[0] & NV30_VP_INST_COND_UPDATE_ENABLE) ? 1 : 0); +} + +static int +NV30VPGetConditionTest(nvsFunc * shader) +{ + int op; + + /* The condition test is unconditionally enabled on some + * instructions. ie: the condition test bit does *NOT* have + * to be set. + * + * FIXME: check other relevant ops for this situation. + */ + op = shader->GetOpcodeHW(shader, 1); + switch (op) { + case NV30_VP_INST_OP_BRA: + return 1; + default: + return ((shader->inst[0] & NV30_VP_INST_COND_TEST_ENABLE) ? 1 : 0); + } +} + +static nvsCond +NV30VPGetCondition(nvsFunc * shader) +{ + int cond; + + cond = ((shader->inst[0] & NV30_VP_INST_COND_MASK) + >> NV30_VP_INST_COND_SHIFT); + + switch (cond) { + case NV30_VP_INST_COND_FL: return NVS_COND_FL; + case NV30_VP_INST_COND_LT: return NVS_COND_LT; + case NV30_VP_INST_COND_EQ: return NVS_COND_EQ; + case NV30_VP_INST_COND_LE: return NVS_COND_LE; + case NV30_VP_INST_COND_GT: return NVS_COND_GT; + case NV30_VP_INST_COND_NE: return NVS_COND_NE; + case NV30_VP_INST_COND_GE: return NVS_COND_GE; + case NV30_VP_INST_COND_TR: return NVS_COND_TR; + default: + return NVS_COND_UNKNOWN; + } +} + +static void +NV30VPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz) +{ + int swzbits; + + swzbits = (shader->inst[0] & NV30_VP_INST_COND_SWZ_ALL_MASK) + >> NV30_VP_INST_COND_SWZ_ALL_SHIFT; + NV20VPTXSwizzle(swzbits, swz); +} + +static int +NV30VPGetCondRegID(nvsFunc * shader) +{ + return 0; +} + + +static int +NV30VPGetBranch(nvsFunc * shader) +{ + return ((shader->inst[2] & NV30_VP_INST_IADDR_MASK) + >> NV30_VP_INST_IADDR_SHIFT); +} + +void +NV30VPInitShaderFuncs(nvsFunc * shader) +{ + /* Inherit NV20 code, a lot of it is the same */ + NV20VPInitShaderFuncs(shader); + + /* Increase max valid opcode ID, and add new instructions */ + NVVP_TX_VOP_COUNT = NVVP_TX_NVS_OP_COUNT = 32; + + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FRC, NVS_OP_FRC, 0, -1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FLR, NVS_OP_FLR, 0, -1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SEQ, NVS_OP_SEQ, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SFL, NVS_OP_SFL, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SGT, NVS_OP_SGT, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SLE, NVS_OP_SLE, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SNE, NVS_OP_SNE, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_STR, NVS_OP_STR, 0, 1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SSG, NVS_OP_SSG, 0, -1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARR, NVS_OP_ARR, 0, -1, -1); + MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARA, NVS_OP_ARA, 3, -1, -1); + + MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_BRA, NVS_OP_BRA, -1, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_CAL, NVS_OP_CAL, -1, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_RET, NVS_OP_RET, -1, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_LG2, NVS_OP_LG2, 2, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_EX2, NVS_OP_EX2, 2, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_SIN, NVS_OP_SIN, 2, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_COS, NVS_OP_COS, 2, -1, -1); + + shader->UploadToHW = NV30VPUploadToHW; + shader->UpdateConst = NV30VPUpdateConst; + + shader->GetOpcodeHW = NV30VPGetOpcodeHW; + + shader->GetDestFile = NV30VPGetDestFile; + shader->GetDestID = NV30VPGetDestID; + shader->GetDestMask = NV30VPGetDestMask; + + shader->GetSourceID = NV30VPGetSourceID; + shader->GetSourceAbs = NV30VPGetSourceAbs; + + shader->GetRelAddressRegID = NV30VPGetRelAddressRegID; + shader->GetRelAddressSwizzle = NV30VPGetRelAddressSwizzle; + + shader->SupportsConditional = NV30VPSupportsConditional; + shader->GetConditionUpdate = NV30VPGetConditionUpdate; + shader->GetConditionTest = NV30VPGetConditionTest; + shader->GetCondition = NV30VPGetCondition; + shader->GetCondRegSwizzle = NV30VPGetCondRegSwizzle; + shader->GetCondRegID = NV30VPGetCondRegID; + + shader->GetBranch = NV30VPGetBranch; + shader->SetBranchTarget = NV30VPSetBranchTarget; +} + diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_fragprog.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_fragprog.c new file mode 100644 index 000000000..3e4ae0496 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_fragprog.c @@ -0,0 +1,224 @@ +#include "nouveau_shader.h" +#include "nv40_shader.h" + +/* branching ops */ +unsigned int NVFP_TX_BOP_COUNT = 5; +struct _op_xlat NVFP_TX_BOP[64]; + + +/***************************************************************************** + * Assembly routines + * - These extend the NV30 routines, which are almost identical. NV40 + * just has branching hacked into the instruction set. + */ +static int +NV40FPSupportsResultScale(nvsFunc *shader, nvsScale scale) +{ + switch (scale) { + case NVS_SCALE_1X: + case NVS_SCALE_2X: + case NVS_SCALE_4X: + case NVS_SCALE_8X: + case NVS_SCALE_INV_2X: + case NVS_SCALE_INV_4X: + case NVS_SCALE_INV_8X: + return 1; + default: + return 0; + } +} + +static void +NV40FPSetResultScale(nvsFunc *shader, nvsScale scale) +{ + shader->inst[2] &= ~NV40_FP_OP_DST_SCALE_MASK; + shader->inst[2] |= ((unsigned int)scale << NV40_FP_OP_DST_SCALE_SHIFT); +} + +static void +NV40FPSetBranchTarget(nvsFunc *shader, int addr) +{ + shader->inst[2] &= ~NV40_FP_OP_IADDR_MASK; + shader->inst[2] |= (addr << NV40_FP_OP_IADDR_SHIFT); +} + +static void +NV40FPSetBranchElse(nvsFunc *shader, int addr) +{ + shader->inst[2] &= ~NV40_FP_OP_ELSE_ID_MASK; + shader->inst[2] |= (addr << NV40_FP_OP_ELSE_ID_SHIFT); +} + +static void +NV40FPSetBranchEnd(nvsFunc *shader, int addr) +{ + shader->inst[3] &= ~NV40_FP_OP_END_ID_MASK; + shader->inst[3] |= (addr << NV40_FP_OP_END_ID_SHIFT); +} + +static void +NV40FPSetLoopParams(nvsFunc *shader, int count, int initial, int increment) +{ + shader->inst[2] &= ~(NV40_FP_OP_LOOP_COUNT_MASK | + NV40_FP_OP_LOOP_INDEX_MASK | + NV40_FP_OP_LOOP_INCR_MASK); + shader->inst[2] |= ((count << NV40_FP_OP_LOOP_COUNT_SHIFT) | + (initial << NV40_FP_OP_LOOP_INDEX_SHIFT) | + (increment << NV40_FP_OP_LOOP_INCR_SHIFT)); +} + +/***************************************************************************** + * Disassembly routines + */ +static struct _op_xlat * +NV40FPGetOPTXRec(nvsFunc * shader, int merged) +{ + struct _op_xlat *opr; + int op; + + op = shader->GetOpcodeHW(shader, 0); + if (shader->inst[2] & NV40_FP_OP_OPCODE_IS_BRANCH) { + opr = NVFP_TX_BOP; + op &= ~NV40_FP_OP_OPCODE_IS_BRANCH; + if (op > NVFP_TX_BOP_COUNT) + return NULL; + } + else { + opr = NVFP_TX_AOP; + if (op > NVFP_TX_AOP_COUNT) + return NULL; + } + + if (opr[op].SOP == NVS_OP_UNKNOWN) + return NULL; + return &opr[op]; +} + +static int +NV40FPGetSourceID(nvsFunc * shader, int merged, int pos) +{ + switch (shader->GetSourceFile(shader, merged, pos)) { + case NVS_FILE_ATTRIB: + switch ((shader->inst[0] & NV40_FP_OP_INPUT_SRC_MASK) + >> NV40_FP_OP_INPUT_SRC_SHIFT) { + case NV40_FP_OP_INPUT_SRC_POSITION: return NVS_FR_POSITION; + case NV40_FP_OP_INPUT_SRC_COL0 : return NVS_FR_COL0; + case NV40_FP_OP_INPUT_SRC_COL1 : return NVS_FR_COL1; + case NV40_FP_OP_INPUT_SRC_FOGC : return NVS_FR_FOGCOORD; + case NV40_FP_OP_INPUT_SRC_TC(0) : return NVS_FR_TEXCOORD0; + case NV40_FP_OP_INPUT_SRC_TC(1) : return NVS_FR_TEXCOORD1; + case NV40_FP_OP_INPUT_SRC_TC(2) : return NVS_FR_TEXCOORD2; + case NV40_FP_OP_INPUT_SRC_TC(3) : return NVS_FR_TEXCOORD3; + case NV40_FP_OP_INPUT_SRC_TC(4) : return NVS_FR_TEXCOORD4; + case NV40_FP_OP_INPUT_SRC_TC(5) : return NVS_FR_TEXCOORD5; + case NV40_FP_OP_INPUT_SRC_TC(6) : return NVS_FR_TEXCOORD6; + case NV40_FP_OP_INPUT_SRC_TC(7) : return NVS_FR_TEXCOORD7; + case NV40_FP_OP_INPUT_SRC_FACING : return NVS_FR_FACING; + default: + return -1; + } + break; + case NVS_FILE_TEMP: + { + unsigned int src; + + src = shader->GetSourceHW(shader, merged, pos); + return ((src & NV40_FP_REG_SRC_MASK) >> NV40_FP_REG_SRC_SHIFT); + } + case NVS_FILE_CONST: /* inlined into fragprog */ + default: + return -1; + } +} + +static int +NV40FPGetBranch(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_IADDR_MASK) + >> NV40_FP_OP_IADDR_SHIFT);; +} + +static int +NV40FPGetBranchElse(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_ELSE_ID_MASK) + >> NV40_FP_OP_ELSE_ID_SHIFT); +} + +static int +NV40FPGetBranchEnd(nvsFunc * shader) +{ + return ((shader->inst[3] & NV40_FP_OP_END_ID_MASK) + >> NV40_FP_OP_END_ID_SHIFT); +} + +static int +NV40FPGetLoopCount(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_LOOP_COUNT_MASK) + >> NV40_FP_OP_LOOP_COUNT_SHIFT); +} + +static int +NV40FPGetLoopInitial(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_LOOP_INDEX_MASK) + >> NV40_FP_OP_LOOP_INDEX_SHIFT); +} + +static int +NV40FPGetLoopIncrement(nvsFunc * shader) +{ + return ((shader->inst[2] & NV40_FP_OP_LOOP_INCR_MASK) + >> NV40_FP_OP_LOOP_INCR_SHIFT); +} + +void +NV40FPInitShaderFuncs(nvsFunc * shader) +{ + /* Inherit NV30 FP code, it's mostly the same */ + NV30FPInitShaderFuncs(shader); + + /* Kill off opcodes seen on NV30, but not seen on NV40 - need to find + * out if these actually work or not. + * + * update: either LIT/RSQ don't work on nv40, or I generate bad code for + * them. haven't tested the others yet + */ + MOD_OPCODE(NVFP_TX_AOP, 0x1B, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RSQ */ + MOD_OPCODE(NVFP_TX_AOP, 0x1E, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LIT */ + MOD_OPCODE(NVFP_TX_AOP, 0x1F, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 LRP */ + MOD_OPCODE(NVFP_TX_AOP, 0x26, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 POW */ + MOD_OPCODE(NVFP_TX_AOP, 0x36, NVS_OP_UNKNOWN, -1, -1, -1); /* NV30 RFL */ + + /* Extra opcodes supported on NV40 */ + MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DIV , NVS_OP_DIV , 0, 1, -1); + MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_DP2A , NVS_OP_DP2A, 0, 1, 2); + MOD_OPCODE(NVFP_TX_AOP, NV40_FP_OP_OPCODE_TXL , NVS_OP_TXL , 0, -1, -1); + + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_BRK , NVS_OP_BRK , -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_CAL , NVS_OP_CAL , -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_IF , NVS_OP_IF , -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_LOOP, NVS_OP_LOOP, -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_REP , NVS_OP_REP , -1, -1, -1); + MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_RET , NVS_OP_RET , -1, -1, -1); + + shader->SupportsResultScale = NV40FPSupportsResultScale; + shader->SetResultScale = NV40FPSetResultScale; + + /* fragment.facing */ + shader->GetSourceID = NV40FPGetSourceID; + + /* branching */ + shader->GetOPTXRec = NV40FPGetOPTXRec; + shader->GetBranch = NV40FPGetBranch; + shader->GetBranchElse = NV40FPGetBranchElse; + shader->GetBranchEnd = NV40FPGetBranchEnd; + shader->GetLoopCount = NV40FPGetLoopCount; + shader->GetLoopInitial = NV40FPGetLoopInitial; + shader->GetLoopIncrement = NV40FPGetLoopIncrement; + shader->SetBranchTarget = NV40FPSetBranchTarget; + shader->SetBranchElse = NV40FPSetBranchElse; + shader->SetBranchEnd = NV40FPSetBranchEnd; + shader->SetLoopParams = NV40FPSetLoopParams; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_shader.h b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_shader.h new file mode 100644 index 000000000..584f4c23e --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_shader.h @@ -0,0 +1,467 @@ +#ifndef __NV40_SHADER_H__ +#define __NV40_SHADER_H__ + +/* Vertex programs instruction set + * + * The NV40 instruction set is very similar to NV30. Most fields are in + * a slightly different position in the instruction however. + * + * Merged instructions + * In some cases it is possible to put two instructions into one opcode + * slot. The rules for when this is OK is not entirely clear to me yet. + * + * There are separate writemasks and dest temp register fields for each + * grouping of instructions. There is however only one field with the + * ID of a result register. Writing to temp/result regs is selected by + * setting VEC_RESULT/SCA_RESULT. + * + * Temporary registers + * The source/dest temp register fields have been extended by 1 bit, to + * give a total of 32 temporary registers. + * + * Relative Addressing + * NV40 can use an address register to index into vertex attribute regs. + * This is done by putting the offset value into INPUT_SRC and setting + * the INDEX_INPUT flag. + * + * Conditional execution (see NV_vertex_program{2,3} for details) + * There is a second condition code register on NV40, it's use is enabled + * by setting the COND_REG_SELECT_1 flag. + * + * Texture lookup + * TODO + */ + +/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */ +#define NV40_VP_INST_VEC_RESULT (1 << 30) +/* uncertain.. */ +#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29) +/* use address reg as index into attribs */ +#define NV40_VP_INST_INDEX_INPUT (1 << 27) +#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25) +#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24) +#define NV40_VP_INST_SRC2_ABS (1 << 23) +#define NV40_VP_INST_SRC1_ABS (1 << 22) +#define NV40_VP_INST_SRC0_ABS (1 << 21) +#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15 +#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 15) +#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13) +#define NV40_VP_INST_COND_SHIFT 10 +#define NV40_VP_INST_COND_MASK (0x7 << 10) +# define NV40_VP_INST_COND_FL 0 +# define NV40_VP_INST_COND_LT 1 +# define NV40_VP_INST_COND_EQ 2 +# define NV40_VP_INST_COND_LE 3 +# define NV40_VP_INST_COND_GT 4 +# define NV40_VP_INST_COND_NE 5 +# define NV40_VP_INST_COND_GE 6 +# define NV40_VP_INST_COND_TR 7 +#define NV40_VP_INST_COND_SWZ_X_SHIFT 8 +#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8) +#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6 +#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6) +#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4 +#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4) +#define NV40_VP_INST_COND_SWZ_W_SHIFT 2 +#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2) +#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2 +#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2) +#define NV40_VP_INST_ADDR_SWZ_SHIFT 0 +#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0) +#define NV40_VP_INST0_KNOWN ( \ + NV40_VP_INST_INDEX_INPUT | \ + NV40_VP_INST_COND_REG_SELECT_1 | \ + NV40_VP_INST_ADDR_REG_SELECT_1 | \ + NV40_VP_INST_SRC2_ABS | \ + NV40_VP_INST_SRC1_ABS | \ + NV40_VP_INST_SRC0_ABS | \ + NV40_VP_INST_VEC_DEST_TEMP_MASK | \ + NV40_VP_INST_COND_TEST_ENABLE | \ + NV40_VP_INST_COND_MASK | \ + NV40_VP_INST_COND_SWZ_ALL_MASK | \ + NV40_VP_INST_ADDR_SWZ_MASK) + +/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */ +#define NV40_VP_INST_VEC_OPCODE_SHIFT 22 +#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22) +# define NV40_VP_INST_OP_NOP 0x00 +# define NV40_VP_INST_OP_MOV 0x01 +# define NV40_VP_INST_OP_MUL 0x02 +# define NV40_VP_INST_OP_ADD 0x03 +# define NV40_VP_INST_OP_MAD 0x04 +# define NV40_VP_INST_OP_DP3 0x05 +# define NV40_VP_INST_OP_DP4 0x07 +# define NV40_VP_INST_OP_DPH 0x06 +# define NV40_VP_INST_OP_DST 0x08 +# define NV40_VP_INST_OP_MIN 0x09 +# define NV40_VP_INST_OP_MAX 0x0A +# define NV40_VP_INST_OP_SLT 0x0B +# define NV40_VP_INST_OP_SGE 0x0C +# define NV40_VP_INST_OP_ARL 0x0D +# define NV40_VP_INST_OP_FRC 0x0E +# define NV40_VP_INST_OP_FLR 0x0F +# define NV40_VP_INST_OP_SEQ 0x10 +# define NV40_VP_INST_OP_SFL 0x11 +# define NV40_VP_INST_OP_SGT 0x12 +# define NV40_VP_INST_OP_SLE 0x13 +# define NV40_VP_INST_OP_SNE 0x14 +# define NV40_VP_INST_OP_STR 0x15 +# define NV40_VP_INST_OP_SSG 0x16 +# define NV40_VP_INST_OP_ARR 0x17 +# define NV40_VP_INST_OP_ARA 0x18 +# define NV40_VP_INST_OP_TXWHAT 0x19 +#define NV40_VP_INST_SCA_OPCODE_SHIFT 27 +#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27) +# define NV40_VP_INST_OP_RCP 0x02 +# define NV40_VP_INST_OP_RCC 0x03 +# define NV40_VP_INST_OP_RSQ 0x04 +# define NV40_VP_INST_OP_EXP 0x05 +# define NV40_VP_INST_OP_LOG 0x06 +# define NV40_VP_INST_OP_LIT 0x07 +# define NV40_VP_INST_OP_BRA 0x09 +# define NV40_VP_INST_OP_CAL 0x0B +# define NV40_VP_INST_OP_RET 0x0C +# define NV40_VP_INST_OP_LG2 0x0D +# define NV40_VP_INST_OP_EX2 0x0E +# define NV40_VP_INST_OP_SIN 0x0F +# define NV40_VP_INST_OP_COS 0x10 +# define NV40_VP_INST_OP_PUSHA 0x13 +# define NV40_VP_INST_OP_POPA 0x14 +#define NV40_VP_INST_CONST_SRC_SHIFT 12 +#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12) +#define NV40_VP_INST_INPUT_SRC_SHIFT 8 +#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8) +# define NV40_VP_INST_IN_POS 0 +# define NV40_VP_INST_IN_WEIGHT 1 +# define NV40_VP_INST_IN_NORMAL 2 +# define NV40_VP_INST_IN_COL0 3 +# define NV40_VP_INST_IN_COL1 4 +# define NV40_VP_INST_IN_FOGC 5 +# define NV40_VP_INST_IN_TC0 8 +# define NV40_VP_INST_IN_TC(n) (8+n) +#define NV40_VP_INST_SRC0H_SHIFT 0 +#define NV40_VP_INST_SRC0H_MASK (0xFF << 0) +#define NV40_VP_INST1_KNOWN ( \ + NV40_VP_INST_VEC_OPCODE_MASK | \ + NV40_VP_INST_SCA_OPCODE_MASK | \ + NV40_VP_INST_CONST_SRC_MASK | \ + NV40_VP_INST_INPUT_SRC_MASK | \ + NV40_VP_INST_SRC0H_MASK \ + ) + +/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */ +#define NV40_VP_INST_SRC0L_SHIFT 23 +#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23) +#define NV40_VP_INST_SRC1_SHIFT 6 +#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6) +#define NV40_VP_INST_SRC2H_SHIFT 0 +#define NV40_VP_INST_SRC2H_MASK (0x3F << 0) +#define NV40_VP_INST_IADDRH_SHIFT 0 +#define NV40_VP_INST_IADDRH_MASK (0x1F << 0) + +/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */ +#define NV40_VP_INST_IADDRL_SHIFT 29 +#define NV40_VP_INST_IADDRL_MASK (7 << 29) +#define NV40_VP_INST_SRC2L_SHIFT 21 +#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21) +#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17 +#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17) +# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20) +# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19) +# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18) +# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17) +#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13 +#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13) +# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16) +# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15) +# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14) +# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13) +#define NV40_VP_INST_SCA_RESULT (1 << 12) +#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7 +#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7) +#define NV40_VP_INST_DEST_SHIFT 2 +#define NV40_VP_INST_DEST_MASK (31 << 2) +# define NV40_VP_INST_DEST_POS 0 +# define NV40_VP_INST_DEST_COL0 1 +# define NV40_VP_INST_DEST_COL1 2 +# define NV40_VP_INST_DEST_BFC0 3 +# define NV40_VP_INST_DEST_BFC1 4 +# define NV40_VP_INST_DEST_FOGC 5 +# define NV40_VP_INST_DEST_PSZ 6 +# define NV40_VP_INST_DEST_TC0 7 +# define NV40_VP_INST_DEST_TC(n) (7+n) +# define NV40_VP_INST_DEST_TEMP 0x1F +#define NV40_VP_INST_INDEX_CONST (1 << 1) +#define NV40_VP_INST_LAST (1 << 0) +#define NV40_VP_INST3_KNOWN ( \ + NV40_VP_INST_SRC2L_MASK |\ + NV40_VP_INST_SCA_WRITEMASK_MASK |\ + NV40_VP_INST_VEC_WRITEMASK_MASK |\ + NV40_VP_INST_SCA_DEST_TEMP_MASK |\ + NV40_VP_INST_DEST_MASK |\ + NV40_VP_INST_INDEX_CONST) + +/* Useful to split the source selection regs into their pieces */ +#define NV40_VP_SRC0_HIGH_SHIFT 9 +#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00 +#define NV40_VP_SRC0_LOW_MASK 0x000001FF +#define NV40_VP_SRC2_HIGH_SHIFT 11 +#define NV40_VP_SRC2_HIGH_MASK 0x0001F800 +#define NV40_VP_SRC2_LOW_MASK 0x000007FF + +/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */ +#define NV40_VP_SRC_NEGATE (1 << 16) +#define NV40_VP_SRC_SWZ_X_SHIFT 14 +#define NV40_VP_SRC_SWZ_X_MASK (3 << 14) +#define NV40_VP_SRC_SWZ_Y_SHIFT 12 +#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12) +#define NV40_VP_SRC_SWZ_Z_SHIFT 10 +#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10) +#define NV40_VP_SRC_SWZ_W_SHIFT 8 +#define NV40_VP_SRC_SWZ_W_MASK (3 << 8) +#define NV40_VP_SRC_SWZ_ALL_SHIFT 8 +#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8) +#define NV40_VP_SRC_TEMP_SRC_SHIFT 2 +#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2) +#define NV40_VP_SRC_REG_TYPE_SHIFT 0 +#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0) +# define NV40_VP_SRC_REG_TYPE_UNK0 0 +# define NV40_VP_SRC_REG_TYPE_TEMP 1 +# define NV40_VP_SRC_REG_TYPE_INPUT 2 +# define NV40_VP_SRC_REG_TYPE_CONST 3 + + +/* + * Each fragment program opcode appears to be comprised of 4 32-bit values. + * + * 0 - Opcode, output reg/mask, ATTRIB source + * 1 - Source 0 + * 2 - Source 1 + * 3 - Source 2 + * + * There appears to be no special difference between result regs and temp regs. + * result.color == R0.xyzw + * result.depth == R1.z + * When the fragprog contains instructions to write depth, + * NV30_TCL_PRIMITIVE_3D_UNK1D78=0 otherwise it is set to 1. + * + * Constants are inserted directly after the instruction that uses them. + * + * It appears that it's not possible to use two input registers in one + * instruction as the input sourcing is done in the instruction dword + * and not the source selection dwords. As such instructions such as: + * + * ADD result.color, fragment.color, fragment.texcoord[0]; + * + * must be split into two MOV's and then an ADD (nvidia does this) but + * I'm not sure why it's not just one MOV and then source the second input + * in the ADD instruction.. + * + * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary + * negation requires multiplication with a const. + * + * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO and + * SWIZZLE_ONE. + * + * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as + * SWIZZLE_ZERO is implemented simply by not writing to the relevant components + * of the destination. + * + * Looping + * Loops appear to be fairly expensive on NV40 at least, the proprietary + * driver goes to a lot of effort to avoid using the native looping + * instructions. If the total number of *executed* instructions between + * REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop. + * The maximum loop count is 255. + * + * Conditional execution + * TODO + * + * Non-native instructions: + * LIT + * LRP - MAD+MAD + * SUB - ADD, negate second source + * RSQ - LG2 + EX2 + * POW - LG2 + MUL + EX2 + * SCS - COS + SIN + * XPD + * DP2 - MUL + ADD + * NRM + */ + +//== Opcode / Destination selection == +#define NV40_FP_OP_PROGRAM_END (1 << 0) +#define NV40_FP_OP_OUT_REG_SHIFT 1 +#define NV40_FP_OP_OUT_REG_MASK (31 << 1) +/* Needs to be set when writing outputs to get expected result.. */ +#define NV40_FP_OP_UNK0_7 (1 << 7) +#define NV40_FP_OP_COND_WRITE_ENABLE (1 << 8) +#define NV40_FP_OP_OUTMASK_SHIFT 9 +#define NV40_FP_OP_OUTMASK_MASK (0xF << 9) +# define NV40_FP_OP_OUT_X (1 << 9) +# define NV40_FP_OP_OUT_Y (1 <<10) +# define NV40_FP_OP_OUT_Z (1 <<11) +# define NV40_FP_OP_OUT_W (1 <<12) +/* Uncertain about these, especially the input_src values.. it's possible that + * they can be dynamically changed. + */ +#define NV40_FP_OP_INPUT_SRC_SHIFT 13 +#define NV40_FP_OP_INPUT_SRC_MASK (15 << 13) +# define NV40_FP_OP_INPUT_SRC_POSITION 0x0 +# define NV40_FP_OP_INPUT_SRC_COL0 0x1 +# define NV40_FP_OP_INPUT_SRC_COL1 0x2 +# define NV40_FP_OP_INPUT_SRC_FOGC 0x3 +# define NV40_FP_OP_INPUT_SRC_TC0 0x4 +# define NV40_FP_OP_INPUT_SRC_TC(n) (0x4 + n) +# define NV40_FP_OP_INPUT_SRC_FACING 0xE +#define NV40_FP_OP_TEX_UNIT_SHIFT 17 +#define NV40_FP_OP_TEX_UNIT_MASK (0xF << 17) +#define NV40_FP_OP_PRECISION_SHIFT 22 +#define NV40_FP_OP_PRECISION_MASK (3 << 22) +# define NV40_FP_PRECISION_FP32 0 +# define NV40_FP_PRECISION_FP16 1 +# define NV40_FP_PRECISION_FX12 2 +#define NV40_FP_OP_OPCODE_SHIFT 24 +#define NV40_FP_OP_OPCODE_MASK (0x3F << 24) +# define NV40_FP_OP_OPCODE_NOP 0x00 +# define NV40_FP_OP_OPCODE_MOV 0x01 +# define NV40_FP_OP_OPCODE_MUL 0x02 +# define NV40_FP_OP_OPCODE_ADD 0x03 +# define NV40_FP_OP_OPCODE_MAD 0x04 +# define NV40_FP_OP_OPCODE_DP3 0x05 +# define NV40_FP_OP_OPCODE_DP4 0x06 +# define NV40_FP_OP_OPCODE_DST 0x07 +# define NV40_FP_OP_OPCODE_MIN 0x08 +# define NV40_FP_OP_OPCODE_MAX 0x09 +# define NV40_FP_OP_OPCODE_SLT 0x0A +# define NV40_FP_OP_OPCODE_SGE 0x0B +# define NV40_FP_OP_OPCODE_SLE 0x0C +# define NV40_FP_OP_OPCODE_SGT 0x0D +# define NV40_FP_OP_OPCODE_SNE 0x0E +# define NV40_FP_OP_OPCODE_SEQ 0x0F +# define NV40_FP_OP_OPCODE_FRC 0x10 +# define NV40_FP_OP_OPCODE_FLR 0x11 +# define NV40_FP_OP_OPCODE_KIL 0x12 +# define NV40_FP_OP_OPCODE_PK4B 0x13 +# define NV40_FP_OP_OPCODE_UP4B 0x14 +/* DDX/DDY can only write to XY */ +# define NV40_FP_OP_OPCODE_DDX 0x15 +# define NV40_FP_OP_OPCODE_DDY 0x16 +# define NV40_FP_OP_OPCODE_TEX 0x17 +# define NV40_FP_OP_OPCODE_TXP 0x18 +# define NV40_FP_OP_OPCODE_TXD 0x19 +# define NV40_FP_OP_OPCODE_RCP 0x1A +# define NV40_FP_OP_OPCODE_EX2 0x1C +# define NV40_FP_OP_OPCODE_LG2 0x1D +# define NV40_FP_OP_OPCODE_COS 0x22 +# define NV40_FP_OP_OPCODE_SIN 0x23 +# define NV40_FP_OP_OPCODE_PK2H 0x24 +# define NV40_FP_OP_OPCODE_UP2H 0x25 +# define NV40_FP_OP_OPCODE_PK4UB 0x27 +# define NV40_FP_OP_OPCODE_UP4UB 0x28 +# define NV40_FP_OP_OPCODE_PK2US 0x29 +# define NV40_FP_OP_OPCODE_UP2US 0x2A +# define NV40_FP_OP_OPCODE_DP2A 0x2E +# define NV40_FP_OP_OPCODE_TXL 0x2F +# define NV40_FP_OP_OPCODE_TXB 0x31 +# define NV40_FP_OP_OPCODE_DIV 0x3A +/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/ +# define NV40_FP_OP_BRA_OPCODE_BRK 0x0 +# define NV40_FP_OP_BRA_OPCODE_CAL 0x1 +# define NV40_FP_OP_BRA_OPCODE_IF 0x2 +# define NV40_FP_OP_BRA_OPCODE_LOOP 0x3 +# define NV40_FP_OP_BRA_OPCODE_REP 0x4 +# define NV40_FP_OP_BRA_OPCODE_RET 0x5 +#define NV40_FP_OP_OUT_SAT (1 << 31) + +/* high order bits of SRC0 */ +#define NV40_FP_OP_OUT_ABS (1 << 29) +#define NV40_FP_OP_COND_SWZ_W_SHIFT 27 +#define NV40_FP_OP_COND_SWZ_W_MASK (3 << 27) +#define NV40_FP_OP_COND_SWZ_Z_SHIFT 25 +#define NV40_FP_OP_COND_SWZ_Z_MASK (3 << 25) +#define NV40_FP_OP_COND_SWZ_Y_SHIFT 23 +#define NV40_FP_OP_COND_SWZ_Y_MASK (3 << 23) +#define NV40_FP_OP_COND_SWZ_X_SHIFT 21 +#define NV40_FP_OP_COND_SWZ_X_MASK (3 << 21) +#define NV40_FP_OP_COND_SWZ_ALL_SHIFT 21 +#define NV40_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21) +#define NV40_FP_OP_COND_SHIFT 18 +#define NV40_FP_OP_COND_MASK (0x07 << 18) +# define NV40_FP_OP_COND_FL 0 +# define NV40_FP_OP_COND_LT 1 +# define NV40_FP_OP_COND_EQ 2 +# define NV40_FP_OP_COND_LE 3 +# define NV40_FP_OP_COND_GT 4 +# define NV40_FP_OP_COND_NE 5 +# define NV40_FP_OP_COND_GE 6 +# define NV40_FP_OP_COND_TR 7 + +/* high order bits of SRC1 */ +#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31) +#define NV40_FP_OP_DST_SCALE_SHIFT 28 +#define NV40_FP_OP_DST_SCALE_MASK (3 << 28) + +/* SRC1 LOOP */ +#define NV40_FP_OP_LOOP_INCR_SHIFT 19 +#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19) +#define NV40_FP_OP_LOOP_INDEX_SHIFT 10 +#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10) +#define NV40_FP_OP_LOOP_COUNT_SHIFT 2 +#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2) + +/* SRC1 IF */ +#define NV40_FP_OP_ELSE_ID_SHIFT 2 +#define NV40_FP_OP_ELSE_ID_MASK (0xFF << 2) + +/* SRC1 CAL */ +#define NV40_FP_OP_IADDR_SHIFT 2 +#define NV40_FP_OP_IADDR_MASK (0xFF << 2) + +/* SRC1 REP + * I have no idea why there are 3 count values here.. but they + * have always been filled with the same value in my tests so + * far.. + */ +#define NV40_FP_OP_REP_COUNT1_SHIFT 2 +#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2) +#define NV40_FP_OP_REP_COUNT2_SHIFT 10 +#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10) +#define NV40_FP_OP_REP_COUNT3_SHIFT 19 +#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19) + +/* SRC2 REP/IF */ +#define NV40_FP_OP_END_ID_SHIFT 2 +#define NV40_FP_OP_END_ID_MASK (0xFF << 2) + +// SRC2 high-order +#define NV40_FP_OP_INDEX_INPUT (1 << 30) +#define NV40_FP_OP_ADDR_INDEX_SHIFT 19 +#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19) + +//== Register selection == +#define NV40_FP_REG_TYPE_SHIFT 0 +#define NV40_FP_REG_TYPE_MASK (3 << 0) +# define NV40_FP_REG_TYPE_TEMP 0 +# define NV40_FP_REG_TYPE_INPUT 1 +# define NV40_FP_REG_TYPE_CONST 2 +#define NV40_FP_REG_SRC_SHIFT 2 +#define NV40_FP_REG_SRC_MASK (31 << 2) +#define NV40_FP_REG_UNK_0 (1 << 8) +#define NV40_FP_REG_SWZ_ALL_SHIFT 9 +#define NV40_FP_REG_SWZ_ALL_MASK (255 << 9) +#define NV40_FP_REG_SWZ_X_SHIFT 9 +#define NV40_FP_REG_SWZ_X_MASK (3 << 9) +#define NV40_FP_REG_SWZ_Y_SHIFT 11 +#define NV40_FP_REG_SWZ_Y_MASK (3 << 11) +#define NV40_FP_REG_SWZ_Z_SHIFT 13 +#define NV40_FP_REG_SWZ_Z_MASK (3 << 13) +#define NV40_FP_REG_SWZ_W_SHIFT 15 +#define NV40_FP_REG_SWZ_W_MASK (3 << 15) +# define NV40_FP_SWIZZLE_X 0 +# define NV40_FP_SWIZZLE_Y 1 +# define NV40_FP_SWIZZLE_Z 2 +# define NV40_FP_SWIZZLE_W 3 +#define NV40_FP_REG_NEGATE (1 << 17) + +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_vertprog.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_vertprog.c new file mode 100644 index 000000000..d054140bc --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv40_vertprog.c @@ -0,0 +1,778 @@ +#include "nouveau_shader.h" +#include "nouveau_msg.h" +#include "nv40_shader.h" + +/***************************************************************************** + * Assembly routines + */ +static int +NV40VPSupportsOpcode(nvsFunc * shader, nvsOpcode op) +{ + if (shader->GetOPTXFromSOP(op, NULL)) + return 1; + return 0; +} + +static void +NV40VPSetOpcode(nvsFunc *shader, unsigned int opcode, int slot) +{ + if (slot) { + shader->inst[1] &= ~NV40_VP_INST_SCA_OPCODE_MASK; + shader->inst[1] |= (opcode << NV40_VP_INST_SCA_OPCODE_SHIFT); + } else { + shader->inst[1] &= ~NV40_VP_INST_VEC_OPCODE_MASK; + shader->inst[1] |= (opcode << NV40_VP_INST_VEC_OPCODE_SHIFT); + } +} + +static void +NV40VPSetCCUpdate(nvsFunc *shader) +{ + shader->inst[0] |= NV40_VP_INST_COND_UPDATE_ENABLE; +} + +static void +NV40VPSetCondition(nvsFunc *shader, int on, nvsCond cond, int reg, + nvsSwzComp *swizzle) +{ + unsigned int hwcond; + + if (on ) shader->inst[0] |= NV40_VP_INST_COND_TEST_ENABLE; + else shader->inst[0] &= ~NV40_VP_INST_COND_TEST_ENABLE; + if (reg) shader->inst[0] |= NV40_VP_INST_COND_REG_SELECT_1; + else shader->inst[0] &= ~NV40_VP_INST_COND_REG_SELECT_1; + + switch (cond) { + case NVS_COND_TR: hwcond = NV40_VP_INST_COND_TR; break; + case NVS_COND_FL: hwcond = NV40_VP_INST_COND_FL; break; + case NVS_COND_LT: hwcond = NV40_VP_INST_COND_LT; break; + case NVS_COND_GT: hwcond = NV40_VP_INST_COND_GT; break; + case NVS_COND_NE: hwcond = NV40_VP_INST_COND_NE; break; + case NVS_COND_EQ: hwcond = NV40_VP_INST_COND_EQ; break; + case NVS_COND_GE: hwcond = NV40_VP_INST_COND_GE; break; + case NVS_COND_LE: hwcond = NV40_VP_INST_COND_LE; break; + default: + WARN_ONCE("unknown vp cond %d\n", cond); + hwcond = NV40_VP_INST_COND_TR; + break; + } + shader->inst[0] &= ~NV40_VP_INST_COND_MASK; + shader->inst[0] |= (hwcond << NV40_VP_INST_COND_SHIFT); + + shader->inst[0] &= ~NV40_VP_INST_COND_SWZ_ALL_MASK; + shader->inst[0] |= (swizzle[NVS_SWZ_X] << NV40_VP_INST_COND_SWZ_X_SHIFT); + shader->inst[0] |= (swizzle[NVS_SWZ_Y] << NV40_VP_INST_COND_SWZ_Y_SHIFT); + shader->inst[0] |= (swizzle[NVS_SWZ_Z] << NV40_VP_INST_COND_SWZ_Z_SHIFT); + shader->inst[0] |= (swizzle[NVS_SWZ_W] << NV40_VP_INST_COND_SWZ_W_SHIFT); +} + +/* these just exist here until nouveau_reg.h has them. */ +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_COL0 (1<<0) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_COL1 (1<<1) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_BFC0 (1<<2) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_BFC1 (1<<3) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_FOGC (1<<4) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_PSZ (1<<5) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP0 (1<<6) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP1 (1<<7) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP2 (1<<8) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP3 (1<<9) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP4 (1<<10) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP5 (1<<11) +#define NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_TEX0 (1<<14) + +static unsigned int +NV40VPTranslateResultReg(nvsFunc *shader, nvsFixedReg result, + unsigned int *mask_ret) +{ + unsigned int *out_reg = &shader->card_priv->NV30VP.vp_out_reg; + unsigned int *clip_en = &shader->card_priv->NV30VP.clip_enables; + + *mask_ret = 0xf; + + switch (result) { + case NVS_FR_POSITION: + /* out_reg POS implied */ + return NV40_VP_INST_DEST_POS; + case NVS_FR_COL0: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_COL0; + return NV40_VP_INST_DEST_COL0; + case NVS_FR_COL1: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_COL1; + return NV40_VP_INST_DEST_COL1; + case NVS_FR_BFC0: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_BFC0; + return NV40_VP_INST_DEST_BFC0; + case NVS_FR_BFC1: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_BFC1; + return NV40_VP_INST_DEST_BFC1; + case NVS_FR_FOGCOORD: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_FOGC; + *mask_ret = 0x8; + return NV40_VP_INST_DEST_FOGC; + case NVS_FR_CLIP0: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP0; + (*clip_en) |= 0x00000002; + *mask_ret = 0x4; + return NV40_VP_INST_DEST_FOGC; + case NVS_FR_CLIP1: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP1; + (*clip_en) |= 0x00000020; + *mask_ret = 0x2; + return NV40_VP_INST_DEST_FOGC; + case NVS_FR_CLIP2: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP2; + (*clip_en) |= 0x00000200; + *mask_ret = 0x1; + return NV40_VP_INST_DEST_FOGC; + case NVS_FR_POINTSZ: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_PSZ; + *mask_ret = 0x8; + return NV40_VP_INST_DEST_PSZ; + case NVS_FR_CLIP3: + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP3; + (*clip_en) |= 0x00002000; + *mask_ret = 0x4; + return NV40_VP_INST_DEST_PSZ; + case NVS_FR_CLIP4: + (*clip_en) |= 0x00020000; + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP4; + *mask_ret = 0x2; + return NV40_VP_INST_DEST_PSZ; + case NVS_FR_CLIP5: + (*clip_en) |= 0x00200000; + (*out_reg) |= NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_CLP5; + *mask_ret = 0x1; + return NV40_VP_INST_DEST_PSZ; + case NVS_FR_TEXCOORD0: + case NVS_FR_TEXCOORD1: + case NVS_FR_TEXCOORD2: + case NVS_FR_TEXCOORD3: + case NVS_FR_TEXCOORD4: + case NVS_FR_TEXCOORD5: + case NVS_FR_TEXCOORD6: + case NVS_FR_TEXCOORD7: + { + int unit = result - NVS_FR_TEXCOORD0; + (*out_reg) |= (NV30_TCL_PRIMITIVE_3D_VP_OUT_REG_TEX0 << unit); + return NV40_VP_INST_DEST_TC(unit); + } + default: + WARN_ONCE("unknown vp output %d\n", result); + return NV40_VP_INST_DEST_POS; + } +} + +static void +NV40VPSetResult(nvsFunc *shader, nvsRegister * dest, unsigned int mask, + int slot) +{ + unsigned int hwmask = 0; + + if (mask & SMASK_X) hwmask |= (1 << 3); + if (mask & SMASK_Y) hwmask |= (1 << 2); + if (mask & SMASK_Z) hwmask |= (1 << 1); + if (mask & SMASK_W) hwmask |= (1 << 0); + + if (dest->file == NVS_FILE_RESULT) { + unsigned int valid_mask; + int hwidx; + + hwidx = NV40VPTranslateResultReg(shader, dest->index, &valid_mask); + if (hwmask & ~valid_mask) + WARN_ONCE("writing invalid components of result reg\n"); + hwmask &= valid_mask; + + shader->inst[3] &= ~NV40_VP_INST_DEST_MASK; + shader->inst[3] |= (hwidx << NV40_VP_INST_DEST_SHIFT); + + if (slot) shader->inst[3] |= NV40_VP_INST_SCA_RESULT; + else shader->inst[0] |= NV40_VP_INST_VEC_RESULT; + } else { + /* NVS_FILE_TEMP || NVS_FILE_ADDRESS */ + if (slot) { + shader->inst[3] &= ~NV40_VP_INST_SCA_RESULT; + shader->inst[3] &= ~NV40_VP_INST_SCA_DEST_TEMP_MASK; + shader->inst[3] |= (dest->index << NV40_VP_INST_SCA_DEST_TEMP_SHIFT); + } else { + shader->inst[0] &= ~NV40_VP_INST_VEC_RESULT; + shader->inst[0] &= ~(NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20)); + shader->inst[0] |= (dest->index << NV40_VP_INST_VEC_DEST_TEMP_SHIFT); + } + } + + if (slot) { + shader->inst[3] &= ~NV40_VP_INST_SCA_WRITEMASK_MASK; + shader->inst[3] |= (hwmask << NV40_VP_INST_SCA_WRITEMASK_SHIFT); + } else { + shader->inst[3] &= ~NV40_VP_INST_VEC_WRITEMASK_MASK; + shader->inst[3] |= (hwmask << NV40_VP_INST_VEC_WRITEMASK_SHIFT); + } +} + +static void +NV40VPInsertSource(nvsFunc *shader, unsigned int hw, int pos) +{ + switch (pos) { + case 0: + shader->inst[1] &= ~NV40_VP_INST_SRC0H_MASK; + shader->inst[2] &= ~NV40_VP_INST_SRC0L_MASK; + shader->inst[1] |= ((hw & NV40_VP_SRC0_HIGH_MASK) >> + NV40_VP_SRC0_HIGH_SHIFT) + << NV40_VP_INST_SRC0H_SHIFT; + shader->inst[2] |= (hw & NV40_VP_SRC0_LOW_MASK) + << NV40_VP_INST_SRC0L_SHIFT; + break; + case 1: + shader->inst[2] &= ~NV40_VP_INST_SRC1_MASK; + shader->inst[2] |= hw + << NV40_VP_INST_SRC1_SHIFT; + break; + case 2: + shader->inst[2] &= ~NV40_VP_INST_SRC2H_MASK; + shader->inst[3] &= ~NV40_VP_INST_SRC2L_MASK; + shader->inst[2] |= ((hw & NV40_VP_SRC2_HIGH_MASK) >> + NV40_VP_SRC2_HIGH_SHIFT) + << NV40_VP_INST_SRC2H_SHIFT; + shader->inst[3] |= (hw & NV40_VP_SRC2_LOW_MASK) + << NV40_VP_INST_SRC2L_SHIFT; + break; + default: + assert(0); + break; + } +} + +static void +NV40VPSetSource(nvsFunc *shader, nvsRegister * src, int pos) +{ + unsigned int hw = 0; + + switch (src->file) { + case NVS_FILE_ADDRESS: + break; + case NVS_FILE_ATTRIB: + hw |= (NV40_VP_SRC_REG_TYPE_INPUT << NV40_VP_SRC_REG_TYPE_SHIFT); + + shader->inst[1] &= ~NV40_VP_INST_INPUT_SRC_MASK; + shader->inst[1] |= (src->index << NV40_VP_INST_INPUT_SRC_SHIFT); + shader->card_priv->NV30VP.vp_in_reg |= (1 << src->index); + if (src->indexed) { + shader->inst[0] |= NV40_VP_INST_INDEX_INPUT; + if (src->addr_reg) + shader->inst[0] |= NV40_VP_INST_ADDR_REG_SELECT_1; + else + shader->inst[0] &= ~NV40_VP_INST_ADDR_REG_SELECT_1; + shader->inst[0] &= ~NV40_VP_INST_ADDR_SWZ_SHIFT; + shader->inst[0] |= (src->addr_comp << NV40_VP_INST_ADDR_SWZ_SHIFT); + } else + shader->inst[0] &= ~NV40_VP_INST_INDEX_INPUT; + break; + case NVS_FILE_CONST: + hw |= (NV40_VP_SRC_REG_TYPE_CONST << NV40_VP_SRC_REG_TYPE_SHIFT); + + shader->inst[1] &= ~NV40_VP_INST_CONST_SRC_MASK; + shader->inst[1] |= (src->index << NV40_VP_INST_CONST_SRC_SHIFT); + if (src->indexed) { + shader->inst[3] |= NV40_VP_INST_INDEX_CONST; + if (src->addr_reg) + shader->inst[0] |= NV40_VP_INST_ADDR_REG_SELECT_1; + else + shader->inst[0] &= ~NV40_VP_INST_ADDR_REG_SELECT_1; + shader->inst[0] &= ~NV40_VP_INST_ADDR_SWZ_MASK; + shader->inst[0] |= (src->addr_comp << NV40_VP_INST_ADDR_SWZ_SHIFT); + } else + shader->inst[3] &= ~NV40_VP_INST_INDEX_CONST; + break; + case NVS_FILE_TEMP: + hw |= (NV40_VP_SRC_REG_TYPE_TEMP << NV40_VP_SRC_REG_TYPE_SHIFT); + hw |= (src->index << NV40_VP_SRC_TEMP_SRC_SHIFT); + break; + default: + fprintf(stderr, "unknown source file %d\n", src->file); + assert(0); + break; + } + + if (src->file != NVS_FILE_ADDRESS) { + if (src->negate) + hw |= NV40_VP_SRC_NEGATE; + if (src->abs) + shader->inst[0] |= (1 << (21 + pos)); + else + shader->inst[0] &= ~(1 << (21 + pos)); + hw |= (src->swizzle[0] << NV40_VP_SRC_SWZ_X_SHIFT); + hw |= (src->swizzle[1] << NV40_VP_SRC_SWZ_Y_SHIFT); + hw |= (src->swizzle[2] << NV40_VP_SRC_SWZ_Z_SHIFT); + hw |= (src->swizzle[3] << NV40_VP_SRC_SWZ_W_SHIFT); + + NV40VPInsertSource(shader, hw, pos); + } +} + +static void +NV40VPSetBranchTarget(nvsFunc *shader, int addr) +{ + shader->inst[2] &= ~NV40_VP_INST_IADDRH_MASK; + shader->inst[2] |= ((addr & 0xf8) >> 3) << NV40_VP_INST_IADDRH_SHIFT; + shader->inst[3] &= ~NV40_VP_INST_IADDRL_MASK; + shader->inst[3] |= ((addr & 0x07) << NV40_VP_INST_IADDRL_SHIFT); +} + +static void +NV40VPInitInstruction(nvsFunc *shader) +{ + unsigned int hwsrc = 0; + + shader->inst[0] = /*NV40_VP_INST_VEC_RESULT | */ + NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); + shader->inst[1] = 0; + shader->inst[2] = 0; + shader->inst[3] = NV40_VP_INST_SCA_RESULT | + NV40_VP_INST_SCA_DEST_TEMP_MASK | + NV40_VP_INST_DEST_MASK; + + hwsrc = (NV40_VP_SRC_REG_TYPE_INPUT << NV40_VP_SRC_REG_TYPE_SHIFT) | + (NVS_SWZ_X << NV40_VP_SRC_SWZ_X_SHIFT) | + (NVS_SWZ_Y << NV40_VP_SRC_SWZ_Y_SHIFT) | + (NVS_SWZ_Z << NV40_VP_SRC_SWZ_Z_SHIFT) | + (NVS_SWZ_W << NV40_VP_SRC_SWZ_W_SHIFT); + NV40VPInsertSource(shader, hwsrc, 0); + NV40VPInsertSource(shader, hwsrc, 1); + NV40VPInsertSource(shader, hwsrc, 2); +} + +static void +NV40VPSetLastInst(nvsFunc *shader) +{ + shader->inst[3] |= 1; +} + +/***************************************************************************** + * Disassembly routines + */ +static int +NV40VPHasMergedInst(nvsFunc * shader) +{ + if (shader->GetOpcodeHW(shader, 0) != NV40_VP_INST_OP_NOP && + shader->GetOpcodeHW(shader, 1) != NV40_VP_INST_OP_NOP) + return 1; + return 0; +} + +static unsigned int +NV40VPGetOpcodeHW(nvsFunc * shader, int slot) +{ + int op; + + if (slot) + op = (shader->inst[1] & NV40_VP_INST_SCA_OPCODE_MASK) + >> NV40_VP_INST_SCA_OPCODE_SHIFT; + else + op = (shader->inst[1] & NV40_VP_INST_VEC_OPCODE_MASK) + >> NV40_VP_INST_VEC_OPCODE_SHIFT; + + return op; +} + +static nvsRegFile +NV40VPGetDestFile(nvsFunc * shader, int merged) +{ + nvsOpcode op; + + op = shader->GetOpcode(shader, merged); + switch (op) { + case NVS_OP_ARL: + case NVS_OP_ARR: + case NVS_OP_ARA: + case NVS_OP_POPA: + return NVS_FILE_ADDRESS; + default: + if (shader->GetOpcodeSlot(shader, merged)) { + if (shader->inst[3] & NV40_VP_INST_SCA_RESULT) + return NVS_FILE_RESULT; + } + else { + if (shader->inst[0] & NV40_VP_INST_VEC_RESULT) + return NVS_FILE_RESULT; + } + return NVS_FILE_TEMP; + } + +} + +static unsigned int +NV40VPGetDestID(nvsFunc * shader, int merged) +{ + int id; + + switch (shader->GetDestFile(shader, merged)) { + case NVS_FILE_RESULT: + id = ((shader->inst[3] & NV40_VP_INST_DEST_MASK) + >> NV40_VP_INST_DEST_SHIFT); + switch (id) { + case NV40_VP_INST_DEST_POS : return NVS_FR_POSITION; + case NV40_VP_INST_DEST_COL0: return NVS_FR_COL0; + case NV40_VP_INST_DEST_COL1: return NVS_FR_COL1; + case NV40_VP_INST_DEST_BFC0: return NVS_FR_BFC0; + case NV40_VP_INST_DEST_BFC1: return NVS_FR_BFC1; + case NV40_VP_INST_DEST_FOGC: { + int mask = shader->GetDestMask(shader, merged); + switch (mask) { + case SMASK_X: return NVS_FR_FOGCOORD; + case SMASK_Y: return NVS_FR_CLIP0; + case SMASK_Z: return NVS_FR_CLIP1; + case SMASK_W: return NVS_FR_CLIP2; + default: + printf("more than 1 mask component set in FOGC writemask!\n"); + return NVS_FR_UNKNOWN; + } + } + case NV40_VP_INST_DEST_PSZ: + { + int mask = shader->GetDestMask(shader, merged); + switch (mask) { + case SMASK_X: return NVS_FR_POINTSZ; + case SMASK_Y: return NVS_FR_CLIP3; + case SMASK_Z: return NVS_FR_CLIP4; + case SMASK_W: return NVS_FR_CLIP5; + default: + printf("more than 1 mask component set in PSZ writemask!\n"); + return NVS_FR_UNKNOWN; + } + } + case NV40_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0; + case NV40_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1; + case NV40_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2; + case NV40_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3; + case NV40_VP_INST_DEST_TC(4): return NVS_FR_TEXCOORD4; + case NV40_VP_INST_DEST_TC(5): return NVS_FR_TEXCOORD5; + case NV40_VP_INST_DEST_TC(6): return NVS_FR_TEXCOORD6; + case NV40_VP_INST_DEST_TC(7): return NVS_FR_TEXCOORD7; + default: + return -1; + } + case NVS_FILE_ADDRESS: + /* Instructions that write address regs are encoded as if + * they would write temps. + */ + case NVS_FILE_TEMP: + if (shader->GetOpcodeSlot(shader, merged)) + id = ((shader->inst[3] & NV40_VP_INST_SCA_DEST_TEMP_MASK) + >> NV40_VP_INST_SCA_DEST_TEMP_SHIFT); + else + id = ((shader->inst[0] & NV40_VP_INST_VEC_DEST_TEMP_MASK) + >> NV40_VP_INST_VEC_DEST_TEMP_SHIFT); + return id; + default: + return -1; + } +} + +static unsigned int +NV40VPGetDestMask(nvsFunc * shader, int merged) +{ + unsigned int mask = 0; + + if (shader->GetOpcodeSlot(shader, merged)) { + if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_X) mask |= SMASK_X; + if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_Y) mask |= SMASK_Y; + if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_Z) mask |= SMASK_Z; + if (shader->inst[3] & NV40_VP_INST_SCA_WRITEMASK_W) mask |= SMASK_W; + } else { + if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_X) mask |= SMASK_X; + if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_Y) mask |= SMASK_Y; + if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_Z) mask |= SMASK_Z; + if (shader->inst[3] & NV40_VP_INST_VEC_WRITEMASK_W) mask |= SMASK_W; + } + + return mask; +} + +static unsigned int +NV40VPGetSourceHW(nvsFunc * shader, int merged, int pos) +{ + struct _op_xlat *opr; + unsigned int src; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr) + return -1; + + switch (opr->srcpos[pos]) { + case 0: + src = ((shader->inst[1] & NV40_VP_INST_SRC0H_MASK) + >> NV40_VP_INST_SRC0H_SHIFT) + << NV40_VP_SRC0_HIGH_SHIFT; + src |= ((shader->inst[2] & NV40_VP_INST_SRC0L_MASK) + >> NV40_VP_INST_SRC0L_SHIFT); + break; + case 1: + src = ((shader->inst[2] & NV40_VP_INST_SRC1_MASK) + >> NV40_VP_INST_SRC1_SHIFT); + break; + case 2: + src = ((shader->inst[2] & NV40_VP_INST_SRC2H_MASK) + >> NV40_VP_INST_SRC2H_SHIFT) + << NV40_VP_SRC2_HIGH_SHIFT; + src |= ((shader->inst[3] & NV40_VP_INST_SRC2L_MASK) + >> NV40_VP_INST_SRC2L_SHIFT); + break; + default: + src = -1; + } + + return src; +} + +static nvsRegFile +NV40VPGetSourceFile(nvsFunc * shader, int merged, int pos) +{ + unsigned int src; + struct _op_xlat *opr; + int file; + + opr = shader->GetOPTXRec(shader, merged); + if (!opr || opr->srcpos[pos] == -1) + return -1; + + switch (opr->srcpos[pos]) { + case SPOS_ADDRESS: return NVS_FILE_ADDRESS; + default: + src = shader->GetSourceHW(shader, merged, pos); + file = (src & NV40_VP_SRC_REG_TYPE_MASK) >> NV40_VP_SRC_REG_TYPE_SHIFT; + + switch (file) { + case NV40_VP_SRC_REG_TYPE_TEMP : return NVS_FILE_TEMP; + case NV40_VP_SRC_REG_TYPE_INPUT: return NVS_FILE_ATTRIB; + case NV40_VP_SRC_REG_TYPE_CONST: return NVS_FILE_CONST; + default: + return NVS_FILE_UNKNOWN; + } + } +} + +static int +NV40VPGetSourceID(nvsFunc * shader, int merged, int pos) +{ + switch (shader->GetSourceFile(shader, merged, pos)) { + case NVS_FILE_ATTRIB: + switch ((shader->inst[1] & NV40_VP_INST_INPUT_SRC_MASK) + >> NV40_VP_INST_INPUT_SRC_SHIFT) { + case NV40_VP_INST_IN_POS: return NVS_FR_POSITION; + case NV40_VP_INST_IN_WEIGHT: return NVS_FR_WEIGHT; + case NV40_VP_INST_IN_NORMAL: return NVS_FR_NORMAL; + case NV40_VP_INST_IN_COL0: return NVS_FR_COL0; + case NV40_VP_INST_IN_COL1: return NVS_FR_COL1; + case NV40_VP_INST_IN_FOGC: return NVS_FR_FOGCOORD; + case NV40_VP_INST_IN_TC(0): return NVS_FR_TEXCOORD0; + case NV40_VP_INST_IN_TC(1): return NVS_FR_TEXCOORD1; + case NV40_VP_INST_IN_TC(2): return NVS_FR_TEXCOORD2; + case NV40_VP_INST_IN_TC(3): return NVS_FR_TEXCOORD3; + case NV40_VP_INST_IN_TC(4): return NVS_FR_TEXCOORD4; + case NV40_VP_INST_IN_TC(5): return NVS_FR_TEXCOORD5; + case NV40_VP_INST_IN_TC(6): return NVS_FR_TEXCOORD6; + case NV40_VP_INST_IN_TC(7): return NVS_FR_TEXCOORD7; + default: + return -1; + } + break; + case NVS_FILE_CONST: + return ((shader->inst[1] & NV40_VP_INST_CONST_SRC_MASK) + >> NV40_VP_INST_CONST_SRC_SHIFT); + case NVS_FILE_TEMP: + { + unsigned int src; + + src = shader->GetSourceHW(shader, merged, pos); + return ((src & NV40_VP_SRC_TEMP_SRC_MASK) >> + NV40_VP_SRC_TEMP_SRC_SHIFT); + } + default: + return -1; + } +} + +static int +NV40VPGetSourceNegate(nvsFunc * shader, int merged, int pos) +{ + unsigned int src; + + src = shader->GetSourceHW(shader, merged, pos); + + if (src == -1) + return -1; + return ((src & NV40_VP_SRC_NEGATE) ? 1 : 0); +} + +static void +NV40VPGetSourceSwizzle(nvsFunc * shader, int merged, int pos, nvsSwzComp *swz) +{ + unsigned int src; + int swzbits; + + src = shader->GetSourceHW(shader, merged, pos); + swzbits = (src & NV40_VP_SRC_SWZ_ALL_MASK) >> NV40_VP_SRC_SWZ_ALL_SHIFT; + NV20VPTXSwizzle(swzbits, swz); +} + +static int +NV40VPGetSourceIndexed(nvsFunc * shader, int merged, int pos) +{ + switch (shader->GetSourceFile(shader, merged, pos)) { + case NVS_FILE_ATTRIB: + return ((shader->inst[0] & NV40_VP_INST_INDEX_INPUT) ? 1 : 0); + case NVS_FILE_CONST: + return ((shader->inst[3] & NV40_VP_INST_INDEX_CONST) ? 1 : 0); + default: + return 0; + } +} + +static nvsSwzComp +NV40VPGetAddressRegSwizzle(nvsFunc * shader) +{ + nvsSwzComp swz; + + swz = NV20VP_TX_SWIZZLE[(shader->inst[0] & NV40_VP_INST_ADDR_SWZ_MASK) + >> NV40_VP_INST_ADDR_SWZ_SHIFT]; + return swz; +} + +static int +NV40VPSupportsConditional(nvsFunc * shader) +{ + /*FIXME: Is this true of all ops? */ + return 1; +} + +static int +NV40VPGetConditionUpdate(nvsFunc * shader) +{ + return ((shader->inst[0] & NV40_VP_INST_COND_UPDATE_ENABLE) ? 1 : 0); +} + +static int +NV40VPGetConditionTest(nvsFunc * shader) +{ + int op; + + /* The condition test is unconditionally enabled on some + * instructions. ie: the condition test bit does *NOT* have + * to be set. + * + * FIXME: check other relevant ops for this situation. + */ + op = shader->GetOpcodeHW(shader, 1); + switch (op) { + case NV40_VP_INST_OP_BRA: + return 1; + default: + return ((shader->inst[0] & NV40_VP_INST_COND_TEST_ENABLE) ? 1 : 0); + } +} + +static nvsCond +NV40VPGetCondition(nvsFunc * shader) +{ + int cond; + + cond = ((shader->inst[0] & NV40_VP_INST_COND_MASK) + >> NV40_VP_INST_COND_SHIFT); + + switch (cond) { + case NV40_VP_INST_COND_FL: return NVS_COND_FL; + case NV40_VP_INST_COND_LT: return NVS_COND_LT; + case NV40_VP_INST_COND_EQ: return NVS_COND_EQ; + case NV40_VP_INST_COND_LE: return NVS_COND_LE; + case NV40_VP_INST_COND_GT: return NVS_COND_GT; + case NV40_VP_INST_COND_NE: return NVS_COND_NE; + case NV40_VP_INST_COND_GE: return NVS_COND_GE; + case NV40_VP_INST_COND_TR: return NVS_COND_TR; + default: + return NVS_COND_UNKNOWN; + } +} + +static void +NV40VPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz) +{ + int swzbits; + + swzbits = (shader->inst[0] & NV40_VP_INST_COND_SWZ_ALL_MASK) + >> NV40_VP_INST_COND_SWZ_ALL_SHIFT; + NV20VPTXSwizzle(swzbits, swz); +} + +static int +NV40VPGetCondRegID(nvsFunc * shader) +{ + return ((shader->inst[0] & NV40_VP_INST_COND_REG_SELECT_1) ? 1 : 0); +} + +static int +NV40VPGetBranch(nvsFunc * shader) +{ + int addr; + + addr = ((shader->inst[2] & NV40_VP_INST_IADDRH_MASK) + >> NV40_VP_INST_IADDRH_SHIFT) << 3; + addr |= ((shader->inst[3] & NV40_VP_INST_IADDRL_MASK) + >> NV40_VP_INST_IADDRL_SHIFT); + return addr; +} + +void +NV40VPInitShaderFuncs(nvsFunc * shader) +{ + /* Inherit NV30 VP code, we share some of it */ + NV30VPInitShaderFuncs(shader); + + /* Limits */ + shader->MaxInst = 4096; + shader->MaxAttrib = 16; + shader->MaxTemp = 32; + shader->MaxAddress = 2; + shader->MaxConst = 256; + shader->caps = SCAP_SRC_ABS; + + /* Add extra opcodes for NV40+ */ +// MOD_OPCODE(NVVP_TX_VOP, NV40_VP_INST_OP_TXWHAT, NVS_OP_TEX , 0, 4, -1); + MOD_OPCODE(NVVP_TX_SOP, NV40_VP_INST_OP_PUSHA, NVS_OP_PUSHA, 3, -1, -1); + MOD_OPCODE(NVVP_TX_SOP, NV40_VP_INST_OP_POPA , NVS_OP_POPA , -1, -1, -1); + + shader->InitInstruction = NV40VPInitInstruction; + shader->SupportsOpcode = NV40VPSupportsOpcode; + shader->SetOpcode = NV40VPSetOpcode; + shader->SetCCUpdate = NV40VPSetCCUpdate; + shader->SetCondition = NV40VPSetCondition; + shader->SetResult = NV40VPSetResult; + shader->SetSource = NV40VPSetSource; + shader->SetLastInst = NV40VPSetLastInst; + shader->SetBranchTarget = NV40VPSetBranchTarget; + + shader->HasMergedInst = NV40VPHasMergedInst; + shader->GetOpcodeHW = NV40VPGetOpcodeHW; + + shader->GetDestFile = NV40VPGetDestFile; + shader->GetDestID = NV40VPGetDestID; + shader->GetDestMask = NV40VPGetDestMask; + + shader->GetSourceHW = NV40VPGetSourceHW; + shader->GetSourceFile = NV40VPGetSourceFile; + shader->GetSourceID = NV40VPGetSourceID; + shader->GetSourceNegate = NV40VPGetSourceNegate; + shader->GetSourceSwizzle = NV40VPGetSourceSwizzle; + shader->GetSourceIndexed = NV40VPGetSourceIndexed; + + shader->GetRelAddressSwizzle = NV40VPGetAddressRegSwizzle; + + shader->SupportsConditional = NV40VPSupportsConditional; + shader->GetConditionUpdate = NV40VPGetConditionUpdate; + shader->GetConditionTest = NV40VPGetConditionTest; + shader->GetCondition = NV40VPGetCondition; + shader->GetCondRegSwizzle = NV40VPGetCondRegSwizzle; + shader->GetCondRegID = NV40VPGetCondRegID; + + shader->GetBranch = NV40VPGetBranch; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/nouveau/nv50_state.c b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv50_state.c new file mode 100644 index 000000000..818e26861 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/nouveau/nv50_state.c @@ -0,0 +1,641 @@ +/************************************************************************** + +Copyright 2006 Nouveau +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#include "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" +#include "nouveau_state.h" + +#include "tnl/t_pipeline.h" + +#include "mtypes.h" +#include "colormac.h" + +static void nv50AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte ubRef; + CLAMPED_FLOAT_TO_UBYTE(ubRef, ref); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF, 2); + OUT_RING_CACHE(ubRef); + OUT_RING_CACHE(func); +} + +static void nv50BlendColor(GLcontext *ctx, const GLfloat color[4]) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_COLOR_R, 4); + OUT_RING_CACHEf(color[0]); + OUT_RING_CACHEf(color[1]); + OUT_RING_CACHEf(color[2]); + OUT_RING_CACHEf(color[3]); +} + +static void nv50BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_EQUATION_RGB, 1); + OUT_RING_CACHE(modeRGB); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_EQUATION_ALPHA, 1); + OUT_RING_CACHE(modeA); +} + + +static void nv50BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC_RGB, 2); + OUT_RING_CACHE(sfactorRGB); /* FIXME, sometimes has |0x4000 */ + OUT_RING_CACHE(dfactorRGB); /* FIXME, sometimes has |0x4000 */ + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC_ALPHA, 2); + OUT_RING_CACHE(sfactorA); /* FIXME, sometimes has |0x4000 */ + OUT_RING_CACHE(dfactorA); /* FIXME, sometimes has |0x4000 */ +} + +static void nv50Clear(GLcontext *ctx, GLbitfield mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLuint hw_bufs = 0; + + if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) + hw_bufs |= 0x3c; + if (mask & (BUFFER_BIT_STENCIL)) + hw_bufs |= 0x02; + if (mask & (BUFFER_BIT_DEPTH)) + hw_bufs |= 0x01; + + if (hw_bufs) { + BEGIN_RING_SIZE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CLEAR_BUFFERS, 1); + OUT_RING(hw_bufs); + } +} + +static void nv50ClearColor(GLcontext *ctx, const GLfloat color[4]) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CLEAR_COLOR_R, 4); + OUT_RING_CACHEf(color[0]); + OUT_RING_CACHEf(color[1]); + OUT_RING_CACHEf(color[2]); + OUT_RING_CACHEf(color[3]); +} + +static void nv50ClearDepth(GLcontext *ctx, GLclampd d) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CLEAR_DEPTH, 1); + OUT_RING_CACHEf(d); +} + +/* we're don't support indexed buffers + void (*ClearIndex)(GLcontext *ctx, GLuint index) + */ + +static void nv50ClearStencil(GLcontext *ctx, GLint s) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CLEAR_STENCIL, 1); + OUT_RING_CACHE(s); +} + +static void nv50ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation) +{ + /* Only using shaders */ +} + +static void nv50ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask, + GLboolean bmask, GLboolean amask ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + int i; + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_COLOR_MASK(0), 8); + for (i=0; i<8; i++) { + OUT_RING_CACHE(((amask && 0x01) << 12) | ((bmask && 0x01) << 8) | ((gmask && 0x01)<< 4) | ((rmask && 0x01) << 0)); + } +} + +static void nv50ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode) +{ + // TODO I need love +} + +static void nv50CullFace(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CULL_FACE, 1); + OUT_RING_CACHE(mode); +} + +static void nv50FrontFace(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_FRONT_FACE, 1); + OUT_RING_CACHE(mode); +} + +static void nv50DepthFunc(GLcontext *ctx, GLenum func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1); + OUT_RING_CACHE(func); +} + +static void nv50DepthMask(GLcontext *ctx, GLboolean flag) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1); + OUT_RING_CACHE(flag); +} + +static void nv50DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2); + OUT_RING_CACHEf(nearval); + OUT_RING_CACHEf(farval); +} + +/** Specify the current buffer for writing */ +//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer ); +/** Specify the buffers for writing for fragment programs*/ +//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers ); + +static void nv50Enable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + switch(cap) + { + case GL_ALPHA_TEST: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_AUTO_NORMAL: +// case GL_BLEND: +// case GL_CLIP_PLANE0: +// case GL_CLIP_PLANE1: +// case GL_CLIP_PLANE2: +// case GL_CLIP_PLANE3: +// case GL_CLIP_PLANE4: +// case GL_CLIP_PLANE5: + case GL_COLOR_LOGIC_OP: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LOGIC_OP_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_COLOR_MATERIAL: +// case GL_COLOR_SUM_EXT: +// case GL_COLOR_TABLE: +// case GL_CONVOLUTION_1D: +// case GL_CONVOLUTION_2D: + case GL_CULL_FACE: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_DEPTH_TEST: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_DITHER: +// case GL_FOG: +// case GL_HISTOGRAM: +// case GL_INDEX_LOGIC_OP: +// case GL_LIGHT0: +// case GL_LIGHT1: +// case GL_LIGHT2: +// case GL_LIGHT3: +// case GL_LIGHT4: +// case GL_LIGHT5: +// case GL_LIGHT6: +// case GL_LIGHT7: +// case GL_LIGHTING: + case GL_LINE_SMOOTH: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LINE_SMOOTH_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_LINE_STIPPLE: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LINE_STIPPLE_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_MAP1_COLOR_4: +// case GL_MAP1_INDEX: +// case GL_MAP1_NORMAL: +// case GL_MAP1_TEXTURE_COORD_1: +// case GL_MAP1_TEXTURE_COORD_2: +// case GL_MAP1_TEXTURE_COORD_3: +// case GL_MAP1_TEXTURE_COORD_4: +// case GL_MAP1_VERTEX_3: +// case GL_MAP1_VERTEX_4: +// case GL_MAP2_COLOR_4: +// case GL_MAP2_INDEX: +// case GL_MAP2_NORMAL: +// case GL_MAP2_TEXTURE_COORD_1: +// case GL_MAP2_TEXTURE_COORD_2: +// case GL_MAP2_TEXTURE_COORD_3: +// case GL_MAP2_TEXTURE_COORD_4: +// case GL_MAP2_VERTEX_3: +// case GL_MAP2_VERTEX_4: +// case GL_MINMAX: +// case GL_NORMALIZE: +// case GL_POINT_SMOOTH: + case GL_POLYGON_OFFSET_POINT: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_OFFSET_LINE: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_OFFSET_FILL: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_SMOOTH: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1); + OUT_RING_CACHE(state); + break; + case GL_POLYGON_STIPPLE: + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_POST_COLOR_MATRIX_COLOR_TABLE: +// case GL_POST_CONVOLUTION_COLOR_TABLE: +// case GL_RESCALE_NORMAL: + case GL_SCISSOR_TEST: + /* No enable bit, nv50Scissor will adjust to max range */ + ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); + break; +// case GL_SEPARABLE_2D: + case GL_STENCIL_TEST: + // TODO BACK and FRONT ? + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1); + OUT_RING_CACHE(state); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1); + OUT_RING_CACHE(state); + break; +// case GL_TEXTURE_GEN_Q: +// case GL_TEXTURE_GEN_R: +// case GL_TEXTURE_GEN_S: +// case GL_TEXTURE_GEN_T: +// case GL_TEXTURE_1D: +// case GL_TEXTURE_2D: +// case GL_TEXTURE_3D: + } +} + +static void nv50Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + /* Only using shaders */ +} + +static void nv50Hint(GLcontext *ctx, GLenum target, GLenum mode) +{ + // TODO I need love (fog and line_smooth hints) +} + +// void (*IndexMask)(GLcontext *ctx, GLuint mask); + +static void nv50Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params ) +{ + /* Only with shaders */ +} + +/** Set the lighting model parameters */ +void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params); + + +static void nv50LineStipple(GLcontext *ctx, GLint factor, GLushort pattern ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1); + OUT_RING_CACHE((pattern << 8) | factor); +} + +static void nv50LineWidth(GLcontext *ctx, GLfloat width) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LINE_WIDTH, 1); + OUT_RING_CACHEf(width); +} + +static void nv50LogicOpcode(GLcontext *ctx, GLenum opcode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_LOGIC_OP_OP, 1); + OUT_RING_CACHE(opcode); +} + +static void nv50PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + /*TODO: not sure what goes here. */ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + +} + +/** Specify the diameter of rasterized points */ +static void nv50PointSize(GLcontext *ctx, GLfloat size) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POINT_SIZE, 1); + OUT_RING_CACHEf(size); +} + +/** Select a polygon rasterization mode */ +static void nv50PolygonMode(GLcontext *ctx, GLenum face, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1); + OUT_RING_CACHE(mode); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1); + OUT_RING_CACHE(mode); + } +} + +/** Set the scale and units used to calculate depth values */ +static void nv50PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 1); + OUT_RING_CACHEf(factor); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_OFFSET_UNITS, 1); + OUT_RING_CACHEf(units); +} + +/** Set the polygon stippling pattern */ +static void nv50PolygonStipple(GLcontext *ctx, const GLubyte *mask ) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 32); + OUT_RING_CACHEp(mask, 32); +} + +/* Specifies the current buffer for reading */ +void (*ReadBuffer)( GLcontext *ctx, GLenum buffer ); +/** Set rasterization mode */ +void (*RenderMode)(GLcontext *ctx, GLenum mode ); + +/** Define the scissor box */ +static void nv50Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + /* There's no scissor enable bit, so adjust the scissor to cover the + * maximum draw buffer bounds + */ + if (!ctx->Scissor.Enabled) { + x = y = 0; + w = h = 8191; + } else { + x += nmesa->drawX; + y += nmesa->drawY; + } + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2); + OUT_RING_CACHE(((w) << 16) | x); + OUT_RING_CACHE(((h) << 16) | y); +} + +/** Select flat or smooth shading */ +static void nv50ShadeModel(GLcontext *ctx, GLenum mode) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_SHADE_MODEL, 1); + OUT_RING_CACHE(mode); +} + +/** OpenGL 2.0 two-sided StencilFunc */ +static void nv50StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, + GLint ref, GLuint mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC, 1); + OUT_RING_CACHE(func); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_REF, 1); + OUT_RING_CACHE(ref); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_MASK, 1); + OUT_RING_CACHE(mask); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC, 2); + OUT_RING_CACHE(func); + OUT_RING_CACHE(ref); + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_MASK, 1); + OUT_RING_CACHE(mask); + } +} + +/** OpenGL 2.0 two-sided StencilMask */ +static void nv50StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK, 1); + OUT_RING_CACHE(mask); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK, 1); + OUT_RING_CACHE(mask); + } +} + +/** OpenGL 2.0 two-sided StencilOp */ +static void nv50StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, + GLenum zfail, GLenum zpass) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL, 3); + OUT_RING_CACHE(fail); + OUT_RING_CACHE(zfail); + OUT_RING_CACHE(zpass); + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + BEGIN_RING_CACHE(NvSub3D, NV50_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL, 3); + OUT_RING_CACHE(fail); + OUT_RING_CACHE(zfail); + OUT_RING_CACHE(zpass); + } +} + +/** Control the generation of texture coordinates */ +void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname, + const GLfloat *params); +/** Set texture environment parameters */ +void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *param); +/** Set texture parameters */ +void (*TexParameter)(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params); + +static void nv50TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat) +{ + /* Only with shaders */ +} + +static void nv50WindowMoved(nouveauContextPtr nmesa) +{ + GLcontext *ctx = nmesa->glCtx; + GLfloat *v = nmesa->viewport.m; + GLuint w = ctx->Viewport.Width; + GLuint h = ctx->Viewport.Height; + GLuint x = ctx->Viewport.X + nmesa->drawX; + GLuint y = ctx->Viewport.Y + nmesa->drawY; + int i; + + BEGIN_RING_CACHE(NvSub3D, + NV50_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(0), 2); + OUT_RING_CACHE((8191 << 16) | 0); + OUT_RING_CACHE((8191 << 16) | 0); + for (i=1; i<8; i++) { + BEGIN_RING_CACHE(NvSub3D, + NV50_TCL_PRIMITIVE_3D_VIEWPORT_CLIP_HORIZ(i), 2); + OUT_RING_CACHE(0); + OUT_RING_CACHE(0); + } + + ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); +} + +static GLboolean nv50InitCard(nouveauContextPtr nmesa) +{ + int i,j; + + nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D); + + BEGIN_RING_SIZE(NvSub3D, 0x1558, 1); + OUT_RING(1); + + BEGIN_RING_SIZE(NvSub3D, NV50_TCL_PRIMITIVE_3D_SET_OBJECT_1(0), 8); + for (i=0; i<8; i++) { + OUT_RING(NvDmaFB); + } + + BEGIN_RING_SIZE(NvSub3D, NV50_TCL_PRIMITIVE_3D_SET_OBJECT_0(0), 12); + for (i=0; i<12; i++) { + OUT_RING(NvDmaFB); + } + + BEGIN_RING_SIZE(NvSub3D, 0x121c, 1); + OUT_RING(1); + + for (i=0; i<8; i++) { + BEGIN_RING_SIZE(NvSub3D, 0x0200 + (i*0x20), 5); + for (j=0; j<5; j++) { + OUT_RING(0); + } + } + + BEGIN_RING_SIZE(NvSub3D, 0x0fe0, 5); + OUT_RING(0); + OUT_RING(0); + OUT_RING(0x16); + OUT_RING(0); + OUT_RING(0); + + return GL_FALSE; +} + +static GLboolean nv50BindBuffers(nouveauContextPtr nmesa, int num_color, + nouveau_renderbuffer **color, + nouveau_renderbuffer *depth) +{ + return GL_FALSE; +} + +void nv50InitStateFuncs(GLcontext *ctx, struct dd_function_table *func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + func->AlphaFunc = nv50AlphaFunc; + func->BlendColor = nv50BlendColor; + func->BlendEquationSeparate = nv50BlendEquationSeparate; + func->BlendFuncSeparate = nv50BlendFuncSeparate; + func->Clear = nv50Clear; + func->ClearColor = nv50ClearColor; + func->ClearDepth = nv50ClearDepth; + func->ClearStencil = nv50ClearStencil; + func->ClipPlane = nv50ClipPlane; + func->ColorMask = nv50ColorMask; + func->ColorMaterial = nv50ColorMaterial; + func->CullFace = nv50CullFace; + func->FrontFace = nv50FrontFace; + func->DepthFunc = nv50DepthFunc; + func->DepthMask = nv50DepthMask; + func->DepthRange = nv50DepthRange; + func->Enable = nv50Enable; + func->Fogfv = nv50Fogfv; + func->Hint = nv50Hint; + func->Lightfv = nv50Lightfv; +/* func->LightModelfv = nv50LightModelfv; */ + func->LineStipple = nv50LineStipple; + func->LineWidth = nv50LineWidth; + func->LogicOpcode = nv50LogicOpcode; + func->PointParameterfv = nv50PointParameterfv; + func->PointSize = nv50PointSize; + func->PolygonMode = nv50PolygonMode; + func->PolygonOffset = nv50PolygonOffset; + func->PolygonStipple = nv50PolygonStipple; +/* func->ReadBuffer = nv50ReadBuffer; */ +/* func->RenderMode = nv50RenderMode; */ + func->Scissor = nv50Scissor; + func->ShadeModel = nv50ShadeModel; + func->StencilFuncSeparate = nv50StencilFuncSeparate; + func->StencilMaskSeparate = nv50StencilMaskSeparate; + func->StencilOpSeparate = nv50StencilOpSeparate; +/* func->TexGen = nv50TexGen; */ +/* func->TexParameter = nv50TexParameter; */ + func->TextureMatrix = nv50TextureMatrix; + + nmesa->hw_func.InitCard = nv50InitCard; + nmesa->hw_func.BindBuffers = nv50BindBuffers; + nmesa->hw_func.WindowMoved = nv50WindowMoved; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/r300/r300_emit.c b/dist/Mesa/src/mesa/drivers/dri/r300/r300_emit.c new file mode 100644 index 000000000..2c26069f9 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/r300/r300_emit.c @@ -0,0 +1,627 @@ +/* +Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. + +The Weather Channel (TM) funded Tungsten Graphics to develop the +initial release of the Radeon 8500 driver under the XFree86 license. +This notice must be preserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/** + * \file + * + * \author Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "mtypes.h" +#include "colormac.h" +#include "imports.h" +#include "macros.h" +#include "image.h" + +#include "swrast_setup/swrast_setup.h" +#include "math/m_translate.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +#include "r300_context.h" +#include "radeon_ioctl.h" +#include "r300_state.h" +#include "r300_emit.h" +#include "r300_ioctl.h" + +#ifdef USER_BUFFERS +#include "r300_mem.h" +#endif + +#if SWIZZLE_X != R300_INPUT_ROUTE_SELECT_X || \ + SWIZZLE_Y != R300_INPUT_ROUTE_SELECT_Y || \ + SWIZZLE_Z != R300_INPUT_ROUTE_SELECT_Z || \ + SWIZZLE_W != R300_INPUT_ROUTE_SELECT_W || \ + SWIZZLE_ZERO != R300_INPUT_ROUTE_SELECT_ZERO || \ + SWIZZLE_ONE != R300_INPUT_ROUTE_SELECT_ONE +#error Cannot change these! +#endif + +#define DEBUG_ALL DEBUG_VERTS + +#if defined(USE_X86_ASM) +#define COPY_DWORDS( dst, src, nr ) \ +do { \ + int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \ + : "0" (nr), \ + "D" ((long)dst), \ + "S" ((long)src) ); \ +} while (0) +#else +#define COPY_DWORDS( dst, src, nr ) \ +do { \ + int j; \ + for ( j = 0 ; j < nr ; j++ ) \ + dst[j] = ((int *)src)[j]; \ + dst += nr; \ +} while (0) +#endif + +static void r300EmitVec4(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid * data, int stride, int count) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 4) + COPY_DWORDS(out, data, count); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out++; + data += stride; + } +} + +static void r300EmitVec8(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid * data, int stride, int count) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 8) + COPY_DWORDS(out, data, count * 2); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data + 4); + out += 2; + data += stride; + } +} + +static void r300EmitVec12(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid * data, int stride, int count) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d out %p data %p\n", + __FUNCTION__, count, stride, (void *)out, (void *)data); + + if (stride == 12) + COPY_DWORDS(out, data, count * 3); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data + 4); + out[2] = *(int *)(data + 8); + out += 3; + data += stride; + } +} + +static void r300EmitVec16(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid * data, int stride, int count) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 16) + COPY_DWORDS(out, data, count * 4); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data + 4); + out[2] = *(int *)(data + 8); + out[3] = *(int *)(data + 12); + out += 4; + data += stride; + } +} + +static void r300EmitVec(GLcontext * ctx, + struct r300_dma_region *rvb, + GLvoid * data, int size, int stride, int count) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d size %d stride %d\n", + __FUNCTION__, count, size, stride); + + /* Gets triggered when playing with future_hw_tcl_on ... */ + //assert(!rvb->buf); + + if (stride == 0) { + r300AllocDmaRegion(rmesa, rvb, size * 4, 4); + count = 1; + rvb->aos_offset = GET_START(rvb); + rvb->aos_stride = 0; + } else { + r300AllocDmaRegion(rmesa, rvb, size * count * 4, 4); /* alignment? */ + rvb->aos_offset = GET_START(rvb); + rvb->aos_stride = size; + } + + /* Emit the data + */ + switch (size) { + case 1: + r300EmitVec4(ctx, rvb, data, stride, count); + break; + case 2: + r300EmitVec8(ctx, rvb, data, stride, count); + break; + case 3: + r300EmitVec12(ctx, rvb, data, stride, count); + break; + case 4: + r300EmitVec16(ctx, rvb, data, stride, count); + break; + default: + assert(0); + _mesa_exit(-1); + break; + } + +} + +static GLuint t_type(struct dt *dt) +{ + switch (dt->type) { + case GL_UNSIGNED_BYTE: + return AOS_FORMAT_UBYTE; + case GL_SHORT: + return AOS_FORMAT_USHORT; + case GL_FLOAT: + return AOS_FORMAT_FLOAT; + default: + assert(0); + break; + } + + return AOS_FORMAT_FLOAT; +} + +static GLuint t_vir0_size(struct dt *dt) +{ + switch (dt->type) { + case GL_UNSIGNED_BYTE: + return 4; + case GL_SHORT: + return 7; + case GL_FLOAT: + return dt->size - 1; + default: + assert(0); + break; + } + + return 0; +} + +static GLuint t_aos_size(struct dt *dt) +{ + switch (dt->type) { + case GL_UNSIGNED_BYTE: + return 1; + case GL_SHORT: + return 2; + case GL_FLOAT: + return dt->size; + default: + assert(0); + break; + } + + return 0; +} + +static GLuint t_vir0(uint32_t * dst, struct dt *dt, int *inputs, + GLint * tab, GLuint nr) +{ + GLuint i, dw; + + for (i = 0; i + 1 < nr; i += 2) { + dw = t_vir0_size(&dt[tab[i]]) | (inputs[tab[i]] << 8) | + (t_type(&dt[tab[i]]) << 14); + dw |= + (t_vir0_size(&dt[tab[i + 1]]) | + (inputs[tab[i + 1]] << 8) | (t_type(&dt[tab[i + 1]]) + << 14)) << 16; + + if (i + 2 == nr) { + dw |= (1 << (13 + 16)); + } + dst[i >> 1] = dw; + } + + if (nr & 1) { + dw = t_vir0_size(&dt[tab[nr - 1]]) | (inputs[tab[nr - 1]] + << 8) | + (t_type(&dt[tab[nr - 1]]) << 14); + dw |= 1 << 13; + + dst[nr >> 1] = dw; + } + + return (nr + 1) >> 1; +} + +static GLuint t_swizzle(int swizzle[4]) +{ + return (swizzle[0] << R300_INPUT_ROUTE_X_SHIFT) | + (swizzle[1] << R300_INPUT_ROUTE_Y_SHIFT) | + (swizzle[2] << R300_INPUT_ROUTE_Z_SHIFT) | + (swizzle[3] << R300_INPUT_ROUTE_W_SHIFT); +} + +static GLuint t_vir1(uint32_t * dst, int swizzle[][4], GLuint nr) +{ + GLuint i; + + for (i = 0; i + 1 < nr; i += 2) { + dst[i >> 1] = t_swizzle(swizzle[i]) | R300_INPUT_ROUTE_ENABLE; + dst[i >> 1] |= + (t_swizzle(swizzle[i + 1]) | R300_INPUT_ROUTE_ENABLE) + << 16; + } + + if (nr & 1) + dst[nr >> 1] = + t_swizzle(swizzle[nr - 1]) | R300_INPUT_ROUTE_ENABLE; + + return (nr + 1) >> 1; +} + +static GLuint t_emit_size(struct dt *dt) +{ + return dt->size; +} + +static GLuint t_vic(GLcontext * ctx, GLuint InputsRead) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + GLuint i, vic_1 = 0; + + if (InputsRead & (1 << VERT_ATTRIB_POS)) + vic_1 |= R300_INPUT_CNTL_POS; + + if (InputsRead & (1 << VERT_ATTRIB_NORMAL)) + vic_1 |= R300_INPUT_CNTL_NORMAL; + + if (InputsRead & (1 << VERT_ATTRIB_COLOR0)) + vic_1 |= R300_INPUT_CNTL_COLOR; + + r300->state.texture.tc_count = 0; + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (InputsRead & (1 << (VERT_ATTRIB_TEX0 + i))) { + r300->state.texture.tc_count++; + vic_1 |= R300_INPUT_CNTL_TC0 << i; + } + + return vic_1; +} + +/* Emit vertex data to GART memory + * Route inputs to the vertex processor + * This function should never return R300_FALLBACK_TCL when using software tcl. + */ + +int r300EmitArrays(GLcontext * ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + r300ContextPtr r300 = rmesa; + struct radeon_vertex_buffer *VB = &rmesa->state.VB; + GLuint nr; + GLuint count = VB->Count; + GLuint i; + GLuint InputsRead = 0, OutputsWritten = 0; + int *inputs = NULL; + int vir_inputs[VERT_ATTRIB_MAX]; + GLint tab[VERT_ATTRIB_MAX]; + int swizzle[VERT_ATTRIB_MAX][4]; + + if (hw_tcl_on) { + struct r300_vertex_program *prog = + (struct r300_vertex_program *) + CURRENT_VERTEX_SHADER(ctx); + inputs = prog->inputs; + InputsRead = CURRENT_VERTEX_SHADER(ctx)->key.InputsRead; + OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->key.OutputsWritten; + } else { + DECLARE_RENDERINPUTS(inputs_bitset); + inputs = r300->state.sw_tcl_inputs; + + RENDERINPUTS_COPY(inputs_bitset, + TNL_CONTEXT(ctx)->render_inputs_bitset); + + assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_POS)); + InputsRead |= 1 << VERT_ATTRIB_POS; + OutputsWritten |= 1 << VERT_RESULT_HPOS; + + assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_NORMAL) + == 0); + + assert(RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_COLOR0)); + InputsRead |= 1 << VERT_ATTRIB_COLOR0; + OutputsWritten |= 1 << VERT_RESULT_COL0; + + if (RENDERINPUTS_TEST(inputs_bitset, _TNL_ATTRIB_COLOR1)) { + InputsRead |= 1 << VERT_ATTRIB_COLOR1; + OutputsWritten |= 1 << VERT_RESULT_COL1; + } + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (RENDERINPUTS_TEST + (inputs_bitset, _TNL_ATTRIB_TEX(i))) { + InputsRead |= 1 << (VERT_ATTRIB_TEX0 + i); + OutputsWritten |= 1 << (VERT_RESULT_TEX0 + i); + } + + for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) + if (InputsRead & (1 << i)) + inputs[i] = nr++; + else + inputs[i] = -1; + + if (! + (r300->radeon.radeonScreen-> + chip_flags & RADEON_CHIPSET_TCL)) { + /* Fixed, apply to vir0 only */ + memcpy(vir_inputs, inputs, + VERT_ATTRIB_MAX * sizeof(int)); + inputs = vir_inputs; + + if (InputsRead & VERT_ATTRIB_POS) + inputs[VERT_ATTRIB_POS] = 0; + + if (InputsRead & (1 << VERT_ATTRIB_COLOR0)) + inputs[VERT_ATTRIB_COLOR0] = 2; + + if (InputsRead & (1 << VERT_ATTRIB_COLOR1)) + inputs[VERT_ATTRIB_COLOR1] = 3; + + for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) + if (InputsRead & (1 << i)) + inputs[i] = 6 + (i - VERT_ATTRIB_TEX0); + } + + RENDERINPUTS_COPY(rmesa->state.render_inputs_bitset, + inputs_bitset); + } + assert(InputsRead); + assert(OutputsWritten); + + for (i = 0, nr = 0; i < VERT_ATTRIB_MAX; i++) + if (InputsRead & (1 << i)) + tab[nr++] = i; + + if (nr > R300_MAX_AOS_ARRAYS) + return R300_FALLBACK_TCL; + + for (i = 0; i < nr; i++) { + int ci; + int comp_size, fix, found = 0; + + swizzle[i][0] = SWIZZLE_ZERO; + swizzle[i][1] = SWIZZLE_ZERO; + swizzle[i][2] = SWIZZLE_ZERO; + swizzle[i][3] = SWIZZLE_ONE; + + for (ci = 0; ci < VB->AttribPtr[tab[i]].size; ci++) + swizzle[i][ci] = ci; + +#if MESA_BIG_ENDIAN +#define SWAP_INT(a, b) do { \ + int __temp; \ + __temp = a;\ + a = b; \ + b = __temp; \ +} while (0) + + if (VB->AttribPtr[tab[i]].type == GL_UNSIGNED_BYTE) { + SWAP_INT(swizzle[i][0], swizzle[i][3]); + SWAP_INT(swizzle[i][1], swizzle[i][2]); + } +#endif /* MESA_BIG_ENDIAN */ + + if (r300IsGartMemory(rmesa, VB->AttribPtr[tab[i]].data, + /*(count-1)*stride */ 4)) { + if (VB->AttribPtr[tab[i]].stride % 4) + return R300_FALLBACK_TCL; + + rmesa->state.aos[i].address = + VB->AttribPtr[tab[i]].data; + rmesa->state.aos[i].start = 0; + rmesa->state.aos[i].aos_offset = + r300GartOffsetFromVirtual(rmesa, + VB-> + AttribPtr[tab[i]].data); + rmesa->state.aos[i].aos_stride = + VB->AttribPtr[tab[i]].stride / 4; + + rmesa->state.aos[i].aos_size = + t_emit_size(&VB->AttribPtr[tab[i]]); + } else { + /* TODO: r300EmitVec can only handle 4 byte vectors */ + if (VB->AttribPtr[tab[i]].type != GL_FLOAT) + return R300_FALLBACK_TCL; + + r300EmitVec(ctx, &rmesa->state.aos[i], + VB->AttribPtr[tab[i]].data, + t_emit_size(&VB->AttribPtr[tab[i]]), + VB->AttribPtr[tab[i]].stride, count); + } + + rmesa->state.aos[i].aos_size = + t_aos_size(&VB->AttribPtr[tab[i]]); + + comp_size = _mesa_sizeof_type(VB->AttribPtr[tab[i]].type); + + for (fix = 0; fix <= 4 - VB->AttribPtr[tab[i]].size; fix++) { + if ((rmesa->state.aos[i].aos_offset - + comp_size * fix) % 4) + continue; + + found = 1; + break; + } + + if (found) { + if (fix > 0) { + WARN_ONCE("Feeling lucky?\n"); + } + + rmesa->state.aos[i].aos_offset -= comp_size * fix; + + for (ci = 0; ci < VB->AttribPtr[tab[i]].size; ci++) + swizzle[i][ci] += fix; + } else { + WARN_ONCE + ("Cannot handle offset %x with stride %d, comp %d\n", + rmesa->state.aos[i].aos_offset, + rmesa->state.aos[i].aos_stride, + VB->AttribPtr[tab[i]].size); + return R300_FALLBACK_TCL; + } + } + + /* setup INPUT_ROUTE */ + R300_STATECHANGE(r300, vir[0]); + ((drm_r300_cmd_header_t *) r300->hw.vir[0].cmd)->packet0.count = + t_vir0(&r300->hw.vir[0].cmd[R300_VIR_CNTL_0], VB->AttribPtr, + inputs, tab, nr); + + R300_STATECHANGE(r300, vir[1]); + ((drm_r300_cmd_header_t *) r300->hw.vir[1].cmd)->packet0.count = + t_vir1(&r300->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle, nr); + + /* Set up input_cntl */ + /* I don't think this is needed for vertex buffers, but it doesn't hurt anything */ + R300_STATECHANGE(r300, vic); + r300->hw.vic.cmd[R300_VIC_CNTL_0] = 0x5555; /* Hard coded value, no idea what it means */ + r300->hw.vic.cmd[R300_VIC_CNTL_1] = t_vic(ctx, InputsRead); + + /* Stage 3: VAP output */ + + R300_STATECHANGE(r300, vof); + + r300->hw.vof.cmd[R300_VOF_CNTL_0] = 0; + r300->hw.vof.cmd[R300_VOF_CNTL_1] = 0; + + if (OutputsWritten & (1 << VERT_RESULT_HPOS)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= + R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; + + if (OutputsWritten & (1 << VERT_RESULT_COL0)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= + R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; + + if (OutputsWritten & (1 << VERT_RESULT_COL1)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= + R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT; + + /*if(OutputsWritten & (1 << VERT_RESULT_BFC0)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT; + + if(OutputsWritten & (1 << VERT_RESULT_BFC1)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT; */ + //if(OutputsWritten & (1 << VERT_RESULT_FOGC)) + + if (OutputsWritten & (1 << VERT_RESULT_PSIZ)) + r300->hw.vof.cmd[R300_VOF_CNTL_0] |= + R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (OutputsWritten & (1 << (VERT_RESULT_TEX0 + i))) + r300->hw.vof.cmd[R300_VOF_CNTL_1] |= (4 << (3 * i)); + + rmesa->state.aos_count = nr; + + return R300_FALLBACK_NONE; +} + +#ifdef USER_BUFFERS +void r300UseArrays(GLcontext * ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + int i; + + if (rmesa->state.elt_dma.buf) + r300_mem_use(rmesa, rmesa->state.elt_dma.buf->id); + + for (i = 0; i < rmesa->state.aos_count; i++) { + if (rmesa->state.aos[i].buf) + r300_mem_use(rmesa, rmesa->state.aos[i].buf->id); + } +} +#endif + +void r300ReleaseArrays(GLcontext * ctx) +{ + r300ContextPtr rmesa = R300_CONTEXT(ctx); + int i; + + r300ReleaseDmaRegion(rmesa, &rmesa->state.elt_dma, __FUNCTION__); + for (i = 0; i < rmesa->state.aos_count; i++) { + r300ReleaseDmaRegion(rmesa, &rmesa->state.aos[i], __FUNCTION__); + } +} diff --git a/dist/Mesa/src/mesa/drivers/dri/r300/r300_mem.c b/dist/Mesa/src/mesa/drivers/dri/r300/r300_mem.c new file mode 100644 index 000000000..f8f9d4fcd --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/r300/r300_mem.c @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2005 Aapo Tahkola. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * \file + * + * \author Aapo Tahkola <aet@rasterburn.org> + */ + +#include <unistd.h> + +#include "r300_context.h" +#include "r300_cmdbuf.h" +#include "r300_ioctl.h" +#include "r300_mem.h" +#include "radeon_ioctl.h" + +#ifdef USER_BUFFERS + +static void resize_u_list(r300ContextPtr rmesa) +{ + void *temp; + int nsize; + + temp = rmesa->rmm->u_list; + nsize = rmesa->rmm->u_size * 2; + + rmesa->rmm->u_list = _mesa_malloc(nsize * sizeof(*rmesa->rmm->u_list)); + _mesa_memset(rmesa->rmm->u_list, 0, + nsize * sizeof(*rmesa->rmm->u_list)); + + if (temp) { + r300FlushCmdBuf(rmesa, __FUNCTION__); + + _mesa_memcpy(rmesa->rmm->u_list, temp, + rmesa->rmm->u_size * sizeof(*rmesa->rmm->u_list)); + _mesa_free(temp); + } + + rmesa->rmm->u_size = nsize; +} + +void r300_mem_init(r300ContextPtr rmesa) +{ + rmesa->rmm = malloc(sizeof(struct r300_memory_manager)); + memset(rmesa->rmm, 0, sizeof(struct r300_memory_manager)); + + rmesa->rmm->u_size = 128; + resize_u_list(rmesa); +} + +void r300_mem_destroy(r300ContextPtr rmesa) +{ + _mesa_free(rmesa->rmm->u_list); + rmesa->rmm->u_list = NULL; + + _mesa_free(rmesa->rmm); + rmesa->rmm = NULL; +} + +void *r300_mem_ptr(r300ContextPtr rmesa, int id) +{ + assert(id <= rmesa->rmm->u_last); + return rmesa->rmm->u_list[id].ptr; +} + +int r300_mem_find(r300ContextPtr rmesa, void *ptr) +{ + int i; + + for (i = 1; i < rmesa->rmm->u_size + 1; i++) + if (rmesa->rmm->u_list[i].ptr && + ptr >= rmesa->rmm->u_list[i].ptr && + ptr < + rmesa->rmm->u_list[i].ptr + rmesa->rmm->u_list[i].size) + break; + + if (i < rmesa->rmm->u_size + 1) + return i; + + fprintf(stderr, "%p failed\n", ptr); + return 0; +} + +//#define MM_DEBUG +int r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size) +{ + drm_radeon_mem_alloc_t alloc; + int offset = 0, ret; + int i, free = -1; + int done_age; + drm_radeon_mem_free_t memfree; + int tries = 0; + static int bytes_wasted = 0, allocated = 0; + + if (size < 4096) + bytes_wasted += 4096 - size; + + allocated += size; + +#if 0 + static int t = 0; + if (t != time(NULL)) { + t = time(NULL); + fprintf(stderr, "slots used %d, wasted %d kb, allocated %d\n", + rmesa->rmm->u_last, bytes_wasted / 1024, + allocated / 1024); + } +#endif + + memfree.region = RADEON_MEM_REGION_GART; + + again: + + done_age = radeonGetAge((radeonContextPtr) rmesa); + + if (rmesa->rmm->u_last + 1 >= rmesa->rmm->u_size) + resize_u_list(rmesa); + + for (i = rmesa->rmm->u_last + 1; i > 0; i--) { + if (rmesa->rmm->u_list[i].ptr == NULL) { + free = i; + continue; + } + + if (rmesa->rmm->u_list[i].h_pending == 0 && + rmesa->rmm->u_list[i].pending + && rmesa->rmm->u_list[i].age <= done_age) { + memfree.region_offset = + (char *)rmesa->rmm->u_list[i].ptr - + (char *)rmesa->radeon.radeonScreen->gartTextures. + map; + + ret = + drmCommandWrite(rmesa->radeon.radeonScreen-> + driScreen->fd, DRM_RADEON_FREE, + &memfree, sizeof(memfree)); + + if (ret) { + fprintf(stderr, "Failed to free at %p\n", + rmesa->rmm->u_list[i].ptr); + fprintf(stderr, "ret = %s\n", strerror(-ret)); + exit(1); + } else { +#ifdef MM_DEBUG + fprintf(stderr, "really freed %d at age %x\n", + i, + radeonGetAge((radeonContextPtr) rmesa)); +#endif + if (i == rmesa->rmm->u_last) + rmesa->rmm->u_last--; + + if (rmesa->rmm->u_list[i].size < 4096) + bytes_wasted -= + 4096 - rmesa->rmm->u_list[i].size; + + allocated -= rmesa->rmm->u_list[i].size; + rmesa->rmm->u_list[i].pending = 0; + rmesa->rmm->u_list[i].ptr = NULL; + free = i; + } + } + } + rmesa->rmm->u_head = i; + + if (free == -1) { + WARN_ONCE("Ran out of slots!\n"); + //usleep(100); + r300FlushCmdBuf(rmesa, __FUNCTION__); + tries++; + if (tries > 100) { + WARN_ONCE("Ran out of slots!\n"); + exit(1); + } + goto again; + } + + alloc.region = RADEON_MEM_REGION_GART; + alloc.alignment = alignment; + alloc.size = size; + alloc.region_offset = &offset; + + ret = + drmCommandWriteRead(rmesa->radeon.dri.fd, DRM_RADEON_ALLOC, &alloc, + sizeof(alloc)); + if (ret) { +#if 0 + WARN_ONCE("Ran out of mem!\n"); + r300FlushCmdBuf(rmesa, __FUNCTION__); + //usleep(100); + tries2++; + tries = 0; + if (tries2 > 100) { + WARN_ONCE("Ran out of GART memory!\n"); + exit(1); + } + goto again; +#else + WARN_ONCE + ("Ran out of GART memory (for %d)!\nPlease consider adjusting GARTSize option.\n", + size); + return 0; +#endif + } + + i = free; + + if (i > rmesa->rmm->u_last) + rmesa->rmm->u_last = i; + + rmesa->rmm->u_list[i].ptr = + ((GLubyte *) rmesa->radeon.radeonScreen->gartTextures.map) + offset; + rmesa->rmm->u_list[i].size = size; + rmesa->rmm->u_list[i].age = 0; + //fprintf(stderr, "alloc %p at id %d\n", rmesa->rmm->u_list[i].ptr, i); + +#ifdef MM_DEBUG + fprintf(stderr, "allocated %d at age %x\n", i, + radeonGetAge((radeonContextPtr) rmesa)); +#endif + + return i; +} + +void r300_mem_use(r300ContextPtr rmesa, int id) +{ + uint64_t ull; +#ifdef MM_DEBUG + fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, + radeonGetAge((radeonContextPtr) rmesa)); +#endif + drm_r300_cmd_header_t *cmd; + + assert(id <= rmesa->rmm->u_last); + + if (id == 0) + return; + + cmd = + (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa, + 2 + sizeof(ull) / 4, + __FUNCTION__); + cmd[0].scratch.cmd_type = R300_CMD_SCRATCH; + cmd[0].scratch.reg = R300_MEM_SCRATCH; + cmd[0].scratch.n_bufs = 1; + cmd[0].scratch.flags = 0; + cmd++; + + ull = (uint64_t) (intptr_t) & rmesa->rmm->u_list[id].age; + _mesa_memcpy(cmd, &ull, sizeof(ull)); + cmd += sizeof(ull) / 4; + + cmd[0].u = /*id */ 0; + + LOCK_HARDWARE(&rmesa->radeon); /* Protect from DRM. */ + rmesa->rmm->u_list[id].h_pending++; + UNLOCK_HARDWARE(&rmesa->radeon); +} + +unsigned long r300_mem_offset(r300ContextPtr rmesa, int id) +{ + unsigned long offset; + + assert(id <= rmesa->rmm->u_last); + + offset = (char *)rmesa->rmm->u_list[id].ptr - + (char *)rmesa->radeon.radeonScreen->gartTextures.map; + offset += rmesa->radeon.radeonScreen->gart_texture_offset; + + return offset; +} + +void *r300_mem_map(r300ContextPtr rmesa, int id, int access) +{ +#ifdef MM_DEBUG + fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, + radeonGetAge((radeonContextPtr) rmesa)); +#endif + void *ptr; + int tries = 0; + + assert(id <= rmesa->rmm->u_last); + + if (access == R300_MEM_R) { + + if (rmesa->rmm->u_list[id].mapped == 1) + WARN_ONCE("buffer %d already mapped\n", id); + + rmesa->rmm->u_list[id].mapped = 1; + ptr = r300_mem_ptr(rmesa, id); + + return ptr; + } + + if (rmesa->rmm->u_list[id].h_pending) + r300FlushCmdBuf(rmesa, __FUNCTION__); + + if (rmesa->rmm->u_list[id].h_pending) { + return NULL; + } + + while (rmesa->rmm->u_list[id].age > + radeonGetAge((radeonContextPtr) rmesa) && tries++ < 1000) + usleep(10); + + if (tries >= 1000) { + fprintf(stderr, "Idling failed (%x vs %x)\n", + rmesa->rmm->u_list[id].age, + radeonGetAge((radeonContextPtr) rmesa)); + return NULL; + } + + if (rmesa->rmm->u_list[id].mapped == 1) + WARN_ONCE("buffer %d already mapped\n", id); + + rmesa->rmm->u_list[id].mapped = 1; + ptr = r300_mem_ptr(rmesa, id); + + return ptr; +} + +void r300_mem_unmap(r300ContextPtr rmesa, int id) +{ +#ifdef MM_DEBUG + fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, + radeonGetAge((radeonContextPtr) rmesa)); +#endif + + assert(id <= rmesa->rmm->u_last); + + if (rmesa->rmm->u_list[id].mapped == 0) + WARN_ONCE("buffer %d not mapped\n", id); + + rmesa->rmm->u_list[id].mapped = 0; +} + +void r300_mem_free(r300ContextPtr rmesa, int id) +{ +#ifdef MM_DEBUG + fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, + radeonGetAge((radeonContextPtr) rmesa)); +#endif + + assert(id <= rmesa->rmm->u_last); + + if (id == 0) + return; + + if (rmesa->rmm->u_list[id].ptr == NULL) { + WARN_ONCE("Not allocated!\n"); + return; + } + + if (rmesa->rmm->u_list[id].pending) { + WARN_ONCE("%p already pended!\n", rmesa->rmm->u_list[id].ptr); + return; + } + + rmesa->rmm->u_list[id].pending = 1; +} +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/r300/r300_mem.h b/dist/Mesa/src/mesa/drivers/dri/r300/r300_mem.h new file mode 100644 index 000000000..625a7f6d8 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/r300/r300_mem.h @@ -0,0 +1,37 @@ +#ifndef __R300_MEM_H__ +#define __R300_MEM_H__ + +//#define R300_MEM_PDL 0 +#define R300_MEM_UL 1 + +#define R300_MEM_R 1 +#define R300_MEM_W 2 +#define R300_MEM_RW (R300_MEM_R | R300_MEM_W) + +#define R300_MEM_SCRATCH 2 + +struct r300_memory_manager { + struct { + void *ptr; + uint32_t size; + uint32_t age; + uint32_t h_pending; + int pending; + int mapped; + } *u_list; + int u_head, u_size, u_last; + +}; + +extern void r300_mem_init(r300ContextPtr rmesa); +extern void r300_mem_destroy(r300ContextPtr rmesa); +extern void *r300_mem_ptr(r300ContextPtr rmesa, int id); +extern int r300_mem_find(r300ContextPtr rmesa, void *ptr); +extern int r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size); +extern void r300_mem_use(r300ContextPtr rmesa, int id); +extern unsigned long r300_mem_offset(r300ContextPtr rmesa, int id); +extern void *r300_mem_map(r300ContextPtr rmesa, int id, int access); +extern void r300_mem_unmap(r300ContextPtr rmesa, int id); +extern void r300_mem_free(r300ContextPtr rmesa, int id); + +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/r300/r300_vertprog.c b/dist/Mesa/src/mesa/drivers/dri/r300/r300_vertprog.c new file mode 100644 index 000000000..1d90ade2e --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/r300/r300_vertprog.c @@ -0,0 +1,1305 @@ +/************************************************************************** + +Copyright (C) 2005 Aapo Tahkola. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/** + * \file + * + * \author Aapo Tahkola <aet@rasterburn.org> + */ + +#include "glheader.h" +#include "macros.h" +#include "enums.h" +#include "program.h" +#include "shader/prog_instruction.h" +#include "shader/prog_parameter.h" +#include "shader/prog_statevars.h" +#include "tnl/tnl.h" + +#include "r300_context.h" + +#if SWIZZLE_X != VSF_IN_COMPONENT_X || \ + SWIZZLE_Y != VSF_IN_COMPONENT_Y || \ + SWIZZLE_Z != VSF_IN_COMPONENT_Z || \ + SWIZZLE_W != VSF_IN_COMPONENT_W || \ + SWIZZLE_ZERO != VSF_IN_COMPONENT_ZERO || \ + SWIZZLE_ONE != VSF_IN_COMPONENT_ONE || \ + WRITEMASK_X != VSF_FLAG_X || \ + WRITEMASK_Y != VSF_FLAG_Y || \ + WRITEMASK_Z != VSF_FLAG_Z || \ + WRITEMASK_W != VSF_FLAG_W +#error Cannot change these! +#endif + +#define SCALAR_FLAG (1<<31) +#define FLAG_MASK (1<<31) +#define OP_MASK (0xf) /* we are unlikely to have more than 15 */ +#define OPN(operator, ip) {#operator, OPCODE_##operator, ip} + +static struct { + char *name; + int opcode; + unsigned long ip; /* number of input operands and flags */ +} op_names[] = { + /* *INDENT-OFF* */ + OPN(ABS, 1), + OPN(ADD, 2), + OPN(ARL, 1 | SCALAR_FLAG), + OPN(DP3, 2), + OPN(DP4, 2), + OPN(DPH, 2), + OPN(DST, 2), + OPN(EX2, 1 | SCALAR_FLAG), + OPN(EXP, 1 | SCALAR_FLAG), + OPN(FLR, 1), + OPN(FRC, 1), + OPN(LG2, 1 | SCALAR_FLAG), + OPN(LIT, 1), + OPN(LOG, 1 | SCALAR_FLAG), + OPN(MAD, 3), + OPN(MAX, 2), + OPN(MIN, 2), + OPN(MOV, 1), + OPN(MUL, 2), + OPN(POW, 2 | SCALAR_FLAG), + OPN(RCP, 1 | SCALAR_FLAG), + OPN(RSQ, 1 | SCALAR_FLAG), + OPN(SGE, 2), + OPN(SLT, 2), + OPN(SUB, 2), + OPN(SWZ, 1), + OPN(XPD, 2), + OPN(RCC, 0), //extra + OPN(PRINT, 0), + OPN(END, 0) + /* *INDENT-ON* */ +}; + +#undef OPN + +int r300VertexProgUpdateParams(GLcontext * ctx, + struct r300_vertex_program_cont *vp, float *dst) +{ + int pi; + struct gl_vertex_program *mesa_vp = &vp->mesa_program; + float *dst_o = dst; + struct gl_program_parameter_list *paramList; + + if (mesa_vp->IsNVProgram) { + _mesa_load_tracked_matrices(ctx); + + for (pi = 0; pi < MAX_NV_VERTEX_PROGRAM_PARAMS; pi++) { + *dst++ = ctx->VertexProgram.Parameters[pi][0]; + *dst++ = ctx->VertexProgram.Parameters[pi][1]; + *dst++ = ctx->VertexProgram.Parameters[pi][2]; + *dst++ = ctx->VertexProgram.Parameters[pi][3]; + } + return dst - dst_o; + } + + assert(mesa_vp->Base.Parameters); + _mesa_load_state_parameters(ctx, mesa_vp->Base.Parameters); + + if (mesa_vp->Base.Parameters->NumParameters * 4 > + VSF_MAX_FRAGMENT_LENGTH) { + fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__); + _mesa_exit(-1); + } + + paramList = mesa_vp->Base.Parameters; + for (pi = 0; pi < paramList->NumParameters; pi++) { + switch (paramList->Parameters[pi].Type) { + + case PROGRAM_STATE_VAR: + case PROGRAM_NAMED_PARAM: + //fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name); + case PROGRAM_CONSTANT: + *dst++ = paramList->ParameterValues[pi][0]; + *dst++ = paramList->ParameterValues[pi][1]; + *dst++ = paramList->ParameterValues[pi][2]; + *dst++ = paramList->ParameterValues[pi][3]; + break; + + default: + _mesa_problem(NULL, "Bad param type in %s", + __FUNCTION__); + } + + } + + return dst - dst_o; +} + +static unsigned long t_dst_mask(GLuint mask) +{ + /* WRITEMASK_* is equivalent to VSF_FLAG_* */ + return mask & VSF_FLAG_ALL; +} + +static unsigned long t_dst_class(enum register_file file) +{ + + switch (file) { + case PROGRAM_TEMPORARY: + return VSF_OUT_CLASS_TMP; + case PROGRAM_OUTPUT: + return VSF_OUT_CLASS_RESULT; + case PROGRAM_ADDRESS: + return VSF_OUT_CLASS_ADDR; + /* + case PROGRAM_INPUT: + case PROGRAM_LOCAL_PARAM: + case PROGRAM_ENV_PARAM: + case PROGRAM_NAMED_PARAM: + case PROGRAM_STATE_VAR: + case PROGRAM_WRITE_ONLY: + case PROGRAM_ADDRESS: + */ + default: + fprintf(stderr, "problem in %s", __FUNCTION__); + _mesa_exit(-1); + return -1; + } +} + +static unsigned long t_dst_index(struct r300_vertex_program *vp, + struct prog_dst_register *dst) +{ + if (dst->File == PROGRAM_OUTPUT) + return vp->outputs[dst->Index]; + + return dst->Index; +} + +static unsigned long t_src_class(enum register_file file) +{ + + switch (file) { + case PROGRAM_TEMPORARY: + return VSF_IN_CLASS_TMP; + + case PROGRAM_INPUT: + return VSF_IN_CLASS_ATTR; + + case PROGRAM_LOCAL_PARAM: + case PROGRAM_ENV_PARAM: + case PROGRAM_NAMED_PARAM: + case PROGRAM_STATE_VAR: + return VSF_IN_CLASS_PARAM; + /* + case PROGRAM_OUTPUT: + case PROGRAM_WRITE_ONLY: + case PROGRAM_ADDRESS: + */ + default: + fprintf(stderr, "problem in %s", __FUNCTION__); + _mesa_exit(-1); + return -1; + } +} + +static __inline unsigned long t_swizzle(GLubyte swizzle) +{ +/* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */ + return swizzle; +} + +#if 0 +static void vp_dump_inputs(struct r300_vertex_program *vp, char *caller) +{ + int i; + + if (vp == NULL) { + fprintf(stderr, "vp null in call to %s from %s\n", __FUNCTION__, + caller); + return; + } + + fprintf(stderr, "%s:<", caller); + for (i = 0; i < VERT_ATTRIB_MAX; i++) + fprintf(stderr, "%d ", vp->inputs[i]); + fprintf(stderr, ">\n"); + +} +#endif + +static unsigned long t_src_index(struct r300_vertex_program *vp, + struct prog_src_register *src) +{ + int i; + int max_reg = -1; + + if (src->File == PROGRAM_INPUT) { + if (vp->inputs[src->Index] != -1) + return vp->inputs[src->Index]; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + if (vp->inputs[i] > max_reg) + max_reg = vp->inputs[i]; + + vp->inputs[src->Index] = max_reg + 1; + + //vp_dump_inputs(vp, __FUNCTION__); + + return vp->inputs[src->Index]; + } else { + if (src->Index < 0) { + fprintf(stderr, + "negative offsets for indirect addressing do not work.\n"); + return 0; + } + return src->Index; + } +} + +static unsigned long t_src(struct r300_vertex_program *vp, + struct prog_src_register *src) +{ + /* src->NegateBase uses the NEGATE_ flags from program_instruction.h, + * which equal our VSF_FLAGS_ values, so it's safe to just pass it here. + */ + return MAKE_VSF_SOURCE(t_src_index(vp, src), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 1)), + t_swizzle(GET_SWZ(src->Swizzle, 2)), + t_swizzle(GET_SWZ(src->Swizzle, 3)), + t_src_class(src->File), + src->NegateBase) | (src->RelAddr << 4); +} + +static unsigned long t_src_scalar(struct r300_vertex_program *vp, + struct prog_src_register *src) +{ + + return MAKE_VSF_SOURCE(t_src_index(vp, src), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_swizzle(GET_SWZ(src->Swizzle, 0)), + t_src_class(src->File), + src-> + NegateBase ? VSF_FLAG_ALL : VSF_FLAG_NONE) | + (src->RelAddr << 4); +} + +static unsigned long t_opcode(enum prog_opcode opcode) +{ + + switch (opcode) { + /* *INDENT-OFF* */ + case OPCODE_ARL: return R300_VPI_OUT_OP_ARL; + case OPCODE_DST: return R300_VPI_OUT_OP_DST; + case OPCODE_EX2: return R300_VPI_OUT_OP_EX2; + case OPCODE_EXP: return R300_VPI_OUT_OP_EXP; + case OPCODE_FRC: return R300_VPI_OUT_OP_FRC; + case OPCODE_LG2: return R300_VPI_OUT_OP_LG2; + case OPCODE_LOG: return R300_VPI_OUT_OP_LOG; + case OPCODE_MAX: return R300_VPI_OUT_OP_MAX; + case OPCODE_MIN: return R300_VPI_OUT_OP_MIN; + case OPCODE_MUL: return R300_VPI_OUT_OP_MUL; + case OPCODE_RCP: return R300_VPI_OUT_OP_RCP; + case OPCODE_RSQ: return R300_VPI_OUT_OP_RSQ; + case OPCODE_SGE: return R300_VPI_OUT_OP_SGE; + case OPCODE_SLT: return R300_VPI_OUT_OP_SLT; + case OPCODE_DP4: return R300_VPI_OUT_OP_DOT; + /* *INDENT-ON* */ + + default: + fprintf(stderr, "%s: Should not be called with opcode %d!", + __FUNCTION__, opcode); + } + _mesa_exit(-1); + return 0; +} + +static unsigned long op_operands(enum prog_opcode opcode) +{ + int i; + + /* Can we trust mesas opcodes to be in order ? */ + for (i = 0; i < sizeof(op_names) / sizeof(*op_names); i++) + if (op_names[i].opcode == opcode) + return op_names[i].ip; + + fprintf(stderr, "op %d not found in op_names\n", opcode); + _mesa_exit(-1); + return 0; +} + +static GLboolean valid_dst(struct r300_vertex_program *vp, + struct prog_dst_register *dst) +{ + if (dst->File == PROGRAM_OUTPUT && vp->outputs[dst->Index] == -1) { + return GL_FALSE; + } else if (dst->File == PROGRAM_ADDRESS) { + assert(dst->Index == 0); + } + + return GL_TRUE; +} + +/* TODO: Get rid of t_src_class call */ +#define CMP_SRCS(a, b) ((a.RelAddr != b.RelAddr) || (a.Index != b.Index && \ + ((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \ + t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \ + (t_src_class(a.File) == VSF_IN_CLASS_ATTR && \ + t_src_class(b.File) == VSF_IN_CLASS_ATTR)))) \ + +#define ZERO_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \ + SWIZZLE_ZERO, SWIZZLE_ZERO, \ + SWIZZLE_ZERO, SWIZZLE_ZERO, \ + t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4)) + +#define ZERO_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \ + SWIZZLE_ZERO, SWIZZLE_ZERO, \ + SWIZZLE_ZERO, SWIZZLE_ZERO, \ + t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4)) + +#define ZERO_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \ + SWIZZLE_ZERO, SWIZZLE_ZERO, \ + SWIZZLE_ZERO, SWIZZLE_ZERO, \ + t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4)) + +#define ONE_SRC_0 (MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), \ + SWIZZLE_ONE, SWIZZLE_ONE, \ + SWIZZLE_ONE, SWIZZLE_ONE, \ + t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4)) + +#define ONE_SRC_1 (MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), \ + SWIZZLE_ONE, SWIZZLE_ONE, \ + SWIZZLE_ONE, SWIZZLE_ONE, \ + t_src_class(src[1].File), VSF_FLAG_NONE) | (src[1].RelAddr << 4)) + +#define ONE_SRC_2 (MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), \ + SWIZZLE_ONE, SWIZZLE_ONE, \ + SWIZZLE_ONE, SWIZZLE_ONE, \ + t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4)) + +/* DP4 version seems to trigger some hw peculiarity */ +//#define PREFER_DP4 + +#define FREE_TEMPS() \ + do { \ + if(u_temp_i < vp->num_temporaries) { \ + WARN_ONCE("Ran out of temps, num temps %d, us %d\n", vp->num_temporaries, u_temp_i); \ + vp->native = GL_FALSE; \ + } \ + u_temp_i=VSF_MAX_FRAGMENT_TEMPS-1; \ + } while (0) + +static void r300TranslateVertexShader(struct r300_vertex_program *vp, + struct prog_instruction *vpi) +{ + int i, cur_reg = 0; + VERTEX_SHADER_INSTRUCTION *o_inst; + unsigned long operands; + int are_srcs_scalar; + unsigned long hw_op; + /* Initial value should be last tmp reg that hw supports. + Strangely enough r300 doesnt mind even though these would be out of range. + Smart enough to realize that it doesnt need it? */ + int u_temp_i = VSF_MAX_FRAGMENT_TEMPS - 1; + struct prog_src_register src[3]; + + vp->pos_end = 0; /* Not supported yet */ + vp->program.length = 0; + /*vp->num_temporaries=mesa_vp->Base.NumTemporaries; */ + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + vp->inputs[i] = -1; + + for (i = 0; i < VERT_RESULT_MAX; i++) + vp->outputs[i] = -1; + + assert(vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)); + + /* Assign outputs */ + if (vp->key.OutputsWritten & (1 << VERT_RESULT_HPOS)) + vp->outputs[VERT_RESULT_HPOS] = cur_reg++; + + if (vp->key.OutputsWritten & (1 << VERT_RESULT_PSIZ)) + vp->outputs[VERT_RESULT_PSIZ] = cur_reg++; + + if (vp->key.OutputsWritten & (1 << VERT_RESULT_COL0)) + vp->outputs[VERT_RESULT_COL0] = cur_reg++; + + if (vp->key.OutputsWritten & (1 << VERT_RESULT_COL1)) + vp->outputs[VERT_RESULT_COL1] = cur_reg++; + +#if 0 /* Not supported yet */ + if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC0)) + vp->outputs[VERT_RESULT_BFC0] = cur_reg++; + + if (vp->key.OutputsWritten & (1 << VERT_RESULT_BFC1)) + vp->outputs[VERT_RESULT_BFC1] = cur_reg++; + + if (vp->key.OutputsWritten & (1 << VERT_RESULT_FOGC)) + vp->outputs[VERT_RESULT_FOGC] = cur_reg++; +#endif + + for (i = VERT_RESULT_TEX0; i <= VERT_RESULT_TEX7; i++) + if (vp->key.OutputsWritten & (1 << i)) + vp->outputs[i] = cur_reg++; + + vp->translated = GL_TRUE; + vp->native = GL_TRUE; + + o_inst = vp->program.body.i; + for (; vpi->Opcode != OPCODE_END; vpi++, o_inst++) { + FREE_TEMPS(); + + if (!valid_dst(vp, &vpi->DstReg)) { + /* redirect result to unused temp */ + vpi->DstReg.File = PROGRAM_TEMPORARY; + vpi->DstReg.Index = u_temp_i; + } + + operands = op_operands(vpi->Opcode); + are_srcs_scalar = operands & SCALAR_FLAG; + operands &= OP_MASK; + + for (i = 0; i < operands; i++) + src[i] = vpi->SrcReg[i]; + + if (operands == 3) { /* TODO: scalars */ + if (CMP_SRCS(src[1], src[2]) + || CMP_SRCS(src[0], src[2])) { + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i, + VSF_FLAG_ALL, + VSF_OUT_CLASS_TMP); + + o_inst->src[0] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), + SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_W, + t_src_class(src[2].File), + VSF_FLAG_NONE) | (src[2]. + RelAddr << + 4); + + o_inst->src[1] = ZERO_SRC_2; + o_inst->src[2] = ZERO_SRC_2; + o_inst++; + + src[2].File = PROGRAM_TEMPORARY; + src[2].Index = u_temp_i; + src[2].RelAddr = 0; + u_temp_i--; + } + + } + + if (operands >= 2) { + if (CMP_SRCS(src[1], src[0])) { + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, u_temp_i, + VSF_FLAG_ALL, + VSF_OUT_CLASS_TMP); + + o_inst->src[0] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + SWIZZLE_X, SWIZZLE_Y, + SWIZZLE_Z, SWIZZLE_W, + t_src_class(src[0].File), + VSF_FLAG_NONE) | (src[0]. + RelAddr << + 4); + + o_inst->src[1] = ZERO_SRC_0; + o_inst->src[2] = ZERO_SRC_0; + o_inst++; + + src[0].File = PROGRAM_TEMPORARY; + src[0].Index = u_temp_i; + src[0].RelAddr = 0; + u_temp_i--; + } + } + + /* These ops need special handling. */ + switch (vpi->Opcode) { + case OPCODE_POW: + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_POW, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + o_inst->src[0] = t_src_scalar(vp, &src[0]); + o_inst->src[1] = ZERO_SRC_0; + o_inst->src[2] = t_src_scalar(vp, &src[1]); + goto next; + + case OPCODE_MOV: //ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} + case OPCODE_SWZ: +#if 1 + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = ZERO_SRC_0; + o_inst->src[2] = ZERO_SRC_0; +#else + hw_op = + (src[0].File == + PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : + R300_VPI_OUT_OP_MAD; + + o_inst->op = + MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = ONE_SRC_0; + o_inst->src[2] = ZERO_SRC_0; +#endif + + goto next; + + case OPCODE_ADD: +#if 1 + hw_op = (src[0].File == PROGRAM_TEMPORARY && + src[1].File == + PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : + R300_VPI_OUT_OP_MAD; + + o_inst->op = + MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + o_inst->src[0] = ONE_SRC_0; + o_inst->src[1] = t_src(vp, &src[0]); + o_inst->src[2] = t_src(vp, &src[1]); +#else + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = t_src(vp, &src[1]); + o_inst->src[2] = ZERO_SRC_1; + +#endif + goto next; + + case OPCODE_MAD: + hw_op = (src[0].File == PROGRAM_TEMPORARY && + src[1].File == PROGRAM_TEMPORARY && + src[2].File == + PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : + R300_VPI_OUT_OP_MAD; + + o_inst->op = + MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = t_src(vp, &src[1]); + o_inst->src[2] = t_src(vp, &src[2]); + goto next; + + case OPCODE_MUL: /* HW mul can take third arg but appears to have some other limitations. */ + hw_op = (src[0].File == PROGRAM_TEMPORARY && + src[1].File == + PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : + R300_VPI_OUT_OP_MAD; + + o_inst->op = + MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = t_src(vp, &src[1]); + + o_inst->src[2] = ZERO_SRC_1; + goto next; + + case OPCODE_DP3: //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO} + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + + o_inst->src[0] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ + (src[0].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 1)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 2)), + SWIZZLE_ZERO, + t_src_class(src[0].File), + src[0]. + NegateBase ? VSF_FLAG_XYZ : + VSF_FLAG_NONE) | (src[0]. + RelAddr << 4); + + o_inst->src[1] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + t_swizzle(GET_SWZ + (src[1].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[1].Swizzle, 1)), + t_swizzle(GET_SWZ + (src[1].Swizzle, 2)), + SWIZZLE_ZERO, + t_src_class(src[1].File), + src[1]. + NegateBase ? VSF_FLAG_XYZ : + VSF_FLAG_NONE) | (src[1]. + RelAddr << 4); + + o_inst->src[2] = ZERO_SRC_1; + goto next; + + case OPCODE_SUB: //ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W +#if 1 + hw_op = (src[0].File == PROGRAM_TEMPORARY && + src[1].File == + PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : + R300_VPI_OUT_OP_MAD; + + o_inst->op = + MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = ONE_SRC_0; + o_inst->src[2] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + t_swizzle(GET_SWZ + (src[1].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[1].Swizzle, 1)), + t_swizzle(GET_SWZ + (src[1].Swizzle, 2)), + t_swizzle(GET_SWZ + (src[1].Swizzle, 3)), + t_src_class(src[1].File), + (!src[1]. + NegateBase) ? VSF_FLAG_ALL : + VSF_FLAG_NONE) | (src[1]. + RelAddr << 4); +#else + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), + t_swizzle(GET_SWZ + (src[1].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[1].Swizzle, 1)), + t_swizzle(GET_SWZ + (src[1].Swizzle, 2)), + t_swizzle(GET_SWZ + (src[1].Swizzle, 3)), + t_src_class(src[1].File), + (!src[1]. + NegateBase) ? VSF_FLAG_ALL : + VSF_FLAG_NONE) | (src[1]. + RelAddr << 4); + o_inst->src[2] = 0; +#endif + goto next; + + case OPCODE_ABS: //MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_MAX, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ + (src[0].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 1)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 2)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 3)), + t_src_class(src[0].File), + (!src[0]. + NegateBase) ? VSF_FLAG_ALL : + VSF_FLAG_NONE) | (src[0]. + RelAddr << 4); + o_inst->src[2] = 0; + goto next; + + case OPCODE_FLR: + /* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W} + ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */ + + o_inst->op = MAKE_VSF_OP(R300_VPI_OUT_OP_FRC, u_temp_i, + t_dst_mask(vpi->DstReg. + WriteMask), + VSF_OUT_CLASS_TMP); + + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = ZERO_SRC_0; + o_inst->src[2] = ZERO_SRC_0; + o_inst++; + + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_ADD, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = MAKE_VSF_SOURCE(u_temp_i, + VSF_IN_COMPONENT_X, + VSF_IN_COMPONENT_Y, + VSF_IN_COMPONENT_Z, + VSF_IN_COMPONENT_W, + VSF_IN_CLASS_TMP, + /* Not 100% sure about this */ + (!src[0]. + NegateBase) ? + VSF_FLAG_ALL : + VSF_FLAG_NONE + /*VSF_FLAG_ALL */ ); + + o_inst->src[2] = ZERO_SRC_0; + u_temp_i--; + goto next; + + case OPCODE_LG2: // LG2 RESULT 1.X Y Z W PARAM 0{} {X X X X} + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_LG2, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + + o_inst->src[0] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ + (src[0].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 0)), + t_src_class(src[0].File), + src[0]. + NegateBase ? VSF_FLAG_ALL : + VSF_FLAG_NONE) | (src[0]. + RelAddr << 4); + o_inst->src[1] = ZERO_SRC_0; + o_inst->src[2] = ZERO_SRC_0; + goto next; + + case OPCODE_LIT: //LIT TMP 1.Y Z TMP 1{} {X W Z Y} TMP 1{} {Y W Z X} TMP 1{} {Y X Z W} + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_LIT, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + /* NOTE: Users swizzling might not work. */ + o_inst->src[0] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + VSF_IN_COMPONENT_ZERO, // z + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_src_class(src[0]. + File), + src[0]. + NegateBase ? + VSF_FLAG_ALL : + VSF_FLAG_NONE) | + (src[0].RelAddr << 4); + o_inst->src[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + VSF_IN_COMPONENT_ZERO, // z + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_src_class(src[0]. + File), + src[0]. + NegateBase ? + VSF_FLAG_ALL : + VSF_FLAG_NONE) | + (src[0].RelAddr << 4); + o_inst->src[2] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + VSF_IN_COMPONENT_ZERO, // z + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + t_src_class(src[0]. + File), + src[0]. + NegateBase ? + VSF_FLAG_ALL : + VSF_FLAG_NONE) | + (src[0].RelAddr << 4); + goto next; + + case OPCODE_DPH: //DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W} + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_DOT, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + + o_inst->src[0] = + MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), + t_swizzle(GET_SWZ + (src[0].Swizzle, 0)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 1)), + t_swizzle(GET_SWZ + (src[0].Swizzle, 2)), + VSF_IN_COMPONENT_ONE, + t_src_class(src[0].File), + src[0]. + NegateBase ? VSF_FLAG_XYZ : + VSF_FLAG_NONE) | (src[0]. + RelAddr << 4); + o_inst->src[1] = t_src(vp, &src[1]); + o_inst->src[2] = ZERO_SRC_1; + goto next; + + case OPCODE_XPD: + /* mul r0, r1.yzxw, r2.zxyw + mad r0, -r2.yzxw, r1.zxyw, r0 + NOTE: might need MAD_2 + */ + + o_inst->op = MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, u_temp_i, + t_dst_mask(vpi->DstReg. + WriteMask), + VSF_OUT_CLASS_TMP); + + o_inst->src[0] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + t_src_class(src[0]. + File), + src[0]. + NegateBase ? + VSF_FLAG_ALL : + VSF_FLAG_NONE) | + (src[0].RelAddr << 4); + + o_inst->src[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w + t_src_class(src[1]. + File), + src[1]. + NegateBase ? + VSF_FLAG_ALL : + VSF_FLAG_NONE) | + (src[1].RelAddr << 4); + + o_inst->src[2] = ZERO_SRC_1; + o_inst++; + u_temp_i--; + + o_inst->op = + MAKE_VSF_OP(R300_VPI_OUT_OP_MAD, + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + + o_inst->src[0] = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w + t_src_class(src[1]. + File), + (!src[1]. + NegateBase) ? + VSF_FLAG_ALL : + VSF_FLAG_NONE) | + (src[1].RelAddr << 4); + + o_inst->src[1] = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z + t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x + t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y + t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w + t_src_class(src[0]. + File), + src[0]. + NegateBase ? + VSF_FLAG_ALL : + VSF_FLAG_NONE) | + (src[0].RelAddr << 4); + + o_inst->src[2] = MAKE_VSF_SOURCE(u_temp_i + 1, + VSF_IN_COMPONENT_X, + VSF_IN_COMPONENT_Y, + VSF_IN_COMPONENT_Z, + VSF_IN_COMPONENT_W, + VSF_IN_CLASS_TMP, + VSF_FLAG_NONE); + + goto next; + + case OPCODE_RCC: + fprintf(stderr, "Dont know how to handle op %d yet\n", + vpi->Opcode); + _mesa_exit(-1); + break; + case OPCODE_END: + break; + default: + break; + } + + o_inst->op = + MAKE_VSF_OP(t_opcode(vpi->Opcode), + t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), + t_dst_class(vpi->DstReg.File)); + + if (are_srcs_scalar) { + switch (operands) { + case 1: + o_inst->src[0] = t_src_scalar(vp, &src[0]); + o_inst->src[1] = ZERO_SRC_0; + o_inst->src[2] = ZERO_SRC_0; + break; + + case 2: + o_inst->src[0] = t_src_scalar(vp, &src[0]); + o_inst->src[1] = t_src_scalar(vp, &src[1]); + o_inst->src[2] = ZERO_SRC_1; + break; + + case 3: + o_inst->src[0] = t_src_scalar(vp, &src[0]); + o_inst->src[1] = t_src_scalar(vp, &src[1]); + o_inst->src[2] = t_src_scalar(vp, &src[2]); + break; + + default: + fprintf(stderr, + "scalars and op RCC not handled yet"); + _mesa_exit(-1); + break; + } + } else { + switch (operands) { + case 1: + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = ZERO_SRC_0; + o_inst->src[2] = ZERO_SRC_0; + break; + + case 2: + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = t_src(vp, &src[1]); + o_inst->src[2] = ZERO_SRC_1; + break; + + case 3: + o_inst->src[0] = t_src(vp, &src[0]); + o_inst->src[1] = t_src(vp, &src[1]); + o_inst->src[2] = t_src(vp, &src[2]); + break; + + default: + fprintf(stderr, + "scalars and op RCC not handled yet"); + _mesa_exit(-1); + break; + } + } + next:; + } + + /* Will most likely segfault before we get here... fix later. */ + if (o_inst - vp->program.body.i >= VSF_MAX_FRAGMENT_LENGTH / 4) { + vp->program.length = 0; + vp->native = GL_FALSE; + return; + } + vp->program.length = (o_inst - vp->program.body.i) * 4; +#if 0 + fprintf(stderr, "hw program:\n"); + for (i = 0; i < vp->program.length; i++) + fprintf(stderr, "%08x\n", vp->program.body.d[i]); +#endif +} + +static void position_invariant(struct gl_program *prog) +{ + struct prog_instruction *vpi; + struct gl_program_parameter_list *paramList; + int i; + + gl_state_index tokens[STATE_LENGTH] = { STATE_MVP_MATRIX, 0, 0, 0, 0 }; + + /* tokens[4] = matrix modifier */ +#ifdef PREFER_DP4 + tokens[4] = 0; /* not transposed or inverted */ +#else + tokens[4] = STATE_MATRIX_TRANSPOSE; +#endif + paramList = prog->Parameters; + + vpi = _mesa_alloc_instructions(prog->NumInstructions + 4); + _mesa_init_instructions(vpi, prog->NumInstructions + 4); + + for (i = 0; i < 4; i++) { + GLint idx; + tokens[2] = tokens[3] = i; /* matrix row[i]..row[i] */ + idx = _mesa_add_state_reference(paramList, tokens); +#ifdef PREFER_DP4 + vpi[i].Opcode = OPCODE_DP4; + vpi[i].StringPos = 0; + vpi[i].Data = 0; + + vpi[i].DstReg.File = PROGRAM_OUTPUT; + vpi[i].DstReg.Index = VERT_RESULT_HPOS; + vpi[i].DstReg.WriteMask = 1 << i; + vpi[i].DstReg.CondMask = COND_TR; + + vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; + vpi[i].SrcReg[0].Index = idx; + vpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW; + + vpi[i].SrcReg[1].File = PROGRAM_INPUT; + vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; + vpi[i].SrcReg[1].Swizzle = SWIZZLE_XYZW; +#else + if (i == 0) + vpi[i].Opcode = OPCODE_MUL; + else + vpi[i].Opcode = OPCODE_MAD; + + vpi[i].StringPos = 0; + vpi[i].Data = 0; + + if (i == 3) + vpi[i].DstReg.File = PROGRAM_OUTPUT; + else + vpi[i].DstReg.File = PROGRAM_TEMPORARY; + vpi[i].DstReg.Index = 0; + vpi[i].DstReg.WriteMask = 0xf; + vpi[i].DstReg.CondMask = COND_TR; + + vpi[i].SrcReg[0].File = PROGRAM_STATE_VAR; + vpi[i].SrcReg[0].Index = idx; + vpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW; + + vpi[i].SrcReg[1].File = PROGRAM_INPUT; + vpi[i].SrcReg[1].Index = VERT_ATTRIB_POS; + vpi[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(i, i, i, i); + + if (i > 0) { + vpi[i].SrcReg[2].File = PROGRAM_TEMPORARY; + vpi[i].SrcReg[2].Index = 0; + vpi[i].SrcReg[2].Swizzle = SWIZZLE_XYZW; + } +#endif + } + + _mesa_copy_instructions(&vpi[i], prog->Instructions, + prog->NumInstructions); + + free(prog->Instructions); + + prog->Instructions = vpi; + + prog->NumInstructions += 4; + vpi = &prog->Instructions[prog->NumInstructions - 1]; + + assert(vpi->Opcode == OPCODE_END); +} + +static void insert_wpos(struct r300_vertex_program *vp, + struct gl_program *prog, GLuint temp_index) +{ + struct prog_instruction *vpi; + struct prog_instruction *vpi_insert; + int i = 0; + + vpi = _mesa_alloc_instructions(prog->NumInstructions + 2); + _mesa_init_instructions(vpi, prog->NumInstructions + 2); + /* all but END */ + _mesa_copy_instructions(vpi, prog->Instructions, + prog->NumInstructions - 1); + /* END */ + _mesa_copy_instructions(&vpi[prog->NumInstructions + 1], + &prog->Instructions[prog->NumInstructions - 1], + 1); + vpi_insert = &vpi[prog->NumInstructions - 1]; + + vpi_insert[i].Opcode = OPCODE_MOV; + + vpi_insert[i].DstReg.File = PROGRAM_OUTPUT; + vpi_insert[i].DstReg.Index = VERT_RESULT_HPOS; + vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW; + vpi_insert[i].DstReg.CondMask = COND_TR; + + vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; + vpi_insert[i].SrcReg[0].Index = temp_index; + vpi_insert[i].SrcReg[0].Swizzle = SWIZZLE_XYZW; + i++; + + vpi_insert[i].Opcode = OPCODE_MOV; + + vpi_insert[i].DstReg.File = PROGRAM_OUTPUT; + vpi_insert[i].DstReg.Index = VERT_RESULT_TEX0 + vp->wpos_idx; + vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW; + vpi_insert[i].DstReg.CondMask = COND_TR; + + vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY; + vpi_insert[i].SrcReg[0].Index = temp_index; + vpi_insert[i].SrcReg[0].Swizzle = SWIZZLE_XYZW; + i++; + + free(prog->Instructions); + + prog->Instructions = vpi; + + prog->NumInstructions += i; + vpi = &prog->Instructions[prog->NumInstructions - 1]; + + assert(vpi->Opcode == OPCODE_END); +} + +static void pos_as_texcoord(struct r300_vertex_program *vp, + struct gl_program *prog) +{ + struct prog_instruction *vpi; + GLuint tempregi = prog->NumTemporaries; + /* should do something else if no temps left... */ + prog->NumTemporaries++; + + for (vpi = prog->Instructions; vpi->Opcode != OPCODE_END; vpi++) { + if (vpi->DstReg.File == PROGRAM_OUTPUT && + vpi->DstReg.Index == VERT_RESULT_HPOS) { + vpi->DstReg.File = PROGRAM_TEMPORARY; + vpi->DstReg.Index = tempregi; + } + } + insert_wpos(vp, prog, tempregi); +} + +static struct r300_vertex_program *build_program(struct r300_vertex_program_key + *wanted_key, struct gl_vertex_program + *mesa_vp, GLint wpos_idx) +{ + struct r300_vertex_program *vp; + + vp = _mesa_calloc(sizeof(*vp)); + _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key)); + + vp->wpos_idx = wpos_idx; + + if (mesa_vp->IsPositionInvariant) { + position_invariant(&mesa_vp->Base); + } + + if (wpos_idx > -1) + pos_as_texcoord(vp, &mesa_vp->Base); + + assert(mesa_vp->Base.NumInstructions); + + vp->num_temporaries = mesa_vp->Base.NumTemporaries; + + r300TranslateVertexShader(vp, mesa_vp->Base.Instructions); + + return vp; +} + +void r300SelectVertexShader(r300ContextPtr r300) +{ + GLcontext *ctx = ctx = r300->radeon.glCtx; + GLuint InputsRead; + struct r300_vertex_program_key wanted_key = { 0 }; + GLint i; + struct r300_vertex_program_cont *vpc; + struct r300_vertex_program *vp; + GLint wpos_idx; + + vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current; + InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; + + wanted_key.OutputsWritten |= 1 << VERT_RESULT_HPOS; + + wpos_idx = -1; + if (InputsRead & FRAG_BIT_WPOS) { + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (!(InputsRead & (FRAG_BIT_TEX0 << i))) + break; + + if (i == ctx->Const.MaxTextureUnits) { + fprintf(stderr, "\tno free texcoord found\n"); + _mesa_exit(-1); + } + + InputsRead |= (FRAG_BIT_TEX0 << i); + wpos_idx = i; + } + + if (InputsRead & FRAG_BIT_COL0) + wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL0; + + if ((InputsRead & FRAG_BIT_COL1) /*|| + (InputsRead & FRAG_BIT_FOGC) */ ) + wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL1; + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + if (InputsRead & (FRAG_BIT_TEX0 << i)) + wanted_key.OutputsWritten |= + 1 << (VERT_RESULT_TEX0 + i); + + wanted_key.InputsRead = vpc->mesa_program.Base.InputsRead; + if (vpc->mesa_program.IsPositionInvariant) { + /* we wan't position don't we ? */ + wanted_key.InputsRead |= (1 << VERT_ATTRIB_POS); + } + + for (vp = vpc->progs; vp; vp = vp->next) + if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key)) == + 0) { + r300->selected_vp = vp; + return; + } + //_mesa_print_program(&vpc->mesa_program.Base); + + vp = build_program(&wanted_key, &vpc->mesa_program, wpos_idx); + vp->next = vpc->progs; + vpc->progs = vp; + r300->selected_vp = vp; +} diff --git a/dist/Mesa/src/mesa/drivers/dri/r300/r300_vertprog.h b/dist/Mesa/src/mesa/drivers/dri/r300/r300_vertprog.h new file mode 100644 index 000000000..252d5a901 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/dri/r300/r300_vertprog.h @@ -0,0 +1,89 @@ +#ifndef __R300_VERTPROG_H_ +#define __R300_VERTPROG_H_ + +#include "r300_reg.h" + +typedef struct { + GLuint op; + GLuint src[3]; +} VERTEX_SHADER_INSTRUCTION; + +#define VSF_FLAG_X 1 +#define VSF_FLAG_Y 2 +#define VSF_FLAG_Z 4 +#define VSF_FLAG_W 8 +#define VSF_FLAG_XYZ (VSF_FLAG_X | VSF_FLAG_Y | VSF_FLAG_Z) +#define VSF_FLAG_ALL 0xf +#define VSF_FLAG_NONE 0 + +#define VSF_OUT_CLASS_TMP 0 +#define VSF_OUT_CLASS_ADDR 1 +#define VSF_OUT_CLASS_RESULT 2 + +/* first DWORD of an instruction */ + +/* possible operations: + DOT, MUL, ADD, MAD, FRC, MAX, MIN, SGE, SLT, EXP, LOG, LIT, POW, RCP, RSQ, EX2, + LG2, MAD_2 */ + +#define MAKE_VSF_OP(op, out_reg_index, out_reg_fields, class) \ + ((op) \ + | ((out_reg_index) << R300_VPI_OUT_REG_INDEX_SHIFT) \ + | ((out_reg_fields) << 20) \ + | ( (class) << 8 ) ) + +#define EASY_VSF_OP(op, out_reg_index, out_reg_fields, class) \ + MAKE_VSF_OP(R300_VPI_OUT_OP_##op, out_reg_index, VSF_FLAG_##out_reg_fields, VSF_OUT_CLASS_##class) \ + +/* according to Nikolai, the subsequent 3 DWORDs are sources, use same define for each */ + +#define VSF_IN_CLASS_TMP 0 +#define VSF_IN_CLASS_ATTR 1 +#define VSF_IN_CLASS_PARAM 2 +#define VSF_IN_CLASS_NONE 9 + +#define VSF_IN_COMPONENT_X 0 +#define VSF_IN_COMPONENT_Y 1 +#define VSF_IN_COMPONENT_Z 2 +#define VSF_IN_COMPONENT_W 3 +#define VSF_IN_COMPONENT_ZERO 4 +#define VSF_IN_COMPONENT_ONE 5 + +#define MAKE_VSF_SOURCE(in_reg_index, comp_x, comp_y, comp_z, comp_w, class, negate) \ + ( ((in_reg_index)<<R300_VPI_IN_REG_INDEX_SHIFT) \ + | ((comp_x)<<R300_VPI_IN_X_SHIFT) \ + | ((comp_y)<<R300_VPI_IN_Y_SHIFT) \ + | ((comp_z)<<R300_VPI_IN_Z_SHIFT) \ + | ((comp_w)<<R300_VPI_IN_W_SHIFT) \ + | ((negate)<<25) | ((class))) + +#define EASY_VSF_SOURCE(in_reg_index, comp_x, comp_y, comp_z, comp_w, class, negate) \ + MAKE_VSF_SOURCE(in_reg_index, \ + VSF_IN_COMPONENT_##comp_x, \ + VSF_IN_COMPONENT_##comp_y, \ + VSF_IN_COMPONENT_##comp_z, \ + VSF_IN_COMPONENT_##comp_w, \ + VSF_IN_CLASS_##class, VSF_FLAG_##negate) + +/* special sources: */ + +/* (1.0,1.0,1.0,1.0) vector (ATTR, plain ) */ +#define VSF_ATTR_UNITY(reg) EASY_VSF_SOURCE(reg, ONE, ONE, ONE, ONE, ATTR, NONE) +#define VSF_UNITY(reg) EASY_VSF_SOURCE(reg, ONE, ONE, ONE, ONE, NONE, NONE) + +/* contents of unmodified register */ +#define VSF_REG(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, ATTR, NONE) + +/* contents of unmodified parameter */ +#define VSF_PARAM(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, PARAM, NONE) + +/* contents of unmodified temporary register */ +#define VSF_TMP(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, TMP, NONE) + +/* components of ATTR register */ +#define VSF_ATTR_X(reg) EASY_VSF_SOURCE(reg, X, X, X, X, ATTR, NONE) +#define VSF_ATTR_Y(reg) EASY_VSF_SOURCE(reg, Y, Y, Y, Y, ATTR, NONE) +#define VSF_ATTR_Z(reg) EASY_VSF_SOURCE(reg, Z, Z, Z, Z, ATTR, NONE) +#define VSF_ATTR_W(reg) EASY_VSF_SOURCE(reg, W, W, W, W, ATTR, NONE) + +#endif diff --git a/dist/Mesa/src/mesa/drivers/dri/unichrome/server/via_regs.h b/dist/Mesa/src/mesa/drivers/dri/unichrome/server/via_regs.h index 5c5eecbe8..87e1e9daa 100644 --- a/dist/Mesa/src/mesa/drivers/dri/unichrome/server/via_regs.h +++ b/dist/Mesa/src/mesa/drivers/dri/unichrome/server/via_regs.h @@ -44,6 +44,7 @@ #define PCI_CHIP_VT7205 0x7205 #define PCI_CHIP_VT3204 0x3108 #define PCI_CHIP_VT3259 0x3118 +#define PCI_CHIP_VT3344 0x3344 #define BIOS_BSIZE 1024 diff --git a/dist/Mesa/src/mesa/drivers/x11/xm_glide.c b/dist/Mesa/src/mesa/drivers/x11/xm_glide.c new file mode 100644 index 000000000..ae4f4282d --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/x11/xm_glide.c @@ -0,0 +1,276 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glxheader.h" +#include "xmesaP.h" + +#ifdef FX +#include "../glide/fxdrv.h" + +void +FXcreateContext(XMesaVisual v, XMesaWindow w, XMesaContext c, XMesaBuffer b) +{ + char *fxEnvVar = _mesa_getenv("MESA_GLX_FX"); + if (fxEnvVar) { + if (fxEnvVar[0]!='d') { + int attribs[100]; + int numAttribs = 0; + int hw; + if (v->mesa_visual.depthBits > 0) { + attribs[numAttribs++] = FXMESA_DEPTH_SIZE; + attribs[numAttribs++] = v->mesa_visual.depthBits; + } + if (v->mesa_visual.doubleBufferMode) { + attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; + } + if (v->mesa_visual.accumRedBits > 0) { + attribs[numAttribs++] = FXMESA_ACCUM_SIZE; + attribs[numAttribs++] = v->mesa_visual.accumRedBits; + } + if (v->mesa_visual.stencilBits > 0) { + attribs[numAttribs++] = FXMESA_STENCIL_SIZE; + attribs[numAttribs++] = v->mesa_visual.stencilBits; + } + if (v->mesa_visual.alphaBits > 0) { + attribs[numAttribs++] = FXMESA_ALPHA_SIZE; + attribs[numAttribs++] = v->mesa_visual.alphaBits; + } + if (1) { + attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; + attribs[numAttribs++] = (int) &(c->mesa); + } + attribs[numAttribs++] = FXMESA_NONE; + + /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */ + hw = fxMesaSelectCurrentBoard(0); + + /* if these fail, there's a new bug somewhere */ + ASSERT(b->mesa_buffer.Width > 0); + ASSERT(b->mesa_buffer.Height > 0); + + if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) { + b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width, + b->mesa_buffer.Height, attribs); + if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) { + b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; + if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) { + b->FXwindowHack = GL_TRUE; + FX_grSstControl(GR_CONTROL_DEACTIVATE); + } + else { + b->FXwindowHack = GL_FALSE; + } + } + } + else { + if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') + b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, + GR_REFRESH_75Hz, attribs); + else + b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width, + b->mesa_buffer.Height, attribs); + b->FXisHackUsable = GL_FALSE; + b->FXwindowHack = GL_FALSE; + } + /* + fprintf(stderr, + "voodoo %d, wid %d height %d hack: usable %d active %d\n", + hw, b->mesa_buffer.Width, b->mesa_buffer.Height, + b->FXisHackUsable, b->FXwindowHack); + */ + } + } + else { + _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n"); + _mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n"); + _mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n"); + _mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); + } +} + + +void FXdestroyContext( XMesaBuffer b ) +{ + if (b && b->FXctx) + fxMesaDestroyContext(b->FXctx); +} + + +GLboolean FXmakeCurrent( XMesaBuffer b ) +{ + if (b->FXctx) { + fxMesaMakeCurrent(b->FXctx); + + return GL_TRUE; + } + return GL_FALSE; +} + + +/* + * Read image from VooDoo frame buffer into X/Mesa's back XImage. + */ +static void FXgetImage( XMesaBuffer b ) +{ + GET_CURRENT_CONTEXT(ctx); + static unsigned short pixbuf[MAX_WIDTH]; + GLuint x, y; + GLuint width, height; + +#ifdef XFree86Server + x = b->frontxrb->pixmap->x; + y = b->frontxrb->pixmap->y; + width = b->frontxrb->pixmap->width; + height = b->frontxrb->pixmap->height; + depth = b->frontxrb->pixmap->depth; +#else + xmesa_get_window_size(b->display, b, &width, &height); + x = y = 0; +#endif + if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) { + b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width); + b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height); + if (b->mesa_buffer.Width & 1) + b->mesa_buffer.Width--; /* prevent odd width */ + } + + /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */ + /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */ + if (b->xm_visual->undithered_pf==PF_5R6G5B) { + /* Special case: 16bpp RGB */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ + 0, b->FXctx->height - b->mesa_buffer.Height, /*pos*/ + b->mesa_buffer.Width, b->mesa_buffer.Height, /* size */ + b->mesa_buffer.Width * sizeof(GLushort), /* stride */ + b->backxrb->ximage->data); /* dest buffer */ + } + else if (b->xm_visual->dithered_pf==PF_Dither + && GET_VISUAL_DEPTH(b->xm_visual)==8) { + /* Special case: 8bpp RGB */ + for (y=0;y<b->mesa_buffer.Height;y++) { + GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data + + b->backxrb->ximage->bytes_per_line * y; + XDITHER_SETUP(y); + + /* read row from 3Dfx frame buffer */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, + 0, b->FXctx->height-(b->mesa_buffer.Height-y), + b->mesa_buffer.Width, 1, + 0, + pixbuf ); + + /* write to XImage back buffer */ + for (x=0;x<b->mesa_buffer.Width;x++) { + GLubyte r = (pixbuf[x] & 0xf800) >> 8; + GLubyte g = (pixbuf[x] & 0x07e0) >> 3; + GLubyte b = (pixbuf[x] & 0x001f) << 3; + *ptr++ = XDITHER( x, r, g, b); + } + } + } + else { + /* General case: slow! */ + for (y=0;y<b->mesa_buffer.Height;y++) { + /* read row from 3Dfx frame buffer */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, + 0, b->FXctx->height-(b->mesa_buffer.Height-y), + b->mesa_buffer.Width, 1, + 0, + pixbuf ); + + /* write to XImage back buffer */ + for (x=0;x<b->mesa_buffer.Width;x++) { + XMesaPutPixel(b->backxrb->ximage,x,y, + xmesa_color_to_pixel(ctx, + (pixbuf[x] & 0xf800) >> 8, + (pixbuf[x] & 0x07e0) >> 3, + (pixbuf[x] & 0x001f) << 3, + 0xff, + b->xm_visual->undithered_pf)); + } + } + } + /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */ +} + + +GLboolean FXswapBuffers( XMesaBuffer b ) +{ + if (b->FXctx) { + fxMesaSwapBuffers(); + + if (!b->FXwindowHack) + return GL_TRUE; + + FXgetImage(b); + } + return GL_FALSE; +} + + +/* + * Switch 3Dfx support hack between window and full-screen mode. + */ +GLboolean XMesaSetFXmode( GLint mode ) +{ + const char *fx = _mesa_getenv("MESA_GLX_FX"); + if (fx && fx[0] != 'd') { + GET_CURRENT_CONTEXT(ctx); + GrHwConfiguration hw; + if (!FX_grSstQueryHardware(&hw)) { + /*fprintf(stderr, "!grSstQueryHardware\n");*/ + return GL_FALSE; + } + if (hw.num_sst < 1) { + /*fprintf(stderr, "hw.num_sst < 1\n");*/ + return GL_FALSE; + } + if (ctx) { + /* [dBorca] Hack alert: + * oh, this is sooo wrong: ctx above is + * really an fxMesaContext, not an XMesaContext + */ + XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); + if (mode == XMESA_FX_WINDOW) { + if (xmbuf->FXisHackUsable) { + FX_grSstControl(GR_CONTROL_DEACTIVATE); + xmbuf->FXwindowHack = GL_TRUE; + return GL_TRUE; + } + } + else if (mode == XMESA_FX_FULLSCREEN) { + FX_grSstControl(GR_CONTROL_ACTIVATE); + xmbuf->FXwindowHack = GL_FALSE; + return GL_TRUE; + } + else { + /* Error: Bad mode value */ + } + } + } + /*fprintf(stderr, "fallthrough\n");*/ + return GL_FALSE; +} +#endif diff --git a/dist/Mesa/src/mesa/drivers/x11/xm_glide.h b/dist/Mesa/src/mesa/drivers/x11/xm_glide.h new file mode 100644 index 000000000..f7d031652 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/x11/xm_glide.h @@ -0,0 +1,40 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _XM_GLIDE_H_ +#define _XM_GLIDE_H_ + +extern void FXcreateContext( XMesaVisual v, + XMesaWindow w, + XMesaContext c, + XMesaBuffer b ); + +extern void FXdestroyContext( XMesaBuffer b ); + +extern GLboolean FXmakeCurrent( XMesaBuffer b ); + +extern GLboolean FXswapBuffers( XMesaBuffer b ); + +#endif /* _XM_GLIDE_H_ */ diff --git a/dist/Mesa/src/mesa/drivers/x11/xm_image.c b/dist/Mesa/src/mesa/drivers/x11/xm_image.c new file mode 100644 index 000000000..087b4e4c3 --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/x11/xm_image.c @@ -0,0 +1,133 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Brian Paul <brian@precisioninsight.com> + */ + +#include <stdlib.h> +#include <X11/Xmd.h> + +#include "glxheader.h" +#include "xmesaP.h" + +#ifdef XFree86Server + +#ifdef ROUNDUP +#undef ROUNDUP +#endif + +#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3)) + +XMesaImage *XMesaCreateImage(int bitsPerPixel, int width, int height, char *data) +{ + XMesaImage *image; + + image = (XMesaImage *)xalloc(sizeof(XMesaImage)); + + if (image) { + image->width = width; + image->height = height; + image->data = data; + /* Always pad to 32 bits */ + image->bytes_per_line = ROUNDUP((bitsPerPixel * width), 32); + image->bits_per_pixel = bitsPerPixel; + } + + return image; +} + +void XMesaDestroyImage(XMesaImage *image) +{ + if (image->data) + free(image->data); + xfree(image); +} + +unsigned long XMesaGetPixel(XMesaImage *image, int x, int y) +{ + CARD8 *row = (CARD8 *)(image->data + y*image->bytes_per_line); + CARD8 *i8; + CARD16 *i16; + CARD32 *i32; + switch (image->bits_per_pixel) { + case 8: + i8 = (CARD8 *)row; + return i8[x]; + break; + case 15: + case 16: + i16 = (CARD16 *)row; + return i16[x]; + break; + case 24: /* WARNING: architecture specific code */ + i8 = (CARD8 *)row; + return (((CARD32)i8[x*3]) | + (((CARD32)i8[x*3+1])<<8) | + (((CARD32)i8[x*3+2])<<16)); + break; + case 32: + i32 = (CARD32 *)row; + return i32[x]; + break; + } + return 0; +} + +#ifndef XMESA_USE_PUTPIXEL_MACRO +void XMesaPutPixel(XMesaImage *image, int x, int y, unsigned long pixel) +{ + CARD8 *row = (CARD8 *)(image->data + y*image->bytes_per_line); + CARD8 *i8; + CARD16 *i16; + CARD32 *i32; + switch (image->bits_per_pixel) { + case 8: + i8 = (CARD8 *)row; + i8[x] = (CARD8)pixel; + break; + case 15: + case 16: + i16 = (CARD16 *)row; + i16[x] = (CARD16)pixel; + break; + case 24: /* WARNING: architecture specific code */ + i8 = (CARD8 *)__row; + i8[x*3] = (CARD8)(p); + i8[x*3+1] = (CARD8)(p>>8); + i8[x*3+2] = (CARD8)(p>>16); + case 32: + i32 = (CARD32 *)row; + i32[x] = (CARD32)pixel; + break; + } +} +#endif + +#endif /* XFree86Server */ diff --git a/dist/Mesa/src/mesa/drivers/x11/xm_image.h b/dist/Mesa/src/mesa/drivers/x11/xm_image.h new file mode 100644 index 000000000..240ccee1a --- /dev/null +++ b/dist/Mesa/src/mesa/drivers/x11/xm_image.h @@ -0,0 +1,84 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Brian Paul <brian@precisioninsight.com> + */ + +#ifndef _XM_IMAGE_H_ +#define _XM_IMAGE_H_ + +#define XMESA_USE_PUTPIXEL_MACRO + +struct _XMesaImageRec { + int width, height; + char *data; + int bytes_per_line; /* Padded to 32 bits */ + int bits_per_pixel; +}; + +extern XMesaImage *XMesaCreateImage(int bitsPerPixel, int width, int height, + char *data); +extern void XMesaDestroyImage(XMesaImage *image); +extern unsigned long XMesaGetPixel(XMesaImage *image, int x, int y); +#ifdef XMESA_USE_PUTPIXEL_MACRO +#define XMesaPutPixel(__i,__x,__y,__p) \ +{ \ + CARD8 *__row = (CARD8 *)(__i->data + __y*__i->bytes_per_line); \ + CARD8 *__i8; \ + CARD16 *__i16; \ + CARD32 *__i32; \ + switch (__i->bits_per_pixel) { \ + case 8: \ + __i8 = (CARD8 *)__row; \ + __i8[__x] = (CARD8)__p; \ + break; \ + case 15: \ + case 16: \ + __i16 = (CARD16 *)__row; \ + __i16[__x] = (CARD16)__p; \ + break; \ + case 24: /* WARNING: architecture specific code */ \ + __i8 = (CARD8 *)__row; \ + __i8[__x*3] = (CARD8)(__p); \ + __i8[__x*3+1] = (CARD8)(__p>>8); \ + __i8[__x*3+2] = (CARD8)(__p>>16); \ + break; \ + case 32: \ + __i32 = (CARD32 *)__row; \ + __i32[__x] = (CARD32)__p; \ + break; \ + } \ +} +#else +extern void XMesaPutPixel(XMesaImage *image, int x, int y, + unsigned long pixel); +#endif + +#endif /* _XM_IMAGE_H_ */ diff --git a/dist/Mesa/src/mesa/main/queryobj.c b/dist/Mesa/src/mesa/main/queryobj.c new file mode 100644 index 000000000..0e59ba615 --- /dev/null +++ b/dist/Mesa/src/mesa/main/queryobj.c @@ -0,0 +1,538 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.1 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "queryobj.h" +#include "mtypes.h" + + +/** + * Allocate a new query object. This is a fallback routine called via + * ctx->Driver.NewQueryObject(). + * \param ctx - rendering context + * \param id - the new object's ID + * \return pointer to new query_object object or NULL if out of memory. + */ +struct gl_query_object * +_mesa_new_query_object(GLcontext *ctx, GLuint id) +{ + struct gl_query_object *q = MALLOC_STRUCT(gl_query_object); + (void) ctx; + if (q) { + q->Id = id; + q->Result = 0; + q->Active = GL_FALSE; + q->Ready = GL_TRUE; /* correct, see spec */ + } + return q; +} + + +/** + * Delete an occlusion query object. + * Not removed from hash table here. + * XXX maybe add Delete() method to gl_query_object class and call that instead + */ +static void +delete_query_object(struct gl_query_object *q) +{ + FREE(q); +} + + +static struct gl_query_object * +lookup_query_object(GLcontext *ctx, GLuint id) +{ + return (struct gl_query_object *) + _mesa_HashLookup(ctx->Query.QueryObjects, id); +} + + + +void GLAPIENTRY +_mesa_GenQueriesARB(GLsizei n, GLuint *ids) +{ + GLuint first; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); + return; + } + + /* No query objects can be active at this time! */ + if (ctx->Query.CurrentOcclusionObject || + ctx->Query.CurrentTimerObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); + return; + } + + first = _mesa_HashFindFreeKeyBlock(ctx->Query.QueryObjects, n); + if (first) { + GLsizei i; + for (i = 0; i < n; i++) { + struct gl_query_object *q + = ctx->Driver.NewQueryObject(ctx, first + i); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); + return; + } + ids[i] = first + i; + _mesa_HashInsert(ctx->Query.QueryObjects, first + i, q); + } + } +} + + +void GLAPIENTRY +_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); + return; + } + + /* No query objects can be active at this time! */ + if (ctx->Query.CurrentOcclusionObject || + ctx->Query.CurrentTimerObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); + return; + } + + for (i = 0; i < n; i++) { + if (ids[i] > 0) { + struct gl_query_object *q = lookup_query_object(ctx, ids[i]); + if (q) { + ASSERT(!q->Active); /* should be caught earlier */ + _mesa_HashRemove(ctx->Query.QueryObjects, ids[i]); + delete_query_object(q); + } + } + } +} + + +GLboolean GLAPIENTRY +_mesa_IsQueryARB(GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (id && lookup_query_object(ctx, id)) + return GL_TRUE; + else + return GL_FALSE; +} + + +void GLAPIENTRY +_mesa_BeginQueryARB(GLenum target, GLuint id) +{ + struct gl_query_object *q; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + + switch (target) { + case GL_SAMPLES_PASSED_ARB: + if (!ctx->Extensions.ARB_occlusion_query) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); + return; + } + if (ctx->Query.CurrentOcclusionObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); + return; + } + break; +#if FEATURE_EXT_timer_query + case GL_TIME_ELAPSED_EXT: + if (!ctx->Extensions.EXT_timer_query) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); + return; + } + if (ctx->Query.CurrentTimerObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); + return; + } + break; +#endif + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); + return; + } + + if (id == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)"); + return; + } + + q = lookup_query_object(ctx, id); + if (!q) { + /* create new object */ + q = ctx->Driver.NewQueryObject(ctx, id); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB"); + return; + } + _mesa_HashInsert(ctx->Query.QueryObjects, id, q); + } + else { + /* pre-existing object */ + if (q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBeginQueryARB(query already active)"); + return; + } + } + + q->Active = GL_TRUE; + q->Result = 0; + q->Ready = GL_FALSE; + + if (target == GL_SAMPLES_PASSED_ARB) { + ctx->Query.CurrentOcclusionObject = q; + } +#if FEATURE_EXT_timer_query + else if (target == GL_TIME_ELAPSED_EXT) { + ctx->Query.CurrentTimerObject = q; + } +#endif + + if (ctx->Driver.BeginQuery) { + ctx->Driver.BeginQuery(ctx, target, q); + } +} + + +void GLAPIENTRY +_mesa_EndQueryARB(GLenum target) +{ + struct gl_query_object *q; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + + switch (target) { + case GL_SAMPLES_PASSED_ARB: + if (!ctx->Extensions.ARB_occlusion_query) { + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + q = ctx->Query.CurrentOcclusionObject; + ctx->Query.CurrentOcclusionObject = NULL; + break; +#if FEATURE_EXT_timer_query + case GL_TIME_ELAPSED_EXT: + if (!ctx->Extensions.EXT_timer_query) { + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + q = ctx->Query.CurrentTimerObject; + ctx->Query.CurrentTimerObject = NULL; + break; +#endif + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + + if (!q || !q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEndQueryARB(no matching glBeginQueryARB)"); + return; + } + + q->Active = GL_FALSE; + if (ctx->Driver.EndQuery) { + ctx->Driver.EndQuery(ctx, target, q); + } + else { + /* if we're using software rendering/querying */ + q->Ready = GL_TRUE; + } +} + + +void GLAPIENTRY +_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) +{ + struct gl_query_object *q; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (target) { + case GL_SAMPLES_PASSED_ARB: + if (!ctx->Extensions.ARB_occlusion_query) { + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + q = ctx->Query.CurrentOcclusionObject; + break; +#if FEATURE_EXT_timer_query + case GL_TIME_ELAPSED_EXT: + if (!ctx->Extensions.EXT_timer_query) { + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + q = ctx->Query.CurrentTimerObject; + break; +#endif + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)"); + return; + } + + switch (pname) { + case GL_QUERY_COUNTER_BITS_ARB: + *params = 8 * sizeof(q->Result); + break; + case GL_CURRENT_QUERY_ARB: + *params = q ? q->Id : 0; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) +{ + struct gl_query_object *q = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (id) + q = lookup_query_object(ctx, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetQueryObjectivARB(id=%d is invalid or active)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + while (!q->Ready) { + /* Wait for the query to finish! */ + /* If using software rendering, the result will always be ready + * by time we get here. Otherwise, we must be using hardware! + */ + ASSERT(ctx->Driver.EndQuery); + } + /* if result is too large for returned type, clamp to max value */ + if (q->Result > 0x7fffffff) { + *params = 0x7fffffff; + } + else { + *params = q->Result; + } + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = q->Ready; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) +{ + struct gl_query_object *q = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (id) + q = lookup_query_object(ctx, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetQueryObjectuivARB(id=%d is invalid or active)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + while (!q->Ready) { + /* Wait for the query to finish! */ + /* If using software rendering, the result will always be ready + * by time we get here. Otherwise, we must be using hardware! + */ + ASSERT(ctx->Driver.EndQuery); + } + /* if result is too large for returned type, clamp to max value */ + if (q->Result > 0xffffffff) { + *params = 0xffffffff; + } + else { + *params = q->Result; + } + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = q->Ready; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); + return; + } +} + + +#if FEATURE_EXT_timer_query + +/** + * New with GL_EXT_timer_query + */ +void GLAPIENTRY +_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) +{ + struct gl_query_object *q = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (id) + q = lookup_query_object(ctx, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetQueryObjectui64vARB(id=%d is invalid or active)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + while (!q->Ready) { + /* Wait for the query to finish! */ + /* If using software rendering, the result will always be ready + * by time we get here. Otherwise, we must be using hardware! + */ + ASSERT(ctx->Driver.EndQuery); + } + *params = q->Result; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = q->Ready; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjecti64vARB(pname)"); + return; + } +} + + +/** + * New with GL_EXT_timer_query + */ +void GLAPIENTRY +_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) +{ + struct gl_query_object *q = NULL; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (id) + q = lookup_query_object(ctx, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetQueryObjectuui64vARB(id=%d is invalid or active)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + while (!q->Ready) { + /* Wait for the query to finish! */ + /* If using software rendering, the result will always be ready + * by time we get here. Otherwise, we must be using hardware! + */ + ASSERT(ctx->Driver.EndQuery); + } + *params = q->Result; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = q->Ready; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectui64vARB(pname)"); + return; + } +} + +#endif /* FEATURE_EXT_timer_query */ + + +/** + * Allocate/init the context state related to query objects. + */ +void +_mesa_init_query(GLcontext *ctx) +{ +#if FEATURE_ARB_occlusion_query + ctx->Query.QueryObjects = _mesa_NewHashTable(); + ctx->Query.CurrentOcclusionObject = NULL; +#endif +} + + +/** + * Callback for deleting a query object. Called by _mesa_HashDeleteAll(). + */ +static void +delete_queryobj_cb(GLuint id, void *data, void *userData) +{ + struct gl_query_object *q= (struct gl_query_object *) data; + (void) userData; + delete_query_object(q); +} + + +/** + * Free the context state related to query objects. + */ +void +_mesa_free_query_data(GLcontext *ctx) +{ + _mesa_HashDeleteAll(ctx->Query.QueryObjects, delete_queryobj_cb, NULL); + _mesa_DeleteHashTable(ctx->Query.QueryObjects); +} diff --git a/dist/Mesa/src/mesa/main/queryobj.h b/dist/Mesa/src/mesa/main/queryobj.h new file mode 100644 index 000000000..ada8cf835 --- /dev/null +++ b/dist/Mesa/src/mesa/main/queryobj.h @@ -0,0 +1,70 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef OCCLUDE_H +#define OCCLUDE_H + + +extern struct gl_query_object * +_mesa_new_query_object(GLcontext *ctx, GLuint id); + +extern void +_mesa_init_query(GLcontext *ctx); + +extern void +_mesa_free_query_data(GLcontext *ctx); + +extern void GLAPIENTRY +_mesa_GenQueriesARB(GLsizei n, GLuint *ids); + +extern void GLAPIENTRY +_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids); + +extern GLboolean GLAPIENTRY +_mesa_IsQueryARB(GLuint id); + +extern void GLAPIENTRY +_mesa_BeginQueryARB(GLenum target, GLuint id); + +extern void GLAPIENTRY +_mesa_EndQueryARB(GLenum target); + +extern void GLAPIENTRY +_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params); + +extern void GLAPIENTRY +_mesa_GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params); + +extern void GLAPIENTRY +_mesa_GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params); + + +#endif /* OCCLUDE_H */ diff --git a/dist/Mesa/src/mesa/main/shaders.c b/dist/Mesa/src/mesa/main/shaders.c new file mode 100644 index 000000000..7bf880876 --- /dev/null +++ b/dist/Mesa/src/mesa/main/shaders.c @@ -0,0 +1,680 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2004-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "context.h" +#include "shaders.h" + + +/** + * These are basically just wrappers/adaptors for calling the + * ctx->Driver.foobar() GLSL-related functions. + * + * Things are biased toward the OpenGL 2.0 functions rather than the + * ARB extensions (i.e. the ARB functions are layered on the 2.0 functions). + * + * The general idea here is to allow enough modularity such that a + * completely different GLSL implemenation can be plugged in and co-exist + * with Mesa's native GLSL code. + */ + + + +void GLAPIENTRY +_mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.AttachShader(ctx, program, shader); +} + + +void GLAPIENTRY +_mesa_AttachShader(GLuint program, GLuint shader) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.AttachShader(ctx, program, shader); +} + + +void GLAPIENTRY +_mesa_BindAttribLocationARB(GLhandleARB program, GLuint index, + const GLcharARB *name) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.BindAttribLocation(ctx, program, index, name); +} + + +void GLAPIENTRY +_mesa_CompileShaderARB(GLhandleARB shaderObj) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.CompileShader(ctx, shaderObj); +} + + +GLuint GLAPIENTRY +_mesa_CreateShader(GLenum type) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.CreateShader(ctx, type); +} + + +GLhandleARB GLAPIENTRY +_mesa_CreateShaderObjectARB(GLenum type) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.CreateShader(ctx, type); +} + + +GLuint GLAPIENTRY +_mesa_CreateProgram(void) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.CreateProgram(ctx); +} + + +GLhandleARB GLAPIENTRY +_mesa_CreateProgramObjectARB(void) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.CreateProgram(ctx); +} + + +void GLAPIENTRY +_mesa_DeleteObjectARB(GLhandleARB obj) +{ + if (obj) { + GET_CURRENT_CONTEXT(ctx); + if (ctx->Driver.IsProgram(ctx, obj)) { + ctx->Driver.DeleteProgram2(ctx, obj); + } + else if (ctx->Driver.IsShader(ctx, obj)) { + ctx->Driver.DeleteShader(ctx, obj); + } + else { + /* error? */ + } + } +} + + +void GLAPIENTRY +_mesa_DeleteProgram(GLuint name) +{ + if (name) { + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.DeleteProgram2(ctx, name); + } +} + + +void GLAPIENTRY +_mesa_DeleteShader(GLuint name) +{ + if (name) { + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.DeleteShader(ctx, name); + } +} + + +void GLAPIENTRY +_mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.DetachShader(ctx, program, shader); +} + + +void GLAPIENTRY +_mesa_DetachShader(GLuint program, GLuint shader) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.DetachShader(ctx, program, shader); +} + + +void GLAPIENTRY +_mesa_GetActiveAttribARB(GLhandleARB program, GLuint index, + GLsizei maxLength, GLsizei * length, GLint * size, + GLenum * type, GLcharARB * name) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetActiveAttrib(ctx, program, index, maxLength, length, size, + type, name); +} + + +void GLAPIENTRY +_mesa_GetActiveUniformARB(GLhandleARB program, GLuint index, + GLsizei maxLength, GLsizei * length, GLint * size, + GLenum * type, GLcharARB * name) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetActiveUniform(ctx, program, index, maxLength, length, size, + type, name); +} + + +void GLAPIENTRY +_mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount, + GLsizei * count, GLhandleARB * obj) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetAttachedShaders(ctx, container, maxCount, count, obj); +} + + +void GLAPIENTRY +_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount, + GLsizei *count, GLuint *obj) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetAttachedShaders(ctx, program, maxCount, count, obj); +} + + +GLint GLAPIENTRY +_mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.GetAttribLocation(ctx, program, name); +} + + +void GLAPIENTRY +_mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length, + GLcharARB * infoLog) +{ + GET_CURRENT_CONTEXT(ctx); + /* Implement in terms of GetProgramInfoLog, GetShaderInfoLog */ + if (ctx->Driver.IsProgram(ctx, object)) { + ctx->Driver.GetProgramInfoLog(ctx, object, maxLength, length, infoLog); + } + else if (ctx->Driver.IsShader(ctx, object)) { + ctx->Driver.GetShaderInfoLog(ctx, object, maxLength, length, infoLog); + } + else { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInfoLogARB"); + } +} + + +void GLAPIENTRY +_mesa_GetObjectParameterivARB(GLhandleARB object, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + /* Implement in terms of GetProgramiv, GetShaderiv */ + if (ctx->Driver.IsProgram(ctx, object)) { + ctx->Driver.GetProgramiv(ctx, object, pname, params); + } + else if (ctx->Driver.IsShader(ctx, object)) { + ctx->Driver.GetShaderiv(ctx, object, pname, params); + } + else { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetObjectParameterivARB"); + } +} + + +void GLAPIENTRY +_mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname, + GLfloat *params) +{ + GLint iparams[1]; /* XXX is one element enough? */ + _mesa_GetObjectParameterivARB(object, pname, iparams); + params[0] = (GLfloat) iparams[0]; +} + + +void GLAPIENTRY +_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetProgramiv(ctx, program, pname, params); +} + + +void GLAPIENTRY +_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetShaderiv(ctx, shader, pname, params); +} + + +void GLAPIENTRY +_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize, + GLsizei *length, GLchar *infoLog) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetProgramInfoLog(ctx, program, bufSize, length, infoLog); +} + + +void GLAPIENTRY +_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize, + GLsizei *length, GLchar *infoLog) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetShaderInfoLog(ctx, shader, bufSize, length, infoLog); +} + + +void GLAPIENTRY +_mesa_GetShaderSourceARB(GLhandleARB shader, GLsizei maxLength, + GLsizei *length, GLcharARB *sourceOut) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetShaderSource(ctx, shader, maxLength, length, sourceOut); +} + + +void GLAPIENTRY +_mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat * params) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.GetUniformfv(ctx, program, location, params); +} + + +void GLAPIENTRY +_mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint * params) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat fparams[16]; /* XXX is 16 enough? */ + GLuint i; + ctx->Driver.GetUniformfv(ctx, program, location, fparams); + for (i = 0; i < 16; i++) + params[i] = (GLint) fparams[i]; /* XXX correct? */ +} + + + +#if 0 +GLint GLAPIENTRY +_mesa_GetUniformLocation(GLuint program, const GLcharARB *name) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.GetUniformLocation(ctx, program, name); +} +#endif + + +GLhandleARB GLAPIENTRY +_mesa_GetHandleARB(GLenum pname) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.GetHandle(ctx, pname); +} + + +GLint GLAPIENTRY +_mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.GetUniformLocation(ctx, programObj, name); +} + + +GLboolean GLAPIENTRY +_mesa_IsProgram(GLuint name) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.IsProgram(ctx, name); +} + + +GLboolean GLAPIENTRY +_mesa_IsShader(GLuint name) +{ + GET_CURRENT_CONTEXT(ctx); + return ctx->Driver.IsShader(ctx, name); +} + + +void GLAPIENTRY +_mesa_LinkProgramARB(GLhandleARB programObj) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.LinkProgram(ctx, programObj); +} + + +/** + * Called via glShaderSource() and glShaderSourceARB() API functions. + * Basically, concatenate the source code strings into one long string + * and pass it to ctx->Driver.ShaderSource(). + */ +void GLAPIENTRY +_mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count, + const GLcharARB ** string, const GLint * length) +{ + GET_CURRENT_CONTEXT(ctx); + GLint *offsets; + GLsizei i, totalLength; + GLcharARB *source; + + if (string == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB"); + return; + } + + /* + * This array holds offsets of where the appropriate string ends, thus the + * last element will be set to the total length of the source code. + */ + offsets = (GLint *) _mesa_malloc(count * sizeof(GLint)); + if (offsets == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); + return; + } + + for (i = 0; i < count; i++) { + if (string[i] == NULL) { + _mesa_free((GLvoid *) offsets); + _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB(null string)"); + return; + } + if (length == NULL || length[i] < 0) + offsets[i] = _mesa_strlen(string[i]); + else + offsets[i] = length[i]; + /* accumulate string lengths */ + if (i > 0) + offsets[i] += offsets[i - 1]; + } + + /* Total length of source string is sum off all strings plus two. + * One extra byte for terminating zero, another extra byte to silence + * valgrind warnings in the parser/grammer code. + */ + totalLength = offsets[count - 1] + 2; + source = (GLcharARB *) _mesa_malloc(totalLength * sizeof(GLcharARB)); + if (source == NULL) { + _mesa_free((GLvoid *) offsets); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); + return; + } + + for (i = 0; i < count; i++) { + GLint start = (i > 0) ? offsets[i - 1] : 0; + _mesa_memcpy(source + start, string[i], + (offsets[i] - start) * sizeof(GLcharARB)); + } + source[totalLength - 1] = '\0'; + source[totalLength - 2] = '\0'; + + ctx->Driver.ShaderSource(ctx, shaderObj, source); + + _mesa_free(offsets); +} + + +void GLAPIENTRY +_mesa_Uniform1fARB(GLint location, GLfloat v0) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, 1, &v0, GL_FLOAT); +} + +void GLAPIENTRY +_mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[2]; + v[0] = v0; + v[1] = v1; + ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC2); +} + +void GLAPIENTRY +_mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[3]; + v[0] = v0; + v[1] = v1; + v[2] = v2; + ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC3); +} + +void GLAPIENTRY +_mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, + GLfloat v3) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat v[4]; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC4); +} + +void GLAPIENTRY +_mesa_Uniform1iARB(GLint location, GLint v0) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, 1, &v0, GL_INT); +} + +void GLAPIENTRY +_mesa_Uniform2iARB(GLint location, GLint v0, GLint v1) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[2]; + v[0] = v0; + v[1] = v1; + ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC2); +} + +void GLAPIENTRY +_mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[3]; + v[0] = v0; + v[1] = v1; + v[2] = v2; + ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC3); +} + +void GLAPIENTRY +_mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) +{ + GET_CURRENT_CONTEXT(ctx); + GLint v[4]; + v[0] = v0; + v[1] = v1; + v[2] = v2; + v[3] = v3; + ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC4); +} + +void GLAPIENTRY +_mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT); +} + +void GLAPIENTRY +_mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC2); +} + +void GLAPIENTRY +_mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC3); +} + +void GLAPIENTRY +_mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC4); +} + +void GLAPIENTRY +_mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, count, value, GL_INT); +} + +void GLAPIENTRY +_mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC2); +} + +void GLAPIENTRY +_mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC3); +} + +void GLAPIENTRY +_mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC4); +} + + +void GLAPIENTRY +_mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 2, 2, GL_FLOAT_MAT2, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 3, 3, GL_FLOAT_MAT3, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 4, 4, GL_FLOAT_MAT4, + location, count, transpose, value); +} + + +/** + * Non-square UniformMatrix are OpenGL 2.1 + */ +void GLAPIENTRY +_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 2, 3, GL_FLOAT_MAT2x3, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 3, 2, GL_FLOAT_MAT3x2, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 2, 4, GL_FLOAT_MAT2x4, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 4, 2, GL_FLOAT_MAT4x2, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 3, 4, GL_FLOAT_MAT3x4, + location, count, transpose, value); +} + +void GLAPIENTRY +_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.UniformMatrix(ctx, 4, 3, GL_FLOAT_MAT4x3, + location, count, transpose, value); +} + + +void GLAPIENTRY +_mesa_UseProgramObjectARB(GLhandleARB program) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + ctx->Driver.UseProgram(ctx, program); +} + + +void GLAPIENTRY +_mesa_ValidateProgramARB(GLhandleARB program) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Driver.ValidateProgram(ctx, program); +} + diff --git a/dist/Mesa/src/mesa/main/shaders.h b/dist/Mesa/src/mesa/main/shaders.h new file mode 100644 index 000000000..17339ccf6 --- /dev/null +++ b/dist/Mesa/src/mesa/main/shaders.h @@ -0,0 +1,236 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2004-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef SHADERS_H +#define SHADERS_H + + +#include "glheader.h" +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_DeleteObjectARB(GLhandleARB obj); + +extern GLhandleARB GLAPIENTRY +_mesa_GetHandleARB(GLenum pname); + +extern void GLAPIENTRY +_mesa_DetachObjectARB (GLhandleARB, GLhandleARB); + +extern GLhandleARB GLAPIENTRY +_mesa_CreateShaderObjectARB (GLenum); + +extern void GLAPIENTRY +_mesa_ShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *); + +extern void GLAPIENTRY +_mesa_CompileShaderARB (GLhandleARB); + +extern GLhandleARB GLAPIENTRY +_mesa_CreateProgramObjectARB (void); + +extern void GLAPIENTRY +_mesa_AttachObjectARB (GLhandleARB, GLhandleARB); + +extern void GLAPIENTRY +_mesa_LinkProgramARB (GLhandleARB); + +extern void GLAPIENTRY +_mesa_UseProgramObjectARB (GLhandleARB); + +extern void GLAPIENTRY +_mesa_ValidateProgramARB (GLhandleARB); + +extern void GLAPIENTRY +_mesa_Uniform1fARB (GLint, GLfloat); + +extern void GLAPIENTRY +_mesa_Uniform2fARB (GLint, GLfloat, GLfloat); + +extern void GLAPIENTRY +_mesa_Uniform3fARB (GLint, GLfloat, GLfloat, GLfloat); + +extern void GLAPIENTRY +_mesa_Uniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat); + +extern void GLAPIENTRY +_mesa_Uniform1iARB (GLint, GLint); + +extern void GLAPIENTRY +_mesa_Uniform2iARB (GLint, GLint, GLint); + +extern void GLAPIENTRY +_mesa_Uniform3iARB (GLint, GLint, GLint, GLint); + +extern void GLAPIENTRY +_mesa_Uniform4iARB (GLint, GLint, GLint, GLint, GLint); + +extern void GLAPIENTRY +_mesa_Uniform1fvARB (GLint, GLsizei, const GLfloat *); + +extern void GLAPIENTRY +_mesa_Uniform2fvARB (GLint, GLsizei, const GLfloat *); + +extern void GLAPIENTRY +_mesa_Uniform3fvARB (GLint, GLsizei, const GLfloat *); + +extern void GLAPIENTRY +_mesa_Uniform4fvARB (GLint, GLsizei, const GLfloat *); + +extern void GLAPIENTRY +_mesa_Uniform1ivARB (GLint, GLsizei, const GLint *); + +extern void GLAPIENTRY +_mesa_Uniform2ivARB (GLint, GLsizei, const GLint *); + +extern void GLAPIENTRY +_mesa_Uniform3ivARB (GLint, GLsizei, const GLint *); + +extern void GLAPIENTRY +_mesa_Uniform4ivARB (GLint, GLsizei, const GLint *); + +extern void GLAPIENTRY +_mesa_UniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *); + +extern void GLAPIENTRY +_mesa_UniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *); + +extern void GLAPIENTRY +_mesa_UniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *); + +extern void GLAPIENTRY +_mesa_GetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *); + +extern void GLAPIENTRY +_mesa_GetObjectParameterivARB (GLhandleARB, GLenum, GLint *); + +extern void GLAPIENTRY +_mesa_GetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); + +extern void GLAPIENTRY +_mesa_GetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *); + +extern GLint GLAPIENTRY +_mesa_GetUniformLocationARB (GLhandleARB, const GLcharARB *); + +extern void GLAPIENTRY +_mesa_GetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); + +extern void GLAPIENTRY +_mesa_GetUniformfvARB (GLhandleARB, GLint, GLfloat *); + +extern void GLAPIENTRY +_mesa_GetUniformivARB (GLhandleARB, GLint, GLint *); + +extern void GLAPIENTRY +_mesa_GetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); + +#if FEATURE_ARB_vertex_shader + +extern void GLAPIENTRY +_mesa_BindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *); + +extern void GLAPIENTRY +_mesa_GetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); + +extern GLint GLAPIENTRY +_mesa_GetAttribLocationARB (GLhandleARB, const GLcharARB *); + +#endif /* FEATURE_ARB_vertex_shader */ + + +/* 2.0 */ +extern void GLAPIENTRY +_mesa_AttachShader(GLuint program, GLuint shader); + +extern GLuint GLAPIENTRY +_mesa_CreateShader(GLenum); + +extern GLuint GLAPIENTRY +_mesa_CreateProgram(void); + +extern void GLAPIENTRY +_mesa_DeleteProgram(GLuint program); + +extern void GLAPIENTRY +_mesa_DeleteShader(GLuint shader); + +extern void GLAPIENTRY +_mesa_DetachShader(GLuint program, GLuint shader); + +extern void GLAPIENTRY +_mesa_GetAttachedShaders(GLuint program, GLsizei maxCount, + GLsizei *count, GLuint *obj); + +extern void GLAPIENTRY +_mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + +extern void GLAPIENTRY +_mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + +extern GLboolean GLAPIENTRY +_mesa_IsProgram(GLuint program); + +extern GLboolean GLAPIENTRY +_mesa_IsShader(GLuint shader); + + + +/* 2.1 */ +extern void GLAPIENTRY +_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + +extern void GLAPIENTRY +_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, + const GLfloat *value); + + +#endif /* SHADERS_H */ diff --git a/dist/Mesa/src/mesa/shader/prog_debug.c b/dist/Mesa/src/mesa/shader/prog_debug.c new file mode 100644 index 000000000..57929fcbc --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_debug.c @@ -0,0 +1,259 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "nvfragparse.h" +#include "nvvertparse.h" +#include "program.h" +#include "prog_debug.h" +#include "prog_parameter.h" +#include "prog_instruction.h" + + + +/** + * Functions for the experimental GL_MESA_program_debug extension. + */ + + +/* XXX temporary */ +GLAPI void GLAPIENTRY +glProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback, + GLvoid *data) +{ + _mesa_ProgramCallbackMESA(target, callback, data); +} + + +void +_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback, + GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + + switch (target) { + case GL_FRAGMENT_PROGRAM_ARB: + if (!ctx->Extensions.ARB_fragment_program) { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)"); + return; + } + ctx->FragmentProgram.Callback = callback; + ctx->FragmentProgram.CallbackData = data; + break; + case GL_FRAGMENT_PROGRAM_NV: + if (!ctx->Extensions.NV_fragment_program) { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)"); + return; + } + ctx->FragmentProgram.Callback = callback; + ctx->FragmentProgram.CallbackData = data; + break; + case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ + if (!ctx->Extensions.ARB_vertex_program && + !ctx->Extensions.NV_vertex_program) { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)"); + return; + } + ctx->VertexProgram.Callback = callback; + ctx->VertexProgram.CallbackData = data; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramCallbackMESA(target)"); + return; + } +} + + +/* XXX temporary */ +GLAPI void GLAPIENTRY +glGetProgramRegisterfvMESA(GLenum target, + GLsizei len, const GLubyte *registerName, + GLfloat *v) +{ + _mesa_GetProgramRegisterfvMESA(target, len, registerName, v); +} + + +void +_mesa_GetProgramRegisterfvMESA(GLenum target, + GLsizei len, const GLubyte *registerName, + GLfloat *v) +{ + char reg[1000]; + GET_CURRENT_CONTEXT(ctx); + + /* We _should_ be inside glBegin/glEnd */ +#if 0 + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramRegisterfvMESA"); + return; + } +#endif + + /* make null-terminated copy of registerName */ + len = MIN2((unsigned int) len, sizeof(reg) - 1); + _mesa_memcpy(reg, registerName, len); + reg[len] = 0; + + switch (target) { + case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ + if (!ctx->Extensions.ARB_vertex_program && + !ctx->Extensions.NV_vertex_program) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramRegisterfvMESA(target)"); + return; + } + if (!ctx->VertexProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramRegisterfvMESA"); + return; + } + /* GL_NV_vertex_program */ + if (reg[0] == 'R') { + /* Temp register */ + GLint i = _mesa_atoi(reg + 1); + if (i >= (GLint)ctx->Const.VertexProgram.MaxTemps) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + ctx->Driver.GetProgramRegister(ctx, PROGRAM_TEMPORARY, i, v); + } + else if (reg[0] == 'v' && reg[1] == '[') { + /* Vertex Input attribute */ + GLuint i; + for (i = 0; i < ctx->Const.VertexProgram.MaxAttribs; i++) { + const char *name = _mesa_nv_vertex_input_register_name(i); + char number[10]; + _mesa_sprintf(number, "%d", i); + if (_mesa_strncmp(reg + 2, name, 4) == 0 || + _mesa_strncmp(reg + 2, number, _mesa_strlen(number)) == 0) { + ctx->Driver.GetProgramRegister(ctx, PROGRAM_INPUT, i, v); + return; + } + } + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + else if (reg[0] == 'o' && reg[1] == '[') { + /* Vertex output attribute */ + } + /* GL_ARB_vertex_program */ + else if (_mesa_strncmp(reg, "vertex.", 7) == 0) { + + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + break; + case GL_FRAGMENT_PROGRAM_ARB: + if (!ctx->Extensions.ARB_fragment_program) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramRegisterfvMESA(target)"); + return; + } + if (!ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramRegisterfvMESA"); + return; + } + /* XXX to do */ + break; + case GL_FRAGMENT_PROGRAM_NV: + if (!ctx->Extensions.NV_fragment_program) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramRegisterfvMESA(target)"); + return; + } + if (!ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramRegisterfvMESA"); + return; + } + if (reg[0] == 'R') { + /* Temp register */ + GLint i = _mesa_atoi(reg + 1); + if (i >= (GLint)ctx->Const.FragmentProgram.MaxTemps) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + ctx->Driver.GetProgramRegister(ctx, PROGRAM_TEMPORARY, + i, v); + } + else if (reg[0] == 'f' && reg[1] == '[') { + /* Fragment input attribute */ + GLuint i; + for (i = 0; i < ctx->Const.FragmentProgram.MaxAttribs; i++) { + const char *name = _mesa_nv_fragment_input_register_name(i); + if (_mesa_strncmp(reg + 2, name, 4) == 0) { + ctx->Driver.GetProgramRegister(ctx, PROGRAM_INPUT, i, v); + return; + } + } + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + else if (_mesa_strcmp(reg, "o[COLR]") == 0) { + /* Fragment output color */ + ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT, + FRAG_RESULT_COLR, v); + } + else if (_mesa_strcmp(reg, "o[COLH]") == 0) { + /* Fragment output color */ + ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT, + FRAG_RESULT_COLH, v); + } + else if (_mesa_strcmp(reg, "o[DEPR]") == 0) { + /* Fragment output depth */ + ctx->Driver.GetProgramRegister(ctx, PROGRAM_OUTPUT, + FRAG_RESULT_DEPR, v); + } + else { + /* try user-defined identifiers */ + const GLfloat *value = _mesa_lookup_parameter_value( + ctx->FragmentProgram.Current->Base.Parameters, -1, reg); + if (value) { + COPY_4V(v, value); + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, + "glGetProgramRegisterfvMESA(registerName)"); + return; + } + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramRegisterfvMESA(target)"); + return; + } +} diff --git a/dist/Mesa/src/mesa/shader/prog_debug.h b/dist/Mesa/src/mesa/shader/prog_debug.h new file mode 100644 index 000000000..fc400e19d --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_debug.h @@ -0,0 +1,44 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef PROG_DEBUG_H +#define PROG_DEBUG_H 1 + + +/* + * GL_MESA_program_debug + */ + +extern void +_mesa_ProgramCallbackMESA(GLenum target, GLprogramcallbackMESA callback, + GLvoid *data); + +extern void +_mesa_GetProgramRegisterfvMESA(GLenum target, GLsizei len, + const GLubyte *registerName, GLfloat *v); + + + +#endif /* PROG_DEBUG_H */ diff --git a/dist/Mesa/src/mesa/shader/prog_execute.c b/dist/Mesa/src/mesa/shader/prog_execute.c new file mode 100644 index 000000000..9faf9d861 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_execute.c @@ -0,0 +1,1539 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_execute.c + * Software interpreter for vertex/fragment programs. + * \author Brian Paul + */ + +/* + * NOTE: we do everything in single-precision floating point; we don't + * currently observe the single/half/fixed-precision qualifiers. + * + */ + + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "program.h" +#include "prog_execute.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_print.h" +#include "slang_library_noise.h" + + +/* See comments below for info about this */ +#define LAMBDA_ZERO 1 + +/* debug predicate */ +#define DEBUG_PROG 0 + + +/** + * Set x to positive or negative infinity. + */ +#if defined(USE_IEEE) || defined(_WIN32) +#define SET_POS_INFINITY(x) ( *((GLuint *) (void *)&x) = 0x7F800000 ) +#define SET_NEG_INFINITY(x) ( *((GLuint *) (void *)&x) = 0xFF800000 ) +#elif defined(VMS) +#define SET_POS_INFINITY(x) x = __MAXFLOAT +#define SET_NEG_INFINITY(x) x = -__MAXFLOAT +#else +#define SET_POS_INFINITY(x) x = (GLfloat) HUGE_VAL +#define SET_NEG_INFINITY(x) x = (GLfloat) -HUGE_VAL +#endif + +#define SET_FLOAT_BITS(x, bits) ((fi_type *) (void *) &(x))->i = bits + + +static const GLfloat ZeroVec[4] = { 0.0F, 0.0F, 0.0F, 0.0F }; + + + +/** + * Return a pointer to the 4-element float vector specified by the given + * source register. + */ +static INLINE const GLfloat * +get_register_pointer(const struct prog_src_register *source, + const struct gl_program_machine *machine) +{ + if (source->RelAddr) { + const GLint reg = source->Index + machine->AddressReg[0][0]; + if (source->File == PROGRAM_ENV_PARAM) + if (reg < 0 || reg >= MAX_PROGRAM_ENV_PARAMS) + return ZeroVec; + else + return machine->EnvParams[reg]; + else { + const struct gl_program_parameter_list *params; + ASSERT(source->File == PROGRAM_LOCAL_PARAM || + source->File == PROGRAM_STATE_VAR); + params = machine->CurProgram->Parameters; + if (reg < 0 || reg >= params->NumParameters) + return ZeroVec; + else + return params->ParameterValues[reg]; + } + } + + switch (source->File) { + case PROGRAM_TEMPORARY: + ASSERT(source->Index < MAX_PROGRAM_TEMPS); + return machine->Temporaries[source->Index]; + + case PROGRAM_INPUT: + if (machine->CurProgram->Target == GL_VERTEX_PROGRAM_ARB) { + ASSERT(source->Index < VERT_ATTRIB_MAX); + return machine->VertAttribs[source->Index]; + } + else { + ASSERT(source->Index < FRAG_ATTRIB_MAX); + return machine->Attribs[source->Index][machine->CurElement]; + } + + case PROGRAM_OUTPUT: + ASSERT(source->Index < MAX_PROGRAM_OUTPUTS); + return machine->Outputs[source->Index]; + + case PROGRAM_LOCAL_PARAM: + ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS); + return machine->CurProgram->LocalParams[source->Index]; + + case PROGRAM_ENV_PARAM: + ASSERT(source->Index < MAX_PROGRAM_ENV_PARAMS); + return machine->EnvParams[source->Index]; + + case PROGRAM_STATE_VAR: + /* Fallthrough */ + case PROGRAM_CONSTANT: + /* Fallthrough */ + case PROGRAM_UNIFORM: + /* Fallthrough */ + case PROGRAM_NAMED_PARAM: + ASSERT(source->Index < + (GLint) machine->CurProgram->Parameters->NumParameters); + return machine->CurProgram->Parameters->ParameterValues[source->Index]; + + default: + _mesa_problem(NULL, + "Invalid input register file %d in get_register_pointer()", + source->File); + return NULL; + } +} + + +#if FEATURE_MESA_program_debug +static struct gl_program_machine *CurrentMachine = NULL; + +/** + * For GL_MESA_program_debug. + * Return current value (4*GLfloat) of a program register. + * Called via ctx->Driver.GetProgramRegister(). + */ +void +_mesa_get_program_register(GLcontext *ctx, enum register_file file, + GLuint index, GLfloat val[4]) +{ + if (CurrentMachine) { + struct prog_src_register src; + const GLfloat *reg; + src.File = file; + src.Index = index; + reg = get_register_pointer(&src, CurrentMachine); + COPY_4V(val, reg); + } +} +#endif /* FEATURE_MESA_program_debug */ + + +/** + * Fetch a 4-element float vector from the given source register. + * Apply swizzling and negating as needed. + */ +static void +fetch_vector4(const struct prog_src_register *source, + const struct gl_program_machine *machine, GLfloat result[4]) +{ + const GLfloat *src = get_register_pointer(source, machine); + ASSERT(src); + + if (source->Swizzle == SWIZZLE_NOOP) { + /* no swizzling */ + COPY_4V(result, src); + } + else { + ASSERT(GET_SWZ(source->Swizzle, 0) <= 3); + ASSERT(GET_SWZ(source->Swizzle, 1) <= 3); + ASSERT(GET_SWZ(source->Swizzle, 2) <= 3); + ASSERT(GET_SWZ(source->Swizzle, 3) <= 3); + result[0] = src[GET_SWZ(source->Swizzle, 0)]; + result[1] = src[GET_SWZ(source->Swizzle, 1)]; + result[2] = src[GET_SWZ(source->Swizzle, 2)]; + result[3] = src[GET_SWZ(source->Swizzle, 3)]; + } + + if (source->NegateBase) { + result[0] = -result[0]; + result[1] = -result[1]; + result[2] = -result[2]; + result[3] = -result[3]; + } + if (source->Abs) { + result[0] = FABSF(result[0]); + result[1] = FABSF(result[1]); + result[2] = FABSF(result[2]); + result[3] = FABSF(result[3]); + } + if (source->NegateAbs) { + result[0] = -result[0]; + result[1] = -result[1]; + result[2] = -result[2]; + result[3] = -result[3]; + } +} + + +/** + * Fetch the derivative with respect to X or Y for the given register. + * XXX this currently only works for fragment program input attribs. + */ +static void +fetch_vector4_deriv(GLcontext * ctx, + const struct prog_src_register *source, + const struct gl_program_machine *machine, + char xOrY, GLfloat result[4]) +{ + if (source->File == PROGRAM_INPUT && source->Index < machine->NumDeriv) { + const GLint col = machine->CurElement; + const GLfloat w = machine->Attribs[FRAG_ATTRIB_WPOS][col][3]; + const GLfloat invQ = 1.0f / w; + GLfloat deriv[4]; + + if (xOrY == 'X') { + deriv[0] = machine->DerivX[source->Index][0] * invQ; + deriv[1] = machine->DerivX[source->Index][1] * invQ; + deriv[2] = machine->DerivX[source->Index][2] * invQ; + deriv[3] = machine->DerivX[source->Index][3] * invQ; + } + else { + deriv[0] = machine->DerivY[source->Index][0] * invQ; + deriv[1] = machine->DerivY[source->Index][1] * invQ; + deriv[2] = machine->DerivY[source->Index][2] * invQ; + deriv[3] = machine->DerivY[source->Index][3] * invQ; + } + + result[0] = deriv[GET_SWZ(source->Swizzle, 0)]; + result[1] = deriv[GET_SWZ(source->Swizzle, 1)]; + result[2] = deriv[GET_SWZ(source->Swizzle, 2)]; + result[3] = deriv[GET_SWZ(source->Swizzle, 3)]; + + if (source->NegateBase) { + result[0] = -result[0]; + result[1] = -result[1]; + result[2] = -result[2]; + result[3] = -result[3]; + } + if (source->Abs) { + result[0] = FABSF(result[0]); + result[1] = FABSF(result[1]); + result[2] = FABSF(result[2]); + result[3] = FABSF(result[3]); + } + if (source->NegateAbs) { + result[0] = -result[0]; + result[1] = -result[1]; + result[2] = -result[2]; + result[3] = -result[3]; + } + } + else { + ASSIGN_4V(result, 0.0, 0.0, 0.0, 0.0); + } +} + + +/** + * As above, but only return result[0] element. + */ +static void +fetch_vector1(const struct prog_src_register *source, + const struct gl_program_machine *machine, GLfloat result[4]) +{ + const GLfloat *src = get_register_pointer(source, machine); + ASSERT(src); + + result[0] = src[GET_SWZ(source->Swizzle, 0)]; + + if (source->NegateBase) { + result[0] = -result[0]; + } + if (source->Abs) { + result[0] = FABSF(result[0]); + } + if (source->NegateAbs) { + result[0] = -result[0]; + } +} + + +/** + * Test value against zero and return GT, LT, EQ or UN if NaN. + */ +static INLINE GLuint +generate_cc(float value) +{ + if (value != value) + return COND_UN; /* NaN */ + if (value > 0.0F) + return COND_GT; + if (value < 0.0F) + return COND_LT; + return COND_EQ; +} + + +/** + * Test if the ccMaskRule is satisfied by the given condition code. + * Used to mask destination writes according to the current condition code. + */ +static INLINE GLboolean +test_cc(GLuint condCode, GLuint ccMaskRule) +{ + switch (ccMaskRule) { + case COND_EQ: return (condCode == COND_EQ); + case COND_NE: return (condCode != COND_EQ); + case COND_LT: return (condCode == COND_LT); + case COND_GE: return (condCode == COND_GT || condCode == COND_EQ); + case COND_LE: return (condCode == COND_LT || condCode == COND_EQ); + case COND_GT: return (condCode == COND_GT); + case COND_TR: return GL_TRUE; + case COND_FL: return GL_FALSE; + default: return GL_TRUE; + } +} + + +/** + * Evaluate the 4 condition codes against a predicate and return GL_TRUE + * or GL_FALSE to indicate result. + */ +static INLINE GLboolean +eval_condition(const struct gl_program_machine *machine, + const struct prog_instruction *inst) +{ + const GLuint swizzle = inst->DstReg.CondSwizzle; + const GLuint condMask = inst->DstReg.CondMask; + if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) || + test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) || + test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) || + test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + + +/** + * Store 4 floats into a register. Observe the instructions saturate and + * set-condition-code flags. + */ +static void +store_vector4(const struct prog_instruction *inst, + struct gl_program_machine *machine, const GLfloat value[4]) +{ + const struct prog_dst_register *dest = &(inst->DstReg); + const GLboolean clamp = inst->SaturateMode == SATURATE_ZERO_ONE; + GLfloat *dstReg; + GLfloat dummyReg[4]; + GLfloat clampedValue[4]; + GLuint writeMask = dest->WriteMask; + + switch (dest->File) { + case PROGRAM_OUTPUT: + ASSERT(dest->Index < MAX_PROGRAM_OUTPUTS); + dstReg = machine->Outputs[dest->Index]; + break; + case PROGRAM_TEMPORARY: + ASSERT(dest->Index < MAX_PROGRAM_TEMPS); + dstReg = machine->Temporaries[dest->Index]; + break; + case PROGRAM_WRITE_ONLY: + dstReg = dummyReg; + return; + default: + _mesa_problem(NULL, "bad register file in store_vector4(fp)"); + return; + } + +#if 0 + if (value[0] > 1.0e10 || + IS_INF_OR_NAN(value[0]) || + IS_INF_OR_NAN(value[1]) || + IS_INF_OR_NAN(value[2]) || IS_INF_OR_NAN(value[3])) + printf("store %g %g %g %g\n", value[0], value[1], value[2], value[3]); +#endif + + if (clamp) { + clampedValue[0] = CLAMP(value[0], 0.0F, 1.0F); + clampedValue[1] = CLAMP(value[1], 0.0F, 1.0F); + clampedValue[2] = CLAMP(value[2], 0.0F, 1.0F); + clampedValue[3] = CLAMP(value[3], 0.0F, 1.0F); + value = clampedValue; + } + + if (dest->CondMask != COND_TR) { + /* condition codes may turn off some writes */ + if (writeMask & WRITEMASK_X) { + if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 0)], + dest->CondMask)) + writeMask &= ~WRITEMASK_X; + } + if (writeMask & WRITEMASK_Y) { + if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 1)], + dest->CondMask)) + writeMask &= ~WRITEMASK_Y; + } + if (writeMask & WRITEMASK_Z) { + if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 2)], + dest->CondMask)) + writeMask &= ~WRITEMASK_Z; + } + if (writeMask & WRITEMASK_W) { + if (!test_cc(machine->CondCodes[GET_SWZ(dest->CondSwizzle, 3)], + dest->CondMask)) + writeMask &= ~WRITEMASK_W; + } + } + + if (writeMask & WRITEMASK_X) + dstReg[0] = value[0]; + if (writeMask & WRITEMASK_Y) + dstReg[1] = value[1]; + if (writeMask & WRITEMASK_Z) + dstReg[2] = value[2]; + if (writeMask & WRITEMASK_W) + dstReg[3] = value[3]; + + if (inst->CondUpdate) { + if (writeMask & WRITEMASK_X) + machine->CondCodes[0] = generate_cc(value[0]); + if (writeMask & WRITEMASK_Y) + machine->CondCodes[1] = generate_cc(value[1]); + if (writeMask & WRITEMASK_Z) + machine->CondCodes[2] = generate_cc(value[2]); + if (writeMask & WRITEMASK_W) + machine->CondCodes[3] = generate_cc(value[3]); +#if DEBUG_PROG + printf("CondCodes=(%s,%s,%s,%s) for:\n", + _mesa_condcode_string(machine->CondCodes[0]), + _mesa_condcode_string(machine->CondCodes[1]), + _mesa_condcode_string(machine->CondCodes[2]), + _mesa_condcode_string(machine->CondCodes[3])); +#endif + } +} + + +/** + * Execute the given vertex/fragment program. + * + * \param ctx rendering context + * \param program the program to execute + * \param machine machine state (must be initialized) + * \return GL_TRUE if program completed or GL_FALSE if program executed KIL. + */ +GLboolean +_mesa_execute_program(GLcontext * ctx, + const struct gl_program *program, + struct gl_program_machine *machine) +{ + const GLuint numInst = program->NumInstructions; + const GLuint maxExec = 10000; + GLint pc, numExec = 0; + + machine->CurProgram = program; + + if (DEBUG_PROG) { + printf("execute program %u --------------------\n", program->Id); + } + +#if FEATURE_MESA_program_debug + CurrentMachine = machine; +#endif + + if (program->Target == GL_VERTEX_PROGRAM_ARB) { + machine->EnvParams = ctx->VertexProgram.Parameters; + } + else { + machine->EnvParams = ctx->FragmentProgram.Parameters; + } + + for (pc = 0; pc < numInst; pc++) { + const struct prog_instruction *inst = program->Instructions + pc; + +#if FEATURE_MESA_program_debug + if (ctx->FragmentProgram.CallbackEnabled && + ctx->FragmentProgram.Callback) { + ctx->FragmentProgram.CurrentPosition = inst->StringPos; + ctx->FragmentProgram.Callback(program->Target, + ctx->FragmentProgram.CallbackData); + } +#endif + + if (DEBUG_PROG) { + _mesa_print_instruction(inst); + } + + switch (inst->Opcode) { + case OPCODE_ABS: + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = FABSF(a[0]); + result[1] = FABSF(a[1]); + result[2] = FABSF(a[2]); + result[3] = FABSF(a[3]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_ADD: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = a[0] + b[0]; + result[1] = a[1] + b[1]; + result[2] = a[2] + b[2]; + result[3] = a[3] + b[3]; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("ADD (%g %g %g %g) = (%g %g %g %g) + (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_ARL: + { + GLfloat t[4]; + fetch_vector4(&inst->SrcReg[0], machine, t); + machine->AddressReg[0][0] = (GLint) FLOORF(t[0]); + } + break; + case OPCODE_BGNLOOP: + /* no-op */ + break; + case OPCODE_ENDLOOP: + /* subtract 1 here since pc is incremented by for(pc) loop */ + pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */ + break; + case OPCODE_BGNSUB: /* begin subroutine */ + break; + case OPCODE_ENDSUB: /* end subroutine */ + break; + case OPCODE_BRA: /* branch (conditional) */ + /* fall-through */ + case OPCODE_BRK: /* break out of loop (conditional) */ + /* fall-through */ + case OPCODE_CONT: /* continue loop (conditional) */ + if (eval_condition(machine, inst)) { + /* take branch */ + /* Subtract 1 here since we'll do pc++ at end of for-loop */ + pc = inst->BranchTarget - 1; + } + break; + case OPCODE_CAL: /* Call subroutine (conditional) */ + if (eval_condition(machine, inst)) { + /* call the subroutine */ + if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) { + return GL_TRUE; /* Per GL_NV_vertex_program2 spec */ + } + machine->CallStack[machine->StackDepth++] = pc + 1; /* next inst */ + /* Subtract 1 here since we'll do pc++ at end of for-loop */ + pc = inst->BranchTarget - 1; + } + break; + case OPCODE_CMP: + { + GLfloat a[4], b[4], c[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + fetch_vector4(&inst->SrcReg[2], machine, c); + result[0] = a[0] < 0.0F ? b[0] : c[0]; + result[1] = a[1] < 0.0F ? b[1] : c[1]; + result[2] = a[2] < 0.0F ? b[2] : c[2]; + result[3] = a[3] < 0.0F ? b[3] : c[3]; + store_vector4(inst, machine, result); + } + break; + case OPCODE_COS: + { + GLfloat a[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + result[0] = result[1] = result[2] = result[3] + = (GLfloat) _mesa_cos(a[0]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_DDX: /* Partial derivative with respect to X */ + { + GLfloat result[4]; + fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine, + 'X', result); + store_vector4(inst, machine, result); + } + break; + case OPCODE_DDY: /* Partial derivative with respect to Y */ + { + GLfloat result[4]; + fetch_vector4_deriv(ctx, &inst->SrcReg[0], machine, + 'Y', result); + store_vector4(inst, machine, result); + } + break; + case OPCODE_DP3: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = result[1] = result[2] = result[3] = DOT3(a, b); + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("DP3 %g = (%g %g %g) . (%g %g %g)\n", + result[0], a[0], a[1], a[2], b[0], b[1], b[2]); + } + } + break; + case OPCODE_DP4: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = result[1] = result[2] = result[3] = DOT4(a, b); + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("DP4 %g = (%g, %g %g %g) . (%g, %g %g %g)\n", + result[0], a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_DPH: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = result[1] = result[2] = result[3] = + a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + b[3]; + store_vector4(inst, machine, result); + } + break; + case OPCODE_DST: /* Distance vector */ + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = 1.0F; + result[1] = a[1] * b[1]; + result[2] = a[2]; + result[3] = b[3]; + store_vector4(inst, machine, result); + } + break; + case OPCODE_EXP: + { + GLfloat t[4], q[4], floor_t0; + fetch_vector1(&inst->SrcReg[0], machine, t); + floor_t0 = FLOORF(t[0]); + if (floor_t0 > FLT_MAX_EXP) { + SET_POS_INFINITY(q[0]); + SET_POS_INFINITY(q[2]); + } + else if (floor_t0 < FLT_MIN_EXP) { + q[0] = 0.0F; + q[2] = 0.0F; + } + else { + q[0] = LDEXPF(1.0, (int) floor_t0); + /* Note: GL_NV_vertex_program expects + * result.z = result.x * APPX(result.y) + * We do what the ARB extension says. + */ + q[2] = pow(2.0, t[0]); + } + q[1] = t[0] - floor_t0; + q[3] = 1.0F; + store_vector4( inst, machine, q ); + } + break; + case OPCODE_EX2: /* Exponential base 2 */ + { + GLfloat a[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + result[0] = result[1] = result[2] = result[3] = + (GLfloat) _mesa_pow(2.0, a[0]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_FLR: + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = FLOORF(a[0]); + result[1] = FLOORF(a[1]); + result[2] = FLOORF(a[2]); + result[3] = FLOORF(a[3]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_FRC: + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = a[0] - FLOORF(a[0]); + result[1] = a[1] - FLOORF(a[1]); + result[2] = a[2] - FLOORF(a[2]); + result[3] = a[3] - FLOORF(a[3]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_IF: + { + GLboolean cond; + /* eval condition */ + if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { + GLfloat a[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + cond = (a[0] != 0.0); + } + else { + cond = eval_condition(machine, inst); + } + if (DEBUG_PROG) { + printf("IF: %d\n", cond); + } + /* do if/else */ + if (cond) { + /* do if-clause (just continue execution) */ + } + else { + /* go to the instruction after ELSE or ENDIF */ + assert(inst->BranchTarget >= 0); + pc = inst->BranchTarget - 1; + } + } + break; + case OPCODE_ELSE: + /* goto ENDIF */ + assert(inst->BranchTarget >= 0); + pc = inst->BranchTarget - 1; + break; + case OPCODE_ENDIF: + /* nothing */ + break; + case OPCODE_INT: /* float to int */ + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = (GLfloat) (GLint) a[0]; + result[1] = (GLfloat) (GLint) a[1]; + result[2] = (GLfloat) (GLint) a[2]; + result[3] = (GLfloat) (GLint) a[3]; + store_vector4(inst, machine, result); + } + break; + case OPCODE_KIL_NV: /* NV_f_p only (conditional) */ + if (eval_condition(machine, inst)) { + return GL_FALSE; + } + break; + case OPCODE_KIL: /* ARB_f_p only */ + { + GLfloat a[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + if (a[0] < 0.0F || a[1] < 0.0F || a[2] < 0.0F || a[3] < 0.0F) { + return GL_FALSE; + } + } + break; + case OPCODE_LG2: /* log base 2 */ + { + GLfloat a[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + result[0] = result[1] = result[2] = result[3] = LOG2(a[0]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_LIT: + { + const GLfloat epsilon = 1.0F / 256.0F; /* from NV VP spec */ + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + a[0] = MAX2(a[0], 0.0F); + a[1] = MAX2(a[1], 0.0F); + /* XXX ARB version clamps a[3], NV version doesn't */ + a[3] = CLAMP(a[3], -(128.0F - epsilon), (128.0F - epsilon)); + result[0] = 1.0F; + result[1] = a[0]; + /* XXX we could probably just use pow() here */ + if (a[0] > 0.0F) { + if (a[1] == 0.0 && a[3] == 0.0) + result[2] = 1.0; + else + result[2] = EXPF(a[3] * LOGF(a[1])); + } + else { + result[2] = 0.0; + } + result[3] = 1.0F; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("LIT (%g %g %g %g) : (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3]); + } + } + break; + case OPCODE_LOG: + { + GLfloat t[4], q[4], abs_t0; + fetch_vector1(&inst->SrcReg[0], machine, t); + abs_t0 = FABSF(t[0]); + if (abs_t0 != 0.0F) { + /* Since we really can't handle infinite values on VMS + * like other OSes we'll use __MAXFLOAT to represent + * infinity. This may need some tweaking. + */ +#ifdef VMS + if (abs_t0 == __MAXFLOAT) +#else + if (IS_INF_OR_NAN(abs_t0)) +#endif + { + SET_POS_INFINITY(q[0]); + q[1] = 1.0F; + SET_POS_INFINITY(q[2]); + } + else { + int exponent; + GLfloat mantissa = FREXPF(t[0], &exponent); + q[0] = (GLfloat) (exponent - 1); + q[1] = (GLfloat) (2.0 * mantissa); /* map [.5, 1) -> [1, 2) */ + q[2] = (GLfloat) (q[0] + LOG2(q[1])); + } + } + else { + SET_NEG_INFINITY(q[0]); + q[1] = 1.0F; + SET_NEG_INFINITY(q[2]); + } + q[3] = 1.0; + store_vector4(inst, machine, q); + } + break; + case OPCODE_LRP: + { + GLfloat a[4], b[4], c[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + fetch_vector4(&inst->SrcReg[2], machine, c); + result[0] = a[0] * b[0] + (1.0F - a[0]) * c[0]; + result[1] = a[1] * b[1] + (1.0F - a[1]) * c[1]; + result[2] = a[2] * b[2] + (1.0F - a[2]) * c[2]; + result[3] = a[3] * b[3] + (1.0F - a[3]) * c[3]; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("LRP (%g %g %g %g) = (%g %g %g %g), " + "(%g %g %g %g), (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]); + } + } + break; + case OPCODE_MAD: + { + GLfloat a[4], b[4], c[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + fetch_vector4(&inst->SrcReg[2], machine, c); + result[0] = a[0] * b[0] + c[0]; + result[1] = a[1] * b[1] + c[1]; + result[2] = a[2] * b[2] + c[2]; + result[3] = a[3] * b[3] + c[3]; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("MAD (%g %g %g %g) = (%g %g %g %g) * " + "(%g %g %g %g) + (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3]); + } + } + break; + case OPCODE_MAX: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = MAX2(a[0], b[0]); + result[1] = MAX2(a[1], b[1]); + result[2] = MAX2(a[2], b[2]); + result[3] = MAX2(a[3], b[3]); + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("MAX (%g %g %g %g) = (%g %g %g %g), (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_MIN: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = MIN2(a[0], b[0]); + result[1] = MIN2(a[1], b[1]); + result[2] = MIN2(a[2], b[2]); + result[3] = MIN2(a[3], b[3]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_MOV: + { + GLfloat result[4]; + fetch_vector4(&inst->SrcReg[0], machine, result); + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("MOV (%g %g %g %g)\n", + result[0], result[1], result[2], result[3]); + } + } + break; + case OPCODE_MUL: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = a[0] * b[0]; + result[1] = a[1] * b[1]; + result[2] = a[2] * b[2]; + result[3] = a[3] * b[3]; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("MUL (%g %g %g %g) = (%g %g %g %g) * (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_NOISE1: + { + GLfloat a[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + result[0] = + result[1] = + result[2] = result[3] = _slang_library_noise1(a[0]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_NOISE2: + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = + result[1] = + result[2] = result[3] = _slang_library_noise2(a[0], a[1]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_NOISE3: + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = + result[1] = + result[2] = + result[3] = _slang_library_noise3(a[0], a[1], a[2]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_NOISE4: + { + GLfloat a[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + result[0] = + result[1] = + result[2] = + result[3] = _slang_library_noise4(a[0], a[1], a[2], a[3]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_NOP: + break; + case OPCODE_PK2H: /* pack two 16-bit floats in one 32-bit float */ + { + GLfloat a[4], result[4]; + GLhalfNV hx, hy; + GLuint *rawResult = (GLuint *) result; + GLuint twoHalves; + fetch_vector4(&inst->SrcReg[0], machine, a); + hx = _mesa_float_to_half(a[0]); + hy = _mesa_float_to_half(a[1]); + twoHalves = hx | (hy << 16); + rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3] + = twoHalves; + store_vector4(inst, machine, result); + } + break; + case OPCODE_PK2US: /* pack two GLushorts into one 32-bit float */ + { + GLfloat a[4], result[4]; + GLuint usx, usy, *rawResult = (GLuint *) result; + fetch_vector4(&inst->SrcReg[0], machine, a); + a[0] = CLAMP(a[0], 0.0F, 1.0F); + a[1] = CLAMP(a[1], 0.0F, 1.0F); + usx = IROUND(a[0] * 65535.0F); + usy = IROUND(a[1] * 65535.0F); + rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3] + = usx | (usy << 16); + store_vector4(inst, machine, result); + } + break; + case OPCODE_PK4B: /* pack four GLbytes into one 32-bit float */ + { + GLfloat a[4], result[4]; + GLuint ubx, uby, ubz, ubw, *rawResult = (GLuint *) result; + fetch_vector4(&inst->SrcReg[0], machine, a); + a[0] = CLAMP(a[0], -128.0F / 127.0F, 1.0F); + a[1] = CLAMP(a[1], -128.0F / 127.0F, 1.0F); + a[2] = CLAMP(a[2], -128.0F / 127.0F, 1.0F); + a[3] = CLAMP(a[3], -128.0F / 127.0F, 1.0F); + ubx = IROUND(127.0F * a[0] + 128.0F); + uby = IROUND(127.0F * a[1] + 128.0F); + ubz = IROUND(127.0F * a[2] + 128.0F); + ubw = IROUND(127.0F * a[3] + 128.0F); + rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3] + = ubx | (uby << 8) | (ubz << 16) | (ubw << 24); + store_vector4(inst, machine, result); + } + break; + case OPCODE_PK4UB: /* pack four GLubytes into one 32-bit float */ + { + GLfloat a[4], result[4]; + GLuint ubx, uby, ubz, ubw, *rawResult = (GLuint *) result; + fetch_vector4(&inst->SrcReg[0], machine, a); + a[0] = CLAMP(a[0], 0.0F, 1.0F); + a[1] = CLAMP(a[1], 0.0F, 1.0F); + a[2] = CLAMP(a[2], 0.0F, 1.0F); + a[3] = CLAMP(a[3], 0.0F, 1.0F); + ubx = IROUND(255.0F * a[0]); + uby = IROUND(255.0F * a[1]); + ubz = IROUND(255.0F * a[2]); + ubw = IROUND(255.0F * a[3]); + rawResult[0] = rawResult[1] = rawResult[2] = rawResult[3] + = ubx | (uby << 8) | (ubz << 16) | (ubw << 24); + store_vector4(inst, machine, result); + } + break; + case OPCODE_POW: + { + GLfloat a[4], b[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + fetch_vector1(&inst->SrcReg[1], machine, b); + result[0] = result[1] = result[2] = result[3] + = (GLfloat) _mesa_pow(a[0], b[0]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_RCP: + { + GLfloat a[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + if (DEBUG_PROG) { + if (a[0] == 0) + printf("RCP(0)\n"); + else if (IS_INF_OR_NAN(a[0])) + printf("RCP(inf)\n"); + } + result[0] = result[1] = result[2] = result[3] = 1.0F / a[0]; + store_vector4(inst, machine, result); + } + break; + case OPCODE_RET: /* return from subroutine (conditional) */ + if (eval_condition(machine, inst)) { + if (machine->StackDepth == 0) { + return GL_TRUE; /* Per GL_NV_vertex_program2 spec */ + } + /* subtract one because of pc++ in the for loop */ + pc = machine->CallStack[--machine->StackDepth] - 1; + } + break; + case OPCODE_RFL: /* reflection vector */ + { + GLfloat axis[4], dir[4], result[4], tmpX, tmpW; + fetch_vector4(&inst->SrcReg[0], machine, axis); + fetch_vector4(&inst->SrcReg[1], machine, dir); + tmpW = DOT3(axis, axis); + tmpX = (2.0F * DOT3(axis, dir)) / tmpW; + result[0] = tmpX * axis[0] - dir[0]; + result[1] = tmpX * axis[1] - dir[1]; + result[2] = tmpX * axis[2] - dir[2]; + /* result[3] is never written! XXX enforce in parser! */ + store_vector4(inst, machine, result); + } + break; + case OPCODE_RSQ: /* 1 / sqrt() */ + { + GLfloat a[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + a[0] = FABSF(a[0]); + result[0] = result[1] = result[2] = result[3] = INV_SQRTF(a[0]); + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("RSQ %g = 1/sqrt(|%g|)\n", result[0], a[0]); + } + } + break; + case OPCODE_SCS: /* sine and cos */ + { + GLfloat a[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + result[0] = (GLfloat) _mesa_cos(a[0]); + result[1] = (GLfloat) _mesa_sin(a[0]); + result[2] = 0.0; /* undefined! */ + result[3] = 0.0; /* undefined! */ + store_vector4(inst, machine, result); + } + break; + case OPCODE_SEQ: /* set on equal */ + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = (a[0] == b[0]) ? 1.0F : 0.0F; + result[1] = (a[1] == b[1]) ? 1.0F : 0.0F; + result[2] = (a[2] == b[2]) ? 1.0F : 0.0F; + result[3] = (a[3] == b[3]) ? 1.0F : 0.0F; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("SEQ (%g %g %g %g) = (%g %g %g %g) == (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_SFL: /* set false, operands ignored */ + { + static const GLfloat result[4] = { 0.0F, 0.0F, 0.0F, 0.0F }; + store_vector4(inst, machine, result); + } + break; + case OPCODE_SGE: /* set on greater or equal */ + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = (a[0] >= b[0]) ? 1.0F : 0.0F; + result[1] = (a[1] >= b[1]) ? 1.0F : 0.0F; + result[2] = (a[2] >= b[2]) ? 1.0F : 0.0F; + result[3] = (a[3] >= b[3]) ? 1.0F : 0.0F; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("SGE (%g %g %g %g) = (%g %g %g %g) >= (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_SGT: /* set on greater */ + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = (a[0] > b[0]) ? 1.0F : 0.0F; + result[1] = (a[1] > b[1]) ? 1.0F : 0.0F; + result[2] = (a[2] > b[2]) ? 1.0F : 0.0F; + result[3] = (a[3] > b[3]) ? 1.0F : 0.0F; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("SGT (%g %g %g %g) = (%g %g %g %g) > (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_SIN: + { + GLfloat a[4], result[4]; + fetch_vector1(&inst->SrcReg[0], machine, a); + result[0] = result[1] = result[2] = result[3] + = (GLfloat) _mesa_sin(a[0]); + store_vector4(inst, machine, result); + } + break; + case OPCODE_SLE: /* set on less or equal */ + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = (a[0] <= b[0]) ? 1.0F : 0.0F; + result[1] = (a[1] <= b[1]) ? 1.0F : 0.0F; + result[2] = (a[2] <= b[2]) ? 1.0F : 0.0F; + result[3] = (a[3] <= b[3]) ? 1.0F : 0.0F; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("SLE (%g %g %g %g) = (%g %g %g %g) <= (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_SLT: /* set on less */ + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = (a[0] < b[0]) ? 1.0F : 0.0F; + result[1] = (a[1] < b[1]) ? 1.0F : 0.0F; + result[2] = (a[2] < b[2]) ? 1.0F : 0.0F; + result[3] = (a[3] < b[3]) ? 1.0F : 0.0F; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("SLT (%g %g %g %g) = (%g %g %g %g) < (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_SNE: /* set on not equal */ + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = (a[0] != b[0]) ? 1.0F : 0.0F; + result[1] = (a[1] != b[1]) ? 1.0F : 0.0F; + result[2] = (a[2] != b[2]) ? 1.0F : 0.0F; + result[3] = (a[3] != b[3]) ? 1.0F : 0.0F; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("SNE (%g %g %g %g) = (%g %g %g %g) != (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], + b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_STR: /* set true, operands ignored */ + { + static const GLfloat result[4] = { 1.0F, 1.0F, 1.0F, 1.0F }; + store_vector4(inst, machine, result); + } + break; + case OPCODE_SUB: + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = a[0] - b[0]; + result[1] = a[1] - b[1]; + result[2] = a[2] - b[2]; + result[3] = a[3] - b[3]; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("SUB (%g %g %g %g) = (%g %g %g %g) - (%g %g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3]); + } + } + break; + case OPCODE_SWZ: /* extended swizzle */ + { + const struct prog_src_register *source = &inst->SrcReg[0]; + const GLfloat *src = get_register_pointer(source, machine); + GLfloat result[4]; + GLuint i; + for (i = 0; i < 4; i++) { + const GLuint swz = GET_SWZ(source->Swizzle, i); + if (swz == SWIZZLE_ZERO) + result[i] = 0.0; + else if (swz == SWIZZLE_ONE) + result[i] = 1.0; + else { + ASSERT(swz >= 0); + ASSERT(swz <= 3); + result[i] = src[swz]; + } + if (source->NegateBase & (1 << i)) + result[i] = -result[i]; + } + store_vector4(inst, machine, result); + } + break; + case OPCODE_TEX: /* Both ARB and NV frag prog */ + /* Texel lookup */ + { + /* Note: only use the precomputed lambda value when we're + * sampling texture unit [K] with texcoord[K]. + * Otherwise, the lambda value may have no relation to the + * instruction's texcoord or texture image. Using the wrong + * lambda is usually bad news. + * The rest of the time, just use zero (until we get a more + * sophisticated way of computing lambda). + */ + GLfloat coord[4], color[4], lambda; +#if 0 + if (inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit) + lambda = span->array->lambda[inst->TexSrcUnit][column]; + else +#endif + lambda = 0.0; + fetch_vector4(&inst->SrcReg[0], machine, coord); + machine->FetchTexelLod(ctx, coord, lambda, inst->TexSrcUnit, + color); + if (DEBUG_PROG) { + printf("TEX (%g, %g, %g, %g) = texture[%d][%g, %g, %g, %g], " + "lod %f\n", + color[0], color[1], color[2], color[3], + inst->TexSrcUnit, + coord[0], coord[1], coord[2], coord[3], lambda); + } + store_vector4(inst, machine, color); + } + break; + case OPCODE_TXB: /* GL_ARB_fragment_program only */ + /* Texel lookup with LOD bias */ + { + const struct gl_texture_unit *texUnit + = &ctx->Texture.Unit[inst->TexSrcUnit]; + GLfloat coord[4], color[4], lambda, bias; +#if 0 + if (inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit) + lambda = span->array->lambda[inst->TexSrcUnit][column]; + else +#endif + lambda = 0.0; + fetch_vector4(&inst->SrcReg[0], machine, coord); + /* coord[3] is the bias to add to lambda */ + bias = texUnit->LodBias + coord[3]; + if (texUnit->_Current) + bias += texUnit->_Current->LodBias; + machine->FetchTexelLod(ctx, coord, lambda + bias, + inst->TexSrcUnit, color); + store_vector4(inst, machine, color); + } + break; + case OPCODE_TXD: /* GL_NV_fragment_program only */ + /* Texture lookup w/ partial derivatives for LOD */ + { + GLfloat texcoord[4], dtdx[4], dtdy[4], color[4]; + fetch_vector4(&inst->SrcReg[0], machine, texcoord); + fetch_vector4(&inst->SrcReg[1], machine, dtdx); + fetch_vector4(&inst->SrcReg[2], machine, dtdy); + machine->FetchTexelDeriv(ctx, texcoord, dtdx, dtdy, + inst->TexSrcUnit, color); + store_vector4(inst, machine, color); + } + break; + case OPCODE_TXP: /* GL_ARB_fragment_program only */ + /* Texture lookup w/ projective divide */ + { + GLfloat texcoord[4], color[4], lambda; +#if 0 + if (inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit) + lambda = span->array->lambda[inst->TexSrcUnit][column]; + else +#endif + lambda = 0.0; + fetch_vector4(&inst->SrcReg[0], machine, texcoord); + /* Not so sure about this test - if texcoord[3] is + * zero, we'd probably be fine except for an ASSERT in + * IROUND_POS() which gets triggered by the inf values created. + */ + if (texcoord[3] != 0.0) { + texcoord[0] /= texcoord[3]; + texcoord[1] /= texcoord[3]; + texcoord[2] /= texcoord[3]; + } + machine->FetchTexelLod(ctx, texcoord, lambda, + inst->TexSrcUnit, color); + store_vector4(inst, machine, color); + } + break; + case OPCODE_TXP_NV: /* GL_NV_fragment_program only */ + /* Texture lookup w/ projective divide */ + { + GLfloat texcoord[4], color[4], lambda; +#if 0 + if (inst->SrcReg[0].File == PROGRAM_INPUT && + inst->SrcReg[0].Index == FRAG_ATTRIB_TEX0 + inst->TexSrcUnit) + lambda = span->array->lambda[inst->TexSrcUnit][column]; + else +#endif + lambda = 0.0; + fetch_vector4(&inst->SrcReg[0], machine, texcoord); + if (inst->TexSrcTarget != TEXTURE_CUBE_INDEX && + texcoord[3] != 0.0) { + texcoord[0] /= texcoord[3]; + texcoord[1] /= texcoord[3]; + texcoord[2] /= texcoord[3]; + } + machine->FetchTexelLod(ctx, texcoord, lambda, + inst->TexSrcUnit, color); + store_vector4(inst, machine, color); + } + break; + case OPCODE_UP2H: /* unpack two 16-bit floats */ + { + GLfloat a[4], result[4]; + const GLuint *rawBits = (const GLuint *) a; + GLhalfNV hx, hy; + fetch_vector1(&inst->SrcReg[0], machine, a); + hx = rawBits[0] & 0xffff; + hy = rawBits[0] >> 16; + result[0] = result[2] = _mesa_half_to_float(hx); + result[1] = result[3] = _mesa_half_to_float(hy); + store_vector4(inst, machine, result); + } + break; + case OPCODE_UP2US: /* unpack two GLushorts */ + { + GLfloat a[4], result[4]; + const GLuint *rawBits = (const GLuint *) a; + GLushort usx, usy; + fetch_vector1(&inst->SrcReg[0], machine, a); + usx = rawBits[0] & 0xffff; + usy = rawBits[0] >> 16; + result[0] = result[2] = usx * (1.0f / 65535.0f); + result[1] = result[3] = usy * (1.0f / 65535.0f); + store_vector4(inst, machine, result); + } + break; + case OPCODE_UP4B: /* unpack four GLbytes */ + { + GLfloat a[4], result[4]; + const GLuint *rawBits = (const GLuint *) a; + fetch_vector1(&inst->SrcReg[0], machine, a); + result[0] = (((rawBits[0] >> 0) & 0xff) - 128) / 127.0F; + result[1] = (((rawBits[0] >> 8) & 0xff) - 128) / 127.0F; + result[2] = (((rawBits[0] >> 16) & 0xff) - 128) / 127.0F; + result[3] = (((rawBits[0] >> 24) & 0xff) - 128) / 127.0F; + store_vector4(inst, machine, result); + } + break; + case OPCODE_UP4UB: /* unpack four GLubytes */ + { + GLfloat a[4], result[4]; + const GLuint *rawBits = (const GLuint *) a; + fetch_vector1(&inst->SrcReg[0], machine, a); + result[0] = ((rawBits[0] >> 0) & 0xff) / 255.0F; + result[1] = ((rawBits[0] >> 8) & 0xff) / 255.0F; + result[2] = ((rawBits[0] >> 16) & 0xff) / 255.0F; + result[3] = ((rawBits[0] >> 24) & 0xff) / 255.0F; + store_vector4(inst, machine, result); + } + break; + case OPCODE_XPD: /* cross product */ + { + GLfloat a[4], b[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + result[0] = a[1] * b[2] - a[2] * b[1]; + result[1] = a[2] * b[0] - a[0] * b[2]; + result[2] = a[0] * b[1] - a[1] * b[0]; + result[3] = 1.0; + store_vector4(inst, machine, result); + if (DEBUG_PROG) { + printf("XPD (%g %g %g %g) = (%g %g %g) X (%g %g %g)\n", + result[0], result[1], result[2], result[3], + a[0], a[1], a[2], b[0], b[1], b[2]); + } + } + break; + case OPCODE_X2D: /* 2-D matrix transform */ + { + GLfloat a[4], b[4], c[4], result[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + fetch_vector4(&inst->SrcReg[1], machine, b); + fetch_vector4(&inst->SrcReg[2], machine, c); + result[0] = a[0] + b[0] * c[0] + b[1] * c[1]; + result[1] = a[1] + b[0] * c[2] + b[1] * c[3]; + result[2] = a[2] + b[0] * c[0] + b[1] * c[1]; + result[3] = a[3] + b[0] * c[2] + b[1] * c[3]; + store_vector4(inst, machine, result); + } + break; + case OPCODE_PRINT: + { + if (inst->SrcReg[0].File != -1) { + GLfloat a[4]; + fetch_vector4(&inst->SrcReg[0], machine, a); + _mesa_printf("%s%g, %g, %g, %g\n", (const char *) inst->Data, + a[0], a[1], a[2], a[3]); + } + else { + _mesa_printf("%s\n", (const char *) inst->Data); + } + } + break; + case OPCODE_END: + return GL_TRUE; + default: + _mesa_problem(ctx, "Bad opcode %d in _mesa_exec_fragment_program", + inst->Opcode); + return GL_TRUE; /* return value doesn't matter */ + + } + + numExec++; + if (numExec > maxExec) { + _mesa_problem(ctx, "Infinite loop detected in fragment program"); + return GL_TRUE; + } + + } /* for pc */ + +#if FEATURE_MESA_program_debug + CurrentMachine = NULL; +#endif + + return GL_TRUE; +} diff --git a/dist/Mesa/src/mesa/shader/prog_execute.h b/dist/Mesa/src/mesa/shader/prog_execute.h new file mode 100644 index 000000000..be29eceed --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_execute.h @@ -0,0 +1,84 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PROG_EXECUTE_H +#define PROG_EXECUTE_H + + +typedef void (*FetchTexelLodFunc)(GLcontext *ctx, const GLfloat texcoord[4], + GLfloat lambda, GLuint unit, GLfloat color[4]); + +typedef void (*FetchTexelDerivFunc)(GLcontext *ctx, const GLfloat texcoord[4], + const GLfloat texdx[4], + const GLfloat texdy[4], + GLuint unit, GLfloat color[4]); + + +/** The larger of VERT_RESULT_MAX, FRAG_RESULT_MAX */ +#define MAX_PROGRAM_OUTPUTS VERT_RESULT_MAX + + +/** + * Virtual machine state used during execution of vertex/fragment programs. + */ +struct gl_program_machine +{ + const struct gl_program *CurProgram; + + /** Fragment Input attributes */ + GLfloat (*Attribs)[MAX_WIDTH][4]; + GLfloat (*DerivX)[4]; + GLfloat (*DerivY)[4]; + GLuint NumDeriv; /**< Max index into DerivX/Y arrays */ + GLuint CurElement; /**< Index into Attribs arrays */ + + /** Vertex Input attribs */ + GLfloat VertAttribs[VERT_ATTRIB_MAX][4]; + + GLfloat Temporaries[MAX_PROGRAM_TEMPS][4]; + GLfloat Outputs[MAX_PROGRAM_OUTPUTS][4]; + GLfloat (*EnvParams)[4]; /**< Vertex or Fragment env parameters */ + GLuint CondCodes[4]; /**< COND_* value for x/y/z/w */ + GLint AddressReg[MAX_PROGRAM_ADDRESS_REGS][4]; + + GLuint CallStack[MAX_PROGRAM_CALL_DEPTH]; /**< For CAL/RET instructions */ + GLuint StackDepth; /**< Index/ptr to top of CallStack[] */ + + /** Texture fetch functions */ + FetchTexelLodFunc FetchTexelLod; + FetchTexelDerivFunc FetchTexelDeriv; +}; + + +extern void +_mesa_get_program_register(GLcontext *ctx, enum register_file file, + GLuint index, GLfloat val[4]); + +extern GLboolean +_mesa_execute_program(GLcontext *ctx, + const struct gl_program *program, + struct gl_program_machine *machine); + + +#endif /* PROG_EXECUTE_H */ diff --git a/dist/Mesa/src/mesa/shader/prog_instruction.c b/dist/Mesa/src/mesa/shader/prog_instruction.c new file mode 100644 index 000000000..d6b5652a2 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_instruction.c @@ -0,0 +1,245 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "mtypes.h" +#include "prog_instruction.h" + + +/** + * Initialize program instruction fields to defaults. + * \param inst first instruction to initialize + * \param count number of instructions to initialize + */ +void +_mesa_init_instructions(struct prog_instruction *inst, GLuint count) +{ + GLuint i; + + _mesa_bzero(inst, count * sizeof(struct prog_instruction)); + + for (i = 0; i < count; i++) { + inst[i].SrcReg[0].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; + inst[i].SrcReg[1].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; + inst[i].SrcReg[2].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP; + + inst[i].DstReg.File = PROGRAM_UNDEFINED; + inst[i].DstReg.WriteMask = WRITEMASK_XYZW; + inst[i].DstReg.CondMask = COND_TR; + inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP; + + inst[i].SaturateMode = SATURATE_OFF; + inst[i].Precision = FLOAT32; + } +} + + +/** + * Allocate an array of program instructions. + * \param numInst number of instructions + * \return pointer to instruction memory + */ +struct prog_instruction * +_mesa_alloc_instructions(GLuint numInst) +{ + return (struct prog_instruction *) + _mesa_calloc(numInst * sizeof(struct prog_instruction)); +} + + +/** + * Reallocate memory storing an array of program instructions. + * This is used when we need to append additional instructions onto an + * program. + * \param oldInst pointer to first of old/src instructions + * \param numOldInst number of instructions at <oldInst> + * \param numNewInst desired size of new instruction array. + * \return pointer to start of new instruction array. + */ +struct prog_instruction * +_mesa_realloc_instructions(struct prog_instruction *oldInst, + GLuint numOldInst, GLuint numNewInst) +{ + struct prog_instruction *newInst; + + newInst = (struct prog_instruction *) + _mesa_realloc(oldInst, + numOldInst * sizeof(struct prog_instruction), + numNewInst * sizeof(struct prog_instruction)); + + return newInst; +} + + +/** + * Copy an array of program instructions. + * \param dest pointer to destination. + * \param src pointer to source. + * \param n number of instructions to copy. + * \return pointer to destination. + */ +struct prog_instruction * +_mesa_copy_instructions(struct prog_instruction *dest, + const struct prog_instruction *src, GLuint n) +{ + GLuint i; + _mesa_memcpy(dest, src, n * sizeof(struct prog_instruction)); + for (i = 0; i < n; i++) { + if (src[i].Comment) + dest[i].Comment = _mesa_strdup(src[i].Comment); + } + return dest; +} + + +/** + * Basic info about each instruction + */ +struct instruction_info +{ + gl_inst_opcode Opcode; + const char *Name; + GLuint NumSrcRegs; +}; + +/** + * Instruction info + * \note Opcode should equal array index! + */ +static const struct instruction_info InstInfo[MAX_OPCODE] = { + { OPCODE_NOP, "NOP", 0 }, + { OPCODE_ABS, "ABS", 1 }, + { OPCODE_ADD, "ADD", 2 }, + { OPCODE_ARA, "ARA", 1 }, + { OPCODE_ARL, "ARL", 1 }, + { OPCODE_ARL_NV, "ARL", 1 }, + { OPCODE_ARR, "ARL", 1 }, + { OPCODE_BGNLOOP,"BGNLOOP", 0 }, + { OPCODE_BGNSUB, "BGNSUB", 0 }, + { OPCODE_BRA, "BRA", 0 }, + { OPCODE_BRK, "BRK", 0 }, + { OPCODE_CAL, "CAL", 0 }, + { OPCODE_CMP, "CMP", 3 }, + { OPCODE_CONT, "CONT", 0 }, + { OPCODE_COS, "COS", 1 }, + { OPCODE_DDX, "DDX", 1 }, + { OPCODE_DDY, "DDY", 1 }, + { OPCODE_DP3, "DP3", 2 }, + { OPCODE_DP4, "DP4", 2 }, + { OPCODE_DPH, "DPH", 2 }, + { OPCODE_DST, "DST", 2 }, + { OPCODE_ELSE, "ELSE", 0 }, + { OPCODE_END, "END", 0 }, + { OPCODE_ENDIF, "ENDIF", 0 }, + { OPCODE_ENDLOOP,"ENDLOOP", 0 }, + { OPCODE_ENDSUB, "ENDSUB", 0 }, + { OPCODE_EX2, "EX2", 1 }, + { OPCODE_EXP, "EXP", 1 }, + { OPCODE_FLR, "FLR", 1 }, + { OPCODE_FRC, "FRC", 1 }, + { OPCODE_IF, "IF", 0 }, + { OPCODE_INT, "INT", 1 }, + { OPCODE_KIL, "KIL", 1 }, + { OPCODE_KIL_NV, "KIL", 0 }, + { OPCODE_LG2, "LG2", 1 }, + { OPCODE_LIT, "LIT", 1 }, + { OPCODE_LOG, "LOG", 1 }, + { OPCODE_LRP, "LRP", 3 }, + { OPCODE_MAD, "MAD", 3 }, + { OPCODE_MAX, "MAX", 2 }, + { OPCODE_MIN, "MIN", 2 }, + { OPCODE_MOV, "MOV", 1 }, + { OPCODE_MUL, "MUL", 2 }, + { OPCODE_NOISE1, "NOISE1", 1 }, + { OPCODE_NOISE2, "NOISE2", 1 }, + { OPCODE_NOISE3, "NOISE3", 1 }, + { OPCODE_NOISE4, "NOISE4", 1 }, + { OPCODE_PK2H, "PK2H", 1 }, + { OPCODE_PK2US, "PK2US", 1 }, + { OPCODE_PK4B, "PK4B", 1 }, + { OPCODE_PK4UB, "PK4UB", 1 }, + { OPCODE_POW, "POW", 2 }, + { OPCODE_POPA, "POPA", 0 }, + { OPCODE_PRINT, "PRINT", 1 }, + { OPCODE_PUSHA, "PUSHA", 0 }, + { OPCODE_RCC, "RCC", 1 }, + { OPCODE_RCP, "RCP", 1 }, + { OPCODE_RET, "RET", 0 }, + { OPCODE_RFL, "RFL", 1 }, + { OPCODE_RSQ, "RSQ", 1 }, + { OPCODE_SCS, "SCS", 1 }, + { OPCODE_SEQ, "SEQ", 2 }, + { OPCODE_SFL, "SFL", 0 }, + { OPCODE_SGE, "SGE", 2 }, + { OPCODE_SGT, "SGT", 2 }, + { OPCODE_SIN, "SIN", 1 }, + { OPCODE_SLE, "SLE", 2 }, + { OPCODE_SLT, "SLT", 2 }, + { OPCODE_SNE, "SNE", 2 }, + { OPCODE_SSG, "SSG", 1 }, + { OPCODE_STR, "STR", 0 }, + { OPCODE_SUB, "SUB", 2 }, + { OPCODE_SWZ, "SWZ", 1 }, + { OPCODE_TEX, "TEX", 1 }, + { OPCODE_TXB, "TXB", 1 }, + { OPCODE_TXD, "TXD", 3 }, + { OPCODE_TXL, "TXL", 1 }, + { OPCODE_TXP, "TXP", 1 }, + { OPCODE_TXP_NV, "TXP", 1 }, + { OPCODE_UP2H, "UP2H", 1 }, + { OPCODE_UP2US, "UP2US", 1 }, + { OPCODE_UP4B, "UP4B", 1 }, + { OPCODE_UP4UB, "UP4UB", 1 }, + { OPCODE_X2D, "X2D", 3 }, + { OPCODE_XPD, "XPD", 2 } +}; + + +/** + * Return the number of src registers for the given instruction/opcode. + */ +GLuint +_mesa_num_inst_src_regs(gl_inst_opcode opcode) +{ + ASSERT(opcode == InstInfo[opcode].Opcode); + ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode); + return InstInfo[opcode].NumSrcRegs; +} + + +/** + * Return string name for given program opcode. + */ +const char * +_mesa_opcode_string(gl_inst_opcode opcode) +{ + ASSERT(opcode < MAX_OPCODE); + return InstInfo[opcode].Name; +} + diff --git a/dist/Mesa/src/mesa/shader/prog_instruction.h b/dist/Mesa/src/mesa/shader/prog_instruction.h new file mode 100644 index 000000000..c800757aa --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_instruction.h @@ -0,0 +1,447 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file prog_instruction.h + * + * Vertex/fragment program instruction datatypes and constants. + * + * \author Brian Paul + * \author Keith Whitwell + * \author Ian Romanick <idr@us.ibm.com> + */ + + +#ifndef PROG_INSTRUCTION_H +#define PROG_INSTRUCTION_H + + +/** + * Swizzle indexes. + * Do not change! + */ +/*@{*/ +#define SWIZZLE_X 0 +#define SWIZZLE_Y 1 +#define SWIZZLE_Z 2 +#define SWIZZLE_W 3 +#define SWIZZLE_ZERO 4 /**< For SWZ instruction only */ +#define SWIZZLE_ONE 5 /**< For SWZ instruction only */ +#define SWIZZLE_NIL 7 /**< used during shader code gen (undefined value) */ +/*@}*/ + +#define MAKE_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<3) | ((c)<<6) | ((d)<<9)) +#define SWIZZLE_NOOP MAKE_SWIZZLE4(0,1,2,3) +#define GET_SWZ(swz, idx) (((swz) >> ((idx)*3)) & 0x7) +#define GET_BIT(msk, idx) (((msk) >> (idx)) & 0x1) + +#define SWIZZLE_XYZW MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W) +#define SWIZZLE_XXXX MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X) +#define SWIZZLE_YYYY MAKE_SWIZZLE4(SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y) +#define SWIZZLE_ZZZZ MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z) +#define SWIZZLE_WWWW MAKE_SWIZZLE4(SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W) + + +/** + * Writemask values, 1 bit per component. + */ +/*@{*/ +#define WRITEMASK_X 0x1 +#define WRITEMASK_Y 0x2 +#define WRITEMASK_XY 0x3 +#define WRITEMASK_Z 0x4 +#define WRITEMASK_XZ 0x5 +#define WRITEMASK_YZ 0x6 +#define WRITEMASK_XYZ 0x7 +#define WRITEMASK_W 0x8 +#define WRITEMASK_XW 0x9 +#define WRITEMASK_YW 0xa +#define WRITEMASK_XYW 0xb +#define WRITEMASK_ZW 0xc +#define WRITEMASK_XZW 0xd +#define WRITEMASK_YZW 0xe +#define WRITEMASK_XYZW 0xf +/*@}*/ + + +/** + * Condition codes + */ +/*@{*/ +#define COND_GT 1 /**< greater than zero */ +#define COND_EQ 2 /**< equal to zero */ +#define COND_LT 3 /**< less than zero */ +#define COND_UN 4 /**< unordered (NaN) */ +#define COND_GE 5 /**< greater then or equal to zero */ +#define COND_LE 6 /**< less then or equal to zero */ +#define COND_NE 7 /**< not equal to zero */ +#define COND_TR 8 /**< always true */ +#define COND_FL 9 /**< always false */ +/*@}*/ + + +/** + * Instruction precision for GL_NV_fragment_program + */ +/*@{*/ +#define FLOAT32 0x1 +#define FLOAT16 0x2 +#define FIXED12 0x4 +/*@}*/ + + +/** + * Saturation modes when storing values. + */ +/*@{*/ +#define SATURATE_OFF 0 +#define SATURATE_ZERO_ONE 1 +#define SATURATE_PLUS_MINUS_ONE 2 +/*@}*/ + + +/** + * Per-component negation masks + */ +/*@{*/ +#define NEGATE_X 0x1 +#define NEGATE_Y 0x2 +#define NEGATE_Z 0x4 +#define NEGATE_W 0x8 +#define NEGATE_XYZW 0xf +#define NEGATE_NONE 0x0 +/*@}*/ + + +/** + * Program instruction opcodes, for both vertex and fragment programs. + * \note changes to this opcode list must be reflected in t_vb_arbprogram.c + */ +typedef enum prog_opcode { + /* ARB_vp ARB_fp NV_vp NV_fp GLSL */ + /*------------------------------------------*/ + OPCODE_NOP = 0, /* X */ + OPCODE_ABS, /* X X 1.1 X */ + OPCODE_ADD, /* X X X X X */ + OPCODE_ARA, /* 2 */ + OPCODE_ARL, /* X X */ + OPCODE_ARL_NV, /* 2 */ + OPCODE_ARR, /* 2 */ + OPCODE_BGNLOOP, /* opt */ + OPCODE_BGNSUB, /* opt */ + OPCODE_BRA, /* 2 X */ + OPCODE_BRK, /* 2 opt */ + OPCODE_CAL, /* 2 2 */ + OPCODE_CMP, /* X */ + OPCODE_CONT, /* opt */ + OPCODE_COS, /* X 2 X X */ + OPCODE_DDX, /* X X */ + OPCODE_DDY, /* X X */ + OPCODE_DP3, /* X X X X X */ + OPCODE_DP4, /* X X X X X */ + OPCODE_DPH, /* X X 1.1 */ + OPCODE_DST, /* X X X X */ + OPCODE_ELSE, /* X */ + OPCODE_END, /* X X X X opt */ + OPCODE_ENDIF, /* opt */ + OPCODE_ENDLOOP, /* opt */ + OPCODE_ENDSUB, /* opt */ + OPCODE_EX2, /* X X 2 X X */ + OPCODE_EXP, /* X X X */ + OPCODE_FLR, /* X X 2 X X */ + OPCODE_FRC, /* X X 2 X X */ + OPCODE_IF, /* opt */ + OPCODE_INT, /* X */ + OPCODE_KIL, /* X */ + OPCODE_KIL_NV, /* X X */ + OPCODE_LG2, /* X X 2 X X */ + OPCODE_LIT, /* X X X X */ + OPCODE_LOG, /* X X X */ + OPCODE_LRP, /* X X */ + OPCODE_MAD, /* X X X X X */ + OPCODE_MAX, /* X X X X X */ + OPCODE_MIN, /* X X X X X */ + OPCODE_MOV, /* X X X X X */ + OPCODE_MUL, /* X X X X X */ + OPCODE_NOISE1, /* X */ + OPCODE_NOISE2, /* X */ + OPCODE_NOISE3, /* X */ + OPCODE_NOISE4, /* X */ + OPCODE_PK2H, /* X */ + OPCODE_PK2US, /* X */ + OPCODE_PK4B, /* X */ + OPCODE_PK4UB, /* X */ + OPCODE_POW, /* X X X X */ + OPCODE_POPA, /* 3 */ + OPCODE_PRINT, /* X X */ + OPCODE_PUSHA, /* 3 */ + OPCODE_RCC, /* 1.1 */ + OPCODE_RCP, /* X X X X X */ + OPCODE_RET, /* 2 2 */ + OPCODE_RFL, /* X X */ + OPCODE_RSQ, /* X X X X X */ + OPCODE_SCS, /* X */ + OPCODE_SEQ, /* 2 X X */ + OPCODE_SFL, /* 2 X */ + OPCODE_SGE, /* X X X X X */ + OPCODE_SGT, /* 2 X X */ + OPCODE_SIN, /* X 2 X X */ + OPCODE_SLE, /* 2 X X */ + OPCODE_SLT, /* X X X X X */ + OPCODE_SNE, /* 2 X X */ + OPCODE_SSG, /* 2 */ + OPCODE_STR, /* 2 X */ + OPCODE_SUB, /* X X 1.1 X X */ + OPCODE_SWZ, /* X X */ + OPCODE_TEX, /* X 3 X X */ + OPCODE_TXB, /* X 3 X */ + OPCODE_TXD, /* X X */ + OPCODE_TXL, /* 3 2 X */ + OPCODE_TXP, /* X X */ + OPCODE_TXP_NV, /* 3 X */ + OPCODE_UP2H, /* X */ + OPCODE_UP2US, /* X */ + OPCODE_UP4B, /* X */ + OPCODE_UP4UB, /* X */ + OPCODE_X2D, /* X */ + OPCODE_XPD, /* X X X */ + MAX_OPCODE +} gl_inst_opcode; + + +/** + * Instruction source register. + */ +struct prog_src_register +{ + GLuint File:4; /**< One of the PROGRAM_* register file values. */ + GLint Index:9; /**< May be negative for relative addressing. */ + GLuint Swizzle:12; + GLuint RelAddr:1; + + /** + * \name Source register "sign" control. + * + * The ARB and NV extensions allow varrying degrees of control over the + * sign of the source vector components. These values allow enough control + * for all flavors of the extensions. + */ + /*@{*/ + /** + * Per-component negation for the SWZ instruction. For non-SWZ + * instructions the only possible values are NEGATE_XYZW and NEGATE_NONE. + * + * \since + * ARB_vertex_program, ARB_fragment_program + */ + GLuint NegateBase:4; + + /** + * Take the component-wise absolute value. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint Abs:1; + + /** + * Post-absolute value negation (all components). + */ + GLuint NegateAbs:1; + /*@}*/ +}; + + +/** + * Instruction destination register. + */ +struct prog_dst_register +{ + /** + * One of the PROGRAM_* register file values. + */ + GLuint File:4; + + GLuint Index:8; + GLuint WriteMask:4; + + /** + * \name Conditional destination update control. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + /*@{*/ + /** + * Takes one of the 9 possible condition values (EQ, FL, GT, GE, LE, LT, + * NE, TR, or UN). Dest reg is only written to if the matching + * (swizzled) condition code value passes. When a conditional update mask + * is not specified, this will be \c COND_TR. + */ + GLuint CondMask:4; + + /** + * Condition code swizzle value. + */ + GLuint CondSwizzle:12; + + /** + * Selects the condition code register to use for conditional destination + * update masking. In NV_fragmnet_program or NV_vertex_program2 mode, only + * condition code register 0 is available. In NV_vertex_program3 mode, + * condition code registers 0 and 1 are available. + */ + GLuint CondSrc:1; + /*@}*/ + + GLuint pad:31; +}; + + +/** + * Vertex/fragment program instruction. + */ +struct prog_instruction +{ + gl_inst_opcode Opcode; +#if FEATURE_MESA_program_debug + GLshort StringPos; +#endif + /** + * Arbitrary data. Used for the PRINT, CAL, and BRA instructions. + */ + void *Data; + + struct prog_src_register SrcReg[3]; + struct prog_dst_register DstReg; + + /** + * Indicates that the instruction should update the condition code + * register. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint CondUpdate:1; + + /** + * If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the + * condition code register that is to be updated. + * + * In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition + * code register 0 is available. In GL_NV_vertex_program3 mode, condition + * code registers 0 and 1 are available. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint CondDst:1; + + /** + * Saturate each value of the vectored result to the range [0,1] or the + * range [-1,1]. \c SSAT mode (i.e., saturation to the range [-1,1]) is + * only available in NV_fragment_program2 mode. + * Value is one of the SATURATE_* tokens. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program3. + */ + GLuint SaturateMode:2; + + /** + * Per-instruction selectable precision. + * + * \since + * NV_fragment_program, NV_fragment_program_option. + */ + GLuint Precision:3; + + /** + * \name Texture source controls. + * + * The texture source controls are only used with the \c TEX, \c TXD, + * \c TXL, and \c TXP instructions. + * + * \since + * ARB_fragment_program, NV_fragment_program, NV_vertex_program3. + */ + /*@{*/ + /** + * Source texture unit. OpenGL supports a maximum of 32 texture + * units. + */ + GLuint TexSrcUnit:5; + + /** + * Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX. + */ + GLuint TexSrcTarget:3; + /*@}*/ + + /** + * For BRA and CAL instructions, the location to jump to. + * For BGNLOOP, points to ENDLOOP (and vice-versa). + * For BRK, points to BGNLOOP (which points to ENDLOOP). + * For IF, points to else or endif. + * For ELSE, points to endif. + */ + GLint BranchTarget; + + /** + * For TEX instructions in shaders, the sampler to use for the + * texture lookup. + */ + GLint Sampler; + + const char *Comment; +}; + + +extern void +_mesa_init_instructions(struct prog_instruction *inst, GLuint count); + +extern struct prog_instruction * +_mesa_alloc_instructions(GLuint numInst); + +extern struct prog_instruction * +_mesa_realloc_instructions(struct prog_instruction *oldInst, + GLuint numOldInst, GLuint numNewInst); + +extern struct prog_instruction * +_mesa_copy_instructions(struct prog_instruction *dest, + const struct prog_instruction *src, GLuint n); + +extern GLuint +_mesa_num_inst_src_regs(gl_inst_opcode opcode); + +extern const char * +_mesa_opcode_string(gl_inst_opcode opcode); + + +#endif /* PROG_INSTRUCTION_H */ diff --git a/dist/Mesa/src/mesa/shader/prog_parameter.c b/dist/Mesa/src/mesa/shader/prog_parameter.c new file mode 100644 index 000000000..9e3d3fecf --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_parameter.c @@ -0,0 +1,643 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_parameter.c + * Program parameter lists and functions. + * \author Brian Paul + */ + + +#include "glheader.h" +#include "imports.h" +#include "macros.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_statevars.h" + + +struct gl_program_parameter_list * +_mesa_new_parameter_list(void) +{ + return (struct gl_program_parameter_list *) + _mesa_calloc(sizeof(struct gl_program_parameter_list)); +} + + +/** + * Free a parameter list and all its parameters + */ +void +_mesa_free_parameter_list(struct gl_program_parameter_list *paramList) +{ + GLuint i; + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name) + _mesa_free((void *) paramList->Parameters[i].Name); + } + _mesa_free(paramList->Parameters); + if (paramList->ParameterValues) + _mesa_align_free(paramList->ParameterValues); + _mesa_free(paramList); +} + + + +/** + * Add a new parameter to a parameter list. + * Note that parameter values are usually 4-element GLfloat vectors. + * When size > 4 we'll allocate a sequential block of parameters to + * store all the values (in blocks of 4). + * + * \param paramList the list to add the parameter to + * \param type type of parameter, such as + * \param name the parameter name, will be duplicated/copied! + * \param size number of elements in 'values' vector (1..4, or more) + * \param values initial parameter value, up to 4 GLfloats, or NULL + * \param state state indexes, or NULL + * \return index of new parameter in the list, or -1 if error (out of mem) + */ +GLint +_mesa_add_parameter(struct gl_program_parameter_list *paramList, + enum register_file type, const char *name, + GLuint size, GLenum datatype, const GLfloat *values, + const gl_state_index state[STATE_LENGTH]) +{ + const GLuint oldNum = paramList->NumParameters; + const GLuint sz4 = (size + 3) / 4; /* no. of new param slots needed */ + + assert(size > 0); + + if (oldNum + sz4 > paramList->Size) { + /* Need to grow the parameter list array (alloc some extra) */ + paramList->Size = paramList->Size + 4 * sz4; + + /* realloc arrays */ + paramList->Parameters = (struct gl_program_parameter *) + _mesa_realloc(paramList->Parameters, + oldNum * sizeof(struct gl_program_parameter), + paramList->Size * sizeof(struct gl_program_parameter)); + + paramList->ParameterValues = (GLfloat (*)[4]) + _mesa_align_realloc(paramList->ParameterValues, /* old buf */ + oldNum * 4 * sizeof(GLfloat), /* old size */ + paramList->Size * 4 *sizeof(GLfloat), /* new sz */ + 16); + } + + if (!paramList->Parameters || + !paramList->ParameterValues) { + /* out of memory */ + paramList->NumParameters = 0; + paramList->Size = 0; + return -1; + } + else { + GLuint i; + + paramList->NumParameters = oldNum + sz4; + + _mesa_memset(¶mList->Parameters[oldNum], 0, + sz4 * sizeof(struct gl_program_parameter)); + + for (i = 0; i < sz4; i++) { + struct gl_program_parameter *p = paramList->Parameters + oldNum + i; + p->Name = name ? _mesa_strdup(name) : NULL; + p->Type = type; + p->Size = size; + p->DataType = datatype; + if (values) { + COPY_4V(paramList->ParameterValues[oldNum + i], values); + values += 4; + } + else { + /* silence valgrind */ + ASSIGN_4V(paramList->ParameterValues[oldNum + i], 0, 0, 0, 0); + } + size -= 4; + } + + if (state) { + for (i = 0; i < STATE_LENGTH; i++) + paramList->Parameters[oldNum].StateIndexes[i] = state[i]; + } + + return (GLint) oldNum; + } +} + + +/** + * Add a new named program parameter (Ex: NV_fragment_program DEFINE statement) + * \return index of the new entry in the parameter list + */ +GLint +_mesa_add_named_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4]) +{ + return _mesa_add_parameter(paramList, PROGRAM_NAMED_PARAM, name, + 4, GL_NONE, values, NULL); + +} + + +/** + * Add a new named constant to the parameter list. + * This will be used when the program contains something like this: + * PARAM myVals = { 0, 1, 2, 3 }; + * + * \param paramList the parameter list + * \param name the name for the constant + * \param values four float values + * \return index/position of the new parameter in the parameter list + */ +GLint +_mesa_add_named_constant(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], + GLuint size) +{ +#if 0 /* disable this for now -- we need to save the name! */ + GLint pos; + GLuint swizzle; + ASSERT(size == 4); /* XXX future feature */ + /* check if we already have this constant */ + if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) { + return pos; + } +#endif + size = 4; /** XXX fix */ + return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name, + size, GL_NONE, values, NULL); +} + + +/** + * Add a new unnamed constant to the parameter list. This will be used + * when a fragment/vertex program contains something like this: + * MOV r, { 0, 1, 2, 3 }; + * We'll search the parameter list for an existing instance of the + * constant. If swizzleOut is non-null, we'll try swizzling when + * looking for a match. + * + * \param paramList the parameter list + * \param values four float values + * \param swizzleOut returns swizzle mask for accessing the constant + * \return index/position of the new parameter in the parameter list. + */ +GLint +_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, + const GLfloat values[4], GLuint size, + GLuint *swizzleOut) +{ + GLint pos; + ASSERT(size >= 1); + ASSERT(size <= 4); + + if (_mesa_lookup_parameter_constant(paramList, values, + size, &pos, swizzleOut)) { + return pos; + } + + /* Look for empty space in an already unnamed constant parameter + * to add this constant. This will only work for single-element + * constants because we rely on smearing (i.e. .yyyy or .zzzz). + */ + if (size == 1 && swizzleOut) { + for (pos = 0; pos < (GLint) paramList->NumParameters; pos++) { + struct gl_program_parameter *p = paramList->Parameters + pos; + if (p->Type == PROGRAM_CONSTANT && p->Size + size <= 4) { + /* ok, found room */ + GLfloat *pVal = paramList->ParameterValues[pos]; + GLuint swz = p->Size; /* 1, 2 or 3 for Y, Z, W */ + pVal[p->Size] = values[0]; + p->Size++; + *swizzleOut = MAKE_SWIZZLE4(swz, swz, swz, swz); + return pos; + } + } + } + + /* add a new parameter to store this constant */ + pos = _mesa_add_parameter(paramList, PROGRAM_CONSTANT, NULL, + size, GL_NONE, values, NULL); + if (pos >= 0 && swizzleOut) { + if (size == 1) + *swizzleOut = SWIZZLE_XXXX; + else + *swizzleOut = SWIZZLE_NOOP; + } + return pos; +} + + +/** + * Add a uniform to the parameter list. + * Note that if the uniform is an array, size may be greater than + * what's implied by the datatype. + * \param name uniform's name + * \param size number of floats to allocate + * \param datatype GL_FLOAT_VEC3, GL_FLOAT_MAT4, etc. + */ +GLint +_mesa_add_uniform(struct gl_program_parameter_list *paramList, + const char *name, GLuint size, GLenum datatype) +{ + GLint i = _mesa_lookup_parameter_index(paramList, -1, name); + ASSERT(datatype != GL_NONE); + if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_UNIFORM) { + ASSERT(paramList->Parameters[i].Size == size); + ASSERT(paramList->Parameters[i].DataType == datatype); + /* already in list */ + return i; + } + else { + i = _mesa_add_parameter(paramList, PROGRAM_UNIFORM, name, + size, datatype, NULL, NULL); + return i; + } +} + + +/** + * Add a sampler to the parameter list. + * \param name uniform's name + * \param datatype GL_SAMPLER_2D, GL_SAMPLER_2D_RECT_ARB, etc. + */ +GLint +_mesa_add_sampler(struct gl_program_parameter_list *paramList, + const char *name, GLenum datatype) +{ + GLint i = _mesa_lookup_parameter_index(paramList, -1, name); + if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_SAMPLER) { + ASSERT(paramList->Parameters[i].Size == 1); + ASSERT(paramList->Parameters[i].DataType == datatype); + /* already in list */ + return i; + } + else { + const GLint size = 1; /* a sampler is basically a texture unit number */ + i = _mesa_add_parameter(paramList, PROGRAM_SAMPLER, name, + size, datatype, NULL, NULL); + return i; + } +} + + +/** + * Add parameter representing a varying variable. + */ +GLint +_mesa_add_varying(struct gl_program_parameter_list *paramList, + const char *name, GLuint size) +{ + GLint i = _mesa_lookup_parameter_index(paramList, -1, name); + if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_VARYING) { + /* already in list */ + return i; + } + else { + assert(size == 4); + i = _mesa_add_parameter(paramList, PROGRAM_VARYING, name, + size, GL_NONE, NULL, NULL); + return i; + } +} + + +/** + * Add parameter representing a vertex program attribute. + * \param size size of attribute (in floats), may be -1 if unknown + * \param attrib the attribute index, or -1 if unknown + */ +GLint +_mesa_add_attribute(struct gl_program_parameter_list *paramList, + const char *name, GLint size, GLint attrib) +{ + GLint i = _mesa_lookup_parameter_index(paramList, -1, name); + if (i >= 0) { + /* replace */ + if (attrib < 0) + attrib = i; + paramList->Parameters[i].StateIndexes[0] = attrib; + } + else { + /* add */ + gl_state_index state[STATE_LENGTH]; + state[0] = (gl_state_index) attrib; + if (size < 0) + size = 4; + i = _mesa_add_parameter(paramList, PROGRAM_INPUT, name, + size, GL_NONE, NULL, state); + } + return i; +} + + + +#if 0 /* not used yet */ +/** + * Returns the number of 4-component registers needed to store a piece + * of GL state. For matrices this may be as many as 4 registers, + * everything else needs + * just 1 register. + */ +static GLuint +sizeof_state_reference(const GLint *stateTokens) +{ + if (stateTokens[0] == STATE_MATRIX) { + GLuint rows = stateTokens[4] - stateTokens[3] + 1; + assert(rows >= 1); + assert(rows <= 4); + return rows; + } + else { + return 1; + } +} +#endif + + +/** + * Add a new state reference to the parameter list. + * This will be used when the program contains something like this: + * PARAM ambient = state.material.front.ambient; + * + * \param paramList the parameter list + * \param state an array of 6 (STATE_LENGTH) state tokens + * \return index of the new parameter. + */ +GLint +_mesa_add_state_reference(struct gl_program_parameter_list *paramList, + const gl_state_index stateTokens[STATE_LENGTH]) +{ + const GLuint size = 4; /* XXX fix */ + const char *name; + GLint index; + + /* Check if the state reference is already in the list */ + for (index = 0; index < (GLint) paramList->NumParameters; index++) { + GLuint i, match = 0; + for (i = 0; i < STATE_LENGTH; i++) { + if (paramList->Parameters[index].StateIndexes[i] == stateTokens[i]) { + match++; + } + else { + break; + } + } + if (match == STATE_LENGTH) { + /* this state reference is already in the parameter list */ + return index; + } + } + + name = _mesa_program_state_string(stateTokens); + index = _mesa_add_parameter(paramList, PROGRAM_STATE_VAR, name, + size, GL_NONE, + NULL, (gl_state_index *) stateTokens); + paramList->StateFlags |= _mesa_program_state_flags(stateTokens); + + /* free name string here since we duplicated it in add_parameter() */ + _mesa_free((void *) name); + + return index; +} + + +/** + * Lookup a parameter value by name in the given parameter list. + * \return pointer to the float[4] values. + */ +GLfloat * +_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name) +{ + GLuint i = _mesa_lookup_parameter_index(paramList, nameLen, name); + if (i < 0) + return NULL; + else + return paramList->ParameterValues[i]; +} + + +/** + * Given a program parameter name, find its position in the list of parameters. + * \param paramList the parameter list to search + * \param nameLen length of name (in chars). + * If length is negative, assume that name is null-terminated. + * \param name the name to search for + * \return index of parameter in the list. + */ +GLint +_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name) +{ + GLint i; + + if (!paramList) + return -1; + + if (nameLen == -1) { + /* name is null-terminated */ + for (i = 0; i < (GLint) paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name && + _mesa_strcmp(paramList->Parameters[i].Name, name) == 0) + return i; + } + } + else { + /* name is not null-terminated, use nameLen */ + for (i = 0; i < (GLint) paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name && + _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0 + && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen) + return i; + } + } + return -1; +} + + +/** + * Look for a float vector in the given parameter list. The float vector + * may be of length 1, 2, 3 or 4. If swizzleOut is non-null, we'll try + * swizzling to find a match. + * \param list the parameter list to search + * \param v the float vector to search for + * \param size number of element in v + * \param posOut returns the position of the constant, if found + * \param swizzleOut returns a swizzle mask describing location of the + * vector elements if found. + * \return GL_TRUE if found, GL_FALSE if not found + */ +GLboolean +_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list, + const GLfloat v[], GLuint vSize, + GLint *posOut, GLuint *swizzleOut) +{ + GLuint i; + + assert(vSize >= 1); + assert(vSize <= 4); + + if (!list) + return -1; + + for (i = 0; i < list->NumParameters; i++) { + if (list->Parameters[i].Type == PROGRAM_CONSTANT) { + if (!swizzleOut) { + /* swizzle not allowed */ + GLuint j, match = 0; + for (j = 0; j < vSize; j++) { + if (v[j] == list->ParameterValues[i][j]) + match++; + } + if (match == vSize) { + *posOut = i; + return GL_TRUE; + } + } + else { + /* try matching w/ swizzle */ + if (vSize == 1) { + /* look for v[0] anywhere within float[4] value */ + GLuint j; + for (j = 0; j < 4; j++) { + if (list->ParameterValues[i][j] == v[0]) { + /* found it */ + *posOut = i; + *swizzleOut = MAKE_SWIZZLE4(j, j, j, j); + return GL_TRUE; + } + } + } + else if (vSize <= list->Parameters[i].Size) { + /* see if we can match this constant (with a swizzle) */ + GLuint swz[4]; + GLuint match = 0, j, k; + for (j = 0; j < vSize; j++) { + if (v[j] == list->ParameterValues[i][j]) { + swz[j] = j; + match++; + } + else { + for (k = 0; k < list->Parameters[i].Size; k++) { + if (v[j] == list->ParameterValues[i][k]) { + swz[j] = k; + match++; + break; + } + } + } + } + /* smear last value to remaining positions */ + for (; j < 4; j++) + swz[j] = swz[j-1]; + + if (match == vSize) { + *posOut = i; + *swizzleOut = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); + return GL_TRUE; + } + } + } + } + } + + *posOut = -1; + return GL_FALSE; +} + + +struct gl_program_parameter_list * +_mesa_clone_parameter_list(const struct gl_program_parameter_list *list) +{ + struct gl_program_parameter_list *clone; + GLuint i; + + clone = _mesa_new_parameter_list(); + if (!clone) + return NULL; + + /** Not too efficient, but correct */ + for (i = 0; i < list->NumParameters; i++) { + struct gl_program_parameter *p = list->Parameters + i; + GLuint size = MIN2(p->Size, 4); + GLint j = _mesa_add_parameter(clone, p->Type, p->Name, size, p->DataType, + list->ParameterValues[i], NULL); + ASSERT(j >= 0); + /* copy state indexes */ + if (p->Type == PROGRAM_STATE_VAR) { + GLint k; + struct gl_program_parameter *q = clone->Parameters + j; + for (k = 0; k < STATE_LENGTH; k++) { + q->StateIndexes[k] = p->StateIndexes[k]; + } + } + else { + clone->Parameters[j].Size = p->Size; + } + } + + return clone; +} + + +/** + * Find longest name of all uniform parameters in list. + */ +GLuint +_mesa_longest_parameter_name(const struct gl_program_parameter_list *list, + enum register_file type) +{ + GLuint i, maxLen = 0; + if (!list) + return 0; + for (i = 0; i < list->NumParameters; i++) { + if (list->Parameters[i].Type == type) { + GLuint len = _mesa_strlen(list->Parameters[i].Name); + if (len > maxLen) + maxLen = len; + } + } + return maxLen; +} + + +/** + * Count the number of parameters in the last that match the given type. + */ +GLuint +_mesa_num_parameters_of_type(const struct gl_program_parameter_list *list, + enum register_file type) +{ + GLuint i, count = 0; + if (list) { + for (i = 0; i < list->NumParameters; i++) { + if (list->Parameters[i].Type == type) + count++; + } + } + return count; +} diff --git a/dist/Mesa/src/mesa/shader/prog_parameter.h b/dist/Mesa/src/mesa/shader/prog_parameter.h new file mode 100644 index 000000000..09ff851ea --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_parameter.h @@ -0,0 +1,143 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_parameter.c + * Program parameter lists and functions. + * \author Brian Paul + */ + +#ifndef PROG_PARAMETER_H +#define PROG_PARAMETER_H + +#include "mtypes.h" +#include "prog_statevars.h" + + +/** + * Program parameter. + * Used for NV_fragment_program for "DEFINE"d constants and "DECLARE"d + * parameters. + * Also used by ARB_vertex/fragment_programs for state variables, etc. + * Used by shaders for uniforms, constants, varying vars, etc. + */ +struct gl_program_parameter +{ + const char *Name; /**< Null-terminated string */ + enum register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */ + GLenum DataType; /**< GL_FLOAT, GL_FLOAT_VEC2, etc */ + GLuint Size; /**< Number of components (1..4) */ + /** + * A sequence of STATE_* tokens and integers to identify GL state. + */ + gl_state_index StateIndexes[STATE_LENGTH]; +}; + + +/** + * List of gl_program_parameter instances. + */ +struct gl_program_parameter_list +{ + GLuint Size; /**< allocated size of Parameters, ParameterValues */ + GLuint NumParameters; /**< number of parameters in arrays */ + struct gl_program_parameter *Parameters; /**< Array [Size] */ + GLfloat (*ParameterValues)[4]; /**< Array [Size] of GLfloat[4] */ + GLbitfield StateFlags; /**< _NEW_* flags indicating which state changes + might invalidate ParameterValues[] */ +}; + + +extern struct gl_program_parameter_list * +_mesa_new_parameter_list(void); + +extern void +_mesa_free_parameter_list(struct gl_program_parameter_list *paramList); + +extern struct gl_program_parameter_list * +_mesa_clone_parameter_list(const struct gl_program_parameter_list *list); + +extern GLint +_mesa_add_parameter(struct gl_program_parameter_list *paramList, + enum register_file type, const char *name, + GLuint size, GLenum datatype, const GLfloat *values, + const gl_state_index state[STATE_LENGTH]); + +extern GLint +_mesa_add_named_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4]); + +extern GLint +_mesa_add_named_constant(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], + GLuint size); + +extern GLint +_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, + const GLfloat values[4], GLuint size, + GLuint *swizzleOut); + +extern GLint +_mesa_add_uniform(struct gl_program_parameter_list *paramList, + const char *name, GLuint size, GLenum datatype); + +extern GLint +_mesa_add_sampler(struct gl_program_parameter_list *paramList, + const char *name, GLenum datatype); + +extern GLint +_mesa_add_varying(struct gl_program_parameter_list *paramList, + const char *name, GLuint size); + +extern GLint +_mesa_add_attribute(struct gl_program_parameter_list *paramList, + const char *name, GLint size, GLint attrib); + +extern GLint +_mesa_add_state_reference(struct gl_program_parameter_list *paramList, + const gl_state_index stateTokens[STATE_LENGTH]); + +extern GLfloat * +_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name); + +extern GLint +_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name); + +extern GLboolean +_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list, + const GLfloat v[], GLuint vSize, + GLint *posOut, GLuint *swizzleOut); + +extern GLuint +_mesa_longest_parameter_name(const struct gl_program_parameter_list *list, + enum register_file type); + +extern GLuint +_mesa_num_parameters_of_type(const struct gl_program_parameter_list *list, + enum register_file type); + + +#endif /* PROG_PARAMETER_H */ diff --git a/dist/Mesa/src/mesa/shader/prog_print.c b/dist/Mesa/src/mesa/shader/prog_print.c new file mode 100644 index 000000000..e92837f73 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_print.c @@ -0,0 +1,758 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_print.c + * Print vertex/fragment programs - for debugging. + * \author Brian Paul + */ + +#include "glheader.h" +#include "context.h" +#include "imports.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_print.h" +#include "prog_statevars.h" + + + +/** + * Return string name for given program/register file. + */ +static const char * +file_string(enum register_file f, gl_prog_print_mode mode) +{ + switch (f) { + case PROGRAM_TEMPORARY: + return "TEMP"; + case PROGRAM_LOCAL_PARAM: + return "LOCAL"; + case PROGRAM_ENV_PARAM: + return "ENV"; + case PROGRAM_STATE_VAR: + return "STATE"; + case PROGRAM_INPUT: + return "INPUT"; + case PROGRAM_OUTPUT: + return "OUTPUT"; + case PROGRAM_NAMED_PARAM: + return "NAMED"; + case PROGRAM_CONSTANT: + return "CONST"; + case PROGRAM_UNIFORM: + return "UNIFORM"; + case PROGRAM_VARYING: + return "VARYING"; + case PROGRAM_WRITE_ONLY: + return "WRITE_ONLY"; + case PROGRAM_ADDRESS: + return "ADDR"; + case PROGRAM_SAMPLER: + return "SAMPLER"; + default: + return "Unknown program file!"; + } +} + + +/** + * Return ARB_v/f_prog-style input attrib string. + */ +static const char * +arb_input_attrib_string(GLint index, GLenum progType) +{ + const char *vertAttribs[] = { + "vertex.position", + "vertex.weight", + "vertex.normal", + "vertex.color.primary", + "vertex.color.secondary", + "vertex.fogcoord", + "vertex.(six)", + "vertex.(seven)", + "vertex.texcoord[0]", + "vertex.texcoord[1]", + "vertex.texcoord[2]", + "vertex.texcoord[3]", + "vertex.texcoord[4]", + "vertex.texcoord[5]", + "vertex.texcoord[6]", + "vertex.texcoord[7]" + }; + const char *fragAttribs[] = { + "fragment.position", + "fragment.color.primary", + "fragment.color.secondary", + "fragment.fogcoord", + "fragment.texcoord[0]", + "fragment.texcoord[1]", + "fragment.texcoord[2]", + "fragment.texcoord[3]", + "fragment.texcoord[4]", + "fragment.texcoord[5]", + "fragment.texcoord[6]", + "fragment.texcoord[7]", + "fragment.varying[0]", + "fragment.varying[1]", + "fragment.varying[2]", + "fragment.varying[3]", + "fragment.varying[4]", + "fragment.varying[5]", + "fragment.varying[6]", + "fragment.varying[7]" + }; + + if (progType == GL_VERTEX_PROGRAM_ARB) { + assert(index < sizeof(vertAttribs) / sizeof(vertAttribs[0])); + return vertAttribs[index]; + } + else { + assert(index < sizeof(fragAttribs) / sizeof(fragAttribs[0])); + return fragAttribs[index]; + } +} + + +/** + * Return ARB_v/f_prog-style output attrib string. + */ +static const char * +arb_output_attrib_string(GLint index, GLenum progType) +{ + const char *vertResults[] = { + "result.position", + "result.color.primary", + "result.color.secondary", + "result.fogcoord", + "result.texcoord[0]", + "result.texcoord[1]", + "result.texcoord[2]", + "result.texcoord[3]", + "result.texcoord[4]", + "result.texcoord[5]", + "result.texcoord[6]", + "result.texcoord[7]", + "result.varying[0]", + "result.varying[1]", + "result.varying[2]", + "result.varying[3]", + "result.varying[4]", + "result.varying[5]", + "result.varying[6]", + "result.varying[7]" + }; + const char *fragResults[] = { + "result.color", + "result.depth" + }; + + if (progType == GL_VERTEX_PROGRAM_ARB) { + assert(index < sizeof(vertResults) / sizeof(vertResults[0])); + return vertResults[index]; + } + else { + assert(index < sizeof(fragResults) / sizeof(fragResults[0])); + return fragResults[index]; + } +} + + +/** + * Return string representation of the given register. + * Note that some types of registers (like PROGRAM_UNIFORM) aren't defined + * by the ARB/NV program languages so we've taken some liberties here. + * \param file the register file (PROGRAM_INPUT, PROGRAM_TEMPORARY, etc) + * \param index number of the register in the register file + * \param mode the output format/mode/style + * \param prog pointer to containing program + */ +static const char * +reg_string(enum register_file f, GLint index, gl_prog_print_mode mode, + const struct gl_program *prog) +{ + static char str[100]; + + str[0] = 0; + + switch (mode) { + case PROG_PRINT_DEBUG: + sprintf(str, "%s[%d]", file_string(f, mode), index); + break; + + case PROG_PRINT_ARB: + switch (f) { + case PROGRAM_INPUT: + sprintf(str, "%s", arb_input_attrib_string(index, prog->Target)); + break; + case PROGRAM_OUTPUT: + sprintf(str, "%s", arb_output_attrib_string(index, prog->Target)); + break; + case PROGRAM_TEMPORARY: + sprintf(str, "temp%d", index); + break; + case PROGRAM_ENV_PARAM: + sprintf(str, "program.env[%d]", index); + break; + case PROGRAM_LOCAL_PARAM: + sprintf(str, "program.local[%d]", index); + break; + case PROGRAM_VARYING: /* extension */ + sprintf(str, "varying[%d]", index); + break; + case PROGRAM_CONSTANT: /* extension */ + sprintf(str, "constant[%d]", index); + break; + case PROGRAM_UNIFORM: /* extension */ + sprintf(str, "uniform[%d]", index); + break; + case PROGRAM_STATE_VAR: + { + struct gl_program_parameter *param + = prog->Parameters->Parameters + index; + sprintf(str, _mesa_program_state_string(param->StateIndexes)); + } + break; + case PROGRAM_ADDRESS: + sprintf(str, "A%d", index); + break; + default: + _mesa_problem(NULL, "bad file in reg_string()"); + } + break; + + case PROG_PRINT_NV: + switch (f) { + case PROGRAM_INPUT: + if (prog->Target == GL_VERTEX_PROGRAM_ARB) + sprintf(str, "v[%d]", index); + else + sprintf(str, "f[%d]", index); + break; + case PROGRAM_OUTPUT: + sprintf(str, "o[%d]", index); + break; + case PROGRAM_TEMPORARY: + sprintf(str, "R%d", index); + break; + case PROGRAM_ENV_PARAM: + sprintf(str, "c[%d]", index); + break; + case PROGRAM_VARYING: /* extension */ + sprintf(str, "varying[%d]", index); + break; + case PROGRAM_UNIFORM: /* extension */ + sprintf(str, "uniform[%d]", index); + break; + case PROGRAM_CONSTANT: /* extension */ + sprintf(str, "constant[%d]", index); + break; + case PROGRAM_STATE_VAR: /* extension */ + sprintf(str, "state[%d]", index); + break; + default: + _mesa_problem(NULL, "bad file in reg_string()"); + } + break; + + default: + _mesa_problem(NULL, "bad mode in reg_string()"); + } + + return str; +} + + +/** + * Return a string representation of the given swizzle word. + * If extended is true, use extended (comma-separated) format. + * \param swizzle the swizzle field + * \param negateBase 4-bit negation vector + * \param extended if true, also allow 0, 1 values + */ +const char * +_mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended) +{ + static const char swz[] = "xyzw01?!"; + static char s[20]; + GLuint i = 0; + + if (!extended && swizzle == SWIZZLE_NOOP && negateBase == 0) + return ""; /* no swizzle/negation */ + + if (!extended) + s[i++] = '.'; + + if (negateBase & 0x1) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 0)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x2) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 1)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x4) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 2)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x8) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 3)]; + + s[i] = 0; + return s; +} + + +static const char * +writemask_string(GLuint writeMask) +{ + static char s[10]; + GLuint i = 0; + + if (writeMask == WRITEMASK_XYZW) + return ""; + + s[i++] = '.'; + if (writeMask & WRITEMASK_X) + s[i++] = 'x'; + if (writeMask & WRITEMASK_Y) + s[i++] = 'y'; + if (writeMask & WRITEMASK_Z) + s[i++] = 'z'; + if (writeMask & WRITEMASK_W) + s[i++] = 'w'; + + s[i] = 0; + return s; +} + + +const char * +_mesa_condcode_string(GLuint condcode) +{ + switch (condcode) { + case COND_GT: return "GT"; + case COND_EQ: return "EQ"; + case COND_LT: return "LT"; + case COND_UN: return "UN"; + case COND_GE: return "GE"; + case COND_LE: return "LE"; + case COND_NE: return "NE"; + case COND_TR: return "TR"; + case COND_FL: return "FL"; + default: return "cond???"; + } +} + + +static void +print_dst_reg(const struct prog_dst_register *dstReg, gl_prog_print_mode mode, + const struct gl_program *prog) +{ + _mesa_printf("%s%s", + reg_string((enum register_file) dstReg->File, + dstReg->Index, mode, prog), + writemask_string(dstReg->WriteMask)); + + if (dstReg->CondMask != COND_TR) { + _mesa_printf(" (%s.%s)", + _mesa_condcode_string(dstReg->CondMask), + _mesa_swizzle_string(dstReg->CondSwizzle, GL_FALSE, GL_FALSE)); + } + +#if 0 + _mesa_printf("%s[%d]%s", + file_string((enum register_file) dstReg->File, mode), + dstReg->Index, + writemask_string(dstReg->WriteMask)); +#endif +} + +static void +print_src_reg(const struct prog_src_register *srcReg, gl_prog_print_mode mode, + const struct gl_program *prog) +{ + _mesa_printf("%s%s", + reg_string((enum register_file) srcReg->File, + srcReg->Index, mode, prog), + _mesa_swizzle_string(srcReg->Swizzle, + srcReg->NegateBase, GL_FALSE)); +#if 0 + _mesa_printf("%s[%d]%s", + file_string((enum register_file) srcReg->File, mode), + srcReg->Index, + _mesa_swizzle_string(srcReg->Swizzle, + srcReg->NegateBase, GL_FALSE)); +#endif +} + +static void +print_comment(const struct prog_instruction *inst) +{ + if (inst->Comment) + _mesa_printf("; # %s\n", inst->Comment); + else + _mesa_printf(";\n"); +} + + +static void +print_alu_instruction(const struct prog_instruction *inst, + const char *opcode_string, GLuint numRegs, + gl_prog_print_mode mode, + const struct gl_program *prog) +{ + GLuint j; + + _mesa_printf("%s", opcode_string); + if (inst->CondUpdate) + _mesa_printf(".C"); + + /* frag prog only */ + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + + _mesa_printf(" "); + if (inst->DstReg.File != PROGRAM_UNDEFINED) { + print_dst_reg(&inst->DstReg, mode, prog); + } + else { + _mesa_printf(" ???"); + } + + if (numRegs > 0) + _mesa_printf(", "); + + for (j = 0; j < numRegs; j++) { + print_src_reg(inst->SrcReg + j, mode, prog); + if (j + 1 < numRegs) + _mesa_printf(", "); + } + + print_comment(inst); +} + + +void +_mesa_print_alu_instruction(const struct prog_instruction *inst, + const char *opcode_string, GLuint numRegs) +{ + print_alu_instruction(inst, opcode_string, numRegs, PROG_PRINT_DEBUG, NULL); +} + + +void +_mesa_print_instruction(const struct prog_instruction *inst) +{ + /* note: 4th param should be ignored for PROG_PRINT_DEBUG */ + _mesa_print_instruction_opt(inst, 0, PROG_PRINT_DEBUG, NULL); +} + + +/** + * Print a single vertex/fragment program instruction. + */ +GLint +_mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent, + gl_prog_print_mode mode, + const struct gl_program *prog) +{ + GLint i; + + if (inst->Opcode == OPCODE_ELSE || + inst->Opcode == OPCODE_ENDIF || + inst->Opcode == OPCODE_ENDLOOP || + inst->Opcode == OPCODE_ENDSUB) { + indent -= 3; + } + for (i = 0; i < indent; i++) { + _mesa_printf(" "); + } + + switch (inst->Opcode) { + case OPCODE_PRINT: + _mesa_printf("PRINT '%s'", inst->Data); + if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { + _mesa_printf(", "); + _mesa_printf("%s[%d]%s", + file_string((enum register_file) inst->SrcReg[0].File, + mode), + inst->SrcReg[0].Index, + _mesa_swizzle_string(inst->SrcReg[0].Swizzle, + inst->SrcReg[0].NegateBase, GL_FALSE)); + } + if (inst->Comment) + _mesa_printf(" # %s", inst->Comment); + print_comment(inst); + break; + case OPCODE_SWZ: + _mesa_printf("SWZ"); + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + _mesa_printf(" "); + print_dst_reg(&inst->DstReg, mode, prog); + _mesa_printf("%s[%d], %s", + file_string((enum register_file) inst->SrcReg[0].File, + mode), + inst->SrcReg[0].Index, + _mesa_swizzle_string(inst->SrcReg[0].Swizzle, + inst->SrcReg[0].NegateBase, GL_TRUE)); + print_comment(inst); + break; + case OPCODE_TEX: + case OPCODE_TXP: + case OPCODE_TXB: + _mesa_printf("%s", _mesa_opcode_string(inst->Opcode)); + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + _mesa_printf(" "); + print_dst_reg(&inst->DstReg, mode, prog); + _mesa_printf(", "); + print_src_reg(&inst->SrcReg[0], mode, prog); + _mesa_printf(", texture[%d], ", inst->TexSrcUnit); + switch (inst->TexSrcTarget) { + case TEXTURE_1D_INDEX: _mesa_printf("1D"); break; + case TEXTURE_2D_INDEX: _mesa_printf("2D"); break; + case TEXTURE_3D_INDEX: _mesa_printf("3D"); break; + case TEXTURE_CUBE_INDEX: _mesa_printf("CUBE"); break; + case TEXTURE_RECT_INDEX: _mesa_printf("RECT"); break; + default: + ; + } + print_comment(inst); + break; + case OPCODE_ARL: + _mesa_printf("ARL addr.x, "); + print_src_reg(&inst->SrcReg[0], mode, prog); + print_comment(inst); + break; + case OPCODE_BRA: + _mesa_printf("BRA %d (%s%s)", + inst->BranchTarget, + _mesa_condcode_string(inst->DstReg.CondMask), + _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE)); + print_comment(inst); + break; + case OPCODE_IF: + if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { + /* Use ordinary register */ + _mesa_printf("IF "); + print_src_reg(&inst->SrcReg[0], mode, prog); + _mesa_printf("; "); + } + else { + /* Use cond codes */ + _mesa_printf("IF (%s%s);", + _mesa_condcode_string(inst->DstReg.CondMask), + _mesa_swizzle_string(inst->DstReg.CondSwizzle, + 0, GL_FALSE)); + } + _mesa_printf(" # (if false, goto %d)", inst->BranchTarget); + print_comment(inst); + return indent + 3; + case OPCODE_ELSE: + _mesa_printf("ELSE; # (goto %d)\n", inst->BranchTarget); + return indent + 3; + case OPCODE_ENDIF: + _mesa_printf("ENDIF;\n"); + break; + case OPCODE_BGNLOOP: + _mesa_printf("BGNLOOP; # (end at %d)\n", inst->BranchTarget); + return indent + 3; + case OPCODE_ENDLOOP: + _mesa_printf("ENDLOOP; # (goto %d)\n", inst->BranchTarget); + break; + case OPCODE_BRK: + case OPCODE_CONT: + _mesa_printf("%s (%s%s); # (goto %d)", + _mesa_opcode_string(inst->Opcode), + _mesa_condcode_string(inst->DstReg.CondMask), + _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE), + inst->BranchTarget); + print_comment(inst); + break; + + case OPCODE_BGNSUB: + if (mode == PROG_PRINT_NV) { + _mesa_printf("%s:\n", inst->Comment); /* comment is label */ + return indent; + } + else { + _mesa_printf("BGNSUB"); + print_comment(inst); + return indent + 3; + } + case OPCODE_ENDSUB: + if (mode == PROG_PRINT_DEBUG) { + _mesa_printf("ENDSUB"); + print_comment(inst); + } + break; + case OPCODE_CAL: + if (mode == PROG_PRINT_NV) { + _mesa_printf("CAL %s; # (goto %d)\n", inst->Comment, inst->BranchTarget); + } + else { + _mesa_printf("CAL %u", inst->BranchTarget); + print_comment(inst); + } + break; + case OPCODE_RET: + _mesa_printf("RET (%s%s)", + _mesa_condcode_string(inst->DstReg.CondMask), + _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE)); + print_comment(inst); + break; + + case OPCODE_END: + _mesa_printf("END\n"); + break; + case OPCODE_NOP: + if (mode == PROG_PRINT_DEBUG) { + _mesa_printf("NOP"); + print_comment(inst); + } + else if (inst->Comment) { + /* ARB/NV extensions don't have NOP instruction */ + _mesa_printf("# %s\n", inst->Comment); + } + break; + /* XXX may need other special-case instructions */ + default: + /* typical alu instruction */ + print_alu_instruction(inst, + _mesa_opcode_string(inst->Opcode), + _mesa_num_inst_src_regs(inst->Opcode), + mode, prog); + break; + } + return indent; +} + + +/** + * Print program to stdout, default options. + */ +void +_mesa_print_program(const struct gl_program *prog) +{ + _mesa_print_program_opt(prog, PROG_PRINT_DEBUG, GL_TRUE); +} + + +/** + * Print program, with options. + */ +void +_mesa_print_program_opt(const struct gl_program *prog, + gl_prog_print_mode mode, + GLboolean lineNumbers) +{ + GLuint i, indent = 0; + + switch (prog->Target) { + case GL_VERTEX_PROGRAM_ARB: + if (mode == PROG_PRINT_ARB) + _mesa_printf("!!ARBvp1.0\n"); + else if (mode == PROG_PRINT_NV) + _mesa_printf("!!VP1.0\n"); + else + _mesa_printf("# Vertex Program/Shader\n"); + break; + case GL_FRAGMENT_PROGRAM_ARB: + case GL_FRAGMENT_PROGRAM_NV: + if (mode == PROG_PRINT_ARB) + _mesa_printf("!!ARBfp1.0\n"); + else if (mode == PROG_PRINT_NV) + _mesa_printf("!!FP1.0\n"); + else + _mesa_printf("# Fragment Program/Shader\n"); + break; + } + + for (i = 0; i < prog->NumInstructions; i++) { + if (lineNumbers) + _mesa_printf("%3d: ", i); + indent = _mesa_print_instruction_opt(prog->Instructions + i, + indent, mode, prog); + } +} + + +/** + * Print all of a program's parameters. + */ +void +_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog) +{ + _mesa_printf("InputsRead: 0x%x\n", prog->InputsRead); + _mesa_printf("OutputsWritten: 0x%x\n", prog->OutputsWritten); + _mesa_printf("NumInstructions=%d\n", prog->NumInstructions); + _mesa_printf("NumTemporaries=%d\n", prog->NumTemporaries); + _mesa_printf("NumParameters=%d\n", prog->NumParameters); + _mesa_printf("NumAttributes=%d\n", prog->NumAttributes); + _mesa_printf("NumAddressRegs=%d\n", prog->NumAddressRegs); + + _mesa_load_state_parameters(ctx, prog->Parameters); + +#if 0 + _mesa_printf("Local Params:\n"); + for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){ + const GLfloat *p = prog->LocalParams[i]; + _mesa_printf("%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]); + } +#endif + _mesa_print_parameter_list(prog->Parameters); +} + + +void +_mesa_print_parameter_list(const struct gl_program_parameter_list *list) +{ + const gl_prog_print_mode mode = PROG_PRINT_DEBUG; + GLuint i; + + _mesa_printf("param list %p\n", (void *) list); + for (i = 0; i < list->NumParameters; i++){ + struct gl_program_parameter *param = list->Parameters + i; + const GLfloat *v = list->ParameterValues[i]; + _mesa_printf("param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g};\n", + i, param->Size, + file_string(list->Parameters[i].Type, mode), + param->Name, v[0], v[1], v[2], v[3]); + } +} diff --git a/dist/Mesa/src/mesa/shader/prog_print.h b/dist/Mesa/src/mesa/shader/prog_print.h new file mode 100644 index 000000000..36c47e0df --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_print.h @@ -0,0 +1,72 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef PROG_PRINT_H +#define PROG_PRINT_H + + +/** + * The output style to use when printing programs. + */ +typedef enum { + PROG_PRINT_ARB, + PROG_PRINT_NV, + PROG_PRINT_DEBUG +} gl_prog_print_mode; + + +extern const char * +_mesa_condcode_string(GLuint condcode); + +extern const char * +_mesa_swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended); + +extern void +_mesa_print_alu_instruction(const struct prog_instruction *inst, + const char *opcode_string, GLuint numRegs); + +extern void +_mesa_print_instruction(const struct prog_instruction *inst); + +extern GLint +_mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent, + gl_prog_print_mode mode, + const struct gl_program *prog); + +extern void +_mesa_print_program(const struct gl_program *prog); + +extern void +_mesa_print_program_opt(const struct gl_program *prog, gl_prog_print_mode mode, + GLboolean lineNumbers); + +extern void +_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog); + +extern void +_mesa_print_parameter_list(const struct gl_program_parameter_list *list); + + +#endif /* PROG_PRINT_H */ diff --git a/dist/Mesa/src/mesa/shader/prog_statevars.c b/dist/Mesa/src/mesa/shader/prog_statevars.c new file mode 100644 index 000000000..975a617ac --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_statevars.c @@ -0,0 +1,824 @@ +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_statevars.c + * Program state variable management. + * \author Brian Paul + */ + + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "prog_statevars.h" +#include "prog_parameter.h" +#include "nvvertparse.h" + + +/** + * Use the list of tokens in the state[] array to find global GL state + * and return it in <value>. Usually, four values are returned in <value> + * but matrix queries may return as many as 16 values. + * This function is used for ARB vertex/fragment programs. + * The program parser will produce the state[] values. + */ +static void +_mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], + GLfloat *value) +{ + switch (state[0]) { + case STATE_MATERIAL: + { + /* state[1] is either 0=front or 1=back side */ + const GLuint face = (GLuint) state[1]; + const struct gl_material *mat = &ctx->Light.Material; + ASSERT(face == 0 || face == 1); + /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */ + ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT); + /* XXX we could get rid of this switch entirely with a little + * work in arbprogparse.c's parse_state_single_item(). + */ + /* state[2] is the material attribute */ + switch (state[2]) { + case STATE_AMBIENT: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]); + return; + case STATE_DIFFUSE: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]); + return; + case STATE_SPECULAR: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]); + return; + case STATE_EMISSION: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]); + return; + case STATE_SHININESS: + value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0]; + value[1] = 0.0F; + value[2] = 0.0F; + value[3] = 1.0F; + return; + default: + _mesa_problem(ctx, "Invalid material state in fetch_state"); + return; + } + } + case STATE_LIGHT: + { + /* state[1] is the light number */ + const GLuint ln = (GLuint) state[1]; + /* state[2] is the light attribute */ + switch (state[2]) { + case STATE_AMBIENT: + COPY_4V(value, ctx->Light.Light[ln].Ambient); + return; + case STATE_DIFFUSE: + COPY_4V(value, ctx->Light.Light[ln].Diffuse); + return; + case STATE_SPECULAR: + COPY_4V(value, ctx->Light.Light[ln].Specular); + return; + case STATE_POSITION: + COPY_4V(value, ctx->Light.Light[ln].EyePosition); + return; + case STATE_ATTENUATION: + value[0] = ctx->Light.Light[ln].ConstantAttenuation; + value[1] = ctx->Light.Light[ln].LinearAttenuation; + value[2] = ctx->Light.Light[ln].QuadraticAttenuation; + value[3] = ctx->Light.Light[ln].SpotExponent; + return; + case STATE_SPOT_DIRECTION: + COPY_3V(value, ctx->Light.Light[ln].EyeDirection); + value[3] = ctx->Light.Light[ln]._CosCutoff; + return; + case STATE_SPOT_CUTOFF: + value[0] = ctx->Light.Light[ln].SpotCutoff; + return; + case STATE_HALF_VECTOR: + { + static const GLfloat eye_z[] = {0, 0, 1}; + GLfloat p[3]; + /* Compute infinite half angle vector: + * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) + * light.EyePosition.w should be 0 for infinite lights. + */ + COPY_3V(p, ctx->Light.Light[ln].EyePosition); + NORMALIZE_3FV(p); + ADD_3V(value, p, eye_z); + NORMALIZE_3FV(value); + value[3] = 1.0; + } + return; + case STATE_POSITION_NORMALIZED: + COPY_4V(value, ctx->Light.Light[ln].EyePosition); + NORMALIZE_3FV( value ); + return; + default: + _mesa_problem(ctx, "Invalid light state in fetch_state"); + return; + } + } + case STATE_LIGHTMODEL_AMBIENT: + COPY_4V(value, ctx->Light.Model.Ambient); + return; + case STATE_LIGHTMODEL_SCENECOLOR: + if (state[1] == 0) { + /* front */ + GLint i; + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Model.Ambient[i] + * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] + + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; + } + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; + } + else { + /* back */ + GLint i; + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Model.Ambient[i] + * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] + + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; + } + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; + } + return; + case STATE_LIGHTPROD: + { + const GLuint ln = (GLuint) state[1]; + const GLuint face = (GLuint) state[2]; + GLint i; + ASSERT(face == 0 || face == 1); + switch (state[3]) { + case STATE_AMBIENT: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Ambient[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + case STATE_DIFFUSE: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Diffuse[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + case STATE_SPECULAR: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Specular[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + default: + _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); + return; + } + } + case STATE_TEXGEN: + { + /* state[1] is the texture unit */ + const GLuint unit = (GLuint) state[1]; + /* state[2] is the texgen attribute */ + switch (state[2]) { + case STATE_TEXGEN_EYE_S: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS); + return; + case STATE_TEXGEN_EYE_T: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT); + return; + case STATE_TEXGEN_EYE_R: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR); + return; + case STATE_TEXGEN_EYE_Q: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ); + return; + case STATE_TEXGEN_OBJECT_S: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS); + return; + case STATE_TEXGEN_OBJECT_T: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT); + return; + case STATE_TEXGEN_OBJECT_R: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR); + return; + case STATE_TEXGEN_OBJECT_Q: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ); + return; + default: + _mesa_problem(ctx, "Invalid texgen state in fetch_state"); + return; + } + } + case STATE_TEXENV_COLOR: + { + /* state[1] is the texture unit */ + const GLuint unit = (GLuint) state[1]; + COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); + } + return; + case STATE_FOG_COLOR: + COPY_4V(value, ctx->Fog.Color); + return; + case STATE_FOG_PARAMS: + value[0] = ctx->Fog.Density; + value[1] = ctx->Fog.Start; + value[2] = ctx->Fog.End; + value[3] = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + return; + case STATE_CLIPPLANE: + { + const GLuint plane = (GLuint) state[1]; + COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); + } + return; + case STATE_POINT_SIZE: + value[0] = ctx->Point.Size; + value[1] = ctx->Point.MinSize; + value[2] = ctx->Point.MaxSize; + value[3] = ctx->Point.Threshold; + return; + case STATE_POINT_ATTENUATION: + value[0] = ctx->Point.Params[0]; + value[1] = ctx->Point.Params[1]; + value[2] = ctx->Point.Params[2]; + value[3] = 1.0F; + return; + case STATE_MODELVIEW_MATRIX: + case STATE_PROJECTION_MATRIX: + case STATE_MVP_MATRIX: + case STATE_TEXTURE_MATRIX: + case STATE_PROGRAM_MATRIX: + { + /* state[0] = modelview, projection, texture, etc. */ + /* state[1] = which texture matrix or program matrix */ + /* state[2] = first row to fetch */ + /* state[3] = last row to fetch */ + /* state[4] = transpose, inverse or invtrans */ + const GLmatrix *matrix; + const gl_state_index mat = state[0]; + const GLuint index = (GLuint) state[1]; + const GLuint firstRow = (GLuint) state[2]; + const GLuint lastRow = (GLuint) state[3]; + const gl_state_index modifier = state[4]; + const GLfloat *m; + GLuint row, i; + ASSERT(firstRow >= 0); + ASSERT(firstRow < 4); + ASSERT(lastRow >= 0); + ASSERT(lastRow < 4); + if (mat == STATE_MODELVIEW_MATRIX) { + matrix = ctx->ModelviewMatrixStack.Top; + } + else if (mat == STATE_PROJECTION_MATRIX) { + matrix = ctx->ProjectionMatrixStack.Top; + } + else if (mat == STATE_MVP_MATRIX) { + matrix = &ctx->_ModelProjectMatrix; + } + else if (mat == STATE_TEXTURE_MATRIX) { + matrix = ctx->TextureMatrixStack[index].Top; + } + else if (mat == STATE_PROGRAM_MATRIX) { + matrix = ctx->ProgramMatrixStack[index].Top; + } + else { + _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); + return; + } + if (modifier == STATE_MATRIX_INVERSE || + modifier == STATE_MATRIX_INVTRANS) { + /* Be sure inverse is up to date: + */ + _math_matrix_alloc_inv( (GLmatrix *) matrix ); + _math_matrix_analyse( (GLmatrix*) matrix ); + m = matrix->inv; + } + else { + m = matrix->m; + } + if (modifier == STATE_MATRIX_TRANSPOSE || + modifier == STATE_MATRIX_INVTRANS) { + for (i = 0, row = firstRow; row <= lastRow; row++) { + value[i++] = m[row * 4 + 0]; + value[i++] = m[row * 4 + 1]; + value[i++] = m[row * 4 + 2]; + value[i++] = m[row * 4 + 3]; + } + } + else { + for (i = 0, row = firstRow; row <= lastRow; row++) { + value[i++] = m[row + 0]; + value[i++] = m[row + 4]; + value[i++] = m[row + 8]; + value[i++] = m[row + 12]; + } + } + } + return; + case STATE_DEPTH_RANGE: + value[0] = ctx->Viewport.Near; /* near */ + value[1] = ctx->Viewport.Far; /* far */ + value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */ + value[3] = 0; + return; + case STATE_FRAGMENT_PROGRAM: + { + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + const int idx = (int) state[2]; + switch (state[1]) { + case STATE_ENV: + COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); + break; + case STATE_LOCAL: + COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); + break; + default: + _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); + return; + } + } + return; + + case STATE_VERTEX_PROGRAM: + { + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + const int idx = (int) state[2]; + switch (state[1]) { + case STATE_ENV: + COPY_4V(value, ctx->VertexProgram.Parameters[idx]); + break; + case STATE_LOCAL: + COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); + break; + default: + _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); + return; + } + } + return; + + case STATE_NORMAL_SCALE: + ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); + return; + + case STATE_INTERNAL: + switch (state[1]) { + case STATE_NORMAL_SCALE: + ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); + return; + case STATE_TEXRECT_SCALE: + { + const int unit = (int) state[2]; + const struct gl_texture_object *texObj + = ctx->Texture.Unit[unit]._Current; + if (texObj) { + struct gl_texture_image *texImage = texObj->Image[0][0]; + ASSIGN_4V(value, 1.0 / texImage->Width, + 1.0 / texImage->Height, + 0.0, 1.0); + } + } + return; + case STATE_FOG_PARAMS_OPTIMIZED: + /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) + * might be more expensive than EX2 on some hw, plus it needs + * another constant (e) anyway. Linear fog can now be done with a + * single MAD. + * linear: fogcoord * -1/(end-start) + end/(end-start) + * exp: 2^-(density/ln(2) * fogcoord) + * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2) + */ + value[0] = -1.0F / (ctx->Fog.End - ctx->Fog.Start); + value[1] = ctx->Fog.End / (ctx->Fog.End - ctx->Fog.Start); + value[2] = ctx->Fog.Density * ONE_DIV_LN2; + value[3] = ctx->Fog.Density * ONE_DIV_SQRT_LN2; + return; + case STATE_SPOT_DIR_NORMALIZED: { + /* here, state[2] is the light number */ + /* pre-normalize spot dir */ + const GLuint ln = (GLuint) state[2]; + COPY_3V(value, ctx->Light.Light[ln].EyeDirection); + NORMALIZE_3FV(value); + value[3] = ctx->Light.Light[ln]._CosCutoff; + return; + } + default: + /* unknown state indexes are silently ignored + * should be handled by the driver. + */ + return; + } + return; + + default: + _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); + return; + } +} + + +/** + * Return a bitmask of the Mesa state flags (_NEW_* values) which would + * indicate that the given context state may have changed. + * The bitmask is used during validation to determine if we need to update + * vertex/fragment program parameters (like "state.material.color") when + * some GL state has changed. + */ +GLbitfield +_mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) +{ + switch (state[0]) { + case STATE_MATERIAL: + case STATE_LIGHT: + case STATE_LIGHTMODEL_AMBIENT: + case STATE_LIGHTMODEL_SCENECOLOR: + case STATE_LIGHTPROD: + return _NEW_LIGHT; + + case STATE_TEXGEN: + case STATE_TEXENV_COLOR: + return _NEW_TEXTURE; + + case STATE_FOG_COLOR: + case STATE_FOG_PARAMS: + return _NEW_FOG; + + case STATE_CLIPPLANE: + return _NEW_TRANSFORM; + + case STATE_POINT_SIZE: + case STATE_POINT_ATTENUATION: + return _NEW_POINT; + + case STATE_MODELVIEW_MATRIX: + return _NEW_MODELVIEW; + case STATE_PROJECTION_MATRIX: + return _NEW_PROJECTION; + case STATE_MVP_MATRIX: + return _NEW_MODELVIEW | _NEW_PROJECTION; + case STATE_TEXTURE_MATRIX: + return _NEW_TEXTURE_MATRIX; + case STATE_PROGRAM_MATRIX: + return _NEW_TRACK_MATRIX; + + case STATE_DEPTH_RANGE: + return _NEW_VIEWPORT; + + case STATE_FRAGMENT_PROGRAM: + case STATE_VERTEX_PROGRAM: + return _NEW_PROGRAM; + + case STATE_NORMAL_SCALE: + return _NEW_MODELVIEW; + + case STATE_INTERNAL: + switch (state[1]) { + case STATE_TEXRECT_SCALE: + return _NEW_TEXTURE; + default: + /* unknown state indexes are silently ignored and + * no flag set, since it is handled by the driver. + */ + return 0; + } + + default: + _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); + return 0; + } +} + + +static void +append(char *dst, const char *src) +{ + while (*dst) + dst++; + while (*src) + *dst++ = *src++; + *dst = 0; +} + + +static void +append_token(char *dst, gl_state_index k) +{ + switch (k) { + case STATE_MATERIAL: + append(dst, "material"); + break; + case STATE_LIGHT: + append(dst, "light"); + break; + case STATE_LIGHTMODEL_AMBIENT: + append(dst, "lightmodel.ambient"); + break; + case STATE_LIGHTMODEL_SCENECOLOR: + break; + case STATE_LIGHTPROD: + append(dst, "lightprod"); + break; + case STATE_TEXGEN: + append(dst, "texgen"); + break; + case STATE_FOG_COLOR: + append(dst, "fog.color"); + break; + case STATE_FOG_PARAMS: + append(dst, "fog.params"); + break; + case STATE_CLIPPLANE: + append(dst, "clip"); + break; + case STATE_POINT_SIZE: + append(dst, "point.size"); + break; + case STATE_POINT_ATTENUATION: + append(dst, "point.attenuation"); + break; + case STATE_MODELVIEW_MATRIX: + append(dst, "matrix.modelview"); + break; + case STATE_PROJECTION_MATRIX: + append(dst, "matrix.projection"); + break; + case STATE_MVP_MATRIX: + append(dst, "matrix.mvp"); + break; + case STATE_TEXTURE_MATRIX: + append(dst, "matrix.texture"); + break; + case STATE_PROGRAM_MATRIX: + append(dst, "matrix.program"); + break; + case STATE_MATRIX_INVERSE: + append(dst, ".inverse"); + break; + case STATE_MATRIX_TRANSPOSE: + append(dst, ".transpose"); + break; + case STATE_MATRIX_INVTRANS: + append(dst, ".invtrans"); + break; + case STATE_AMBIENT: + append(dst, ".ambient"); + break; + case STATE_DIFFUSE: + append(dst, ".diffuse"); + break; + case STATE_SPECULAR: + append(dst, ".specular"); + break; + case STATE_EMISSION: + append(dst, ".emission"); + break; + case STATE_SHININESS: + append(dst, "lshininess"); + break; + case STATE_HALF_VECTOR: + append(dst, ".half"); + break; + case STATE_POSITION: + append(dst, ".position"); + break; + case STATE_ATTENUATION: + append(dst, ".attenuation"); + break; + case STATE_SPOT_DIRECTION: + append(dst, ".spot.direction"); + break; + case STATE_SPOT_CUTOFF: + append(dst, ".spot.cutoff"); + break; + case STATE_TEXGEN_EYE_S: + append(dst, "eye.s"); + break; + case STATE_TEXGEN_EYE_T: + append(dst, "eye.t"); + break; + case STATE_TEXGEN_EYE_R: + append(dst, "eye.r"); + break; + case STATE_TEXGEN_EYE_Q: + append(dst, "eye.q"); + break; + case STATE_TEXGEN_OBJECT_S: + append(dst, "object.s"); + break; + case STATE_TEXGEN_OBJECT_T: + append(dst, "object.t"); + break; + case STATE_TEXGEN_OBJECT_R: + append(dst, "object.r"); + break; + case STATE_TEXGEN_OBJECT_Q: + append(dst, "object.q"); + break; + case STATE_TEXENV_COLOR: + append(dst, "texenv"); + break; + case STATE_DEPTH_RANGE: + append(dst, "depth.range"); + break; + case STATE_VERTEX_PROGRAM: + case STATE_FRAGMENT_PROGRAM: + break; + case STATE_ENV: + append(dst, "env"); + break; + case STATE_LOCAL: + append(dst, "local"); + break; + case STATE_NORMAL_SCALE: + append(dst, "normalScale"); + break; + case STATE_INTERNAL: + case STATE_POSITION_NORMALIZED: + append(dst, "(internal)"); + break; + default: + ; + } +} + +static void +append_face(char *dst, GLint face) +{ + if (face == 0) + append(dst, "front."); + else + append(dst, "back."); +} + +static void +append_index(char *dst, GLint index) +{ + char s[20]; + _mesa_sprintf(s, "[%d]", index); + append(dst, s); +} + +/** + * Make a string from the given state vector. + * For example, return "state.matrix.texture[2].inverse". + * Use _mesa_free() to deallocate the string. + */ +const char * +_mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) +{ + char str[1000] = ""; + char tmp[30]; + + append(str, "state."); + append_token(str, (gl_state_index) state[0]); + + switch (state[0]) { + case STATE_MATERIAL: + append_face(str, state[1]); + append_token(str, (gl_state_index) state[2]); + break; + case STATE_LIGHT: + append_index(str, state[1]); /* light number [i]. */ + append_token(str, (gl_state_index) state[2]); /* coefficients */ + break; + case STATE_LIGHTMODEL_AMBIENT: + append(str, "lightmodel.ambient"); + break; + case STATE_LIGHTMODEL_SCENECOLOR: + if (state[1] == 0) { + append(str, "lightmodel.front.scenecolor"); + } + else { + append(str, "lightmodel.back.scenecolor"); + } + break; + case STATE_LIGHTPROD: + append_index(str, state[1]); /* light number [i]. */ + append_face(str, state[2]); + append_token(str, (gl_state_index) state[3]); + break; + case STATE_TEXGEN: + append_index(str, state[1]); /* tex unit [i] */ + append_token(str, (gl_state_index) state[2]); /* plane coef */ + break; + case STATE_TEXENV_COLOR: + append_index(str, state[1]); /* tex unit [i] */ + append(str, "color"); + break; + case STATE_CLIPPLANE: + append_index(str, state[1]); /* plane [i] */ + append(str, ".plane"); + break; + case STATE_MODELVIEW_MATRIX: + case STATE_PROJECTION_MATRIX: + case STATE_MVP_MATRIX: + case STATE_TEXTURE_MATRIX: + case STATE_PROGRAM_MATRIX: + { + /* state[0] = modelview, projection, texture, etc. */ + /* state[1] = which texture matrix or program matrix */ + /* state[2] = first row to fetch */ + /* state[3] = last row to fetch */ + /* state[4] = transpose, inverse or invtrans */ + const gl_state_index mat = (gl_state_index) state[0]; + const GLuint index = (GLuint) state[1]; + const GLuint firstRow = (GLuint) state[2]; + const GLuint lastRow = (GLuint) state[3]; + const gl_state_index modifier = (gl_state_index) state[4]; + if (index || + mat == STATE_TEXTURE_MATRIX || + mat == STATE_PROGRAM_MATRIX) + append_index(str, index); + if (modifier) + append_token(str, modifier); + if (firstRow == lastRow) + _mesa_sprintf(tmp, ".row[%d]", firstRow); + else + _mesa_sprintf(tmp, ".row[%d..%d]", firstRow, lastRow); + append(str, tmp); + } + break; + case STATE_POINT_SIZE: + break; + case STATE_POINT_ATTENUATION: + break; + case STATE_FOG_PARAMS: + break; + case STATE_FOG_COLOR: + break; + case STATE_DEPTH_RANGE: + break; + case STATE_FRAGMENT_PROGRAM: + case STATE_VERTEX_PROGRAM: + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + append_token(str, (gl_state_index) state[1]); + append_index(str, state[2]); + break; + case STATE_INTERNAL: + break; + default: + _mesa_problem(NULL, "Invalid state in _mesa_program_state_string"); + break; + } + + return _mesa_strdup(str); +} + + +/** + * Loop over all the parameters in a parameter list. If the parameter + * is a GL state reference, look up the current value of that state + * variable and put it into the parameter's Value[4] array. + * This would be called at glBegin time when using a fragment program. + */ +void +_mesa_load_state_parameters(GLcontext *ctx, + struct gl_program_parameter_list *paramList) +{ + GLuint i; + + if (!paramList) + return; + + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { + _mesa_fetch_state(ctx, + (gl_state_index *) paramList->Parameters[i].StateIndexes, + paramList->ParameterValues[i]); + } + } +} + diff --git a/dist/Mesa/src/mesa/shader/prog_statevars.h b/dist/Mesa/src/mesa/shader/prog_statevars.h new file mode 100644 index 000000000..3281a4a2a --- /dev/null +++ b/dist/Mesa/src/mesa/shader/prog_statevars.h @@ -0,0 +1,129 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PROG_STATEVARS_H +#define PROG_STATEVARS_H + +#include "mtypes.h" + + +/** + * Number of STATE_* values we need to address any GL state. + * Used to dimension arrays. + */ +#define STATE_LENGTH 5 + + +/** + * Used for describing GL state referenced from inside ARB vertex and + * fragment programs. + * A string such as "state.light[0].ambient" gets translated into a + * sequence of tokens such as [ STATE_LIGHT, 0, STATE_AMBIENT ]. + * + * For state that's an array, like STATE_CLIPPLANE, the 2nd token [1] should + * always be the array index. + */ +typedef enum gl_state_index_ { + STATE_MATERIAL = 100, /* start at 100 so small ints are seen as ints */ + + STATE_LIGHT, + STATE_LIGHTMODEL_AMBIENT, + STATE_LIGHTMODEL_SCENECOLOR, + STATE_LIGHTPROD, + + STATE_TEXGEN, + + STATE_FOG_COLOR, + STATE_FOG_PARAMS, + + STATE_CLIPPLANE, + + STATE_POINT_SIZE, + STATE_POINT_ATTENUATION, + + STATE_MODELVIEW_MATRIX, + STATE_PROJECTION_MATRIX, + STATE_MVP_MATRIX, + STATE_TEXTURE_MATRIX, + STATE_PROGRAM_MATRIX, + STATE_MATRIX_INVERSE, + STATE_MATRIX_TRANSPOSE, + STATE_MATRIX_INVTRANS, + + STATE_AMBIENT, + STATE_DIFFUSE, + STATE_SPECULAR, + STATE_EMISSION, + STATE_SHININESS, + STATE_HALF_VECTOR, + + STATE_POSITION, + STATE_ATTENUATION, + STATE_SPOT_DIRECTION, + STATE_SPOT_CUTOFF, + + STATE_TEXGEN_EYE_S, + STATE_TEXGEN_EYE_T, + STATE_TEXGEN_EYE_R, + STATE_TEXGEN_EYE_Q, + STATE_TEXGEN_OBJECT_S, + STATE_TEXGEN_OBJECT_T, + STATE_TEXGEN_OBJECT_R, + STATE_TEXGEN_OBJECT_Q, + + STATE_TEXENV_COLOR, + + STATE_DEPTH_RANGE, + + STATE_VERTEX_PROGRAM, + STATE_FRAGMENT_PROGRAM, + + STATE_ENV, + STATE_LOCAL, + + STATE_INTERNAL, /* Mesa additions */ + STATE_NORMAL_SCALE, + STATE_TEXRECT_SCALE, + STATE_POSITION_NORMALIZED, /* normalized light position */ + STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */ + STATE_SPOT_DIR_NORMALIZED, /* pre-normalized spot dir */ + STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */ +} gl_state_index; + + + +extern void +_mesa_load_state_parameters(GLcontext *ctx, + struct gl_program_parameter_list *paramList); + + +extern GLbitfield +_mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]); + + +extern const char * +_mesa_program_state_string(const gl_state_index state[STATE_LENGTH]); + + +#endif /* PROG_STATEVARS_H */ diff --git a/dist/Mesa/src/mesa/shader/shader_api.c b/dist/Mesa/src/mesa/shader/shader_api.c new file mode 100644 index 000000000..b794e30e9 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/shader_api.c @@ -0,0 +1,1228 @@ +/* + * Mesa 3-D graphics library + * Version: 7.0 + * + * Copyright (C) 2004-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file shader_api.c + * Implementation of GLSL-related API functions + * \author Brian Paul + */ + +/** + * XXX things to do: + * 1. Check that the right error code is generated for all _mesa_error() calls. + * 2. Insert FLUSH_VERTICES calls in various places + */ + + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "macros.h" +#include "program.h" +#include "prog_parameter.h" +#include "prog_print.h" +#include "prog_statevars.h" +#include "shader_api.h" + +#include "slang_compile.h" +#include "slang_link.h" + + + +/** + * Allocate a new gl_shader_program object, initialize it. + */ +struct gl_shader_program * +_mesa_new_shader_program(GLcontext *ctx, GLuint name) +{ + struct gl_shader_program *shProg; + shProg = CALLOC_STRUCT(gl_shader_program); + if (shProg) { + shProg->Type = GL_SHADER_PROGRAM_MESA; + shProg->Name = name; + shProg->RefCount = 1; + shProg->Attributes = _mesa_new_parameter_list(); + } + return shProg; +} + + +/** + * Clear (free) the shader program state that gets produced by linking. + */ +void +_mesa_clear_shader_program_data(GLcontext *ctx, + struct gl_shader_program *shProg) +{ + if (shProg->VertexProgram) { + if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) { + /* to prevent a double-free in the next call */ + shProg->VertexProgram->Base.Parameters = NULL; + } + _mesa_delete_program(ctx, &shProg->VertexProgram->Base); + shProg->VertexProgram = NULL; + } + + if (shProg->FragmentProgram) { + if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) { + /* to prevent a double-free in the next call */ + shProg->FragmentProgram->Base.Parameters = NULL; + } + _mesa_delete_program(ctx, &shProg->FragmentProgram->Base); + shProg->FragmentProgram = NULL; + } + + if (shProg->Uniforms) { + _mesa_free_parameter_list(shProg->Uniforms); + shProg->Uniforms = NULL; + } + + if (shProg->Varying) { + _mesa_free_parameter_list(shProg->Varying); + shProg->Varying = NULL; + } +} + + +/** + * Free all the data that hangs off a shader program object, but not the + * object itself. + */ +void +_mesa_free_shader_program_data(GLcontext *ctx, + struct gl_shader_program *shProg) +{ + GLuint i; + + assert(shProg->Type == GL_SHADER_PROGRAM_MESA); + + _mesa_clear_shader_program_data(ctx, shProg); + + if (shProg->Attributes) { + _mesa_free_parameter_list(shProg->Attributes); + shProg->Attributes = NULL; + } + + /* detach shaders */ + for (i = 0; i < shProg->NumShaders; i++) { + _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); + } + if (shProg->Shaders) { + _mesa_free(shProg->Shaders); + shProg->Shaders = NULL; + } +} + + +/** + * Free/delete a shader program object. + */ +void +_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg) +{ + _mesa_free_shader_program_data(ctx, shProg); + if (shProg->Shaders) { + _mesa_free(shProg->Shaders); + shProg->Shaders = NULL; + } + _mesa_free(shProg); +} + + +/** + * Set ptr to point to shProg. + * If ptr is pointing to another object, decrement its refcount (and delete + * if refcount hits zero). + * Then set ptr to point to shProg, incrementing its refcount. + */ +/* XXX this could be static */ +void +_mesa_reference_shader_program(GLcontext *ctx, + struct gl_shader_program **ptr, + struct gl_shader_program *shProg) +{ + assert(ptr); + if (*ptr == shProg) { + /* no-op */ + return; + } + if (*ptr) { + /* Unreference the old shader program */ + GLboolean deleteFlag = GL_FALSE; + struct gl_shader_program *old = *ptr; + + ASSERT(old->RefCount > 0); + old->RefCount--; + /*printf("SHPROG DECR %p (%d) to %d\n", + (void*) old, old->Name, old->RefCount);*/ + deleteFlag = (old->RefCount == 0); + + if (deleteFlag) { + _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name); + _mesa_free_shader_program(ctx, old); + } + + *ptr = NULL; + } + assert(!*ptr); + + if (shProg) { + shProg->RefCount++; + /*printf("SHPROG INCR %p (%d) to %d\n", + (void*) shProg, shProg->Name, shProg->RefCount);*/ + *ptr = shProg; + } +} + + +/** + * Lookup a GLSL program object. + */ +struct gl_shader_program * +_mesa_lookup_shader_program(GLcontext *ctx, GLuint name) +{ + struct gl_shader_program *shProg; + if (name) { + shProg = (struct gl_shader_program *) + _mesa_HashLookup(ctx->Shared->ShaderObjects, name); + /* Note that both gl_shader and gl_shader_program objects are kept + * in the same hash table. Check the object's type to be sure it's + * what we're expecting. + */ + if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) { + return NULL; + } + return shProg; + } + return NULL; +} + + +/** + * Allocate a new gl_shader object, initialize it. + */ +struct gl_shader * +_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type) +{ + struct gl_shader *shader; + assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER); + shader = CALLOC_STRUCT(gl_shader); + if (shader) { + shader->Type = type; + shader->Name = name; + shader->RefCount = 1; + } + return shader; +} + + +void +_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh) +{ + GLuint i; + if (sh->Source) + _mesa_free((void *) sh->Source); + if (sh->InfoLog) + _mesa_free(sh->InfoLog); + for (i = 0; i < sh->NumPrograms; i++) { + assert(sh->Programs[i]); + _mesa_delete_program(ctx, sh->Programs[i]); + } + if (sh->Programs) + _mesa_free(sh->Programs); + _mesa_free(sh); +} + + +/** + * Set ptr to point to sh. + * If ptr is pointing to another shader, decrement its refcount (and delete + * if refcount hits zero). + * Then set ptr to point to sh, incrementing its refcount. + */ +/* XXX this could be static */ +void +_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr, + struct gl_shader *sh) +{ + assert(ptr); + if (*ptr == sh) { + /* no-op */ + return; + } + if (*ptr) { + /* Unreference the old shader */ + GLboolean deleteFlag = GL_FALSE; + struct gl_shader *old = *ptr; + + ASSERT(old->RefCount > 0); + old->RefCount--; + /*printf("SHADER DECR %p (%d) to %d\n", + (void*) old, old->Name, old->RefCount);*/ + deleteFlag = (old->RefCount == 0); + + if (deleteFlag) { + _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name); + _mesa_free_shader(ctx, old); + } + + *ptr = NULL; + } + assert(!*ptr); + + if (sh) { + /* reference new */ + sh->RefCount++; + /*printf("SHADER INCR %p (%d) to %d\n", + (void*) sh, sh->Name, sh->RefCount);*/ + *ptr = sh; + } +} + + +/** + * Lookup a GLSL shader object. + */ +struct gl_shader * +_mesa_lookup_shader(GLcontext *ctx, GLuint name) +{ + if (name) { + struct gl_shader *sh = (struct gl_shader *) + _mesa_HashLookup(ctx->Shared->ShaderObjects, name); + /* Note that both gl_shader and gl_shader_program objects are kept + * in the same hash table. Check the object's type to be sure it's + * what we're expecting. + */ + if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) { + return NULL; + } + return sh; + } + return NULL; +} + + +/** + * Initialize context's shader state. + */ +void +_mesa_init_shader_state(GLcontext * ctx) +{ + /* Device drivers may override these to control what kind of instructions + * are generated by the GLSL compiler. + */ + ctx->Shader.EmitHighLevelInstructions = GL_TRUE; + ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */ + ctx->Shader.EmitComments = GL_FALSE; +} + + +/** + * Free the per-context shader-related state. + */ +void +_mesa_free_shader_state(GLcontext *ctx) +{ + _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL); +} + + +/** + * Copy string from <src> to <dst>, up to maxLength characters, returning + * length of <dst> in <length>. + * \param src the strings source + * \param maxLength max chars to copy + * \param length returns number of chars copied + * \param dst the string destination + */ +static void +copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src) +{ + GLsizei len; + for (len = 0; len < maxLength - 1 && src && src[len]; len++) + dst[len] = src[len]; + if (maxLength > 0) + dst[len] = 0; + if (length) + *length = len; +} + + +/** + * Called via ctx->Driver.AttachShader() + */ +void +_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); + const GLuint n = shProg->NumShaders; + GLuint i; + + if (!shProg || !sh) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glAttachShader(bad program or shader name)"); + return; + } + + for (i = 0; i < n; i++) { + if (shProg->Shaders[i] == sh) { + /* already attached */ + return; + } + } + + /* grow list */ + shProg->Shaders = (struct gl_shader **) + _mesa_realloc(shProg->Shaders, + n * sizeof(struct gl_shader *), + (n + 1) * sizeof(struct gl_shader *)); + if (!shProg->Shaders) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader"); + return; + } + + /* append */ + shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */ + _mesa_reference_shader(ctx, &shProg->Shaders[n], sh); + shProg->NumShaders++; +} + + +void +_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, + const GLchar *name) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + const GLint size = -1; /* unknown size */ + GLint i, oldIndex; + + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)"); + return; + } + + if (!name) + return; + + if (strncmp(name, "gl_", 3) == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindAttribLocation(illegal name)"); + return; + } + + if (shProg->LinkStatus) { + /* get current index/location for the attribute */ + oldIndex = _mesa_get_attrib_location(ctx, program, name); + } + else { + oldIndex = -1; + } + + /* this will replace the current value if it's already in the list */ + i = _mesa_add_attribute(shProg->Attributes, name, size, index); + if (i < 0) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation"); + } + + if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) { + /* If the index changed, need to search/replace references to that attribute + * in the vertex program. + */ + _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index); + } +} + + +GLuint +_mesa_create_shader(GLcontext *ctx, GLenum type) +{ + struct gl_shader *sh; + GLuint name; + + name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); + + switch (type) { + case GL_FRAGMENT_SHADER: + case GL_VERTEX_SHADER: + sh = _mesa_new_shader(ctx, name, type); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)"); + return 0; + } + + _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); + + return name; +} + + +GLuint +_mesa_create_program(GLcontext *ctx) +{ + GLuint name; + struct gl_shader_program *shProg; + + name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); + shProg = _mesa_new_shader_program(ctx, name); + + _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); + + assert(shProg->RefCount == 1); + + return name; +} + + +/** + * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's + * DeleteProgramARB. + */ +void +_mesa_delete_program2(GLcontext *ctx, GLuint name) +{ + /* + * NOTE: deleting shaders/programs works a bit differently than + * texture objects (and buffer objects, etc). Shader/program + * handles/IDs exist in the hash table until the object is really + * deleted (refcount==0). With texture objects, the handle/ID is + * removed from the hash table in glDeleteTextures() while the tex + * object itself might linger until its refcount goes to zero. + */ + struct gl_shader_program *shProg; + + shProg = _mesa_lookup_shader_program(ctx, name); + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)"); + return; + } + + shProg->DeletePending = GL_TRUE; + + /* effectively, decr shProg's refcount */ + _mesa_reference_shader_program(ctx, &shProg, NULL); +} + + +void +_mesa_delete_shader(GLcontext *ctx, GLuint shader) +{ + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); + if (!sh) { + return; + } + + sh->DeletePending = GL_TRUE; + + /* effectively, decr sh's refcount */ + _mesa_reference_shader(ctx, &sh, NULL); +} + + +void +_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + const GLuint n = shProg->NumShaders; + GLuint i, j; + + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glDetachShader(bad program or shader name)"); + return; + } + + for (i = 0; i < n; i++) { + if (shProg->Shaders[i]->Name == shader) { + /* found it */ + struct gl_shader **newList; + + /* derefernce */ + _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); + + /* alloc new, smaller array */ + newList = (struct gl_shader **) + _mesa_malloc((n - 1) * sizeof(struct gl_shader *)); + if (!newList) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); + return; + } + for (j = 0; j < i; j++) { + newList[j] = shProg->Shaders[j]; + } + while (++i < n) + newList[j++] = shProg->Shaders[i]; + _mesa_free(shProg->Shaders); + + shProg->Shaders = newList; + shProg->NumShaders = n - 1; + +#ifdef DEBUG + /* sanity check */ + { + for (j = 0; j < shProg->NumShaders; j++) { + assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || + shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); + assert(shProg->Shaders[j]->RefCount > 0); + } + } +#endif + + return; + } + } + + /* not found */ + _mesa_error(ctx, GL_INVALID_VALUE, + "glDetachShader(shader not found)"); +} + + +void +_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, + GLsizei maxLength, GLsizei *length, GLint *size, + GLenum *type, GLchar *nameOut) +{ + static const GLenum vec_types[] = { + GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4 + }; + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + GLint sz; + + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib"); + return; + } + + if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); + return; + } + + copy_string(nameOut, maxLength, length, + shProg->Attributes->Parameters[index].Name); + sz = shProg->Attributes->Parameters[index].Size; + if (size) + *size = sz; + if (type) + *type = vec_types[sz]; /* XXX this is a temporary hack */ +} + + +/** + * Called via ctx->Driver.GetActiveUniform(). + */ +void +_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, + GLsizei maxLength, GLsizei *length, GLint *size, + GLenum *type, GLchar *nameOut) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + GLuint ind, j; + + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform"); + return; + } + + if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); + return; + } + + ind = 0; + for (j = 0; j < shProg->Uniforms->NumParameters; j++) { + if (shProg->Uniforms->Parameters[j].Type == PROGRAM_UNIFORM || + shProg->Uniforms->Parameters[j].Type == PROGRAM_SAMPLER) { + if (ind == index) { + /* found it */ + copy_string(nameOut, maxLength, length, + shProg->Uniforms->Parameters[j].Name); + if (size) + *size = shProg->Uniforms->Parameters[j].Size; + if (type) + *type = shProg->Uniforms->Parameters[j].DataType; + return; + } + ind++; + } + } + + _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); +} + + +/** + * Called via ctx->Driver.GetAttachedShaders(). + */ +void +_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount, + GLsizei *count, GLuint *obj) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + if (shProg) { + GLint i; + for (i = 0; i < maxCount && i < shProg->NumShaders; i++) { + obj[i] = shProg->Shaders[i]->Name; + } + if (count) + *count = i; + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders"); + } +} + + +GLint +_mesa_get_attrib_location(GLcontext *ctx, GLuint program, + const GLchar *name) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation"); + return -1; + } + + if (!shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetAttribLocation(program not linked)"); + return -1; + } + + if (!name) + return -1; + + if (shProg->Attributes) { + GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name); + if (i >= 0) { + return shProg->Attributes->Parameters[i].StateIndexes[0]; + } + } + return -1; +} + + +GLuint +_mesa_get_handle(GLcontext *ctx, GLenum pname) +{ +#if 0 + GET_CURRENT_CONTEXT(ctx); + + switch (pname) { + case GL_PROGRAM_OBJECT_ARB: + { + struct gl2_program_intf **pro = ctx->Shader.CurrentProgram; + + if (pro != NULL) + return (**pro)._container._generic. + GetName((struct gl2_generic_intf **) (pro)); + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB"); + } +#endif + return 0; +} + + +void +_mesa_get_programiv(GLcontext *ctx, GLuint program, + GLenum pname, GLint *params) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)"); + return; + } + + switch (pname) { + case GL_DELETE_STATUS: + *params = shProg->DeletePending; + break; + case GL_LINK_STATUS: + *params = shProg->LinkStatus; + break; + case GL_VALIDATE_STATUS: + *params = shProg->Validated; + break; + case GL_INFO_LOG_LENGTH: + *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0; + break; + case GL_ATTACHED_SHADERS: + *params = shProg->NumShaders; + break; + case GL_ACTIVE_ATTRIBUTES: + *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0; + break; + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = _mesa_longest_parameter_name(shProg->Attributes, + PROGRAM_INPUT) + 1; + break; + case GL_ACTIVE_UNIFORMS: + *params + = _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_UNIFORM) + + _mesa_num_parameters_of_type(shProg->Uniforms, PROGRAM_SAMPLER); + break; + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + *params = MAX2( + _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_UNIFORM), + _mesa_longest_parameter_name(shProg->Uniforms, PROGRAM_SAMPLER)); + if (*params > 0) + (*params)++; /* add one for terminating zero */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)"); + return; + } +} + + +void +_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params) +{ + struct gl_shader *shader = _mesa_lookup_shader(ctx, name); + + if (!shader) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)"); + return; + } + + switch (pname) { + case GL_SHADER_TYPE: + *params = shader->Type; + break; + case GL_DELETE_STATUS: + *params = shader->DeletePending; + break; + case GL_COMPILE_STATUS: + *params = shader->CompileStatus; + break; + case GL_INFO_LOG_LENGTH: + *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0; + break; + case GL_SHADER_SOURCE_LENGTH: + *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)"); + return; + } +} + + +void +_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize, + GLsizei *length, GLchar *infoLog) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)"); + return; + } + copy_string(infoLog, bufSize, length, shProg->InfoLog); +} + + +void +_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize, + GLsizei *length, GLchar *infoLog) +{ + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); + if (!sh) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)"); + return; + } + copy_string(infoLog, bufSize, length, sh->InfoLog); +} + + +/** + * Called via ctx->Driver.GetShaderSource(). + */ +void +_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *sourceOut) +{ + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); + if (!sh) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)"); + return; + } + copy_string(sourceOut, maxLength, length, sh->Source); +} + + +/** + * Called via ctx->Driver.GetUniformfv(). + */ +void +_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location, + GLfloat *params) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + if (shProg) { + GLint i; + if (location >= 0 && location < shProg->Uniforms->NumParameters) { + for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) { + params[i] = shProg->Uniforms->ParameterValues[location][i]; + } + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)"); + } + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)"); + } +} + + +/** + * Called via ctx->Driver.GetUniformLocation(). + */ +GLint +_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name) +{ + struct gl_shader_program *shProg + = _mesa_lookup_shader_program(ctx, program); + if (shProg) { + GLuint loc; + for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) { + const struct gl_program_parameter *u + = shProg->Uniforms->Parameters + loc; + /* XXX this is a temporary simplification / short-cut. + * We need to handle things like "e.c[0].b" as seen in the + * GLSL orange book, page 189. + */ + if ((u->Type == PROGRAM_UNIFORM || + u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) { + return loc; + } + } + } + return -1; + +} + + +GLboolean +_mesa_is_program(GLcontext *ctx, GLuint name) +{ + struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name); + return shProg ? GL_TRUE : GL_FALSE; +} + + +GLboolean +_mesa_is_shader(GLcontext *ctx, GLuint name) +{ + struct gl_shader *shader = _mesa_lookup_shader(ctx, name); + return shader ? GL_TRUE : GL_FALSE; +} + + + +/** + * Called via ctx->Driver.ShaderSource() + */ +void +_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source) +{ + struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); + if (!sh) { + _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)"); + return; + } + + /* free old shader source string and install new one */ + if (sh->Source) { + _mesa_free((void *) sh->Source); + } + sh->Source = source; + sh->CompileStatus = GL_FALSE; +} + + +/** + * Called via ctx->Driver.CompileShader() + */ +void +_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj) +{ + struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj); + + if (!sh) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)"); + return; + } + + sh->CompileStatus = _slang_compile(ctx, sh); +} + + +/** + * Called via ctx->Driver.LinkProgram() + */ +void +_mesa_link_program(GLcontext *ctx, GLuint program) +{ + struct gl_shader_program *shProg; + + shProg = _mesa_lookup_shader_program(ctx, program); + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)"); + return; + } + + _slang_link(ctx, program, shProg); +} + + +/** + * Called via ctx->Driver.UseProgram() + */ +void +_mesa_use_program(GLcontext *ctx, GLuint program) +{ + struct gl_shader_program *shProg; + + if (ctx->Shader.CurrentProgram && + ctx->Shader.CurrentProgram->Name == program) { + /* no-op */ + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (program) { + shProg = _mesa_lookup_shader_program(ctx, program); + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glUseProgramObjectARB(programObj)"); + return; + } + } + else { + shProg = NULL; + } + + _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg); +} + + +/** + * Called via ctx->Driver.Uniform(). + */ +void +_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, + const GLvoid *values, GLenum type) +{ + struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; + GLint elems, i, k; + + if (!shProg || !shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)"); + return; + } + + if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) { + _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + /* + * If we're setting a sampler, we must use glUniformi1()! + */ + if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) { + GLint unit; + if (type != GL_INT || count != 1) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUniform(only glUniform1i can be used " + "to set sampler uniforms)"); + return; + } + /* check that the sampler (tex unit index) is legal */ + unit = ((GLint *) values)[0]; + if (unit >= ctx->Const.MaxTextureImageUnits) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glUniform1(invalid sampler/tex unit index)"); + return; + } + } + + if (count < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)"); + return; + } + + switch (type) { + case GL_FLOAT: + case GL_INT: + elems = 1; + break; + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + elems = 2; + break; + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + elems = 3; + break; + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + elems = 4; + break; + default: + _mesa_problem(ctx, "Invalid type in _mesa_uniform"); + return; + } + + if (count * elems > shProg->Uniforms->Parameters[location].Size) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)"); + return; + } + + for (k = 0; k < count; k++) { + GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k]; + if (type == GL_INT || + type == GL_INT_VEC2 || + type == GL_INT_VEC3 || + type == GL_INT_VEC4) { + const GLint *iValues = ((const GLint *) values) + k * elems; + for (i = 0; i < elems; i++) { + uniformVal[i] = (GLfloat) iValues[i]; + } + } + else { + const GLfloat *fValues = ((const GLfloat *) values) + k * elems; + for (i = 0; i < elems; i++) { + uniformVal[i] = fValues[i]; + } + } + } + + if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) { + if (shProg->VertexProgram) + _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base); + if (shProg->FragmentProgram) + _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base); + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + } +} + + +/** + * Called by ctx->Driver.UniformMatrix(). + */ +void +_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, + GLenum matrixType, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *values) +{ + struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; + if (!shProg || !shProg->LinkStatus) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glUniformMatrix(program not linked)"); + return; + } + if (location < 0 || location >= shProg->Uniforms->NumParameters) { + _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)"); + return; + } + if (values == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + /* + * Note: the _columns_ of a matrix are stored in program registers, not + * the rows. + */ + /* XXXX need to test 3x3 and 2x2 matrices... */ + if (transpose) { + GLuint row, col; + for (col = 0; col < cols; col++) { + GLfloat *v = shProg->Uniforms->ParameterValues[location + col]; + for (row = 0; row < rows; row++) { + v[row] = values[row * cols + col]; + } + } + } + else { + GLuint row, col; + for (col = 0; col < cols; col++) { + GLfloat *v = shProg->Uniforms->ParameterValues[location + col]; + for (row = 0; row < rows; row++) { + v[row] = values[col * rows + row]; + } + } + } +} + + +void +_mesa_validate_program(GLcontext *ctx, GLuint program) +{ + struct gl_shader_program *shProg; + shProg = _mesa_lookup_shader_program(ctx, program); + if (!shProg) { + _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)"); + return; + } + /* XXX temporary */ + shProg->Validated = GL_TRUE; + + /* From the GL spec: + any two active samplers in the current program object are of + different types, but refer to the same texture image unit, + + any active sampler in the current program object refers to a texture + image unit where fixed-function fragment processing accesses a + texture target that does not match the sampler type, or + + the sum of the number of active samplers in the program and the + number of texture image units enabled for fixed-function fragment + processing exceeds the combined limit on the total number of texture + image units allowed. + */ +} diff --git a/dist/Mesa/src/mesa/shader/shader_api.h b/dist/Mesa/src/mesa/shader/shader_api.h new file mode 100644 index 000000000..27e5870d7 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/shader_api.h @@ -0,0 +1,185 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2004-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef SHADER_API_H +#define SHADER_API_H + + +#include "glheader.h" +#include "mtypes.h" + + +/** + * Internal functions + */ + +extern void +_mesa_init_shader_state(GLcontext * ctx); + +extern void +_mesa_free_shader_state(GLcontext *ctx); + +extern struct gl_shader_program * +_mesa_new_shader_program(GLcontext *ctx, GLuint name); + +extern void +_mesa_clear_shader_program_data(GLcontext *ctx, + struct gl_shader_program *shProg); + +extern void +_mesa_free_shader_program_data(GLcontext *ctx, + struct gl_shader_program *shProg); + +extern void +_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg); + +extern void +_mesa_reference_shader_program(GLcontext *ctx, + struct gl_shader_program **ptr, + struct gl_shader_program *shProg); + +extern struct gl_shader_program * +_mesa_lookup_shader_program(GLcontext *ctx, GLuint name); + + +extern struct gl_shader * +_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type); + +extern void +_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh); + +extern void +_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr, + struct gl_shader *sh); + +extern struct gl_shader * +_mesa_lookup_shader(GLcontext *ctx, GLuint name); + + +/** + * API/Driver functions + */ + +extern void +_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader); + +extern void +_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, + const GLchar *name); + +extern void +_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj); + +extern GLuint +_mesa_create_shader(GLcontext *ctx, GLenum type); + +extern GLuint +_mesa_create_program(GLcontext *ctx); + +extern void +_mesa_delete_program2(GLcontext *ctx, GLuint name); + +extern void +_mesa_delete_shader(GLcontext *ctx, GLuint shader); + +extern void +_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader); + +extern void +_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, + GLsizei maxLength, GLsizei *length, GLint *size, + GLenum *type, GLchar *name); + +extern void +_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, + GLsizei maxLength, GLsizei *length, GLint *size, + GLenum *type, GLchar *name); + +extern void +_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount, + GLsizei *count, GLuint *obj); + +extern GLint +_mesa_get_attrib_location(GLcontext *ctx, GLuint program, + const GLchar *name); + +extern GLuint +_mesa_get_handle(GLcontext *ctx, GLenum pname); + +extern void +_mesa_get_programiv(GLcontext *ctx, GLuint program, + GLenum pname, GLint *params); + +extern void +_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + +extern void +_mesa_get_shaderiv(GLcontext *ctx, GLuint shader, GLenum pname, GLint *params); + +extern void +_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + +extern void +_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength, + GLsizei *length, GLchar *sourceOut); + +extern void +_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location, + GLfloat *params); + +extern GLint +_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name); + +extern GLboolean +_mesa_is_program(GLcontext *ctx, GLuint name); + +extern GLboolean +_mesa_is_shader(GLcontext *ctx, GLuint name); + +extern void +_mesa_link_program(GLcontext *ctx, GLuint program); + +extern void +_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source); + +extern void +_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, + const GLvoid *values, GLenum type); + +void +_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, + GLenum matrixType, GLint location, GLsizei count, + GLboolean transpose, const GLfloat *values); + +extern void +_mesa_use_program(GLcontext *ctx, GLuint program); + +extern void +_mesa_validate_program(GLcontext *ctx, GLuint program); + + +#endif /* SHADER_API_H */ diff --git a/dist/Mesa/src/mesa/shader/slang/library/Makefile b/dist/Mesa/src/mesa/shader/slang/library/Makefile new file mode 100644 index 000000000..dc67b5908 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/Makefile @@ -0,0 +1,81 @@ +# src/mesa/shader/slang/library/Makefile + +TOP = ../../../../.. + +include $(TOP)/configs/current + +INCDIR = $(TOP)/include + +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) + +# +# targets +# + +.PHONY: default clean + +default: syntax builtin + +clean: + rm -f syn_to_c gc_to_bin *_syn.h *_gc.h + +syntax: slang_pp_directives_syn.h slang_pp_expression_syn.h slang_shader_syn.h slang_pp_version_syn.h + +builtin: builtin_110 builtin_120 + +# +# executables +# + +syn_to_c: syn_to_c.c + $(CC) syn_to_c.c -o syn_to_c + +gc_to_bin: gc_to_bin.c slang_shader_syn.h + $(CC) gc_to_bin.c -o gc_to_bin + +# +# syntax scripts +# + +slang_pp_directives_syn.h: syn_to_c slang_pp_directives.syn + ./syn_to_c slang_pp_directives.syn > slang_pp_directives_syn.h + +slang_pp_expression_syn.h: syn_to_c slang_pp_expression.syn + ./syn_to_c slang_pp_expression.syn > slang_pp_expression_syn.h + +slang_shader_syn.h: syn_to_c slang_shader.syn + ./syn_to_c slang_shader.syn > slang_shader_syn.h + +slang_pp_version_syn.h: syn_to_c slang_pp_version.syn + ./syn_to_c slang_pp_version.syn > slang_pp_version_syn.h + +# +# builtin library sources +# + +builtin_110: slang_common_builtin_gc.h slang_core_gc.h slang_fragment_builtin_gc.h slang_vertex_builtin_gc.h + +builtin_120: slang_120_core_gc.h slang_builtin_120_common_gc.h slang_builtin_120_fragment_gc.h + + +slang_120_core_gc.h: gc_to_bin slang_120_core.gc + ./gc_to_bin 1 slang_120_core.gc slang_120_core_gc.h + +slang_builtin_120_common_gc.h: gc_to_bin slang_builtin_120_common.gc + ./gc_to_bin 1 slang_builtin_120_common.gc slang_builtin_120_common_gc.h + +slang_builtin_120_fragment_gc.h: gc_to_bin slang_builtin_120_fragment.gc + ./gc_to_bin 1 slang_builtin_120_fragment.gc slang_builtin_120_fragment_gc.h + +slang_common_builtin_gc.h: gc_to_bin slang_common_builtin.gc + ./gc_to_bin 1 slang_common_builtin.gc slang_common_builtin_gc.h + +slang_core_gc.h: gc_to_bin slang_core.gc + ./gc_to_bin 1 slang_core.gc slang_core_gc.h + +slang_fragment_builtin_gc.h: gc_to_bin slang_fragment_builtin.gc + ./gc_to_bin 1 slang_fragment_builtin.gc slang_fragment_builtin_gc.h + +slang_vertex_builtin_gc.h: gc_to_bin slang_vertex_builtin.gc + ./gc_to_bin 2 slang_vertex_builtin.gc slang_vertex_builtin_gc.h + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_120_core.gc b/dist/Mesa/src/mesa/shader/slang/library/slang_120_core.gc new file mode 100644 index 000000000..15ca3a81a --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_120_core.gc @@ -0,0 +1,2028 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// Constructors and operators introduced in GLSL 1.20 - mostly on new +// (non-square) types of matrices. +// +// One important change in the language is that when a matrix is used +// as an argument to a matrix constructor, it must be the only argument +// for the constructor. The compiler takes care of it by itself and +// here we only care to re-introduce constructors for old (square) +// types of matrices. +// + +// +// From Shader Spec, ver. 1.20, rev. 6 +// + +//// mat2x3: 2 columns of vec3 + +mat2x3 __constructor(const float f00, const float f10, const float f20, + const float f01, const float f11, const float f21) +{ + __retVal[0].x = f00; + __retVal[0].y = f10; + __retVal[0].z = f20; + __retVal[1].x = f01; + __retVal[1].y = f11; + __retVal[1].z = f21; +} + +mat2x3 __constructor(const float f) +{ + __retVal = mat2x3( f, 0.0, 0.0, + 0.0, f, 0.0); +} + +mat2x3 __constructor(const int i) +{ + const float f = float(i); + __retVal = mat2x3(f); +} + +mat2x3 __constructor(const bool b) +{ + const float f = float(b); + __retVal = mat2x3(f); +} + +mat2x3 __constructor(const vec3 c0, const vec3 c1) +{ + __retVal[0] = c0; + __retVal[1] = c1; +} + + + +//// mat2x4: 2 columns of vec4 + +mat2x4 __constructor(const float f00, const float f10, const float f20, const float f30, + const float f01, const float f11, const float f21, const float f31) +{ + __retVal[0].x = f00; + __retVal[0].y = f10; + __retVal[0].z = f20; + __retVal[0].w = f30; + __retVal[1].x = f01; + __retVal[1].y = f11; + __retVal[1].z = f21; + __retVal[1].w = f31; +} + +mat2x4 __constructor(const float f) +{ + __retVal = mat2x4( f, 0.0, 0.0, 0.0, + 0.0, f, 0.0, 0.0); +} + +mat2x4 __constructor(const int i) +{ + const float f = float(i); + __retVal = mat2x4(f); +} + +mat2x4 __constructor(const bool b) +{ + const float f = float(b); + __retVal = mat2x4(f); +} + +mat2x4 __constructor(const vec4 c0, const vec4 c1) +{ + __retVal[0] = c0; + __retVal[1] = c1; +} + + + +//// mat3x2: 3 columns of vec2 + +mat3x2 __constructor(const float f00, const float f10, + const float f01, const float f11, + const float f02, const float f12) +{ + __retVal[0].x = f00; + __retVal[0].y = f10; + __retVal[1].x = f01; + __retVal[1].y = f11; + __retVal[2].x = f02; + __retVal[2].y = f12; +} + +mat3x2 __constructor(const float f) +{ + __retVal = mat3x2( f, 0.0, + 0.0, f, + 0.0, 0.0); +} + +mat3x2 __constructor(const int i) +{ + const float f = float(i); + __retVal = mat3x2(f); +} + +mat3x2 __constructor(const bool b) +{ + const float f = float(b); + __retVal = mat3x2(f); +} + +mat3x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2) +{ + __retVal[0] = c0; + __retVal[1] = c1; + __retVal[2] = c2; +} + + + +//// mat3x4: 3 columns of vec4 + +mat3x4 __constructor(const float f00, const float f10, const float f20, const float f30, + const float f01, const float f11, const float f21, const float f31, + const float f02, const float f12, const float f22, const float f32) +{ + __retVal[0].x = f00; + __retVal[0].y = f10; + __retVal[0].z = f20; + __retVal[0].w = f30; + __retVal[1].x = f01; + __retVal[1].y = f11; + __retVal[1].z = f21; + __retVal[1].w = f31; + __retVal[2].x = f02; + __retVal[2].y = f12; + __retVal[2].z = f22; + __retVal[2].w = f32; +} + +mat3x4 __constructor(const float f) +{ + __retVal = mat3x4( f, 0.0, 0.0, 0.0, + 0.0, f, 0.0, 0.0, + 0.0, 0.0, f, 0.0); +} + +mat3x4 __constructor(const int i) +{ + const float f = float(i); + __retVal = mat3x4(f); +} + +mat3x4 __constructor(const bool b) +{ + const float f = float(b); + __retVal = mat3x4(f); +} + +mat3x4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2) +{ + __retVal[0] = c0; + __retVal[1] = c1; + __retVal[2] = c2; +} + + + +//// mat4x2: 4 columns of vec2 + +mat4x2 __constructor(const float f00, const float f10, + const float f01, const float f11, + const float f02, const float f12, + const float f03, const float f13) +{ + __retVal[0].x = f00; + __retVal[0].y = f10; + __retVal[1].x = f01; + __retVal[1].y = f11; + __retVal[2].x = f02; + __retVal[2].y = f12; + __retVal[3].x = f03; + __retVal[3].y = f13; +} + +mat4x2 __constructor(const float f) +{ + __retVal = mat4x2( f, 0.0, + 0.0, 4, + 0.0, 0.0, + 0.0, 0.0); +} + +mat4x2 __constructor(const int i) +{ + const float f = float(i); + __retVal = mat4x2(f); +} + +mat4x2 __constructor(const bool b) +{ + const float f = float(b); + __retVal = mat4x2(f); +} + +mat4x2 __constructor(const vec2 c0, const vec2 c1, const vec2 c2, const vec2 c3) +{ + __retVal[0] = c0; + __retVal[1] = c1; + __retVal[2] = c2; + __retVal[3] = c3; +} + + + +//// mat4x3: 4 columns of vec3 + +mat4x3 __constructor(const float f00, const float f10, const float f20, + const float f01, const float f11, const float f21, + const float f02, const float f12, const float f22, + const float f03, const float f13, const float f23) +{ + __retVal[0].x = f00; + __retVal[0].y = f10; + __retVal[0].z = f20; + __retVal[1].x = f01; + __retVal[1].y = f11; + __retVal[1].z = f21; + __retVal[2].x = f02; + __retVal[2].y = f12; + __retVal[2].z = f22; + __retVal[3].x = f03; + __retVal[3].y = f13; + __retVal[3].z = f23; +} + +mat4x3 __constructor(const float f) +{ + __retVal = mat4x3( f, 0.0, 0.0, + 0.0, f, 0.0, + 0.0, 0.0, f, + 0.0, 0.0, 0.0); +} + +mat4x3 __constructor(const int i) +{ + const float f = float(i); + __retVal = mat4x3(f); +} + +mat4x3 __constructor(const bool b) +{ + const float f = float(b); + __retVal = mat4x3(f); +} + +mat4x3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2, const vec3 c3) +{ + __retVal[0] = c0; + __retVal[1] = c1; + __retVal[2] = c2; + __retVal[3] = c3; +} + + + +//// misc assorted matrix constructors + +mat2 __constructor(const mat2 m) +{ + __retVal = m; +} + +mat2 __constructor(const mat3x2 m) +{ + __retVal = mat2(m[0], m[1]); +} + +mat2 __constructor(const mat4x2 m) +{ + __retVal = mat2(m[0], m[1]); +} + +mat2 __constructor(const mat2x3 m) +{ + __retVal = mat2(m[0].xy, m[1].xy); +} + +mat2 __constructor(const mat2x4 m) +{ + __retVal = mat2(m[0].xy, m[1].xy); +} + +mat2 __constructor(const mat3 m) +{ + __retVal = mat2(m[0].xy, m[1].xy); +} + +mat2 __constructor(const mat3x4 m) +{ + __retVal = mat2(m[0].xy, m[1].xy); +} + +mat2 __constructor(const mat4x3 m) +{ + __retVal = mat2(m[0].xy, m[1].xy); +} + +mat2 __constructor(const mat4 m) +{ + __retVal = mat2(m[0].xy, m[1].xy); +} + + + +mat2x3 __constructor(const mat2x3 m) +{ + __retVal = m; +} + +mat2x3 __constructor(const mat3 m) +{ + __retVal = mat2x3(m[0], m[1]); +} + +mat2x3 __constructor(const mat4x3 m) +{ + __retVal = mat2x3(m[0], m[1]); +} + +mat2x3 __constructor(const mat2x4 m) +{ + __retVal = mat2x3(m[0].xyz, m[1].xyz); +} + +mat2x3 __constructor(const mat3x4 m) +{ + __retVal = mat2x3(m[0].xyz, m[1].xyz); +} + +mat2x3 __constructor(const mat4 m) +{ + __retVal = mat2x3(m[0].xyz, m[1].xyz); +} + +mat2x3 __constructor(const mat2 m) +{ + __retVal = mat2x3(m[0].x, m[0].y, 0.0, + m[1].x, m[1].y, 0.0); +} + +mat2x3 __constructor(const mat3x2 m) +{ + __retVal = mat2x3(m[0].x, m[0].y, 0.0, + m[1].x, m[1].y, 0.0); +} + +mat2x3 __constructor(const mat4x2 m) +{ + __retVal = mat2x3(m[0].x, m[0].y, 0.0, + m[1].x, m[1].y, 0.0); +} + + + +mat2x4 __constructor(const mat2x4 m) +{ + __retVal = m; +} + +mat2x4 __constructor(const mat3x4 m) +{ + __retVal = mat2x4(m[0], m[1]); +} + +mat2x4 __constructor(const mat4 m) +{ + __retVal = mat2x4(m[0], m[1]); +} + +mat2x4 __constructor(const mat2x3 m) +{ + __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0, + m[1].x, m[1].y, m[1].z, 0.0); +} + +mat2x4 __constructor(const mat3 m) +{ + __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0, + m[1].x, m[1].y, m[1].z, 0.0); +} + +mat2x4 __constructor(const mat4x3 m) +{ + __retVal = mat2x4(m[0].x, m[0].y, m[0].z, 0.0, + m[1].x, m[1].y, m[1].z, 0.0); +} + +mat2x4 __constructor(const mat2 m) +{ + __retVal = mat2x4(m[0].x, m[1].y, 0.0, 0.0, + m[1].x, m[1].y, 0.0, 0.0); +} + +mat2x4 __constructor(const mat3x2 m) +{ + __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0, + m[1].x, m[1].y, 0.0, 0.0); +} + +mat2x4 __constructor(const mat4x2 m) +{ + __retVal = mat2x4(m[0].x, m[0].y, 0.0, 0.0, + m[1].x, m[1].y, 0.0, 0.0); +} + + + +mat3x2 __constructor(const mat3x2 m) +{ + __retVal = m; +} + +mat3x2 __constructor(const mat4x2 m) +{ + __retVal = mat3x2(m[0], m[1], m[2]); +} + +mat3x2 __constructor(const mat3 m) +{ + __retVal = mat3x2(m[0], m[1], m[2]); +} + +mat3x2 __constructor(const mat3x4 m) +{ + __retVal = mat3x2(m[0].x, m[0].y, + m[1].x, m[1].y, + m[2].x, m[2].y); +} + +mat3x2 __constructor(const mat4x3 m) +{ + __retVal = mat3x2(m[0].x, m[0].y, + m[1].x, m[1].y, + m[2].x, m[2].y); +} + +mat3x2 __constructor(const mat4 m) +{ + __retVal = mat3x2(m[0].x, m[0].y, + m[1].x, m[1].y, + 0.0, 0.0); +} + +mat3x2 __constructor(const mat2 m) +{ + __retVal = mat3x2(m[0], m[1], vec2(0.0)); +} + +mat3x2 __constructor(const mat2x3 m) +{ + __retVal = mat3x2(m[0].x, m[0].y, + m[1].x, m[1].y, + 0.0, 0.0); +} + +mat3x2 __constructor(const mat2x4 m) +{ + __retVal = mat3x2(m[0].x, m[0].y, + m[1].x, m[1].y, + 0.0, 0.0); +} + + + + +mat3 __constructor(const mat3 m) +{ + __retVal = m; +} + +mat3 __constructor(const mat4x3 m) +{ + __retVal = mat3 ( + m[0], + m[1], + m[2] + ); +} + +mat3 __constructor(const mat3x4 m) +{ + __retVal = mat3 ( + m[0].xyz, + m[1].xyz, + m[2].xyz + ); +} + +mat3 __constructor(const mat4 m) +{ + __retVal = mat3 ( + m[0].xyz, + m[1].xyz, + m[2].xyz + ); +} + +mat3 __constructor(const mat2x3 m) +{ + __retVal = mat3 ( + m[0], + m[1], + 0., 0., 1. + ); +} + +mat3 __constructor(const mat2x4 m) +{ + __retVal = mat3 ( + m[0].xyz, + m[1].xyz, + 0., 0., 1. + ); +} + +mat3 __constructor(const mat3x2 m) +{ + __retVal = mat3 ( + m[0], 0., + m[1], 0., + m[2], 1. + ); +} + +mat3 __constructor(const mat4x2 m) +{ + __retVal = mat3 ( + m[0], 0., + m[1], 0., + m[2], 1. + ); +} + +mat3 __constructor(const mat2 m) +{ + __retVal = mat3 ( + m[0], 0., + m[1], 0., + 0., 0., 1. + ); +} + + +mat3x4 __constructor(const mat3x4 m) +{ + __retVal = m; +} + +mat3x4 __constructor(const mat4 m) +{ + __retVal = mat3x4 ( + m[0], + m[1], + m[2] + ); +} + +mat3x4 __constructor(const mat3 m) +{ + __retVal = mat3x4 ( + m[0], 0., + m[1], 0., + m[2], 0. + ); +} + +mat3x4 __constructor(const mat4x3 m) +{ + __retVal = mat3x4 ( + m[0], 0., + m[1], 0., + m[2], 0. + ); +} + +mat3x4 __constructor(const mat2x4 m) +{ + __retVal = mat3x4 ( + m[0], + m[1], + 0., 0., 1., 0. + ); +} + +mat3x4 __constructor(const mat2x3 m) +{ + __retVal = mat3x4 ( + m[0], 0., + m[1], 0., + 0., 0., 1., 0. + ); +} + +mat3x4 __constructor(const mat3x2 m) +{ + __retVal = mat3x4 ( + m[0], 0., 0., + m[1], 0., 0., + m[2], 1., 0. + ); +} + +mat3x4 __constructor(const mat4x2 m) +{ + __retVal = mat3x4 ( + m[0], 0., 0., + m[1], 0., 0., + m[2], 1., 0. + ); +} + +mat3x4 __constructor(const mat2 m) +{ + __retVal = mat3x4 ( + m[0], 0., 0., + m[1], 0., 0., + 0., 0., 1., 0. + ); +} + + +mat4x2 __constructor(const mat4x2 m) +{ + __retVal = m; +} + +mat4x2 __constructor(const mat4x3 m) +{ + __retVal = mat4x2 ( + m[0].xy, + m[1].xy, + m[2].xy, + m[3].xy + ); +} + +mat4x2 __constructor(const mat4 m) +{ + __retVal = mat4x2 ( + m[0].xy, + m[1].xy, + m[2].xy, + m[3].xy + ); +} + +mat4x2 __constructor(const mat3x2 m) +{ + __retVal = mat4x2 ( + m[0], + m[1], + 0., 0. + ); +} + +mat4x2 __constructor(const mat3 m) +{ + __retVal = mat4x2 ( + m[0].xy, + m[1].xy, + m[2].xy, + 0., 0. + ); +} + +mat4x2 __constructor(const mat3x4 m) +{ + __retVal = mat4x2 ( + m[0].xy, + m[1].xy, + m[2].xy, + 0., 0. + ); +} + +mat4x2 __constructor(const mat2 m) +{ + __retVal = mat4x2 ( + m[0], + m[1], + 0., 0., + 0., 0. + ); +} + +mat4x2 __constructor(const mat2x3 m) +{ + __retVal = mat4x2 ( + m[0].xy, + m[1].xy, + 0., 0., + 0., 0. + ); +} + +mat4x2 __constructor(const mat2x4 m) +{ + __retVal = mat4x2 ( + m[0].xy, + m[1].xy, + 0., 0., + 0., 0. + ); +} + + +mat4x3 __constructor(const mat4x3 m) +{ + __retVal = m; +} + +mat4x3 __constructor(const mat4 m) +{ + __retVal = mat4x3 ( + m[0].xyz, + m[1].xyz, + m[2].xyz, + m[3].xyz + ); +} + +mat4x3 __constructor(const mat3 m) +{ + __retVal = mat4x3 ( + m[0], + m[1], + m[2], + 0., 0., 0. + ); +} + +mat4x3 __constructor(const mat3x4 m) +{ + __retVal = mat4x3 ( + m[0].xyz, + m[1].xyz, + m[2].xyz, + 0., 0., 0. + ); +} + +mat4x3 __constructor(const mat4x2 m) +{ + __retVal = mat4x3 ( + m[0], 0., + m[1], 0., + m[2], 1., + m[3], 0. + ); +} + +mat4x3 __constructor(const mat2x3 m) +{ + __retVal = mat4x3 ( + m[0], + m[1], + 0., 0., 1., + 0., 0., 0. + ); +} + +mat4x3 __constructor(const mat3x2 m) +{ + __retVal = mat4x3 ( + m[0], 0., + m[1], 0., + m[2], 1., + 0., 0., 0. + ); +} + +mat4x3 __constructor(const mat2x4 m) +{ + __retVal = mat4x3 ( + m[0].xyz, + m[1].xyz, + 0., 0., 1., + 0., 0., 0. + ); +} + +mat4x3 __constructor(const mat2 m) +{ + __retVal = mat4x3 ( + m[0], 0., + m[1], 0., + 0., 0., 1., + 0., 0., 0. + ); +} + + +mat4 __constructor(const mat4 m) +{ + __retVal = m; +} + +mat4 __constructor(const mat3x4 m) +{ + __retVal = mat4 ( + m[0], + m[1], + m[2], + 0., 0., 0., 1. + ); +} + +mat4 __constructor(const mat4x3 m) +{ + __retVal = mat4 ( + m[0], 0., + m[1], 0., + m[2], 0., + m[3], 1. + ); +} + +mat4 __constructor(const mat2x4 m) +{ + __retVal = mat4 ( + m[0], + m[1], + 0., 0., 1., 0., + 0., 0., 0., 1. + ); +} + +mat4 __constructor(const mat4x2 m) +{ + __retVal = mat4 ( + m[0], 0., 0., + m[1], 0., 0., + m[2], 1., 0., + m[3], 0., 1. + ); +} + +mat4 __constructor(const mat3 m) +{ + __retVal = mat4 ( + m[0], 0., + m[1], 0., + m[2], 0., + 0., 0., 0., 1. + ); +} + +mat4 __constructor(const mat2x3 m) +{ + __retVal = mat4 ( + m[0], 0., + m[1], 0., + 0., 0., 1., 0., + 0., 0., 0., 1. + ); +} + +mat4 __constructor(const mat3x2 m) +{ + __retVal = mat4 ( + m[0], 0., 0., + m[1], 0., 0., + m[2], 1., 0., + 0., 0., 0., 1. + ); +} + +mat4 __constructor(const mat2 m) +{ + __retVal = mat4 ( + m[0], 0., 0., + m[1], 0., 0., + 0., 0., 1., 0., + 0., 0., 0., 1. + ); +} + + +void __operator += (inout mat2x3 m, const mat2x3 n) { + m[0] += n[0]; + m[1] += n[1]; +} + +void __operator += (inout mat2x4 m, const mat2x4 n) { + m[0] += n[0]; + m[1] += n[1]; +} + +void __operator += (inout mat3x2 m, const mat3x2 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; +} + +void __operator += (inout mat3x4 m, const mat3x4 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; +} + +void __operator += (inout mat4x2 m, const mat4x2 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; + m[3] += n[3]; +} + +void __operator += (inout mat4x3 m, const mat4x3 n) { + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; + m[3] += n[3]; +} + + +void __operator -= (inout mat2x3 m, const mat2x3 n) { + m[0] -= n[0]; + m[1] -= n[1]; +} + +void __operator -= (inout mat2x4 m, const mat2x4 n) { + m[0] -= n[0]; + m[1] -= n[1]; +} + +void __operator -= (inout mat3x2 m, const mat3x2 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; +} + +void __operator -= (inout mat3x4 m, const mat3x4 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; +} + +void __operator -= (inout mat4x2 m, const mat4x2 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; + m[3] -= n[3]; +} + +void __operator -= (inout mat4x3 m, const mat4x3 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; + m[3] -= n[3]; +} + + +void __operator /= (inout mat2x3 m, const mat2x3 n) { + m[0] /= n[0]; + m[1] /= n[1]; +} + +void __operator /= (inout mat2x4 m, const mat2x4 n) { + m[0] /= n[0]; + m[1] /= n[1]; +} + +void __operator /= (inout mat3x2 m, const mat3x2 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; +} + +void __operator /= (inout mat3x4 m, const mat3x4 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; +} + +void __operator /= (inout mat4x2 m, const mat4x2 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; + m[3] /= n[3]; +} + +void __operator /= (inout mat4x3 m, const mat4x3 n) { + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; + m[3] /= n[3]; +} + + +vec3 __operator * (const mat2x3 m, const vec2 v) +{ + __retVal.x = v.x * m[0].x + v.y * m[1].x; + __retVal.y = v.x * m[0].y + v.y * m[1].y; + __retVal.z = v.x * m[0].z + v.y * m[1].z; +} + +vec4 __operator * (const mat2x4 m, const vec2 v) +{ + __retVal.x = v.x * m[0].x + v.y * m[1].x; + __retVal.y = v.x * m[0].y + v.y * m[1].y; + __retVal.z = v.x * m[0].z + v.y * m[1].z; + __retVal.w = v.x * m[0].w + v.y * m[1].w; +} + +vec2 __operator * (const mat3x2 m, const vec3 v) +{ + __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x; + __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y; +} + +vec4 __operator * (const mat3x4 m, const vec3 v) +{ + __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x; + __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y; + __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z; + __retVal.w = v.x * m[0].w + v.y * m[1].w + v.z * m[2].w; +} + +vec2 __operator * (const mat4x2 m, const vec4 v) +{ + __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x; + __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y; +} + +vec3 __operator * (const mat4x3 m, const vec4 v) +{ + __retVal.x = v.x * m[0].x + v.y * m[1].x + v.z * m[2].x + v.w * m[3].x; + __retVal.y = v.x * m[0].y + v.y * m[1].y + v.z * m[2].y + v.w * m[3].y; + __retVal.z = v.x * m[0].z + v.y * m[1].z + v.z * m[2].z + v.w * m[3].z; +} + + +mat3x2 __operator * (const mat2 m, const mat3x2 n) +{ + //return mat3x2 (m * n[0], m * n[1], m * n[2]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; +} + +mat4x2 __operator * (const mat2 m, const mat4x2 n) +{ + //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; + __retVal[3] = m * n[3]; +} + + +mat2x3 __operator * (const mat2x3 m, const mat2 n) +{ + //return mat2x3 (m * n[0], m * n[1]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; +} + +mat3 __operator * (const mat2x3 m, const mat3x2 n) +{ + //return mat3 (m * n[0], m * n[1], m * n[2]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; +} + +mat4x3 __operator * (const mat2x3 m, const mat4x2 n) +{ + //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; + __retVal[3] = m * n[3]; +} + + +mat2x4 __operator * (const mat2x4 m, const mat2 n) +{ + //return mat2x4 (m * n[0], m * n[1]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; +} + +mat3x4 __operator * (const mat2x4 m, const mat3x2 n) +{ + //return mat3x4 (m * n[0], m * n[1], m * n[2]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; +} + +mat4 __operator * (const mat2x4 m, const mat4x2 n) +{ + //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; + __retVal[3] = m * n[3]; +} + + +mat2 __operator * (const mat3x2 m, const mat2x3 n) +{ + //return mat2 (m * n[0], m * n[1]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; +} + +mat3x2 __operator * (const mat3x2 m, const mat3 n) +{ + //return mat3x2 (m * n[0], m * n[1], m * n[2]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; +} + +mat4x2 __operator * (const mat3x2 m, const mat4x3 n) +{ + //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; + __retVal[3] = m * n[3]; +} + + +mat2x3 __operator * (const mat3 m, const mat2x3 n) +{ + //return mat2x3 (m * n[0], m * n[1]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; +} + +mat4x3 __operator * (const mat3 m, const mat4x3 n) +{ + //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; + __retVal[3] = m * n[3]; +} + + +mat2x4 __operator * (const mat3x4 m, const mat2x3 n) +{ + //return mat2x4 (m * n[0], m * n[1]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; +} + +mat3x4 __operator * (const mat3x4 m, const mat3 n) +{ + //return mat3x4 (m * n[0], m * n[1], m * n[2]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; +} + +mat4 __operator * (const mat3x4 m, const mat4x3 n) +{ + //return mat4 (m * n[0], m * n[1], m * n[2], m * n[3]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; + __retVal[3] = m * n[3]; +} + + +mat2 __operator * (const mat4x2 m, const mat2x4 n) +{ + //return = mat2 (m * n[0], m * n[1]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; +} + +mat3x2 __operator * (const mat4x2 m, const mat3x4 n) +{ + //return mat3x2 (m * n[0], m * n[1], m * n[2]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; +} + +mat4x2 __operator * (const mat4x2 m, const mat4 n) +{ + //return mat4x2 (m * n[0], m * n[1], m * n[2], m * n[3]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; + __retVal[3] = m * n[3]; +} + + +mat2x3 __operator * (const mat4x3 m, const mat2x4 n) +{ + //return mat2x3 (m * n[0], m * n[1]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; +} + +mat3 __operator * (const mat4x3 m, const mat3x4 n) +{ + //return mat3 (m * n[0], m * n[1], m * n[2]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; +} + +mat4x3 __operator * (const mat4x3 m, const mat4 n) +{ + //return mat4x3 (m * n[0], m * n[1], m * n[2], m * n[3]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; + __retVal[3] = m * n[3]; +} + + +mat2x4 __operator * (const mat4 m, const mat2x4 n) +{ + //return mat2x4 (m * n[0], m * n[1]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; +} + +mat3x4 __operator * (const mat4 m, const mat3x4 n) +{ + //return mat3x4 (m * n[0], m * n[1], m * n[2]); + __retVal[0] = m * n[0]; + __retVal[1] = m * n[1]; + __retVal[2] = m * n[2]; +} + + +void __operator *= (inout mat2x3 m, const mat2 n) { + m = m * n; +} + +void __operator *= (inout mat2x4 m, const mat2 n) { + m = m * n; +} + +void __operator *= (inout mat3x2 m, const mat3 n) { + m = m * n; +} + +void __operator *= (inout mat3x4 m, const mat3 n) { + m = m * n; +} + +void __operator *= (inout mat4x2 m, const mat4 n) { + m = m * n; +} + +void __operator *= (inout mat4x3 m, const mat4 n) { + m = m * n; +} + + +vec3 __operator * (const vec2 v, const mat3x2 m) +{ + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); + __retVal.z = dot(v, m[2]); +} + +vec4 __operator * (const vec2 v, const mat4x2 m) +{ + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); + __retVal.z = dot(v, m[2]); + __retVal.w = dot(v, m[3]); +} + +vec2 __operator * (const vec3 v, const mat2x3 m) +{ + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); +} + +vec4 __operator * (const vec3 v, const mat4x3 m) +{ + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); + __retVal.z = dot(v, m[2]); + __retVal.w = dot(v, m[3]); +} + +vec2 __operator * (const vec4 v, const mat2x4 m) +{ + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); +} + +vec3 __operator * (const vec4 v, const mat3x4 m) +{ + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); + __retVal.z = dot(v, m[2]); +} + + +void __operator += (inout mat2x3 m, const float a) { + m[0] += a; + m[1] += a; +} + +void __operator += (inout mat2x4 m, const float a) { + m[0] += a; + m[1] += a; +} + +void __operator += (inout mat3x2 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; +} + +void __operator += (inout mat3x4 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; +} + +void __operator += (inout mat4x2 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; + m[3] += a; +} + +void __operator += (inout mat4x3 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; + m[3] += a; +} + + +void __operator -= (inout mat2x3 m, const float a) { + m[0] -= a; + m[1] -= a; +} + +void __operator -= (inout mat2x4 m, const float a) { + m[0] -= a; + m[1] -= a; +} + +void __operator -= (inout mat3x2 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; +} + +void __operator -= (inout mat3x4 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; +} + +void __operator -= (inout mat4x2 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; + m[3] -= a; +} + +void __operator -= (inout mat4x3 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; + m[3] -= a; +} + + +void __operator *= (inout mat2x3 m, const float a) { + m[0] *= a; + m[1] *= a; +} + +void __operator *= (inout mat2x4 m, const float a) { + m[0] *= a; + m[1] *= a; +} + +void __operator *= (inout mat3x2 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; +} + +void __operator *= (inout mat3x4 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; +} + +void __operator *= (inout mat4x2 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; + m[3] *= a; +} + +void __operator *= (inout mat4x3 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; + m[3] *= a; +} + + +void __operator /= (inout mat2x3 m, const float a) { + m[0] /= a; + m[1] /= a; +} + +void __operator /= (inout mat2x4 m, const float a) { + m[0] /= a; + m[1] /= a; +} + +void __operator /= (inout mat3x2 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; +} + +void __operator /= (inout mat3x4 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; +} + +void __operator /= (inout mat4x2 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; + m[3] /= a; +} + +void __operator /= (inout mat4x3 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; + m[3] /= a; +} + + +mat2x3 __operator + (const mat2x3 m, const mat2x3 n) { + return mat2x3 (m[0] + n[0], m[1] + n[1]); +} + +mat2x4 __operator + (const mat2x4 m, const mat2x4 n) { + return mat2x4 (m[0] + n[0], m[1] + n[1]); +} + +mat3x2 __operator + (const mat3x2 m, const mat3x2 n) { + return mat3x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2]); +} + +mat3x4 __operator + (const mat3x4 m, const mat3x4 n) { + return mat3x4 (m[0] + n[0], m[1] + n[1], m[2] + n[2]); +} + +mat4x2 __operator + (const mat4x2 m, const mat4x2 n) { + return mat4x2 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]); +} + +mat4x3 __operator + (const mat4x3 m, const mat4x3 n) { + return mat4x3 (m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3]); +} + + +mat2x3 __operator - (const mat2x3 m, const mat2x3 n) { + return mat2x3 (m[0] - n[0], m[1] - n[1]); +} + +mat2x4 __operator - (const mat2x4 m, const mat2x4 n) { + return mat2x4 (m[0] - n[0], m[1] - n[1]); +} + +mat3x2 __operator - (const mat3x2 m, const mat3x2 n) { + return mat3x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2]); +} + +mat3x4 __operator - (const mat3x4 m, const mat3x4 n) { + return mat3x4 (m[0] - n[0], m[1] - n[1], m[2] - n[2]); +} + +mat4x2 __operator - (const mat4x2 m, const mat4x2 n) { + return mat4x2 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]); +} + +mat4x3 __operator - (const mat4x3 m, const mat4x3 n) { + return mat4x3 (m[0] - n[0], m[1] - n[1], m[2] - n[2], m[3] - n[3]); +} + + +mat2x3 __operator / (const mat2x3 m, const mat2x3 n) { + return mat2x3 (m[0] / n[0], m[1] / n[1]); +} + +mat2x4 __operator / (const mat2x4 m, const mat2x4 n) { + return mat2x4 (m[0] / n[0], m[1] / n[1]); +} + +mat3x2 __operator / (const mat3x2 m, const mat3x2 n) { + return mat3x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2]); +} + +mat3x4 __operator / (const mat3x4 m, const mat3x4 n) { + return mat3x4 (m[0] / n[0], m[1] / n[1], m[2] / n[2]); +} + +mat4x2 __operator / (const mat4x2 m, const mat4x2 n) { + return mat4x2 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]); +} + +mat4x3 __operator / (const mat4x3 m, const mat4x3 n) { + return mat4x3 (m[0] / n[0], m[1] / n[1], m[2] / n[2], m[3] / n[3]); +} + + +mat2x3 __operator + (const float a, const mat2x3 n) { + return mat2x3 (a + n[0], a + n[1]); +} + +mat2x3 __operator + (const mat2x3 m, const float b) { + return mat2x3 (m[0] + b, m[1] + b); +} + +mat2x4 __operator + (const float a, const mat2x4 n) { + return mat2x4 (a + n[0], a + n[1]); +} + +mat2x4 __operator + (const mat2x4 m, const float b) { + return mat2x4 (m[0] + b, m[1] + b); +} + +mat3x2 __operator + (const float a, const mat3x2 n) { + return mat3x2 (a + n[0], a + n[1], a + n[2]); +} + +mat3x2 __operator + (const mat3x2 m, const float b) { + return mat3x2 (m[0] + b, m[1] + b, m[2] + b); +} + +mat3x4 __operator + (const float a, const mat3x4 n) { + return mat3x4 (a + n[0], a + n[1], a + n[2]); +} + +mat3x4 __operator + (const mat3x4 m, const float b) { + return mat3x4 (m[0] + b, m[1] + b, m[2] + b); +} + +mat4x2 __operator + (const mat4x2 m, const float b) { + return mat4x2 (m[0] + b, m[1] + b, m[2] + b, m[3] + b); +} + +mat4x2 __operator + (const float a, const mat4x2 n) { + return mat4x2 (a + n[0], a + n[1], a + n[2], a + n[3]); +} + +mat4x3 __operator + (const mat4x3 m, const float b) { + return mat4x3 (m[0] + b, m[1] + b, m[2] + b, m[3] + b); +} + +mat4x3 __operator + (const float a, const mat4x3 n) { + return mat4x3 (a + n[0], a + n[1], a + n[2], a + n[3]); +} + + +mat2x3 __operator - (const float a, const mat2x3 n) { + return mat2x3 (a - n[0], a - n[1]); +} + +mat2x3 __operator - (const mat2x3 m, const float b) { + return mat2x3 (m[0] - b, m[1] - b); +} + +mat2x4 __operator - (const float a, const mat2x4 n) { + return mat2x4 (a - n[0], a - n[1]); +} + +mat2x4 __operator - (const mat2x4 m, const float b) { + return mat2x4 (m[0] - b, m[1] - b); +} + +mat3x2 __operator - (const float a, const mat3x2 n) { + return mat3x2 (a - n[0], a - n[1], a - n[2]); +} + +mat3x2 __operator - (const mat3x2 m, const float b) { + return mat3x2 (m[0] - b, m[1] - b, m[2] - b); +} + +mat3x4 __operator - (const float a, const mat3x4 n) { + return mat3x4 (a - n[0], a - n[1], a - n[2]); +} + +mat3x4 __operator - (const mat3x4 m, const float b) { + return mat3x4 (m[0] - b, m[1] - b, m[2] - b); +} + +mat4x2 __operator - (const mat4x2 m, const float b) { + return mat4x2 (m[0] - b, m[1] - b, m[2] - b, m[3] - b); +} + +mat4x2 __operator - (const float a, const mat4x2 n) { + return mat4x2 (a - n[0], a - n[1], a - n[2], a - n[3]); +} + +mat4x3 __operator - (const mat4x3 m, const float b) { + return mat4x3 (m[0] - b, m[1] - b, m[2] - b, m[3] - b); +} + +mat4x3 __operator - (const float a, const mat4x3 n) { + return mat4x3 (a - n[0], a - n[1], a - n[2], a - n[3]); +} + + +mat2x3 __operator * (const float a, const mat2x3 n) +{ + //return mat2x3 (a * n[0], a * n[1]); + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; +} + +mat2x3 __operator * (const mat2x3 m, const float b) +{ + //return mat2x3 (m[0] * b, m[1] * b); + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; +} + +mat2x4 __operator * (const float a, const mat2x4 n) +{ + //return mat2x4 (a * n[0], a * n[1]); + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; +} + +mat2x4 __operator * (const mat2x4 m, const float b) +{ + //return mat2x4 (m[0] * b, m[1] * b); + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; +} + +mat3x2 __operator * (const float a, const mat3x2 n) +{ + //return mat3x2 (a * n[0], a * n[1], a * n[2]); + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; + __retVal[2] = a * n[2]; +} + +mat3x2 __operator * (const mat3x2 m, const float b) +{ + //return mat3x2 (m[0] * b, m[1] * b, m[2] * b); + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; + __retVal[2] = m[2] * b; +} + +mat3x4 __operator * (const float a, const mat3x4 n) +{ + //return mat3x4 (a * n[0], a * n[1], a * n[2]); + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; + __retVal[2] = a * n[2]; +} + +mat3x4 __operator * (const mat3x4 m, const float b) +{ + //return mat3x4 (m[0] * b, m[1] * b, m[2] * b); + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; + __retVal[2] = m[2] * b; +} + +mat4x2 __operator * (const mat4x2 m, const float b) +{ + //return mat4x2 (m[0] * b, m[1] * b, m[2] * b, m[3] * b); + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; + __retVal[2] = m[2] * b; + __retVal[3] = m[3] * b; +} + +mat4x2 __operator * (const float a, const mat4x2 n) +{ + //return mat4x2 (a * n[0], a * n[1], a * n[2], a * n[3]); + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; + __retVal[2] = a * n[2]; + __retVal[3] = a * n[3]; +} + +mat4x3 __operator * (const mat4x3 m, const float b) +{ + //return mat4x3 (m[0] * b, m[1] * b, m[2] * b, m[3] * b); + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; + __retVal[2] = m[2] * b; + __retVal[3] = m[3] * b; +} + +mat4x3 __operator * (const float a, const mat4x3 n) +{ + //return mat4x3 (a * n[0], a * n[1], a * n[2], a * n[3]); + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; + __retVal[2] = a * n[2]; + __retVal[3] = a * n[3]; +} + + +mat2x3 __operator / (const float a, const mat2x3 n) +{ + //return mat2x3 (a / n[0], a / n[1]); + const float inv = 1.0 / a; + __retVal[0] = inv * n[0]; + __retVal[1] = inv * n[1]; +} + +mat2x3 __operator / (const mat2x3 m, const float b) +{ + //return mat2x3 (m[0] / b, m[1] / b); + const float inv = 1.0 / b; + __retVal[0] = m[0] * inv; + __retVal[1] = m[1] * inv; +} + +mat2x4 __operator / (const float a, const mat2x4 n) +{ + //return mat2x4 (a / n[0], a / n[1]); + const float inv = 1.0 / a; + __retVal[0] = inv * n[0]; + __retVal[1] = inv * n[1]; +} + +mat2x4 __operator / (const mat2x4 m, const float b) +{ + //return mat2x4 (m[0] / b, m[1] / b); + const float inv = 1.0 / b; + __retVal[0] = m[0] * inv; + __retVal[1] = m[1] * inv; +} + +mat3x2 __operator / (const float a, const mat3x2 n) +{ + //return mat3x2 (a / n[0], a / n[1], a / n[2]); + const float inv = 1.0 / a; + __retVal[0] = inv * n[0]; + __retVal[1] = inv * n[1]; + __retVal[2] = inv * n[2]; +} + +mat3x2 __operator / (const mat3x2 m, const float b) +{ + //return mat3x2 (m[0] / b, m[1] / b, m[2] / b); + const float inv = 1.0 / b; + __retVal[0] = m[0] * inv; + __retVal[1] = m[1] * inv; + __retVal[2] = m[2] * inv; +} + +mat3x4 __operator / (const float a, const mat3x4 n) +{ + //return mat3x4 (a / n[0], a / n[1], a / n[2]); + const float inv = 1.0 / a; + __retVal[0] = inv * n[0]; + __retVal[1] = inv * n[1]; + __retVal[2] = inv * n[2]; +} + +mat3x4 __operator / (const mat3x4 m, const float b) +{ + //return mat3x4 (m[0] / b, m[1] / b, m[2] / b); + const float inv = 1.0 / b; + __retVal[0] = m[0] * inv; + __retVal[1] = m[1] * inv; + __retVal[2] = m[2] * inv; +} + +mat4x2 __operator / (const mat4x2 m, const float b) +{ + //return mat4x2 (m[0] / b, m[1] / b, m[2] / b, m[3] / b); + const float inv = 1.0 / b; + __retVal[0] = m[0] * inv; + __retVal[1] = m[1] * inv; + __retVal[2] = m[2] * inv; + __retVal[3] = m[3] * inv; +} + +mat4x2 __operator / (const float a, const mat4x2 n) +{ + //return mat4x2 (a / n[0], a / n[1], a / n[2], a / n[3]); + const float inv = 1.0 / a; + __retVal[0] = inv * n[0]; + __retVal[1] = inv * n[1]; + __retVal[2] = inv * n[2]; + __retVal[3] = inv * n[3]; +} + +mat4x3 __operator / (const mat4x3 m, const float b) +{ + //return mat4x3 (m[0] / b, m[1] / b, m[2] / b, m[3] / b); + const float inv = 1.0 / b; + __retVal[0] = m[0] * inv; + __retVal[1] = m[1] * inv; + __retVal[2] = m[2] * inv; + __retVal[3] = m[3] * inv; +} + +mat4x3 __operator / (const float a, const mat4x3 n) +{ + //return mat4x3 (a / n[0], a / n[1], a / n[2], a / n[3]); + const float inv = 1.0 / a; + __retVal[0] = inv * n[0]; + __retVal[1] = inv * n[1]; + __retVal[2] = inv * n[2]; + __retVal[3] = inv * n[3]; +} + + +mat2x3 __operator - (const mat2x3 m) { + return mat2x3 (-m[0], -m[1]); +} + +mat2x4 __operator - (const mat2x4 m) { + return mat2x4 (-m[0], -m[1]); +} + +mat3x2 __operator - (const mat3x2 m) { + return mat3x2 (-m[0], -m[1], -m[2]); +} + +mat3x4 __operator - (const mat3x4 m) { + return mat3x4 (-m[0], -m[1], -m[2]); +} + +mat4x2 __operator - (const mat4x2 m) { + return mat4x2 (-m[0], -m[1], -m[2], -m[3]); +} + +mat4x3 __operator - (const mat4x3 m) { + return mat4x3 (-m[0], -m[1], -m[2], -m[3]); +} + + +void __operator -- (inout mat2x3 m) { + --m[0]; + --m[1]; +} + +void __operator -- (inout mat2x4 m) { + --m[0]; + --m[1]; +} + +void __operator -- (inout mat3x2 m) { + --m[0]; + --m[1]; + --m[2]; +} + +void __operator -- (inout mat3x4 m) { + --m[0]; + --m[1]; + --m[2]; +} + +void __operator -- (inout mat4x2 m) { + --m[0]; + --m[1]; + --m[2]; + --m[3]; +} + +void __operator -- (inout mat4x3 m) { + --m[0]; + --m[1]; + --m[2]; + --m[3]; +} + + +void __operator ++ (inout mat2x3 m) { + ++m[0]; + ++m[1]; +} + +void __operator ++ (inout mat2x4 m) { + ++m[0]; + ++m[1]; +} + +void __operator ++ (inout mat3x2 m) { + ++m[0]; + ++m[1]; + ++m[2]; +} + +void __operator ++ (inout mat3x4 m) { + ++m[0]; + ++m[1]; + ++m[2]; +} + +void __operator ++ (inout mat4x2 m) { + ++m[0]; + ++m[1]; + ++m[2]; + ++m[3]; +} + +void __operator ++ (inout mat4x3 m) { + ++m[0]; + ++m[1]; + ++m[2]; + ++m[3]; +} + + +mat2x3 __operator -- (inout mat2x3 m, const int) { + return mat2x3 (m[0]--, m[1]--); +} + +mat2x4 __operator -- (inout mat2x4 m, const int) { + return mat2x4 (m[0]--, m[1]--); +} + +mat3x2 __operator -- (inout mat3x2 m, const int) { + return mat3x2 (m[0]--, m[1]--, m[2]--); +} + +mat3x4 __operator -- (inout mat3x4 m, const int) { + return mat3x4 (m[0]--, m[1]--, m[2]--); +} + +mat4x2 __operator -- (inout mat4x2 m, const int) { + return mat4x2 (m[0]--, m[1]--, m[2]--, m[3]--); +} + +mat4x3 __operator -- (inout mat4x3 m, const int) { + return mat4x3 (m[0]--, m[1]--, m[2]--, m[3]--); +} + + +mat2x3 __operator ++ (inout mat2x3 m, const int) { + return mat2x3 (m[0]++, m[1]++); +} + +mat2x4 __operator ++ (inout mat2x4 m, const int) { + return mat2x4 (m[0]++, m[1]++); +} + +mat3x2 __operator ++ (inout mat3x2 m, const int) { + return mat3x2 (m[0]++, m[1]++, m[2]++); +} + +mat3x4 __operator ++ (inout mat3x4 m, const int) { + return mat3x4 (m[0]++, m[1]++, m[2]++); +} + +mat4x2 __operator ++ (inout mat4x2 m, const int) { + return mat4x2 (m[0]++, m[1]++, m[2]++, m[3]++); +} + +mat4x3 __operator ++ (inout mat4x3 m, const int) { + return mat4x3 (m[0]++, m[1]++, m[2]++, m[3]++); +} + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_120_core_gc.h b/dist/Mesa/src/mesa/shader/slang/library/slang_120_core_gc.h new file mode 100644 index 000000000..b7ef5ed6c --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_120_core_gc.h @@ -0,0 +1,730 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */ +/* slang_120_core.gc */ + +3,1,0,26,1,1,1,0,9,102,48,48,0,0,1,1,0,9,102,49,48,0,0,1,1,0,9,102,50,48,0,0,1,1,0,9,102,48,49,0,0, +1,1,0,9,102,49,49,0,0,1,1,0,9,102,50,49,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59, +120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,121,0,18,102,49,48,0, +20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,122,0,18,102,50,48,0,20,0,9,18,95,95,114, +101,116,86,97,108,0,16,10,49,0,57,59,120,0,18,102,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0, +16,10,49,0,57,59,121,0,18,102,49,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,122, +0,18,102,50,49,0,20,0,0,1,0,26,1,1,1,0,9,102,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97, +116,50,120,51,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0, +48,0,0,0,0,20,0,0,1,0,26,1,1,1,0,5,105,0,0,0,1,3,2,1,9,1,102,0,2,58,102,108,111,97,116,0,18,105,0, +0,0,0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,18,102,0,0,0,20,0,0,1,0,26,1, +1,1,0,1,98,0,0,0,1,3,2,1,9,1,102,0,2,58,102,108,111,97,116,0,18,98,0,0,0,0,0,9,18,95,95,114,101, +116,86,97,108,0,58,109,97,116,50,120,51,0,18,102,0,0,0,20,0,0,1,0,26,1,1,1,0,11,99,48,0,0,1,1,0,11, +99,49,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95,114,101, +116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,0,1,0,28,1,1,1,0,9,102,48,48,0,0,1,1,0,9,102,49,48,0, +0,1,1,0,9,102,50,48,0,0,1,1,0,9,102,51,48,0,0,1,1,0,9,102,48,49,0,0,1,1,0,9,102,49,49,0,0,1,1,0,9, +102,50,49,0,0,1,1,0,9,102,51,49,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,120,0, +18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,121,0,18,102,49,48,0,20,0,9, +18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,122,0,18,102,50,48,0,20,0,9,18,95,95,114,101,116, +86,97,108,0,16,8,48,0,57,59,119,0,18,102,51,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49, +0,57,59,120,0,18,102,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102, +49,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,122,0,18,102,50,49,0,20,0,9,18,95, +95,114,101,116,86,97,108,0,16,10,49,0,57,59,119,0,18,102,51,49,0,20,0,0,1,0,28,1,1,1,0,9,102,0,0,0, +1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0, +48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1, +0,28,1,1,1,0,5,105,0,0,0,1,3,2,1,9,1,102,0,2,58,102,108,111,97,116,0,18,105,0,0,0,0,0,9,18,95,95, +114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,18,102,0,0,0,20,0,0,1,0,28,1,1,1,0,1,98,0,0,0,1, +3,2,1,9,1,102,0,2,58,102,108,111,97,116,0,18,98,0,0,0,0,0,9,18,95,95,114,101,116,86,97,108,0,58, +109,97,116,50,120,52,0,18,102,0,0,0,20,0,0,1,0,28,1,1,1,0,12,99,48,0,0,1,1,0,12,99,49,0,0,0,1,9,18, +95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16, +10,49,0,57,18,99,49,0,20,0,0,1,0,27,1,1,1,0,9,102,48,48,0,0,1,1,0,9,102,49,48,0,0,1,1,0,9,102,48, +49,0,0,1,1,0,9,102,49,49,0,0,1,1,0,9,102,48,50,0,0,1,1,0,9,102,49,50,0,0,0,1,9,18,95,95,114,101, +116,86,97,108,0,16,8,48,0,57,59,120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,59,121,0,18,102,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,120,0,18, +102,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102,49,49,0,20,0,9, +18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,120,0,18,102,48,50,0,20,0,9,18,95,95,114,101,116, +86,97,108,0,16,10,50,0,57,59,121,0,18,102,49,50,0,20,0,0,1,0,27,1,1,1,0,9,102,0,0,0,1,9,18,95,95, +114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18, +102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,27,1,1,1,0,5,105,0,0,0,1,3,2,1,9,1,102,0,2, +58,102,108,111,97,116,0,18,105,0,0,0,0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120, +50,0,18,102,0,0,0,20,0,0,1,0,27,1,1,1,0,1,98,0,0,0,1,3,2,1,9,1,102,0,2,58,102,108,111,97,116,0,18, +98,0,0,0,0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,18,102,0,0,0,20,0,0,1,0, +27,1,1,1,0,10,99,48,0,0,1,1,0,10,99,49,0,0,1,1,0,10,99,50,0,0,0,1,9,18,95,95,114,101,116,86,97,108, +0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,9, +18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,99,50,0,20,0,0,1,0,30,1,1,1,0,9,102,48,48,0,0,1, +1,0,9,102,49,48,0,0,1,1,0,9,102,50,48,0,0,1,1,0,9,102,51,48,0,0,1,1,0,9,102,48,49,0,0,1,1,0,9,102, +49,49,0,0,1,1,0,9,102,50,49,0,0,1,1,0,9,102,51,49,0,0,1,1,0,9,102,48,50,0,0,1,1,0,9,102,49,50,0,0, +1,1,0,9,102,50,50,0,0,1,1,0,9,102,51,50,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59, +120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,121,0,18,102,49,48,0, +20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,122,0,18,102,50,48,0,20,0,9,18,95,95,114, +101,116,86,97,108,0,16,8,48,0,57,59,119,0,18,102,51,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0, +16,10,49,0,57,59,120,0,18,102,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121, +0,18,102,49,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,122,0,18,102,50,49,0,20, +0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,119,0,18,102,51,49,0,20,0,9,18,95,95,114,101, +116,86,97,108,0,16,10,50,0,57,59,120,0,18,102,48,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16, +10,50,0,57,59,121,0,18,102,49,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,122,0, +18,102,50,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,119,0,18,102,51,50,0,20,0, +0,1,0,30,1,1,1,0,9,102,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,18,102, +0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0, +0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,30,1, +1,1,0,5,105,0,0,0,1,3,2,1,9,1,102,0,2,58,102,108,111,97,116,0,18,105,0,0,0,0,0,9,18,95,95,114,101, +116,86,97,108,0,58,109,97,116,51,120,52,0,18,102,0,0,0,20,0,0,1,0,30,1,1,1,0,1,98,0,0,0,1,3,2,1,9, +1,102,0,2,58,102,108,111,97,116,0,18,98,0,0,0,0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116, +51,120,52,0,18,102,0,0,0,20,0,0,1,0,30,1,1,1,0,12,99,48,0,0,1,1,0,12,99,49,0,0,1,1,0,12,99,50,0,0, +0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95,114,101,116,86,97, +108,0,16,10,49,0,57,18,99,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,99,50,0,20, +0,0,1,0,29,1,1,1,0,9,102,48,48,0,0,1,1,0,9,102,49,48,0,0,1,1,0,9,102,48,49,0,0,1,1,0,9,102,49,49,0, +0,1,1,0,9,102,48,50,0,0,1,1,0,9,102,49,50,0,0,1,1,0,9,102,48,51,0,0,1,1,0,9,102,49,51,0,0,0,1,9,18, +95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,120,0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86, +97,108,0,16,8,48,0,57,59,121,0,18,102,49,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0, +57,59,120,0,18,102,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,121,0,18,102, +49,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,120,0,18,102,48,50,0,20,0,9,18,95, +95,114,101,116,86,97,108,0,16,10,50,0,57,59,121,0,18,102,49,50,0,20,0,9,18,95,95,114,101,116,86,97, +108,0,16,10,51,0,57,59,120,0,18,102,48,51,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57, +59,121,0,18,102,49,51,0,20,0,0,1,0,29,1,1,1,0,9,102,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58, +109,97,116,52,120,50,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,16,10,52,0,0,17,48,0,48,0,0,0, +17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,29,1,1,1,0,5,105,0,0,0,1,3,2,1,9,1, +102,0,2,58,102,108,111,97,116,0,18,105,0,0,0,0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116, +52,120,50,0,18,102,0,0,0,20,0,0,1,0,29,1,1,1,0,1,98,0,0,0,1,3,2,1,9,1,102,0,2,58,102,108,111,97, +116,0,18,98,0,0,0,0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,50,0,18,102,0,0,0,20, +0,0,1,0,29,1,1,1,0,10,99,48,0,0,1,1,0,10,99,49,0,0,1,1,0,10,99,50,0,0,1,1,0,10,99,51,0,0,0,1,9,18, +95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16, +10,49,0,57,18,99,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,99,50,0,20,0,9,18, +95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,99,51,0,20,0,0,1,0,31,1,1,1,0,9,102,48,48,0,0,1,1,0, +9,102,49,48,0,0,1,1,0,9,102,50,48,0,0,1,1,0,9,102,48,49,0,0,1,1,0,9,102,49,49,0,0,1,1,0,9,102,50, +49,0,0,1,1,0,9,102,48,50,0,0,1,1,0,9,102,49,50,0,0,1,1,0,9,102,50,50,0,0,1,1,0,9,102,48,51,0,0,1,1, +0,9,102,49,51,0,0,1,1,0,9,102,50,51,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,120, +0,18,102,48,48,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,121,0,18,102,49,48,0,20,0, +9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,59,122,0,18,102,50,48,0,20,0,9,18,95,95,114,101, +116,86,97,108,0,16,10,49,0,57,59,120,0,18,102,48,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16, +10,49,0,57,59,121,0,18,102,49,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,59,122,0, +18,102,50,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,120,0,18,102,48,50,0,20,0, +9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,59,121,0,18,102,49,50,0,20,0,9,18,95,95,114,101, +116,86,97,108,0,16,10,50,0,57,59,122,0,18,102,50,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16, +10,51,0,57,59,120,0,18,102,48,51,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,59,121,0, +18,102,49,51,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,59,122,0,18,102,50,51,0,20,0, +0,1,0,31,1,1,1,0,9,102,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,18,102, +0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0, +0,17,48,0,48,0,0,0,18,102,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,31,1, +1,1,0,5,105,0,0,0,1,3,2,1,9,1,102,0,2,58,102,108,111,97,116,0,18,105,0,0,0,0,0,9,18,95,95,114,101, +116,86,97,108,0,58,109,97,116,52,120,51,0,18,102,0,0,0,20,0,0,1,0,31,1,1,1,0,1,98,0,0,0,1,3,2,1,9, +1,102,0,2,58,102,108,111,97,116,0,18,98,0,0,0,0,0,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116, +52,120,51,0,18,102,0,0,0,20,0,0,1,0,31,1,1,1,0,11,99,48,0,0,1,1,0,11,99,49,0,0,1,1,0,11,99,50,0,0, +1,1,0,11,99,51,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,99,48,0,20,0,9,18,95,95, +114,101,116,86,97,108,0,16,10,49,0,57,18,99,49,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50, +0,57,18,99,50,0,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,99,51,0,20,0,0,1,0,13,1,1, +1,0,13,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,0,13,1,1,1,0,27,109,0,0,0, +1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49, +0,57,0,0,20,0,0,1,0,13,1,1,1,0,29,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50, +0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,0,13,1,1,1,0,26,109,0,0,0,1,9,18,95, +95,114,101,116,86,97,108,0,58,109,97,116,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10, +49,0,57,59,120,121,0,0,0,20,0,0,1,0,13,1,1,1,0,28,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0, +58,109,97,116,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,0,20, +0,0,1,0,13,1,1,1,0,14,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,0,18,109,0, +16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,0,20,0,0,1,0,13,1,1,1,0,30,109,0, +0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0, +18,109,0,16,10,49,0,57,59,120,121,0,0,0,20,0,0,1,0,13,1,1,1,0,31,109,0,0,0,1,9,18,95,95,114,101, +116,86,97,108,0,58,109,97,116,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59, +120,121,0,0,0,20,0,0,1,0,13,1,1,1,0,15,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97, +116,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,0,20,0,0,1,0, +26,1,1,1,0,26,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,0,26,1,1,1,0,14,109, +0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,0,18, +109,0,16,10,49,0,57,0,0,20,0,0,1,0,26,1,1,1,0,31,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58, +109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,0,26,1,1,1,0,28, +109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,59, +120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,0,20,0,0,1,0,26,1,1,1,0,30,109,0,0,0,1,9, +18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,59,120,121,122,0, +0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,0,20,0,0,1,0,26,1,1,1,0,15,109,0,0,0,1,9,18,95,95,114, +101,116,86,97,108,0,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16, +10,49,0,57,59,120,121,122,0,0,0,20,0,0,1,0,26,1,1,1,0,13,109,0,0,0,1,9,18,95,95,114,101,116,86,97, +108,0,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0, +17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0, +0,0,0,20,0,0,1,0,26,1,1,1,0,27,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120, +51,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,17,48,0,48,0,0,0,18,109,0, +16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,26,1,1,1, +0,29,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0, +57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0, +18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,28,1,1,1,0,28,109,0,0,0,1,9,18,95, +95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,0,28,1,1,1,0,30,109,0,0,0,1,9,18,95,95,114,101,116,86, +97,108,0,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,0, +28,1,1,1,0,15,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,18,109,0,16, +8,48,0,57,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,0,28,1,1,1,0,26,109,0,0,0,1,9,18,95,95,114,101,116, +86,97,108,0,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59, +121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109, +0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,122,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,28,1,1, +1,0,14,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0, +57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,17,48,0,48,0,0,0, +18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,122, +0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,28,1,1,1,0,31,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58, +109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0, +16,8,48,0,57,59,122,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57, +59,121,0,0,18,109,0,16,10,49,0,57,59,122,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,28,1,1,1,0,13,109,0,0,0, +1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,59,120,0,0,18, +109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59,120,0,0, +18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,28,1,1,1,0,27,109, +0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,59,120, +0,0,18,109,0,16,8,48,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49,0,57,59, +120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,28,1,1,1, +0,29,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0, +57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,18,109,0,16,10,49, +0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0, +27,1,1,1,0,27,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,0,27,1,1,1,0,29,109, +0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,18,109,0,16,8,48,0,57,0,18, +109,0,16,10,49,0,57,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,0,27,1,1,1,0,14,109,0,0,0,1,9,18,95,95, +114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0, +18,109,0,16,10,50,0,57,0,0,20,0,0,1,0,27,1,1,1,0,30,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0, +58,109,97,116,51,120,50,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109, +0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,120,0,0,18, +109,0,16,10,50,0,57,59,121,0,0,0,20,0,0,1,0,27,1,1,1,0,31,109,0,0,0,1,9,18,95,95,114,101,116,86,97, +108,0,58,109,97,116,51,120,50,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0, +18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,120, +0,0,18,109,0,16,10,50,0,57,59,121,0,0,0,20,0,0,1,0,27,1,1,1,0,15,109,0,0,0,1,9,18,95,95,114,101, +116,86,97,108,0,58,109,97,116,51,120,50,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57, +59,121,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17, +48,0,48,0,0,0,0,20,0,0,1,0,27,1,1,1,0,13,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97, +116,51,120,50,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,58,118,101,99,50,0,17,48,0,48,0,0, +0,0,0,0,20,0,0,1,0,27,1,1,1,0,26,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51, +120,50,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57, +59,120,0,0,18,109,0,16,10,49,0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,27,1,1, +1,0,28,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,50,0,18,109,0,16,8,48,0, +57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,49, +0,57,59,121,0,0,17,48,0,48,0,0,0,17,48,0,48,0,0,0,0,20,0,0,1,0,14,1,1,1,0,14,109,0,0,0,1,9,18,95, +95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,0,14,1,1,1,0,31,109,0,0,0,1,9,18,95,95,114,101,116,86, +97,108,0,58,109,97,116,51,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,18,109,0,16,10,50,0, +57,0,0,20,0,0,1,0,14,1,1,1,0,30,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0, +18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,18,109,0,16,10, +50,0,57,59,120,121,122,0,0,0,20,0,0,1,0,14,1,1,1,0,15,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108, +0,58,109,97,116,51,0,18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121, +122,0,0,18,109,0,16,10,50,0,57,59,120,121,122,0,0,0,20,0,0,1,0,14,1,1,1,0,26,109,0,0,0,1,9,18,95, +95,114,101,116,86,97,108,0,58,109,97,116,51,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,17, +48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,14,1,1,1,0,28,109,0,0,0,1,9,18,95,95,114,101, +116,86,97,108,0,58,109,97,116,51,0,18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57, +59,120,121,122,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,14,1,1,1,0,27,109,0,0,0, +1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18, +109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,0,20,0,0,1,0,14,1,1,1,0, +29,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,18,109,0,16,8,48,0,57,0,17,48, +0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,0,20,0,0,1,0, +14,1,1,1,0,13,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,0,18,109,0,16,8,48,0, +57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0, +0,0,20,0,0,1,0,30,1,1,1,0,30,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,0,30, +1,1,1,0,15,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,18,109,0,16,8, +48,0,57,0,18,109,0,16,10,49,0,57,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,0,30,1,1,1,0,14,109,0,0,0,1, +9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0, +18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,0,20,0,0,1,0,30,1,1, +1,0,31,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0, +57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,0, +20,0,0,1,0,30,1,1,1,0,28,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0, +18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0, +0,0,0,0,20,0,0,1,0,30,1,1,1,0,26,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51, +120,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0, +0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,30,1,1,1,0,27,109,0,0,0,1,9,18,95,95,114, +101,116,86,97,108,0,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0, +18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,17,48, +0,0,0,0,0,20,0,0,1,0,30,1,1,1,0,29,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51, +120,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0, +0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,30,1,1,1,0,13, +109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0,57,0, +17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17, +48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,29,1,1,1,0,29,109,0,0,0,1,9,18,95,95,114,101, +116,86,97,108,0,18,109,0,20,0,0,1,0,29,1,1,1,0,31,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0, +58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0, +0,18,109,0,16,10,50,0,57,59,120,121,0,0,18,109,0,16,10,51,0,57,59,120,121,0,0,0,20,0,0,1,0,29,1,1, +1,0,15,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0, +57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,18,109,0,16,10,50,0,57,59,120,121,0,0,18, +109,0,16,10,51,0,57,59,120,121,0,0,0,20,0,0,1,0,29,1,1,1,0,27,109,0,0,0,1,9,18,95,95,114,101,116, +86,97,108,0,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0, +0,17,48,0,0,0,0,0,20,0,0,1,0,29,1,1,1,0,14,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109, +97,116,52,120,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,18, +109,0,16,10,50,0,57,59,120,121,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,29,1,1,1,0,30,109,0,0, +0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,59,120,121, +0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,18,109,0,16,10,50,0,57,59,120,121,0,0,17,48,0,0,0,0,17, +48,0,0,0,0,0,20,0,0,1,0,29,1,1,1,0,13,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116, +52,120,50,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0, +0,0,17,48,0,0,0,0,0,20,0,0,1,0,29,1,1,1,0,26,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109, +97,116,52,120,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18,109,0,16,10,49,0,57,59,120,121,0,0,17, +48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,29,1,1,1,0,28,109,0,0,0,1,9,18, +95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,59,120,121,0,0,18, +109,0,16,10,49,0,57,59,120,121,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0, +0,1,0,31,1,1,1,0,31,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,18,109,0,20,0,0,1,0,31,1,1,1,0, +15,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57, +59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,18,109,0,16,10,50,0,57,59,120,121,122, +0,0,18,109,0,16,10,51,0,57,59,120,121,122,0,0,0,20,0,0,1,0,31,1,1,1,0,14,109,0,0,0,1,9,18,95,95, +114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0, +18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,31,1,1,1,0,30,109, +0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,59,120, +121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,18,109,0,16,10,50,0,57,59,120,121,122,0,0,17, +48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,31,1,1,1,0,29,109,0,0,0,1,9,18,95,95,114,101, +116,86,97,108,0,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49, +0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,18,109,0,16,10,51,0,57,0,17,48,0,0,0,0, +0,20,0,0,1,0,31,1,1,1,0,26,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51, +0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48, +0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,31,1,1,1,0,27,109,0,0,0,1,9,18,95,95,114,101,116, +86,97,108,0,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0,57, +0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0, +20,0,0,1,0,31,1,1,1,0,28,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0, +18,109,0,16,8,48,0,57,59,120,121,122,0,0,18,109,0,16,10,49,0,57,59,120,121,122,0,0,17,48,0,0,0,0, +17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,31,1,1,1,0,13, +109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,0, +17,48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17, +48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,0,20,0,0,1,0,15,1,1,1,0,15,109,0,0,0,1,9,18,95,95,114,101, +116,86,97,108,0,18,109,0,20,0,0,1,0,15,1,1,1,0,30,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0, +58,109,97,116,52,0,18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,18,109,0,16,10,50,0,57,0,17,48, +0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,15,1,1,1,0,31,109,0,0,0,1,9,18,95, +95,114,101,116,86,97,108,0,58,109,97,116,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10, +49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,18,109,0,16,10,51,0,57,0,17,49,0,0, +0,0,0,20,0,0,1,0,15,1,1,1,0,28,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0, +18,109,0,16,8,48,0,57,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0, +0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,15,1,1,1,0,29,109,0,0,0, +1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,17, +48,0,0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0, +0,0,17,48,0,0,0,0,18,109,0,16,10,51,0,57,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,15,1,1,1,0,14, +109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,58,109,97,116,52,0,18,109,0,16,8,48,0,57,0,17,48,0, +0,0,0,18,109,0,16,10,49,0,57,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0, +17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,15,1,1,1,0,26,109,0,0,0,1,9,18,95,95,114, +101,116,86,97,108,0,58,109,97,116,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,18,109,0,16,10,49,0, +57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0, +0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,15,1,1,1,0,27,109,0,0,0,1,9,18,95,95,114,101,116,86, +97,108,0,58,109,97,116,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,49, +0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18,109,0,16,10,50,0,57,0,17,49,0,0,0,0,17,48,0,0,0,0,17,48,0,0, +0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,15,1,1,1,0,13,109,0,0,0,1,9,18,95,95, +114,101,116,86,97,108,0,58,109,97,116,52,0,18,109,0,16,8,48,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,18, +109,0,16,10,49,0,57,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,17,48, +0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,48,0,0,0,0,17,49,0,0,0,0,0,20,0,0,1,0,0,2,1,1,0,2,26,109,0, +0,1,1,0,26,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57, +18,110,0,16,10,49,0,57,21,0,0,1,0,0,2,1,1,0,2,28,109,0,0,1,1,0,28,110,0,0,0,1,9,18,109,0,16,8,48,0, +57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,0,1,0,0,2,1,1,0, +2,27,109,0,0,1,1,0,27,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16, +10,49,0,57,18,110,0,16,10,49,0,57,21,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,21,0,0,1,0, +0,2,1,1,0,2,30,109,0,0,1,1,0,30,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9, +18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57, +21,0,0,1,0,0,2,1,1,0,2,29,109,0,0,1,1,0,29,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0, +57,21,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,21,0,9,18,109,0,16,10,50,0,57,18,110,0,16, +10,50,0,57,21,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,21,0,0,1,0,0,2,1,1,0,2,31,109,0,0, +1,1,0,31,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,21,0,9,18,109,0,16,10,49,0,57, +18,110,0,16,10,49,0,57,21,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,21,0,9,18,109,0,16,10, +51,0,57,18,110,0,16,10,51,0,57,21,0,0,1,0,0,2,2,1,0,2,26,109,0,0,1,1,0,26,110,0,0,0,1,9,18,109,0, +16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,0,1,0, +0,2,2,1,0,2,28,109,0,0,1,1,0,28,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9, +18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,0,1,0,0,2,2,1,0,2,27,109,0,0,1,1,0,27,110,0,0,0, +1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0, +57,22,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,22,0,0,1,0,0,2,2,1,0,2,30,109,0,0,1,1,0,30, +110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0, +16,10,49,0,57,22,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,22,0,0,1,0,0,2,2,1,0,2,29,109,0, +0,1,1,0,29,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57, +18,110,0,16,10,49,0,57,22,0,9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,22,0,9,18,109,0,16,10, +51,0,57,18,110,0,16,10,51,0,57,22,0,0,1,0,0,2,2,1,0,2,31,109,0,0,1,1,0,31,110,0,0,0,1,9,18,109,0, +16,8,48,0,57,18,110,0,16,8,48,0,57,22,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,22,0,9,18, +109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,22,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,22, +0,0,1,0,0,2,4,1,0,2,26,109,0,0,1,1,0,26,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57, +24,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,0,1,0,0,2,4,1,0,2,28,109,0,0,1,1,0,28, +110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,0,16,10,49,0,57,18,110,0, +16,10,49,0,57,24,0,0,1,0,0,2,4,1,0,2,27,109,0,0,1,1,0,27,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18, +110,0,16,8,48,0,57,24,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,9,18,109,0,16,10,50,0, +57,18,110,0,16,10,50,0,57,24,0,0,1,0,0,2,4,1,0,2,30,109,0,0,1,1,0,30,110,0,0,0,1,9,18,109,0,16,8, +48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,9,18,109,0, +16,10,50,0,57,18,110,0,16,10,50,0,57,24,0,0,1,0,0,2,4,1,0,2,29,109,0,0,1,1,0,29,110,0,0,0,1,9,18, +109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,24,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0, +9,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,24,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0, +57,24,0,0,1,0,0,2,4,1,0,2,31,109,0,0,1,1,0,31,110,0,0,0,1,9,18,109,0,16,8,48,0,57,18,110,0,16,8,48, +0,57,24,0,9,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,24,0,9,18,109,0,16,10,50,0,57,18,110,0, +16,10,50,0,57,24,0,9,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,24,0,0,1,0,11,2,21,1,1,0,26,109, +0,0,1,1,0,10,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,118,0,59,120,0,18,109,0,16, +8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,48,46,20,0,9,18,95,95,114, +101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0, +18,109,0,16,10,49,0,57,59,121,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,118,0,59, +120,0,18,109,0,16,8,48,0,57,59,122,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,122,0,48,46,20, +0,0,1,0,12,2,21,1,1,0,28,109,0,0,1,1,0,10,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0, +18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59, +120,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18,109,0,16,8,48,0, +57,59,121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,20,0,9,18,95,95,114,101,116, +86,97,108,0,59,122,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,122,0,48,18,118,0,59,121,0,18,109, +0,16,10,49,0,57,59,122,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,18,118,0,59,120,0, +18,109,0,16,8,48,0,57,59,119,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,119,0,48,46,20,0,0,1, +0,10,2,21,1,1,0,27,109,0,0,1,1,0,11,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,118, +0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,48, +46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,120,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0, +59,121,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0, +57,59,121,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,121,0,48,46,20,0,0,1,0,12,2,21,1,1,0, +30,109,0,0,1,1,0,11,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,18,118,0,59,120,0,18, +109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,120,0,48,46,18,118,0,59, +122,0,18,109,0,16,10,50,0,57,59,120,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18, +118,0,59,120,0,18,109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0, +48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,121,0,48,46,20,0,9,18,95,95,114,101,116,86,97, +108,0,59,122,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,122,0,48,18,118,0,59,121,0,18,109,0,16, +10,49,0,57,59,122,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,122,0,48,46,20,0,9,18,95,95, +114,101,116,86,97,108,0,59,119,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,119,0,48,18,118,0,59, +121,0,18,109,0,16,10,49,0,57,59,119,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,119,0,48, +46,20,0,0,1,0,10,2,21,1,1,0,29,109,0,0,1,1,0,12,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59, +120,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57, +59,120,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,120,0,48,46,18,118,0,59,119,0,18,109,0, +16,10,51,0,57,59,120,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18, +109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0,59, +122,0,18,109,0,16,10,50,0,57,59,121,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,121,0,48, +46,20,0,0,1,0,11,2,21,1,1,0,31,109,0,0,1,1,0,12,118,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59, +120,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,120,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57, +59,120,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0,57,59,120,0,48,46,18,118,0,59,119,0,18,109,0, +16,10,51,0,57,59,120,0,48,46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,18,118,0,59,120,0,18, +109,0,16,8,48,0,57,59,121,0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,121,0,48,46,18,118,0,59, +122,0,18,109,0,16,10,50,0,57,59,121,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,121,0,48, +46,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,18,118,0,59,120,0,18,109,0,16,8,48,0,57,59,122, +0,48,18,118,0,59,121,0,18,109,0,16,10,49,0,57,59,122,0,48,46,18,118,0,59,122,0,18,109,0,16,10,50,0, +57,59,122,0,48,46,18,118,0,59,119,0,18,109,0,16,10,51,0,57,59,122,0,48,46,20,0,0,1,0,27,2,21,1,1,0, +13,109,0,0,1,1,0,27,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0, +16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0, +57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20, +0,0,1,0,29,2,21,1,1,0,13,109,0,0,1,1,0,29,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0, +57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109, +0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110, +0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16,10, +51,0,57,48,20,0,0,1,0,26,2,21,1,1,0,26,109,0,0,1,1,0,13,110,0,0,0,1,9,18,95,95,114,101,116,86,97, +108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10, +49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,0,14,2,21,1,1,0,26,109,0,0,1,1,0,27,110,0,0,0, +1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95, +95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114, +101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,31,2,21,1,1,0,26, +109,0,0,1,1,0,29,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16, +8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57, +48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9, +18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,0,28,2, +21,1,1,0,28,109,0,0,1,1,0,13,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0, +18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0, +16,10,49,0,57,48,20,0,0,1,0,30,2,21,1,1,0,28,109,0,0,1,1,0,27,110,0,0,0,1,9,18,95,95,114,101,116, +86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0, +16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50, +0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,15,2,21,1,1,0,28,109,0,0,1,1,0,29,110,0,0,0,1,9, +18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95, +114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101, +116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97, +108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,0,13,2,21,1,1,0,27,109,0,0,1,1,0, +26,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48, +20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1, +0,27,2,21,1,1,0,27,109,0,0,1,1,0,14,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18, +109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18, +110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16, +10,50,0,57,48,20,0,0,1,0,29,2,21,1,1,0,27,109,0,0,1,1,0,31,110,0,0,0,1,9,18,95,95,114,101,116,86, +97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16, +10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0, +57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109, +0,18,110,0,16,10,51,0,57,48,20,0,0,1,0,26,2,21,1,1,0,14,109,0,0,1,1,0,26,110,0,0,0,1,9,18,95,95, +114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116, +86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,0,31,2,21,1,1,0,14,109,0,0,1, +1,0,31,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57, +48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9, +18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95, +114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,0,28,2,21,1,1,0, +30,109,0,0,1,1,0,26,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0, +16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0, +57,48,20,0,0,1,0,30,2,21,1,1,0,30,109,0,0,1,1,0,14,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0, +16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0, +57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109, +0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,15,2,21,1,1,0,30,109,0,0,1,1,0,31,110,0,0,0,1,9,18,95,95, +114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116, +86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108, +0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10, +51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,0,13,2,21,1,1,0,29,109,0,0,1,1,0,28,110,0,0,0, +1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95, +95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,0,27,2,21,1,1, +0,29,109,0,0,1,1,0,30,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110, +0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49, +0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48, +20,0,0,1,0,29,2,21,1,1,0,29,109,0,0,1,1,0,15,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18, +109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18, +110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16, +10,51,0,57,48,20,0,0,1,0,26,2,21,1,1,0,31,109,0,0,1,1,0,28,110,0,0,0,1,9,18,95,95,114,101,116,86, +97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16, +10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,0,1,0,14,2,21,1,1,0,31,109,0,0,1,1,0,30,110,0,0, +0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95, +95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114, +101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,31,2,21,1,1,0,31, +109,0,0,1,1,0,15,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16, +8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57, +48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,9, +18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,18,110,0,16,10,51,0,57,48,20,0,0,1,0,28,2, +21,1,1,0,15,109,0,0,1,1,0,28,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0, +18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,18,110,0, +16,10,49,0,57,48,20,0,0,1,0,30,2,21,1,1,0,15,109,0,0,1,1,0,30,110,0,0,0,1,9,18,95,95,114,101,116, +86,97,108,0,16,8,48,0,57,18,109,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0, +16,10,49,0,57,18,109,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50, +0,57,18,109,0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,0,2,3,1,0,2,26,109,0,0,1,1,0,13,110,0,0,0,1,9, +18,109,0,18,109,0,18,110,0,48,20,0,0,1,0,0,2,3,1,0,2,28,109,0,0,1,1,0,13,110,0,0,0,1,9,18,109,0,18, +109,0,18,110,0,48,20,0,0,1,0,0,2,3,1,0,2,27,109,0,0,1,1,0,14,110,0,0,0,1,9,18,109,0,18,109,0,18, +110,0,48,20,0,0,1,0,0,2,3,1,0,2,30,109,0,0,1,1,0,14,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20, +0,0,1,0,0,2,3,1,0,2,29,109,0,0,1,1,0,15,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,0,1,0,0,2, +3,1,0,2,31,109,0,0,1,1,0,15,110,0,0,0,1,9,18,109,0,18,109,0,18,110,0,48,20,0,0,1,0,11,2,21,1,1,0, +10,118,0,0,1,1,0,27,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,100,111,116,0,18, +118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,100,111,116, +0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,100, +111,116,0,18,118,0,0,18,109,0,16,10,50,0,57,0,0,20,0,0,1,0,12,2,21,1,1,0,10,118,0,0,1,1,0,29,109,0, +0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,100,111,116,0,18,118,0,0,18,109,0,16,8,48,0, +57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,100,111,116,0,18,118,0,0,18,109,0,16,10, +49,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,100,111,116,0,18,118,0,0,18,109,0, +16,10,50,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,119,0,58,100,111,116,0,18,118,0,0,18, +109,0,16,10,51,0,57,0,0,20,0,0,1,0,10,2,21,1,1,0,11,118,0,0,1,1,0,26,109,0,0,0,1,9,18,95,95,114, +101,116,86,97,108,0,59,120,0,58,100,111,116,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95, +114,101,116,86,97,108,0,59,121,0,58,100,111,116,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,0, +12,2,21,1,1,0,11,118,0,0,1,1,0,31,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,100, +111,116,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58, +100,111,116,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,122, +0,58,100,111,116,0,18,118,0,0,18,109,0,16,10,50,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0, +59,119,0,58,100,111,116,0,18,118,0,0,18,109,0,16,10,51,0,57,0,0,20,0,0,1,0,10,2,21,1,1,0,12,118,0, +0,1,1,0,28,109,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,59,120,0,58,100,111,116,0,18,118,0,0,18, +109,0,16,8,48,0,57,0,0,20,0,9,18,95,95,114,101,116,86,97,108,0,59,121,0,58,100,111,116,0,18,118,0, +0,18,109,0,16,10,49,0,57,0,0,20,0,0,1,0,11,2,21,1,1,0,12,118,0,0,1,1,0,30,109,0,0,0,1,9,18,95,95, +114,101,116,86,97,108,0,59,120,0,58,100,111,116,0,18,118,0,0,18,109,0,16,8,48,0,57,0,0,20,0,9,18, +95,95,114,101,116,86,97,108,0,59,121,0,58,100,111,116,0,18,118,0,0,18,109,0,16,10,49,0,57,0,0,20,0, +9,18,95,95,114,101,116,86,97,108,0,59,122,0,58,100,111,116,0,18,118,0,0,18,109,0,16,10,50,0,57,0,0, +20,0,0,1,0,0,2,1,1,0,2,26,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109, +0,16,10,49,0,57,18,97,0,21,0,0,1,0,0,2,1,1,0,2,28,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0, +57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97,0,21,0,0,1,0,0,2,1,1,0,2,27,109,0,0,1,1,0,9,97,0,0, +0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97,0,21,0,9,18,109,0,16,10,50, +0,57,18,97,0,21,0,0,1,0,0,2,1,1,0,2,30,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0, +21,0,9,18,109,0,16,10,49,0,57,18,97,0,21,0,9,18,109,0,16,10,50,0,57,18,97,0,21,0,0,1,0,0,2,1,1,0,2, +29,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18,97, +0,21,0,9,18,109,0,16,10,50,0,57,18,97,0,21,0,9,18,109,0,16,10,51,0,57,18,97,0,21,0,0,1,0,0,2,1,1,0, +2,31,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,21,0,9,18,109,0,16,10,49,0,57,18, +97,0,21,0,9,18,109,0,16,10,50,0,57,18,97,0,21,0,9,18,109,0,16,10,51,0,57,18,97,0,21,0,0,1,0,0,2,2, +1,0,2,26,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57, +18,97,0,22,0,0,1,0,0,2,2,1,0,2,28,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0, +9,18,109,0,16,10,49,0,57,18,97,0,22,0,0,1,0,0,2,2,1,0,2,27,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0, +16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,97,0,22,0,9,18,109,0,16,10,50,0,57,18,97,0, +22,0,0,1,0,0,2,2,1,0,2,30,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109, +0,16,10,49,0,57,18,97,0,22,0,9,18,109,0,16,10,50,0,57,18,97,0,22,0,0,1,0,0,2,2,1,0,2,29,109,0,0,1, +1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,97,0,22,0,9,18, +109,0,16,10,50,0,57,18,97,0,22,0,9,18,109,0,16,10,51,0,57,18,97,0,22,0,0,1,0,0,2,2,1,0,2,31,109,0, +0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,22,0,9,18,109,0,16,10,49,0,57,18,97,0,22,0,9, +18,109,0,16,10,50,0,57,18,97,0,22,0,9,18,109,0,16,10,51,0,57,18,97,0,22,0,0,1,0,0,2,3,1,0,2,26,109, +0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0, +0,1,0,0,2,3,1,0,2,28,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16, +10,49,0,57,18,97,0,23,0,0,1,0,0,2,3,1,0,2,27,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18, +97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0,9,18,109,0,16,10,50,0,57,18,97,0,23,0,0,1,0,0,2,3, +1,0,2,30,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57, +18,97,0,23,0,9,18,109,0,16,10,50,0,57,18,97,0,23,0,0,1,0,0,2,3,1,0,2,29,109,0,0,1,1,0,9,97,0,0,0,1, +9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0,9,18,109,0,16,10,50,0, +57,18,97,0,23,0,9,18,109,0,16,10,51,0,57,18,97,0,23,0,0,1,0,0,2,3,1,0,2,31,109,0,0,1,1,0,9,97,0,0, +0,1,9,18,109,0,16,8,48,0,57,18,97,0,23,0,9,18,109,0,16,10,49,0,57,18,97,0,23,0,9,18,109,0,16,10,50, +0,57,18,97,0,23,0,9,18,109,0,16,10,51,0,57,18,97,0,23,0,0,1,0,0,2,4,1,0,2,26,109,0,0,1,1,0,9,97,0, +0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,0,1,0,0,2,4,1,0,2, +28,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97, +0,24,0,0,1,0,0,2,4,1,0,2,27,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0,9,18, +109,0,16,10,49,0,57,18,97,0,24,0,9,18,109,0,16,10,50,0,57,18,97,0,24,0,0,1,0,0,2,4,1,0,2,30,109,0, +0,1,1,0,9,97,0,0,0,1,9,18,109,0,16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,9, +18,109,0,16,10,50,0,57,18,97,0,24,0,0,1,0,0,2,4,1,0,2,29,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0,16, +8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,9,18,109,0,16,10,50,0,57,18,97,0,24,0, +9,18,109,0,16,10,51,0,57,18,97,0,24,0,0,1,0,0,2,4,1,0,2,31,109,0,0,1,1,0,9,97,0,0,0,1,9,18,109,0, +16,8,48,0,57,18,97,0,24,0,9,18,109,0,16,10,49,0,57,18,97,0,24,0,9,18,109,0,16,10,50,0,57,18,97,0, +24,0,9,18,109,0,16,10,51,0,57,18,97,0,24,0,0,1,0,26,2,26,1,1,0,26,109,0,0,1,1,0,26,110,0,0,0,1,8, +58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57, +18,110,0,16,10,49,0,57,46,0,0,0,0,1,0,28,2,26,1,1,0,28,109,0,0,1,1,0,28,110,0,0,0,1,8,58,109,97, +116,50,120,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0, +16,10,49,0,57,46,0,0,0,0,1,0,27,2,26,1,1,0,27,109,0,0,1,1,0,27,110,0,0,0,1,8,58,109,97,116,51,120, +50,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0, +57,46,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,0,0,0,0,1,0,30,2,26,1,1,0,30,109,0,0,1,1, +0,30,110,0,0,0,1,8,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,46,0,18, +109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,46,0, +0,0,0,1,0,29,2,26,1,1,0,29,109,0,0,1,1,0,29,110,0,0,0,1,8,58,109,97,116,52,120,50,0,18,109,0,16,8, +48,0,57,18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,18,109,0,16, +10,50,0,57,18,110,0,16,10,50,0,57,46,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,46,0,0,0,0,1, +0,31,2,26,1,1,0,31,109,0,0,1,1,0,31,110,0,0,0,1,8,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57, +18,110,0,16,8,48,0,57,46,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,46,0,18,109,0,16,10,50,0, +57,18,110,0,16,10,50,0,57,46,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,46,0,0,0,0,1,0,26,2, +27,1,1,0,26,109,0,0,1,1,0,26,110,0,0,0,1,8,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,18,110, +0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,0,0,0,1,0,28,2,27,1,1,0,28, +109,0,0,1,1,0,28,110,0,0,0,1,8,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0, +57,47,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,0,0,0,1,0,27,2,27,1,1,0,27,109,0,0,1,1, +0,27,110,0,0,0,1,8,58,109,97,116,51,120,50,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,0,18, +109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,47,0, +0,0,0,1,0,30,2,27,1,1,0,30,109,0,0,1,1,0,30,110,0,0,0,1,8,58,109,97,116,51,120,52,0,18,109,0,16,8, +48,0,57,18,110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,47,0,18,109,0,16, +10,50,0,57,18,110,0,16,10,50,0,57,47,0,0,0,0,1,0,29,2,27,1,1,0,29,109,0,0,1,1,0,29,110,0,0,0,1,8, +58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57, +18,110,0,16,10,49,0,57,47,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,47,0,18,109,0,16,10,51,0, +57,18,110,0,16,10,51,0,57,47,0,0,0,0,1,0,31,2,27,1,1,0,31,109,0,0,1,1,0,31,110,0,0,0,1,8,58,109,97, +116,52,120,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,47,0,18,109,0,16,10,49,0,57,18,110,0, +16,10,49,0,57,47,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,47,0,18,109,0,16,10,51,0,57,18, +110,0,16,10,51,0,57,47,0,0,0,0,1,0,26,2,22,1,1,0,26,109,0,0,1,1,0,26,110,0,0,0,1,8,58,109,97,116, +50,120,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10, +49,0,57,49,0,0,0,0,1,0,28,2,22,1,1,0,28,109,0,0,1,1,0,28,110,0,0,0,1,8,58,109,97,116,50,120,52,0, +18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49, +0,0,0,0,1,0,27,2,22,1,1,0,27,109,0,0,1,1,0,27,110,0,0,0,1,8,58,109,97,116,51,120,50,0,18,109,0,16, +8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,0,18,109,0, +16,10,50,0,57,18,110,0,16,10,50,0,57,49,0,0,0,0,1,0,30,2,22,1,1,0,30,109,0,0,1,1,0,30,110,0,0,0,1, +8,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,49,0,18,109,0,16,10,49,0, +57,18,110,0,16,10,49,0,57,49,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,49,0,0,0,0,1,0,29,2, +22,1,1,0,29,109,0,0,1,1,0,29,110,0,0,0,1,8,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,18,110, +0,16,8,48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,0,18,109,0,16,10,50,0,57,18, +110,0,16,10,50,0,57,49,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,49,0,0,0,0,1,0,31,2,22,1,1, +0,31,109,0,0,1,1,0,31,110,0,0,0,1,8,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8, +48,0,57,49,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,49,0,18,109,0,16,10,50,0,57,18,110,0,16, +10,50,0,57,49,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,49,0,0,0,0,1,0,26,2,26,1,1,0,9,97,0, +0,1,1,0,26,110,0,0,0,1,8,58,109,97,116,50,120,51,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18, +110,0,16,10,49,0,57,46,0,0,0,0,1,0,26,2,26,1,1,0,26,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,50, +120,51,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,0,0,0,1,0,28,2,26, +1,1,0,9,97,0,0,1,1,0,28,110,0,0,0,1,8,58,109,97,116,50,120,52,0,18,97,0,18,110,0,16,8,48,0,57,46,0, +18,97,0,18,110,0,16,10,49,0,57,46,0,0,0,0,1,0,28,2,26,1,1,0,28,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109, +97,116,50,120,52,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,0,0,0,1, +0,27,2,26,1,1,0,9,97,0,0,1,1,0,27,110,0,0,0,1,8,58,109,97,116,51,120,50,0,18,97,0,18,110,0,16,8,48, +0,57,46,0,18,97,0,18,110,0,16,10,49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,0,0,0,1,0,27,2, +26,1,1,0,27,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,51,120,50,0,18,109,0,16,8,48,0,57,18,98,0, +46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50,0,57,18,98,0,46,0,0,0,0,1,0,30,2,26,1,1, +0,9,97,0,0,1,1,0,30,110,0,0,0,1,8,58,109,97,116,51,120,52,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18, +97,0,18,110,0,16,10,49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,0,0,0,1,0,30,2,26,1,1,0,30, +109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,109,0, +16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50,0,57,18,98,0,46,0,0,0,0,1,0,29,2,26,1,1,0,29,109,0,0, +1,1,0,9,98,0,0,0,1,8,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,109,0,16,10, +49,0,57,18,98,0,46,0,18,109,0,16,10,50,0,57,18,98,0,46,0,18,109,0,16,10,51,0,57,18,98,0,46,0,0,0,0, +1,0,29,2,26,1,1,0,9,97,0,0,1,1,0,29,110,0,0,0,1,8,58,109,97,116,52,120,50,0,18,97,0,18,110,0,16,8, +48,0,57,46,0,18,97,0,18,110,0,16,10,49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,18,97,0,18, +110,0,16,10,51,0,57,46,0,0,0,0,1,0,31,2,26,1,1,0,31,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,52, +120,51,0,18,109,0,16,8,48,0,57,18,98,0,46,0,18,109,0,16,10,49,0,57,18,98,0,46,0,18,109,0,16,10,50, +0,57,18,98,0,46,0,18,109,0,16,10,51,0,57,18,98,0,46,0,0,0,0,1,0,31,2,26,1,1,0,9,97,0,0,1,1,0,31, +110,0,0,0,1,8,58,109,97,116,52,120,51,0,18,97,0,18,110,0,16,8,48,0,57,46,0,18,97,0,18,110,0,16,10, +49,0,57,46,0,18,97,0,18,110,0,16,10,50,0,57,46,0,18,97,0,18,110,0,16,10,51,0,57,46,0,0,0,0,1,0,26, +2,27,1,1,0,9,97,0,0,1,1,0,26,110,0,0,0,1,8,58,109,97,116,50,120,51,0,18,97,0,18,110,0,16,8,48,0,57, +47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,0,0,0,1,0,26,2,27,1,1,0,26,109,0,0,1,1,0,9,98,0,0,0,1,8, +58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0,16,10,49,0,57,18,98,0,47,0,0, +0,0,1,0,28,2,27,1,1,0,9,97,0,0,1,1,0,28,110,0,0,0,1,8,58,109,97,116,50,120,52,0,18,97,0,18,110,0, +16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,0,0,0,1,0,28,2,27,1,1,0,28,109,0,0,1,1,0,9, +98,0,0,0,1,8,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0,16,10,49,0,57, +18,98,0,47,0,0,0,0,1,0,27,2,27,1,1,0,9,97,0,0,1,1,0,27,110,0,0,0,1,8,58,109,97,116,51,120,50,0,18, +97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,18,97,0,18,110,0,16,10,50,0,57, +47,0,0,0,0,1,0,27,2,27,1,1,0,27,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,51,120,50,0,18,109,0,16, +8,48,0,57,18,98,0,47,0,18,109,0,16,10,49,0,57,18,98,0,47,0,18,109,0,16,10,50,0,57,18,98,0,47,0,0,0, +0,1,0,30,2,27,1,1,0,9,97,0,0,1,1,0,30,110,0,0,0,1,8,58,109,97,116,51,120,52,0,18,97,0,18,110,0,16, +8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,18,97,0,18,110,0,16,10,50,0,57,47,0,0,0,0,1,0, +30,2,27,1,1,0,30,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0,57,18, +98,0,47,0,18,109,0,16,10,49,0,57,18,98,0,47,0,18,109,0,16,10,50,0,57,18,98,0,47,0,0,0,0,1,0,29,2, +27,1,1,0,29,109,0,0,1,1,0,9,98,0,0,0,1,8,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,18,98,0, +47,0,18,109,0,16,10,49,0,57,18,98,0,47,0,18,109,0,16,10,50,0,57,18,98,0,47,0,18,109,0,16,10,51,0, +57,18,98,0,47,0,0,0,0,1,0,29,2,27,1,1,0,9,97,0,0,1,1,0,29,110,0,0,0,1,8,58,109,97,116,52,120,50,0, +18,97,0,18,110,0,16,8,48,0,57,47,0,18,97,0,18,110,0,16,10,49,0,57,47,0,18,97,0,18,110,0,16,10,50,0, +57,47,0,18,97,0,18,110,0,16,10,51,0,57,47,0,0,0,0,1,0,31,2,27,1,1,0,31,109,0,0,1,1,0,9,98,0,0,0,1, +8,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,18,98,0,47,0,18,109,0,16,10,49,0,57,18,98,0,47,0, +18,109,0,16,10,50,0,57,18,98,0,47,0,18,109,0,16,10,51,0,57,18,98,0,47,0,0,0,0,1,0,31,2,27,1,1,0,9, +97,0,0,1,1,0,31,110,0,0,0,1,8,58,109,97,116,52,120,51,0,18,97,0,18,110,0,16,8,48,0,57,47,0,18,97,0, +18,110,0,16,10,49,0,57,47,0,18,97,0,18,110,0,16,10,50,0,57,47,0,18,97,0,18,110,0,16,10,51,0,57,47, +0,0,0,0,1,0,26,2,21,1,1,0,9,97,0,0,1,1,0,26,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48, +0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97, +0,18,110,0,16,10,49,0,57,48,20,0,0,1,0,26,2,21,1,1,0,26,109,0,0,1,1,0,9,98,0,0,0,1,9,18,95,95,114, +101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86, +97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,48,20,0,0,1,0,28,2,21,1,1,0,9,97,0,0,1,1,0, +28,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20, +0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,0,1,0,28, +2,21,1,1,0,28,109,0,0,1,1,0,9,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0, +16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0, +57,18,98,0,48,20,0,0,1,0,27,2,21,1,1,0,9,97,0,0,1,1,0,27,110,0,0,0,1,9,18,95,95,114,101,116,86,97, +108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10, +49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18, +97,0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,27,2,21,1,1,0,27,109,0,0,1,1,0,9,98,0,0,0,1,9,18,95,95, +114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116, +86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108, +0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,48,20,0,0,1,0,30,2,21,1,1,0,9,97,0,0,1,1,0,30,110,0, +0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18, +95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114, +101,116,86,97,108,0,16,10,50,0,57,18,97,0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,30,2,21,1,1,0,30, +109,0,0,1,1,0,9,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16,8,48,0,57, +18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49,0,57,18,98,0,48, +20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98,0,48,20,0,0,1,0, +29,2,21,1,1,0,29,109,0,0,1,1,0,9,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109, +0,16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10,49, +0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16,10,50,0,57,18,98, +0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,0,57,18,98,0,48,20,0, +0,1,0,29,2,21,1,1,0,9,97,0,0,1,1,0,29,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57, +18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,97,0,18, +110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0,18,110,0,16, +10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,97,0,18,110,0,16,10,51,0,57, +48,20,0,0,1,0,31,2,21,1,1,0,31,109,0,0,1,1,0,9,98,0,0,0,1,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,18,109,0,16,8,48,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18, +109,0,16,10,49,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,109,0,16, +10,50,0,57,18,98,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,109,0,16,10,51,0,57, +18,98,0,48,20,0,0,1,0,31,2,21,1,1,0,9,97,0,0,1,1,0,31,110,0,0,0,1,9,18,95,95,114,101,116,86,97,108, +0,16,8,48,0,57,18,97,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0, +57,18,97,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57,18,97,0, +18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0,57,18,97,0,18,110,0, +16,10,51,0,57,48,20,0,0,1,0,26,2,22,1,1,0,9,97,0,0,1,1,0,26,110,0,0,0,1,3,2,1,9,1,105,110,118,0,2, +17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,105,110,118,0,18, +110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,105,110,118,0,18, +110,0,16,10,49,0,57,48,20,0,0,1,0,26,2,22,1,1,0,26,109,0,0,1,1,0,9,98,0,0,0,1,3,2,1,9,1,105,110, +118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,109,0,16, +8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,109,0,16,10, +49,0,57,18,105,110,118,0,48,20,0,0,1,0,28,2,22,1,1,0,9,97,0,0,1,1,0,28,110,0,0,0,1,3,2,1,9,1,105, +110,118,0,2,17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18,105, +110,118,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18,105, +110,118,0,18,110,0,16,10,49,0,57,48,20,0,0,1,0,28,2,22,1,1,0,28,109,0,0,1,1,0,9,98,0,0,0,1,3,2,1,9, +1,105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0,57,18, +109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57,18, +109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,0,1,0,27,2,22,1,1,0,9,97,0,0,1,1,0,27,110,0,0,0,1,3,2, +1,9,1,105,110,118,0,2,17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48,0, +57,18,105,110,118,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0,57, +18,105,110,118,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0,57, +18,105,110,118,0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,27,2,22,1,1,0,27,109,0,0,1,1,0,9,98,0,0,0,1, +3,2,1,9,1,105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8,48, +0,57,18,109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49,0, +57,18,109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0, +57,18,109,0,16,10,50,0,57,18,105,110,118,0,48,20,0,0,1,0,30,2,22,1,1,0,9,97,0,0,1,1,0,30,110,0,0,0, +1,3,2,1,9,1,105,110,118,0,2,17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,18,105,110,118,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49, +0,57,18,105,110,118,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0, +57,18,105,110,118,0,18,110,0,16,10,50,0,57,48,20,0,0,1,0,30,2,22,1,1,0,30,109,0,0,1,1,0,9,98,0,0,0, +1,3,2,1,9,1,105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,18,109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49, +0,57,18,109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0, +57,18,109,0,16,10,50,0,57,18,105,110,118,0,48,20,0,0,1,0,29,2,22,1,1,0,29,109,0,0,1,1,0,9,98,0,0,0, +1,3,2,1,9,1,105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,18,109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49, +0,57,18,109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0, +57,18,109,0,16,10,50,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0, +57,18,109,0,16,10,51,0,57,18,105,110,118,0,48,20,0,0,1,0,29,2,22,1,1,0,9,97,0,0,1,1,0,29,110,0,0,0, +1,3,2,1,9,1,105,110,118,0,2,17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,18,105,110,118,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49, +0,57,18,105,110,118,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0, +57,18,105,110,118,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0, +57,18,105,110,118,0,18,110,0,16,10,51,0,57,48,20,0,0,1,0,31,2,22,1,1,0,31,109,0,0,1,1,0,9,98,0,0,0, +1,3,2,1,9,1,105,110,118,0,2,17,49,0,48,0,0,18,98,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,18,109,0,16,8,48,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49, +0,57,18,109,0,16,10,49,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0, +57,18,109,0,16,10,50,0,57,18,105,110,118,0,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0, +57,18,109,0,16,10,51,0,57,18,105,110,118,0,48,20,0,0,1,0,31,2,22,1,1,0,9,97,0,0,1,1,0,31,110,0,0,0, +1,3,2,1,9,1,105,110,118,0,2,17,49,0,48,0,0,18,97,0,49,0,0,9,18,95,95,114,101,116,86,97,108,0,16,8, +48,0,57,18,105,110,118,0,18,110,0,16,8,48,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,49, +0,57,18,105,110,118,0,18,110,0,16,10,49,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,50,0, +57,18,105,110,118,0,18,110,0,16,10,50,0,57,48,20,0,9,18,95,95,114,101,116,86,97,108,0,16,10,51,0, +57,18,105,110,118,0,18,110,0,16,10,51,0,57,48,20,0,0,1,0,26,2,27,1,1,0,26,109,0,0,0,1,8,58,109,97, +116,50,120,51,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0,57,54,0,0,0,0,1,0,28,2,27,1,1,0,28, +109,0,0,0,1,8,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0,57,54,0,0,0, +0,1,0,27,2,27,1,1,0,27,109,0,0,0,1,8,58,109,97,116,51,120,50,0,18,109,0,16,8,48,0,57,54,0,18,109,0, +16,10,49,0,57,54,0,18,109,0,16,10,50,0,57,54,0,0,0,0,1,0,30,2,27,1,1,0,30,109,0,0,0,1,8,58,109,97, +116,51,120,52,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0,57,54,0,18,109,0,16,10,50,0,57,54,0, +0,0,0,1,0,29,2,27,1,1,0,29,109,0,0,0,1,8,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,54,0,18, +109,0,16,10,49,0,57,54,0,18,109,0,16,10,50,0,57,54,0,18,109,0,16,10,51,0,57,54,0,0,0,0,1,0,31,2,27, +1,1,0,31,109,0,0,0,1,8,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,54,0,18,109,0,16,10,49,0,57, +54,0,18,109,0,16,10,50,0,57,54,0,18,109,0,16,10,51,0,57,54,0,0,0,0,1,0,0,2,25,1,0,2,26,109,0,0,0,1, +9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0,0,1,0,0,2,25,1,0,2,28,109,0,0,0,1,9,18, +109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0,0,1,0,0,2,25,1,0,2,27,109,0,0,0,1,9,18,109,0, +16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0,9,18,109,0,16,10,50,0,57,52,0,0,1,0,0,2,25,1,0,2, +30,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0,9,18,109,0,16,10,50,0,57, +52,0,0,1,0,0,2,25,1,0,2,29,109,0,0,0,1,9,18,109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0, +9,18,109,0,16,10,50,0,57,52,0,9,18,109,0,16,10,51,0,57,52,0,0,1,0,0,2,25,1,0,2,31,109,0,0,0,1,9,18, +109,0,16,8,48,0,57,52,0,9,18,109,0,16,10,49,0,57,52,0,9,18,109,0,16,10,50,0,57,52,0,9,18,109,0,16, +10,51,0,57,52,0,0,1,0,0,2,24,1,0,2,26,109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49, +0,57,51,0,0,1,0,0,2,24,1,0,2,28,109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57, +51,0,0,1,0,0,2,24,1,0,2,27,109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57,51,0, +9,18,109,0,16,10,50,0,57,51,0,0,1,0,0,2,24,1,0,2,30,109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18, +109,0,16,10,49,0,57,51,0,9,18,109,0,16,10,50,0,57,51,0,0,1,0,0,2,24,1,0,2,29,109,0,0,0,1,9,18,109, +0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0,57,51,0,9,18,109,0,16,10,50,0,57,51,0,9,18,109,0,16,10, +51,0,57,51,0,0,1,0,0,2,24,1,0,2,31,109,0,0,0,1,9,18,109,0,16,8,48,0,57,51,0,9,18,109,0,16,10,49,0, +57,51,0,9,18,109,0,16,10,50,0,57,51,0,9,18,109,0,16,10,51,0,57,51,0,0,1,0,26,2,25,1,0,2,26,109,0,0, +1,1,0,5,0,0,0,1,8,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,61,0,18,109,0,16,10,49,0,57,61,0, +0,0,0,1,0,28,2,25,1,0,2,28,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0, +57,61,0,18,109,0,16,10,49,0,57,61,0,0,0,0,1,0,27,2,25,1,0,2,27,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97, +116,51,120,50,0,18,109,0,16,8,48,0,57,61,0,18,109,0,16,10,49,0,57,61,0,18,109,0,16,10,50,0,57,61,0, +0,0,0,1,0,30,2,25,1,0,2,30,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0, +57,61,0,18,109,0,16,10,49,0,57,61,0,18,109,0,16,10,50,0,57,61,0,0,0,0,1,0,29,2,25,1,0,2,29,109,0,0, +1,1,0,5,0,0,0,1,8,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,61,0,18,109,0,16,10,49,0,57,61,0, +18,109,0,16,10,50,0,57,61,0,18,109,0,16,10,51,0,57,61,0,0,0,0,1,0,31,2,25,1,0,2,31,109,0,0,1,1,0,5, +0,0,0,1,8,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,61,0,18,109,0,16,10,49,0,57,61,0,18,109, +0,16,10,50,0,57,61,0,18,109,0,16,10,51,0,57,61,0,0,0,0,1,0,26,2,24,1,0,2,26,109,0,0,1,1,0,5,0,0,0, +1,8,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,60,0,18,109,0,16,10,49,0,57,60,0,0,0,0,1,0,28, +2,24,1,0,2,28,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,60,0,18, +109,0,16,10,49,0,57,60,0,0,0,0,1,0,27,2,24,1,0,2,27,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97,116,51,120, +50,0,18,109,0,16,8,48,0,57,60,0,18,109,0,16,10,49,0,57,60,0,18,109,0,16,10,50,0,57,60,0,0,0,0,1,0, +30,2,24,1,0,2,30,109,0,0,1,1,0,5,0,0,0,1,8,58,109,97,116,51,120,52,0,18,109,0,16,8,48,0,57,60,0,18, +109,0,16,10,49,0,57,60,0,18,109,0,16,10,50,0,57,60,0,0,0,0,1,0,29,2,24,1,0,2,29,109,0,0,1,1,0,5,0, +0,0,1,8,58,109,97,116,52,120,50,0,18,109,0,16,8,48,0,57,60,0,18,109,0,16,10,49,0,57,60,0,18,109,0, +16,10,50,0,57,60,0,18,109,0,16,10,51,0,57,60,0,0,0,0,1,0,31,2,24,1,0,2,31,109,0,0,1,1,0,5,0,0,0,1, +8,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,60,0,18,109,0,16,10,49,0,57,60,0,18,109,0,16,10, +50,0,57,60,0,18,109,0,16,10,51,0,57,60,0,0,0,0,0 diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_common.gc b/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_common.gc new file mode 100644 index 000000000..c6264c3b4 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_common.gc @@ -0,0 +1,200 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.20, rev. 6 +// + +// +// 8.5 Matrix Functions +// + +mat2x3 matrixCompMult (mat2x3 m, mat2x3 n) { + return mat2x3 (m[0] * n[0], m[1] * n[1]); +} + +mat2x4 matrixCompMult (mat2x4 m, mat2x4 n) { + return mat2x4 (m[0] * n[0], m[1] * n[1]); +} + +mat3x2 matrixCompMult (mat3x2 m, mat3x2 n) { + return mat3x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2]); +} + +mat3x4 matrixCompMult (mat3x4 m, mat3x4 n) { + return mat3x4 (m[0] * n[0], m[1] * n[1], m[2] * n[2]); +} + +mat4x2 matrixCompMult (mat4x2 m, mat4x2 n) { + return mat4x2 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]); +} + +mat4x3 matrixCompMult (mat4x3 m, mat4x3 n) { + return mat4x3 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]); +} + +mat2 outerProduct (vec2 c, vec2 r) { + return mat2 ( + c.x * r.x, c.y * r.x, + c.x * r.y, c.y * r.y + ); +} + +mat3 outerProduct (vec3 c, vec3 r) { + return mat3 ( + c.x * r.x, c.y * r.x, c.z * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, + c.x * r.z, c.y * r.z, c.z * r.z + ); +} + +mat4 outerProduct (vec4 c, vec4 r) { + return mat4 ( + c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y, + c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z, + c.x * r.w, c.y * r.w, c.z * r.w, c.w * r.w + ); +} + +mat2x3 outerProduct (vec3 c, vec2 r) { + return mat2x3 ( + c.x * r.x, c.y * r.x, c.z * r.x, + c.x * r.y, c.y * r.y, c.z * r.y + ); +} + +mat3x2 outerProduct (vec2 c, vec3 r) { + return mat3x2 ( + c.x * r.x, c.y * r.x, + c.x * r.y, c.y * r.y, + c.x * r.z, c.y * r.z + ); +} + +mat2x4 outerProduct (vec4 c, vec2 r) { + return mat2x4 ( + c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y + ); +} + +mat4x2 outerProduct (vec2 c, vec4 r) { + return mat4x2 ( + c.x * r.x, c.y * r.x, + c.x * r.y, c.y * r.y, + c.x * r.z, c.y * r.z, + c.x * r.w, c.y * r.w + ); +} + +mat3x4 outerProduct (vec4 c, vec3 r) { + return mat3x4 ( + c.x * r.x, c.y * r.x, c.z * r.x, c.w * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, c.w * r.y, + c.x * r.z, c.y * r.z, c.z * r.z, c.w * r.z + ); +} + +mat4x3 outerProduct (vec3 c, vec4 r) { + return mat4x3 ( + c.x * r.x, c.y * r.x, c.z * r.x, + c.x * r.y, c.y * r.y, c.z * r.y, + c.x * r.z, c.y * r.z, c.z * r.z, + c.x * r.w, c.y * r.w, c.z * r.w + ); +} + +mat2 transpose (mat2 m) { + return mat2 ( + m[0].x, m[1].x, + m[0].y, m[1].y + ); +} + +mat3 transpose (mat3 m) { + return mat3 ( + m[0].x, m[1].x, m[2].x, + m[0].y, m[1].y, m[2].y, + m[0].z, m[1].z, m[2].z + ); +} + +mat4 transpose (mat4 m) { + return mat4 ( + m[0].x, m[1].x, m[2].x, m[3].x, + m[0].y, m[1].y, m[2].y, m[3].y, + m[0].z, m[1].z, m[2].z, m[3].z, + m[0].w, m[1].w, m[2].w, m[3].w + ); +} + +mat2x3 transpose (mat3x2 m) { + return mat2x3 ( + m[0].x, m[1].x, m[2].x, + m[0].y, m[1].y, m[2].y + ); +} + +mat3x2 transpose (mat2x3 m) { + return mat3x2 ( + m[0].x, m[1].x, + m[0].y, m[1].y, + m[0].z, m[1].z + ); +} + +mat2x4 transpose (mat4x2 m) { + return mat2x4 ( + m[0].x, m[1].x, m[2].x, m[3].x, + m[0].y, m[1].y, m[2].y, m[3].y + ); +} + +mat4x2 transpose (mat2x4 m) { + return mat4x2 ( + m[0].x, m[1].x, + m[0].y, m[1].y, + m[0].z, m[1].z, + m[0].w, m[1].w + ); +} + +mat3x4 transpose (mat4x3 m) { + return mat3x4 ( + m[0].x, m[1].x, m[2].x, m[3].x, + m[0].y, m[1].y, m[2].y, m[3].y, + m[0].z, m[1].z, m[2].z, m[3].z + ); +} + +mat4x3 transpose (mat3x4 m) { + return mat4x3 ( + m[0].x, m[1].x, m[2].x, + m[0].y, m[1].y, m[2].y, + m[0].z, m[1].z, m[2].z, + m[0].w, m[1].w, m[2].w + ); +} + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_common_gc.h b/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_common_gc.h new file mode 100644 index 000000000..fc1a94421 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_common_gc.h @@ -0,0 +1,104 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */ +/* slang_builtin_120_common.gc */ + +3,1,0,26,0,109,97,116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,26,109,0,0,1,0,0,26,110,0, +0,0,1,8,58,109,97,116,50,120,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10, +49,0,57,18,110,0,16,10,49,0,57,48,0,0,0,0,1,0,28,0,109,97,116,114,105,120,67,111,109,112,77,117, +108,116,0,1,0,0,28,109,0,0,1,0,0,28,110,0,0,0,1,8,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57, +18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,0,0,0,1,0,27,0,109, +97,116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,27,109,0,0,1,0,0,27,110,0,0,0,1,8,58,109, +97,116,51,120,50,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110, +0,16,10,49,0,57,48,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,48,0,0,0,0,1,0,30,0,109,97,116, +114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,30,109,0,0,1,0,0,30,110,0,0,0,1,8,58,109,97,116, +51,120,52,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10, +49,0,57,48,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,48,0,0,0,0,1,0,29,0,109,97,116,114,105, +120,67,111,109,112,77,117,108,116,0,1,0,0,29,109,0,0,1,0,0,29,110,0,0,0,1,8,58,109,97,116,52,120, +50,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48,0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0, +57,48,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57,48,0,18,109,0,16,10,51,0,57,18,110,0,16,10, +51,0,57,48,0,0,0,0,1,0,31,0,109,97,116,114,105,120,67,111,109,112,77,117,108,116,0,1,0,0,31,109,0, +0,1,0,0,31,110,0,0,0,1,8,58,109,97,116,52,120,51,0,18,109,0,16,8,48,0,57,18,110,0,16,8,48,0,57,48, +0,18,109,0,16,10,49,0,57,18,110,0,16,10,49,0,57,48,0,18,109,0,16,10,50,0,57,18,110,0,16,10,50,0,57, +48,0,18,109,0,16,10,51,0,57,18,110,0,16,10,51,0,57,48,0,0,0,0,1,0,13,0,111,117,116,101,114,80,114, +111,100,117,99,116,0,1,0,0,10,99,0,0,1,0,0,10,114,0,0,0,1,8,58,109,97,116,50,0,18,99,0,59,120,0,18, +114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48, +0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,0,0,0,1,0,14,0,111,117,116,101,114,80,114,111,100,117,99, +116,0,1,0,0,11,99,0,0,1,0,0,11,114,0,0,0,1,8,58,109,97,116,51,0,18,99,0,59,120,0,18,114,0,59,120,0, +48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59, +120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59, +121,0,48,0,18,99,0,59,120,0,18,114,0,59,122,0,48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,18,99,0, +59,122,0,18,114,0,59,122,0,48,0,0,0,0,1,0,15,0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0, +0,12,99,0,0,1,0,0,12,114,0,0,0,1,8,58,109,97,116,52,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18, +99,0,59,121,0,18,114,0,59,120,0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,119,0,18, +114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48, +0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,18,99,0,59,119,0,18,114,0,59,121,0,48,0,18,99,0,59,120,0, +18,114,0,59,122,0,48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,18,99,0,59,122,0,18,114,0,59,122,0, +48,0,18,99,0,59,119,0,18,114,0,59,122,0,48,0,18,99,0,59,120,0,18,114,0,59,119,0,48,0,18,99,0,59, +121,0,18,114,0,59,119,0,48,0,18,99,0,59,122,0,18,114,0,59,119,0,48,0,18,99,0,59,119,0,18,114,0,59, +119,0,48,0,0,0,0,1,0,26,0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,11,99,0,0,1,0,0,10, +114,0,0,0,1,8,58,109,97,116,50,120,51,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0, +18,114,0,59,120,0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0, +48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,0,0,0,1,0,27, +0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,10,99,0,0,1,0,0,11,114,0,0,0,1,8,58,109,97, +116,51,120,50,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,0,18, +99,0,59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,120,0,18, +114,0,59,122,0,48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,0,0,0,1,0,28,0,111,117,116,101,114,80, +114,111,100,117,99,116,0,1,0,0,12,99,0,0,1,0,0,10,114,0,0,0,1,8,58,109,97,116,50,120,52,0,18,99,0, +59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,0,18,99,0,59,122,0,18,114,0, +59,120,0,48,0,18,99,0,59,119,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18, +99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,18,99,0,59,119,0,18, +114,0,59,121,0,48,0,0,0,0,1,0,29,0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,10,99,0,0, +1,0,0,12,114,0,0,0,1,8,58,109,97,116,52,120,50,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0, +59,121,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18,99,0,59,121,0,18,114,0, +59,121,0,48,0,18,99,0,59,120,0,18,114,0,59,122,0,48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,18, +99,0,59,120,0,18,114,0,59,119,0,48,0,18,99,0,59,121,0,18,114,0,59,119,0,48,0,0,0,0,1,0,30,0,111, +117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,12,99,0,0,1,0,0,11,114,0,0,0,1,8,58,109,97,116, +51,120,52,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0,59,120,0,48,0,18,99, +0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,119,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114, +0,59,121,0,48,0,18,99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,18, +99,0,59,119,0,18,114,0,59,121,0,48,0,18,99,0,59,120,0,18,114,0,59,122,0,48,0,18,99,0,59,121,0,18, +114,0,59,122,0,48,0,18,99,0,59,122,0,18,114,0,59,122,0,48,0,18,99,0,59,119,0,18,114,0,59,122,0,48, +0,0,0,0,1,0,31,0,111,117,116,101,114,80,114,111,100,117,99,116,0,1,0,0,11,99,0,0,1,0,0,12,114,0,0, +0,1,8,58,109,97,116,52,120,51,0,18,99,0,59,120,0,18,114,0,59,120,0,48,0,18,99,0,59,121,0,18,114,0, +59,120,0,48,0,18,99,0,59,122,0,18,114,0,59,120,0,48,0,18,99,0,59,120,0,18,114,0,59,121,0,48,0,18, +99,0,59,121,0,18,114,0,59,121,0,48,0,18,99,0,59,122,0,18,114,0,59,121,0,48,0,18,99,0,59,120,0,18, +114,0,59,122,0,48,0,18,99,0,59,121,0,18,114,0,59,122,0,48,0,18,99,0,59,122,0,18,114,0,59,122,0,48, +0,18,99,0,59,120,0,18,114,0,59,119,0,48,0,18,99,0,59,121,0,18,114,0,59,119,0,48,0,18,99,0,59,122,0, +18,114,0,59,119,0,48,0,0,0,0,1,0,13,0,116,114,97,110,115,112,111,115,101,0,1,0,0,13,109,0,0,0,1,8, +58,109,97,116,50,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16, +8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,0,0,0,1,0,14,0,116,114,97,110,115,112,111, +115,101,0,1,0,0,14,109,0,0,0,1,8,58,109,97,116,51,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16, +10,49,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0, +16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18,109, +0,16,10,49,0,57,59,122,0,0,18,109,0,16,10,50,0,57,59,122,0,0,0,0,0,1,0,15,0,116,114,97,110,115,112, +111,115,101,0,1,0,0,15,109,0,0,0,1,8,58,109,97,116,52,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0, +16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,120,0,0,18,109,0,16,10,51,0,57,59,120,0,0,18, +109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,121,0,0, +18,109,0,16,10,51,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18,109,0,16,10,49,0,57,59,122,0, +0,18,109,0,16,10,50,0,57,59,122,0,0,18,109,0,16,10,51,0,57,59,122,0,0,18,109,0,16,8,48,0,57,59,119, +0,0,18,109,0,16,10,49,0,57,59,119,0,0,18,109,0,16,10,50,0,57,59,119,0,0,18,109,0,16,10,51,0,57,59, +119,0,0,0,0,0,1,0,26,0,116,114,97,110,115,112,111,115,101,0,1,0,0,27,109,0,0,0,1,8,58,109,97,116, +50,120,51,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,0, +57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50, +0,57,59,121,0,0,0,0,0,1,0,27,0,116,114,97,110,115,112,111,115,101,0,1,0,0,26,109,0,0,0,1,8,58,109, +97,116,51,120,50,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16, +8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18,109,0, +16,10,49,0,57,59,122,0,0,0,0,0,1,0,28,0,116,114,97,110,115,112,111,115,101,0,1,0,0,29,109,0,0,0,1, +8,58,109,97,116,50,120,52,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18, +109,0,16,10,50,0,57,59,120,0,0,18,109,0,16,10,51,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0, +18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59,121,0,0,18,109,0,16,10,51,0,57,59,121, +0,0,0,0,0,1,0,29,0,116,114,97,110,115,112,111,115,101,0,1,0,0,28,109,0,0,0,1,8,58,109,97,116,52, +120,50,0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,8,48,0,57, +59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18,109,0,16,10,49,0, +57,59,122,0,0,18,109,0,16,8,48,0,57,59,119,0,0,18,109,0,16,10,49,0,57,59,119,0,0,0,0,0,1,0,30,0, +116,114,97,110,115,112,111,115,101,0,1,0,0,31,109,0,0,0,1,8,58,109,97,116,51,120,52,0,18,109,0,16, +8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,120,0,0,18,109,0, +16,10,51,0,57,59,120,0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109, +0,16,10,50,0,57,59,121,0,0,18,109,0,16,10,51,0,57,59,121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18, +109,0,16,10,49,0,57,59,122,0,0,18,109,0,16,10,50,0,57,59,122,0,0,18,109,0,16,10,51,0,57,59,122,0,0, +0,0,0,1,0,31,0,116,114,97,110,115,112,111,115,101,0,1,0,0,30,109,0,0,0,1,8,58,109,97,116,52,120,51, +0,18,109,0,16,8,48,0,57,59,120,0,0,18,109,0,16,10,49,0,57,59,120,0,0,18,109,0,16,10,50,0,57,59,120, +0,0,18,109,0,16,8,48,0,57,59,121,0,0,18,109,0,16,10,49,0,57,59,121,0,0,18,109,0,16,10,50,0,57,59, +121,0,0,18,109,0,16,8,48,0,57,59,122,0,0,18,109,0,16,10,49,0,57,59,122,0,0,18,109,0,16,10,50,0,57, +59,122,0,0,18,109,0,16,8,48,0,57,59,119,0,0,18,109,0,16,10,49,0,57,59,119,0,0,18,109,0,16,10,50,0, +57,59,119,0,0,0,0,0,0 diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc b/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc new file mode 100644 index 000000000..7d516046a --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_fragment.gc @@ -0,0 +1,30 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.20, rev. 6 +// + +varying vec2 gl_PointCoord; + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h b/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h new file mode 100644 index 000000000..2400b273d --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_builtin_120_fragment_gc.h @@ -0,0 +1,5 @@ + +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */ +/* slang_builtin_120_fragment.gc */ + +3,2,2,3,10,1,103,108,95,80,111,105,110,116,67,111,111,114,100,0,0,0,0 diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_common_builtin.gc b/dist/Mesa/src/mesa/shader/slang/library/slang_common_builtin.gc new file mode 100644 index 000000000..45cf1c6fd --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_common_builtin.gc @@ -0,0 +1,1822 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.10, rev. 59 +// + +//bp: XXX these will probably go away since the value needs to be +//determined at runtime and may vary from one GLcontext to another... +const int gl_MaxLights = 8; +const int gl_MaxClipPlanes = 6; +const int gl_MaxTextureUnits = 8; +const int gl_MaxTextureCoords = 8; +const int gl_MaxVertexAttribs = 16; +const int gl_MaxVertexUniformComponents = 512; +const int gl_MaxVaryingFloats = 32; +const int gl_MaxVertexTextureImageUnits = 0; +const int gl_MaxCombinedTextureImageUnits = 2; +const int gl_MaxTextureImageUnits = 2; +const int gl_MaxFragmentUniformComponents = 64; +const int gl_MaxDrawBuffers = 1; + +uniform mat4 gl_ModelViewMatrix; +uniform mat4 gl_ProjectionMatrix; +uniform mat4 gl_ModelViewProjectionMatrix; +uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords]; + +uniform mat3 gl_NormalMatrix; +uniform mat3 __NormalMatrixTranspose; // Mesa only + +uniform mat4 gl_ModelViewMatrixInverse; +uniform mat4 gl_ProjectionMatrixInverse; +uniform mat4 gl_ModelViewProjectionMatrixInverse; +uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords]; + +uniform mat4 gl_ModelViewMatrixTranspose; +uniform mat4 gl_ProjectionMatrixTranspose; +uniform mat4 gl_ModelViewProjectionMatrixTranspose; +uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords]; + +uniform mat4 gl_ModelViewMatrixInverseTranspose; +uniform mat4 gl_ProjectionMatrixInverseTranspose; +uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose; +uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords]; + +uniform float gl_NormalScale; + +struct gl_DepthRangeParameters { + float near; + float far; + float diff; +}; + +uniform gl_DepthRangeParameters gl_DepthRange; + +uniform vec4 gl_ClipPlane[gl_MaxClipPlanes]; + +struct gl_PointParameters { + float size; + float sizeMin; + float sizeMax; + float fadeThresholdSize; + float distanceConstantAttenuation; + float distanceLinearAttenuation; + float distanceQuadraticAttenuation; +}; + +uniform gl_PointParameters gl_Point; + +struct gl_MaterialParameters { + vec4 emission; + vec4 ambient; + vec4 diffuse; + vec4 specular; + float shininess; +}; + +uniform gl_MaterialParameters gl_FrontMaterial; +uniform gl_MaterialParameters gl_BackMaterial; + +struct gl_LightSourceParameters { + vec4 ambient; + vec4 diffuse; + vec4 specular; + vec4 position; + vec4 halfVector; + vec3 spotDirection; + float spotExponent; + float spotCutoff; + float spotCosCutoff; + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; +}; + +uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights]; + +struct gl_LightModelParameters { + vec4 ambient; +}; + +uniform gl_LightModelParameters gl_LightModel; + +struct gl_LightModelProducts { + vec4 sceneColor; +}; + +uniform gl_LightModelProducts gl_FrontLightModelProduct; +uniform gl_LightModelProducts gl_BackLightModelProduct; + +struct gl_LightProducts { + vec4 ambient; + vec4 diffuse; + vec4 specular; +}; + +uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights]; +uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights]; + +uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits]; +uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords]; +uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords]; +uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords]; +uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords]; +uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords]; +uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords]; +uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords]; +uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords]; + +struct gl_FogParameters { + vec4 color; + float density; + float start; + float end; + float scale; +}; + +uniform gl_FogParameters gl_Fog; + + + + + +// +// 8.1 Angle and Trigonometry Functions +// + +//// radians + +float radians(const float deg) +{ + const float c = 3.1415926 / 180.0; + __asm vec4_multiply __retVal.x, deg, c; +} + +vec2 radians(const vec2 deg) +{ + const float c = 3.1415926 / 180.0; + __asm vec4_multiply __retVal.xy, deg.xy, c.xx; +} + +vec3 radians(const vec3 deg) +{ + const float c = 3.1415926 / 180.0; + __asm vec4_multiply __retVal.xyz, deg.xyz, c.xxx; +} + +vec4 radians(const vec4 deg) +{ + const float c = 3.1415926 / 180.0; + __asm vec4_multiply __retVal, deg, c.xxxx; +} + + +//// degrees + +float degrees(const float rad) +{ + const float c = 180.0 / 3.1415926; + __asm vec4_multiply __retVal.x, rad, c; +} + +vec2 degrees(const vec2 rad) +{ + const float c = 3.1415926 / 180.0; + __asm vec4_multiply __retVal.xy, rad.xy, c.xx; +} + +vec3 degrees(const vec3 rad) +{ + const float c = 3.1415926 / 180.0; + __asm vec4_multiply __retVal.xyz, rad.xyz, c.xxx; +} + +vec4 degrees(const vec4 rad) +{ + const float c = 3.1415926 / 180.0; + __asm vec4_multiply __retVal, rad, c.xxxx; +} + + +//// sin + +float sin(const float radians) +{ + __asm float_sine __retVal.x, radians; +} + +vec2 sin(const vec2 radians) +{ + __asm float_sine __retVal.x, radians.x; + __asm float_sine __retVal.y, radians.y; +} + +vec3 sin(const vec3 radians) +{ + __asm float_sine __retVal.x, radians.x; + __asm float_sine __retVal.y, radians.y; + __asm float_sine __retVal.z, radians.z; +} + +vec4 sin(const vec4 radians) +{ + __asm float_sine __retVal.x, radians.x; + __asm float_sine __retVal.y, radians.y; + __asm float_sine __retVal.z, radians.z; + __asm float_sine __retVal.w, radians.w; +} + + +//// cos + +float cos(const float radians) +{ + __asm float_cosine __retVal.x, radians; +} + +vec2 cos(const vec2 radians) +{ + __asm float_cosine __retVal.x, radians.x; + __asm float_cosine __retVal.y, radians.y; +} + +vec3 cos(const vec3 radians) +{ + __asm float_cosine __retVal.x, radians.x; + __asm float_cosine __retVal.y, radians.y; + __asm float_cosine __retVal.z, radians.z; +} + +vec4 cos(const vec4 radians) +{ + __asm float_cosine __retVal.x, radians.x; + __asm float_cosine __retVal.y, radians.y; + __asm float_cosine __retVal.z, radians.z; + __asm float_cosine __retVal.w, radians.w; +} + + + +//// tan + +float tan(const float angle) +{ + const float s = sin(angle); + const float c = cos(angle); + return s / c; +} + +vec2 tan(const vec2 angle) +{ + const vec2 s = sin(angle); + const vec2 c = cos(angle); + return s / c; +} + +vec3 tan(const vec3 angle) +{ + const vec3 s = sin(angle); + const vec3 c = cos(angle); + return s / c; +} + +vec4 tan(const vec4 angle) +{ + const vec4 s = sin(angle); + const vec4 c = cos(angle); + return s / c; +} + + + +float asin(const float x) +{ + const float a0 = 1.5707288; // PI/2? + const float a1 = -0.2121144; + const float a2 = 0.0742610; + //const float a3 = -0.0187293; + const float halfPi = 3.1415926 * 0.5; + const float y = abs(x); + // three terms seem to be enough: + __retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + a2 * y))) * sign(x); + // otherwise, try four: + //__retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + y * (a2 + y * a3)))) * sign(x); +} + +vec2 asin(const vec2 v) +{ + __retVal.x = asin(v.x); + __retVal.y = asin(v.y); +} + +vec3 asin(const vec3 v) +{ + __retVal.x = asin(v.x); + __retVal.y = asin(v.y); + __retVal.z = asin(v.z); +} + +vec4 asin(const vec4 v) +{ + __retVal.x = asin(v.x); + __retVal.y = asin(v.y); + __retVal.z = asin(v.z); +} + +float acos(const float x) +{ + const float halfPi = 3.1415926 * 0.5; + __retVal = halfPi - asin(x); +} + +vec2 acos(const vec2 v) +{ + __retVal.x = acos(v.x); + __retVal.y = acos(v.y); +} + +vec3 acos(const vec3 v) +{ + __retVal.x = acos(v.x); + __retVal.y = acos(v.y); + __retVal.z = acos(v.z); +} + +vec4 acos(const vec4 v) +{ + __retVal.x = acos(v.x); + __retVal.y = acos(v.y); + __retVal.z = acos(v.z); + __retVal.w = acos(v.w); +} + +float atan(const float x) +{ + __retVal = asin(x * inversesqrt(x * x + 1.0)); +} + +vec2 atan(const vec2 y_over_x) +{ + __retVal.x = atan(y_over_x.x); + __retVal.y = atan(y_over_x.y); +} + +vec3 atan(const vec3 y_over_x) +{ + __retVal.x = atan(y_over_x.x); + __retVal.y = atan(y_over_x.y); + __retVal.z = atan(y_over_x.z); +} + +vec4 atan(const vec4 y_over_x) +{ + __retVal.x = atan(y_over_x.x); + __retVal.y = atan(y_over_x.y); + __retVal.z = atan(y_over_x.z); + __retVal.w = atan(y_over_x.w); +} + +float atan(const float y, const float x) +{ + if (x == 0.0) + return 0.0; + float z = atan(y / x); + if (x < 0.0) + { + if (y < 0.0) + return z - 3.141593; + return z + 3.141593; + } + return z; +} + +vec2 atan(const vec2 u, const vec2 v) +{ + __retVal.x = atan(u.x, v.x); + __retVal.y = atan(u.y, v.y); +} + +vec3 atan(const vec3 u, const vec3 v) +{ + __retVal.x = atan(u.x, v.x); + __retVal.y = atan(u.y, v.y); + __retVal.z = atan(u.z, v.z); +} + +vec4 atan(const vec4 u, const vec4 v) +{ + __retVal.x = atan(u.x, v.x); + __retVal.y = atan(u.y, v.y); + __retVal.z = atan(u.z, v.z); + __retVal.w = atan(u.w, v.w); +} + + +// +// 8.2 Exponential Functions +// + +//// pow + +float pow(const float a, const float b) +{ + __asm float_power __retVal.x, a, b; +} + +vec2 pow(const vec2 a, const vec2 b) +{ + __asm float_power __retVal.x, a.x, b.x; + __asm float_power __retVal.y, a.y, b.y; +} + +vec3 pow(const vec3 a, const vec3 b) +{ + __asm float_power __retVal.x, a.x, b.x; + __asm float_power __retVal.y, a.y, b.y; + __asm float_power __retVal.z, a.z, b.z; +} + +vec4 pow(const vec4 a, const vec4 b) +{ + __asm float_power __retVal.x, a.x, b.x; + __asm float_power __retVal.y, a.y, b.y; + __asm float_power __retVal.z, a.z, b.z; + __asm float_power __retVal.w, a.w, b.w; +} + + +//// exp + +float exp(const float a) +{ + const float e = 2.71828; + __asm float_power __retVal, e, a; +} + +vec2 exp(const vec2 a) +{ + const float e = 2.71828; + __asm float_power __retVal.x, e, a.x; + __asm float_power __retVal.y, e, a.y; +} + +vec3 exp(const vec3 a) +{ + const float e = 2.71828; + __asm float_power __retVal.x, e, a.x; + __asm float_power __retVal.y, e, a.y; + __asm float_power __retVal.z, e, a.z; +} + +vec4 exp(const vec4 a) +{ + const float e = 2.71828; + __asm float_power __retVal.x, e, a.x; + __asm float_power __retVal.y, e, a.y; + __asm float_power __retVal.z, e, a.z; + __asm float_power __retVal.w, e, a.w; +} + + + +//// log2 + +float log2(const float x) +{ + __asm float_log2 __retVal.x, x; +} + +vec2 log2(const vec2 v) +{ + __asm float_log2 __retVal.x, v.x; + __asm float_log2 __retVal.y, v.y; +} + +vec3 log2(const vec3 v) +{ + __asm float_log2 __retVal.x, v.x; + __asm float_log2 __retVal.y, v.y; + __asm float_log2 __retVal.z, v.z; +} + +vec4 log2(const vec4 v) +{ + __asm float_log2 __retVal.x, v.x; + __asm float_log2 __retVal.y, v.y; + __asm float_log2 __retVal.z, v.z; + __asm float_log2 __retVal.w, v.w; +} + + +//// log (natural log) + +float log(const float x) +{ + // note: logBaseB(x) = logBaseN(x) / logBaseN(B) + // compute log(x) = log2(x) / log2(e) + // c = 1.0 / log2(e) = 0.693147181 + const float c = 0.693147181; + return log2(x) * c; +} + +vec2 log(const vec2 v) +{ + const float c = 0.693147181; + return log2(v) * c; +} + +vec3 log(const vec3 v) +{ + const float c = 0.693147181; + return log2(v) * c; +} + +vec4 log(const vec4 v) +{ + const float c = 0.693147181; + return log2(v) * c; +} + + +//// exp2 + +float exp2(const float a) +{ + __asm float_exp2 __retVal.x, a; +} + +vec2 exp2(const vec2 a) +{ + __asm float_exp2 __retVal.x, a.x; + __asm float_exp2 __retVal.y, a.y; +} + +vec3 exp2(const vec3 a) +{ + __asm float_exp2 __retVal.x, a.x; + __asm float_exp2 __retVal.y, a.y; + __asm float_exp2 __retVal.z, a.z; +} + +vec4 exp2(const vec4 a) +{ + __asm float_exp2 __retVal.x, a.x; + __asm float_exp2 __retVal.y, a.y; + __asm float_exp2 __retVal.z, a.z; + __asm float_exp2 __retVal.w, a.w; +} + + +//// sqrt + +float sqrt(const float x) +{ + float r; + __asm float_rsq r, x; + __asm float_rcp __retVal.x, r; +} + +vec2 sqrt(const vec2 v) +{ + float r; + __asm float_rsq r, v.x; + __asm float_rcp __retVal.x, r; + __asm float_rsq r, v.y; + __asm float_rcp __retVal.y, r; +} + +vec3 sqrt(const vec3 v) +{ + float r; + __asm float_rsq r, v.x; + __asm float_rcp __retVal.x, r; + __asm float_rsq r, v.y; + __asm float_rcp __retVal.y, r; + __asm float_rsq r, v.z; + __asm float_rcp __retVal.z, r; +} + +vec4 sqrt(const vec4 v) +{ + float r; + __asm float_rsq r, v.x; + __asm float_rcp __retVal.x, r; + __asm float_rsq r, v.y; + __asm float_rcp __retVal.y, r; + __asm float_rsq r, v.z; + __asm float_rcp __retVal.z, r; + __asm float_rsq r, v.w; + __asm float_rcp __retVal.w, r; +} + + +//// inversesqrt + +float inversesqrt(const float x) +{ + __asm float_rsq __retVal.x, x; +} + +vec2 inversesqrt(const vec2 v) +{ + __asm float_rsq __retVal.x, v.x; + __asm float_rsq __retVal.y, v.y; +} + +vec3 inversesqrt(const vec3 v) +{ + __asm float_rsq __retVal.x, v.x; + __asm float_rsq __retVal.y, v.y; + __asm float_rsq __retVal.z, v.z; +} + +vec4 inversesqrt(const vec4 v) +{ + __asm float_rsq __retVal.x, v.x; + __asm float_rsq __retVal.y, v.y; + __asm float_rsq __retVal.z, v.z; + __asm float_rsq __retVal.w, v.w; +} + + +//// normalize + +float normalize(const float x) +{ + __retVal.x = 1.0; +} + +vec2 normalize(const vec2 v) +{ + const float s = inversesqrt(dot(v, v)); + __asm vec4_multiply __retVal.xy, v, s.xx; +} + +vec3 normalize(const vec3 v) +{ +// const float s = inversesqrt(dot(v, v)); +// __retVal = v * s; +// XXX note, we _could_ use __retVal.w instead of tmp and and save a +// register, but that's actually a compilation error because v is a vec3 +// and the .w suffix is illegal. Oh well. + float tmp; + __asm vec3_dot tmp, v, v; + __asm float_rsq tmp, tmp; + __asm vec4_multiply __retVal.xyz, v, tmp.xxx; +} + +vec4 normalize(const vec4 v) +{ + float tmp; + __asm vec4_dot tmp, v, v; + __asm float_rsq tmp, tmp; + __asm vec4_multiply __retVal.xyz, v, tmp.xxx; +} + + + +// +// 8.3 Common Functions +// + + +//// abs + +float abs(const float a) +{ + __asm vec4_abs __retVal.x, a; +} + +vec2 abs(const vec2 a) +{ + __asm vec4_abs __retVal.xy, a; +} + +vec3 abs(const vec3 a) +{ + __asm vec4_abs __retVal.xyz, a; +} + +vec4 abs(const vec4 a) +{ + __asm vec4_abs __retVal, a; +} + + +//// sign + +float sign(const float x) +{ + float p, n; + __asm vec4_sgt p.x, x, 0.0; // p = (x > 0) + __asm vec4_sgt n.x, 0.0, x; // n = (x < 0) + __asm vec4_subtract __retVal.x, p, n; // sign = p - n +} + +vec2 sign(const vec2 v) +{ + vec2 p, n; + __asm vec4_sgt p.xy, v, 0.0; + __asm vec4_sgt n.xy, 0.0, v; + __asm vec4_subtract __retVal.xy, p, n; +} + +vec3 sign(const vec3 v) +{ + vec3 p, n; + __asm vec4_sgt p.xyz, v, 0.0; + __asm vec4_sgt n.xyz, 0.0, v; + __asm vec4_subtract __retVal.xyz, p, n; +} + +vec4 sign(const vec4 v) +{ + vec4 p, n; + __asm vec4_sgt p, v, 0.0; + __asm vec4_sgt n, 0.0, v; + __asm vec4_subtract __retVal, p, n; +} + + +//// floor + +float floor(const float a) +{ + __asm vec4_floor __retVal.x, a; +} + +vec2 floor(const vec2 a) +{ + __asm vec4_floor __retVal.xy, a; +} + +vec3 floor(const vec3 a) +{ + __asm vec4_floor __retVal.xyz, a; +} + +vec4 floor(const vec4 a) +{ + __asm vec4_floor __retVal, a; +} + + +//// ceil + +float ceil(const float a) +{ + // XXX this could be improved + float b = -a; + __asm vec4_floor b, b; + __retVal.x = -b; +} + +vec2 ceil(const vec2 a) +{ + vec2 b = -a; + __asm vec4_floor b, b; + __retVal.xy = -b; +} + +vec3 ceil(const vec3 a) +{ + vec3 b = -a; + __asm vec4_floor b, b; + __retVal.xyz = -b; +} + +vec4 ceil(const vec4 a) +{ + vec4 b = -a; + __asm vec4_floor b, b; + __retVal = -b; +} + + +//// fract + +float fract(const float a) +{ + __asm vec4_frac __retVal.x, a; +} + +vec2 fract(const vec2 a) +{ + __asm vec4_frac __retVal.xy, a; +} + +vec3 fract(const vec3 a) +{ + __asm vec4_frac __retVal.xyz, a; +} + +vec4 fract(const vec4 a) +{ + __asm vec4_frac __retVal, a; +} + + +//// mod (very untested!) + +float mod(const float a, const float b) +{ + float oneOverB; + __asm float_rcp oneOverB, b; + __retVal.x = a - b * floor(a * oneOverB); +} + +vec2 mod(const vec2 a, const float b) +{ + float oneOverB; + __asm float_rcp oneOverB, b; + __retVal.xy = a - b * floor(a * oneOverB); +} + +vec3 mod(const vec3 a, const float b) +{ + float oneOverB; + __asm float_rcp oneOverB, b; + __retVal.xyz = a - b * floor(a * oneOverB); +} + +vec4 mod(const vec4 a, const float b) +{ + float oneOverB; + __asm float_rcp oneOverB, b; + __retVal = a - b * floor(a * oneOverB); +} + +vec2 mod(const vec2 a, const vec2 b) +{ + float oneOverBx, oneOverBy; + __asm float_rcp oneOverBx, b.x; + __asm float_rcp oneOverBy, b.y; + __retVal.x = a.x - b.x * floor(a.x * oneOverBx); + __retVal.y = a.y - b.y * floor(a.y * oneOverBy); +} + +vec3 mod(const vec3 a, const vec3 b) +{ + float oneOverBx, oneOverBy, oneOverBz; + __asm float_rcp oneOverBx, b.x; + __asm float_rcp oneOverBy, b.y; + __asm float_rcp oneOverBz, b.z; + __retVal.x = a.x - b.x * floor(a.x * oneOverBx); + __retVal.y = a.y - b.y * floor(a.y * oneOverBy); + __retVal.z = a.z - b.z * floor(a.z * oneOverBz); +} + +vec4 mod(const vec4 a, const vec4 b) +{ + float oneOverBx, oneOverBy, oneOverBz, oneOverBw; + __asm float_rcp oneOverBx, b.x; + __asm float_rcp oneOverBy, b.y; + __asm float_rcp oneOverBz, b.z; + __asm float_rcp oneOverBw, b.w; + __retVal.x = a.x - b.x * floor(a.x * oneOverBx); + __retVal.y = a.y - b.y * floor(a.y * oneOverBy); + __retVal.z = a.z - b.z * floor(a.z * oneOverBz); + __retVal.w = a.w - b.w * floor(a.w * oneOverBw); +} + + +//// min + +float min(const float a, const float b) +{ + __asm vec4_min __retVal.x, a.x, b.x; +} + +vec2 min(const vec2 a, const vec2 b) +{ + __asm vec4_min __retVal.xy, a.xy, b.xy; +} + +vec3 min(const vec3 a, const vec3 b) +{ + __asm vec4_min __retVal.xyz, a.xyz, b.xyz; +} + +vec4 min(const vec4 a, const vec4 b) +{ + __asm vec4_min __retVal, a, b; +} + +vec2 min(const vec2 a, const float b) +{ + __asm vec4_min __retVal, a.xy, b.xx; +} + +vec3 min(const vec3 a, const float b) +{ + __asm vec4_min __retVal, a.xyz, b.xxx; +} + +vec4 min(const vec4 a, const float b) +{ + __asm vec4_min __retVal, a, b.xxxx; +} + + +//// max + +float max(const float a, const float b) +{ + __asm vec4_max __retVal.x, a.x, b.x; +} + +vec2 max(const vec2 a, const vec2 b) +{ + __asm vec4_max __retVal.xy, a.xy, b.xy; +} + +vec3 max(const vec3 a, const vec3 b) +{ + __asm vec4_max __retVal.xyz, a.xyz, b.xyz; +} + +vec4 max(const vec4 a, const vec4 b) +{ + __asm vec4_max __retVal, a, b; +} + +vec2 max(const vec2 a, const float b) +{ + __asm vec4_max __retVal, a.xy, b.xx; +} + +vec3 max(const vec3 a, const float b) +{ + __asm vec4_max __retVal, a.xyz, b.xxx; +} + +vec4 max(const vec4 a, const float b) +{ + __asm vec4_max __retVal, a, b.xxxx; +} + + +//// clamp + +float clamp(const float val, const float minVal, const float maxVal) +{ + __asm vec4_clamp __retVal, val, minVal, maxVal; +} + +vec2 clamp(const vec2 val, const float minVal, const float maxVal) +{ + __asm vec4_clamp __retVal, val, minVal, maxVal; +} + +vec3 clamp(const vec3 val, const float minVal, const float maxVal) +{ + __asm vec4_clamp __retVal, val, minVal, maxVal; +} + +vec4 clamp(const vec4 val, const float minVal, const float maxVal) +{ + __asm vec4_clamp __retVal, val, minVal, maxVal; +} + +vec2 clamp(const vec2 val, const vec2 minVal, const vec2 maxVal) +{ + __asm vec4_clamp __retVal, val, minVal, maxVal; +} + +vec3 clamp(const vec3 val, const vec3 minVal, const vec3 maxVal) +{ + __asm vec4_clamp __retVal, val, minVal, maxVal; +} + +vec4 clamp(const vec4 val, const vec4 minVal, const vec4 maxVal) +{ + __asm vec4_clamp __retVal, val, minVal, maxVal; +} + + +//// mix + +float mix(const float x, const float y, const float a) +{ + __asm vec4_lrp __retVal, a, y, x; +} + +vec2 mix(const vec2 x, const vec2 y, const float a) +{ + __asm vec4_lrp __retVal, a, y, x; +} + +vec3 mix(const vec3 x, const vec3 y, const float a) +{ + __asm vec4_lrp __retVal, a, y, x; +} + +vec4 mix(const vec4 x, const vec4 y, const float a) +{ + __asm vec4_lrp __retVal, a, y, x; +} + +vec2 mix(const vec2 x, const vec2 y, const vec2 a) +{ + __asm vec4_lrp __retVal, a, y, x; +} + +vec3 mix(const vec3 x, const vec3 y, const vec3 a) +{ + __asm vec4_lrp __retVal, a, y, x; +} + +vec4 mix(const vec4 x, const vec4 y, const vec4 a) +{ + __asm vec4_lrp __retVal, a, y, x; +} + + +//// step (untested) + +float step(const float edge, const float x) +{ + __asm vec4_sgt __retVal.x, x, edge; +} + +vec2 step(const vec2 edge, const vec2 x) +{ + __asm vec4_sgt __retVal.xy, x, edge; +} + +vec3 step(const vec3 edge, const vec3 x) +{ + __asm vec4_sgt __retVal.xyz, x, edge; +} + +vec4 step(const vec4 edge, const vec4 x) +{ + __asm vec4_sgt __retVal, x, edge; +} + +vec2 step(const float edge, const vec2 v) +{ + __asm vec4_sgt __retVal.xy, v, edge.xx; +} + +vec3 step(const float edge, const vec3 v) +{ + __asm vec4_sgt __retVal.xyz, v, edge.xxx; +} + +vec4 step(const float edge, const vec4 v) +{ + __asm vec4_sgt __retVal, v, edge.xxxx; +} + + +//// smoothstep (untested) + +float smoothstep(const float edge0, const float edge1, const float x) +{ + float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + +vec2 smoothstep(const vec2 edge0, const vec2 edge1, const vec2 v) +{ + vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + +vec3 smoothstep(const vec3 edge0, const vec3 edge1, const vec3 v) +{ + vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + +vec4 smoothstep(const vec4 edge0, const vec4 edge1, const vec4 v) +{ + vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + +vec2 smoothstep(const float edge0, const float edge1, const vec2 v) +{ + vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + +vec3 smoothstep(const float edge0, const float edge1, const vec3 v) +{ + vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + +vec4 smoothstep(const float edge0, const float edge1, const vec4 v) +{ + vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t); +} + + + +// +// 8.4 Geometric Functions +// + + +//// length + +float length(const float x) +{ + return abs(x); +} + +float length(const vec2 v) +{ + float r; + const float p = dot(v, v); // p = v.x * v.x + v.y * v.y + __asm float_rsq r, p; // r = 1 / sqrt(p) + __asm float_rcp __retVal.x, r; // retVal = 1 / r +} + +float length(const vec3 v) +{ + float r; + const float p = dot(v, v); // p = v.x * v.x + v.y * v.y + v.z * v.z + __asm float_rsq r, p; // r = 1 / sqrt(p) + __asm float_rcp __retVal.x, r; // retVal = 1 / r +} + +float length(const vec4 v) +{ + float r; + const float p = dot(v, v); // p = v.x * v.x + v.y * v.y + ... + __asm float_rsq r, p; // r = 1 / sqrt(p) + __asm float_rcp __retVal.x, r; // retVal = 1 / r +} + + +//// distance + +float distance(const float x, const float y) +{ + const float d = x - y; + __retVal = length(d); +} + +float distance(const vec2 v, const vec2 u) +{ + const vec2 d2 = v - u; + __retVal = length(d2); +} + +float distance(const vec3 v, const vec3 u) +{ + const vec3 d3 = v - u; + __retVal = length(d3); +} + +float distance(const vec4 v, const vec4 u) +{ + const vec4 d4 = v - u; + __retVal = length(d4); +} + + +//// cross + +vec3 cross(const vec3 v, const vec3 u) +{ + __asm vec3_cross __retVal.xyz, v, u; +} + + +//// faceforward + +float faceforward(const float N, const float I, const float Nref) +{ + // this could probably be done better + const float d = dot(Nref, I); + float s; + __asm vec4_sgt s.x, 0.0, d; // s = (0.0 > d) ? 1 : 0 + return mix(-N, N, s); +} + +vec2 faceforward(const vec2 N, const vec2 I, const vec2 Nref) +{ + // this could probably be done better + const float d = dot(Nref, I); + float s; + __asm vec4_sgt s.x, 0.0, d; // s = (0.0 > d) ? 1 : 0 + return mix(-N, N, s); +} + +vec3 faceforward(const vec3 N, const vec3 I, const vec3 Nref) +{ + // this could probably be done better + const float d = dot(Nref, I); + float s; + __asm vec4_sgt s.x, 0.0, d; // s = (0.0 > d) ? 1 : 0 + return mix(-N, N, s); +} + +vec4 faceforward(const vec4 N, const vec4 I, const vec4 Nref) +{ + // this could probably be done better + const float d = dot(Nref, I); + float s; + __asm vec4_sgt s.x, 0.0, d; // s = (0.0 > d) ? 1 : 0 + return mix(-N, N, s); +} + + +//// reflect + +float reflect(const float I, const float N) +{ + return I - 2.0 * dot(N, I) * N; +} + +vec2 reflect(const vec2 I, const vec2 N) +{ + return I - 2.0 * dot(N, I) * N; +} + +vec3 reflect(const vec3 I, const vec3 N) +{ + return I - 2.0 * dot(N, I) * N; +} + +vec4 reflect(const vec4 I, const vec4 N) +{ + return I - 2.0 * dot(N, I) * N; +} + +//// refract + +float refract(const float I, const float N, const float eta) +{ + float k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)); + if (k < 0.0) + return 0.0; + return eta * I - (eta * dot(N, I) + sqrt(k)) * N; +} + +vec2 refract(const vec2 I, const vec2 N, const float eta) +{ + float k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)); + if (k < 0.0) + return 0.0; + return eta * I - (eta * dot(N, I) + sqrt(k)) * N; +} + +vec3 refract(const vec3 I, const vec3 N, const float eta) +{ + float k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)); + if (k < 0.0) + return 0.0; + return eta * I - (eta * dot(N, I) + sqrt(k)) * N; +} + +vec4 refract(const vec4 I, const vec4 N, const float eta) +{ + float k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)); + if (k < 0.0) + return 0.0; + return eta * I - (eta * dot(N, I) + sqrt(k)) * N; +} + + + + +// +// 8.5 Matrix Functions +// + +mat2 matrixCompMult (mat2 m, mat2 n) { + return mat2 (m[0] * n[0], m[1] * n[1]); +} + +mat3 matrixCompMult (mat3 m, mat3 n) { + return mat3 (m[0] * n[0], m[1] * n[1], m[2] * n[2]); +} + +mat4 matrixCompMult (mat4 m, mat4 n) { + return mat4 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]); +} + + + + +// +// 8.6 Vector Relational Functions +// + +//// lessThan + +bvec2 lessThan(const vec2 u, const vec2 v) +{ + __asm vec4_slt __retVal.xy, u, v; +} + +bvec3 lessThan(const vec3 u, const vec3 v) +{ + __asm vec4_slt __retVal.xyz, u, v; +} + +bvec4 lessThan(const vec4 u, const vec4 v) +{ + __asm vec4_slt __retVal, u, v; +} + +bvec2 lessThan(const ivec2 u, const ivec2 v) +{ + __asm vec4_slt __retVal.xy, u, v; +} + +bvec3 lessThan(const ivec3 u, const ivec3 v) +{ + __asm vec4_slt __retVal.xyz, u, v; +} + +bvec4 lessThan(const ivec4 u, const ivec4 v) +{ + __asm vec4_slt __retVal, u, v; +} + + +//// lessThanEqual + +bvec2 lessThanEqual(const vec2 u, const vec2 v) +{ + __asm vec4_sle __retVal.xy, u, v; +} + +bvec3 lessThanEqual(const vec3 u, const vec3 v) +{ + __asm vec4_sle __retVal.xyz, u, v; +} + +bvec4 lessThanEqual(const vec4 u, const vec4 v) +{ + __asm vec4_sle __retVal, u, v; +} + +bvec2 lessThanEqual(const ivec2 u, const ivec2 v) +{ + __asm vec4_sle __retVal.xy, u, v; +} + +bvec3 lessThanEqual(const ivec3 u, const ivec3 v) +{ + __asm vec4_sle __retVal.xyz, u, v; +} + +bvec4 lessThanEqual(const ivec4 u, const ivec4 v) +{ + __asm vec4_sle __retVal, u, v; +} + + +//// greaterThan + +bvec2 greaterThan(const vec2 u, const vec2 v) +{ + __asm vec4_sgt __retVal.xy, u, v; +} + +bvec3 greaterThan(const vec3 u, const vec3 v) +{ + __asm vec4_sgt __retVal.xyz, u, v; +} + +bvec4 greaterThan(const vec4 u, const vec4 v) +{ + __asm vec4_sgt __retVal, u, v; +} + +bvec2 greaterThan(const ivec2 u, const ivec2 v) +{ + __asm vec4_sgt __retVal.xy, u, v; +} + +bvec3 greaterThan(const ivec3 u, const ivec3 v) +{ + __asm vec4_sgt __retVal.xyz, u, v; +} + +bvec4 greaterThan(const ivec4 u, const ivec4 v) +{ + __asm vec4_sgt __retVal, u, v; +} + + +//// greaterThanEqual + +bvec2 greaterThanEqual(const vec2 u, const vec2 v) +{ + __asm vec4_sge __retVal.xy, u, v; +} + +bvec3 greaterThanEqual(const vec3 u, const vec3 v) +{ + __asm vec4_sge __retVal.xyz, u, v; +} + +bvec4 greaterThanEqual(const vec4 u, const vec4 v) +{ + __asm vec4_sge __retVal, u, v; +} + +bvec2 greaterThanEqual(const ivec2 u, const ivec2 v) +{ + __asm vec4_sge __retVal.xy, u, v; +} + +bvec3 greaterThanEqual(const ivec3 u, const ivec3 v) +{ + __asm vec4_sge __retVal.xyz, u, v; +} + +bvec4 greaterThanEqual(const ivec4 u, const ivec4 v) +{ + __asm vec4_sge __retVal, u, v; +} + + +//// equal + +bvec2 equal(const vec2 u, const vec2 v) +{ + __asm vec4_seq __retVal.xy, u, v; +} + +bvec3 equal(const vec3 u, const vec3 v) +{ + __asm vec4_seq __retVal.xyz, u, v; +} + +bvec4 equal(const vec4 u, const vec4 v) +{ + __asm vec4_seq __retVal, u, v; +} + +bvec2 equal(const ivec2 u, const ivec2 v) +{ + __asm vec4_seq __retVal.xy, u, v; +} + +bvec3 equal(const ivec3 u, const ivec3 v) +{ + __asm vec4_seq __retVal.xyz, u, v; +} + +bvec4 equal(const ivec4 u, const ivec4 v) +{ + __asm vec4_seq __retVal, u, v; +} + + +//// notEqual + +bvec2 notEqual(const vec2 u, const vec2 v) +{ + __asm vec4_sne __retVal.xy, u, v; +} + +bvec3 notEqual(const vec3 u, const vec3 v) +{ + __asm vec4_sne __retVal.xyz, u, v; +} + +bvec4 notEqual(const vec4 u, const vec4 v) +{ + __asm vec4_sne __retVal, u, v; +} + +bvec2 notEqual(const ivec2 u, const ivec2 v) +{ + __asm vec4_sne __retVal.xy, u, v; +} + +bvec3 notEqual(const ivec3 u, const ivec3 v) +{ + __asm vec4_sne __retVal.xyz, u, v; +} + +bvec4 notEqual(const ivec4 u, const ivec4 v) +{ + __asm vec4_sne __retVal, u, v; +} + + +//// any + +bool any(const bvec2 v) +{ + float sum; + __asm vec4_add sum.x, v.x, v.y; + __asm vec4_sne __retVal.x, sum.x, 0.0; +} + +bool any(const bvec3 v) +{ + float sum; + __asm vec4_add sum.x, v.x, v.y; + __asm vec4_add sum.x, sum.x, v.z; + __asm vec4_sne __retVal.x, sum.x, 0.0; +} + +bool any(const bvec4 v) +{ + float sum; + __asm vec4_add sum.x, v.x, v.y; + __asm vec4_add sum.x, sum.x, v.z; + __asm vec4_add sum.x, sum.x, v.w; + __asm vec4_sne __retVal.x, sum.x, 0.0; +} + + +//// all + +bool all (const vec2 v) +{ + float prod; + __asm vec4_multiply prod.x, v.x, v.y; + __asm vec4_sne __retVal.x, prod.x, 0.0; + return v.x && v.y; +} + +bool all (const bvec3 v) +{ + float prod; + __asm vec4_multiply prod.x, v.x, v.y; + __asm vec4_multiply prod.x, prod.x, v.z; + __asm vec4_sne __retVal.x, prod.x, 0.0; +} + +bool all (const bvec4 v) +{ + float prod; + __asm vec4_multiply prod.x, v.x, v.y; + __asm vec4_multiply prod.x, prod.x, v.z; + __asm vec4_multiply prod.x, prod.x, v.w; + __asm vec4_sne __retVal.x, prod.x, 0.0; +} + + + +//// not + +bvec2 not (const bvec2 v) +{ + __asm vec4_seq __retVal.xy, v, 0.0; +} + +bvec3 not (const bvec3 v) +{ + __asm vec4_seq __retVal.xyz, v, 0.0; +} + +bvec4 not (const bvec4 v) +{ + __asm vec4_seq __retVal, v, 0.0; +} + + + +//// Texture Lookup Functions (for both fragment and vertex shaders) + +vec4 texture1D(const sampler1D sampler, const float coord) +{ + __asm vec4_tex1d __retVal, sampler, coord; +} + +vec4 texture1DProj(const sampler1D sampler, const vec2 coord) +{ + // need to swizzle .y into .w + __asm vec4_texp1d __retVal, sampler, coord.xyyy; +} + +vec4 texture1DProj(const sampler1D sampler, const vec4 coord) +{ + __asm vec4_texp1d __retVal, sampler, coord; +} + + +vec4 texture2D(const sampler2D sampler, const vec2 coord) +{ + __asm vec4_tex2d __retVal, sampler, coord; +} + +vec4 texture2DProj(const sampler2D sampler, const vec3 coord) +{ + // need to swizzle 'z' into 'w'. + __asm vec4_texp2d __retVal, sampler, coord.xyzz; +} + +vec4 texture2DProj(const sampler2D sampler, const vec4 coord) +{ + __asm vec4_texp2d __retVal, sampler, coord; +} + + +vec4 texture3D(const sampler3D sampler, const vec3 coord) +{ + __asm vec4_tex3d __retVal, sampler, coord; +} + +vec4 texture3DProj(const sampler3D sampler, const vec4 coord) +{ + __asm vec4_texp3d __retVal, sampler, coord; +} + + +vec4 textureCube(const samplerCube sampler, const vec3 coord) +{ + __asm vec4_texcube __retVal, sampler, coord; +} + + + +vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord) +{ + __asm vec4_tex1d __retVal, sampler, coord; +} + +vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord) +{ + // .s and .p will be divided by .q + __asm vec4_texp1d __retVal, sampler, coord; +} + +vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord) +{ + __asm vec4_tex2d __retVal, sampler, coord; +} + +vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord) +{ + // .s, .t and .p will be divided by .q + __asm vec4_texp2d __retVal, sampler, coord; +} + + +//// GL_ARB_texture_rectangle: +vec4 texture2DRect(const sampler2DRect sampler, const vec2 coord) +{ + __asm vec4_tex_rect __retVal, sampler, coord; +} + +vec4 texture2DRectProj(const sampler2DRect sampler, const vec3 coord) +{ + // need to swizzle .y into .w + __asm vec4_texp_rect __retVal, sampler, coord.xyzz; +} + +vec4 texture2DRectProj(const sampler2DRect sampler, const vec4 coord) +{ + __asm vec4_texp_rect __retVal, sampler, ccoord; +} + +vec4 shadow2DRect(const sampler2DRectShadow sampler, const vec3 coord) +{ + __asm vec4_tex_rect __retVal, sampler, coord; +} + +vec4 shadow2DRectProj(const sampler2DRectShadow sampler, const vec4 coord) +{ + __asm vec4_texp_rect __retVal, sampler, coord; +} + + + +// +// 8.9 Noise Functions +// +// AUTHOR: Stefan Gustavson (stegu@itn.liu.se), Nov 26, 2005 +// + +float noise1(const float x) +{ + __asm float_noise1 __retVal, x; +} + + +float noise1(const vec2 x) +{ + __asm float_noise2 __retVal, x; +} + +float noise1(const vec3 x) +{ + __asm float_noise3 __retVal, x; +} + +float noise1(const vec4 x) +{ + __asm float_noise4 __retVal, x; +} + +vec2 noise2(const float x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + 19.34); +} + +vec2 noise2(const vec2 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec2(19.34, 7.66)); +} + +vec2 noise2(const vec3 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23)); +} + +vec2 noise2(const vec4 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77)); +} + +vec3 noise3(const float x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + 19.34); + __retVal.z = noise1(x + 5.47); +} + +vec3 noise3(const vec2 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec2(19.34, 7.66)); + __retVal.z = noise1(x + vec2(5.47, 17.85)); +} + +vec3 noise3(const vec3 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23)); + __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04)); +} + +vec3 noise3(const vec4 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77)); + __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19)); +} + +vec4 noise4(const float x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + 19.34); + __retVal.z = noise1(x + 5.47); + __retVal.w = noise1(x + 23.54); +} + +vec4 noise4(const vec2 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec2 (19.34, 7.66)); + __retVal.z = noise1(x + vec2 (5.47, 17.85)); + __retVal.w = noise1(x + vec2 (23.54, 29.11)); +} + +vec4 noise4(const vec3 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23)); + __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04)); + __retVal.w = noise1(x + vec3(23.54, 29.11, 31.91)); +} + +vec4 noise4(const vec4 x) +{ + __retVal.x = noise1(x); + __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77)); + __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19)); + __retVal.w = noise1(x + vec4(23.54, 29.11, 31.91, 37.48)); +} diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_core.gc b/dist/Mesa/src/mesa/shader/slang/library/slang_core.gc new file mode 100644 index 000000000..4639660ba --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_core.gc @@ -0,0 +1,2634 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// This file defines nearly all constructors and operators for built-in data +// types, using extended language syntax. In general, compiler treats +// constructors and operators as ordinary functions with some exceptions. +// For example, the language does not allow functions to be called in +// constant expressions - here the exception is made to allow it. +// +// Each implementation provides its own version of this file. Each +// implementation can define the required set of operators and constructors +// in its own fashion. +// +// The extended language syntax is only present when compiling this file. +// It is implicitly included at the very beginning of the compiled shader, +// so no built-in functions can be used. +// +// To communicate with the implementation, a special extended "__asm" keyword +// is used, followed by an instruction name (any valid identifier), a +// destination variable identifier and a list of zero or more source +// variable identifiers. +// +// A variable identifier is a variable name declared earlier in the code +// (as a function parameter, local or global variable). +// +// An instruction name designates an instruction that must be exported +// by the implementation. Each instruction receives data from source +// variable identifiers and returns data in the destination variable +// identifier. +// +// It is up to the implementation how to define a particular operator +// or constructor. If it is expected to being used rarely, it can be +// defined in terms of other operators and constructors, +// for example: +// +// ivec2 __operator + (const ivec2 x, const ivec2 y) { +// return ivec2 (x[0] + y[0], x[1] + y[1]); +// } +// +// If a particular operator or constructor is expected to be used very +// often or is an atomic operation (that is, an operation that cannot be +// expressed in terms of other operations or would create a dependency +// cycle) it must be defined using one or more __asm constructs. +// +// Each implementation must define constructors for all scalar types +// (bool, float, int). There are 9 scalar-to-scalar constructors +// (including identity constructors). However, since the language +// introduces special constructors (like matrix constructor with a single +// scalar value), implementations must also implement these cases. +// The compiler provides the following algorithm when resolving a constructor: +// - try to find a constructor with a prototype matching ours, +// - if no constructor is found and this is a scalar-to-scalar constructor, +// raise an error, +// - if a constructor is found, execute it and return, +// - count the size of the constructor parameter list - if it is less than +// the size of our constructor's type, raise an error, +// - for each parameter in the list do a recursive constructor matching for +// appropriate scalar fields in the constructed variable, +// +// Each implementation must also define a set of operators that deal with +// built-in data types. +// There are four kinds of operators: +// 1) Operators that are implemented only by the compiler: "()" (function +// call), "," (sequence) and "?:" (selection). +// 2) Operators that are implemented by the compiler by expressing it in +// terms of other operators: +// - "." (field selection) - translated to subscript access, +// - "&&" (logical and) - translated to "<left_expr> ? <right_expr> : +// false", +// - "||" (logical or) - translated to "<left_expr> ? true : <right_expr>", +// 3) Operators that can be defined by the implementation and if the required +// prototype is not found, standard behaviour is used: +// - "==", "!=", "=" (equality, assignment) - compare or assign +// matching fields one-by-one; +// note that at least operators for scalar data types must be defined +// by the implementation to get it work, +// 4) All other operators not mentioned above. If no required prototype is +// found, an error is raised. An implementation must follow the language +// specification to provide all valid operator prototypes. +// + + + +//// Basic, scalar constructors/casts + +int __constructor(const float f) +{ + __asm float_to_int __retVal, f; +} + +bool __constructor(const int i) +{ + const float zero = 0.0; + __asm vec4_seq __retVal, i, zero; +} + +bool __constructor(const float f) +{ + const float zero = 0.0; + __asm vec4_seq __retVal, i, zero; +} + +int __constructor(const bool b) +{ + __retVal = b; +} + +float __constructor(const bool b) +{ + __retVal = b; +} + +float __constructor(const int i) +{ + __asm int_to_float __retVal, i; +} + +bool __constructor(const bool b) +{ + __retVal = b; +} + +int __constructor(const int i) +{ + __retVal = i; +} + +float __constructor(const float f) +{ + __retVal = f; +} + + +//// vec2 constructors + +vec2 __constructor(const float x, const float y) +{ + __retVal.x = x; + __retVal.y = y; +} + +vec2 __constructor(const float f) +{ + __retVal.xy = f.xx; +} + +vec2 __constructor(const int i) +{ + __retVal.xy = i.xx; +} + +vec2 __constructor(const bool b) +{ + __retVal.xy = b.xx; +} + +vec2 __constructor(const vec3 v) +{ + __retVal.xy = v.xy; +} + +vec2 __constructor(const vec4 v) +{ + __retVal.xy = v.xy; +} + + +//// vec3 constructors + +vec3 __constructor(const float x, const float y, const float z) +{ + __retVal.x = x; + __retVal.y = y; + __retVal.z = z; +} + +vec3 __constructor(const float f) +{ + __retVal.xyz = f.xxx; +} + +vec3 __constructor(const int i) +{ + __asm int_to_float __retVal.xyz, i.xxx; +} + +vec3 __constructor(const bool b) +{ + __retVal.xyz = b.xxx; +} + +vec3 __constructor(const vec4 v) +{ + __retVal.xyz = v.xyz; +} + + +//// vec4 constructors + +vec4 __constructor(const float x, const float y, const float z, const float w) +{ + __retVal.x = x; + __retVal.y = y; + __retVal.z = z; + __retVal.w = w; +} + +vec4 __constructor(const float f) +{ + __retVal = f.xxxx; +} + +vec4 __constructor(const int i) +{ + __retVal = i.xxxx; +} + +vec4 __constructor(const bool b) +{ + __retVal = b.xxxx; +} + +vec4 __constructor(const vec3 v3, const float f) +{ + // XXX this constructor shouldn't be needed anymore + __retVal.xyz = v3; + __retVal.w = f; +} + + +//// ivec2 constructors + +ivec2 __constructor(const int i, const int j) +{ + __retVal.x = i; + __retVal.y = j; +} + +ivec2 __constructor(const int i) +{ + __retVal.xy = i.xx; +} + +ivec2 __constructor(const float f) +{ + __asm float_to_int __retVal.xy, f.xx; +} + +ivec2 __constructor(const bool b) +{ + __asm float_to_int __retVal.xy, b.xx; +} + + +//// ivec3 constructors + +ivec3 __constructor(const int i, const int j, const int k) +{ + __retVal.x = i; + __retVal.y = j; + __retVal.z = k; +} + +ivec3 __constructor(const int i) +{ + __retVal.xyz = i.xxx; +} + +ivec3 __constructor(const float f) +{ + __retVal.xyz = f.xxx; +} + +ivec3 __constructor(const bool b) +{ + __retVal.xyz = b.xxx; +} + + +//// ivec4 constructors + +ivec4 __constructor(const int x, const int y, const int z, const int w) +{ + __retVal.x = x; + __retVal.y = y; + __retVal.z = z; + __retVal.w = w; +} + +ivec4 __constructor(const int i) +{ + __retVal = i.xxxx; +} + +ivec4 __constructor(const float f) +{ + __asm float_to_int __retVal, f.xxxx; +} + +ivec4 __constructor(const bool b) +{ + __retVal = b.xxxx; +} + + +//// bvec2 constructors + +bvec2 __constructor(const bool b1, const bool b2) +{ + __retVal.x = b1; + __retVal.y = b2; +} + +bvec2 __constructor(const bool b) +{ + __retVal.xy = b.xx; +} + +bvec2 __constructor(const float f) +{ + const vec2 zero = vec2(0.0, 0.0); + __asm vec4_seq __retVal.xy, f.xx, zero; +} + +bvec2 __constructor(const int i) +{ + const ivec2 zero = ivec2(0, 0); + __asm vec4_seq __retVal.xy, i.xx, zero; +} + + +//// bvec3 constructors + +bvec3 __constructor(const bool b1, const bool b2, const bool b3) +{ + __retVal.x = b1; + __retVal.y = b2; + __retVal.z = b3; +} + +bvec3 __constructor(const bool b) +{ + __retVal.xyz = b.xxx; +} + +bvec3 __constructor(const float f) +{ + const vec3 zero = vec3(0.0, 0.0, 0.0); + __asm vec4_seq __retVal.xyz, f.xxx, zero; +} + +bvec3 __constructor(const int i) +{ + const ivec3 zero = ivec3(0, 0, 0); + __asm vec4_seq __retVal.xyz, i.xxx, zero; +} + + +//// bvec4 constructors + +bvec4 __constructor(const bool b1, const bool b2, const bool b3, const bool b4) +{ + __retVal.x = b1; + __retVal.y = b2; + __retVal.z = b3; + __retVal.w = b4; +} + +bvec4 __constructor(const bool b) +{ + __retVal.xyzw = b.xxxx; +} + +bvec4 __constructor(const float f) +{ + const vec4 zero = vec4(0.0, 0.0, 0.0, 0.0); + __asm vec4_seq __retVal, f.xxxx, zero; +} + +bvec4 __constructor(const int i) +{ + const ivec4 zero = ivec4(0, 0, 0, 0); + __asm vec4_seq __retVal, i.xxxx, zero; +} + + + +//// mat2 constructors + +mat2 __constructor(const float m00, const float m10, + const float m01, const float m11) +{ + __retVal[0].x = m00; + __retVal[0].y = m10; + __retVal[1].x = m01; + __retVal[1].y = m11; +} + +mat2 __constructor(const float f) +{ + __retVal[0].x = f; + __retVal[0].y = 0.0; + __retVal[1].x = 0.0; + __retVal[1].y = f; +} + +mat2 __constructor(const int i) +{ + return mat2(float(i)); +} + +mat2 __constructor(const bool b) +{ + return mat2(float(b)); +} + +mat2 __constructor(const vec2 c0, const vec2 c1) +{ + __retVal[0] = c0; + __retVal[1] = c1; +} + + +//// mat3 constructors + +mat3 __constructor(const float m00, const float m10, const float m20, + const float m01, const float m11, const float m21, + const float m02, const float m12, const float m22) +{ + __retVal[0].x = m00; + __retVal[0].y = m10; + __retVal[0].z = m20; + __retVal[1].x = m01; + __retVal[1].y = m11; + __retVal[1].z = m21; + __retVal[2].x = m02; + __retVal[2].y = m12; + __retVal[2].z = m22; +} + +mat3 __constructor(const float f) +{ + vec2 v = vec2(f, 0.0); + __retVal[0] = v.xyy; + __retVal[1] = v.yxy; + __retVal[2] = v.yyx; +} + +mat3 __constructor(const int i) +{ + return mat3(float(i)); +} + +mat3 __constructor(const bool b) +{ + return mat3(float(b)); +} + +mat3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2) +{ + __retVal[0] = c0; + __retVal[1] = c1; + __retVal[2] = c2; +} + + +//// mat4 constructors + +mat4 __constructor(const float m00, const float m10, const float m20, const float m30, + const float m01, const float m11, const float m21, const float m31, + const float m02, const float m12, const float m22, const float m32, + const float m03, const float m13, const float m23, const float m33) +{ + __retVal[0].x = m00; + __retVal[0].y = m10; + __retVal[0].z = m20; + __retVal[0].w = m30; + __retVal[1].x = m01; + __retVal[1].y = m11; + __retVal[1].z = m21; + __retVal[1].w = m31; + __retVal[2].x = m02; + __retVal[2].y = m12; + __retVal[2].z = m22; + __retVal[2].w = m32; + __retVal[3].x = m03; + __retVal[3].y = m13; + __retVal[3].z = m23; + __retVal[3].w = m33; +} + + +mat4 __constructor(const float f) +{ + vec2 v = vec2(f, 0.0); + __retVal[0] = v.xyyy; + __retVal[1] = v.yxyy; + __retVal[2] = v.yyxy; + __retVal[3] = v.yyyx; +} + +mat4 __constructor(const int i) +{ + return mat4(float(i)); +} + +mat4 __constructor(const bool b) +{ + return mat4(float(b)); +} + +mat4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2, const vec4 c3) +{ + __retVal[0] = c0; + __retVal[1] = c1; + __retVal[2] = c2; + __retVal[3] = c3; +} + + + +//// Basic int operators + +int __operator + (const int a, const int b) +{ +// XXX If we ever have int registers, we'll do something like this: +// XXX For now, mostly treat ints as floats. +// float x, y; +// __asm int_to_float x, a; +// __asm int_to_float y, b; +// __asm vec4_add x.x, x.x, y.x; +// __asm float_to_int __retVal, x; + float x; + __asm vec4_add x, a, b; + __asm float_to_int __retVal, x; +} + +int __operator - (const int a, const int b) +{ + float x; + __asm vec4_subtract x, a, b; + __asm float_to_int __retVal, x; +} + +int __operator * (const int a, const int b) +{ + float x; + __asm vec4_multiply x, a, b; + __asm float_to_int __retVal, x; +} + +int __operator / (const int a, const int b) +{ + float bInv, x; + __asm float_rcp bInv, b; + __asm vec4_multiply x, a, bInv; + __asm float_to_int __retVal, x; +} + + +//// Basic ivec2 operators + +ivec2 __operator + (const ivec2 a, const ivec2 b) +{ + vec2 x; + __asm vec4_add x, a, b; + __asm float_to_int __retVal, x; +} + +ivec2 __operator - (const ivec2 a, const ivec2 b) +{ + vec2 x; + __asm vec4_subtract x, a, b; + __asm float_to_int __retVal, x; +} + +ivec2 __operator * (const ivec2 a, const ivec2 b) +{ + vec2 x; + __asm vec4_multiply x, a, b; + __asm float_to_int __retVal, x; +} + +ivec2 __operator / (const ivec2 a, const ivec2 b) +{ + vec2 bInv, x; + __asm float_rcp bInv.x, b.x; + __asm float_rcp bInv.y, b.y; + __asm vec4_multiply x, a, bInv; + __asm float_to_int __retVal, x; +} + + +//// Basic ivec3 operators + +ivec3 __operator + (const ivec3 a, const ivec3 b) +{ + vec3 x; + __asm vec4_add x, a, b; + __asm float_to_int __retVal, x; +} + +ivec3 __operator - (const ivec3 a, const ivec3 b) +{ + vec3 x; + __asm vec4_subtract x, a, b; + __asm float_to_int __retVal, x; +} + +ivec3 __operator * (const ivec3 a, const ivec3 b) +{ + vec3 x; + __asm vec4_multiply x, a, b; + __asm float_to_int __retVal, x; +} + +ivec3 __operator / (const ivec3 a, const ivec3 b) +{ + vec3 bInv, x; + __asm float_rcp bInv.x, b.x; + __asm float_rcp bInv.y, b.y; + __asm float_rcp bInv.z, b.z; + __asm vec4_multiply x, a, bInv; + __asm float_to_int __retVal, x; +} + + +//// Basic ivec4 operators + +ivec4 __operator + (const ivec4 a, const ivec4 b) +{ + vec3 x; + __asm vec4_add x, a, b; + __asm float_to_int __retVal, x; +} + +ivec4 __operator - (const ivec4 a, const ivec4 b) +{ + vec4 x; + __asm vec4_subtract x, a, b; + __asm float_to_int __retVal, x; +} + +ivec4 __operator * (const ivec4 a, const ivec4 b) +{ + vec4 x; + __asm vec4_multiply x, a, b; + __asm float_to_int __retVal, x; +} + +ivec4 __operator / (const ivec4 a, const ivec4 b) +{ + vec4 bInv, x; + __asm float_rcp bInv.x, b.x; + __asm float_rcp bInv.y, b.y; + __asm float_rcp bInv.z, b.z; + __asm float_rcp bInv.w, b.w; + __asm vec4_multiply x, a, bInv; + __asm float_to_int __retVal, x; +} + + +//// Basic float operators + +float __operator + (const float a, const float b) +{ + __asm vec4_add __retVal.x, a, b; +} + +float __operator - (const float a, const float b) +{ + __asm vec4_subtract __retVal.x, a, b; +} + +float __operator * (const float a, const float b) +{ + __asm vec4_multiply __retVal.x, a, b; +} + +float __operator / (const float a, const float b) +{ + float bInv; + __asm float_rcp bInv.x, b.x; + __asm vec4_multiply __retVal.x, a, bInv; +} + + +//// Basic vec2 operators + +vec2 __operator + (const vec2 v, const vec2 u) +{ + __asm vec4_add __retVal.xy, v, u; +} + +vec2 __operator - (const vec2 v, const vec2 u) +{ + __asm vec4_subtract __retVal.xy, v, u; +} + +vec2 __operator * (const vec2 v, const vec2 u) +{ + __asm vec4_multiply __retVal.xy, v, u; +} + +vec2 __operator / (const vec2 v, const vec2 u) +{ + vec2 w; // = 1 / u + __asm float_rcp w.x, u.x; + __asm float_rcp w.y, u.y; + __asm vec4_multiply __retVal.xy, v, w; +} + + +//// Basic vec3 operators + +vec3 __operator + (const vec3 v, const vec3 u) +{ + __asm vec4_add __retVal.xyz, v, u; +} + +vec3 __operator - (const vec3 v, const vec3 u) +{ + __asm vec4_subtract __retVal.xyz, v, u; +} + +vec3 __operator * (const vec3 v, const vec3 u) +{ + __asm vec4_multiply __retVal.xyz, v, u; +} + +vec3 __operator / (const vec3 v, const vec3 u) +{ + vec3 w; // = 1 / u + __asm float_rcp w.x, u.x; + __asm float_rcp w.y, u.y; + __asm float_rcp w.z, u.z; + __asm vec4_multiply __retVal.xyz, v, w; +} + + +//// Basic vec4 operators + +vec4 __operator + (const vec4 v, const vec4 u) +{ + __asm vec4_add __retVal, v, u; +} + +vec4 __operator - (const vec4 v, const vec4 u) +{ + __asm vec4_subtract __retVal, v, u; +} + +vec4 __operator * (const vec4 v, const vec4 u) +{ + __asm vec4_multiply __retVal, v, u; +} + +vec4 __operator / (const vec4 v, const vec4 u) +{ + vec4 w; // = 1 / u + __asm float_rcp w.x, u.x; + __asm float_rcp w.y, u.y; + __asm float_rcp w.z, u.z; + __asm float_rcp w.w, u.w; + __asm vec4_multiply __retVal, v, w; +} + + + + +//// Basic vec2/float operators + +vec2 __operator + (const float a, const vec2 u) +{ + __asm vec4_add __retVal.xy, a.xx, u.xy; +} + +vec2 __operator + (const vec2 v, const float b) +{ + __asm vec4_add __retVal.xy, v.xy, b.xx; +} + +vec2 __operator - (const float a, const vec2 u) +{ + __asm vec4_subtract __retVal.xy, a.xx, u.xy; +} + +vec2 __operator - (const vec2 v, const float b) +{ + __asm vec4_subtract __retVal.xy, v.xy, b.xx; +} + +vec2 __operator * (const float a, const vec2 u) +{ + __asm vec4_multiply __retVal.xy, a.xx, u.xy; +} + +vec2 __operator * (const vec2 v, const float b) +{ + __asm vec4_multiply __retVal.xy, v.xy, b.xx; +} + +vec2 __operator / (const float a, const vec2 u) +{ + vec2 invU; + __asm float_rcp invU.x, u.x; + __asm float_rcp invU.y, u.y; + __asm vec4_multiply __retVal.xy, a.xx, invU.xy; +} + +vec2 __operator / (const vec2 v, const float b) +{ + float invB; + __asm float_rcp invB, b; + __asm vec4_multiply __retVal.xy, v.xy, invB.xx; +} + + +//// Basic vec3/float operators + +vec3 __operator + (const float a, const vec3 u) +{ + __asm vec4_add __retVal.xyz, a.xxx, u.xyz; +} + +vec3 __operator + (const vec3 v, const float b) +{ + __asm vec4_add __retVal.xyz, v.xyz, b.xxx; +} + +vec3 __operator - (const float a, const vec3 u) +{ + __asm vec4_subtract __retVal.xyz, a.xxx, u.xyz; +} + +vec3 __operator - (const vec3 v, const float b) +{ + __asm vec4_subtract __retVal.xyz, v.xyz, b.xxx; +} + +vec3 __operator * (const float a, const vec3 u) +{ + __asm vec4_multiply __retVal.xyz, a.xxx, u.xyz; +} + +vec3 __operator * (const vec3 v, const float b) +{ + __asm vec4_multiply __retVal.xyz, v.xyz, b.xxx; +} + +vec3 __operator / (const float a, const vec3 u) +{ + vec3 invU; + __asm float_rcp invU.x, u.x; + __asm float_rcp invU.y, u.y; + __asm float_rcp invU.z, u.z; + __asm vec4_multiply __retVal.xyz, a.xxx, invU.xyz; +} + +vec3 __operator / (const vec3 v, const float b) +{ + float invB; + __asm float_rcp invB, b; + __asm vec4_multiply __retVal.xyz, v.xyz, invB.xxx; +} + + +//// Basic vec4/float operators + +vec4 __operator + (const float a, const vec4 u) +{ + __asm vec4_add __retVal, a.xxxx, u; +} + +vec4 __operator + (const vec4 v, const float b) +{ + __asm vec4_add __retVal, v, b.xxxx; +} + +vec4 __operator - (const float a, const vec4 u) +{ + __asm vec4_subtract __retVal, a.xxxx, u; +} + +vec4 __operator - (const vec4 v, const float b) +{ + __asm vec4_subtract __retVal, v, b.xxxx; +} + +vec4 __operator * (const float a, const vec4 u) +{ + __asm vec4_multiply __retVal, a.xxxx, u; +} + +vec4 __operator * (const vec4 v, const float b) +{ + __asm vec4_multiply __retVal, v, b.xxxx; +} + +vec4 __operator / (const float a, const vec4 u) +{ + vec4 invU; + __asm float_rcp invU.x, u.x; + __asm float_rcp invU.y, u.y; + __asm float_rcp invU.z, u.z; + __asm float_rcp invU.w, u.w; + __asm vec4_multiply __retVal, a.xxxx, invU; +} + +vec4 __operator / (const vec4 v, const float b) +{ + float invB; + __asm float_rcp invB, b; + __asm vec4_multiply __retVal, v, invB.xxxx; +} + + + +//// Basic ivec2/int operators + +ivec2 __operator + (const int a, const ivec2 u) +{ + __retVal = ivec2(a) + u; +} + +ivec2 __operator + (const ivec2 v, const int b) +{ + __retVal = v + ivec2(b); +} + +ivec2 __operator - (const int a, const ivec2 u) +{ + __retVal = ivec2(a) - u; +} + +ivec2 __operator - (const ivec2 v, const int b) +{ + __retVal = v - ivec2(b); +} + +ivec2 __operator * (const int a, const ivec2 u) +{ + __retVal = ivec2(a) * u; +} + +ivec2 __operator * (const ivec2 v, const int b) +{ + __retVal = v * ivec2(b); +} + +ivec2 __operator / (const int a, const ivec2 u) +{ + __retVal = ivec2(a) / u; +} + +ivec2 __operator / (const ivec2 v, const int b) +{ + __retVal = v / ivec2(b); +} + + +//// Basic ivec3/int operators + +ivec3 __operator + (const int a, const ivec3 u) +{ + __retVal = ivec3(a) + u; +} + +ivec3 __operator + (const ivec3 v, const int b) +{ + __retVal = v + ivec3(b); +} + +ivec3 __operator - (const int a, const ivec3 u) +{ + __retVal = ivec3(a) - u; +} + +ivec3 __operator - (const ivec3 v, const int b) +{ + __retVal = v - ivec3(b); +} + +ivec3 __operator * (const int a, const ivec3 u) +{ + __retVal = ivec3(a) * u; +} + +ivec3 __operator * (const ivec3 v, const int b) +{ + __retVal = v * ivec3(b); +} + +ivec3 __operator / (const int a, const ivec3 u) +{ + __retVal = ivec3(a) / u; +} + +ivec3 __operator / (const ivec3 v, const int b) +{ + __retVal = v / ivec3(b); +} + + +//// Basic ivec4/int operators + +ivec4 __operator + (const int a, const ivec4 u) +{ + __retVal = ivec4(a) + u; +} + +ivec4 __operator + (const ivec4 v, const int b) +{ + __retVal = v + ivec4(b); +} + +ivec4 __operator - (const int a, const ivec4 u) +{ + __retVal = ivec4(a) - u; +} + +ivec4 __operator - (const ivec4 v, const int b) +{ + __retVal = v - ivec4(b); +} + +ivec4 __operator * (const int a, const ivec4 u) +{ + __retVal = ivec4(a) * u; +} + +ivec4 __operator * (const ivec4 v, const int b) +{ + __retVal = v * ivec4(b); +} + +ivec4 __operator / (const int a, const ivec4 u) +{ + __retVal = ivec4(a) / u; +} + +ivec4 __operator / (const ivec4 v, const int b) +{ + __retVal = v / ivec4(b); +} + + + + +//// Unary negation operator + +int __operator - (const int a) +{ + __asm vec4_negate __retVal.x, a; +} + +ivec2 __operator - (const ivec2 v) +{ + __asm vec4_negate __retVal, v; +} + +ivec3 __operator - (const ivec3 v) +{ + __asm vec4_negate __retVal, v; +} + +ivec4 __operator - (const ivec4 v) +{ + __asm vec4_negate __retVal, v; +} + +float __operator - (const float a) +{ + __asm vec4_negate __retVal.x, a; +} + +vec2 __operator - (const vec2 v) +{ + __asm vec4_negate __retVal.xy, v.xy; +} + +vec3 __operator - (const vec3 v) +{ + __asm vec4_negate __retVal.xyz, v.xyz; +} + +vec4 __operator - (const vec4 v) +{ + __asm vec4_negate __retVal, v; +} + +mat2 __operator - (const mat2 m) +{ + __retVal[0] = -m[0]; + __retVal[1] = -m[1]; +} + +mat3 __operator - (const mat3 m) +{ + __retVal[0] = -m[0]; + __retVal[1] = -m[1]; + __retVal[2] = -m[2]; +} + +mat4 __operator - (const mat4 m) +{ + __retVal[0] = -m[0]; + __retVal[1] = -m[1]; + __retVal[2] = -m[2]; + __retVal[3] = -m[3]; +} + + + +//// dot product + +float dot(const float a, const float b) +{ + __retVal = a * b; +} + +float dot(const vec2 a, const vec2 b) +{ + __retVal = a.x * b.x + a.y * b.y; +} + +float dot(const vec3 a, const vec3 b) +{ + __asm vec3_dot __retVal, a, b; +} + +float dot(const vec4 a, const vec4 b) +{ + __asm vec4_dot __retVal, a, b; +} + + + +//// int assignment operators + +void __operator += (inout int a, const int b) +{ + __asm vec4_add a, a, b; +} + +void __operator -= (inout int a, const int b) +{ + __asm vec4_subtract a, a, b; +} + +void __operator *= (inout int a, const int b) +{ + __asm vec4_multiply a, a, b; +} + +void __operator /= (inout int a, const int b) +{ + float invB; + __asm float_rcp invB, b; + __asm vec4_multiply a, a, invB; +} + + +//// ivec2 assignment operators + +void __operator += (inout ivec2 v, const ivec2 u) +{ + __asm vec4_add v, v, u; +} + +void __operator -= (inout ivec2 v, const ivec2 u) +{ + __asm vec4_subtract v, v, u; +} + +void __operator *= (inout ivec2 v, const ivec2 u) +{ + __asm vec4_multiply v, v, u; +} + +void __operator /= (inout ivec2 v, const ivec2 u) +{ + ivec2 inv, z; + __asm float_rcp inv.x, u.x; + __asm float_rcp inv.y, u.y; + __asm vec4_multiply z, v, inv; + __asm float_to_int __retVal, z; +} + + +//// ivec3 assignment operators + +void __operator += (inout ivec3 v, const ivec3 u) +{ + __asm vec4_add v, v, u; +} + +void __operator -= (inout ivec3 v, const ivec3 u) +{ + __asm vec4_subtract v, v, u; +} + +void __operator *= (inout ivec3 v, const ivec3 u) +{ + __asm vec4_multiply v, v, u; +} + +void __operator /= (inout ivec3 v, const ivec3 u) +{ + ivec3 inv, z; + __asm float_rcp inv.x, u.x; + __asm float_rcp inv.y, u.y; + __asm vec4_multiply z, v, inv; + __asm float_to_int __retVal, z; +} + + +//// ivec4 assignment operators + +void __operator += (inout ivec4 v, const ivec4 u) +{ + __asm vec4_add v, v, u; +} + +void __operator -= (inout ivec4 v, const ivec4 u) +{ + __asm vec4_subtract v, v, u; +} + +void __operator *= (inout ivec4 v, const ivec4 u) +{ + __asm vec4_multiply v, v, u; +} + +void __operator /= (inout ivec4 v, const ivec4 u) +{ + ivec4 inv, z; + __asm float_rcp inv.x, u.x; + __asm float_rcp inv.y, u.y; + __asm vec4_multiply z, v, inv; + __asm float_to_int __retVal, z; +} + + +//// float assignment operators + +void __operator += (inout float a, const float b) +{ + __asm vec4_add a.x, a.x, b; +} + +void __operator -= (inout float a, const float b) +{ + __asm vec4_subtract a.x, a, b; +} + +void __operator *= (inout float a, const float b) +{ + __asm vec4_multiply a.x, a, b; +} + +void __operator /= (inout float a, const float b) +{ + float w; // = 1 / b + __asm float_rcp w.x, b; + __asm vec4_multiply a.x, a, w; +} + + +//// vec2 assignment operators + +void __operator += (inout vec2 v, const vec2 u) +{ + __asm vec4_add v.xy, v.xy, u.xy; +} + +void __operator -= (inout vec2 v, const vec2 u) +{ + __asm vec4_subtract v.xy, v.xy, u.xy; +} + +void __operator *= (inout vec2 v, const vec2 u) +{ + __asm vec4_multiply v.xy, v.xy, u.xy; +} + +void __operator /= (inout vec2 v, const vec2 u) +{ + vec2 w; + __asm float_rcp w.x, u.x; + __asm float_rcp w.y, u.y; + __asm vec4_multiply v.xy, v.xy, w.xy; +} + + +//// vec3 assignment operators + +void __operator += (inout vec3 v, const vec3 u) +{ + __asm vec4_add v.xyz, v, u; +} + +void __operator -= (inout vec3 v, const vec3 u) +{ + __asm vec4_subtract v.xyz, v, u; +} + +void __operator *= (inout vec3 v, const vec3 u) +{ + __asm vec4_multiply v.xyz, v, u; +} + +void __operator /= (inout vec3 v, const vec3 u) +{ + vec3 w; + __asm float_rcp w.x, u.x; + __asm float_rcp w.y, u.y; + __asm float_rcp w.z, u.z; + __asm vec4_multiply v.xyz, v.xyz, w.xyz; +} + + +//// vec4 assignment operators + +void __operator += (inout vec4 v, const vec4 u) +{ + __asm vec4_add v, v, u; +} + +void __operator -= (inout vec4 v, const vec4 u) +{ + __asm vec4_subtract v, v, u; +} + +void __operator *= (inout vec4 v, const vec4 u) +{ + __asm vec4_multiply v, v, u; +} + +void __operator /= (inout vec4 v, const vec4 u) +{ + vec4 w; + __asm float_rcp w.x, u.x; + __asm float_rcp w.y, u.y; + __asm float_rcp w.z, u.z; + __asm float_rcp w.w, u.w; + __asm vec4_multiply v, v, w; +} + + + +//// ivec2/int assignment operators + +void __operator += (inout ivec2 v, const int a) +{ + __asm vec4_add v.xy, v.xy, a.xx; +} + +void __operator -= (inout ivec2 v, const int a) +{ + __asm vec4_subtract v.xy, v.xy, a.xx; +} + +void __operator *= (inout ivec2 v, const int a) +{ + __asm vec4_multiply v.xy, v.xy, a.xx; + v.x *= a; + v.y *= a; +} + +void __operator /= (inout ivec2 v, const int a) +{ +// XXX rcp + v.x /= a; + v.y /= a; +} + + +//// ivec3/int assignment operators + +void __operator += (inout ivec3 v, const int a) +{ + __asm vec4_add v.xyz, v.xyz, a.xxx; +} + +void __operator -= (inout ivec3 v, const int a) +{ + __asm vec4_subtract v.xyz, v.xyz, a.xxx; +} + +void __operator *= (inout ivec3 v, const int a) +{ + __asm vec4_multiply v.xyz, v.xyz, a.xxx; +} + +void __operator /= (inout ivec3 v, const int a) +{ + // XXX rcp + v.x /= a; + v.y /= a; + v.z /= a; +} + + +//// ivec4/int assignment operators + +void __operator += (inout ivec4 v, const int a) +{ + __asm vec4_add v, v, a.xxxx; +} + +void __operator -= (inout ivec4 v, const int a) +{ + __asm vec4_subtract v, v, a.xxxx; +} + +void __operator *= (inout ivec4 v, const int a) +{ + __asm vec4_multiply v, v, a.xxxx; +} + +void __operator /= (inout ivec4 v, const int a) +{ + v.x /= a; + v.y /= a; + v.z /= a; + v.w /= a; +} + + + +//// vec2/float assignment operators + +void __operator += (inout vec2 v, const float a) +{ + __asm vec4_add v.xy, v, a.xx; +} + +void __operator -= (inout vec2 v, const float a) +{ + __asm vec4_subtract v.xy, v, a.xx; +} + +void __operator *= (inout vec2 v, const float a) +{ + __asm vec4_multiply v.xy, v, a.xx; +} + +void __operator /= (inout vec2 v, const float a) +{ + float invA; + __asm float_rcp invA, a; + __asm vec4_multiply v.xy, v.xy, a.xx; +} + + +//// vec3/float assignment operators + +void __operator += (inout vec3 v, const float a) +{ + __asm vec4_add v.xyz, v, a.xxx; +} + +void __operator -= (inout vec3 v, const float a) +{ + __asm vec4_subtract v.xyz, v, a.xxx; +} + +void __operator *= (inout vec3 v, const float a) +{ + __asm vec4_multiply v.xyz, v, a.xxx; +} + +void __operator /= (inout vec3 v, const float a) +{ + float invA; + __asm float_rcp invA, a; + __asm vec4_multiply v.xyz, v.xyz, a.xxx; +} + + +//// vec4/float assignment operators + +void __operator += (inout vec4 v, const float a) +{ + __asm vec4_add v, v, a.xxxx; +} + +void __operator -= (inout vec4 v, const float a) +{ + __asm vec4_subtract v, v, a.xxxx; +} + +void __operator *= (inout vec4 v, const float a) +{ + __asm vec4_multiply v, v, a.xxxx; +} + +void __operator /= (inout vec4 v, const float a) +{ + float invA; + __asm float_rcp invA, a; + __asm vec4_multiply v, v, a.xxxx; +} + + + + + +//// Basic mat2 operations + +mat2 __operator + (const mat2 m, const mat2 n) +{ + __retVal[0] = m[0] + n[0]; + __retVal[1] = m[1] + n[1]; +} + +mat2 __operator - (const mat2 m, const mat2 n) +{ + __retVal[0] = m[0] - n[0]; + __retVal[1] = m[1] - n[1]; +} + +mat2 __operator * (const mat2 m, const mat2 n) +{ + vec2 mRow0, mRow1; + mRow0.x = m[0].x; + mRow0.y = m[1].x; + mRow1.x = m[0].y; + mRow1.y = m[1].y; + __retVal[0].x = dot(mRow0, n[0]); + __retVal[1].x = dot(mRow0, n[1]); + __retVal[0].y = dot(mRow1, n[0]); + __retVal[1].y = dot(mRow1, n[1]); +} + +mat2 __operator / (const mat2 m, const mat2 n) +{ + __retVal[0] = m[0] / n[0]; + __retVal[1] = m[1] / n[1]; +} + + +//// Basic mat3 operations + +mat3 __operator + (const mat3 m, const mat3 n) +{ + __retVal[0] = m[0] + n[0]; + __retVal[1] = m[1] + n[1]; + __retVal[2] = m[2] + n[2]; +} + +mat3 __operator - (const mat3 m, const mat3 n) +{ + __retVal[0] = m[0] - n[0]; + __retVal[1] = m[1] - n[1]; + __retVal[2] = m[2] - n[2]; +} + +mat3 __operator * (const mat3 m, const mat3 n) +{ + // sub-blocks to reduce register usage + { + vec3 mRow0; + mRow0.x = m[0].x; + mRow0.y = m[1].x; + mRow0.z = m[2].x; + __retVal[0].x = dot(mRow0, n[0]); + __retVal[1].x = dot(mRow0, n[1]); + __retVal[2].x = dot(mRow0, n[2]); + } + { + vec3 mRow1; + mRow1.x = m[0].y; + mRow1.y = m[1].y; + mRow1.z = m[2].y; + __retVal[0].y = dot(mRow1, n[0]); + __retVal[1].y = dot(mRow1, n[1]); + __retVal[2].y = dot(mRow1, n[2]); + } + { + vec3 mRow2; + mRow2.x = m[0].z; + mRow2.y = m[1].z; + mRow2.z = m[2].z; + __retVal[0].z = dot(mRow2, n[0]); + __retVal[1].z = dot(mRow2, n[1]); + __retVal[2].z = dot(mRow2, n[2]); + } +} + +mat3 __operator / (const mat3 m, const mat3 n) +{ + __retVal[0] = m[0] / n[0]; + __retVal[1] = m[1] / n[1]; + __retVal[2] = m[2] / n[2]; +} + + +//// Basic mat4 operations + +mat4 __operator + (const mat4 m, const mat4 n) +{ + __retVal[0] = m[0] + n[0]; + __retVal[1] = m[1] + n[1]; + __retVal[2] = m[2] + n[2]; + __retVal[3] = m[3] + n[3]; +} + +mat4 __operator - (const mat4 m, const mat4 n) +{ + __retVal[0] = m[0] - n[0]; + __retVal[1] = m[1] - n[1]; + __retVal[2] = m[2] - n[2]; + __retVal[3] = m[3] - n[3]; +} + +mat4 __operator * (const mat4 m, const mat4 n) +{ + // sub-blocks to reduce temporary usage + { + vec4 mRow0; + mRow0.x = m[0].x; + mRow0.y = m[1].x; + mRow0.z = m[2].x; + mRow0.w = m[3].x; + __retVal[0].x = dot(mRow0, n[0]); + __retVal[1].x = dot(mRow0, n[1]); + __retVal[2].x = dot(mRow0, n[2]); + __retVal[3].x = dot(mRow0, n[3]); + } + { + vec4 mRow1; + mRow1.x = m[0].y; + mRow1.y = m[1].y; + mRow1.z = m[2].y; + mRow1.w = m[3].y; + __retVal[0].y = dot(mRow1, n[0]); + __retVal[1].y = dot(mRow1, n[1]); + __retVal[2].y = dot(mRow1, n[2]); + __retVal[3].y = dot(mRow1, n[3]); + } + { + vec4 mRow2; + mRow2.x = m[0].z; + mRow2.y = m[1].z; + mRow2.z = m[2].z; + mRow2.w = m[3].z; + __retVal[0].z = dot(mRow2, n[0]); + __retVal[1].z = dot(mRow2, n[1]); + __retVal[2].z = dot(mRow2, n[2]); + __retVal[3].z = dot(mRow2, n[3]); + } + { + vec4 mRow3; + mRow3.x = m[0].w; + mRow3.y = m[1].w; + mRow3.z = m[2].w; + mRow3.w = m[3].w; + __retVal[0].w = dot(mRow3, n[0]); + __retVal[1].w = dot(mRow3, n[1]); + __retVal[2].w = dot(mRow3, n[2]); + __retVal[3].w = dot(mRow3, n[3]); + } +} + +mat4 __operator / (const mat4 m, const mat4 n) +{ + __retVal[0] = m[0] / n[0]; + __retVal[1] = m[1] / n[1]; + __retVal[2] = m[2] / n[2]; + __retVal[3] = m[3] / n[3]; +} + + +//// mat2/float operations + +mat2 __operator + (const float a, const mat2 n) +{ + __retVal[0] = a + n[0]; + __retVal[1] = a + n[1]; +} + +mat2 __operator + (const mat2 m, const float b) +{ + __retVal[0] = m[0] + b; + __retVal[1] = m[1] + b; +} + +mat2 __operator - (const float a, const mat2 n) +{ + __retVal[0] = a - n[0]; + __retVal[1] = a - n[1]; +} + +mat2 __operator - (const mat2 m, const float b) +{ + __retVal[0] = m[0] - b; + __retVal[1] = m[1] - b; +} + +mat2 __operator * (const float a, const mat2 n) +{ + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; +} + +mat2 __operator * (const mat2 m, const float b) +{ + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; +} + +mat2 __operator / (const float a, const mat2 n) +{ + __retVal[0] = a / n[0]; + __retVal[1] = a / n[1]; +} + +mat2 __operator / (const mat2 m, const float b) +{ + __retVal[0] = m[0] / b; + __retVal[1] = m[1] / b; +} + + +//// mat3/float operations + +mat3 __operator + (const float a, const mat3 n) +{ + __retVal[0] = a + n[0]; + __retVal[1] = a + n[1]; + __retVal[2] = a + n[2]; +} + +mat3 __operator + (const mat3 m, const float b) +{ + __retVal[0] = m[0] + b; + __retVal[1] = m[1] + b; + __retVal[2] = m[2] + b; +} + +mat3 __operator - (const float a, const mat3 n) +{ + __retVal[0] = a - n[0]; + __retVal[1] = a - n[1]; + __retVal[2] = a - n[2]; +} + +mat3 __operator - (const mat3 m, const float b) +{ + __retVal[0] = m[0] - b; + __retVal[1] = m[1] - b; + __retVal[2] = m[2] - b; +} + +mat3 __operator * (const float a, const mat3 n) +{ + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; + __retVal[2] = a * n[2]; +} + +mat3 __operator * (const mat3 m, const float b) +{ + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; + __retVal[2] = m[2] * b; +} + +mat3 __operator / (const float a, const mat3 n) +{ + __retVal[0] = a / n[0]; + __retVal[1] = a / n[1]; + __retVal[2] = a / n[2]; +} + +mat3 __operator / (const mat3 m, const float b) +{ + __retVal[0] = m[0] / b; + __retVal[1] = m[1] / b; + __retVal[2] = m[2] / b; +} + + +//// mat4/float operations + +mat4 __operator + (const float a, const mat4 n) +{ + __retVal[0] = a + n[0]; + __retVal[1] = a + n[1]; + __retVal[2] = a + n[2]; + __retVal[3] = a + n[3]; +} + +mat4 __operator + (const mat4 m, const float b) +{ + __retVal[0] = m[0] + b; + __retVal[1] = m[1] + b; + __retVal[2] = m[2] + b; + __retVal[3] = m[3] + b; +} + +mat4 __operator - (const float a, const mat4 n) +{ + __retVal[0] = a - n[0]; + __retVal[1] = a - n[1]; + __retVal[2] = a - n[2]; + __retVal[3] = a - n[3]; +} + +mat4 __operator - (const mat4 m, const float b) +{ + __retVal[0] = m[0] - b; + __retVal[1] = m[1] - b; + __retVal[2] = m[2] - b; + __retVal[3] = m[3] - b; +} + +mat4 __operator * (const float a, const mat4 n) +{ + __retVal[0] = a * n[0]; + __retVal[1] = a * n[1]; + __retVal[2] = a * n[2]; + __retVal[3] = a * n[3]; +} + +mat4 __operator * (const mat4 m, const float b) +{ + __retVal[0] = m[0] * b; + __retVal[1] = m[1] * b; + __retVal[2] = m[2] * b; + __retVal[3] = m[3] * b; +} + +mat4 __operator / (const float a, const mat4 n) +{ + __retVal[0] = a / n[0]; + __retVal[1] = a / n[1]; + __retVal[2] = a / n[2]; + __retVal[3] = a / n[3]; +} + +mat4 __operator / (const mat4 m, const float b) +{ + __retVal[0] = m[0] / b; + __retVal[1] = m[1] / b; + __retVal[2] = m[2] / b; + __retVal[3] = m[3] / b; +} + + + +//// matrix / vector products + +vec2 __operator * (const mat2 m, const vec2 v) +{ + vec2 r0, r1; + r0.x = m[0].x; + r0.y = m[1].x; + r1.x = m[0].y; + r1.y = m[1].y; + __retVal.x = dot(r0, v); + __retVal.y = dot(r1, v); +} + +vec2 __operator * (const vec2 v, const mat2 m) +{ + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); +} + +vec3 __operator * (const mat3 m, const vec3 v) +{ + { + vec3 r0; + r0.x = m[0].x; + r0.y = m[1].x; + r0.z = m[2].x; + __asm vec3_dot __retVal.x, r0, v; + } + { + vec3 r1; + r1.x = m[0].y; + r1.y = m[1].y; + r1.z = m[2].y; + __asm vec3_dot __retVal.y, r1, v; + } + { + vec3 r2; + r2.x = m[0].z; + r2.y = m[1].z; + r2.z = m[2].z; + __asm vec3_dot __retVal.z, r2, v; + } +} + +vec3 __operator * (const vec3 v, const mat3 m) +{ + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); + __retVal.z = dot(v, m[2]); +} + +vec4 __operator * (const mat4 m, const vec4 v) +{ + // extract rows, then do dot product + { + vec4 r0; + r0.x = m[0].x; + r0.y = m[1].x; + r0.z = m[2].x; + r0.w = m[3].x; + __asm vec4_dot __retVal.x, r0, v; + } + { + vec4 r1; + r1.x = m[0].y; + r1.y = m[1].y; + r1.z = m[2].y; + r1.w = m[3].y; + __asm vec4_dot __retVal.y, r1, v; + } + { + vec4 r2; + r2.x = m[0].z; + r2.y = m[1].z; + r2.z = m[2].z; + r2.w = m[3].z; + __asm vec4_dot __retVal.z, r2, v; + } + { + vec4 r3; + r3.x = m[0].w; + r3.y = m[1].w; + r3.z = m[2].w; + r3.w = m[3].w; + __asm vec4_dot __retVal.w, r3, v; + } +} + +vec4 __operator * (const vec4 v, const mat4 m) +{ + //mm + __retVal.x = dot(v, m[0]); + __retVal.y = dot(v, m[1]); + __retVal.z = dot(v, m[2]); + __retVal.w = dot(v, m[3]); +} + + + +//// mat2 assignment operators + +void __operator += (inout mat2 m, const mat2 n) +{ + m[0] += n[0]; + m[1] += n[1]; +} + +void __operator -= (inout mat2 m, const mat2 n) +{ + m[0] -= n[0]; + m[1] -= n[1]; +} + +void __operator *= (inout mat2 m, const mat2 n) +{ + m = m * n; +} + +void __operator /= (inout mat2 m, const mat2 n) +{ + m[0] /= n[0]; + m[1] /= n[1]; +} + + +//// mat3 assignment operators + +void __operator += (inout mat3 m, const mat3 n) +{ + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; +} + +void __operator -= (inout mat3 m, const mat3 n) +{ + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; +} + +void __operator *= (inout mat3 m, const mat3 n) +{ + m = m * n; +} + +void __operator /= (inout mat3 m, const mat3 n) +{ + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; +} + + +// mat4 assignment operators + +void __operator += (inout mat4 m, const mat4 n) +{ + m[0] += n[0]; + m[1] += n[1]; + m[2] += n[2]; + m[3] += n[3]; +} + +void __operator -= (inout mat4 m, const mat4 n) { + m[0] -= n[0]; + m[1] -= n[1]; + m[2] -= n[2]; + m[3] -= n[3]; +} + +void __operator *= (inout mat4 m, const mat4 n) +{ + m = m * n; +} + +void __operator /= (inout mat4 m, const mat4 n) +{ + m[0] /= n[0]; + m[1] /= n[1]; + m[2] /= n[2]; + m[3] /= n[3]; +} + + +//// mat2/float assignment operators + +void __operator += (inout mat2 m, const float a) { + m[0] += a; + m[1] += a; +} + +void __operator -= (inout mat2 m, const float a) { + m[0] -= a; + m[1] -= a; +} + +void __operator *= (inout mat2 m, const float a) { + m[0] *= a; + m[1] *= a; +} + +void __operator /= (inout mat2 m, const float a) { + m[0] /= a; + m[1] /= a; +} + + +//// mat3/float assignment operators + +void __operator += (inout mat3 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; +} + +void __operator -= (inout mat3 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; +} + +void __operator *= (inout mat3 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; +} + +void __operator /= (inout mat3 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; +} + + +//// mat4/float assignment operators + +void __operator += (inout mat4 m, const float a) { + m[0] += a; + m[1] += a; + m[2] += a; + m[3] += a; +} + +void __operator -= (inout mat4 m, const float a) { + m[0] -= a; + m[1] -= a; + m[2] -= a; + m[3] -= a; +} + +void __operator *= (inout mat4 m, const float a) { + m[0] *= a; + m[1] *= a; + m[2] *= a; + m[3] *= a; +} + +void __operator /= (inout mat4 m, const float a) { + m[0] /= a; + m[1] /= a; + m[2] /= a; + m[3] /= a; +} + + + +//// vec/mat assignment operators + +void __operator *= (inout vec2 v, const mat2 m) +{ + v = v * m; +} + +void __operator *= (inout vec3 v, const mat3 m) +{ + v = v * m; +} + +void __operator *= (inout vec4 v, const mat4 m) +{ + v = v * m; +} + + + +//// pre-decrement operators + +int __operator --(inout int a) +{ + a = a - 1; + __retVal = a; +} + +ivec2 __operator --(inout ivec2 v) +{ + v = v - ivec2(1); + __retVal = v; +} + +ivec3 __operator --(inout ivec3 v) +{ + v = v - ivec3(1); + __retVal = v; +} + +ivec4 __operator --(inout ivec4 v) +{ + v = v - ivec4(1); + __retVal = v; +} + + +float __operator --(inout float a) +{ + a = a - 1.0; + __retVal = a; +} + +vec2 __operator --(inout vec2 v) +{ + v = v - vec2(1.0); + __retVal = v; +} + +vec3 __operator --(inout vec3 v) +{ + v = v - vec3(1.0); + __retVal = v; +} + +vec4 __operator --(inout vec4 v) +{ + v = v - vec4(1.0); + __retVal = v; +} + + +mat2 __operator --(inout mat2 m) +{ + m[0] = m[0] - vec2(1.0); + m[1] = m[1] - vec2(1.0); + __retVal = m; +} + +mat3 __operator --(inout mat3 m) +{ + m[0] = m[0] - vec3(1.0); + m[1] = m[1] - vec3(1.0); + m[2] = m[2] - vec3(1.0); + __retVal = m; +} + +mat4 __operator --(inout mat4 m) +{ + m[0] = m[0] - vec4(1.0); + m[1] = m[1] - vec4(1.0); + m[2] = m[2] - vec4(1.0); + m[3] = m[3] - vec4(1.0); + __retVal = m; +} + + +//// pre-increment operators + +int __operator ++(inout int a) +{ + a = a + 1; + __retVal = a; +} + +ivec2 __operator ++(inout ivec2 v) +{ + v = v + ivec2(1); + __retVal = v; +} + +ivec3 __operator ++(inout ivec3 v) +{ + v = v + ivec3(1); + __retVal = v; +} + +ivec4 __operator ++(inout ivec4 v) +{ + v = v + ivec4(1); + __retVal = v; +} + + +float __operator ++(inout float a) +{ + a = a + 1.0; + __retVal = a; +} + +vec2 __operator ++(inout vec2 v) +{ + v = v + vec2(1.0); + __retVal = v; +} + +vec3 __operator ++(inout vec3 v) +{ + v = v + vec3(1.0); + __retVal = v; +} + +vec4 __operator ++(inout vec4 v) +{ + v = v + vec4(1.0); + __retVal = v; +} + + +mat2 __operator ++(inout mat2 m) +{ + m[0] = m[0] + vec2(1.0); + m[1] = m[1] + vec2(1.0); + __retVal = m; +} + +mat3 __operator ++(inout mat3 m) +{ + m[0] = m[0] + vec3(1.0); + m[1] = m[1] + vec3(1.0); + m[2] = m[2] + vec3(1.0); + __retVal = m; +} + +mat4 __operator ++(inout mat4 m) +{ + m[0] = m[0] + vec4(1.0); + m[1] = m[1] + vec4(1.0); + m[2] = m[2] + vec4(1.0); + m[3] = m[3] + vec4(1.0); + __retVal = m; +} + + + +//// post-decrement + +int __postDecr(inout int a) +{ + __retVal = a; + a = a - 1; +} + +ivec2 __postDecr(inout ivec2 v) +{ + __retVal = v; + v = v - ivec2(1); +} + +ivec3 __postDecr(inout ivec3 v) +{ + __retVal = v; + v = v - ivec3(1); +} + +ivec4 __postDecr(inout ivec4 v) +{ + __retVal = v; + v = v - ivec4(1); +} + + +float __postDecr(inout float a) +{ + __retVal = a; + a = a - 1.0; +} + +vec2 __postDecr(inout vec2 v) +{ + __retVal = v; + v = v - vec2(1.0); +} + +vec3 __postDecr(inout vec3 v) +{ + __retVal = v; + v = v - vec3(1.0); +} + +vec4 __postDecr(inout vec4 v) +{ + __retVal = v; + v = v - vec4(1.0); +} + + +mat2 __postDecr(inout mat2 m) +{ + __retVal = m; + m[0] = m[0] - vec2(1.0); + m[1] = m[1] - vec2(1.0); +} + +mat3 __postDecr(inout mat3 m) +{ + __retVal = m; + m[0] = m[0] - vec3(1.0); + m[1] = m[1] - vec3(1.0); + m[2] = m[2] - vec3(1.0); +} + +mat4 __postDecr(inout mat4 m) +{ + __retVal = m; + m[0] = m[0] - vec4(1.0); + m[1] = m[1] - vec4(1.0); + m[2] = m[2] - vec4(1.0); + m[3] = m[3] - vec4(1.0); +} + + +//// post-increment + +float __postIncr(inout float a) +{ + __retVal = a; + a = a + 1; +} + +vec2 __postIncr(inout vec2 v) +{ + __retVal = v; + v = v + vec2(1.0); +} + +vec3 __postIncr(inout vec3 v) +{ + __retVal = v; + v = v + vec3(1.0); +} + +vec4 __postIncr(inout vec4 v) +{ + __retVal = v; + v = v + vec4(1.0); +} + + +int __postIncr(inout int a) +{ + __retVal = a; + a = a + 1; +} + +ivec2 __postIncr(inout ivec2 v) +{ + __retVal = v; + v = v + ivec2(1); +} + +ivec3 __postIncr(inout ivec3 v) +{ + __retVal = v; + v = v + ivec3(1); +} + +ivec4 __postIncr(inout ivec4 v) +{ + __retVal = v; + v = v + ivec3(1); +} + + +mat2 __postIncr(inout mat2 m) +{ + mat2 n = m; + m[0] = m[0] + vec2(1.0); + m[1] = m[1] + vec2(1.0); + return n; +} + +mat3 __postIncr(inout mat3 m) +{ + mat3 n = m; + m[0] = m[0] + vec3(1.0); + m[1] = m[1] + vec3(1.0); + m[2] = m[2] + vec3(1.0); + return n; +} + +mat4 __postIncr(inout mat4 m) +{ + mat4 n = m; + m[0] = m[0] + vec4(1.0); + m[1] = m[1] + vec4(1.0); + m[2] = m[2] + vec4(1.0); + m[3] = m[3] + vec4(1.0); + return n; +} + + + +//// inequality operators + + +// XXX are the inequality operators for floats/ints really needed???? +bool __operator < (const float a, const float b) +{ + __asm vec4_sgt __retVal.x, b, a; +} + + +bool __operator < (const int a, const int b) { + return float (a) < float (b); +} + +bool __operator > (const float a, const float b) { + bool c; + __asm float_less c, b, a; + return c; +} + +bool __operator > (const int a, const int b) { + return float (a) > float (b); +} + +bool __operator >= (const float a, const float b) { + bool g, e; + __asm float_less g, b, a; + __asm float_equal e, a, b; + return g || e; +} + +bool __operator >= (const int a, const int b) { + return float (a) >= float (b); +} + +bool __operator <= (const float a, const float b) { + bool g, e; + __asm float_less g, a, b; + __asm float_equal e, a, b; + return g || e; +} + +bool __operator <= (const int a, const int b) { + return float (a) <= float (b); +} + + + +// +// MESA-specific extension functions. +// + +void printMESA (const float f) { + __asm float_print f; +} + +void printMESA (const int i) { + __asm int_print i; +} + +void printMESA (const bool b) { + __asm bool_print b; +} + +void printMESA (const vec2 v) { + printMESA (v.x); + printMESA (v.y); +} + +void printMESA (const vec3 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); +} + +void printMESA (const vec4 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); + printMESA (v.w); +} + +void printMESA (const ivec2 v) { + printMESA (v.x); + printMESA (v.y); +} + +void printMESA (const ivec3 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); +} + +void printMESA (const ivec4 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); + printMESA (v.w); +} + +void printMESA (const bvec2 v) { + printMESA (v.x); + printMESA (v.y); +} + +void printMESA (const bvec3 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); +} + +void printMESA (const bvec4 v) { + printMESA (v.x); + printMESA (v.y); + printMESA (v.z); + printMESA (v.w); +} + +void printMESA (const mat2 m) { + printMESA (m[0]); + printMESA (m[1]); +} + +void printMESA (const mat3 m) { + printMESA (m[0]); + printMESA (m[1]); + printMESA (m[2]); +} + +void printMESA (const mat4 m) { + printMESA (m[0]); + printMESA (m[1]); + printMESA (m[2]); + printMESA (m[3]); +} + +void printMESA (const sampler1D e) { + __asm int_print e; +} + +void printMESA (const sampler2D e) { + __asm int_print e; +} + +void printMESA (const sampler3D e) { + __asm int_print e; +} + +void printMESA (const samplerCube e) { + __asm int_print e; +} + +void printMESA (const sampler1DShadow e) { + __asm int_print e; +} + +void printMESA (const sampler2DShadow e) { + __asm int_print e; +} + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_fragment_builtin.gc b/dist/Mesa/src/mesa/shader/slang/library/slang_fragment_builtin.gc new file mode 100644 index 000000000..416c6ff31 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_fragment_builtin.gc @@ -0,0 +1,239 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.10, rev. 59 +// + +__fixed_input vec4 gl_FragCoord; +__fixed_input bool gl_FrontFacing; +__fixed_output vec4 gl_FragColor; +__fixed_output vec4 gl_FragData[gl_MaxDrawBuffers]; +__fixed_output float gl_FragDepth; + +varying vec4 gl_Color; +varying vec4 gl_SecondaryColor; +varying vec4 gl_TexCoord[gl_MaxTextureCoords]; +varying float gl_FogFragCoord; + + + +//// 8.7 Texture Lookup Functions (with bias) + +vec4 texture1D(const sampler1D sampler, const float coord, const float bias) +{ + vec4 coord4; + coord4.x = coord; + coord4.w = bias; + __asm vec4_texb1d __retVal, sampler, coord4; +} + +vec4 texture1DProj(const sampler1D sampler, const vec2 coord, const float bias) +{ + // do projection here (there's no vec4_texbp1d instruction) + vec4 pcoord; + pcoord.x = coord.x / coord.y; + pcoord.w = bias; + __asm vec4_texb1d __retVal, sampler, pcoord; +} + +vec4 texture1DProj(const sampler1D sampler, const vec4 coord, const float bias) +{ + // do projection here (there's no vec4_texbp1d instruction) + vec4 pcoord; + pcoord.x = coord.x / coord.z; + pcoord.w = bias; + __asm vec4_texb1d __retVal, sampler, pcoord; +} + + + + +vec4 texture2D(const sampler2D sampler, const vec2 coord, const float bias) +{ + vec4 coord4; + coord4.xy = coord.xy; + coord4.w = bias; + __asm vec4_texb2d __retVal, sampler, coord4; +} + +vec4 texture2DProj(const sampler2D sampler, const vec3 coord, const float bias) +{ + // do projection here (there's no vec4_texbp2d instruction) + vec4 pcoord; + pcoord.xy = coord.xy / coord.z; + pcoord.w = bias; + __asm vec4_texb2d __retVal, sampler, pcoord; +} + +vec4 texture2DProj(const sampler2D sampler, const vec4 coord, const float bias) +{ + // do projection here (there's no vec4_texbp2d instruction) + vec4 pcoord; + pcoord.xy = coord.xy / coord.w; + pcoord.w = bias; + __asm vec4_texb2d __retVal, sampler, pcoord; +} + + + + +vec4 texture3D(const sampler3D sampler, const vec3 coord, const float bias) +{ + vec4 coord4; + coord4.xyz = coord.xyz; + coord4.w = bias; + __asm vec4_texb3d __retVal, sampler, coord4; +} + +vec4 texture3DProj(const sampler3D sampler, const vec4 coord, const float bias) +{ + // do projection here (there's no vec4_texbp3d instruction) + vec4 pcoord; + pcoord.xyz = coord.xyz / coord.w; + pcoord.w = bias; + __asm vec4_texb3d __retVal, sampler, pcoord; +} + + + + +vec4 textureCube(const samplerCube sampler, const vec3 coord, const float bias) +{ + vec4 coord4; + coord4.xyz = coord; + coord4.w = bias; + __asm vec4_texcube __retVal, sampler, coord4; +} + + + + +// For shadow textures, we use the regular tex instructions since they should +// do the depth comparison step. + +vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord, const float bias) +{ + vec4 coord4; + coord4.xyz = coord; + coord4.w = bias; + __asm vec4_texb1d __retVal, sampler, coord4; +} + +vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord, const float bias) +{ + vec4 pcoord; + pcoord.x = coord.x / coord.w; + pcoord.z = coord.z; + pcoord.w = bias; + __asm vec4_texb1d __retVal, sampler, pcoord; +} + +vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord, const float bias) +{ + vec4 coord4; + coord4.xyz = coord; + coord4.w = bias; + __asm vec4_texb2d __retVal, sampler, coord4; +} + +vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord, const float bias) +{ + vec4 pcoord; + pcoord.xy = coord.xy / coord.w; + pcoord.z = coord.z; + pcoord.w = bias; + __asm vec4_texb2d __retVal, sampler, pcoord; +} + + + +// +// 8.8 Fragment Processing Functions +// + +float dFdx(const float p) +{ + __asm vec4_ddx __retVal.x, p.xxxx; +} + +vec2 dFdx(const vec2 p) +{ + __asm vec4_ddx __retVal.xy, p.xyyy; +} + +vec3 dFdx(const vec3 p) +{ + __asm vec4_ddx __retVal.xyz, p.xyzz; +} + +vec4 dFdx(const vec4 p) +{ + __asm vec4_ddx __retVal, p; +} + +float dFdy(const float p) +{ + __asm vec4_ddy __retVal.x, p.xxxx; +} + +vec2 dFdy(const vec2 p) +{ + __asm vec4_ddy __retVal.xy, p.xyyy; +} + +vec3 dFdy(const vec3 p) +{ + __asm vec4_ddy __retVal.xyz, p.xyzz; +} + +vec4 dFdy(const vec4 p) +{ + __asm vec4_ddy __retVal, p; +} + +float fwidth (const float p) +{ + // XXX hand-write with __asm + return abs(dFdx(p)) + abs(dFdy(p)); +} + +vec2 fwidth(const vec2 p) +{ + // XXX hand-write with __asm + return abs(dFdx(p)) + abs(dFdy(p)); +} + +vec3 fwidth(const vec3 p) +{ + // XXX hand-write with __asm + return abs(dFdx(p)) + abs(dFdy(p)); +} + +vec4 fwidth(const vec4 p) +{ + // XXX hand-write with __asm + return abs(dFdx(p)) + abs(dFdy(p)); +} + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_pp_directives.syn b/dist/Mesa/src/mesa/shader/slang/library/slang_pp_directives.syn new file mode 100644 index 000000000..d4a321034 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_pp_directives.syn @@ -0,0 +1,385 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_pp_directives.syn + * slang preprocessor directives parser + * \author Michal Krol + */ + +.syntax source; + +/* + * This syntax script preprocesses a GLSL shader. + * It is assumed, that the #version directive has been parsed. Separate pass for parsing + * version gives better control on behavior depending on the version number given. + * + * The output is a source string with comments and directives removed. White spaces and comments + * are replaced with on or more spaces. All new-lines are preserved and converted to Linux format. + * Directives are escaped with a null character. The end of the source string is marked by + * two consecutive null characters. The consumer is responsible for executing the escaped + * directives, removing dead portions of code and expanding macros. + */ + +.emtcode ESCAPE_TOKEN 0 + +/* + * The TOKEN_* symbols follow the ESCAPE_TOKEN. + * + * NOTE: + * There is no TOKEN_IFDEF and neither is TOKEN_IFNDEF. They are handled with TOKEN_IF and + * operator defined. + * The "#ifdef SYMBOL" is replaced with "#if defined SYMBOL" + * The "#ifndef SYMBOL" is replaced with "#if !defined SYMBOL" + */ +.emtcode TOKEN_END 0 +.emtcode TOKEN_DEFINE 1 +.emtcode TOKEN_UNDEF 2 +.emtcode TOKEN_IF 3 +.emtcode TOKEN_ELSE 4 +.emtcode TOKEN_ELIF 5 +.emtcode TOKEN_ENDIF 6 +.emtcode TOKEN_ERROR 7 +.emtcode TOKEN_PRAGMA 8 +.emtcode TOKEN_EXTENSION 9 +.emtcode TOKEN_LINE 10 + +/* + * The PARAM_* symbols follow the TOKEN_DEFINE. + */ +.emtcode PARAM_END 0 +.emtcode PARAM_PARAMETER 1 + +/* + * The BEHAVIOR_* symbols follow the TOKEN_EXTENSION. + */ +.emtcode BEHAVIOR_REQUIRE 1 +.emtcode BEHAVIOR_ENABLE 2 +.emtcode BEHAVIOR_WARN 3 +.emtcode BEHAVIOR_DISABLE 4 + +source + optional_directive .and .loop source_element .and '\0' .emit ESCAPE_TOKEN .emit TOKEN_END; + +source_element + c_style_comment_block .or cpp_style_comment_block .or new_line_directive .or source_token; + +c_style_comment_block + '/' .and '*' .and c_style_comment_rest .and .true .emit ' '; + +c_style_comment_rest + .loop c_style_comment_body .and c_style_comment_end; + +c_style_comment_body + c_style_comment_char_nostar .or c_style_comment_char_star_noslashstar; + +c_style_comment_char_nostar + new_line .or '\x2B'-'\xFF' .or '\x01'-'\x29'; + +c_style_comment_char_star_noslashstar + '*' .and c_style_comment_char_star_noslashstar_1; +c_style_comment_char_star_noslashstar_1 + c_style_comment_char_noslashstar .or c_style_comment_char_star_noslashstar; + +c_style_comment_char_noslashstar + new_line .or '\x30'-'\xFF' .or '\x01'-'\x29' .or '\x2B'-'\x2E'; + +c_style_comment_end + '*' .and .loop c_style_comment_char_star .and '/'; + +c_style_comment_char_star + '*'; + +cpp_style_comment_block + '/' .and '/' .and cpp_style_comment_block_1; +cpp_style_comment_block_1 + cpp_style_comment_block_2 .or cpp_style_comment_block_3; +cpp_style_comment_block_2 + .loop cpp_style_comment_char .and new_line_directive; +cpp_style_comment_block_3 + .loop cpp_style_comment_char; + +cpp_style_comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +new_line_directive + new_line .and optional_directive; + +new_line + generic_new_line .emit '\n'; + +generic_new_line + carriage_return_line_feed .or line_feed_carriage_return .or '\n' .or '\r'; + +carriage_return_line_feed + '\r' .and '\n'; + +line_feed_carriage_return + '\n' .and '\r'; + +optional_directive + directive .emit ESCAPE_TOKEN .or .true; + +directive + dir_define .emit TOKEN_DEFINE .or + dir_undef .emit TOKEN_UNDEF .or + dir_if .emit TOKEN_IF .or + dir_ifdef .emit TOKEN_IF .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e' .emit 'd' + .emit ' ' .or + dir_ifndef .emit TOKEN_IF .emit '!' .emit 'd' .emit 'e' .emit 'f' .emit 'i' .emit 'n' .emit 'e' + .emit 'd' .emit ' ' .or + dir_else .emit TOKEN_ELSE .or + dir_elif .emit TOKEN_ELIF .or + dir_endif .emit TOKEN_ENDIF .or + dir_ext .emit TOKEN_EXTENSION .or + dir_line .emit TOKEN_LINE; + +dir_define + optional_space .and '#' .and optional_space .and "define" .and symbol .and opt_parameters .and + definition; + +dir_undef + optional_space .and '#' .and optional_space .and "undef" .and symbol; + +dir_if + optional_space .and '#' .and optional_space .and "if" .and expression; + +dir_ifdef + optional_space .and '#' .and optional_space .and "ifdef" .and symbol; + +dir_ifndef + optional_space .and '#' .and optional_space .and "ifndef" .and symbol; + +dir_else + optional_space .and '#' .and optional_space .and "else"; + +dir_elif + optional_space .and '#' .and optional_space .and "elif" .and expression; + +dir_endif + optional_space .and '#' .and optional_space .and "endif"; + +dir_ext + optional_space .and '#' .and optional_space .and "extension" .and space .and extension_name .and + optional_space .and ':' .and optional_space .and extension_behavior; + +dir_line + optional_space .and '#' .and optional_space .and "line" .and expression; + +symbol + space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0'; + +opt_parameters + parameters .or .true .emit PARAM_END; + +parameters + '(' .and parameters_1 .and optional_space .and ')' .emit PARAM_END; +parameters_1 + parameters_2 .or .true; +parameters_2 + parameter .emit PARAM_PARAMETER .and .loop parameters_3; +parameters_3 + optional_space .and ',' .and parameter .emit PARAM_PARAMETER; + +parameter + optional_space .and symbol_character .emit * .and .loop symbol_character2 .emit * .and + .true .emit '\0'; + +definition + .loop definition_character .emit * .and .true .emit '\0'; + +definition_character + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +expression + expression_element .and .loop expression_element .and .true .emit '\0'; + +expression_element + expression_character .emit *; + +expression_character + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +extension_name + symbol_character .emit * .and .loop symbol_character2 .emit * .and .true .emit '\0'; + +extension_behavior + "require" .emit BEHAVIOR_REQUIRE .or + "enable" .emit BEHAVIOR_ENABLE .or + "warn" .emit BEHAVIOR_WARN .or + "disable" .emit BEHAVIOR_DISABLE; + +optional_space + .loop single_space; + +space + single_space .and .loop single_space; + +single_space + ' ' .or '\t'; + +source_token + space .emit ' ' .or complex_token .or source_token_1; +source_token_1 + simple_token .emit ' ' .and .true .emit ' '; + +/* + * All possible tokens. + */ + +complex_token + identifier .or number; + +simple_token + increment .or decrement .or lequal .or gequal .or equal .or nequal .or and .or xor .or or .or + addto .or subtractfrom .or multiplyto .or divideto .or other; + +identifier + identifier_char1 .emit * .and .loop identifier_char2 .emit *; +identifier_char1 + 'a'-'z' .or 'A'-'Z' .or '_'; +identifier_char2 + 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_'; + +number + float .or integer; + +digit_oct + '0'-'7'; + +digit_dec + '0'-'9'; + +digit_hex + '0'-'9' .or 'A'-'F' .or 'a'-'f'; + +float + float_1 .or float_2; +float_1 + float_fractional_constant .and float_optional_exponent_part; +float_2 + float_digit_sequence .and float_exponent_part; + +float_fractional_constant + float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3; +float_fractional_constant_1 + float_digit_sequence .and '.' .emit '.' .and float_digit_sequence; +float_fractional_constant_2 + float_digit_sequence .and '.' .emit '.'; +float_fractional_constant_3 + '.' .emit '.' .and float_digit_sequence; + +float_optional_exponent_part + float_exponent_part .or .true; + +float_digit_sequence + digit_dec .emit * .and .loop digit_dec .emit *; + +float_exponent_part + float_exponent_part_1 .or float_exponent_part_2; +float_exponent_part_1 + 'e' .emit 'e' .and float_optional_sign .and float_digit_sequence; +float_exponent_part_2 + 'E' .emit 'E' .and float_optional_sign .and float_digit_sequence; + +float_optional_sign + '+' .emit '+' .or '-' .emit '-' .or .true; + +integer + integer_hex .or integer_oct .or integer_dec; + +integer_hex + '0' .emit '0' .and integer_hex_1 .emit * .and digit_hex .emit * .and + .loop digit_hex .emit *; +integer_hex_1 + 'x' .or 'X'; + +integer_oct + '0' .emit '0' .and .loop digit_oct .emit *; + +integer_dec + digit_dec .emit * .and .loop digit_dec .emit *; + +increment + '+' .emit * .and '+' .emit *; + +decrement + '-' .emit * .and '-' .emit *; + +lequal + '<' .emit * .and '=' .emit *; + +gequal + '>' .emit * .and '=' .emit *; + +equal + '=' .emit * .and '=' .emit *; + +nequal + '!' .emit * .and '=' .emit *; + +and + '&' .emit * .and '&' .emit *; + +xor + '^' .emit * .and '^' .emit *; + +or + '|' .emit * .and '|' .emit *; + +addto + '+' .emit * .and '=' .emit *; + +subtractfrom + '-' .emit * .and '=' .emit *; + +multiplyto + '*' .emit * .and '=' .emit *; + +divideto + '/' .emit * .and '=' .emit *; + +/* + * All characters except '\0' and '#'. + */ +other + '\x24'-'\xFF' .emit * .or '\x01'-'\x22' .emit *; + +symbol_character + 'A'-'Z' .or 'a'-'z' .or '_'; + +symbol_character2 + 'A'-'Z' .or 'a'-'z' .or '0'-'9' .or '_'; + +.string string_lexer; + +string_lexer + lex_first_identifier_character .and .loop lex_next_identifier_character; + +lex_first_identifier_character + 'a'-'z' .or 'A'-'Z' .or '_'; + +lex_next_identifier_character + 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_'; + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_pp_expression.syn b/dist/Mesa/src/mesa/shader/slang/library/slang_pp_expression.syn new file mode 100644 index 000000000..bfdb220bf --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_pp_expression.syn @@ -0,0 +1,265 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_pp_expression.syn + * slang preprocessor expression parser + * \author Michal Krol + */ + +/* + * Parses one or two (optional) expressions on literal integer constants. Those expressions come + * from #if #elif and #line directives. The preprocessor already parsed those directives and + * expanded the expression (expressions). All occurences of the operator "defined" are already + * replaced with either "0" or "1" literals. + */ + +.syntax expression; + +/* + * Those separate individual expressions. + * For #if/#elif case it is: EXP_EXPRESSION ... EXP_END + * For #line case it may be: EXP_EXPRESSION ... EXP_EXPRESSION ... EXP_END + */ +.emtcode EXP_END 0 +.emtcode EXP_EXPRESSION 1 + +.emtcode OP_END 0 +.emtcode OP_PUSHINT 1 +.emtcode OP_LOGICALOR 2 +.emtcode OP_LOGICALAND 3 +.emtcode OP_OR 4 +.emtcode OP_XOR 5 +.emtcode OP_AND 6 +.emtcode OP_EQUAL 7 +.emtcode OP_NOTEQUAL 8 +.emtcode OP_LESSEQUAL 9 +.emtcode OP_GREATEREQUAL 10 +.emtcode OP_LESS 11 +.emtcode OP_GREATER 12 +.emtcode OP_LEFTSHIFT 13 +.emtcode OP_RIGHTSHIFT 14 +.emtcode OP_ADD 15 +.emtcode OP_SUBTRACT 16 +.emtcode OP_MULTIPLY 17 +.emtcode OP_DIVIDE 18 +.emtcode OP_MODULUS 19 +.emtcode OP_PLUS 20 +.emtcode OP_MINUS 21 +.emtcode OP_NEGATE 22 +.emtcode OP_COMPLEMENT 23 + +expression + first_expression .and optional_second_expression .and optional_space .and '\0' .emit EXP_END; + +first_expression + optional_space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END; + +optional_second_expression + second_expression .or .true; + +second_expression + space .and logical_or_expression .emit EXP_EXPRESSION .and .true .emit OP_END; + +logical_or_expression + logical_and_expression .and .loop logical_or_expression_1; +logical_or_expression_1 + barbar .and logical_and_expression .and .true .emit OP_LOGICALOR; + +logical_and_expression + or_expression .and .loop logical_and_expression_1; +logical_and_expression_1 + ampersandampersand .and or_expression .and .true .emit OP_LOGICALAND; + +or_expression + xor_expression .and .loop or_expression_1; +or_expression_1 + bar .and xor_expression .and .true .emit OP_OR; + +xor_expression + and_expression .and .loop xor_expression_1; +xor_expression_1 + caret .and and_expression .and .true .emit OP_XOR; + +and_expression + equality_expression .and .loop and_expression_1; +and_expression_1 + ampersand .and equality_expression .and .true .emit OP_AND; + +equality_expression + relational_expression .and .loop equality_expression_1; +equality_expression_1 + equality_expression_2 .or equality_expression_3; +equality_expression_2 + equalsequals .and relational_expression .and .true .emit OP_EQUAL; +equality_expression_3 + bangequals .and relational_expression .and .true .emit OP_NOTEQUAL; + +relational_expression + shift_expression .and .loop relational_expression_1; +relational_expression_1 + relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or + relational_expression_5; +relational_expression_2 + lessequals .and shift_expression .and .true .emit OP_LESSEQUAL; +relational_expression_3 + greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL; +relational_expression_4 + less .and shift_expression .and .true .emit OP_LESS; +relational_expression_5 + greater .and shift_expression .and .true .emit OP_GREATER; + +shift_expression + additive_expression .and .loop shift_expression_1; +shift_expression_1 + shift_expression_2 .or shift_expression_3; +shift_expression_2 + lessless .and additive_expression .and .true .emit OP_LEFTSHIFT; +shift_expression_3 + greatergreater .and additive_expression .and .true .emit OP_RIGHTSHIFT; + +additive_expression + multiplicative_expression .and .loop additive_expression_1; +additive_expression_1 + additive_expression_2 .or additive_expression_3; +additive_expression_2 + plus .and multiplicative_expression .and .true .emit OP_ADD; +additive_expression_3 + dash .and multiplicative_expression .and .true .emit OP_SUBTRACT; + +multiplicative_expression + unary_expression .and .loop multiplicative_expression_1; +multiplicative_expression_1 + multiplicative_expression_2 .or multiplicative_expression_3 .or multiplicative_expression_4; +multiplicative_expression_2 + star .and unary_expression .and .true .emit OP_MULTIPLY; +multiplicative_expression_3 + slash .and unary_expression .and .true .emit OP_DIVIDE; +multiplicative_expression_4 + percent .and unary_expression .and .true .emit OP_MODULUS; + +unary_expression + primary_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or + unary_expression_4; +unary_expression_1 + plus .and unary_expression .and .true .emit OP_PLUS; +unary_expression_2 + dash .and unary_expression .and .true .emit OP_MINUS; +unary_expression_3 + bang .and unary_expression .and .true .emit OP_NEGATE; +unary_expression_4 + tilda .and unary_expression .and .true .emit OP_COMPLEMENT; + +primary_expression + intconstant .or primary_expression_1; +primary_expression_1 + lparen .and logical_or_expression .and rparen; + +intconstant + integer .emit OP_PUSHINT; + +integer + integer_dec; + +integer_dec + digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\0'; + +digit_dec + '0'-'9'; + +optional_space + .loop single_space; + +space + single_space .and .loop single_space; + +single_space + ' ' .or '\t'; + +ampersand + optional_space .and '&' .and optional_space; + +ampersandampersand + optional_space .and '&' .and '&' .and optional_space; + +bang + optional_space .and '!' .and optional_space; + +bangequals + optional_space .and '!' .and '=' .and optional_space; + +bar + optional_space .and '|' .and optional_space; + +barbar + optional_space .and '|' .and '|' .and optional_space; + +caret + optional_space .and '^' .and optional_space; + +dash + optional_space .and '-' .and optional_space; + +equalsequals + optional_space .and '=' .and '=' .and optional_space; + +greater + optional_space .and '>' .and optional_space; + +greaterequals + optional_space .and '>' .and '=' .and optional_space; + +greatergreater + optional_space .and '>' .and '>' .and optional_space; + +less + optional_space .and '<' .and optional_space; + +lessequals + optional_space .and '<' .and '=' .and optional_space; + +lessless + optional_space .and '<' .and '<' .and optional_space; + +lparen + optional_space .and '(' .and optional_space; + +percent + optional_space .and '%' .and optional_space; + +plus + optional_space .and '+' .and optional_space; + +rparen + optional_space .and ')' .and optional_space; + +slash + optional_space .and '/' .and optional_space; + +star + optional_space .and '*' .and optional_space; + +tilda + optional_space .and '~' .and optional_space; + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_pp_version.syn b/dist/Mesa/src/mesa/shader/slang/library/slang_pp_version.syn new file mode 100644 index 000000000..d5e9317b5 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_pp_version.syn @@ -0,0 +1,121 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_pp_version.syn + * slang #version directive syntax + * \author Michal Krol + */ + +.syntax version_directive; + +version_directive + version_directive_1 .and .loop version_directive_2; +version_directive_1 + prior_optional_spaces .and optional_version_directive .and .true .emit $; +version_directive_2 + prior_optional_spaces .and version_directive_body .and .true .emit $; + +optional_version_directive + version_directive_body .or .true .emit 10 .emit 1; + +version_directive_body + '#' .and optional_space .and "version" .and space .and version_number .and optional_space .and + new_line; + +version_number + version_number_110 .or version_number_120; + +version_number_110 + leading_zeroes .and "110" .emit 10 .emit 1; + +version_number_120 + leading_zeroes .and "120" .emit 20 .emit 1; + +leading_zeroes + .loop zero; + +zero + '0'; + +space + single_space .and .loop single_space; + +optional_space + .loop single_space; + +single_space + ' ' .or '\t'; + +prior_optional_spaces + .loop prior_space; + +prior_space + c_style_comment_block .or cpp_style_comment_block .or space .or new_line; + +c_style_comment_block + '/' .and '*' .and c_style_comment_rest; + +c_style_comment_rest + .loop c_style_comment_char_no_star .and c_style_comment_rest_1; +c_style_comment_rest_1 + c_style_comment_end .or c_style_comment_rest_2; +c_style_comment_rest_2 + '*' .and c_style_comment_rest; + +c_style_comment_char_no_star + '\x2B'-'\xFF' .or '\x01'-'\x29'; + +c_style_comment_end + '*' .and '/'; + +cpp_style_comment_block + '/' .and '/' .and cpp_style_comment_block_1; +cpp_style_comment_block_1 + cpp_style_comment_block_2 .or cpp_style_comment_block_3; +cpp_style_comment_block_2 + .loop cpp_style_comment_char .and new_line; +cpp_style_comment_block_3 + .loop cpp_style_comment_char; + +cpp_style_comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +new_line + cr_lf .or lf_cr .or '\n' .or '\r'; + +cr_lf + '\r' .and '\n'; + +lf_cr + '\n' .and '\r'; + +.string __string_filter; + +__string_filter + .loop __identifier_char; + +__identifier_char + 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9'; + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_shader.syn b/dist/Mesa/src/mesa/shader/slang/library/slang_shader.syn new file mode 100644 index 000000000..1764d1ae6 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_shader.syn @@ -0,0 +1,1549 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2004-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * \file slang_shader.syn + * slang vertex/fragment shader syntax + * \author Michal Krol + */ + +/* + * usage: + * syn2c slang_shader.syn > slang_shader_syn.h + * + * when modifying or extending this file, several things must be taken into consideration: + * - when adding new operators that were marked as reserved in the initial specification, + * one must only uncomment particular lines of code that refer to operators being added; + * - when adding new shader target, one must reserve new value for shader_type register and + * use it in .if constructs for symbols that are exclusive for that shader; + * - some symbols mimic output of other symbols - the best example is the "for" construct: + * expression "for (foo(); ; bar())" is seen as "for (foo(); true; bar())" by the output + * processor - hence, special care must be taken when rearranging output of essential symbols; + * - order of single-quoted tokens does matter in alternatives - so do not parse "<" operator + * before "<<" and "<<" before "<<="; + * - all double-quoted tokens are internally preprocessed to eliminate problems with parsing + * strings that are prefixes of other strings, like "sampler1D" and "sampler1DShadow"; + */ + +.syntax translation_unit; + +/* revision number - increment after each change affecting emitted output */ +.emtcode REVISION 3 + +/* external declaration */ +.emtcode EXTERNAL_NULL 0 +.emtcode EXTERNAL_FUNCTION_DEFINITION 1 +.emtcode EXTERNAL_DECLARATION 2 + +/* declaration */ +.emtcode DECLARATION_FUNCTION_PROTOTYPE 1 +.emtcode DECLARATION_INIT_DECLARATOR_LIST 2 + +/* function type */ +.emtcode FUNCTION_ORDINARY 0 +.emtcode FUNCTION_CONSTRUCTOR 1 +.emtcode FUNCTION_OPERATOR 2 + +/* operator type */ +.emtcode OPERATOR_ADDASSIGN 1 +.emtcode OPERATOR_SUBASSIGN 2 +.emtcode OPERATOR_MULASSIGN 3 +.emtcode OPERATOR_DIVASSIGN 4 +/*.emtcode OPERATOR_MODASSIGN 5*/ +/*.emtcode OPERATOR_LSHASSIGN 6*/ +/*.emtcode OPERATOR_RSHASSIGN 7*/ +/*.emtcode OPERATOR_ORASSIGN 8*/ +/*.emtcode OPERATOR_XORASSIGN 9*/ +/*.emtcode OPERATOR_ANDASSIGN 10*/ +.emtcode OPERATOR_LOGICALXOR 11 +/*.emtcode OPERATOR_BITOR 12*/ +/*.emtcode OPERATOR_BITXOR 13*/ +/*.emtcode OPERATOR_BITAND 14*/ +.emtcode OPERATOR_LESS 15 +.emtcode OPERATOR_GREATER 16 +.emtcode OPERATOR_LESSEQUAL 17 +.emtcode OPERATOR_GREATEREQUAL 18 +/*.emtcode OPERATOR_LSHIFT 19*/ +/*.emtcode OPERATOR_RSHIFT 20*/ +.emtcode OPERATOR_MULTIPLY 21 +.emtcode OPERATOR_DIVIDE 22 +/*.emtcode OPERATOR_MODULUS 23*/ +.emtcode OPERATOR_INCREMENT 24 +.emtcode OPERATOR_DECREMENT 25 +.emtcode OPERATOR_PLUS 26 +.emtcode OPERATOR_MINUS 27 +/*.emtcode OPERATOR_COMPLEMENT 28*/ +.emtcode OPERATOR_NOT 29 + +/* init declarator list */ +.emtcode DECLARATOR_NONE 0 +.emtcode DECLARATOR_NEXT 1 + +/* variable declaration */ +.emtcode VARIABLE_NONE 0 +.emtcode VARIABLE_IDENTIFIER 1 +.emtcode VARIABLE_INITIALIZER 2 +.emtcode VARIABLE_ARRAY_EXPLICIT 3 +.emtcode VARIABLE_ARRAY_UNKNOWN 4 + +/* type qualifier */ +.emtcode TYPE_QUALIFIER_NONE 0 +.emtcode TYPE_QUALIFIER_CONST 1 +.emtcode TYPE_QUALIFIER_ATTRIBUTE 2 +.emtcode TYPE_QUALIFIER_VARYING 3 +.emtcode TYPE_QUALIFIER_UNIFORM 4 +.emtcode TYPE_QUALIFIER_FIXEDOUTPUT 5 +.emtcode TYPE_QUALIFIER_FIXEDINPUT 6 + +/* type specifier */ +.emtcode TYPE_SPECIFIER_VOID 0 +.emtcode TYPE_SPECIFIER_BOOL 1 +.emtcode TYPE_SPECIFIER_BVEC2 2 +.emtcode TYPE_SPECIFIER_BVEC3 3 +.emtcode TYPE_SPECIFIER_BVEC4 4 +.emtcode TYPE_SPECIFIER_INT 5 +.emtcode TYPE_SPECIFIER_IVEC2 6 +.emtcode TYPE_SPECIFIER_IVEC3 7 +.emtcode TYPE_SPECIFIER_IVEC4 8 +.emtcode TYPE_SPECIFIER_FLOAT 9 +.emtcode TYPE_SPECIFIER_VEC2 10 +.emtcode TYPE_SPECIFIER_VEC3 11 +.emtcode TYPE_SPECIFIER_VEC4 12 +.emtcode TYPE_SPECIFIER_MAT2 13 +.emtcode TYPE_SPECIFIER_MAT3 14 +.emtcode TYPE_SPECIFIER_MAT4 15 +.emtcode TYPE_SPECIFIER_SAMPLER1D 16 +.emtcode TYPE_SPECIFIER_SAMPLER2D 17 +.emtcode TYPE_SPECIFIER_SAMPLER3D 18 +.emtcode TYPE_SPECIFIER_SAMPLERCUBE 19 +.emtcode TYPE_SPECIFIER_SAMPLER1DSHADOW 20 +.emtcode TYPE_SPECIFIER_SAMPLER2DSHADOW 21 +.emtcode TYPE_SPECIFIER_SAMPLER2DRECT 22 +.emtcode TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23 +.emtcode TYPE_SPECIFIER_STRUCT 24 +.emtcode TYPE_SPECIFIER_TYPENAME 25 + +/* OpenGL 2.1 */ +.emtcode TYPE_SPECIFIER_MAT23 26 +.emtcode TYPE_SPECIFIER_MAT32 27 +.emtcode TYPE_SPECIFIER_MAT24 28 +.emtcode TYPE_SPECIFIER_MAT42 29 +.emtcode TYPE_SPECIFIER_MAT34 30 +.emtcode TYPE_SPECIFIER_MAT43 31 + + +/* structure field */ +.emtcode FIELD_NONE 0 +.emtcode FIELD_NEXT 1 +.emtcode FIELD_ARRAY 2 + +/* operation */ +.emtcode OP_END 0 +.emtcode OP_BLOCK_BEGIN_NO_NEW_SCOPE 1 +.emtcode OP_BLOCK_BEGIN_NEW_SCOPE 2 +.emtcode OP_DECLARE 3 +.emtcode OP_ASM 4 +.emtcode OP_BREAK 5 +.emtcode OP_CONTINUE 6 +.emtcode OP_DISCARD 7 +.emtcode OP_RETURN 8 +.emtcode OP_EXPRESSION 9 +.emtcode OP_IF 10 +.emtcode OP_WHILE 11 +.emtcode OP_DO 12 +.emtcode OP_FOR 13 +.emtcode OP_PUSH_VOID 14 +.emtcode OP_PUSH_BOOL 15 +.emtcode OP_PUSH_INT 16 +.emtcode OP_PUSH_FLOAT 17 +.emtcode OP_PUSH_IDENTIFIER 18 +.emtcode OP_SEQUENCE 19 +.emtcode OP_ASSIGN 20 +.emtcode OP_ADDASSIGN 21 +.emtcode OP_SUBASSIGN 22 +.emtcode OP_MULASSIGN 23 +.emtcode OP_DIVASSIGN 24 +/*.emtcode OP_MODASSIGN 25*/ +/*.emtcode OP_LSHASSIGN 26*/ +/*.emtcode OP_RSHASSIGN 27*/ +/*.emtcode OP_ORASSIGN 28*/ +/*.emtcode OP_XORASSIGN 29*/ +/*.emtcode OP_ANDASSIGN 30*/ +.emtcode OP_SELECT 31 +.emtcode OP_LOGICALOR 32 +.emtcode OP_LOGICALXOR 33 +.emtcode OP_LOGICALAND 34 +/*.emtcode OP_BITOR 35*/ +/*.emtcode OP_BITXOR 36*/ +/*.emtcode OP_BITAND 37*/ +.emtcode OP_EQUAL 38 +.emtcode OP_NOTEQUAL 39 +.emtcode OP_LESS 40 +.emtcode OP_GREATER 41 +.emtcode OP_LESSEQUAL 42 +.emtcode OP_GREATEREQUAL 43 +/*.emtcode OP_LSHIFT 44*/ +/*.emtcode OP_RSHIFT 45*/ +.emtcode OP_ADD 46 +.emtcode OP_SUBTRACT 47 +.emtcode OP_MULTIPLY 48 +.emtcode OP_DIVIDE 49 +/*.emtcode OP_MODULUS 50*/ +.emtcode OP_PREINCREMENT 51 +.emtcode OP_PREDECREMENT 52 +.emtcode OP_PLUS 53 +.emtcode OP_MINUS 54 +/*.emtcode OP_COMPLEMENT 55*/ +.emtcode OP_NOT 56 +.emtcode OP_SUBSCRIPT 57 +.emtcode OP_CALL 58 +.emtcode OP_FIELD 59 +.emtcode OP_POSTINCREMENT 60 +.emtcode OP_POSTDECREMENT 61 + +/* parameter qualifier */ +.emtcode PARAM_QUALIFIER_IN 0 +.emtcode PARAM_QUALIFIER_OUT 1 +.emtcode PARAM_QUALIFIER_INOUT 2 + +/* function parameter */ +.emtcode PARAMETER_NONE 0 +.emtcode PARAMETER_NEXT 1 + +/* function parameter array presence */ +.emtcode PARAMETER_ARRAY_NOT_PRESENT 0 +.emtcode PARAMETER_ARRAY_PRESENT 1 + +.errtext INVALID_EXTERNAL_DECLARATION "2001: Invalid external declaration." +.errtext INVALID_OPERATOR_OVERRIDE "2002: Invalid operator override." +.errtext LBRACE_EXPECTED "2003: '{' expected but '$err_token$' found." +.errtext LPAREN_EXPECTED "2004: '(' expected but '$err_token$' found." +.errtext RPAREN_EXPECTED "2005: ')' expected but '$err_token$' found." + +/* tells whether the shader that is being parsed is a built-in shader or not */ +/* 0 - normal behaviour */ +/* 1 - accepts constructor and operator definitions and __asm statements */ +/* the implementation will set it to 1 when compiling internal built-in shaders */ +.regbyte parsing_builtin 0 + +/* holds the type of the shader being parsed; possible values are listed below */ +/* FRAGMENT_SHADER 1 */ +/* VERTEX_SHADER 2 */ +/* shader type is set by the caller before parsing */ +.regbyte shader_type 0 + +/* + <variable_identifier> ::= <identifier> +*/ +variable_identifier + identifier .emit OP_PUSH_IDENTIFIER; + +/* + <primary_expression> ::= <variable_identifier> + | <intconstant> + | <floatconstant> + | <boolconstant> + | "(" <expression> ")" +*/ +primary_expression + floatconstant .or boolconstant .or intconstant .or variable_identifier .or primary_expression_1; +primary_expression_1 + lparen .and expression .and rparen; + +/* + <postfix_expression> ::= <primary_expression> + | <postfix_expression> "[" <integer_expression> "]" + | <function_call> + | <postfix_expression> "." <field_selection> + | <postfix_expression> "++" + | <postfix_expression> "--" +*/ +postfix_expression + postfix_expression_1 .and .loop postfix_expression_2; +postfix_expression_1 + function_call .or primary_expression; +postfix_expression_2 + postfix_expression_3 .or postfix_expression_4 .or + plusplus .emit OP_POSTINCREMENT .or + minusminus .emit OP_POSTDECREMENT; +postfix_expression_3 + lbracket .and integer_expression .and rbracket .emit OP_SUBSCRIPT; +postfix_expression_4 + dot .and field_selection .emit OP_FIELD; + +/* + <integer_expression> ::= <expression> +*/ +integer_expression + expression; + +/* + <function_call> ::= <function_call_generic> +*/ +function_call + function_call_generic .emit OP_CALL .and .true .emit OP_END; + +/* + <function_call_generic> ::= <function_call_header_with_parameters> ")" + | <function_call_header_no_parameters> ")" +*/ +function_call_generic + function_call_generic_1 .or function_call_generic_2; +function_call_generic_1 + function_call_header_with_parameters .and rparen .error RPAREN_EXPECTED; +function_call_generic_2 + function_call_header_no_parameters .and rparen .error RPAREN_EXPECTED; + +/* + <function_call_header_no_parameters>::= <function_call_header> "void" + | <function_call_header> +*/ +function_call_header_no_parameters + function_call_header .and function_call_header_no_parameters_1; +function_call_header_no_parameters_1 + "void" .or .true; + +/* + <function_call_header_with_parameters>::= <function_call_header> <assignment_expression> + | <function_call_header_with_parameters> "," + <assignment_expression> +*/ +function_call_header_with_parameters + function_call_header .and assignment_expression .and .true .emit OP_END .and + .loop function_call_header_with_parameters_1; +function_call_header_with_parameters_1 + comma .and assignment_expression .and .true .emit OP_END; + +/* + <function_call_header> ::= <function_identifier> "(" +*/ +function_call_header + function_identifier .and lparen; + +/* + <function_identifier> ::= <constructor_identifier> + | <identifier> + +note: <constructor_identifier> has been deleted +*/ +function_identifier + identifier; + +/* + <unary_expression> ::= <postfix_expression> + | "++" <unary_expression> + | "--" <unary_expression> + | <unary_operator> <unary_expression> + + <unary_operator> ::= "+" + | "-" + | "!" + | "~" // reserved +*/ +unary_expression + postfix_expression .or unary_expression_1 .or unary_expression_2 .or unary_expression_3 .or + unary_expression_4 .or unary_expression_5/* .or unary_expression_6*/; +unary_expression_1 + plusplus .and unary_expression .and .true .emit OP_PREINCREMENT; +unary_expression_2 + minusminus .and unary_expression .and .true .emit OP_PREDECREMENT; +unary_expression_3 + plus .and unary_expression .and .true .emit OP_PLUS; +unary_expression_4 + minus .and unary_expression .and .true .emit OP_MINUS; +unary_expression_5 + bang .and unary_expression .and .true .emit OP_NOT; +/*unary_expression_6 + tilde .and unary_expression .and .true .emit OP_COMPLEMENT;*/ + +/* + <multiplicative_expression> ::= <unary_expression> + | <multiplicative_expression> "*" <unary_expression> + | <multiplicative_expression> "/" <unary_expression> + | <multiplicative_expression> "%" <unary_expression> // reserved +*/ +multiplicative_expression + unary_expression .and .loop multiplicative_expression_1; +multiplicative_expression_1 + multiplicative_expression_2 .or multiplicative_expression_3/* .or multiplicative_expression_4*/; +multiplicative_expression_2 + star .and unary_expression .and .true .emit OP_MULTIPLY; +multiplicative_expression_3 + slash .and unary_expression .and .true .emit OP_DIVIDE; +/*multiplicative_expression_4 + percent .and unary_expression .and .true .emit OP_MODULUS;*/ + +/* + <additive_expression> ::= <multiplicative_expression> + | <additive_expression> "+" <multiplicative_expression> + | <additive_expression> "-" <multiplicative_expression> +*/ +additive_expression + multiplicative_expression .and .loop additive_expression_1; +additive_expression_1 + additive_expression_2 .or additive_expression_3; +additive_expression_2 + plus .and multiplicative_expression .and .true .emit OP_ADD; +additive_expression_3 + minus .and multiplicative_expression .and .true .emit OP_SUBTRACT; + +/* + <shift_expression> ::= <additive_expression> + | <shift_expression> "<<" <additive_expression> // reserved + | <shift_expression> ">>" <additive_expression> // reserved +*/ +shift_expression + additive_expression/* .and .loop shift_expression_1*/; +/*shift_expression_1 + shift_expression_2 .or shift_expression_3;*/ +/*shift_expression_2 + lessless .and additive_expression .and .true .emit OP_LSHIFT;*/ +/*shift_expression_3 + greatergreater .and additive_expression .and .true .emit OP_RSHIFT;*/ + +/* + <relational_expression> ::= <shift_expression> + | <relational_expression> "<" <shift_expression> + | <relational_expression> ">" <shift_expression> + | <relational_expression> "<=" <shift_expression> + | <relational_expression> ">=" <shift_expression> +*/ +relational_expression + shift_expression .and .loop relational_expression_1; +relational_expression_1 + relational_expression_2 .or relational_expression_3 .or relational_expression_4 .or + relational_expression_5; +relational_expression_2 + lessequals .and shift_expression .and .true .emit OP_LESSEQUAL; +relational_expression_3 + greaterequals .and shift_expression .and .true .emit OP_GREATEREQUAL; +relational_expression_4 + less .and shift_expression .and .true .emit OP_LESS; +relational_expression_5 + greater .and shift_expression .and .true .emit OP_GREATER; + +/* + <equality_expression> ::= <relational_expression> + | <equality_expression> "==" <relational_expression> + | <equality_expression> "!=" <relational_expression> +*/ +equality_expression + relational_expression .and .loop equality_expression_1; +equality_expression_1 + equality_expression_2 .or equality_expression_3; +equality_expression_2 + equalsequals .and relational_expression .and .true .emit OP_EQUAL; +equality_expression_3 + bangequals .and relational_expression .and .true .emit OP_NOTEQUAL; + +/* + <and_expression> ::= <equality_expression> + | <and_expression> "&" <equality_expression> // reserved +*/ +and_expression + equality_expression/* .and .loop and_expression_1*/; +/*and_expression_1 + ampersand .and equality_expression .and .true .emit OP_BITAND;*/ + +/* + <exclusive_or_expression> ::= <and_expression> + | <exclusive_or_expression> "^" <and_expression> // reserved +*/ +exclusive_or_expression + and_expression/* .and .loop exclusive_or_expression_1*/; +/*exclusive_or_expression_1 + caret .and and_expression .and .true .emit OP_BITXOR;*/ + +/* + <inclusive_or_expression> ::= <exclusive_or_expression> + | <inclusive_or_expression> "|" <exclusive_or_expression> // reserved +*/ +inclusive_or_expression + exclusive_or_expression/* .and .loop inclusive_or_expression_1*/; +/*inclusive_or_expression_1 + bar .and exclusive_or_expression .and .true .emit OP_BITOR;*/ + +/* + <logical_and_expression> ::= <inclusive_or_expression> + | <logical_and_expression> "&&" <inclusive_or_expression> +*/ +logical_and_expression + inclusive_or_expression .and .loop logical_and_expression_1; +logical_and_expression_1 + ampersandampersand .and inclusive_or_expression .and .true .emit OP_LOGICALAND; + +/* + <logical_xor_expression> ::= <logical_and_expression> + | <logical_xor_expression> "^^" <logical_and_expression> +*/ +logical_xor_expression + logical_and_expression .and .loop logical_xor_expression_1; +logical_xor_expression_1 + caretcaret .and logical_and_expression .and .true .emit OP_LOGICALXOR; + +/* + <logical_or_expression> ::= <logical_xor_expression> + | <logical_or_expression> "||" <logical_xor_expression> +*/ +logical_or_expression + logical_xor_expression .and .loop logical_or_expression_1; +logical_or_expression_1 + barbar .and logical_xor_expression .and .true .emit OP_LOGICALOR; + +/* + <conditional_expression> ::= <logical_or_expression> + | <logical_or_expression> "?" <expression> ":" + <conditional_expression> +*/ +conditional_expression + logical_or_expression .and .loop conditional_expression_1; +conditional_expression_1 + question .and expression .and colon .and conditional_expression .and .true .emit OP_SELECT; + +/* + <assignment_expression> ::= <conditional_expression> + | <unary_expression> <assignment_operator> + <assignment_expression> + + <assignment_operator> ::= "=" + | "*=" + | "/=" + | "+=" + | "-=" + | "%=" // reserved + | "<<=" // reserved + | ">>=" // reserved + | "&=" // reserved + | "^=" // reserved + | "|=" // reserved +*/ +assignment_expression + assignment_expression_1 .or assignment_expression_2 .or assignment_expression_3 .or + assignment_expression_4 .or assignment_expression_5/* .or assignment_expression_6 .or + assignment_expression_7 .or assignment_expression_8 .or assignment_expression_9 .or + assignment_expression_10 .or assignment_expression_11*/ .or conditional_expression; +assignment_expression_1 + unary_expression .and equals .and assignment_expression .and .true .emit OP_ASSIGN; +assignment_expression_2 + unary_expression .and starequals .and assignment_expression .and .true .emit OP_MULASSIGN; +assignment_expression_3 + unary_expression .and slashequals .and assignment_expression .and .true .emit OP_DIVASSIGN; +assignment_expression_4 + unary_expression .and plusequals .and assignment_expression .and .true .emit OP_ADDASSIGN; +assignment_expression_5 + unary_expression .and minusequals .and assignment_expression .and .true .emit OP_SUBASSIGN; +/*assignment_expression_6 + unary_expression .and percentequals .and assignment_expression .and .true .emit OP_MODASSIGN;*/ +/*assignment_expression_7 + unary_expression .and lesslessequals .and assignment_expression .and .true .emit OP_LSHASSIGN;*/ +/*assignment_expression_8 + unary_expression .and greatergreaterequals .and assignment_expression .and + .true .emit OP_RSHASSIGN;*/ +/*assignment_expression_9 + unary_expression .and ampersandequals .and assignment_expression .and .true .emit OP_ANDASSIGN;*/ +/*assignment_expression_10 + unary_expression .and caretequals .and assignment_expression .and .true .emit OP_XORASSIGN;*/ +/*assignment_expression_11 + unary_expression .and barequals .and assignment_expression .and .true .emit OP_ORASSIGN;*/ + +/* + <expression> ::= <assignment_expression> + | <expression> "," <assignment_expression> +*/ +expression + assignment_expression .and .loop expression_1; +expression_1 + comma .and assignment_expression .and .true .emit OP_SEQUENCE; + +/* + <constant_expression> ::= <conditional_expression> +*/ +constant_expression + conditional_expression .and .true .emit OP_END; + +/* + <declaration> ::= <function_prototype> ";" + | <init_declarator_list> ";" +*/ +declaration + declaration_1 .or declaration_2; +declaration_1 + function_prototype .emit DECLARATION_FUNCTION_PROTOTYPE .and semicolon; +declaration_2 + init_declarator_list .emit DECLARATION_INIT_DECLARATOR_LIST .and semicolon; + +/* + <function_prototype> ::= <function_header> "void" ")" + | <function_declarator> ")" +*/ +function_prototype + function_prototype_1 .or function_prototype_2; +function_prototype_1 + function_header .and "void" .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE; +function_prototype_2 + function_declarator .and rparen .error RPAREN_EXPECTED .emit PARAMETER_NONE; + +/* + <function_declarator> ::= <function_header> + | <function_header_with_parameters> +*/ +function_declarator + function_header_with_parameters .or function_header; + +/* + <function_header_with_parameters> ::= <function_header> <parameter_declaration> + | <function_header_with_parameters> "," + <parameter_declaration> +*/ +function_header_with_parameters + function_header .and parameter_declaration .and .loop function_header_with_parameters_1; +function_header_with_parameters_1 + comma .and parameter_declaration; + +/* + <function_header> ::= <fully_specified_type> <identifier> "(" +*/ +function_header + function_header_nospace .or function_header_space; +function_header_space + fully_specified_type_space .and space .and function_decl_identifier .and lparen; +function_header_nospace + fully_specified_type_nospace .and function_decl_identifier .and lparen; + +/* + <function_decl_identifier> ::= "__constructor" + | <__operator> + | <identifier> + +note: this is an extension to the standard language specification - normally slang disallows + operator and constructor prototypes and definitions +*/ +function_decl_identifier + .if (parsing_builtin != 0) __operator .emit FUNCTION_OPERATOR .or + .if (parsing_builtin != 0) "__constructor" .emit FUNCTION_CONSTRUCTOR .or + identifier .emit FUNCTION_ORDINARY; + +/* + <__operator> ::= "__operator" <overriden_op> + +note: this is an extension to the standard language specification - normally slang disallows + operator prototypes and definitions +*/ +__operator + "__operator" .and overriden_operator .error INVALID_OPERATOR_OVERRIDE; + +/* + <overriden_op> ::= "=" + | "+=" + | "-=" + | "*=" + | "/=" + | "%=" // reserved + | "<<=" // reserved + | ">>=" // reserved + | "&=" // reserved + | "^=" // reserved + | "|=" // reserved + | "^^" + | "|" // reserved + | "^" // reserved + | "&" // reserved + | "==" + | "!=" + | "<" + | ">" + | "<=" + | ">=" + | "<<" // reserved + | ">>" // reserved + | "*" + | "/" + | "%" // reserved + | "++" + | "--" + | "+" + | "-" + | "~" // reserved + | "!" + +note: this is an extension to the standard language specification - normally slang disallows + operator prototypes and definitions +*/ +overriden_operator + plusplus .emit OPERATOR_INCREMENT .or + plusequals .emit OPERATOR_ADDASSIGN .or + plus .emit OPERATOR_PLUS .or + minusminus .emit OPERATOR_DECREMENT .or + minusequals .emit OPERATOR_SUBASSIGN .or + minus .emit OPERATOR_MINUS .or + bang .emit OPERATOR_NOT .or + starequals .emit OPERATOR_MULASSIGN .or + star .emit OPERATOR_MULTIPLY .or + slashequals .emit OPERATOR_DIVASSIGN .or + slash .emit OPERATOR_DIVIDE .or + lessequals .emit OPERATOR_LESSEQUAL .or + /*lesslessequals .emit OPERATOR_LSHASSIGN .or*/ + /*lessless .emit OPERATOR_LSHIFT .or*/ + less .emit OPERATOR_LESS .or + greaterequals .emit OPERATOR_GREATEREQUAL .or + /*greatergreaterequals .emit OPERATOR_RSHASSIGN .or*/ + /*greatergreater .emit OPERATOR_RSHIFT .or*/ + greater .emit OPERATOR_GREATER .or + /*percentequals .emit OPERATOR_MODASSIGN .or*/ + /*percent .emit OPERATOR_MODULUS .or*/ + /*ampersandequals .emit OPERATOR_ANDASSIGN */ + /*ampersand .emit OPERATOR_BITAND .or*/ + /*barequals .emit OPERATOR_ORASSIGN .or*/ + /*bar .emit OPERATOR_BITOR .or*/ + /*tilde .emit OPERATOR_COMPLEMENT .or*/ + /*caretequals .emit OPERATOR_XORASSIGN .or*/ + caretcaret .emit OPERATOR_LOGICALXOR /*.or + caret .emit OPERATOR_BITXOR*/; + +/* + <parameter_declarator> ::= <type_specifier> <identifier> + | <type_specifier> <identifier> "[" <constant_expression> + "]" +*/ +parameter_declarator + parameter_declarator_nospace .or parameter_declarator_space; +parameter_declarator_nospace + type_specifier_nospace .and identifier .and parameter_declarator_1; +parameter_declarator_space + type_specifier_space .and space .and identifier .and parameter_declarator_1; +parameter_declarator_1 + parameter_declarator_2 .emit PARAMETER_ARRAY_PRESENT .or + .true .emit PARAMETER_ARRAY_NOT_PRESENT; +parameter_declarator_2 + lbracket .and constant_expression .and rbracket; + +/* + <parameter_declaration> ::= <type_qualifier> <parameter_qualifier> + <parameter_declarator> + | <type_qualifier> <parameter_qualifier> + <parameter_type_specifier> + | <parameter_qualifier> <parameter_declarator> + | <parameter_qualifier> <parameter_type_specifier> +*/ +parameter_declaration + parameter_declaration_1 .emit PARAMETER_NEXT; +parameter_declaration_1 + parameter_declaration_2 .or parameter_declaration_3; +parameter_declaration_2 + type_qualifier .and space .and parameter_qualifier .and parameter_declaration_4; +parameter_declaration_3 + parameter_qualifier .emit TYPE_QUALIFIER_NONE .and parameter_declaration_4; +parameter_declaration_4 + parameter_declarator .or parameter_type_specifier; + +/* + <parameter_qualifier> ::= "in" + | "out" + | "inout" + | "" +*/ +parameter_qualifier + parameter_qualifier_1 .or .true .emit PARAM_QUALIFIER_IN; +parameter_qualifier_1 + parameter_qualifier_2 .and space; +parameter_qualifier_2 + "in" .emit PARAM_QUALIFIER_IN .or + "out" .emit PARAM_QUALIFIER_OUT .or + "inout" .emit PARAM_QUALIFIER_INOUT; + +/* + <parameter_type_specifier> ::= <type_specifier> + | <type_specifier> "[" <constant_expression> "]" +*/ +parameter_type_specifier + parameter_type_specifier_1 .and .true .emit '\0' .and parameter_type_specifier_2; +parameter_type_specifier_1 + type_specifier_nospace .or type_specifier_space; +parameter_type_specifier_2 + parameter_type_specifier_3 .emit PARAMETER_ARRAY_PRESENT .or + .true .emit PARAMETER_ARRAY_NOT_PRESENT; +parameter_type_specifier_3 + lbracket .and constant_expression .and rbracket; + +/* + <init_declarator_list> ::= <single_declaration> + | <init_declarator_list> "," <identifier> + | <init_declarator_list> "," <identifier> "[" "]" + | <init_declarator_list> "," <identifier> "[" + <constant_expression> "]" + | <init_declarator_list> "," <identifier> "=" + <initializer> +*/ +init_declarator_list + single_declaration .and .loop init_declarator_list_1 .emit DECLARATOR_NEXT .and + .true .emit DECLARATOR_NONE; +init_declarator_list_1 + comma .and identifier .emit VARIABLE_IDENTIFIER .and init_declarator_list_2; +init_declarator_list_2 + init_declarator_list_3 .or init_declarator_list_4 .or .true .emit VARIABLE_NONE; +init_declarator_list_3 + equals .and initializer .emit VARIABLE_INITIALIZER; +init_declarator_list_4 + lbracket .and init_declarator_list_5 .and rbracket; +init_declarator_list_5 + constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN; + +/* + <single_declaration> ::= <fully_specified_type> + | <fully_specified_type> <identifier> + | <fully_specified_type> <identifier> "[" "]" + | <fully_specified_type> <identifier> "[" + <constant_expression> "]" + | <fully_specified_type> <identifier> "=" <initializer> +*/ +single_declaration + single_declaration_nospace .or single_declaration_space; +single_declaration_space + fully_specified_type_space .and single_declaration_space_1; +single_declaration_nospace + fully_specified_type_nospace .and single_declaration_nospace_1; +single_declaration_space_1 + single_declaration_space_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE; +single_declaration_nospace_1 + single_declaration_nospace_2 .emit VARIABLE_IDENTIFIER .or .true .emit VARIABLE_NONE; +single_declaration_space_2 + space .and identifier .and single_declaration_3; +single_declaration_nospace_2 + identifier .and single_declaration_3; +single_declaration_3 + single_declaration_4 .or single_declaration_5 .or .true .emit VARIABLE_NONE; +single_declaration_4 + equals .and initializer .emit VARIABLE_INITIALIZER; +single_declaration_5 + lbracket .and single_declaration_6 .and rbracket; +single_declaration_6 + constant_expression .emit VARIABLE_ARRAY_EXPLICIT .or .true .emit VARIABLE_ARRAY_UNKNOWN; + +/* + <fully_specified_type> ::= <type_specifier> + | <type_qualifier> <type_specifier> +*/ +fully_specified_type_space + fully_specified_type_1 .and type_specifier_space; +fully_specified_type_nospace + fully_specified_type_1 .and type_specifier_nospace; +fully_specified_type_1 + fully_specified_type_2 .or .true .emit TYPE_QUALIFIER_NONE; +fully_specified_type_2 + type_qualifier .and space; + +/* + <type_qualifier> ::= "const" + | "attribute" // Vertex only. + | "varying" + | "uniform" + | "__fixed_output" + | "__fixed_input" + +note: this is an extension to the standard language specification - normally slang disallows + __fixed_output and __fixed_input type qualifiers +*/ +type_qualifier + "const" .emit TYPE_QUALIFIER_CONST .or + .if (shader_type == 2) "attribute" .emit TYPE_QUALIFIER_ATTRIBUTE .or + "varying" .emit TYPE_QUALIFIER_VARYING .or + "uniform" .emit TYPE_QUALIFIER_UNIFORM .or + .if (parsing_builtin != 0) "__fixed_output" .emit TYPE_QUALIFIER_FIXEDOUTPUT .or + .if (parsing_builtin != 0) "__fixed_input" .emit TYPE_QUALIFIER_FIXEDINPUT; + +/* + <type_specifier> ::= "void" + | "float" + | "int" + | "bool" + | "vec2" + | "vec3" + | "vec4" + | "bvec2" + | "bvec3" + | "bvec4" + | "ivec2" + | "ivec3" + | "ivec4" + | "mat2" + | "mat3" + | "mat4" + | "mat2x3" + | "mat3x2" + | "mat2x4" + | "mat4x2" + | "mat3x4" + | "mat4x3" + | "sampler1D" + | "sampler2D" + | "sampler3D" + | "samplerCube" + | "sampler1DShadow" + | "sampler2DShadow" + | "sampler2DRect" + | "sampler2DRectShadow" + | <struct_specifier> + | <type_name> +*/ +type_specifier_space + "void" .emit TYPE_SPECIFIER_VOID .or + "float" .emit TYPE_SPECIFIER_FLOAT .or + "int" .emit TYPE_SPECIFIER_INT .or + "bool" .emit TYPE_SPECIFIER_BOOL .or + "vec2" .emit TYPE_SPECIFIER_VEC2 .or + "vec3" .emit TYPE_SPECIFIER_VEC3 .or + "vec4" .emit TYPE_SPECIFIER_VEC4 .or + "bvec2" .emit TYPE_SPECIFIER_BVEC2 .or + "bvec3" .emit TYPE_SPECIFIER_BVEC3 .or + "bvec4" .emit TYPE_SPECIFIER_BVEC4 .or + "ivec2" .emit TYPE_SPECIFIER_IVEC2 .or + "ivec3" .emit TYPE_SPECIFIER_IVEC3 .or + "ivec4" .emit TYPE_SPECIFIER_IVEC4 .or + "mat2" .emit TYPE_SPECIFIER_MAT2 .or + "mat3" .emit TYPE_SPECIFIER_MAT3 .or + "mat4" .emit TYPE_SPECIFIER_MAT4 .or + "mat2x3" .emit TYPE_SPECIFIER_MAT23 .or + "mat3x2" .emit TYPE_SPECIFIER_MAT32 .or + "mat2x4" .emit TYPE_SPECIFIER_MAT24 .or + "mat4x2" .emit TYPE_SPECIFIER_MAT42 .or + "mat3x4" .emit TYPE_SPECIFIER_MAT34 .or + "mat4x3" .emit TYPE_SPECIFIER_MAT43 .or + "sampler1D" .emit TYPE_SPECIFIER_SAMPLER1D .or + "sampler2D" .emit TYPE_SPECIFIER_SAMPLER2D .or + "sampler3D" .emit TYPE_SPECIFIER_SAMPLER3D .or + "samplerCube" .emit TYPE_SPECIFIER_SAMPLERCUBE .or + "sampler1DShadow" .emit TYPE_SPECIFIER_SAMPLER1DSHADOW .or + "sampler2DShadow" .emit TYPE_SPECIFIER_SAMPLER2DSHADOW .or + "sampler2DRect" .emit TYPE_SPECIFIER_SAMPLER2DRECT .or + "sampler2DRectShadow" .emit TYPE_SPECIFIER_SAMPLER2DRECTSHADOW .or + type_name .emit TYPE_SPECIFIER_TYPENAME; +type_specifier_nospace + struct_specifier .emit TYPE_SPECIFIER_STRUCT; + +/* + <struct_specifier> ::= "struct" <identifier> "{" <struct_declaration_list> "}" + | "struct" "{" <struct_declaration_list> "}" +*/ +struct_specifier + "struct" .and struct_specifier_1 .and optional_space .and lbrace .error LBRACE_EXPECTED .and + struct_declaration_list .and rbrace .emit FIELD_NONE; +struct_specifier_1 + struct_specifier_2 .or .true .emit '\0'; +struct_specifier_2 + space .and identifier; + +/* + <struct_declaration_list> ::= <struct_declaration> + | <struct_declaration_list> <struct_declaration> +*/ +struct_declaration_list + struct_declaration .and .loop struct_declaration .emit FIELD_NEXT; + +/* + <struct_declaration> ::= <type_specifier> <struct_declarator_list> ";" +*/ +struct_declaration + struct_declaration_nospace .or struct_declaration_space; +struct_declaration_space + type_specifier_space .and space .and struct_declarator_list .and semicolon .emit FIELD_NONE; +struct_declaration_nospace + type_specifier_nospace .and struct_declarator_list .and semicolon .emit FIELD_NONE; + +/* + <struct_declarator_list> ::= <struct_declarator> + | <struct_declarator_list> "," <struct_declarator> +*/ +struct_declarator_list + struct_declarator .and .loop struct_declarator_list_1 .emit FIELD_NEXT; +struct_declarator_list_1 + comma .and struct_declarator; + +/* + <struct_declarator> ::= <identifier> + | <identifier> "[" <constant_expression> "]" +*/ +struct_declarator + identifier .and struct_declarator_1; +struct_declarator_1 + struct_declarator_2 .emit FIELD_ARRAY .or .true .emit FIELD_NONE; +struct_declarator_2 + lbracket .and constant_expression .and rbracket; + +/* + <initializer> ::= <assignment_expression> +*/ +initializer + assignment_expression .and .true .emit OP_END; + +/* + <declaration_statement> ::= <declaration> +*/ +declaration_statement + declaration; + +/* + <statement> ::= <compound_statement> + | <simple_statement> +*/ +statement + compound_statement .or simple_statement; +statement_space + compound_statement .or statement_space_1; +statement_space_1 + space .and simple_statement; + +/* + <simple_statement> ::= <__asm_statement> + | <selection_statement> + | <iteration_statement> + | <jump_statement> + | <expression_statement> + | <declaration_statement> + +note: this is an extension to the standard language specification - normally slang disallows + use of __asm statements +*/ +simple_statement + .if (parsing_builtin != 0) __asm_statement .emit OP_ASM .or + selection_statement .or + iteration_statement .or + jump_statement .or + expression_statement .emit OP_EXPRESSION .or + declaration_statement .emit OP_DECLARE; + +/* + <compound_statement> ::= "{" "}" + | "{" <statement_list> "}" +*/ +compound_statement + compound_statement_1 .emit OP_BLOCK_BEGIN_NEW_SCOPE .and .true .emit OP_END; +compound_statement_1 + compound_statement_2 .or compound_statement_3; +compound_statement_2 + lbrace .and rbrace; +compound_statement_3 + lbrace .and statement_list .and rbrace; + +/* + <statement_no_new_scope> ::= <compound_statement_no_new_scope> + | <simple_statement> +*/ +statement_no_new_scope + compound_statement_no_new_scope .or simple_statement; + +/* + <compound_statement_no_new_scope> ::= "{" "}" + | "{" <statement_list> "}" +*/ +compound_statement_no_new_scope + compound_statement_no_new_scope_1 .emit OP_BLOCK_BEGIN_NO_NEW_SCOPE .and .true .emit OP_END; +compound_statement_no_new_scope_1 + compound_statement_no_new_scope_2 .or compound_statement_no_new_scope_3; +compound_statement_no_new_scope_2 + lbrace .and rbrace; +compound_statement_no_new_scope_3 + lbrace .and statement_list .and rbrace; + +/* + <statement_list> ::= <statement> + | <statement_list> <statement> +*/ +statement_list + statement .and .loop statement; + +/* + <expression_statement> ::= ";" + | <expression> ";" +*/ +expression_statement + expression_statement_1 .or expression_statement_2; +expression_statement_1 + semicolon .emit OP_PUSH_VOID .emit OP_END; +expression_statement_2 + expression .and semicolon .emit OP_END; + +/* + <selection_statement> ::= "if" "(" <expression> ")" <selection_rest_statement> +*/ +selection_statement + "if" .emit OP_IF .and lparen .error LPAREN_EXPECTED .and expression .and + rparen .error RPAREN_EXPECTED .emit OP_END .and selection_rest_statement; + +/* + <selection_rest_statement> ::= <statement> "else" <statement> + | <statement> +*/ +selection_rest_statement + statement .and selection_rest_statement_1; +selection_rest_statement_1 + selection_rest_statement_2 .or .true .emit OP_EXPRESSION .emit OP_PUSH_VOID .emit OP_END; +selection_rest_statement_2 + "else" .and optional_space .and statement; + +/* + <condition> ::= <expression> + | <fully_specified_type> <identifier> "=" <initializer> + +note: if <condition_1> is executed, the emit format must match <declaration> emit format +*/ +condition + condition_1 .emit OP_DECLARE .emit DECLARATION_INIT_DECLARATOR_LIST .or + condition_3 .emit OP_EXPRESSION; +condition_1 + condition_1_nospace .or condition_1_space; +condition_1_nospace + fully_specified_type_nospace .and condition_2; +condition_1_space + fully_specified_type_space .and space .and condition_2; +condition_2 + identifier .emit VARIABLE_IDENTIFIER .and equals .emit VARIABLE_INITIALIZER .and + initializer .and .true .emit DECLARATOR_NONE; +condition_3 + expression .and .true .emit OP_END; + +/* + <iteration_statement> ::= "while" "(" <condition> ")" <statement> + | "do" <statement> "while" "(" <expression> ")" ";" + | "for" "(" <for_init_statement> <for_rest_statement> ")" + <statement_no_new_scope> +*/ +iteration_statement + iteration_statement_1 .or iteration_statement_2 .or iteration_statement_3; +iteration_statement_1 + "while" .emit OP_WHILE .and lparen .error LPAREN_EXPECTED .and condition .and + rparen .error RPAREN_EXPECTED .and statement; +iteration_statement_2 + "do" .emit OP_DO .and statement_space .and "while" .and lparen .error LPAREN_EXPECTED .and + expression .and rparen .error RPAREN_EXPECTED .emit OP_END .and semicolon; +iteration_statement_3 + "for" .emit OP_FOR .and lparen .error LPAREN_EXPECTED .and for_init_statement .and + for_rest_statement .and rparen .error RPAREN_EXPECTED .and statement_no_new_scope; + +/* + <for_init_statement> ::= <expression_statement> + | <declaration_statement> +*/ +for_init_statement + expression_statement .emit OP_EXPRESSION .or declaration_statement .emit OP_DECLARE; + +/* + <conditionopt> ::= <condition> + | "" + +note: <conditionopt> is used only by "for" statement - if <condition> is ommitted, parser + simulates default behaviour, that is simulates "true" expression +*/ +conditionopt + condition .or + .true .emit OP_EXPRESSION .emit OP_PUSH_BOOL .emit 2 .emit '1' .emit '\0' .emit OP_END; + +/* + <for_rest_statement> ::= <conditionopt> ";" + | <conditionopt> ";" <expression> +*/ +for_rest_statement + conditionopt .and semicolon .and for_rest_statement_1; +for_rest_statement_1 + for_rest_statement_2 .or .true .emit OP_PUSH_VOID .emit OP_END; +for_rest_statement_2 + expression .and .true .emit OP_END; + +/* + <jump_statement> ::= "continue" ";" + | "break" ";" + | "return" ";" + | "return" <expression> ";" + | "discard" ";" // Fragment shader only. +*/ +jump_statement + jump_statement_1 .or jump_statement_2 .or jump_statement_3 .or jump_statement_4 .or + .if (shader_type == 1) jump_statement_5; +jump_statement_1 + "continue" .and semicolon .emit OP_CONTINUE; +jump_statement_2 + "break" .and semicolon .emit OP_BREAK; +jump_statement_3 + "return" .emit OP_RETURN .and optional_space .and expression .and semicolon .emit OP_END; +jump_statement_4 + "return" .emit OP_RETURN .and semicolon .emit OP_PUSH_VOID .emit OP_END; +jump_statement_5 + "discard" .and semicolon .emit OP_DISCARD; + +/* + <__asm_statement> ::= "__asm" <identifier> <asm_arguments> ";" + +note: this is an extension to the standard language specification - normally slang disallows + __asm statements +*/ +__asm_statement + "__asm" .and space .and identifier .and space .and asm_arguments .and semicolon .emit OP_END; + +/* + <asm_arguments> ::= <asm_argument> + | <asm_arguments> "," <asm_argument> + +note: this is an extension to the standard language specification - normally slang disallows + __asm statements +*/ +asm_arguments + asm_argument .and .true .emit OP_END .and .loop asm_arguments_1; +asm_arguments_1 + comma .and asm_argument .and .true .emit OP_END; + +/* + <asm_argument> ::= <variable_identifier> + | <floatconstant> + +note: this is an extension to the standard language specification - normally slang disallows + __asm statements +*/ +asm_argument + var_with_field .or + variable_identifier .or + floatconstant; + +var_with_field + variable_identifier .and dot .and field_selection .emit OP_FIELD; + +/* + <translation_unit> ::= <external_declaration> + | <translation_unit> <external_declaration> +*/ +translation_unit + optional_space .emit REVISION .and external_declaration .error INVALID_EXTERNAL_DECLARATION .and + .loop external_declaration .and optional_space .and + '\0' .error INVALID_EXTERNAL_DECLARATION .emit EXTERNAL_NULL; + +/* + <external_declaration> ::= <function_definition> + | <declaration> +*/ +external_declaration + function_definition .emit EXTERNAL_FUNCTION_DEFINITION .or + declaration .emit EXTERNAL_DECLARATION; + +/* + <function_definition> :: <function_prototype> <compound_statement_no_new_scope> +*/ +function_definition + function_prototype .and compound_statement_no_new_scope; + +/* helper rulez, not part of the official language syntax */ + +digit_oct + '0'-'7'; + +digit_dec + '0'-'9'; + +digit_hex + '0'-'9' .or 'A'-'F' .or 'a'-'f'; + +id_character_first + 'a'-'z' .or 'A'-'Z' .or '_'; + +id_character_next + id_character_first .or digit_dec; + +identifier + id_character_first .emit * .and .loop id_character_next .emit * .and .true .emit '\0'; + +float + float_1 .or float_2; +float_1 + float_fractional_constant .and float_optional_exponent_part; +float_2 + float_digit_sequence .and .true .emit '\0' .and float_exponent_part; + +float_fractional_constant + float_fractional_constant_1 .or float_fractional_constant_2 .or float_fractional_constant_3; +float_fractional_constant_1 + float_digit_sequence .and '.' .and float_digit_sequence; +float_fractional_constant_2 + float_digit_sequence .and '.' .and .true .emit '\0'; +float_fractional_constant_3 + '.' .emit '\0' .and float_digit_sequence; + +float_optional_exponent_part + float_exponent_part .or .true .emit '\0'; + +float_digit_sequence + digit_dec .emit * .and .loop digit_dec .emit * .and .true .emit '\0'; + +float_exponent_part + float_exponent_part_1 .or float_exponent_part_2; +float_exponent_part_1 + 'e' .and float_optional_sign .and float_digit_sequence; +float_exponent_part_2 + 'E' .and float_optional_sign .and float_digit_sequence; + +float_optional_sign + float_sign .or .true; + +float_sign + '+' .or '-' .emit '-'; + +integer + integer_hex .or integer_oct .or integer_dec; + +integer_hex + '0' .and integer_hex_1 .emit 0x10 .and digit_hex .emit * .and .loop digit_hex .emit * .and + .true .emit '\0'; +integer_hex_1 + 'x' .or 'X'; + +integer_oct + '0' .emit 8 .emit * .and .loop digit_oct .emit * .and .true .emit '\0'; + +integer_dec + digit_dec .emit 10 .emit * .and .loop digit_dec .emit * .and .true .emit '\0'; + +boolean + "true" .emit 2 .emit '1' .emit '\0' .or + "false" .emit 2 .emit '0' .emit '\0'; + +type_name + identifier; + +field_selection + identifier; + +floatconstant + float .emit OP_PUSH_FLOAT; + +intconstant + integer .emit OP_PUSH_INT; + +boolconstant + boolean .emit OP_PUSH_BOOL; + +optional_space + .loop single_space; + +space + single_space .and .loop single_space; + +single_space + white_char .or c_style_comment_block .or cpp_style_comment_block; + +white_char + ' ' .or '\t' .or new_line .or '\v' .or '\f'; + +new_line + cr_lf .or lf_cr .or '\n' .or '\r'; + +cr_lf + '\r' .and '\n'; + +lf_cr + '\n' .and '\r'; + +c_style_comment_block + '/' .and '*' .and c_style_comment_rest; + +c_style_comment_rest + .loop c_style_comment_char_no_star .and c_style_comment_rest_1; +c_style_comment_rest_1 + c_style_comment_end .or c_style_comment_rest_2; +c_style_comment_rest_2 + '*' .and c_style_comment_rest; + +c_style_comment_char_no_star + '\x2B'-'\xFF' .or '\x01'-'\x29'; + +c_style_comment_end + '*' .and '/'; + +cpp_style_comment_block + '/' .and '/' .and cpp_style_comment_block_1; +cpp_style_comment_block_1 + cpp_style_comment_block_2 .or cpp_style_comment_block_3; +cpp_style_comment_block_2 + .loop cpp_style_comment_char .and new_line; +cpp_style_comment_block_3 + .loop cpp_style_comment_char; + +cpp_style_comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +/* lexical rulez */ + +/*ampersand + optional_space .and '&' .and optional_space;*/ + +ampersandampersand + optional_space .and '&' .and '&' .and optional_space; + +/*ampersandequals + optional_space .and '&' .and '=' .and optional_space;*/ + +/*bar + optional_space .and '|' .and optional_space;*/ + +barbar + optional_space .and '|' .and '|' .and optional_space; + +/*barequals + optional_space .and '|' .and '=' .and optional_space;*/ + +bang + optional_space .and '!' .and optional_space; + +bangequals + optional_space .and '!' .and '=' .and optional_space; + +/*caret + optional_space .and '^' .and optional_space;*/ + +caretcaret + optional_space .and '^' .and '^' .and optional_space; + +/*caretequals + optional_space .and '^' .and '=' .and optional_space;*/ + +colon + optional_space .and ':' .and optional_space; + +comma + optional_space .and ',' .and optional_space; + +dot + optional_space .and '.' .and optional_space; + +equals + optional_space .and '=' .and optional_space; + +equalsequals + optional_space .and '=' .and '=' .and optional_space; + +greater + optional_space .and '>' .and optional_space; + +greaterequals + optional_space .and '>' .and '=' .and optional_space; + +/*greatergreater + optional_space .and '>' .and '>' .and optional_space;*/ + +/*greatergreaterequals + optional_space .and '>' .and '>' .and '=' .and optional_space;*/ + +lbrace + optional_space .and '{' .and optional_space; + +lbracket + optional_space .and '[' .and optional_space; + +less + optional_space .and '<' .and optional_space; + +lessequals + optional_space .and '<' .and '=' .and optional_space; + +/*lessless + optional_space .and '<' .and '<' .and optional_space;*/ + +/*lesslessequals + optional_space .and '<' .and '<' .and '=' .and optional_space;*/ + +lparen + optional_space .and '(' .and optional_space; + +minus + optional_space .and '-' .and optional_space; + +minusequals + optional_space .and '-' .and '=' .and optional_space; + +minusminus + optional_space .and '-' .and '-' .and optional_space; + +/*percent + optional_space .and '%' .and optional_space;*/ + +/*percentequals + optional_space .and '%' .and '=' .and optional_space;*/ + +plus + optional_space .and '+' .and optional_space; + +plusequals + optional_space .and '+' .and '=' .and optional_space; + +plusplus + optional_space .and '+' .and '+' .and optional_space; + +question + optional_space .and '?' .and optional_space; + +rbrace + optional_space .and '}' .and optional_space; + +rbracket + optional_space .and ']' .and optional_space; + +rparen + optional_space .and ')' .and optional_space; + +semicolon + optional_space .and ';' .and optional_space; + +slash + optional_space .and '/' .and optional_space; + +slashequals + optional_space .and '/' .and '=' .and optional_space; + +star + optional_space .and '*' .and optional_space; + +starequals + optional_space .and '*' .and '=' .and optional_space; + +/*tilde + optional_space .and '~' .and optional_space;*/ + +/* string rulez - these are used internally by the parser when parsing quoted strings */ + +.string string_lexer; + +string_lexer + lex_first_identifier_character .and .loop lex_next_identifier_character; + +lex_first_identifier_character + 'a'-'z' .or 'A'-'Z' .or '_'; + +lex_next_identifier_character + 'a'-'z' .or 'A'-'Z' .or '0'-'9' .or '_'; + +/* error rulez - these are used by error messages */ + +err_token + '~' .or '`' .or '!' .or '@' .or '#' .or '$' .or '%' .or '^' .or '&' .or '*' .or '(' .or ')' .or + '-' .or '+' .or '=' .or '|' .or '\\' .or '[' .or ']' .or '{' .or '}' .or ':' .or ';' .or '"' .or + '\'' .or '<' .or ',' .or '>' .or '.' .or '/' .or '?' .or err_identifier; + +err_identifier + id_character_first .and .loop id_character_next; + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_version.syn b/dist/Mesa/src/mesa/shader/slang/library/slang_version.syn new file mode 100644 index 000000000..aaf8bef34 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_version.syn @@ -0,0 +1,118 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_version.syn + * slang #version directive syntax + * \author Michal Krol + */ + +.syntax version_directive; + +version_directive + version_directive_1 .and .loop version_directive_2; +version_directive_1 + prior_optional_spaces .and optional_version_directive .and .true .emit $; +version_directive_2 + prior_optional_spaces .and version_directive_body .and .true .emit $; + +optional_version_directive + version_directive_body .or .true .emit 10 .emit 1; + +version_directive_body + '#' .and optional_space .and "version" .and space .and version_number .and optional_space .and + new_line; + +version_number + version_number_110; + +version_number_110 + leading_zeroes .and "110" .emit 10 .emit 1; + +leading_zeroes + .loop zero; + +zero + '0'; + +space + single_space .and .loop single_space; + +optional_space + .loop single_space; + +single_space + ' ' .or '\t'; + +prior_optional_spaces + .loop prior_space; + +prior_space + c_style_comment_block .or cpp_style_comment_block .or space .or new_line; + +c_style_comment_block + '/' .and '*' .and c_style_comment_rest; + +c_style_comment_rest + .loop c_style_comment_char_no_star .and c_style_comment_rest_1; +c_style_comment_rest_1 + c_style_comment_end .or c_style_comment_rest_2; +c_style_comment_rest_2 + '*' .and c_style_comment_rest; + +c_style_comment_char_no_star + '\x2B'-'\xFF' .or '\x01'-'\x29'; + +c_style_comment_end + '*' .and '/'; + +cpp_style_comment_block + '/' .and '/' .and cpp_style_comment_block_1; +cpp_style_comment_block_1 + cpp_style_comment_block_2 .or cpp_style_comment_block_3; +cpp_style_comment_block_2 + .loop cpp_style_comment_char .and new_line; +cpp_style_comment_block_3 + .loop cpp_style_comment_char; + +cpp_style_comment_char + '\x0E'-'\xFF' .or '\x01'-'\x09' .or '\x0B'-'\x0C'; + +new_line + cr_lf .or lf_cr .or '\n' .or '\r'; + +cr_lf + '\r' .and '\n'; + +lf_cr + '\n' .and '\r'; + +.string __string_filter; + +__string_filter + .loop __identifier_char; + +__identifier_char + 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9'; + diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_version_syn.h b/dist/Mesa/src/mesa/shader/slang/library/slang_version_syn.h new file mode 100644 index 000000000..3b94d8592 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_version_syn.h @@ -0,0 +1,64 @@ +".syntax version_directive;\n" +"version_directive\n" +" version_directive_1 .and .loop version_directive_2;\n" +"version_directive_1\n" +" prior_optional_spaces .and optional_version_directive .and .true .emit $;\n" +"version_directive_2\n" +" prior_optional_spaces .and version_directive_body .and .true .emit $;\n" +"optional_version_directive\n" +" version_directive_body .or .true .emit 10 .emit 1;\n" +"version_directive_body\n" +" '#' .and optional_space .and \"version\" .and space .and version_number .and optional_space .and\n" +" new_line;\n" +"version_number\n" +" version_number_110;\n" +"version_number_110\n" +" leading_zeroes .and \"110\" .emit 10 .emit 1;\n" +"leading_zeroes\n" +" .loop zero;\n" +"zero\n" +" '0';\n" +"space\n" +" single_space .and .loop single_space;\n" +"optional_space\n" +" .loop single_space;\n" +"single_space\n" +" ' ' .or '\\t';\n" +"prior_optional_spaces\n" +" .loop prior_space;\n" +"prior_space\n" +" c_style_comment_block .or cpp_style_comment_block .or space .or new_line;\n" +"c_style_comment_block\n" +" '/' .and '*' .and c_style_comment_rest;\n" +"c_style_comment_rest\n" +" .loop c_style_comment_char_no_star .and c_style_comment_rest_1;\n" +"c_style_comment_rest_1\n" +" c_style_comment_end .or c_style_comment_rest_2;\n" +"c_style_comment_rest_2\n" +" '*' .and c_style_comment_rest;\n" +"c_style_comment_char_no_star\n" +" '\\x2B'-'\\xFF' .or '\\x01'-'\\x29';\n" +"c_style_comment_end\n" +" '*' .and '/';\n" +"cpp_style_comment_block\n" +" '/' .and '/' .and cpp_style_comment_block_1;\n" +"cpp_style_comment_block_1\n" +" cpp_style_comment_block_2 .or cpp_style_comment_block_3;\n" +"cpp_style_comment_block_2\n" +" .loop cpp_style_comment_char .and new_line;\n" +"cpp_style_comment_block_3\n" +" .loop cpp_style_comment_char;\n" +"cpp_style_comment_char\n" +" '\\x0E'-'\\xFF' .or '\\x01'-'\\x09' .or '\\x0B'-'\\x0C';\n" +"new_line\n" +" cr_lf .or lf_cr .or '\\n' .or '\\r';\n" +"cr_lf\n" +" '\\r' .and '\\n';\n" +"lf_cr\n" +" '\\n' .and '\\r';\n" +".string __string_filter;\n" +"__string_filter\n" +" .loop __identifier_char;\n" +"__identifier_char\n" +" 'a'-'z' .or 'A'-'Z' .or '_' .or '0'-'9';\n" +"" diff --git a/dist/Mesa/src/mesa/shader/slang/library/slang_vertex_builtin.gc b/dist/Mesa/src/mesa/shader/slang/library/slang_vertex_builtin.gc new file mode 100644 index 000000000..20c924a30 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/library/slang_vertex_builtin.gc @@ -0,0 +1,187 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +// +// From Shader Spec, ver. 1.10, rev. 59 +// + +__fixed_output vec4 gl_Position; +__fixed_output float gl_PointSize; +__fixed_output vec4 gl_ClipVertex; + +attribute vec4 gl_Color; +attribute vec4 gl_SecondaryColor; +attribute vec3 gl_Normal; +attribute vec4 gl_Vertex; +attribute vec4 gl_MultiTexCoord0; +attribute vec4 gl_MultiTexCoord1; +attribute vec4 gl_MultiTexCoord2; +attribute vec4 gl_MultiTexCoord3; +attribute vec4 gl_MultiTexCoord4; +attribute vec4 gl_MultiTexCoord5; +attribute vec4 gl_MultiTexCoord6; +attribute vec4 gl_MultiTexCoord7; +attribute float gl_FogCoord; + +varying vec4 gl_FrontColor; +varying vec4 gl_BackColor; +varying vec4 gl_FrontSecondaryColor; +varying vec4 gl_BackSecondaryColor; +varying vec4 gl_TexCoord[gl_MaxTextureCoords]; +varying float gl_FogFragCoord; + +// +// Geometric Functions +// + +vec4 ftransform() +{ + __retVal = gl_Vertex * gl_ModelViewProjectionMatrixTranspose; +} + + + +// +// 8.7 Texture Lookup Functions +// These are pretty much identical to the ones in slang_fragment_builtin.gc +// When used in a vertex program, the texture sample instructions should not +// be using a LOD term so it's effectively zero. Adding 'lod' to that does +// what we want. +// + +vec4 texture1DLod(const sampler1D sampler, const float coord, const float lod) +{ + vec4 coord4; + coord4.x = coord; + coord4.w = lod; + __asm vec4_texb1d __retVal, sampler, coord4; +} + +vec4 texture1DProjLod(const sampler1D sampler, const vec2 coord, const float lod) +{ + vec4 pcoord; + pcoord.x = coord.x / coord.y; + pcoord.w = lod; + __asm vec4_texb1d __retVal, sampler, pcoord; +} + +vec4 texture1DProjLod(const sampler1D sampler, const vec4 coord, const float lod) +{ + vec4 pcoord; + pcoord.x = coord.x / coord.z; + pcoord.w = lod; + __asm vec4_texb1d __retVal, sampler, pcoord; +} + + + +vec4 texture2DLod(const sampler2D sampler, const vec2 coord, const float lod) +{ + vec4 coord4; + coord4.xy = coord.xy; + coord4.w = lod; + __asm vec4_texb2d __retVal, sampler, coord4; +} + +vec4 texture2DProjLod(const sampler2D sampler, const vec3 coord, const float lod) +{ + vec4 pcoord; + pcoord.xy = coord.xy / coord.z; + pcoord.w = lod; + __asm vec4_texb2d __retVal, sampler, pcoord; +} + +vec4 texture2DProjLod(const sampler2D sampler, const vec4 coord, const float lod) +{ + vec4 pcoord; + pcoord.xy = coord.xy / coord.z; + pcoord.w = lod; + __asm vec4_texb2d __retVal, sampler, pcoord; +} + + +vec4 texture3DLod(const sampler3D sampler, const vec3 coord, const float lod) +{ + vec4 coord4; + coord4.xyz = coord.xyz; + coord4.w = lod; + __asm vec4_texb3d __retVal, sampler, coord4; +} + +vec4 texture3DProjLod(const sampler3D sampler, const vec4 coord, const float lod) +{ + // do projection here (there's no vec4_texbp3d instruction) + vec4 pcoord; + pcoord.xyz = coord.xyz / coord.w; + pcoord.w = lod; + __asm vec4_texb3d __retVal, sampler, pcoord; +} + + +vec4 textureCubeLod(const samplerCube sampler, const vec3 coord, const float lod) +{ + vec4 coord4; + coord4.xyz = coord; + coord4.w = lod; + __asm vec4_texcube __retVal, sampler, coord4; +} + + +vec4 shadow1DLod(const sampler1DShadow sampler, const vec3 coord, const float lod) +{ + vec4 coord4; + coord4.xyz = coord; + coord4.w = lod; + __asm vec4_texb1d __retVal, sampler, coord4; +} + +vec4 shadow1DProjLod(const sampler1DShadow sampler, const vec4 coord, + const float lod) +{ + vec4 pcoord; + pcoord.x = coord.x / coord.w; + pcoord.z = coord.z; + pcoord.w = lod; + __asm vec4_texb1d __retVal, sampler, pcoord; +} + + +vec4 shadow2DLod(const sampler2DShadow sampler, const vec3 coord, const float lod) +{ + vec4 coord4; + coord4.xyz = coord; + coord4.w = lod; + __asm vec4_texb2d __retVal, sampler, coord4; +} + +vec4 shadow2DProjLod(const sampler2DShadow sampler, const vec4 coord, + const float lod) +{ + vec4 pcoord; + pcoord.xy = coord.xy / coord.w; + pcoord.z = coord.z; + pcoord.w = lod; + __asm vec4_texb2d __retVal, sampler, pcoord; +} + diff --git a/dist/Mesa/src/mesa/shader/slang/slang_builtin.c b/dist/Mesa/src/mesa/shader/slang/slang_builtin.c new file mode 100644 index 000000000..6ee0fd33b --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_builtin.c @@ -0,0 +1,440 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_builtin.c + * Resolve built-in uniform vars. + * \author Brian Paul + */ + +#include "imports.h" +#include "slang_builtin.h" +#include "slang_ir.h" +#include "mtypes.h" +#include "program.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_statevars.h" + + +/** + * Lookup GL state given a variable name, 0, 1 or 2 indexes and a field. + * Allocate room for the state in the given param list and return position + * in the list. + * Yes, this is kind of ugly, but it works. + */ +static GLint +lookup_statevar(const char *var, GLint index1, GLint index2, const char *field, + GLuint *swizzleOut, + struct gl_program_parameter_list *paramList) +{ + /* + * NOTE: The ARB_vertex_program extension specified that matrices get + * loaded in registers in row-major order. With GLSL, we want column- + * major order. So, we need to transpose all matrices here... + */ + static const struct { + const char *name; + gl_state_index matrix; + gl_state_index modifier; + } matrices[] = { + { "gl_ModelViewMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE }, + { "gl_ModelViewMatrixInverse", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS }, + { "gl_ModelViewMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 }, + { "gl_ModelViewMatrixInverseTranspose", STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE }, + + { "gl_ProjectionMatrix", STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE }, + { "gl_ProjectionMatrixInverse", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS }, + { "gl_ProjectionMatrixTranspose", STATE_PROJECTION_MATRIX, 0 }, + { "gl_ProjectionMatrixInverseTranspose", STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE }, + + { "gl_ModelViewProjectionMatrix", STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE }, + { "gl_ModelViewProjectionMatrixInverse", STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS }, + { "gl_ModelViewProjectionMatrixTranspose", STATE_MVP_MATRIX, 0 }, + { "gl_ModelViewProjectionMatrixInverseTranspose", STATE_MVP_MATRIX, STATE_MATRIX_INVERSE }, + + { "gl_TextureMatrix", STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE }, + { "gl_TextureMatrixInverse", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS }, + { "gl_TextureMatrixTranspose", STATE_TEXTURE_MATRIX, 0 }, + { "gl_TextureMatrixInverseTranspose", STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE }, + + /* XXX verify these!!! */ + { "gl_NormalMatrix", STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE }, + { "__NormalMatrixTranspose", STATE_MODELVIEW_MATRIX, 0 }, + + { NULL, 0, 0 } + }; + gl_state_index tokens[STATE_LENGTH]; + GLuint i; + GLboolean isMatrix = GL_FALSE; + + for (i = 0; i < STATE_LENGTH; i++) { + tokens[i] = 0; + } + *swizzleOut = SWIZZLE_NOOP; + + /* first, look if var is a pre-defined matrix */ + for (i = 0; matrices[i].name; i++) { + if (strcmp(var, matrices[i].name) == 0) { + tokens[0] = matrices[i].matrix; + /* tokens[1], [2] and [3] filled below */ + tokens[4] = matrices[i].modifier; + isMatrix = GL_TRUE; + break; + } + } + + if (isMatrix) { + if (tokens[0] == STATE_TEXTURE_MATRIX) { + if (index1 >= 0) { + tokens[1] = index1; + index1 = 0; /* prevent extra addition at end of function */ + } + } + } + else if (strcmp(var, "gl_DepthRange") == 0) { + tokens[0] = STATE_DEPTH_RANGE; + if (strcmp(field, "near") == 0) { + *swizzleOut = SWIZZLE_XXXX; + } + else if (strcmp(field, "far") == 0) { + *swizzleOut = SWIZZLE_YYYY; + } + else if (strcmp(field, "diff") == 0) { + *swizzleOut = SWIZZLE_ZZZZ; + } + else { + return -1; + } + } + else if (strcmp(var, "gl_ClipPlane") == 0) { + tokens[0] = STATE_CLIPPLANE; + tokens[1] = index1; + } + else if (strcmp(var, "gl_Point") == 0) { + if (strcmp(field, "size") == 0) { + tokens[0] = STATE_POINT_SIZE; + *swizzleOut = SWIZZLE_XXXX; + } + else if (strcmp(field, "sizeMin") == 0) { + tokens[0] = STATE_POINT_SIZE; + *swizzleOut = SWIZZLE_YYYY; + } + else if (strcmp(field, "sizeMax") == 0) { + tokens[0] = STATE_POINT_SIZE; + *swizzleOut = SWIZZLE_ZZZZ; + } + else if (strcmp(field, "fadeThresholdSize") == 0) { + tokens[0] = STATE_POINT_SIZE; + *swizzleOut = SWIZZLE_WWWW; + } + else if (strcmp(field, "distanceConstantAttenuation") == 0) { + tokens[0] = STATE_POINT_ATTENUATION; + *swizzleOut = SWIZZLE_XXXX; + } + else if (strcmp(field, "distanceLinearAttenuation") == 0) { + tokens[0] = STATE_POINT_ATTENUATION; + *swizzleOut = SWIZZLE_YYYY; + } + else if (strcmp(field, "distanceQuadraticAttenuation") == 0) { + tokens[0] = STATE_POINT_ATTENUATION; + *swizzleOut = SWIZZLE_ZZZZ; + } + else { + return -1; + } + } + else if (strcmp(var, "gl_FrontMaterial") == 0 || + strcmp(var, "gl_BackMaterial") == 0) { + tokens[0] = STATE_MATERIAL; + if (strcmp(var, "gl_FrontMaterial") == 0) + tokens[1] = 0; + else + tokens[1] = 1; + if (strcmp(field, "emission") == 0) { + tokens[2] = STATE_EMISSION; + } + else if (strcmp(field, "ambient") == 0) { + tokens[2] = STATE_AMBIENT; + } + else if (strcmp(field, "diffuse") == 0) { + tokens[2] = STATE_DIFFUSE; + } + else if (strcmp(field, "specular") == 0) { + tokens[2] = STATE_SPECULAR; + } + else if (strcmp(field, "shininess") == 0) { + tokens[2] = STATE_SHININESS; + *swizzleOut = SWIZZLE_XXXX; + } + else { + return -1; + } + } + else if (strcmp(var, "gl_LightSource") == 0) { + tokens[0] = STATE_LIGHT; + tokens[1] = index1; + if (strcmp(field, "ambient") == 0) { + tokens[2] = STATE_AMBIENT; + } + else if (strcmp(field, "diffuse") == 0) { + tokens[2] = STATE_DIFFUSE; + } + else if (strcmp(field, "specular") == 0) { + tokens[2] = STATE_SPECULAR; + } + else if (strcmp(field, "position") == 0) { + tokens[2] = STATE_POSITION; + } + else if (strcmp(field, "halfVector") == 0) { + tokens[2] = STATE_HALF_VECTOR; + } + else if (strcmp(field, "spotDirection") == 0) { + tokens[2] = STATE_SPOT_DIRECTION; + } + else if (strcmp(field, "spotCosCutoff") == 0) { + tokens[2] = STATE_SPOT_DIRECTION; + *swizzleOut = SWIZZLE_WWWW; + } + else if (strcmp(field, "spotCutoff") == 0) { + tokens[2] = STATE_SPOT_CUTOFF; + *swizzleOut = SWIZZLE_XXXX; + } + else if (strcmp(field, "spotExponent") == 0) { + tokens[2] = STATE_ATTENUATION; + *swizzleOut = SWIZZLE_WWWW; + } + else if (strcmp(field, "constantAttenuation") == 0) { + tokens[2] = STATE_ATTENUATION; + *swizzleOut = SWIZZLE_XXXX; + } + else if (strcmp(field, "linearAttenuation") == 0) { + tokens[2] = STATE_ATTENUATION; + *swizzleOut = SWIZZLE_YYYY; + } + else if (strcmp(field, "quadraticAttenuation") == 0) { + tokens[2] = STATE_ATTENUATION; + *swizzleOut = SWIZZLE_ZZZZ; + } + else { + return -1; + } + } + else if (strcmp(var, "gl_LightModel") == 0) { + if (strcmp(field, "ambient") == 0) { + tokens[0] = STATE_LIGHTMODEL_AMBIENT; + } + else { + return -1; + } + } + else if (strcmp(var, "gl_FrontLightModelProduct") == 0) { + if (strcmp(field, "ambient") == 0) { + tokens[0] = STATE_LIGHTMODEL_SCENECOLOR; + tokens[1] = 0; + } + else { + return -1; + } + } + else if (strcmp(var, "gl_BackLightModelProduct") == 0) { + if (strcmp(field, "ambient") == 0) { + tokens[0] = STATE_LIGHTMODEL_SCENECOLOR; + tokens[1] = 1; + } + else { + return -1; + } + } + else if (strcmp(var, "gl_FrontLightProduct") == 0 || + strcmp(var, "gl_BackLightProduct") == 0) { + tokens[0] = STATE_LIGHTPROD; + tokens[1] = index1; /* light number */ + if (strcmp(var, "gl_FrontLightProduct") == 0) { + tokens[2] = 0; /* front */ + } + else { + tokens[2] = 1; /* back */ + } + if (strcmp(field, "ambient") == 0) { + tokens[3] = STATE_AMBIENT; + } + else if (strcmp(field, "diffuse") == 0) { + tokens[3] = STATE_DIFFUSE; + } + else if (strcmp(field, "specular") == 0) { + tokens[3] = STATE_SPECULAR; + } + else { + return -1; + } + } + else if (strcmp(var, "gl_TextureEnvColor") == 0) { + tokens[0] = STATE_TEXENV_COLOR; + tokens[1] = index1; + } + else if (strcmp(var, "gl_EyePlaneS") == 0) { + tokens[0] = STATE_TEXGEN; + tokens[1] = index1; /* tex unit */ + tokens[2] = STATE_TEXGEN_EYE_S; + } + else if (strcmp(var, "gl_EyePlaneT") == 0) { + tokens[0] = STATE_TEXGEN; + tokens[1] = index1; /* tex unit */ + tokens[2] = STATE_TEXGEN_EYE_T; + } + else if (strcmp(var, "gl_EyePlaneR") == 0) { + tokens[0] = STATE_TEXGEN; + tokens[1] = index1; /* tex unit */ + tokens[2] = STATE_TEXGEN_EYE_R; + } + else if (strcmp(var, "gl_EyePlaneQ") == 0) { + tokens[0] = STATE_TEXGEN; + tokens[1] = index1; /* tex unit */ + tokens[2] = STATE_TEXGEN_EYE_Q; + } + else if (strcmp(var, "gl_ObjectPlaneS") == 0) { + tokens[0] = STATE_TEXGEN; + tokens[1] = index1; /* tex unit */ + tokens[2] = STATE_TEXGEN_OBJECT_S; + } + else if (strcmp(var, "gl_ObjectPlaneT") == 0) { + tokens[0] = STATE_TEXGEN; + tokens[1] = index1; /* tex unit */ + tokens[2] = STATE_TEXGEN_OBJECT_T; + } + else if (strcmp(var, "gl_ObjectPlaneR") == 0) { + tokens[0] = STATE_TEXGEN; + tokens[1] = index1; /* tex unit */ + tokens[2] = STATE_TEXGEN_OBJECT_R; + } + else if (strcmp(var, "gl_ObjectPlaneQ") == 0) { + tokens[0] = STATE_TEXGEN; + tokens[1] = index1; /* tex unit */ + tokens[2] = STATE_TEXGEN_OBJECT_Q; + } + else if (strcmp(var, "gl_Fog") == 0) { + if (strcmp(field, "color") == 0) { + tokens[0] = STATE_FOG_COLOR; + } + else if (strcmp(field, "density") == 0) { + tokens[0] = STATE_FOG_PARAMS; + *swizzleOut = SWIZZLE_XXXX; + } + else if (strcmp(field, "start") == 0) { + tokens[0] = STATE_FOG_PARAMS; + *swizzleOut = SWIZZLE_YYYY; + } + else if (strcmp(field, "end") == 0) { + tokens[0] = STATE_FOG_PARAMS; + *swizzleOut = SWIZZLE_ZZZZ; + } + else if (strcmp(field, "scale") == 0) { + tokens[0] = STATE_FOG_PARAMS; + *swizzleOut = SWIZZLE_WWWW; + } + else { + return -1; + } + } + else { + return -1; + } + + if (isMatrix) { + /* load all four columns of matrix */ + GLint pos[4]; + GLuint j; + for (j = 0; j < 4; j++) { + tokens[2] = tokens[3] = j; /* jth row of matrix */ + pos[j] = _mesa_add_state_reference(paramList, tokens); + assert(pos[j] >= 0); + ASSERT(pos[j] >= 0); + } + return pos[0] + index1; + } + else { + /* allocate a single register */ + GLint pos = _mesa_add_state_reference(paramList, tokens); + ASSERT(pos >= 0); + return pos; + } +} + + +/** + * Allocate storage for a pre-defined uniform (a GL state variable). + * As a memory-saving optimization, we try to only allocate storage for + * state vars that are actually used. + * For example, the "gl_LightSource" uniform is huge. If we only use + * a handful of gl_LightSource fields, we don't want to allocate storage + * for all of gl_LightSource. + * + * Currently, all pre-defined uniforms are in one of these forms: + * var + * var[i] + * var.field + * var[i].field + * var[i][j] + */ +GLint +_slang_alloc_statevar(slang_ir_node *n, + struct gl_program_parameter_list *paramList) +{ + slang_ir_node *n0 = n; + const char *field = NULL, *var; + GLint index1 = -1, index2 = -1, pos; + GLuint swizzle; + + if (n->Opcode == IR_FIELD) { + field = n->Field; + n = n->Children[0]; + } + + if (n->Opcode == IR_ELEMENT) { + /* XXX can only handle constant indexes for now */ + assert(n->Children[1]->Opcode == IR_FLOAT); + index1 = (GLint) n->Children[1]->Value[0]; + n = n->Children[0]; + } + + if (n->Opcode == IR_ELEMENT) { + /* XXX can only handle constant indexes for now */ + assert(n->Children[1]->Opcode == IR_FLOAT); + index2 = (GLint) n->Children[1]->Value[0]; + n = n->Children[0]; + } + + assert(n->Opcode == IR_VAR); + var = (char *) n->Var->a_name; + + pos = lookup_statevar(var, index1, index2, field, &swizzle, paramList); + assert(pos >= 0); + if (pos >= 0) { + n0->Store->Index = pos; + n0->Store->Swizzle = swizzle; + } + return pos; +} + diff --git a/dist/Mesa/src/mesa/shader/slang/slang_builtin.h b/dist/Mesa/src/mesa/shader/slang/slang_builtin.h new file mode 100644 index 000000000..ae20c844d --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_builtin.h @@ -0,0 +1,39 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef SLANG_BUILTIN_H +#define SLANG_BUILTIN_H + +#include "prog_parameter.h" +#include "slang_utility.h" +#include "slang_ir.h" + + +extern GLint +_slang_alloc_statevar(slang_ir_node *n, + struct gl_program_parameter_list *paramList); + + +#endif /* SLANG_BUILTIN_H */ diff --git a/dist/Mesa/src/mesa/shader/slang/slang_codegen.c b/dist/Mesa/src/mesa/shader/slang/slang_codegen.c new file mode 100644 index 000000000..675dd8318 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_codegen.c @@ -0,0 +1,3153 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_codegen.c + * Generate IR tree from AST. + * \author Brian Paul + */ + + +/*** + *** NOTES: + *** The new_() functions return a new instance of a simple IR node. + *** The gen_() functions generate larger IR trees from the simple nodes. + ***/ + + + +#include "main/imports.h" +#include "main/macros.h" +#include "main/mtypes.h" +#include "shader/program.h" +#include "shader/prog_instruction.h" +#include "shader/prog_parameter.h" +#include "shader/prog_statevars.h" +#include "slang_typeinfo.h" +#include "slang_codegen.h" +#include "slang_compile.h" +#include "slang_label.h" +#include "slang_mem.h" +#include "slang_simplify.h" +#include "slang_emit.h" +#include "slang_vartable.h" +#include "slang_ir.h" +#include "slang_print.h" + + +static slang_ir_node * +_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper); + + +static GLboolean +is_sampler_type(const slang_fully_specified_type *t) +{ + switch (t->specifier.type) { + case SLANG_SPEC_SAMPLER1D: + case SLANG_SPEC_SAMPLER2D: + case SLANG_SPEC_SAMPLER3D: + case SLANG_SPEC_SAMPLERCUBE: + case SLANG_SPEC_SAMPLER1DSHADOW: + case SLANG_SPEC_SAMPLER2DSHADOW: + case SLANG_SPEC_SAMPLER2DRECT: + case SLANG_SPEC_SAMPLER2DRECTSHADOW: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Return the offset (in floats or ints) of the named field within + * the given struct. Return -1 if field not found. + * If field is NULL, return the size of the struct instead. + */ +static GLint +_slang_field_offset(const slang_type_specifier *spec, slang_atom field) +{ + GLint offset = 0; + GLuint i; + for (i = 0; i < spec->_struct->fields->num_variables; i++) { + const slang_variable *v = spec->_struct->fields->variables[i]; + const GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier); + if (sz > 1) { + /* types larger than 1 float are register (4-float) aligned */ + offset = (offset + 3) & ~3; + } + if (field && v->a_name == field) { + return offset; + } + offset += sz; + } + if (field) + return -1; /* field not found */ + else + return offset; /* struct size */ +} + + +/** + * Return the size (in floats) of the given type specifier. + * If the size is greater than 4, the size should be a multiple of 4 + * so that the correct number of 4-float registers are allocated. + * For example, a mat3x2 is size 12 because we want to store the + * 3 columns in 3 float[4] registers. + */ +GLuint +_slang_sizeof_type_specifier(const slang_type_specifier *spec) +{ + GLuint sz; + switch (spec->type) { + case SLANG_SPEC_VOID: + sz = 0; + break; + case SLANG_SPEC_BOOL: + sz = 1; + break; + case SLANG_SPEC_BVEC2: + sz = 2; + break; + case SLANG_SPEC_BVEC3: + sz = 3; + break; + case SLANG_SPEC_BVEC4: + sz = 4; + break; + case SLANG_SPEC_INT: + sz = 1; + break; + case SLANG_SPEC_IVEC2: + sz = 2; + break; + case SLANG_SPEC_IVEC3: + sz = 3; + break; + case SLANG_SPEC_IVEC4: + sz = 4; + break; + case SLANG_SPEC_FLOAT: + sz = 1; + break; + case SLANG_SPEC_VEC2: + sz = 2; + break; + case SLANG_SPEC_VEC3: + sz = 3; + break; + case SLANG_SPEC_VEC4: + sz = 4; + break; + case SLANG_SPEC_MAT2: + sz = 2 * 4; /* 2 columns (regs) */ + break; + case SLANG_SPEC_MAT3: + sz = 3 * 4; + break; + case SLANG_SPEC_MAT4: + sz = 4 * 4; + break; + case SLANG_SPEC_MAT23: + sz = 2 * 4; /* 2 columns (regs) */ + break; + case SLANG_SPEC_MAT32: + sz = 3 * 4; /* 3 columns (regs) */ + break; + case SLANG_SPEC_MAT24: + sz = 2 * 4; + break; + case SLANG_SPEC_MAT42: + sz = 4 * 4; /* 4 columns (regs) */ + break; + case SLANG_SPEC_MAT34: + sz = 3 * 4; + break; + case SLANG_SPEC_MAT43: + sz = 4 * 4; /* 4 columns (regs) */ + break; + case SLANG_SPEC_SAMPLER1D: + case SLANG_SPEC_SAMPLER2D: + case SLANG_SPEC_SAMPLER3D: + case SLANG_SPEC_SAMPLERCUBE: + case SLANG_SPEC_SAMPLER1DSHADOW: + case SLANG_SPEC_SAMPLER2DSHADOW: + case SLANG_SPEC_SAMPLER2DRECT: + case SLANG_SPEC_SAMPLER2DRECTSHADOW: + sz = 1; /* a sampler is basically just an integer index */ + break; + case SLANG_SPEC_STRUCT: + sz = _slang_field_offset(spec, 0); /* special use */ + if (sz > 4) { + sz = (sz + 3) & ~0x3; /* round up to multiple of four */ + } + break; + case SLANG_SPEC_ARRAY: + sz = _slang_sizeof_type_specifier(spec->_array); + break; + default: + _mesa_problem(NULL, "Unexpected type in _slang_sizeof_type_specifier()"); + sz = 0; + } + + if (sz > 4) { + /* if size is > 4, it should be a multiple of four */ + assert((sz & 0x3) == 0); + } + return sz; +} + + +/** + * Establish the binding between a slang_ir_node and a slang_variable. + * Then, allocate/attach a slang_ir_storage object to the IR node if needed. + * The IR node must be a IR_VAR or IR_VAR_DECL node. + * \param n the IR node + * \param var the variable to associate with the IR node + */ +static void +_slang_attach_storage(slang_ir_node *n, slang_variable *var) +{ + assert(n); + assert(var); + assert(n->Opcode == IR_VAR || n->Opcode == IR_VAR_DECL); + assert(!n->Var || n->Var == var); + + n->Var = var; + + if (!n->Store) { + /* need to setup storage */ + if (n->Var && n->Var->aux) { + /* node storage info = var storage info */ + n->Store = (slang_ir_storage *) n->Var->aux; + } + else { + /* alloc new storage info */ + n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -5); + if (n->Var) + n->Var->aux = n->Store; + assert(n->Var->aux); + } + } +} + + +/** + * Return the TEXTURE_*_INDEX value that corresponds to a sampler type, + * or -1 if the type is not a sampler. + */ +static GLint +sampler_to_texture_index(const slang_type_specifier_type type) +{ + switch (type) { + case SLANG_SPEC_SAMPLER1D: + return TEXTURE_1D_INDEX; + case SLANG_SPEC_SAMPLER2D: + return TEXTURE_2D_INDEX; + case SLANG_SPEC_SAMPLER3D: + return TEXTURE_3D_INDEX; + case SLANG_SPEC_SAMPLERCUBE: + return TEXTURE_CUBE_INDEX; + case SLANG_SPEC_SAMPLER1DSHADOW: + return TEXTURE_1D_INDEX; /* XXX fix */ + case SLANG_SPEC_SAMPLER2DSHADOW: + return TEXTURE_2D_INDEX; /* XXX fix */ + case SLANG_SPEC_SAMPLER2DRECT: + return TEXTURE_RECT_INDEX; + case SLANG_SPEC_SAMPLER2DRECTSHADOW: + return TEXTURE_RECT_INDEX; /* XXX fix */ + default: + return -1; + } +} + + +/** + * Return the VERT_ATTRIB_* or FRAG_ATTRIB_* value that corresponds to + * a vertex or fragment program input variable. Return -1 if the input + * name is invalid. + * XXX return size too + */ +static GLint +_slang_input_index(const char *name, GLenum target, GLuint *swizzleOut) +{ + struct input_info { + const char *Name; + GLuint Attrib; + GLuint Swizzle; + }; + static const struct input_info vertInputs[] = { + { "gl_Vertex", VERT_ATTRIB_POS, SWIZZLE_NOOP }, + { "gl_Normal", VERT_ATTRIB_NORMAL, SWIZZLE_NOOP }, + { "gl_Color", VERT_ATTRIB_COLOR0, SWIZZLE_NOOP }, + { "gl_SecondaryColor", VERT_ATTRIB_COLOR1, SWIZZLE_NOOP }, + { "gl_FogCoord", VERT_ATTRIB_FOG, SWIZZLE_XXXX }, + { "gl_MultiTexCoord0", VERT_ATTRIB_TEX0, SWIZZLE_NOOP }, + { "gl_MultiTexCoord1", VERT_ATTRIB_TEX1, SWIZZLE_NOOP }, + { "gl_MultiTexCoord2", VERT_ATTRIB_TEX2, SWIZZLE_NOOP }, + { "gl_MultiTexCoord3", VERT_ATTRIB_TEX3, SWIZZLE_NOOP }, + { "gl_MultiTexCoord4", VERT_ATTRIB_TEX4, SWIZZLE_NOOP }, + { "gl_MultiTexCoord5", VERT_ATTRIB_TEX5, SWIZZLE_NOOP }, + { "gl_MultiTexCoord6", VERT_ATTRIB_TEX6, SWIZZLE_NOOP }, + { "gl_MultiTexCoord7", VERT_ATTRIB_TEX7, SWIZZLE_NOOP }, + { NULL, 0, SWIZZLE_NOOP } + }; + static const struct input_info fragInputs[] = { + { "gl_FragCoord", FRAG_ATTRIB_WPOS, SWIZZLE_NOOP }, + { "gl_Color", FRAG_ATTRIB_COL0, SWIZZLE_NOOP }, + { "gl_SecondaryColor", FRAG_ATTRIB_COL1, SWIZZLE_NOOP }, + { "gl_FogFragCoord", FRAG_ATTRIB_FOGC, SWIZZLE_XXXX }, + { "gl_TexCoord", FRAG_ATTRIB_TEX0, SWIZZLE_NOOP }, + { "gl_FrontFacing", FRAG_ATTRIB_FOGC, SWIZZLE_YYYY }, /*XXX*/ + { NULL, 0, SWIZZLE_NOOP } + }; + GLuint i; + const struct input_info *inputs + = (target == GL_VERTEX_PROGRAM_ARB) ? vertInputs : fragInputs; + + ASSERT(MAX_TEXTURE_UNITS == 8); /* if this fails, fix vertInputs above */ + + for (i = 0; inputs[i].Name; i++) { + if (strcmp(inputs[i].Name, name) == 0) { + /* found */ + *swizzleOut = inputs[i].Swizzle; + return inputs[i].Attrib; + } + } + return -1; +} + + +/** + * Return the VERT_RESULT_* or FRAG_RESULT_* value that corresponds to + * a vertex or fragment program output variable. Return -1 for an invalid + * output name. + */ +static GLint +_slang_output_index(const char *name, GLenum target) +{ + struct output_info { + const char *Name; + GLuint Attrib; + }; + static const struct output_info vertOutputs[] = { + { "gl_Position", VERT_RESULT_HPOS }, + { "gl_FrontColor", VERT_RESULT_COL0 }, + { "gl_BackColor", VERT_RESULT_BFC0 }, + { "gl_FrontSecondaryColor", VERT_RESULT_COL1 }, + { "gl_BackSecondaryColor", VERT_RESULT_BFC1 }, + { "gl_TexCoord", VERT_RESULT_TEX0 }, + { "gl_FogFragCoord", VERT_RESULT_FOGC }, + { "gl_PointSize", VERT_RESULT_PSIZ }, + { NULL, 0 } + }; + static const struct output_info fragOutputs[] = { + { "gl_FragColor", FRAG_RESULT_COLR }, + { "gl_FragDepth", FRAG_RESULT_DEPR }, + { "gl_FragData", FRAG_RESULT_DATA0 }, + { NULL, 0 } + }; + GLuint i; + const struct output_info *outputs + = (target == GL_VERTEX_PROGRAM_ARB) ? vertOutputs : fragOutputs; + + for (i = 0; outputs[i].Name; i++) { + if (strcmp(outputs[i].Name, name) == 0) { + /* found */ + return outputs[i].Attrib; + } + } + return -1; +} + + + +/**********************************************************************/ + + +/** + * Map "_asm foo" to IR_FOO, etc. + */ +typedef struct +{ + const char *Name; + slang_ir_opcode Opcode; + GLuint HaveRetValue, NumParams; +} slang_asm_info; + + +static slang_asm_info AsmInfo[] = { + /* vec4 binary op */ + { "vec4_add", IR_ADD, 1, 2 }, + { "vec4_subtract", IR_SUB, 1, 2 }, + { "vec4_multiply", IR_MUL, 1, 2 }, + { "vec4_dot", IR_DOT4, 1, 2 }, + { "vec3_dot", IR_DOT3, 1, 2 }, + { "vec3_cross", IR_CROSS, 1, 2 }, + { "vec4_lrp", IR_LRP, 1, 3 }, + { "vec4_min", IR_MIN, 1, 2 }, + { "vec4_max", IR_MAX, 1, 2 }, + { "vec4_clamp", IR_CLAMP, 1, 3 }, + { "vec4_seq", IR_SEQUAL, 1, 2 }, + { "vec4_sne", IR_SNEQUAL, 1, 2 }, + { "vec4_sge", IR_SGE, 1, 2 }, + { "vec4_sgt", IR_SGT, 1, 2 }, + { "vec4_sle", IR_SLE, 1, 2 }, + { "vec4_slt", IR_SLT, 1, 2 }, + /* vec4 unary */ + { "vec4_floor", IR_FLOOR, 1, 1 }, + { "vec4_frac", IR_FRAC, 1, 1 }, + { "vec4_abs", IR_ABS, 1, 1 }, + { "vec4_negate", IR_NEG, 1, 1 }, + { "vec4_ddx", IR_DDX, 1, 1 }, + { "vec4_ddy", IR_DDY, 1, 1 }, + /* float binary op */ + { "float_power", IR_POW, 1, 2 }, + /* texture / sampler */ + { "vec4_tex1d", IR_TEX, 1, 2 }, + { "vec4_texb1d", IR_TEXB, 1, 2 }, /* 1d w/ bias */ + { "vec4_texp1d", IR_TEXP, 1, 2 }, /* 1d w/ projection */ + { "vec4_tex2d", IR_TEX, 1, 2 }, + { "vec4_texb2d", IR_TEXB, 1, 2 }, /* 2d w/ bias */ + { "vec4_texp2d", IR_TEXP, 1, 2 }, /* 2d w/ projection */ + { "vec4_tex3d", IR_TEX, 1, 2 }, + { "vec4_texb3d", IR_TEXB, 1, 2 }, /* 3d w/ bias */ + { "vec4_texp3d", IR_TEXP, 1, 2 }, /* 3d w/ projection */ + { "vec4_texcube", IR_TEX, 1, 2 }, /* cubemap */ + { "vec4_tex_rect", IR_TEX, 1, 2 }, /* rectangle */ + { "vec4_texp_rect", IR_TEX, 1, 2 },/* rectangle w/ projection */ + + /* unary op */ + { "int_to_float", IR_I_TO_F, 1, 1 }, + { "float_to_int", IR_F_TO_I, 1, 1 }, + { "float_exp", IR_EXP, 1, 1 }, + { "float_exp2", IR_EXP2, 1, 1 }, + { "float_log2", IR_LOG2, 1, 1 }, + { "float_rsq", IR_RSQ, 1, 1 }, + { "float_rcp", IR_RCP, 1, 1 }, + { "float_sine", IR_SIN, 1, 1 }, + { "float_cosine", IR_COS, 1, 1 }, + { "float_noise1", IR_NOISE1, 1, 1}, + { "float_noise2", IR_NOISE2, 1, 1}, + { "float_noise3", IR_NOISE3, 1, 1}, + { "float_noise4", IR_NOISE4, 1, 1}, + + { NULL, IR_NOP, 0, 0 } +}; + + +static slang_ir_node * +new_node3(slang_ir_opcode op, + slang_ir_node *c0, slang_ir_node *c1, slang_ir_node *c2) +{ + slang_ir_node *n = (slang_ir_node *) _slang_alloc(sizeof(slang_ir_node)); + if (n) { + n->Opcode = op; + n->Children[0] = c0; + n->Children[1] = c1; + n->Children[2] = c2; + n->Writemask = WRITEMASK_XYZW; + n->InstLocation = -1; + } + return n; +} + +static slang_ir_node * +new_node2(slang_ir_opcode op, slang_ir_node *c0, slang_ir_node *c1) +{ + return new_node3(op, c0, c1, NULL); +} + +static slang_ir_node * +new_node1(slang_ir_opcode op, slang_ir_node *c0) +{ + return new_node3(op, c0, NULL, NULL); +} + +static slang_ir_node * +new_node0(slang_ir_opcode op) +{ + return new_node3(op, NULL, NULL, NULL); +} + + +static slang_ir_node * +new_seq(slang_ir_node *left, slang_ir_node *right) +{ + if (!left) + return right; + if (!right) + return left; + return new_node2(IR_SEQ, left, right); +} + +static slang_ir_node * +new_label(slang_label *label) +{ + slang_ir_node *n = new_node0(IR_LABEL); + assert(label); + if (n) + n->Label = label; + return n; +} + +static slang_ir_node * +new_float_literal(const float v[4], GLuint size) +{ + slang_ir_node *n = new_node0(IR_FLOAT); + assert(size <= 4); + COPY_4V(n->Value, v); + /* allocate a storage object, but compute actual location (Index) later */ + n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size); + return n; +} + + +static slang_ir_node * +new_not(slang_ir_node *n) +{ + return new_node1(IR_NOT, n); +} + + +/** + * Inlined subroutine. + */ +static slang_ir_node * +new_inlined_function_call(slang_ir_node *code, slang_label *name) +{ + slang_ir_node *n = new_node1(IR_CALL, code); + assert(name); + if (n) + n->Label = name; + return n; +} + + +/** + * Unconditional jump. + */ +static slang_ir_node * +new_return(slang_label *dest) +{ + slang_ir_node *n = new_node0(IR_RETURN); + assert(dest); + if (n) + n->Label = dest; + return n; +} + + +static slang_ir_node * +new_loop(slang_ir_node *body) +{ + return new_node1(IR_LOOP, body); +} + + +static slang_ir_node * +new_break(slang_ir_node *loopNode) +{ + slang_ir_node *n = new_node0(IR_BREAK); + assert(loopNode); + assert(loopNode->Opcode == IR_LOOP); + if (n) { + /* insert this node at head of linked list */ + n->List = loopNode->List; + loopNode->List = n; + } + return n; +} + + +/** + * Make new IR_BREAK_IF_TRUE. + */ +static slang_ir_node * +new_break_if_true(slang_ir_node *loopNode, slang_ir_node *cond) +{ + slang_ir_node *n; + assert(loopNode); + assert(loopNode->Opcode == IR_LOOP); + n = new_node1(IR_BREAK_IF_TRUE, cond); + if (n) { + /* insert this node at head of linked list */ + n->List = loopNode->List; + loopNode->List = n; + } + return n; +} + + +/** + * Make new IR_CONT_IF_TRUE node. + */ +static slang_ir_node * +new_cont_if_true(slang_ir_node *loopNode, slang_ir_node *cond) +{ + slang_ir_node *n; + assert(loopNode); + assert(loopNode->Opcode == IR_LOOP); + n = new_node1(IR_CONT_IF_TRUE, cond); + if (n) { + /* insert this node at head of linked list */ + n->List = loopNode->List; + loopNode->List = n; + } + return n; +} + + +static slang_ir_node * +new_cond(slang_ir_node *n) +{ + slang_ir_node *c = new_node1(IR_COND, n); + return c; +} + + +static slang_ir_node * +new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart) +{ + return new_node3(IR_IF, cond, ifPart, elsePart); +} + + +/** + * New IR_VAR node - a reference to a previously declared variable. + */ +static slang_ir_node * +new_var(slang_assemble_ctx *A, slang_operation *oper, slang_atom name) +{ + slang_ir_node *n; + slang_variable *var = _slang_locate_variable(oper->locals, name, GL_TRUE); + if (!var) + return NULL; + + assert(!oper->var || oper->var == var); + + n = new_node0(IR_VAR); + if (n) { + _slang_attach_storage(n, var); + } + return n; +} + + +/** + * Check if the given function is really just a wrapper for a + * basic assembly instruction. + */ +static GLboolean +slang_is_asm_function(const slang_function *fun) +{ + if (fun->body->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE && + fun->body->num_children == 1 && + fun->body->children[0].type == SLANG_OPER_ASM) { + return GL_TRUE; + } + return GL_FALSE; +} + + +static GLboolean +_slang_is_noop(const slang_operation *oper) +{ + if (!oper || + oper->type == SLANG_OPER_VOID || + (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID)) + return GL_TRUE; + else + return GL_FALSE; +} + + +/** + * Recursively search tree for a node of the given type. + */ +static slang_operation * +_slang_find_node_type(slang_operation *oper, slang_operation_type type) +{ + GLuint i; + if (oper->type == type) + return oper; + for (i = 0; i < oper->num_children; i++) { + slang_operation *p = _slang_find_node_type(&oper->children[i], type); + if (p) + return p; + } + return NULL; +} + + +static void +slang_resolve_variable(slang_operation *oper) +{ + if (oper->type == SLANG_OPER_IDENTIFIER && !oper->var) { + oper->var = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE); + } +} + + +/** + * Replace particular variables (SLANG_OPER_IDENTIFIER) with new expressions. + */ +static void +slang_substitute(slang_assemble_ctx *A, slang_operation *oper, + GLuint substCount, slang_variable **substOld, + slang_operation **substNew, GLboolean isLHS) +{ + switch (oper->type) { + case SLANG_OPER_VARIABLE_DECL: + { + slang_variable *v = _slang_locate_variable(oper->locals, + oper->a_id, GL_TRUE); + assert(v); + if (v->initializer && oper->num_children == 0) { + /* set child of oper to copy of initializer */ + oper->num_children = 1; + oper->children = slang_operation_new(1); + slang_operation_copy(&oper->children[0], v->initializer); + } + if (oper->num_children == 1) { + /* the initializer */ + slang_substitute(A, &oper->children[0], substCount, + substOld, substNew, GL_FALSE); + } + } + break; + case SLANG_OPER_IDENTIFIER: + assert(oper->num_children == 0); + if (1/**!isLHS XXX FIX */) { + slang_atom id = oper->a_id; + slang_variable *v; + GLuint i; + v = _slang_locate_variable(oper->locals, id, GL_TRUE); + if (!v) { + _mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id); + return; + } + + /* look for a substitution */ + for (i = 0; i < substCount; i++) { + if (v == substOld[i]) { + /* OK, replace this SLANG_OPER_IDENTIFIER with a new expr */ +#if 0 /* DEBUG only */ + if (substNew[i]->type == SLANG_OPER_IDENTIFIER) { + assert(substNew[i]->var); + assert(substNew[i]->var->a_name); + printf("Substitute %s with %s in id node %p\n", + (char*)v->a_name, (char*) substNew[i]->var->a_name, + (void*) oper); + } + else { + printf("Substitute %s with %f in id node %p\n", + (char*)v->a_name, substNew[i]->literal[0], + (void*) oper); + } +#endif + slang_operation_copy(oper, substNew[i]); + break; + } + } + } + break; + + case SLANG_OPER_RETURN: + /* do return replacement here too */ + assert(oper->num_children == 0 || oper->num_children == 1); + if (oper->num_children == 1 && !_slang_is_noop(&oper->children[0])) { + /* replace: + * return expr; + * with: + * __retVal = expr; + * return; + * then do substitutions on the assignment. + */ + slang_operation *blockOper, *assignOper, *returnOper; + + /* check if function actually has a return type */ + assert(A->CurFunction); + if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) { + slang_info_log_error(A->log, "illegal return expression"); + return; + } + + blockOper = slang_operation_new(1); + blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; + blockOper->num_children = 2; + blockOper->locals->outer_scope = oper->locals->outer_scope; + blockOper->children = slang_operation_new(2); + assignOper = blockOper->children + 0; + returnOper = blockOper->children + 1; + + assignOper->type = SLANG_OPER_ASSIGN; + assignOper->num_children = 2; + assignOper->locals->outer_scope = blockOper->locals; + assignOper->children = slang_operation_new(2); + assignOper->children[0].type = SLANG_OPER_IDENTIFIER; + assignOper->children[0].a_id = slang_atom_pool_atom(A->atoms, "__retVal"); + assignOper->children[0].locals->outer_scope = assignOper->locals; + + slang_operation_copy(&assignOper->children[1], + &oper->children[0]); + + returnOper->type = SLANG_OPER_RETURN; /* return w/ no value */ + assert(returnOper->num_children == 0); + + /* do substitutions on the "__retVal = expr" sub-tree */ + slang_substitute(A, assignOper, + substCount, substOld, substNew, GL_FALSE); + + /* install new code */ + slang_operation_copy(oper, blockOper); + slang_operation_destruct(blockOper); + } + else { + /* check if return value was expected */ + assert(A->CurFunction); + if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) { + slang_info_log_error(A->log, "return statement requires an expression"); + return; + } + } + break; + + case SLANG_OPER_ASSIGN: + case SLANG_OPER_SUBSCRIPT: + /* special case: + * child[0] can't have substitutions but child[1] can. + */ + slang_substitute(A, &oper->children[0], + substCount, substOld, substNew, GL_TRUE); + slang_substitute(A, &oper->children[1], + substCount, substOld, substNew, GL_FALSE); + break; + case SLANG_OPER_FIELD: + /* XXX NEW - test */ + slang_substitute(A, &oper->children[0], + substCount, substOld, substNew, GL_TRUE); + break; + default: + { + GLuint i; + for (i = 0; i < oper->num_children; i++) + slang_substitute(A, &oper->children[i], + substCount, substOld, substNew, GL_FALSE); + } + } +} + + + +/** + * Produce inline code for a call to an assembly instruction. + * This is typically used to compile a call to a built-in function like this: + * + * vec4 mix(const vec4 x, const vec4 y, const vec4 a) + * { + * __asm vec4_lrp __retVal, a, y, x; + * } + * + * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM. + */ +static slang_operation * +slang_inline_asm_function(slang_assemble_ctx *A, + slang_function *fun, slang_operation *oper) +{ + const GLuint numArgs = oper->num_children; + GLuint i; + slang_operation *inlined; + const GLboolean haveRetValue = _slang_function_has_return_value(fun); + slang_variable **substOld; + slang_operation **substNew; + + ASSERT(slang_is_asm_function(fun)); + ASSERT(fun->param_count == numArgs + haveRetValue); + + /* + printf("Inline %s as %s\n", + (char*) fun->header.a_name, + (char*) fun->body->children[0].a_id); + */ + + /* + * We'll substitute formal params with actual args in the asm call. + */ + substOld = (slang_variable **) + _slang_alloc(numArgs * sizeof(slang_variable *)); + substNew = (slang_operation **) + _slang_alloc(numArgs * sizeof(slang_operation *)); + for (i = 0; i < numArgs; i++) { + substOld[i] = fun->parameters->variables[i]; + substNew[i] = oper->children + i; + } + + /* make a copy of the code to inline */ + inlined = slang_operation_new(1); + slang_operation_copy(inlined, &fun->body->children[0]); + if (haveRetValue) { + /* get rid of the __retVal child */ + for (i = 0; i < numArgs; i++) { + inlined->children[i] = inlined->children[i + 1]; + } + inlined->num_children--; + } + + /* now do formal->actual substitutions */ + slang_substitute(A, inlined, numArgs, substOld, substNew, GL_FALSE); + + _slang_free(substOld); + _slang_free(substNew); + + return inlined; +} + + +/** + * Inline the given function call operation. + * Return a new slang_operation that corresponds to the inlined code. + */ +static slang_operation * +slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun, + slang_operation *oper, slang_operation *returnOper) +{ + typedef enum { + SUBST = 1, + COPY_IN, + COPY_OUT + } ParamMode; + ParamMode *paramMode; + const GLboolean haveRetValue = _slang_function_has_return_value(fun); + const GLuint numArgs = oper->num_children; + const GLuint totalArgs = numArgs + haveRetValue; + slang_operation *args = oper->children; + slang_operation *inlined, *top; + slang_variable **substOld; + slang_operation **substNew; + GLuint substCount, numCopyIn, i; + slang_function *prevFunction; + + /* save / push */ + prevFunction = A->CurFunction; + A->CurFunction = fun; + + /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */ + assert(fun->param_count == totalArgs); + + /* allocate temporary arrays */ + paramMode = (ParamMode *) + _slang_alloc(totalArgs * sizeof(ParamMode)); + substOld = (slang_variable **) + _slang_alloc(totalArgs * sizeof(slang_variable *)); + substNew = (slang_operation **) + _slang_alloc(totalArgs * sizeof(slang_operation *)); + +#if 0 + printf("Inline call to %s (total vars=%d nparams=%d)\n", + (char *) fun->header.a_name, + fun->parameters->num_variables, numArgs); +#endif + + if (haveRetValue && !returnOper) { + /* Create 3-child comma sequence for inlined code: + * child[0]: declare __resultTmp + * child[1]: inlined function body + * child[2]: __resultTmp + */ + slang_operation *commaSeq; + slang_operation *declOper = NULL; + slang_variable *resultVar; + + commaSeq = slang_operation_new(1); + commaSeq->type = SLANG_OPER_SEQUENCE; + assert(commaSeq->locals); + commaSeq->locals->outer_scope = oper->locals->outer_scope; + commaSeq->num_children = 3; + commaSeq->children = slang_operation_new(3); + /* allocate the return var */ + resultVar = slang_variable_scope_grow(commaSeq->locals); + /* + printf("Alloc __resultTmp in scope %p for retval of calling %s\n", + (void*)commaSeq->locals, (char *) fun->header.a_name); + */ + + resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp"); + resultVar->type = fun->header.type; /* XXX copy? */ + resultVar->isTemp = GL_TRUE; + + /* child[0] = __resultTmp declaration */ + declOper = &commaSeq->children[0]; + declOper->type = SLANG_OPER_VARIABLE_DECL; + declOper->a_id = resultVar->a_name; + declOper->locals->outer_scope = commaSeq->locals; + + /* child[1] = function body */ + inlined = &commaSeq->children[1]; + inlined->locals->outer_scope = commaSeq->locals; + + /* child[2] = __resultTmp reference */ + returnOper = &commaSeq->children[2]; + returnOper->type = SLANG_OPER_IDENTIFIER; + returnOper->a_id = resultVar->a_name; + returnOper->locals->outer_scope = commaSeq->locals; + + top = commaSeq; + } + else { + top = inlined = slang_operation_new(1); + /* XXXX this may be inappropriate!!!! */ + inlined->locals->outer_scope = oper->locals->outer_scope; + } + + + assert(inlined->locals); + + /* Examine the parameters, look for inout/out params, look for possible + * substitutions, etc: + * param type behaviour + * in copy actual to local + * const in substitute param with actual + * out copy out + */ + substCount = 0; + for (i = 0; i < totalArgs; i++) { + slang_variable *p = fun->parameters->variables[i]; + /* + printf("Param %d: %s %s \n", i, + slang_type_qual_string(p->type.qualifier), + (char *) p->a_name); + */ + if (p->type.qualifier == SLANG_QUAL_INOUT || + p->type.qualifier == SLANG_QUAL_OUT) { + /* an output param */ + slang_operation *arg; + if (i < numArgs) + arg = &args[i]; + else + arg = returnOper; + paramMode[i] = SUBST; + + if (arg->type == SLANG_OPER_IDENTIFIER) + slang_resolve_variable(arg); + + /* replace parameter 'p' with argument 'arg' */ + substOld[substCount] = p; + substNew[substCount] = arg; /* will get copied */ + substCount++; + } + else if (p->type.qualifier == SLANG_QUAL_CONST) { + /* a constant input param */ + if (args[i].type == SLANG_OPER_IDENTIFIER || + args[i].type == SLANG_OPER_LITERAL_FLOAT) { + /* replace all occurances of this parameter variable with the + * actual argument variable or a literal. + */ + paramMode[i] = SUBST; + slang_resolve_variable(&args[i]); + substOld[substCount] = p; + substNew[substCount] = &args[i]; /* will get copied */ + substCount++; + } + else { + paramMode[i] = COPY_IN; + } + } + else { + paramMode[i] = COPY_IN; + } + assert(paramMode[i]); + } + + /* actual code inlining: */ + slang_operation_copy(inlined, fun->body); + + /*** XXX review this */ + assert(inlined->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE); + inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE; + +#if 0 + printf("======================= orig body code ======================\n"); + printf("=== params scope = %p\n", (void*) fun->parameters); + slang_print_tree(fun->body, 8); + printf("======================= copied code =========================\n"); + slang_print_tree(inlined, 8); +#endif + + /* do parameter substitution in inlined code: */ + slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE); + +#if 0 + printf("======================= subst code ==========================\n"); + slang_print_tree(inlined, 8); + printf("=============================================================\n"); +#endif + + /* New prolog statements: (inserted before the inlined code) + * Copy the 'in' arguments. + */ + numCopyIn = 0; + for (i = 0; i < numArgs; i++) { + if (paramMode[i] == COPY_IN) { + slang_variable *p = fun->parameters->variables[i]; + /* declare parameter 'p' */ + slang_operation *decl = slang_operation_insert(&inlined->num_children, + &inlined->children, + numCopyIn); + /* + printf("COPY_IN %s from expr\n", (char*)p->a_name); + */ + decl->type = SLANG_OPER_VARIABLE_DECL; + assert(decl->locals); + decl->locals->outer_scope = inlined->locals; + decl->a_id = p->a_name; + decl->num_children = 1; + decl->children = slang_operation_new(1); + + /* child[0] is the var's initializer */ + slang_operation_copy(&decl->children[0], args + i); + + numCopyIn++; + } + } + + /* New epilog statements: + * 1. Create end of function label to jump to from return statements. + * 2. Copy the 'out' parameter vars + */ + { + slang_operation *lab = slang_operation_insert(&inlined->num_children, + &inlined->children, + inlined->num_children); + lab->type = SLANG_OPER_LABEL; + lab->label = A->curFuncEndLabel; + } + + for (i = 0; i < totalArgs; i++) { + if (paramMode[i] == COPY_OUT) { + const slang_variable *p = fun->parameters->variables[i]; + /* actualCallVar = outParam */ + /*if (i > 0 || !haveRetValue)*/ + slang_operation *ass = slang_operation_insert(&inlined->num_children, + &inlined->children, + inlined->num_children); + ass->type = SLANG_OPER_ASSIGN; + ass->num_children = 2; + ass->locals->outer_scope = inlined->locals; + ass->children = slang_operation_new(2); + ass->children[0] = args[i]; /*XXX copy */ + ass->children[1].type = SLANG_OPER_IDENTIFIER; + ass->children[1].a_id = p->a_name; + ass->children[1].locals->outer_scope = ass->locals; + } + } + + _slang_free(paramMode); + _slang_free(substOld); + _slang_free(substNew); + +#if 0 + printf("Done Inline call to %s (total vars=%d nparams=%d)\n", + (char *) fun->header.a_name, + fun->parameters->num_variables, numArgs); + slang_print_tree(top, 0); +#endif + + /* pop */ + A->CurFunction = prevFunction; + + return top; +} + + +static slang_ir_node * +_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun, + slang_operation *oper, slang_operation *dest) +{ + slang_ir_node *n; + slang_operation *inlined; + slang_label *prevFuncEndLabel; + char name[200]; + + prevFuncEndLabel = A->curFuncEndLabel; + sprintf(name, "__endOfFunc_%s_", (char *) fun->header.a_name); + A->curFuncEndLabel = _slang_label_new(name); + assert(A->curFuncEndLabel); + + if (slang_is_asm_function(fun) && !dest) { + /* assemble assembly function - tree style */ + inlined = slang_inline_asm_function(A, fun, oper); + } + else { + /* non-assembly function */ + inlined = slang_inline_function_call(A, fun, oper, dest); + if (inlined && _slang_find_node_type(inlined, SLANG_OPER_RETURN)) { + slang_operation *callOper; + /* The function we're calling has one or more 'return' statements. + * So, we can't truly inline this function because we need to + * implement 'return' with RET (and CAL). + * Nevertheless, we performed "inlining" to make a new instance + * of the function body to deal with static register allocation. + * + * XXX check if there's one 'return' and if it's the very last + * statement in the function - we can optimize that case. + */ + assert(inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE || + inlined->type == SLANG_OPER_SEQUENCE); + if (_slang_function_has_return_value(fun) && !dest) { + assert(inlined->children[0].type == SLANG_OPER_VARIABLE_DECL); + assert(inlined->children[2].type == SLANG_OPER_IDENTIFIER); + callOper = &inlined->children[1]; + } + else { + callOper = inlined; + } + callOper->type = SLANG_OPER_INLINED_CALL; + callOper->fun = fun; + callOper->label = _slang_label_new_unique((char*) fun->header.a_name); + } + } + + if (!inlined) + return NULL; + + /* Replace the function call with the inlined block */ + slang_operation_destruct(oper); + *oper = *inlined; + _slang_free(inlined); + +#if 0 + assert(inlined->locals); + printf("*** Inlined code for call to %s:\n", + (char*) fun->header.a_name); + slang_print_tree(oper, 10); + printf("\n"); +#endif + + n = _slang_gen_operation(A, oper); + + /*_slang_label_delete(A->curFuncEndLabel);*/ + A->curFuncEndLabel = prevFuncEndLabel; + + return n; +} + + +static slang_asm_info * +slang_find_asm_info(const char *name) +{ + GLuint i; + for (i = 0; AsmInfo[i].Name; i++) { + if (_mesa_strcmp(AsmInfo[i].Name, name) == 0) { + return AsmInfo + i; + } + } + return NULL; +} + + +static GLuint +make_writemask(const char *field) +{ + GLuint mask = 0x0; + while (*field) { + switch (*field) { + case 'x': + case 's': + case 'r': + mask |= WRITEMASK_X; + break; + case 'y': + case 't': + case 'g': + mask |= WRITEMASK_Y; + break; + case 'z': + case 'p': + case 'b': + mask |= WRITEMASK_Z; + break; + case 'w': + case 'q': + case 'a': + mask |= WRITEMASK_W; + break; + default: + _mesa_problem(NULL, "invalid writemask in make_writemask()"); + return 0; + } + field++; + } + if (mask == 0x0) + return WRITEMASK_XYZW; + else + return mask; +} + + +/** + * Generate IR tree for an asm instruction/operation such as: + * __asm vec4_dot __retVal.x, v1, v2; + */ +static slang_ir_node * +_slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper, + slang_operation *dest) +{ + const slang_asm_info *info; + slang_ir_node *kids[3], *n; + GLuint j, firstOperand; + + assert(oper->type == SLANG_OPER_ASM); + + info = slang_find_asm_info((char *) oper->a_id); + if (!info) { + _mesa_problem(NULL, "undefined __asm function %s\n", + (char *) oper->a_id); + assert(info); + } + assert(info->NumParams <= 3); + + if (info->NumParams == oper->num_children) { + /* Storage for result is not specified. + * Children[0], [1] are the operands. + */ + firstOperand = 0; + } + else { + /* Storage for result (child[0]) is specified. + * Children[1], [2] are the operands. + */ + firstOperand = 1; + } + + /* assemble child(ren) */ + kids[0] = kids[1] = kids[2] = NULL; + for (j = 0; j < info->NumParams; j++) { + kids[j] = _slang_gen_operation(A, &oper->children[firstOperand + j]); + if (!kids[j]) + return NULL; + } + + n = new_node3(info->Opcode, kids[0], kids[1], kids[2]); + + if (firstOperand) { + /* Setup n->Store to be a particular location. Otherwise, storage + * for the result (a temporary) will be allocated later. + */ + GLuint writemask = WRITEMASK_XYZW; + slang_operation *dest_oper; + slang_ir_node *n0; + + dest_oper = &oper->children[0]; + while (dest_oper->type == SLANG_OPER_FIELD) { + /* writemask */ + writemask &= make_writemask((char*) dest_oper->a_id); + dest_oper = &dest_oper->children[0]; + } + + n0 = _slang_gen_operation(A, dest_oper); + assert(n0->Var); + assert(n0->Store); + assert(!n->Store); + n->Store = n0->Store; + n->Writemask = writemask; + + _slang_free(n0); + } + + return n; +} + + +static void +print_funcs(struct slang_function_scope_ *scope, const char *name) +{ + GLuint i; + for (i = 0; i < scope->num_functions; i++) { + slang_function *f = &scope->functions[i]; + if (!name || strcmp(name, (char*) f->header.a_name) == 0) + printf(" %s (%d args)\n", name, f->param_count); + + } + if (scope->outer_scope) + print_funcs(scope->outer_scope, name); +} + + +/** + * Return first function in the scope that has the given name. + * This is the function we'll try to call when there is no exact match + * between function parameters and call arguments. + * + * XXX we should really create a list of candidate functions and try + * all of them... + */ +static slang_function * +_slang_first_function(struct slang_function_scope_ *scope, const char *name) +{ + GLuint i; + for (i = 0; i < scope->num_functions; i++) { + slang_function *f = &scope->functions[i]; + if (strcmp(name, (char*) f->header.a_name) == 0) + return f; + } + if (scope->outer_scope) + return _slang_first_function(scope->outer_scope, name); + return NULL; +} + + + +/** + * Assemble a function call, given a particular function name. + * \param name the function's name (operators like '*' are possible). + */ +static slang_ir_node * +_slang_gen_function_call_name(slang_assemble_ctx *A, const char *name, + slang_operation *oper, slang_operation *dest) +{ + slang_operation *params = oper->children; + const GLuint param_count = oper->num_children; + slang_atom atom; + slang_function *fun; + + atom = slang_atom_pool_atom(A->atoms, name); + if (atom == SLANG_ATOM_NULL) + return NULL; + + /* + * Use 'name' to find the function to call + */ + fun = _slang_locate_function(A->space.funcs, atom, params, param_count, + &A->space, A->atoms, A->log); + if (!fun) { + /* A function with exactly the right parameters/types was not found. + * Try adapting the parameters. + */ + fun = _slang_first_function(A->space.funcs, name); + if (!fun || !_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) { + slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name); + return NULL; + } + assert(fun); + } + + return _slang_gen_function_call(A, fun, oper, dest); +} + + +static GLboolean +_slang_is_constant_cond(const slang_operation *oper, GLboolean *value) +{ + if (oper->type == SLANG_OPER_LITERAL_FLOAT || + oper->type == SLANG_OPER_LITERAL_INT || + oper->type == SLANG_OPER_LITERAL_BOOL) { + if (oper->literal[0]) + *value = GL_TRUE; + else + *value = GL_FALSE; + return GL_TRUE; + } + else if (oper->type == SLANG_OPER_EXPRESSION && + oper->num_children == 1) { + return _slang_is_constant_cond(&oper->children[0], value); + } + return GL_FALSE; +} + + +/** + * Test if an operation is a scalar or boolean. + */ +static GLboolean +_slang_is_scalar_or_boolean(slang_assemble_ctx *A, slang_operation *oper) +{ + slang_typeinfo type; + GLint size; + + slang_typeinfo_construct(&type); + _slang_typeof_operation(A, oper, &type); + size = _slang_sizeof_type_specifier(&type.spec); + slang_typeinfo_destruct(&type); + return size == 1; +} + + +/** + * Generate loop code using high-level IR_LOOP instruction + */ +static slang_ir_node * +_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper) +{ + /* + * LOOP: + * BREAK if !expr (child[0]) + * body code (child[1]) + */ + slang_ir_node *prevLoop, *loop, *breakIf, *body; + GLboolean isConst, constTrue; + + /* type-check expression */ + if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) { + slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'"); + return NULL; + } + + /* Check if loop condition is a constant */ + isConst = _slang_is_constant_cond(&oper->children[0], &constTrue); + + if (isConst && !constTrue) { + /* loop is never executed! */ + return new_node0(IR_NOP); + } + + loop = new_loop(NULL); + + /* save old, push new loop */ + prevLoop = A->CurLoop; + A->CurLoop = loop; + + if (isConst && constTrue) { + /* while(nonzero constant), no conditional break */ + breakIf = NULL; + } + else { + slang_ir_node *cond + = new_cond(new_not(_slang_gen_operation(A, &oper->children[0]))); + breakIf = new_break_if_true(A->CurLoop, cond); + } + body = _slang_gen_operation(A, &oper->children[1]); + loop->Children[0] = new_seq(breakIf, body); + + /* Do infinite loop detection */ + /* loop->List is head of linked list of break/continue nodes */ + if (!loop->List && isConst && constTrue) { + /* infinite loop detected */ + A->CurLoop = prevLoop; /* clean-up */ + slang_info_log_error(A->log, "Infinite loop detected!"); + return NULL; + } + + /* pop loop, restore prev */ + A->CurLoop = prevLoop; + + return loop; +} + + +/** + * Generate IR tree for a do-while loop using high-level LOOP, IF instructions. + */ +static slang_ir_node * +_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper) +{ + /* + * LOOP: + * body code (child[0]) + * tail code: + * BREAK if !expr (child[1]) + */ + slang_ir_node *prevLoop, *loop; + GLboolean isConst, constTrue; + + /* type-check expression */ + if (!_slang_is_scalar_or_boolean(A, &oper->children[1])) { + slang_info_log_error(A->log, "scalar/boolean expression expected for 'do/while'"); + return NULL; + } + + loop = new_loop(NULL); + + /* save old, push new loop */ + prevLoop = A->CurLoop; + A->CurLoop = loop; + + /* loop body: */ + loop->Children[0] = _slang_gen_operation(A, &oper->children[0]); + + /* Check if loop condition is a constant */ + isConst = _slang_is_constant_cond(&oper->children[1], &constTrue); + if (isConst && constTrue) { + /* do { } while(1) ==> no conditional break */ + loop->Children[1] = NULL; /* no tail code */ + } + else { + slang_ir_node *cond + = new_cond(new_not(_slang_gen_operation(A, &oper->children[1]))); + loop->Children[1] = new_break_if_true(A->CurLoop, cond); + } + + /* XXX we should do infinite loop detection, as above */ + + /* pop loop, restore prev */ + A->CurLoop = prevLoop; + + return loop; +} + + +/** + * Generate for-loop using high-level IR_LOOP instruction. + */ +static slang_ir_node * +_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper) +{ + /* + * init code (child[0]) + * LOOP: + * BREAK if !expr (child[1]) + * body code (child[3]) + * tail code: + * incr code (child[2]) // XXX continue here + */ + slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr; + + init = _slang_gen_operation(A, &oper->children[0]); + loop = new_loop(NULL); + + /* save old, push new loop */ + prevLoop = A->CurLoop; + A->CurLoop = loop; + + cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1]))); + breakIf = new_break_if_true(A->CurLoop, cond); + body = _slang_gen_operation(A, &oper->children[3]); + incr = _slang_gen_operation(A, &oper->children[2]); + + loop->Children[0] = new_seq(breakIf, body); + loop->Children[1] = incr; /* tail code */ + + /* pop loop, restore prev */ + A->CurLoop = prevLoop; + + return new_seq(init, loop); +} + + +static slang_ir_node * +_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper) +{ + slang_ir_node *n, *loopNode; + assert(oper->type == SLANG_OPER_CONTINUE); + loopNode = A->CurLoop; + assert(loopNode); + assert(loopNode->Opcode == IR_LOOP); + n = new_node0(IR_CONT); + if (n) { + n->Parent = loopNode; + /* insert this node at head of linked list */ + n->List = loopNode->List; + loopNode->List = n; + } + return n; +} + + +/** + * Determine if the given operation is of a specific type. + */ +static GLboolean +is_operation_type(const slang_operation *oper, slang_operation_type type) +{ + if (oper->type == type) + return GL_TRUE; + else if ((oper->type == SLANG_OPER_BLOCK_NEW_SCOPE || + oper->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) && + oper->num_children == 1) + return is_operation_type(&oper->children[0], type); + else + return GL_FALSE; +} + + +/** + * Generate IR tree for an if/then/else conditional using high-level + * IR_IF instruction. + */ +static slang_ir_node * +_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) +{ + /* + * eval expr (child[0]) + * IF expr THEN + * if-body code + * ELSE + * else-body code + * ENDIF + */ + const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]); + slang_ir_node *ifNode, *cond, *ifBody, *elseBody; + GLboolean isConst, constTrue; + + /* type-check expression */ + if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) { + slang_info_log_error(A->log, "scalar/boolean expression expected for 'if'"); + return NULL; + } + + isConst = _slang_is_constant_cond(&oper->children[0], &constTrue); + if (isConst) { + if (constTrue) { + /* if (true) ... */ + return _slang_gen_operation(A, &oper->children[1]); + } + else { + /* if (false) ... */ + return _slang_gen_operation(A, &oper->children[2]); + } + } + + cond = _slang_gen_operation(A, &oper->children[0]); + cond = new_cond(cond); + + if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)) { + /* Special case: generate a conditional break */ + ifBody = new_break_if_true(A->CurLoop, cond); + if (haveElseClause) { + elseBody = _slang_gen_operation(A, &oper->children[2]); + return new_seq(ifBody, elseBody); + } + return ifBody; + } + else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)) { + /* Special case: generate a conditional break */ + ifBody = new_cont_if_true(A->CurLoop, cond); + if (haveElseClause) { + elseBody = _slang_gen_operation(A, &oper->children[2]); + return new_seq(ifBody, elseBody); + } + return ifBody; + } + else { + /* general case */ + ifBody = _slang_gen_operation(A, &oper->children[1]); + if (haveElseClause) + elseBody = _slang_gen_operation(A, &oper->children[2]); + else + elseBody = NULL; + ifNode = new_if(cond, ifBody, elseBody); + return ifNode; + } +} + + + +static slang_ir_node * +_slang_gen_not(slang_assemble_ctx * A, const slang_operation *oper) +{ + slang_ir_node *n; + + assert(oper->type == SLANG_OPER_NOT); + + /* type-check expression */ + if (!_slang_is_scalar_or_boolean(A, &oper->children[0])) { + slang_info_log_error(A->log, + "scalar/boolean expression expected for '!'"); + return NULL; + } + + n = _slang_gen_operation(A, &oper->children[0]); + if (n) + return new_not(n); + else + return NULL; +} + + +static slang_ir_node * +_slang_gen_xor(slang_assemble_ctx * A, const slang_operation *oper) +{ + slang_ir_node *n1, *n2; + + assert(oper->type == SLANG_OPER_LOGICALXOR); + + if (!_slang_is_scalar_or_boolean(A, &oper->children[0]) || + !_slang_is_scalar_or_boolean(A, &oper->children[0])) { + slang_info_log_error(A->log, + "scalar/boolean expressions expected for '^^'"); + return NULL; + } + + n1 = _slang_gen_operation(A, &oper->children[0]); + if (!n1) + return NULL; + n2 = _slang_gen_operation(A, &oper->children[1]); + if (!n2) + return NULL; + return new_node2(IR_NOTEQUAL, n1, n2); +} + + +/** + * Generate IR node for storage of a temporary of given size. + */ +static slang_ir_node * +_slang_gen_temporary(GLint size) +{ + slang_ir_storage *store; + slang_ir_node *n = NULL; + + store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size); + if (store) { + n = new_node0(IR_VAR_DECL); + if (n) { + n->Store = store; + } + else { + _slang_free(store); + } + } + return n; +} + + +/** + * Generate IR node for allocating/declaring a variable. + */ +static slang_ir_node * +_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var) +{ + slang_ir_node *n; + assert(!is_sampler_type(&var->type)); + n = new_node0(IR_VAR_DECL); + if (n) { + _slang_attach_storage(n, var); + + assert(var->aux); + assert(n->Store == var->aux); + assert(n->Store); + assert(n->Store->Index < 0); + + n->Store->File = PROGRAM_TEMPORARY; + n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier); + assert(n->Store->Size > 0); + } + return n; +} + + +/** + * Generate code for a selection expression: b ? x : y + * XXX In some cases we could implement a selection expression + * with an LRP instruction (use the boolean as the interpolant). + * Otherwise, we use an IF/ELSE/ENDIF construct. + */ +static slang_ir_node * +_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) +{ + slang_ir_node *cond, *ifNode, *trueExpr, *falseExpr, *trueNode, *falseNode; + slang_ir_node *tmpDecl, *tmpVar, *tree; + slang_typeinfo type; + int size; + + assert(oper->type == SLANG_OPER_SELECT); + assert(oper->num_children == 3); + + /* size of x or y's type */ + slang_typeinfo_construct(&type); + _slang_typeof_operation(A, &oper->children[1], &type); + size = _slang_sizeof_type_specifier(&type.spec); + assert(size > 0); + + /* temporary var */ + tmpDecl = _slang_gen_temporary(size); + + /* the condition (child 0) */ + cond = _slang_gen_operation(A, &oper->children[0]); + cond = new_cond(cond); + + /* if-true body (child 1) */ + tmpVar = new_node0(IR_VAR); + tmpVar->Store = tmpDecl->Store; + trueExpr = _slang_gen_operation(A, &oper->children[1]); + trueNode = new_node2(IR_MOVE, tmpVar, trueExpr); + + /* if-false body (child 2) */ + tmpVar = new_node0(IR_VAR); + tmpVar->Store = tmpDecl->Store; + falseExpr = _slang_gen_operation(A, &oper->children[2]); + falseNode = new_node2(IR_MOVE, tmpVar, falseExpr); + + ifNode = new_if(cond, trueNode, falseNode); + + /* tmp var value */ + tmpVar = new_node0(IR_VAR); + tmpVar->Store = tmpDecl->Store; + + tree = new_seq(ifNode, tmpVar); + tree = new_seq(tmpDecl, tree); + + /*_slang_print_ir_tree(tree, 10);*/ + return tree; +} + + +/** + * Generate code for &&. + */ +static slang_ir_node * +_slang_gen_logical_and(slang_assemble_ctx *A, slang_operation *oper) +{ + /* rewrite "a && b" as "a ? b : false" */ + slang_operation *select; + slang_ir_node *n; + + select = slang_operation_new(1); + select->type = SLANG_OPER_SELECT; + select->num_children = 3; + select->children = slang_operation_new(3); + + slang_operation_copy(&select->children[0], &oper->children[0]); + slang_operation_copy(&select->children[1], &oper->children[1]); + select->children[2].type = SLANG_OPER_LITERAL_BOOL; + ASSIGN_4V(select->children[2].literal, 0, 0, 0, 0); /* false */ + select->children[2].literal_size = 1; + + n = _slang_gen_select(A, select); + return n; +} + + +/** + * Generate code for ||. + */ +static slang_ir_node * +_slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper) +{ + /* rewrite "a || b" as "a ? true : b" */ + slang_operation *select; + slang_ir_node *n; + + select = slang_operation_new(1); + select->type = SLANG_OPER_SELECT; + select->num_children = 3; + select->children = slang_operation_new(3); + + slang_operation_copy(&select->children[0], &oper->children[0]); + select->children[1].type = SLANG_OPER_LITERAL_BOOL; + ASSIGN_4V(select->children[1].literal, 1, 1, 1, 1); /* true */ + select->children[1].literal_size = 1; + slang_operation_copy(&select->children[2], &oper->children[1]); + + n = _slang_gen_select(A, select); + return n; +} + + +/** + * Generate IR tree for a return statement. + */ +static slang_ir_node * +_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) +{ + const GLboolean haveReturnValue + = (oper->num_children == 1 && oper->children[0].type != SLANG_OPER_VOID); + + /* error checking */ + assert(A->CurFunction); + if (haveReturnValue && + A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) { + slang_info_log_error(A->log, "illegal return expression"); + return NULL; + } + else if (!haveReturnValue && + A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) { + slang_info_log_error(A->log, "return statement requires an expression"); + return NULL; + } + + if (!haveReturnValue) { + return new_return(A->curFuncEndLabel); + } + else { + /* + * Convert from: + * return expr; + * To: + * __retVal = expr; + * return; // goto __endOfFunction + */ + slang_operation *assign; + slang_atom a_retVal; + slang_ir_node *n; + + a_retVal = slang_atom_pool_atom(A->atoms, "__retVal"); + assert(a_retVal); + +#if 1 /* DEBUG */ + { + slang_variable *v + = _slang_locate_variable(oper->locals, a_retVal, GL_TRUE); + if (!v) { + /* trying to return a value in a void-valued function */ + return NULL; + } + } +#endif + + assign = slang_operation_new(1); + assign->type = SLANG_OPER_ASSIGN; + assign->num_children = 2; + assign->children = slang_operation_new(2); + /* lhs (__retVal) */ + assign->children[0].type = SLANG_OPER_IDENTIFIER; + assign->children[0].a_id = a_retVal; + assign->children[0].locals->outer_scope = assign->locals; + /* rhs (expr) */ + /* XXX we might be able to avoid this copy someday */ + slang_operation_copy(&assign->children[1], &oper->children[0]); + + /* assemble the new code */ + n = new_seq(_slang_gen_operation(A, assign), + new_return(A->curFuncEndLabel)); + + slang_operation_delete(assign); + return n; + } +} + + +/** + * Generate IR tree for a variable declaration. + */ +static slang_ir_node * +_slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper) +{ + slang_ir_node *n; + slang_ir_node *varDecl; + slang_variable *v; + const char *varName = (char *) oper->a_id; + + assert(oper->num_children == 0 || oper->num_children == 1); + + v = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE); + assert(v); + + varDecl = _slang_gen_var_decl(A, v); + + if (oper->num_children > 0) { + /* child is initializer */ + slang_ir_node *var, *init, *rhs; + assert(oper->num_children == 1); + var = new_var(A, oper, oper->a_id); + if (!var) { + slang_info_log_error(A->log, "undefined variable '%s'", varName); + return NULL; + } + /* XXX make copy of this initializer? */ + rhs = _slang_gen_operation(A, &oper->children[0]); + if (!rhs) + return NULL; /* must have found an error */ + init = new_node2(IR_MOVE, var, rhs); + /*assert(rhs->Opcode != IR_SEQ);*/ + n = new_seq(varDecl, init); + } + else if (v->initializer) { + slang_ir_node *var, *init, *rhs; + var = new_var(A, oper, oper->a_id); + if (!var) { + slang_info_log_error(A->log, "undefined variable '%s'", varName); + return NULL; + } +#if 0 + /* XXX make copy of this initializer? */ + { + slang_operation dup; + slang_operation_construct(&dup); + slang_operation_copy(&dup, v->initializer); + _slang_simplify(&dup, &A->space, A->atoms); + rhs = _slang_gen_operation(A, &dup); + } +#else + _slang_simplify(v->initializer, &A->space, A->atoms); + rhs = _slang_gen_operation(A, v->initializer); +#endif + if (!rhs) + return NULL; + + assert(rhs); + init = new_node2(IR_MOVE, var, rhs); + /* + assert(rhs->Opcode != IR_SEQ); + */ + n = new_seq(varDecl, init); + } + else { + n = varDecl; + } + return n; +} + + +/** + * Generate IR tree for a variable (such as in an expression). + */ +static slang_ir_node * +_slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper) +{ + /* If there's a variable associated with this oper (from inlining) + * use it. Otherwise, use the oper's var id. + */ + slang_atom aVar = oper->var ? oper->var->a_name : oper->a_id; + slang_ir_node *n = new_var(A, oper, aVar); + if (!n) { + slang_info_log_error(A->log, "undefined variable '%s'", (char *) aVar); + return NULL; + } + return n; +} + + +/** + * Some write-masked assignments are simple, but others are hard. + * Simple example: + * vec3 v; + * v.xy = vec2(a, b); + * Hard example: + * vec3 v; + * v.zy = vec2(a, b); + * this gets transformed/swizzled into: + * v.zy = vec2(a, b).*yx* (* = don't care) + * This function helps to determine simple vs. non-simple. + */ +static GLboolean +_slang_simple_writemask(GLuint writemask, GLuint swizzle) +{ + switch (writemask) { + case WRITEMASK_X: + return GET_SWZ(swizzle, 0) == SWIZZLE_X; + case WRITEMASK_Y: + return GET_SWZ(swizzle, 1) == SWIZZLE_Y; + case WRITEMASK_Z: + return GET_SWZ(swizzle, 2) == SWIZZLE_Z; + case WRITEMASK_W: + return GET_SWZ(swizzle, 3) == SWIZZLE_W; + case WRITEMASK_XY: + return (GET_SWZ(swizzle, 0) == SWIZZLE_X) + && (GET_SWZ(swizzle, 1) == SWIZZLE_Y); + case WRITEMASK_XYZ: + return (GET_SWZ(swizzle, 0) == SWIZZLE_X) + && (GET_SWZ(swizzle, 1) == SWIZZLE_Y) + && (GET_SWZ(swizzle, 2) == SWIZZLE_Z); + case WRITEMASK_XYZW: + return swizzle == SWIZZLE_NOOP; + default: + return GL_FALSE; + } +} + + +/** + * Convert the given swizzle into a writemask. In some cases this + * is trivial, in other cases, we'll need to also swizzle the right + * hand side to put components in the right places. + * \param swizzle the incoming swizzle + * \param writemaskOut returns the writemask + * \param swizzleOut swizzle to apply to the right-hand-side + * \return GL_FALSE for simple writemasks, GL_TRUE for non-simple + */ +static GLboolean +swizzle_to_writemask(GLuint swizzle, + GLuint *writemaskOut, GLuint *swizzleOut) +{ + GLuint mask = 0x0, newSwizzle[4]; + GLint i, size; + + /* make new dst writemask, compute size */ + for (i = 0; i < 4; i++) { + const GLuint swz = GET_SWZ(swizzle, i); + if (swz == SWIZZLE_NIL) { + /* end */ + break; + } + assert(swz >= 0 && swz <= 3); + mask |= (1 << swz); + } + assert(mask <= 0xf); + size = i; /* number of components in mask/swizzle */ + + *writemaskOut = mask; + + /* make new src swizzle, by inversion */ + for (i = 0; i < 4; i++) { + newSwizzle[i] = i; /*identity*/ + } + for (i = 0; i < size; i++) { + const GLuint swz = GET_SWZ(swizzle, i); + newSwizzle[swz] = i; + } + *swizzleOut = MAKE_SWIZZLE4(newSwizzle[0], + newSwizzle[1], + newSwizzle[2], + newSwizzle[3]); + + if (_slang_simple_writemask(mask, *swizzleOut)) { + if (size >= 1) + assert(GET_SWZ(*swizzleOut, 0) == SWIZZLE_X); + if (size >= 2) + assert(GET_SWZ(*swizzleOut, 1) == SWIZZLE_Y); + if (size >= 3) + assert(GET_SWZ(*swizzleOut, 2) == SWIZZLE_Z); + if (size >= 4) + assert(GET_SWZ(*swizzleOut, 3) == SWIZZLE_W); + return GL_TRUE; + } + else + return GL_FALSE; +} + + +static slang_ir_node * +_slang_gen_swizzle(slang_ir_node *child, GLuint swizzle) +{ + slang_ir_node *n = new_node1(IR_SWIZZLE, child); + assert(child); + if (n) { + n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -1); + n->Store->Swizzle = swizzle; + } + return n; +} + + +/** + * Generate IR tree for an assignment (=). + */ +static slang_ir_node * +_slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper) +{ + if (oper->children[0].type == SLANG_OPER_IDENTIFIER) { + /* Check that var is writeable */ + slang_variable *var + = _slang_locate_variable(oper->children[0].locals, + oper->children[0].a_id, GL_TRUE); + if (!var) { + slang_info_log_error(A->log, "undefined variable '%s'", + (char *) oper->children[0].a_id); + return NULL; + } + if (var->type.qualifier == SLANG_QUAL_CONST || + var->type.qualifier == SLANG_QUAL_ATTRIBUTE || + var->type.qualifier == SLANG_QUAL_UNIFORM || + (var->type.qualifier == SLANG_QUAL_VARYING && + A->program->Target == GL_FRAGMENT_PROGRAM_ARB)) { + slang_info_log_error(A->log, + "illegal assignment to read-only variable '%s'", + (char *) oper->children[0].a_id); + return NULL; + } + } + + if (oper->children[0].type == SLANG_OPER_IDENTIFIER && + oper->children[1].type == SLANG_OPER_CALL) { + /* Special case of: x = f(a, b) + * Replace with f(a, b, x) (where x == hidden __retVal out param) + * + * XXX this could be even more effective if we could accomodate + * cases such as "v.x = f();" - would help with typical vertex + * transformation. + */ + slang_ir_node *n; + n = _slang_gen_function_call_name(A, + (const char *) oper->children[1].a_id, + &oper->children[1], &oper->children[0]); + return n; + } + else { + slang_ir_node *n, *lhs, *rhs; + lhs = _slang_gen_operation(A, &oper->children[0]); + + if (lhs) { + if (!(lhs->Store->File == PROGRAM_OUTPUT || + lhs->Store->File == PROGRAM_TEMPORARY || + (lhs->Store->File == PROGRAM_VARYING && + A->program->Target == GL_VERTEX_PROGRAM_ARB) || + lhs->Store->File == PROGRAM_UNDEFINED)) { + slang_info_log_error(A->log, + "illegal assignment to read-only l-value"); + return NULL; + } + } + + rhs = _slang_gen_operation(A, &oper->children[1]); + if (lhs && rhs) { + /* convert lhs swizzle into writemask */ + GLuint writemask, newSwizzle; + if (!swizzle_to_writemask(lhs->Store->Swizzle, + &writemask, &newSwizzle)) { + /* Non-simple writemask, need to swizzle right hand side in + * order to put components into the right place. + */ + rhs = _slang_gen_swizzle(rhs, newSwizzle); + } + n = new_node2(IR_MOVE, lhs, rhs); + n->Writemask = writemask; + return n; + } + else { + return NULL; + } + } +} + + +/** + * Generate IR tree for referencing a field in a struct (or basic vector type) + */ +static slang_ir_node * +_slang_gen_field(slang_assemble_ctx * A, slang_operation *oper) +{ + slang_typeinfo ti; + + /* type of struct */ + slang_typeinfo_construct(&ti); + _slang_typeof_operation(A, &oper->children[0], &ti); + + if (_slang_type_is_vector(ti.spec.type)) { + /* the field should be a swizzle */ + const GLuint rows = _slang_type_dim(ti.spec.type); + slang_swizzle swz; + slang_ir_node *n; + GLuint swizzle; + if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) { + slang_info_log_error(A->log, "Bad swizzle"); + } + swizzle = MAKE_SWIZZLE4(swz.swizzle[0], + swz.swizzle[1], + swz.swizzle[2], + swz.swizzle[3]); + + n = _slang_gen_operation(A, &oper->children[0]); + /* create new parent node with swizzle */ + if (n) + n = _slang_gen_swizzle(n, swizzle); + return n; + } + else if ( ti.spec.type == SLANG_SPEC_FLOAT + || ti.spec.type == SLANG_SPEC_INT) { + const GLuint rows = 1; + slang_swizzle swz; + slang_ir_node *n; + GLuint swizzle; + if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) { + slang_info_log_error(A->log, "Bad swizzle"); + } + swizzle = MAKE_SWIZZLE4(swz.swizzle[0], + swz.swizzle[1], + swz.swizzle[2], + swz.swizzle[3]); + n = _slang_gen_operation(A, &oper->children[0]); + /* create new parent node with swizzle */ + n = _slang_gen_swizzle(n, swizzle); + return n; + } + else { + /* the field is a structure member (base.field) */ + /* oper->children[0] is the base */ + /* oper->a_id is the field name */ + slang_ir_node *base, *n; + slang_typeinfo field_ti; + GLint fieldSize, fieldOffset = -1; + /* type of field */ + slang_typeinfo_construct(&field_ti); + _slang_typeof_operation(A, oper, &field_ti); + + fieldSize = _slang_sizeof_type_specifier(&field_ti.spec); + if (fieldSize > 0) + fieldOffset = _slang_field_offset(&ti.spec, oper->a_id); + + if (fieldSize == 0 || fieldOffset < 0) { + slang_info_log_error(A->log, + "\"%s\" is not a member of struct \"%s\"", + (char *) oper->a_id, + (char *) ti.spec._struct->a_name); + return NULL; + } + assert(fieldSize >= 0); + + base = _slang_gen_operation(A, &oper->children[0]); + if (!base) { + /* error msg should have already been logged */ + return NULL; + } + + n = new_node1(IR_FIELD, base); + if (n) { + n->Field = (char *) oper->a_id; + n->FieldOffset = fieldOffset; + assert(n->FieldOffset >= 0); + n->Store = _slang_new_ir_storage(base->Store->File, + base->Store->Index, + fieldSize); + } + return n; + +#if 0 + _mesa_problem(NULL, "glsl structs/fields not supported yet"); + return NULL; +#endif + } +} + + +/** + * Gen code for array indexing. + */ +static slang_ir_node * +_slang_gen_subscript(slang_assemble_ctx * A, slang_operation *oper) +{ + slang_typeinfo array_ti; + + /* get array's type info */ + slang_typeinfo_construct(&array_ti); + _slang_typeof_operation(A, &oper->children[0], &array_ti); + + if (_slang_type_is_vector(array_ti.spec.type)) { + /* indexing a simple vector type: "vec4 v; v[0]=p;" */ + /* translate the index into a swizzle/writemask: "v.x=p" */ + const GLuint max = _slang_type_dim(array_ti.spec.type); + GLint index; + slang_ir_node *n; + + index = (GLint) oper->children[1].literal[0]; + if (oper->children[1].type != SLANG_OPER_LITERAL_INT || + index >= max) { + slang_info_log_error(A->log, "Invalid array index for vector type"); + return NULL; + } + + n = _slang_gen_operation(A, &oper->children[0]); + if (n) { + /* use swizzle to access the element */ + GLuint swizzle = MAKE_SWIZZLE4(SWIZZLE_X + index, + SWIZZLE_NIL, + SWIZZLE_NIL, + SWIZZLE_NIL); + n = _slang_gen_swizzle(n, swizzle); + /*n->Store = _slang_clone_ir_storage_swz(n->Store, */ + n->Writemask = WRITEMASK_X << index; + } + return n; + } + else { + /* conventional array */ + slang_typeinfo elem_ti; + slang_ir_node *elem, *array, *index; + GLint elemSize, arrayLen; + + /* size of array element */ + slang_typeinfo_construct(&elem_ti); + _slang_typeof_operation(A, oper, &elem_ti); + elemSize = _slang_sizeof_type_specifier(&elem_ti.spec); + + if (_slang_type_is_matrix(array_ti.spec.type)) + arrayLen = _slang_type_dim(array_ti.spec.type); + else + arrayLen = array_ti.array_len; + + slang_typeinfo_destruct(&array_ti); + slang_typeinfo_destruct(&elem_ti); + + if (elemSize <= 0) { + /* unknown var or type */ + slang_info_log_error(A->log, "Undefined variable or type"); + return NULL; + } + + array = _slang_gen_operation(A, &oper->children[0]); + index = _slang_gen_operation(A, &oper->children[1]); + if (array && index) { + /* bounds check */ + if (index->Opcode == IR_FLOAT && + ((int) index->Value[0] < 0 || + (int) index->Value[0] >= arrayLen)) { + slang_info_log_error(A->log, + "Array index out of bounds (index=%d size=%d)", + (int) index->Value[0], arrayLen); + _slang_free_ir_tree(array); + _slang_free_ir_tree(index); + return NULL; + } + + elem = new_node2(IR_ELEMENT, array, index); + elem->Store = _slang_new_ir_storage(array->Store->File, + array->Store->Index, + elemSize); + /* XXX try to do some array bounds checking here */ + return elem; + } + else { + _slang_free_ir_tree(array); + _slang_free_ir_tree(index); + return NULL; + } + } +} + + +/** + * Look for expressions such as: gl_ModelviewMatrix * gl_Vertex + * and replace with this: gl_Vertex * gl_ModelviewMatrixTranpose + * Since matrices are stored in column-major order, the second form of + * multiplication is much more efficient (just 4 dot products). + */ +static void +_slang_check_matmul_optimization(slang_assemble_ctx *A, slang_operation *oper) +{ + static const struct { + const char *orig; + const char *tranpose; + } matrices[] = { + {"gl_ModelViewMatrix", "gl_ModelViewMatrixTranspose"}, + {"gl_ProjectionMatrix", "gl_ProjectionMatrixTranspose"}, + {"gl_ModelViewProjectionMatrix", "gl_ModelViewProjectionMatrixTranspose"}, + {"gl_TextureMatrix", "gl_TextureMatrixTranspose"}, + {"gl_NormalMatrix", "__NormalMatrixTranspose"}, + { NULL, NULL } + }; + + assert(oper->type == SLANG_OPER_MULTIPLY); + if (oper->children[0].type == SLANG_OPER_IDENTIFIER) { + GLuint i; + for (i = 0; matrices[i].orig; i++) { + if (oper->children[0].a_id + == slang_atom_pool_atom(A->atoms, matrices[i].orig)) { + /* + _mesa_printf("Replace %s with %s\n", + matrices[i].orig, matrices[i].tranpose); + */ + assert(oper->children[0].type == SLANG_OPER_IDENTIFIER); + oper->children[0].a_id + = slang_atom_pool_atom(A->atoms, matrices[i].tranpose); + /* finally, swap the operands */ + _slang_operation_swap(&oper->children[0], &oper->children[1]); + return; + } + } + } +} + + +/** + * Generate IR tree for a slang_operation (AST node) + */ +static slang_ir_node * +_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) +{ + switch (oper->type) { + case SLANG_OPER_BLOCK_NEW_SCOPE: + { + slang_ir_node *n; + + _slang_push_var_table(A->vartable); + + oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; /* temp change */ + n = _slang_gen_operation(A, oper); + oper->type = SLANG_OPER_BLOCK_NEW_SCOPE; /* restore */ + + _slang_pop_var_table(A->vartable); + + if (n) + n = new_node1(IR_SCOPE, n); + return n; + } + break; + + case SLANG_OPER_BLOCK_NO_NEW_SCOPE: + /* list of operations */ + if (oper->num_children > 0) + { + slang_ir_node *n, *tree = NULL; + GLuint i; + + for (i = 0; i < oper->num_children; i++) { + n = _slang_gen_operation(A, &oper->children[i]); + if (!n) { + _slang_free_ir_tree(tree); + return NULL; /* error must have occured */ + } + tree = tree ? new_seq(tree, n) : n; + } + +#if 00 + if (oper->locals->num_variables > 0) { + int i; + /* + printf("\n****** Deallocate vars in scope!\n"); + */ + for (i = 0; i < oper->locals->num_variables; i++) { + slang_variable *v = oper->locals->variables + i; + if (v->aux) { + slang_ir_storage *store = (slang_ir_storage *) v->aux; + /* + printf(" Deallocate var %s\n", (char*) v->a_name); + */ + assert(store->File == PROGRAM_TEMPORARY); + assert(store->Index >= 0); + _slang_free_temp(A->vartable, store->Index, store->Size); + } + } + } +#endif + return tree; + } + else { + return new_node0(IR_NOP); + } + + case SLANG_OPER_EXPRESSION: + return _slang_gen_operation(A, &oper->children[0]); + + case SLANG_OPER_FOR: + return _slang_gen_for(A, oper); + case SLANG_OPER_DO: + return _slang_gen_do(A, oper); + case SLANG_OPER_WHILE: + return _slang_gen_while(A, oper); + case SLANG_OPER_BREAK: + if (!A->CurLoop) { + slang_info_log_error(A->log, "'break' not in loop"); + return NULL; + } + return new_break(A->CurLoop); + case SLANG_OPER_CONTINUE: + if (!A->CurLoop) { + slang_info_log_error(A->log, "'continue' not in loop"); + return NULL; + } + return _slang_gen_continue(A, oper); + case SLANG_OPER_DISCARD: + return new_node0(IR_KILL); + + case SLANG_OPER_EQUAL: + return new_node2(IR_EQUAL, + _slang_gen_operation(A, &oper->children[0]), + _slang_gen_operation(A, &oper->children[1])); + case SLANG_OPER_NOTEQUAL: + return new_node2(IR_NOTEQUAL, + _slang_gen_operation(A, &oper->children[0]), + _slang_gen_operation(A, &oper->children[1])); + case SLANG_OPER_GREATER: + return new_node2(IR_SGT, + _slang_gen_operation(A, &oper->children[0]), + _slang_gen_operation(A, &oper->children[1])); + case SLANG_OPER_LESS: + return new_node2(IR_SLT, + _slang_gen_operation(A, &oper->children[0]), + _slang_gen_operation(A, &oper->children[1])); + case SLANG_OPER_GREATEREQUAL: + return new_node2(IR_SGE, + _slang_gen_operation(A, &oper->children[0]), + _slang_gen_operation(A, &oper->children[1])); + case SLANG_OPER_LESSEQUAL: + return new_node2(IR_SLE, + _slang_gen_operation(A, &oper->children[0]), + _slang_gen_operation(A, &oper->children[1])); + case SLANG_OPER_ADD: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_function_call_name(A, "+", oper, NULL); + return n; + } + case SLANG_OPER_SUBTRACT: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_function_call_name(A, "-", oper, NULL); + return n; + } + case SLANG_OPER_MULTIPLY: + { + slang_ir_node *n; + assert(oper->num_children == 2); + _slang_check_matmul_optimization(A, oper); + n = _slang_gen_function_call_name(A, "*", oper, NULL); + return n; + } + case SLANG_OPER_DIVIDE: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_function_call_name(A, "/", oper, NULL); + return n; + } + case SLANG_OPER_MINUS: + { + slang_ir_node *n; + assert(oper->num_children == 1); + n = _slang_gen_function_call_name(A, "-", oper, NULL); + return n; + } + case SLANG_OPER_PLUS: + /* +expr --> do nothing */ + return _slang_gen_operation(A, &oper->children[0]); + case SLANG_OPER_VARIABLE_DECL: + return _slang_gen_declaration(A, oper); + case SLANG_OPER_ASSIGN: + return _slang_gen_assignment(A, oper); + case SLANG_OPER_ADDASSIGN: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_function_call_name(A, "+=", oper, &oper->children[0]); + return n; + } + case SLANG_OPER_SUBASSIGN: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_function_call_name(A, "-=", oper, &oper->children[0]); + return n; + } + break; + case SLANG_OPER_MULASSIGN: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_function_call_name(A, "*=", oper, &oper->children[0]); + return n; + } + case SLANG_OPER_DIVASSIGN: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_function_call_name(A, "/=", oper, &oper->children[0]); + return n; + } + case SLANG_OPER_LOGICALAND: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_logical_and(A, oper); + return n; + } + case SLANG_OPER_LOGICALOR: + { + slang_ir_node *n; + assert(oper->num_children == 2); + n = _slang_gen_logical_or(A, oper); + return n; + } + case SLANG_OPER_LOGICALXOR: + return _slang_gen_xor(A, oper); + case SLANG_OPER_NOT: + return _slang_gen_not(A, oper); + case SLANG_OPER_SELECT: /* b ? x : y */ + { + slang_ir_node *n; + assert(oper->num_children == 3); + n = _slang_gen_select(A, oper); + return n; + } + + case SLANG_OPER_ASM: + return _slang_gen_asm(A, oper, NULL); + case SLANG_OPER_CALL: + return _slang_gen_function_call_name(A, (const char *) oper->a_id, + oper, NULL); + case SLANG_OPER_RETURN: + return _slang_gen_return(A, oper); + case SLANG_OPER_LABEL: + return new_label(oper->label); + case SLANG_OPER_IDENTIFIER: + return _slang_gen_variable(A, oper); + case SLANG_OPER_IF: + return _slang_gen_if(A, oper); + case SLANG_OPER_FIELD: + return _slang_gen_field(A, oper); + case SLANG_OPER_SUBSCRIPT: + return _slang_gen_subscript(A, oper); + case SLANG_OPER_LITERAL_FLOAT: + /* fall-through */ + case SLANG_OPER_LITERAL_INT: + /* fall-through */ + case SLANG_OPER_LITERAL_BOOL: + return new_float_literal(oper->literal, oper->literal_size); + + case SLANG_OPER_POSTINCREMENT: /* var++ */ + { + slang_ir_node *n; + assert(oper->num_children == 1); + n = _slang_gen_function_call_name(A, "__postIncr", oper, NULL); + return n; + } + case SLANG_OPER_POSTDECREMENT: /* var-- */ + { + slang_ir_node *n; + assert(oper->num_children == 1); + n = _slang_gen_function_call_name(A, "__postDecr", oper, NULL); + return n; + } + case SLANG_OPER_PREINCREMENT: /* ++var */ + { + slang_ir_node *n; + assert(oper->num_children == 1); + n = _slang_gen_function_call_name(A, "++", oper, NULL); + return n; + } + case SLANG_OPER_PREDECREMENT: /* --var */ + { + slang_ir_node *n; + assert(oper->num_children == 1); + n = _slang_gen_function_call_name(A, "--", oper, NULL); + return n; + } + + case SLANG_OPER_INLINED_CALL: + case SLANG_OPER_SEQUENCE: + { + slang_ir_node *tree = NULL; + GLuint i; + for (i = 0; i < oper->num_children; i++) { + slang_ir_node *n = _slang_gen_operation(A, &oper->children[i]); + tree = tree ? new_seq(tree, n) : n; + } + if (oper->type == SLANG_OPER_INLINED_CALL) { + tree = new_inlined_function_call(tree, oper->label); + } + return tree; + } + + case SLANG_OPER_NONE: + case SLANG_OPER_VOID: + /* returning NULL here would generate an error */ + return new_node0(IR_NOP); + + default: + _mesa_problem(NULL, "bad node type %d in _slang_gen_operation", + oper->type); + return new_node0(IR_NOP); + } + + return NULL; +} + + + +/** + * Called by compiler when a global variable has been parsed/compiled. + * Here we examine the variable's type to determine what kind of register + * storage will be used. + * + * A uniform such as "gl_Position" will become the register specification + * (PROGRAM_OUTPUT, VERT_RESULT_HPOS). Or, uniform "gl_FogFragCoord" + * will be (PROGRAM_INPUT, FRAG_ATTRIB_FOGC). + * + * Samplers are interesting. For "uniform sampler2D tex;" we'll specify + * (PROGRAM_SAMPLER, index) where index is resolved at link-time to an + * actual texture unit (as specified by the user calling glUniform1i()). + */ +GLboolean +_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, + slang_unit_type type) +{ + struct gl_program *prog = A->program; + const char *varName = (char *) var->a_name; + GLboolean success = GL_TRUE; + slang_ir_storage *store = NULL; + int dbg = 0; + const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier); + const GLint texIndex = sampler_to_texture_index(var->type.specifier.type); + + if (texIndex != -1) { + /* Texture sampler: + * store->File = PROGRAM_SAMPLER + * store->Index = sampler uniform location + * store->Size = texture type index (1D, 2D, 3D, cube, etc) + */ + GLint samplerUniform + = _mesa_add_sampler(prog->Parameters, varName, datatype); + store = _slang_new_ir_storage(PROGRAM_SAMPLER, samplerUniform, texIndex); + if (dbg) printf("SAMPLER "); + } + else if (var->type.qualifier == SLANG_QUAL_UNIFORM) { + /* Uniform variable */ + const GLint size = _slang_sizeof_type_specifier(&var->type.specifier) + * MAX2(var->array_len, 1); + if (prog) { + /* user-defined uniform */ + if (datatype == GL_NONE) { + if (var->type.specifier.type == SLANG_SPEC_STRUCT) { + _mesa_problem(NULL, "user-declared uniform structs not supported yet"); + /* XXX what we need to do is unroll the struct into its + * basic types, creating a uniform variable for each. + * For example: + * struct foo { + * vec3 a; + * vec4 b; + * }; + * uniform foo f; + * + * Should produce uniforms: + * "f.a" (GL_FLOAT_VEC3) + * "f.b" (GL_FLOAT_VEC4) + */ + } + else { + slang_info_log_error(A->log, + "invalid datatype for uniform variable %s", + (char *) var->a_name); + } + return GL_FALSE; + } + else { + GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName, + size, datatype); + store = _slang_new_ir_storage(PROGRAM_UNIFORM, uniformLoc, size); + } + } + else { + /* pre-defined uniform, like gl_ModelviewMatrix */ + /* We know it's a uniform, but don't allocate storage unless + * it's really used. + */ + store = _slang_new_ir_storage(PROGRAM_STATE_VAR, -1, size); + } + if (dbg) printf("UNIFORM (sz %d) ", size); + } + else if (var->type.qualifier == SLANG_QUAL_VARYING) { + const GLint size = 4; /* XXX fix */ + if (prog) { + /* user-defined varying */ + GLint varyingLoc = _mesa_add_varying(prog->Varying, varName, size); + store = _slang_new_ir_storage(PROGRAM_VARYING, varyingLoc, size); + } + else { + /* pre-defined varying, like gl_Color or gl_TexCoord */ + if (type == SLANG_UNIT_FRAGMENT_BUILTIN) { + GLuint swizzle; + GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB, + &swizzle); + assert(index >= 0); + store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); + store->Swizzle = swizzle; + assert(index < FRAG_ATTRIB_MAX); + } + else { + GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB); + assert(index >= 0); + assert(type == SLANG_UNIT_VERTEX_BUILTIN); + store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); + assert(index < VERT_RESULT_MAX); + } + if (dbg) printf("V/F "); + } + if (dbg) printf("VARYING "); + } + else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) { + if (prog) { + /* user-defined vertex attribute */ + const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); + const GLint attr = -1; /* unknown */ + GLint index = _mesa_add_attribute(prog->Attributes, varName, + size, attr); + assert(index >= 0); + store = _slang_new_ir_storage(PROGRAM_INPUT, + VERT_ATTRIB_GENERIC0 + index, size); + } + else { + /* pre-defined vertex attrib */ + GLuint swizzle; + GLint index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB, + &swizzle); + GLint size = 4; /* XXX? */ + assert(index >= 0); + store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); + store->Swizzle = swizzle; + } + if (dbg) printf("ATTRIB "); + } + else if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT) { + GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */ + GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB, + &swizzle); + GLint size = 4; /* XXX? */ + store = _slang_new_ir_storage(PROGRAM_INPUT, index, size); + store->Swizzle = swizzle; + if (dbg) printf("INPUT "); + } + else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) { + if (type == SLANG_UNIT_VERTEX_BUILTIN) { + GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB); + GLint size = 4; /* XXX? */ + store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); + } + else { + GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB); + GLint size = 4; /* XXX? */ + assert(type == SLANG_UNIT_FRAGMENT_BUILTIN); + store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size); + } + if (dbg) printf("OUTPUT "); + } + else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) { + /* pre-defined global constant, like gl_MaxLights */ + const GLint size = _slang_sizeof_type_specifier(&var->type.specifier); + store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size); + if (dbg) printf("CONST "); + } + else { + /* ordinary variable (may be const) */ + slang_ir_node *n; + + /* IR node to declare the variable */ + n = _slang_gen_var_decl(A, var); + + /* IR code for the var's initializer, if present */ + if (var->initializer) { + slang_ir_node *lhs, *rhs, *init; + + /* Generate IR_MOVE instruction to initialize the variable */ + lhs = new_node0(IR_VAR); + lhs->Var = var; + lhs->Store = n->Store; + + /* constant folding, etc */ + _slang_simplify(var->initializer, &A->space, A->atoms); + + rhs = _slang_gen_operation(A, var->initializer); + assert(rhs); + init = new_node2(IR_MOVE, lhs, rhs); + n = new_seq(n, init); + } + + success = _slang_emit_code(n, A->vartable, A->program, GL_FALSE, A->log); + + _slang_free_ir_tree(n); + } + + if (dbg) printf("GLOBAL VAR %s idx %d\n", (char*) var->a_name, + store ? store->Index : -2); + + if (store) + var->aux = store; /* save var's storage info */ + + return success; +} + + +/** + * Produce an IR tree from a function AST (fun->body). + * Then call the code emitter to convert the IR tree into gl_program + * instructions. + */ +GLboolean +_slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) +{ + slang_ir_node *n; + GLboolean success = GL_TRUE; + + if (_mesa_strcmp((char *) fun->header.a_name, "main") != 0) { + /* we only really generate code for main, all other functions get + * inlined. + */ +#if 0 + /* do some basic error checking though */ + if (fun->header.type.specifier.type != SLANG_SPEC_VOID) { + /* check that non-void functions actually return something */ + slang_operation *op + = _slang_find_node_type(fun->body, SLANG_OPER_RETURN); + if (!op) { + slang_info_log_error(A->log, + "function \"%s\" has no return statement", + (char *) fun->header.a_name); + printf( + "function \"%s\" has no return statement\n", + (char *) fun->header.a_name); + return GL_FALSE; + } + } +#endif + return GL_TRUE; /* not an error */ + } + +#if 0 + printf("\n*********** codegen_function %s\n", (char *) fun->header.a_name); + slang_print_function(fun, 1); +#endif + + /* should have been allocated earlier: */ + assert(A->program->Parameters ); + assert(A->program->Varying); + assert(A->vartable); + A->CurLoop = NULL; + A->CurFunction = fun; + + /* fold constant expressions, etc. */ + _slang_simplify(fun->body, &A->space, A->atoms); + +#if 0 + printf("\n*********** simplified %s\n", (char *) fun->header.a_name); + slang_print_function(fun, 1); +#endif + + /* Create an end-of-function label */ + A->curFuncEndLabel = _slang_label_new("__endOfFunc__main"); + + /* push new vartable scope */ + _slang_push_var_table(A->vartable); + + /* Generate IR tree for the function body code */ + n = _slang_gen_operation(A, fun->body); + if (n) + n = new_node1(IR_SCOPE, n); + + /* pop vartable, restore previous */ + _slang_pop_var_table(A->vartable); + + if (!n) { + /* XXX record error */ + return GL_FALSE; + } + + /* append an end-of-function-label to IR tree */ + n = new_seq(n, new_label(A->curFuncEndLabel)); + + /*_slang_label_delete(A->curFuncEndLabel);*/ + A->curFuncEndLabel = NULL; + +#if 0 + printf("************* New AST for %s *****\n", (char*)fun->header.a_name); + slang_print_function(fun, 1); +#endif +#if 0 + printf("************* IR for %s *******\n", (char*)fun->header.a_name); + _slang_print_ir_tree(n, 0); +#endif +#if 0 + printf("************* End codegen function ************\n\n"); +#endif + + /* Emit program instructions */ + success = _slang_emit_code(n, A->vartable, A->program, GL_TRUE, A->log); + _slang_free_ir_tree(n); + + /* free codegen context */ + /* + _mesa_free(A->codegen); + */ + + return success; +} + diff --git a/dist/Mesa/src/mesa/shader/slang/slang_codegen.h b/dist/Mesa/src/mesa/shader/slang/slang_codegen.h new file mode 100644 index 000000000..821d39616 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_codegen.h @@ -0,0 +1,45 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef SLANG_CODEGEN_H +#define SLANG_CODEGEN_H + + +#include "imports.h" +#include "slang_compile.h" + + +extern GLuint +_slang_sizeof_type_specifier(const slang_type_specifier *spec); + +extern GLboolean +_slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun); + +extern GLboolean +_slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var, + slang_unit_type type); + + +#endif /* SLANG_CODEGEN_H */ diff --git a/dist/Mesa/src/mesa/shader/slang/slang_emit.c b/dist/Mesa/src/mesa/shader/slang/slang_emit.c new file mode 100644 index 000000000..fe13f2865 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_emit.c @@ -0,0 +1,1849 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_emit.c + * Emit program instructions (PI code) from IR trees. + * \author Brian Paul + */ + +/*** + *** NOTES + *** + *** To emit GPU instructions, we basically just do an in-order traversal + *** of the IR tree. + ***/ + + +#include "main/imports.h" +#include "main/context.h" +#include "main/macros.h" +#include "shader/program.h" +#include "shader/prog_instruction.h" +#include "shader/prog_parameter.h" +#include "shader/prog_print.h" +#include "slang_builtin.h" +#include "slang_emit.h" +#include "slang_mem.h" + + +#define PEEPHOLE_OPTIMIZATIONS 1 +#define ANNOTATE 0 + + +typedef struct +{ + slang_info_log *log; + slang_var_table *vt; + struct gl_program *prog; + struct gl_program **Subroutines; + GLuint NumSubroutines; + + /* code-gen options */ + GLboolean EmitHighLevelInstructions; + GLboolean EmitCondCodes; + GLboolean EmitComments; + GLboolean EmitBeginEndSub; /* XXX TEMPORARY */ +} slang_emit_info; + + + +static struct gl_program * +new_subroutine(slang_emit_info *emitInfo, GLuint *id) +{ + GET_CURRENT_CONTEXT(ctx); + const GLuint n = emitInfo->NumSubroutines; + + emitInfo->Subroutines = (struct gl_program **) + _mesa_realloc(emitInfo->Subroutines, + n * sizeof(struct gl_program), + (n + 1) * sizeof(struct gl_program)); + emitInfo->Subroutines[n] = _mesa_new_program(ctx, emitInfo->prog->Target, 0); + emitInfo->Subroutines[n]->Parameters = emitInfo->prog->Parameters; + emitInfo->NumSubroutines++; + *id = n; + return emitInfo->Subroutines[n]; +} + + +/** + * Convert a writemask to a swizzle. Used for testing cond codes because + * we only want to test the cond code component(s) that was set by the + * previous instruction. + */ +static GLuint +writemask_to_swizzle(GLuint writemask) +{ + if (writemask == WRITEMASK_X) + return SWIZZLE_XXXX; + if (writemask == WRITEMASK_Y) + return SWIZZLE_YYYY; + if (writemask == WRITEMASK_Z) + return SWIZZLE_ZZZZ; + if (writemask == WRITEMASK_W) + return SWIZZLE_WWWW; + return SWIZZLE_XYZW; /* shouldn't be hit */ +} + + +/** + * Swizzle a swizzle. That is, return swz2(swz1) + */ +static GLuint +swizzle_swizzle(GLuint swz1, GLuint swz2) +{ + GLuint i, swz, s[4]; + for (i = 0; i < 4; i++) { + GLuint c = GET_SWZ(swz2, i); + s[i] = GET_SWZ(swz1, c); + } + swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]); + return swz; +} + + +slang_ir_storage * +_slang_new_ir_storage(enum register_file file, GLint index, GLint size) +{ + slang_ir_storage *st; + st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage)); + if (st) { + st->File = file; + st->Index = index; + st->Size = size; + st->Swizzle = SWIZZLE_NOOP; + } + return st; +} + + +/** + * Allocate temporary storage for an intermediate result (such as for + * a multiply or add, etc. + */ +static GLboolean +alloc_temp_storage(slang_emit_info *emitInfo, slang_ir_node *n, GLint size) +{ + assert(!n->Var); + assert(!n->Store); + assert(size > 0); + n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size); + if (!_slang_alloc_temp(emitInfo->vt, n->Store)) { + slang_info_log_error(emitInfo->log, + "Ran out of registers, too many temporaries"); + _slang_free(n->Store); + n->Store = NULL; + return GL_FALSE; + } + return GL_TRUE; +} + + +/** + * Free temporary storage, if n->Store is, in fact, temp storage. + * Otherwise, no-op. + */ +static void +free_temp_storage(slang_var_table *vt, slang_ir_node *n) +{ + if (n->Store->File == PROGRAM_TEMPORARY && + n->Store->Index >= 0 && + n->Opcode != IR_SWIZZLE) { + if (_slang_is_temp(vt, n->Store)) { + _slang_free_temp(vt, n->Store); + n->Store->Index = -1; + n->Store->Size = -1; + /*_mesa_free(n->Store);*/ /* XXX leak */ + n->Store = NULL; + } + } +} + + +/** + * Convert IR storage to an instruction dst register. + */ +static void +storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st, + GLuint writemask) +{ + assert(st->Index >= 0); + dst->File = st->File; + dst->Index = st->Index; + assert(st->File != PROGRAM_UNDEFINED); + assert(st->Size >= 1); + assert(st->Size <= 4); + if (st->Size == 1) { + GLuint comp = GET_SWZ(st->Swizzle, 0); + assert(comp < 4); + dst->WriteMask = WRITEMASK_X << comp; + } + else { + dst->WriteMask = writemask; + } +} + + +/** + * Convert IR storage to an instruction src register. + */ +static void +storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st) +{ + static const GLuint defaultSwizzle[4] = { + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X), + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), + MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W) + }; + assert(st->File >= 0); + assert(st->File < PROGRAM_UNDEFINED); + assert(st->Size >= 1); + assert(st->Size <= 4); + src->File = st->File; + src->Index = st->Index; + if (st->Swizzle != SWIZZLE_NOOP) + src->Swizzle = st->Swizzle; + else + src->Swizzle = defaultSwizzle[st->Size - 1]; /*XXX really need this?*/ + + assert(GET_SWZ(src->Swizzle, 0) <= 3); + assert(GET_SWZ(src->Swizzle, 1) <= 3); + assert(GET_SWZ(src->Swizzle, 2) <= 3); + assert(GET_SWZ(src->Swizzle, 3) <= 3); +} + + +/* + * Setup an instrucion src register to point to a scalar constant. + */ +static void +constant_to_src_reg(struct prog_src_register *src, GLfloat val, + slang_emit_info *emitInfo) +{ + GLuint zeroSwizzle; + GLint zeroReg; + GLfloat value[4]; + + value[0] = val; + zeroReg = _mesa_add_unnamed_constant(emitInfo->prog->Parameters, + value, 1, &zeroSwizzle); + assert(zeroReg >= 0); + + src->File = PROGRAM_CONSTANT; + src->Index = zeroReg; + src->Swizzle = zeroSwizzle; +} + + +/** + * Add new instruction at end of given program. + * \param prog the program to append instruction onto + * \param opcode opcode for the new instruction + * \return pointer to the new instruction + */ +static struct prog_instruction * +new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode) +{ + struct gl_program *prog = emitInfo->prog; + struct prog_instruction *inst; + +#if 0 + /* print prev inst */ + if (prog->NumInstructions > 0) { + _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1); + } +#endif + prog->Instructions = _mesa_realloc_instructions(prog->Instructions, + prog->NumInstructions, + prog->NumInstructions + 1); + inst = prog->Instructions + prog->NumInstructions; + prog->NumInstructions++; + _mesa_init_instructions(inst, 1); + inst->Opcode = opcode; + inst->BranchTarget = -1; /* invalid */ + /* + printf("New inst %d: %p %s\n", prog->NumInstructions-1,(void*)inst, + _mesa_opcode_string(inst->Opcode)); + */ + return inst; +} + + +/** + * Return pointer to last instruction in program. + */ +static struct prog_instruction * +prev_instruction(slang_emit_info *emitInfo) +{ + struct gl_program *prog = emitInfo->prog; + if (prog->NumInstructions == 0) + return NULL; + else + return prog->Instructions + prog->NumInstructions - 1; +} + + +static struct prog_instruction * +emit(slang_emit_info *emitInfo, slang_ir_node *n); + + +/** + * Return an annotation string for given node's storage. + */ +static char * +storage_annotation(const slang_ir_node *n, const struct gl_program *prog) +{ +#if ANNOTATE + const slang_ir_storage *st = n->Store; + static char s[100] = ""; + + if (!st) + return _mesa_strdup(""); + + switch (st->File) { + case PROGRAM_CONSTANT: + if (st->Index >= 0) { + const GLfloat *val = prog->Parameters->ParameterValues[st->Index]; + if (st->Swizzle == SWIZZLE_NOOP) + sprintf(s, "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]); + else { + sprintf(s, "%g", val[GET_SWZ(st->Swizzle, 0)]); + } + } + break; + case PROGRAM_TEMPORARY: + if (n->Var) + sprintf(s, "%s", (char *) n->Var->a_name); + else + sprintf(s, "t[%d]", st->Index); + break; + case PROGRAM_STATE_VAR: + case PROGRAM_UNIFORM: + sprintf(s, "%s", prog->Parameters->Parameters[st->Index].Name); + break; + case PROGRAM_VARYING: + sprintf(s, "%s", prog->Varying->Parameters[st->Index].Name); + break; + case PROGRAM_INPUT: + sprintf(s, "input[%d]", st->Index); + break; + case PROGRAM_OUTPUT: + sprintf(s, "output[%d]", st->Index); + break; + default: + s[0] = 0; + } + return _mesa_strdup(s); +#else + return NULL; +#endif +} + + +/** + * Return an annotation string for an instruction. + */ +static char * +instruction_annotation(gl_inst_opcode opcode, char *dstAnnot, + char *srcAnnot0, char *srcAnnot1, char *srcAnnot2) +{ +#if ANNOTATE + const char *operator; + char *s; + int len = 50; + + if (dstAnnot) + len += strlen(dstAnnot); + else + dstAnnot = _mesa_strdup(""); + + if (srcAnnot0) + len += strlen(srcAnnot0); + else + srcAnnot0 = _mesa_strdup(""); + + if (srcAnnot1) + len += strlen(srcAnnot1); + else + srcAnnot1 = _mesa_strdup(""); + + if (srcAnnot2) + len += strlen(srcAnnot2); + else + srcAnnot2 = _mesa_strdup(""); + + switch (opcode) { + case OPCODE_ADD: + operator = "+"; + break; + case OPCODE_SUB: + operator = "-"; + break; + case OPCODE_MUL: + operator = "*"; + break; + case OPCODE_DP3: + operator = "DP3"; + break; + case OPCODE_DP4: + operator = "DP4"; + break; + case OPCODE_XPD: + operator = "XPD"; + break; + case OPCODE_RSQ: + operator = "RSQ"; + break; + case OPCODE_SGT: + operator = ">"; + break; + default: + operator = ","; + } + + s = (char *) malloc(len); + sprintf(s, "%s = %s %s %s %s", dstAnnot, + srcAnnot0, operator, srcAnnot1, srcAnnot2); + assert(_mesa_strlen(s) < len); + + free(dstAnnot); + free(srcAnnot0); + free(srcAnnot1); + free(srcAnnot2); + + return s; +#else + return NULL; +#endif +} + + +/** + * Emit an instruction that's just a comment. + */ +static struct prog_instruction * +emit_comment(slang_emit_info *emitInfo, const char *s) +{ + struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP); + if (inst) { + inst->Comment = _mesa_strdup(s); + } + return inst; +} + + +/** + * Generate code for a simple arithmetic instruction. + * Either 1, 2 or 3 operands. + */ +static struct prog_instruction * +emit_arith(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + const slang_ir_info *info = _slang_ir_info(n->Opcode); + char *srcAnnot[3], *dstAnnot; + GLuint i; + + assert(info); + assert(info->InstOpcode != OPCODE_NOP); + + srcAnnot[0] = srcAnnot[1] = srcAnnot[2] = dstAnnot = NULL; + +#if PEEPHOLE_OPTIMIZATIONS + /* Look for MAD opportunity */ + if (info->NumParams == 2 && + n->Opcode == IR_ADD && n->Children[0]->Opcode == IR_MUL) { + /* found pattern IR_ADD(IR_MUL(A, B), C) */ + emit(emitInfo, n->Children[0]->Children[0]); /* A */ + emit(emitInfo, n->Children[0]->Children[1]); /* B */ + emit(emitInfo, n->Children[1]); /* C */ + /* generate MAD instruction */ + inst = new_instruction(emitInfo, OPCODE_MAD); + /* operands: A, B, C: */ + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Children[0]->Store); + storage_to_src_reg(&inst->SrcReg[1], n->Children[0]->Children[1]->Store); + storage_to_src_reg(&inst->SrcReg[2], n->Children[1]->Store); + free_temp_storage(emitInfo->vt, n->Children[0]->Children[0]); + free_temp_storage(emitInfo->vt, n->Children[0]->Children[1]); + free_temp_storage(emitInfo->vt, n->Children[1]); + } + else if (info->NumParams == 2 && + n->Opcode == IR_ADD && n->Children[1]->Opcode == IR_MUL) { + /* found pattern IR_ADD(A, IR_MUL(B, C)) */ + emit(emitInfo, n->Children[0]); /* A */ + emit(emitInfo, n->Children[1]->Children[0]); /* B */ + emit(emitInfo, n->Children[1]->Children[1]); /* C */ + /* generate MAD instruction */ + inst = new_instruction(emitInfo, OPCODE_MAD); + /* operands: B, C, A */ + storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Children[0]->Store); + storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Children[1]->Store); + storage_to_src_reg(&inst->SrcReg[2], n->Children[0]->Store); + free_temp_storage(emitInfo->vt, n->Children[1]->Children[0]); + free_temp_storage(emitInfo->vt, n->Children[1]->Children[1]); + free_temp_storage(emitInfo->vt, n->Children[0]); + } + else +#endif + { + /* normal case */ + + /* gen code for children */ + for (i = 0; i < info->NumParams; i++) { + emit(emitInfo, n->Children[i]); + if (!n->Children[i] || !n->Children[i]->Store) { + /* error recovery */ + return NULL; + } + } + + /* gen this instruction and src registers */ + inst = new_instruction(emitInfo, info->InstOpcode); + for (i = 0; i < info->NumParams; i++) + storage_to_src_reg(&inst->SrcReg[i], n->Children[i]->Store); + + /* annotation */ + for (i = 0; i < info->NumParams; i++) + srcAnnot[i] = storage_annotation(n->Children[i], emitInfo->prog); + + /* free temps */ + for (i = 0; i < info->NumParams; i++) + free_temp_storage(emitInfo->vt, n->Children[i]); + } + + /* result storage */ + if (!n->Store) { + /* XXX this size isn't correct, it depends on the operands */ + if (!alloc_temp_storage(emitInfo, n, info->ResultSize)) + return NULL; + } + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + + dstAnnot = storage_annotation(n, emitInfo->prog); + + inst->Comment = instruction_annotation(inst->Opcode, dstAnnot, srcAnnot[0], + srcAnnot[1], srcAnnot[2]); + + /*_mesa_print_instruction(inst);*/ + return inst; +} + + +/** + * Emit code for == and != operators. These could normally be handled + * by emit_arith() except we need to be able to handle structure comparisons. + */ +static struct prog_instruction * +emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + GLint size; + + assert(n->Opcode == IR_EQUAL || n->Opcode == IR_NOTEQUAL); + + /* gen code for children */ + emit(emitInfo, n->Children[0]); + emit(emitInfo, n->Children[1]); + + assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size); + size = n->Children[0]->Store->Size; + + if (size == 1) { + gl_inst_opcode opcode; + + if (!n->Store) { + if (!alloc_temp_storage(emitInfo, n, 1)) /* 1 bool */ + return NULL; + } + + opcode = n->Opcode == IR_EQUAL ? OPCODE_SEQ : OPCODE_SNE; + inst = new_instruction(emitInfo, opcode); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + } + else if (size <= 4) { + GLuint swizzle; + gl_inst_opcode dotOp; + + assert(!n->Store); + if (!n->Store) { + if (!alloc_temp_storage(emitInfo, n, size)) /* 'size' bools */ + return NULL; + } + + if (size == 4) { + dotOp = OPCODE_DP4; + swizzle = SWIZZLE_XYZW; + } + else if (size == 3) { + dotOp = OPCODE_DP3; + swizzle = SWIZZLE_XYZW; + } + else { + assert(size == 2); + dotOp = OPCODE_DP3; + swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y); + } + + /* Compute equality, inequality (tmp1 = (A ?= B)) */ + inst = new_instruction(emitInfo, OPCODE_SNE); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + inst->Comment = _mesa_strdup("Compare values"); + + /* Compute tmp2 = DOT(tmp1, tmp1) (reduction) */ + inst = new_instruction(emitInfo, dotOp); + storage_to_src_reg(&inst->SrcReg[0], n->Store); + storage_to_src_reg(&inst->SrcReg[1], n->Store); + inst->SrcReg[0].Swizzle = inst->SrcReg[1].Swizzle = swizzle; /*override*/ + free_temp_storage(emitInfo->vt, n); /* free tmp1 */ + if (!alloc_temp_storage(emitInfo, n, 1)) /* alloc tmp2 */ + return NULL; + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + inst->Comment = _mesa_strdup("Reduce vec to bool"); + + if (n->Opcode == IR_EQUAL) { + /* compute tmp2.x = !tmp2.x via tmp2.x = (tmp2.x == 0) */ + inst = new_instruction(emitInfo, OPCODE_SEQ); + storage_to_src_reg(&inst->SrcReg[0], n->Store); + constant_to_src_reg(&inst->SrcReg[1], 0.0, emitInfo); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + inst->Comment = _mesa_strdup("Invert true/false"); + } + } + else { + /* size > 4, struct compare */ +#if 0 + GLint i, num = (n->Children[0]->Store->Size + 3) / 4; + /*printf("BEGIN COMPARE size %d\n", num);*/ + for (i = 0; i < num; i++) { + inst = new_instruction(emitInfo, opcode); + inst->SrcReg[0].File = n->Children[0]->Store->File; + inst->SrcReg[0].Index = n->Children[0]->Store->Index + i; + inst->SrcReg[1].File = n->Children[1]->Store->File; + inst->SrcReg[1].Index = n->Children[1]->Store->Index + i; + inst->DstReg.File = n->Store->File; + inst->DstReg.Index = n->Store->Index; + + inst->CondUpdate = 1; /* update cond code */ + if (i > 0) { + inst->DstReg.CondMask = COND_NE; /* update if !=0 */ + } + /*_mesa_print_instruction(inst);*/ + } + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); +#endif + _mesa_problem(NULL, "struct comparison not implemented yet"); + inst = NULL; + } + + /* free temps */ + free_temp_storage(emitInfo->vt, n->Children[0]); + free_temp_storage(emitInfo->vt, n->Children[1]); + + return inst; +} + + + +/** + * Generate code for an IR_CLAMP instruction. + */ +static struct prog_instruction * +emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + + assert(n->Opcode == IR_CLAMP); + /* ch[0] = value + * ch[1] = min limit + * ch[2] = max limit + */ + + inst = emit(emitInfo, n->Children[0]); + + /* If lower limit == 0.0 and upper limit == 1.0, + * set prev instruction's SaturateMode field to SATURATE_ZERO_ONE. + * Else, + * emit OPCODE_MIN, OPCODE_MAX sequence. + */ +#if 0 + /* XXX this isn't quite finished yet */ + if (n->Children[1]->Opcode == IR_FLOAT && + n->Children[1]->Value[0] == 0.0 && + n->Children[1]->Value[1] == 0.0 && + n->Children[1]->Value[2] == 0.0 && + n->Children[1]->Value[3] == 0.0 && + n->Children[2]->Opcode == IR_FLOAT && + n->Children[2]->Value[0] == 1.0 && + n->Children[2]->Value[1] == 1.0 && + n->Children[2]->Value[2] == 1.0 && + n->Children[2]->Value[3] == 1.0) { + if (!inst) { + inst = prev_instruction(prog); + } + if (inst && inst->Opcode != OPCODE_NOP) { + /* and prev instruction's DstReg matches n->Children[0]->Store */ + inst->SaturateMode = SATURATE_ZERO_ONE; + n->Store = n->Children[0]->Store; + return inst; + } + } +#endif + + if (!n->Store) + if (!alloc_temp_storage(emitInfo, n, n->Children[0]->Store->Size)) + return NULL; + + emit(emitInfo, n->Children[1]); + emit(emitInfo, n->Children[2]); + + /* tmp = max(ch[0], ch[1]) */ + inst = new_instruction(emitInfo, OPCODE_MAX); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store); + + /* tmp = min(tmp, ch[2]) */ + inst = new_instruction(emitInfo, OPCODE_MIN); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Store); + storage_to_src_reg(&inst->SrcReg[1], n->Children[2]->Store); + + return inst; +} + + +static struct prog_instruction * +emit_negation(slang_emit_info *emitInfo, slang_ir_node *n) +{ + /* Implement as MOV dst, -src; */ + /* XXX we could look at the previous instruction and in some circumstances + * modify it to accomplish the negation. + */ + struct prog_instruction *inst; + + emit(emitInfo, n->Children[0]); + + if (!n->Store) + if (!alloc_temp_storage(emitInfo, n, n->Children[0]->Store->Size)) + return NULL; + + inst = new_instruction(emitInfo, OPCODE_MOV); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + inst->SrcReg[0].NegateBase = NEGATE_XYZW; + return inst; +} + + +static struct prog_instruction * +emit_label(slang_emit_info *emitInfo, const slang_ir_node *n) +{ + assert(n->Label); +#if 0 + /* XXX this fails in loop tail code - investigate someday */ + assert(_slang_label_get_location(n->Label) < 0); + _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions, + emitInfo->prog); +#else + if (_slang_label_get_location(n->Label) < 0) + _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions, + emitInfo->prog); +#endif + return NULL; +} + + +/** + * Emit code for a function call. + * Note that for each time a function is called, we emit the function's + * body code again because the set of available registers may be different. + */ +static struct prog_instruction * +emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct gl_program *progSave; + struct prog_instruction *inst; + GLuint subroutineId; + + assert(n->Opcode == IR_CALL); + assert(n->Label); + + /* save/push cur program */ + progSave = emitInfo->prog; + emitInfo->prog = new_subroutine(emitInfo, &subroutineId); + + _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions, + emitInfo->prog); + + if (emitInfo->EmitBeginEndSub) { + /* BGNSUB isn't a real instruction. + * We require a label (i.e. "foobar:") though, if we're going to + * print the program in the NV format. The BNGSUB instruction is + * really just a NOP to attach the label to. + */ + inst = new_instruction(emitInfo, OPCODE_BGNSUB); + inst->Comment = _mesa_strdup(n->Label->Name); + } + + /* body of function: */ + emit(emitInfo, n->Children[0]); + n->Store = n->Children[0]->Store; + + /* add RET instruction now, if needed */ + inst = prev_instruction(emitInfo); + if (inst && inst->Opcode != OPCODE_RET) { + inst = new_instruction(emitInfo, OPCODE_RET); + } + + if (emitInfo->EmitBeginEndSub) { + inst = new_instruction(emitInfo, OPCODE_ENDSUB); + inst->Comment = _mesa_strdup(n->Label->Name); + } + + /* pop/restore cur program */ + emitInfo->prog = progSave; + + /* emit the function call */ + inst = new_instruction(emitInfo, OPCODE_CAL); + /* The branch target is just the subroutine number (changed later) */ + inst->BranchTarget = subroutineId; + inst->Comment = _mesa_strdup(n->Label->Name); + assert(inst->BranchTarget >= 0); + + return inst; +} + + +/** + * Emit code for a 'return' statement. + */ +static struct prog_instruction * +emit_return(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + assert(n); + assert(n->Opcode == IR_RETURN); + assert(n->Label); + inst = new_instruction(emitInfo, OPCODE_RET); + inst->DstReg.CondMask = COND_TR; /* always return */ + return inst; +} + + +static struct prog_instruction * +emit_kill(slang_emit_info *emitInfo) +{ + struct prog_instruction *inst; + /* NV-KILL - discard fragment depending on condition code. + * Note that ARB-KILL depends on sign of vector operand. + */ + inst = new_instruction(emitInfo, OPCODE_KIL_NV); + inst->DstReg.CondMask = COND_TR; /* always branch */ + return inst; +} + + +static struct prog_instruction * +emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + + (void) emit(emitInfo, n->Children[1]); + + if (n->Opcode == IR_TEX) { + inst = new_instruction(emitInfo, OPCODE_TEX); + } + else if (n->Opcode == IR_TEXB) { + inst = new_instruction(emitInfo, OPCODE_TXB); + } + else { + assert(n->Opcode == IR_TEXP); + inst = new_instruction(emitInfo, OPCODE_TXP); + } + + if (!n->Store) + if (!alloc_temp_storage(emitInfo, n, 4)) + return NULL; + + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + + /* Child[1] is the coord */ + assert(n->Children[1]->Store->File != PROGRAM_UNDEFINED); + assert(n->Children[1]->Store->Index >= 0); + storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + + /* Child[0] is the sampler (a uniform which'll indicate the texture unit) */ + assert(n->Children[0]->Store); + /* Store->Index is the sampler index */ + assert(n->Children[0]->Store->Index >= 0); + /* Store->Size is the texture target */ + assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX); + assert(n->Children[0]->Store->Size <= TEXTURE_RECT_INDEX); + + inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */ + inst->TexSrcTarget = n->Children[0]->Store->Size; + inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at + * link time, using the sampler uniform's value. + */ + return inst; +} + + +static struct prog_instruction * +emit_move(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + + /* lhs */ + emit(emitInfo, n->Children[0]); + if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) { + /* an error should have been already recorded */ + return NULL; + } + + /* rhs */ + assert(n->Children[1]); + inst = emit(emitInfo, n->Children[1]); + + if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) { + if (!emitInfo->log->text) { + slang_info_log_error(emitInfo->log, "invalid assignment"); + } + return NULL; + } + + assert(n->Children[1]->Store->Index >= 0); + + /*assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);*/ + + n->Store = n->Children[0]->Store; + +#if PEEPHOLE_OPTIMIZATIONS + if (inst && + _slang_is_temp(emitInfo->vt, n->Children[1]->Store) && + (inst->DstReg.File == n->Children[1]->Store->File) && + (inst->DstReg.Index == n->Children[1]->Store->Index)) { + /* Peephole optimization: + * The Right-Hand-Side has its results in a temporary place. + * Modify the RHS (and the prev instruction) to store its results + * in the destination specified by n->Children[0]. + * Then, this MOVE is a no-op. + */ + if (n->Children[1]->Opcode != IR_SWIZZLE) + _slang_free_temp(emitInfo->vt, n->Children[1]->Store); + *n->Children[1]->Store = *n->Children[0]->Store; + /* fixup the previous instruction (which stored the RHS result) */ + assert(n->Children[0]->Store->Index >= 0); + storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask); + return inst; + } + else +#endif + { + if (n->Children[0]->Store->Size > 4) { + /* move matrix/struct etc (block of registers) */ + slang_ir_storage dstStore = *n->Children[0]->Store; + slang_ir_storage srcStore = *n->Children[1]->Store; + GLint size = srcStore.Size; + ASSERT(n->Children[0]->Writemask == WRITEMASK_XYZW); + ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP); + dstStore.Size = 4; + srcStore.Size = 4; + while (size >= 4) { + inst = new_instruction(emitInfo, OPCODE_MOV); + inst->Comment = _mesa_strdup("IR_MOVE block"); + storage_to_dst_reg(&inst->DstReg, &dstStore, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], &srcStore); + srcStore.Index++; + dstStore.Index++; + size -= 4; + } + } + else { + /* single register move */ + char *srcAnnot, *dstAnnot; + inst = new_instruction(emitInfo, OPCODE_MOV); + assert(n->Children[0]->Store->Index >= 0); + storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + dstAnnot = storage_annotation(n->Children[0], emitInfo->prog); + srcAnnot = storage_annotation(n->Children[1], emitInfo->prog); + inst->Comment = instruction_annotation(inst->Opcode, dstAnnot, + srcAnnot, NULL, NULL); + } + free_temp_storage(emitInfo->vt, n->Children[1]); + return inst; + } +} + + +/** + * An IR_COND node wraps a boolean expression which is used by an + * IF or WHILE test. This is where we'll set condition codes, if needed. + */ +static struct prog_instruction * +emit_cond(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + + assert(n->Opcode == IR_COND); + + if (!n->Children[0]) + return NULL; + + /* emit code for the expression */ + inst = emit(emitInfo, n->Children[0]); + + if (!n->Children[0]->Store) { + /* error recovery */ + return NULL; + } + + assert(n->Children[0]->Store); + /*assert(n->Children[0]->Store->Size == 1);*/ + + if (emitInfo->EmitCondCodes) { + if (inst && + n->Children[0]->Store && + inst->DstReg.File == n->Children[0]->Store->File && + inst->DstReg.Index == n->Children[0]->Store->Index) { + /* The previous instruction wrote to the register who's value + * we're testing. Just fix that instruction so that the + * condition codes are computed. + */ + inst->CondUpdate = GL_TRUE; + n->Store = n->Children[0]->Store; + return inst; + } + else { + /* This'll happen for things like "if (i) ..." where no code + * is normally generated for the expression "i". + * Generate a move instruction just to set condition codes. + */ + if (!alloc_temp_storage(emitInfo, n, 1)) + return NULL; + inst = new_instruction(emitInfo, OPCODE_MOV); + inst->CondUpdate = GL_TRUE; + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + _slang_free_temp(emitInfo->vt, n->Store); + inst->Comment = _mesa_strdup("COND expr"); + return inst; + } + } + else { + /* No-op: the boolean result of the expression is in a regular reg */ + n->Store = n->Children[0]->Store; + return inst; + } +} + + +/** + * Logical-NOT + */ +static struct prog_instruction * +emit_not(slang_emit_info *emitInfo, slang_ir_node *n) +{ + static const struct { + gl_inst_opcode op, opNot; + } operators[] = { + { OPCODE_SLT, OPCODE_SGE }, + { OPCODE_SLE, OPCODE_SGT }, + { OPCODE_SGT, OPCODE_SLE }, + { OPCODE_SGE, OPCODE_SLT }, + { OPCODE_SEQ, OPCODE_SNE }, + { OPCODE_SNE, OPCODE_SEQ }, + { 0, 0 } + }; + struct prog_instruction *inst; + GLuint i; + + /* child expr */ + inst = emit(emitInfo, n->Children[0]); + +#if PEEPHOLE_OPTIMIZATIONS + if (inst) { + /* if the prev instruction was a comparison instruction, invert it */ + for (i = 0; operators[i].op; i++) { + if (inst->Opcode == operators[i].op) { + inst->Opcode = operators[i].opNot; + n->Store = n->Children[0]->Store; + return inst; + } + } + } +#endif + + /* else, invert using SEQ (v = v == 0) */ + if (!n->Store) + if (!alloc_temp_storage(emitInfo, n, n->Children[0]->Store->Size)) + return NULL; + + inst = new_instruction(emitInfo, OPCODE_SEQ); + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + constant_to_src_reg(&inst->SrcReg[1], 0.0, emitInfo); + free_temp_storage(emitInfo->vt, n->Children[0]); + + inst->Comment = _mesa_strdup("NOT"); + return inst; +} + + +static struct prog_instruction * +emit_if(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct gl_program *prog = emitInfo->prog; + GLuint ifInstLoc, elseInstLoc = 0; + GLuint condWritemask = 0; + + /* emit condition expression code */ + { + struct prog_instruction *inst; + inst = emit(emitInfo, n->Children[0]); + if (emitInfo->EmitCondCodes) { + if (!inst) { + /* error recovery */ + return NULL; + } + condWritemask = inst->DstReg.WriteMask; + } + } + +#if 0 + assert(n->Children[0]->Store->Size == 1); /* a bool! */ +#endif + + ifInstLoc = prog->NumInstructions; + if (emitInfo->EmitHighLevelInstructions) { + struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_IF); + if (emitInfo->EmitCondCodes) { + ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */ + /* only test the cond code (1 of 4) that was updated by the + * previous instruction. + */ + ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); + } + else { + /* test reg.x */ + storage_to_src_reg(&ifInst->SrcReg[0], n->Children[0]->Store); + } + } + else { + /* conditional jump to else, or endif */ + struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_BRA); + ifInst->DstReg.CondMask = COND_EQ; /* BRA if cond is zero */ + ifInst->Comment = _mesa_strdup("if zero"); + ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); + } + + /* if body */ + emit(emitInfo, n->Children[1]); + + if (n->Children[2]) { + /* have else body */ + elseInstLoc = prog->NumInstructions; + if (emitInfo->EmitHighLevelInstructions) { + (void) new_instruction(emitInfo, OPCODE_ELSE); + } + else { + /* jump to endif instruction */ + struct prog_instruction *inst; + inst = new_instruction(emitInfo, OPCODE_BRA); + inst->Comment = _mesa_strdup("else"); + inst->DstReg.CondMask = COND_TR; /* always branch */ + } + prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions; + emit(emitInfo, n->Children[2]); + } + else { + /* no else body */ + prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions; + } + + if (emitInfo->EmitHighLevelInstructions) { + (void) new_instruction(emitInfo, OPCODE_ENDIF); + } + + if (n->Children[2]) { + prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions; + } + return NULL; +} + + +static struct prog_instruction * +emit_loop(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct gl_program *prog = emitInfo->prog; + struct prog_instruction *endInst; + GLuint beginInstLoc, tailInstLoc, endInstLoc; + slang_ir_node *ir; + + /* emit OPCODE_BGNLOOP */ + beginInstLoc = prog->NumInstructions; + if (emitInfo->EmitHighLevelInstructions) { + (void) new_instruction(emitInfo, OPCODE_BGNLOOP); + } + + /* body */ + emit(emitInfo, n->Children[0]); + + /* tail */ + tailInstLoc = prog->NumInstructions; + if (n->Children[1]) { + if (emitInfo->EmitComments) + emit_comment(emitInfo, "Loop tail code:"); + emit(emitInfo, n->Children[1]); + } + + endInstLoc = prog->NumInstructions; + if (emitInfo->EmitHighLevelInstructions) { + /* emit OPCODE_ENDLOOP */ + endInst = new_instruction(emitInfo, OPCODE_ENDLOOP); + } + else { + /* emit unconditional BRA-nch */ + endInst = new_instruction(emitInfo, OPCODE_BRA); + endInst->DstReg.CondMask = COND_TR; /* always true */ + } + /* ENDLOOP's BranchTarget points to the BGNLOOP inst */ + endInst->BranchTarget = beginInstLoc; + + if (emitInfo->EmitHighLevelInstructions) { + /* BGNLOOP's BranchTarget points to the ENDLOOP inst */ + prog->Instructions[beginInstLoc].BranchTarget = prog->NumInstructions -1; + } + + /* Done emitting loop code. Now walk over the loop's linked list of + * BREAK and CONT nodes, filling in their BranchTarget fields (which + * will point to the ENDLOOP+1 or BGNLOOP instructions, respectively). + */ + for (ir = n->List; ir; ir = ir->List) { + struct prog_instruction *inst = prog->Instructions + ir->InstLocation; + assert(inst->BranchTarget < 0); + if (ir->Opcode == IR_BREAK || + ir->Opcode == IR_BREAK_IF_TRUE) { + assert(inst->Opcode == OPCODE_BRK || + inst->Opcode == OPCODE_BRA); + /* go to instruction after end of loop */ + inst->BranchTarget = endInstLoc + 1; + } + else { + assert(ir->Opcode == IR_CONT || + ir->Opcode == IR_CONT_IF_TRUE); + assert(inst->Opcode == OPCODE_CONT || + inst->Opcode == OPCODE_BRA); + /* go to instruction at tail of loop */ + inst->BranchTarget = endInstLoc; + } + } + return NULL; +} + + +/** + * Unconditional "continue" or "break" statement. + * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted. + */ +static struct prog_instruction * +emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n) +{ + gl_inst_opcode opcode; + struct prog_instruction *inst; + + if (n->Opcode == IR_CONT) { + /* we need to execute the loop's tail code before doing CONT */ + assert(n->Parent); + assert(n->Parent->Opcode == IR_LOOP); + if (n->Parent->Children[1]) { + /* emit tail code */ + if (emitInfo->EmitComments) { + emit_comment(emitInfo, "continue - tail code:"); + } + emit(emitInfo, n->Parent->Children[1]); + } + } + + /* opcode selection */ + if (emitInfo->EmitHighLevelInstructions) { + opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK; + } + else { + opcode = OPCODE_BRA; + } + n->InstLocation = emitInfo->prog->NumInstructions; + inst = new_instruction(emitInfo, opcode); + inst->DstReg.CondMask = COND_TR; /* always true */ + return inst; +} + + +/** + * Conditional "continue" or "break" statement. + * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted. + */ +static struct prog_instruction * +emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + + assert(n->Opcode == IR_CONT_IF_TRUE || + n->Opcode == IR_BREAK_IF_TRUE); + + /* evaluate condition expr, setting cond codes */ + inst = emit(emitInfo, n->Children[0]); + if (emitInfo->EmitCondCodes) { + assert(inst); + inst->CondUpdate = GL_TRUE; + } + + n->InstLocation = emitInfo->prog->NumInstructions; + + /* opcode selection */ + if (emitInfo->EmitHighLevelInstructions) { + const gl_inst_opcode opcode + = (n->Opcode == IR_CONT_IF_TRUE) ? OPCODE_CONT : OPCODE_BRK; + if (emitInfo->EmitCondCodes) { + /* Get the writemask from the previous instruction which set + * the condcodes. Use that writemask as the CondSwizzle. + */ + const GLuint condWritemask = inst->DstReg.WriteMask; + inst = new_instruction(emitInfo, opcode); + inst->DstReg.CondMask = COND_NE; + inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); + return inst; + } + else { + /* IF reg + * BRK/CONT; + * ENDIF + */ + GLint ifInstLoc; + ifInstLoc = emitInfo->prog->NumInstructions; + inst = new_instruction(emitInfo, OPCODE_IF); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + n->InstLocation = emitInfo->prog->NumInstructions; + + inst = new_instruction(emitInfo, opcode); + inst = new_instruction(emitInfo, OPCODE_ENDIF); + + emitInfo->prog->Instructions[ifInstLoc].BranchTarget + = emitInfo->prog->NumInstructions; + return inst; + } + } + else { + const GLuint condWritemask = inst->DstReg.WriteMask; + assert(emitInfo->EmitCondCodes); + inst = new_instruction(emitInfo, OPCODE_BRA); + inst->DstReg.CondMask = COND_NE; + inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); + return inst; + } +} + + + +/** + * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term). + * Ex: fix_swizzle("zyNN") -> "zyyy" + */ +static GLuint +fix_swizzle(GLuint swizzle) +{ + GLuint swz[4], i; + for (i = 0; i < 4; i++) { + swz[i] = GET_SWZ(swizzle, i); + if (swz[i] == SWIZZLE_NIL) { + swz[i] = swz[i - 1]; + } + } + return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); +} + + +/** + * Return the number of components actually named by the swizzle. + * Recall that swizzles may have undefined/don't-care values. + */ +static GLuint +swizzle_size(GLuint swizzle) +{ + GLuint size = 0, i; + for (i = 0; i < 4; i++) { + GLuint swz = GET_SWZ(swizzle, i); + size += (swz >= 0 && swz <= 3); + } + return size; +} + + +static struct prog_instruction * +emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) +{ + GLuint swizzle; + struct prog_instruction *inst; + + inst = emit(emitInfo, n->Children[0]); + +#ifdef DEBUG + { + GLuint s = n->Children[0]->Store->Swizzle; + assert(GET_SWZ(s, 0) != SWIZZLE_NIL); + assert(GET_SWZ(s, 1) != SWIZZLE_NIL); + assert(GET_SWZ(s, 2) != SWIZZLE_NIL); + assert(GET_SWZ(s, 3) != SWIZZLE_NIL); + } +#endif + /* For debug: n->Var = n->Children[0]->Var; */ + + /* "pull-up" the child's storage info, applying our swizzle info */ + n->Store->File = n->Children[0]->Store->File; + n->Store->Index = n->Children[0]->Store->Index; + n->Store->Size = swizzle_size(n->Store->Swizzle); +#if 0 + printf("Emit Swizzle %s reg %d chSize %d mySize %d\n", + _mesa_swizzle_string(n->Store->Swizzle, 0, 0), + n->Store->Index, n->Children[0]->Store->Size, + n->Store->Size); +#endif + + /* apply this swizzle to child's swizzle to get composed swizzle */ + swizzle = fix_swizzle(n->Store->Swizzle); /* remove the don't care terms */ + n->Store->Swizzle = swizzle_swizzle(n->Children[0]->Store->Swizzle, + swizzle); + + return inst; +} + + +/** + * Dereference array element. Just resolve storage for the array + * element represented by this node. + */ +static struct prog_instruction * +emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n) +{ + assert(n->Store); + assert(n->Store->File != PROGRAM_UNDEFINED); + assert(n->Store->Size > 0); + + if (n->Store->File == PROGRAM_STATE_VAR) { + n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); + return NULL; + } + + if (n->Children[1]->Opcode == IR_FLOAT) { + /* Constant index */ + const GLint arrayAddr = n->Children[0]->Store->Index; + const GLint index = (GLint) n->Children[1]->Value[0]; + n->Store->Index = arrayAddr + index; + } + else { + /* Variable index - PROBLEM */ + const GLint arrayAddr = n->Children[0]->Store->Index; + const GLint index = 0; + _mesa_problem(NULL, "variable array indexes not supported yet!"); + n->Store->Index = arrayAddr + index; + } + return NULL; /* no instruction */ +} + + +/** + * Resolve storage for accessing a structure field. + */ +static struct prog_instruction * +emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n) +{ + if (n->Store->File == PROGRAM_STATE_VAR) { + n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); + } + else { + GLint offset = n->FieldOffset / 4; + assert(n->Children[0]->Store->Index >= 0); + n->Store->Index = n->Children[0]->Store->Index + offset; + if (n->Store->Size == 1) { + GLint swz = n->FieldOffset % 4; + n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz); + } + else { + n->Store->Swizzle = SWIZZLE_XYZW; + } + } + return NULL; /* no instruction */ +} + + +static struct prog_instruction * +emit(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + if (!n) + return NULL; + + switch (n->Opcode) { + case IR_SEQ: + /* sequence of two sub-trees */ + assert(n->Children[0]); + assert(n->Children[1]); + emit(emitInfo, n->Children[0]); + inst = emit(emitInfo, n->Children[1]); +#if 0 + assert(!n->Store); +#endif + n->Store = n->Children[1]->Store; + return inst; + + case IR_SCOPE: + /* new variable scope */ + _slang_push_var_table(emitInfo->vt); + inst = emit(emitInfo, n->Children[0]); + _slang_pop_var_table(emitInfo->vt); + return inst; + + case IR_VAR_DECL: + /* Variable declaration - allocate a register for it */ + assert(n->Store); + assert(n->Store->File != PROGRAM_UNDEFINED); + assert(n->Store->Size > 0); + /*assert(n->Store->Index < 0);*/ + if (!n->Var || n->Var->isTemp) { + /* a nameless/temporary variable, will be freed after first use */ + /*NEW*/ + if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) { + slang_info_log_error(emitInfo->log, + "Ran out of registers, too many temporaries"); + return NULL; + } + } + else { + /* a regular variable */ + _slang_add_variable(emitInfo->vt, n->Var); + if (!_slang_alloc_var(emitInfo->vt, n->Store)) { + slang_info_log_error(emitInfo->log, + "Ran out of registers, too many variables"); + return NULL; + } + /* + printf("IR_VAR_DECL %s %d store %p\n", + (char*) n->Var->a_name, n->Store->Index, (void*) n->Store); + */ + assert(n->Var->aux == n->Store); + } + if (emitInfo->EmitComments) { + /* emit NOP with comment describing the variable's storage location */ + char s[1000]; + sprintf(s, "TEMP[%d]%s = variable %s (size %d)", + n->Store->Index, + _mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE), + (n->Var ? (char *) n->Var->a_name : "anonymous"), + n->Store->Size); + inst = emit_comment(emitInfo, s); + return inst; + } + return NULL; + + case IR_VAR: + /* Reference to a variable + * Storage should have already been resolved/allocated. + */ + assert(n->Store); + assert(n->Store->File != PROGRAM_UNDEFINED); + + if (n->Store->File == PROGRAM_STATE_VAR && + n->Store->Index < 0) { + n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters); + } + + if (n->Store->Index < 0) { + /* probably ran out of registers */ + return NULL; + } + assert(n->Store->Size > 0); + break; + + case IR_ELEMENT: + return emit_array_element(emitInfo, n); + case IR_FIELD: + return emit_struct_field(emitInfo, n); + case IR_SWIZZLE: + return emit_swizzle(emitInfo, n); + + case IR_I_TO_F: + /* just move */ + emit(emitInfo, n->Children[0]); + inst = new_instruction(emitInfo, OPCODE_MOV); + if (!n->Store) { + if (!alloc_temp_storage(emitInfo, n, 1)) + return NULL; + } + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + if (emitInfo->EmitComments) + inst->Comment = _mesa_strdup("int to float"); + return NULL; + + /* Simple arithmetic */ + /* unary */ + case IR_RSQ: + case IR_RCP: + case IR_FLOOR: + case IR_FRAC: + case IR_F_TO_I: + case IR_ABS: + case IR_SIN: + case IR_COS: + case IR_DDX: + case IR_DDY: + case IR_NOISE1: + case IR_NOISE2: + case IR_NOISE3: + case IR_NOISE4: + /* binary */ + case IR_ADD: + case IR_SUB: + case IR_MUL: + case IR_DOT4: + case IR_DOT3: + case IR_CROSS: + case IR_MIN: + case IR_MAX: + case IR_SEQUAL: + case IR_SNEQUAL: + case IR_SGE: + case IR_SGT: + case IR_SLE: + case IR_SLT: + case IR_POW: + case IR_EXP: + case IR_EXP2: + /* trinary operators */ + case IR_LRP: + return emit_arith(emitInfo, n); + + case IR_EQUAL: + case IR_NOTEQUAL: + return emit_compare(emitInfo, n); + + case IR_CLAMP: + return emit_clamp(emitInfo, n); + case IR_TEX: + case IR_TEXB: + case IR_TEXP: + return emit_tex(emitInfo, n); + case IR_NEG: + return emit_negation(emitInfo, n); + case IR_FLOAT: + /* find storage location for this float constant */ + n->Store->Index = _mesa_add_unnamed_constant(emitInfo->prog->Parameters, + n->Value, + n->Store->Size, + &n->Store->Swizzle); + if (n->Store->Index < 0) { + slang_info_log_error(emitInfo->log, "Ran out of space for constants"); + return NULL; + } + return NULL; + + case IR_MOVE: + return emit_move(emitInfo, n); + + case IR_COND: + return emit_cond(emitInfo, n); + + case IR_NOT: + return emit_not(emitInfo, n); + + case IR_LABEL: + return emit_label(emitInfo, n); + + case IR_KILL: + return emit_kill(emitInfo); + + case IR_CALL: + /* new variable scope for subroutines/function calls */ + _slang_push_var_table(emitInfo->vt); + inst = emit_fcall(emitInfo, n); + _slang_pop_var_table(emitInfo->vt); + return inst; + + case IR_IF: + return emit_if(emitInfo, n); + + case IR_LOOP: + return emit_loop(emitInfo, n); + case IR_BREAK_IF_TRUE: + case IR_CONT_IF_TRUE: + return emit_cont_break_if_true(emitInfo, n); + case IR_BREAK: + /* fall-through */ + case IR_CONT: + return emit_cont_break(emitInfo, n); + + case IR_BEGIN_SUB: + return new_instruction(emitInfo, OPCODE_BGNSUB); + case IR_END_SUB: + return new_instruction(emitInfo, OPCODE_ENDSUB); + case IR_RETURN: + return emit_return(emitInfo, n); + + case IR_NOP: + return NULL; + + default: + _mesa_problem(NULL, "Unexpected IR opcode in emit()\n"); + } + return NULL; +} + + +/** + * After code generation, any subroutines will be in separate program + * objects. This function appends all the subroutines onto the main + * program and resolves the linking of all the branch/call instructions. + * XXX this logic should really be part of the linking process... + */ +static void +_slang_resolve_subroutines(slang_emit_info *emitInfo) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_program *mainP = emitInfo->prog; + GLuint *subroutineLoc, i, total; + + subroutineLoc + = (GLuint *) _mesa_malloc(emitInfo->NumSubroutines * sizeof(GLuint)); + + /* total number of instructions */ + total = mainP->NumInstructions; + for (i = 0; i < emitInfo->NumSubroutines; i++) { + subroutineLoc[i] = total; + total += emitInfo->Subroutines[i]->NumInstructions; + } + + /* adjust BrancTargets within the functions */ + for (i = 0; i < emitInfo->NumSubroutines; i++) { + struct gl_program *sub = emitInfo->Subroutines[i]; + GLuint j; + for (j = 0; j < sub->NumInstructions; j++) { + struct prog_instruction *inst = sub->Instructions + j; + if (inst->Opcode != OPCODE_CAL && inst->BranchTarget >= 0) { + inst->BranchTarget += subroutineLoc[i]; + } + } + } + + /* append subroutines' instructions after main's instructions */ + mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions, + mainP->NumInstructions, + total); + mainP->NumInstructions = total; + for (i = 0; i < emitInfo->NumSubroutines; i++) { + struct gl_program *sub = emitInfo->Subroutines[i]; + _mesa_copy_instructions(mainP->Instructions + subroutineLoc[i], + sub->Instructions, + sub->NumInstructions); + /* delete subroutine code */ + sub->Parameters = NULL; /* prevent double-free */ + _mesa_delete_program(ctx, sub); + } + + /* free subroutine list */ + if (emitInfo->Subroutines) { + _mesa_free(emitInfo->Subroutines); + emitInfo->Subroutines = NULL; + } + emitInfo->NumSubroutines = 0; + + /* Examine CAL instructions. + * At this point, the BranchTarget field of the CAL instruction is + * the number/id of the subroutine to call (an index into the + * emitInfo->Subroutines list). + * Translate that into an actual instruction location now. + */ + for (i = 0; i < mainP->NumInstructions; i++) { + struct prog_instruction *inst = mainP->Instructions + i; + if (inst->Opcode == OPCODE_CAL) { + const GLuint f = inst->BranchTarget; + inst->BranchTarget = subroutineLoc[f]; + } + } + + _mesa_free(subroutineLoc); +} + + + + +GLboolean +_slang_emit_code(slang_ir_node *n, slang_var_table *vt, + struct gl_program *prog, GLboolean withEnd, + slang_info_log *log) +{ + GET_CURRENT_CONTEXT(ctx); + GLboolean success; + slang_emit_info emitInfo; + + emitInfo.log = log; + emitInfo.vt = vt; + emitInfo.prog = prog; + emitInfo.Subroutines = NULL; + emitInfo.NumSubroutines = 0; + + emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions; + emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes; + emitInfo.EmitComments = ctx->Shader.EmitComments; + emitInfo.EmitBeginEndSub = GL_TRUE; + + if (!emitInfo.EmitCondCodes) { + emitInfo.EmitHighLevelInstructions = GL_TRUE; + } + + (void) emit(&emitInfo, n); + + /* finish up by adding the END opcode to program */ + if (withEnd) { + struct prog_instruction *inst; + inst = new_instruction(&emitInfo, OPCODE_END); + } + + _slang_resolve_subroutines(&emitInfo); + + success = GL_TRUE; + +#if 0 + printf("*********** End emit code (%u inst):\n", prog->NumInstructions); + _mesa_print_program(prog); + _mesa_print_program_parameters(ctx,prog); +#endif + + return success; +} diff --git a/dist/Mesa/src/mesa/shader/slang/slang_emit.h b/dist/Mesa/src/mesa/shader/slang/slang_emit.h new file mode 100644 index 000000000..13ba6d7d6 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_emit.h @@ -0,0 +1,49 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_EMIT_H +#define SLANG_EMIT_H + + +#include "imports.h" +#include "slang_compile.h" +#include "slang_ir.h" +#include "mtypes.h" + + +extern void +slang_print_ir(const slang_ir_node *n, int indent); + + +extern slang_ir_storage * +_slang_new_ir_storage(enum register_file file, GLint index, GLint size); + + +extern GLboolean +_slang_emit_code(slang_ir_node *n, slang_var_table *vartable, + struct gl_program *prog, GLboolean withEnd, + slang_info_log *log); + + +#endif /* SLANG_EMIT_H */ diff --git a/dist/Mesa/src/mesa/shader/slang/slang_ir.c b/dist/Mesa/src/mesa/shader/slang/slang_ir.c new file mode 100644 index 000000000..92e8d0345 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_ir.c @@ -0,0 +1,382 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "imports.h" +#include "context.h" +#include "slang_ir.h" +#include "slang_mem.h" +#include "shader/prog_print.h" + + +static const slang_ir_info IrInfo[] = { + /* binary ops */ + { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 }, + { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 }, + { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 }, + { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */ + { IR_DOT4, "IR_DOT_4", OPCODE_DP4, 1, 2 }, + { IR_DOT3, "IR_DOT_3", OPCODE_DP3, 1, 2 }, + { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 }, + { IR_LRP, "IR_LRP", OPCODE_LRP, 4, 3 }, + { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 }, + { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 }, + { IR_CLAMP, "IR_CLAMP", OPCODE_NOP, 4, 3 }, /* special case: emit_clamp() */ + { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 }, + { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 }, + { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 }, + { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 }, + { IR_SLE, "IR_SLE", OPCODE_SLE, 4, 2 }, + { IR_SLT, "IR_SLT", OPCODE_SLT, 4, 2 }, + { IR_POW, "IR_POW", OPCODE_POW, 1, 2 }, + /* unary ops */ + { IR_I_TO_F, "IR_I_TO_F", OPCODE_NOP, 1, 1 }, + { IR_F_TO_I, "IR_F_TO_I", OPCODE_INT, 4, 1 }, /* 4 floats to 4 ints */ + { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 }, + { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 }, + { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 }, + { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 }, + { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 }, + { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 }, + { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 }, + { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 }, + { IR_NEG, "IR_NEG", OPCODE_NOP, 4, 1 }, /* special case: emit_negation() */ + { IR_DDX, "IR_DDX", OPCODE_DDX, 4, 1 }, + { IR_DDY, "IR_DDY", OPCODE_DDY, 4, 1 }, + { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 }, + { IR_COS, "IR_COS", OPCODE_COS, 1, 1 }, + { IR_NOISE1, "IR_NOISE1", OPCODE_NOISE1, 1, 1 }, + { IR_NOISE2, "IR_NOISE2", OPCODE_NOISE2, 1, 1 }, + { IR_NOISE3, "IR_NOISE3", OPCODE_NOISE3, 1, 1 }, + { IR_NOISE4, "IR_NOISE4", OPCODE_NOISE4, 1, 1 }, + + /* other */ + { IR_SEQ, "IR_SEQ", OPCODE_NOP, 0, 0 }, + { IR_SCOPE, "IR_SCOPE", OPCODE_NOP, 0, 0 }, + { IR_LABEL, "IR_LABEL", OPCODE_NOP, 0, 0 }, + { IR_IF, "IR_IF", OPCODE_NOP, 0, 0 }, + { IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 }, + { IR_COND, "IR_COND", OPCODE_NOP, 0, 0 }, + { IR_CALL, "IR_CALL", OPCODE_NOP, 0, 0 }, + { IR_MOVE, "IR_MOVE", OPCODE_NOP, 0, 1 }, + { IR_NOT, "IR_NOT", OPCODE_NOP, 1, 1 }, + { IR_VAR, "IR_VAR", OPCODE_NOP, 0, 0 }, + { IR_VAR_DECL, "IR_VAR_DECL", OPCODE_NOP, 0, 0 }, + { IR_TEX, "IR_TEX", OPCODE_TEX, 4, 1 }, + { IR_TEXB, "IR_TEXB", OPCODE_TXB, 4, 1 }, + { IR_TEXP, "IR_TEXP", OPCODE_TXP, 4, 1 }, + { IR_FLOAT, "IR_FLOAT", OPCODE_NOP, 0, 0 }, /* float literal */ + { IR_FIELD, "IR_FIELD", OPCODE_NOP, 0, 0 }, + { IR_ELEMENT, "IR_ELEMENT", OPCODE_NOP, 0, 0 }, + { IR_SWIZZLE, "IR_SWIZZLE", OPCODE_NOP, 0, 0 }, + { IR_NOP, NULL, OPCODE_NOP, 0, 0 } +}; + + +const slang_ir_info * +_slang_ir_info(slang_ir_opcode opcode) +{ + GLuint i; + for (i = 0; IrInfo[i].IrName; i++) { + if (IrInfo[i].IrOpcode == opcode) { + return IrInfo + i; + } + } + return NULL; +} + + +static const char * +_slang_ir_name(slang_ir_opcode opcode) +{ + return _slang_ir_info(opcode)->IrName; +} + + +#if 0 /* no longer needed with mempool */ +/** + * Since many IR nodes might point to the same IR storage info, we need + * to be careful when deleting things. + * Before deleting an IR tree, traverse it and do refcounting on the + * IR storage nodes. Use the refcount info during delete to free things + * properly. + */ +static void +_slang_refcount_storage(slang_ir_node *n) +{ + GLuint i; + if (!n) + return; + if (n->Store) + n->Store->RefCount++; + for (i = 0; i < 3; i++) + _slang_refcount_storage(n->Children[i]); +} +#endif + + +static void +_slang_free_ir(slang_ir_node *n) +{ + GLuint i; + if (!n) + return; + +#if 0 + if (n->Store) { + n->Store->RefCount--; + if (n->Store->RefCount == 0) { + _slang_free(n->Store); + n->Store = NULL; + } + } +#endif + + for (i = 0; i < 3; i++) + _slang_free_ir(n->Children[i]); + /* Do not free n->List since it's a child elsewhere */ + _slang_free(n); +} + + +/** + * Recursively free an IR tree. + */ +void +_slang_free_ir_tree(slang_ir_node *n) +{ +#if 0 + _slang_refcount_storage(n); +#endif + _slang_free_ir(n); +} + + + +static const char * +swizzle_string(GLuint swizzle) +{ + static char s[6]; + GLuint i; + s[0] = '.'; + for (i = 1; i < 5; i++) { + s[i] = "xyzw"[GET_SWZ(swizzle, i-1)]; + } + s[i] = 0; + return s; +} + + +static const char * +writemask_string(GLuint writemask) +{ + static char s[6]; + GLuint i, j = 0; + s[j++] = '.'; + for (i = 0; i < 4; i++) { + if (writemask & (1 << i)) + s[j++] = "xyzw"[i]; + } + s[j] = 0; + return s; +} + + +static const char * +storage_string(const slang_ir_storage *st) +{ + static const char *files[] = { + "TEMP", + "LOCAL_PARAM", + "ENV_PARAM", + "STATE", + "INPUT", + "OUTPUT", + "NAMED_PARAM", + "CONSTANT", + "UNIFORM", + "WRITE_ONLY", + "ADDRESS", + "SAMPLER", + "UNDEFINED" + }; + static char s[100]; +#if 0 + if (st->Size == 1) + sprintf(s, "%s[%d]", files[st->File], st->Index); + else + sprintf(s, "%s[%d..%d]", files[st->File], st->Index, + st->Index + st->Size - 1); +#endif + assert(st->File < (GLint) (sizeof(files) / sizeof(files[0]))); + sprintf(s, "%s[%d]", files[st->File], st->Index); + return s; +} + + +static void +spaces(int n) +{ + while (n-- > 0) { + printf(" "); + } +} + + +void +_slang_print_ir_tree(const slang_ir_node *n, int indent) +{ +#define IND 0 + + if (!n) + return; +#if !IND + if (n->Opcode != IR_SEQ) +#else + printf("%3d:", indent); +#endif + spaces(indent); + + switch (n->Opcode) { + case IR_SEQ: +#if IND + printf("SEQ at %p\n", (void*) n); +#endif + assert(n->Children[0]); + assert(n->Children[1]); + _slang_print_ir_tree(n->Children[0], indent + IND); + _slang_print_ir_tree(n->Children[1], indent + IND); + break; + case IR_SCOPE: + printf("NEW SCOPE\n"); + assert(!n->Children[1]); + _slang_print_ir_tree(n->Children[0], indent + 3); + break; + case IR_MOVE: + printf("MOVE (writemask = %s)\n", writemask_string(n->Writemask)); + _slang_print_ir_tree(n->Children[0], indent+3); + _slang_print_ir_tree(n->Children[1], indent+3); + break; + case IR_LABEL: + printf("LABEL: %s\n", n->Label->Name); + break; + case IR_COND: + printf("COND\n"); + _slang_print_ir_tree(n->Children[0], indent + 3); + break; + + case IR_IF: + printf("IF \n"); + _slang_print_ir_tree(n->Children[0], indent+3); + spaces(indent); + printf("THEN\n"); + _slang_print_ir_tree(n->Children[1], indent+3); + if (n->Children[2]) { + spaces(indent); + printf("ELSE\n"); + _slang_print_ir_tree(n->Children[2], indent+3); + } + spaces(indent); + printf("ENDIF\n"); + break; + + case IR_BEGIN_SUB: + printf("BEGIN_SUB\n"); + break; + case IR_END_SUB: + printf("END_SUB\n"); + break; + case IR_RETURN: + printf("RETURN\n"); + break; + case IR_CALL: + printf("CALL %s\n", n->Label->Name); + break; + + case IR_LOOP: + printf("LOOP\n"); + _slang_print_ir_tree(n->Children[0], indent+3); + if (n->Children[1]) { + spaces(indent); + printf("TAIL:\n"); + _slang_print_ir_tree(n->Children[1], indent+3); + } + spaces(indent); + printf("ENDLOOP\n"); + break; + case IR_CONT: + printf("CONT\n"); + break; + case IR_BREAK: + printf("BREAK\n"); + break; + case IR_BREAK_IF_TRUE: + printf("BREAK_IF_TRUE\n"); + _slang_print_ir_tree(n->Children[0], indent+3); + break; + case IR_CONT_IF_TRUE: + printf("CONT_IF_TRUE\n"); + _slang_print_ir_tree(n->Children[0], indent+3); + break; + + case IR_VAR: + printf("VAR %s%s at %s store %p\n", + (n->Var ? (char *) n->Var->a_name : "TEMP"), + swizzle_string(n->Store->Swizzle), + storage_string(n->Store), (void*) n->Store); + break; + case IR_VAR_DECL: + printf("VAR_DECL %s (%p) at %s store %p\n", + (n->Var ? (char *) n->Var->a_name : "TEMP"), + (void*) n->Var, storage_string(n->Store), + (void*) n->Store); + break; + case IR_FIELD: + printf("FIELD %s of\n", n->Field); + _slang_print_ir_tree(n->Children[0], indent+3); + break; + case IR_FLOAT: + printf("FLOAT %g %g %g %g\n", + n->Value[0], n->Value[1], n->Value[2], n->Value[3]); + break; + case IR_I_TO_F: + printf("INT_TO_FLOAT\n"); + _slang_print_ir_tree(n->Children[0], indent+3); + break; + case IR_F_TO_I: + printf("FLOAT_TO_INT\n"); + _slang_print_ir_tree(n->Children[0], indent+3); + break; + case IR_SWIZZLE: + printf("SWIZZLE %s of (store %p) \n", + swizzle_string(n->Store->Swizzle), (void*) n->Store); + _slang_print_ir_tree(n->Children[0], indent + 3); + break; + default: + printf("%s (%p, %p) (store %p)\n", _slang_ir_name(n->Opcode), + (void*) n->Children[0], (void*) n->Children[1], (void*) n->Store); + _slang_print_ir_tree(n->Children[0], indent+3); + _slang_print_ir_tree(n->Children[1], indent+3); + } +} diff --git a/dist/Mesa/src/mesa/shader/slang/slang_ir.h b/dist/Mesa/src/mesa/shader/slang/slang_ir.h new file mode 100644 index 000000000..c7c0ddbf9 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_ir.h @@ -0,0 +1,203 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_ir.h + * Mesa GLSL Intermediate Representation tree types and constants. + * \author Brian Paul + */ + + +#ifndef SLANG_IR_H +#define SLANG_IR_H + + +#include "imports.h" +#include "slang_compile.h" +#include "slang_label.h" +#include "mtypes.h" + + +/** + * Intermediate Representation opcodes + */ +typedef enum +{ + IR_NOP = 0, + IR_SEQ, /* sequence (eval left, then right) */ + IR_SCOPE, /* new variable scope (one child) */ + + IR_LABEL, /* target of a jump or cjump */ + + IR_COND, /* conditional expression/predicate */ + + IR_IF, /* high-level IF/then/else */ + /* Children[0] = conditional expression */ + /* Children[1] = if-true part */ + /* Children[2] = if-else part, or NULL */ + + IR_BEGIN_SUB, /* begin subroutine */ + IR_END_SUB, /* end subroutine */ + IR_RETURN, /* return from subroutine */ + IR_CALL, /* call subroutine */ + + IR_LOOP, /* high-level loop-begin / loop-end */ + /* Children[0] = loop body */ + /* Children[1] = loop tail code, or NULL */ + + IR_CONT, /* continue loop */ + /* n->Parent = ptr to parent IR_LOOP Node */ + IR_BREAK, /* break loop */ + + IR_BREAK_IF_TRUE, + IR_CONT_IF_TRUE, + /* Children[0] = the condition expression */ + + IR_MOVE, + + /* vector ops: */ + IR_ADD, + IR_SUB, + IR_MUL, + IR_DIV, + IR_DOT4, + IR_DOT3, + IR_CROSS, /* vec3 cross product */ + IR_LRP, + IR_CLAMP, + IR_MIN, + IR_MAX, + IR_SEQUAL, /* Set if args are equal (vector) */ + IR_SNEQUAL, /* Set if args are not equal (vector) */ + IR_SGE, /* Set if greater or equal (vector) */ + IR_SGT, /* Set if greater than (vector) */ + IR_SLE, /* Set if less or equal (vector) */ + IR_SLT, /* Set if less than (vector) */ + IR_POW, /* x^y */ + IR_EXP, /* e^x */ + IR_EXP2, /* 2^x */ + IR_LOG2, /* log base 2 */ + IR_RSQ, /* 1/sqrt() */ + IR_RCP, /* reciprocol */ + IR_FLOOR, + IR_FRAC, + IR_ABS, /* absolute value */ + IR_NEG, /* negate */ + IR_DDX, /* derivative w.r.t. X */ + IR_DDY, /* derivative w.r.t. Y */ + IR_SIN, /* sine */ + IR_COS, /* cosine */ + IR_NOISE1, /* noise(x) */ + IR_NOISE2, /* noise(x, y) */ + IR_NOISE3, /* noise(x, y, z) */ + IR_NOISE4, /* noise(x, y, z, w) */ + + IR_EQUAL, /* boolean equality */ + IR_NOTEQUAL,/* boolean inequality */ + IR_NOT, /* boolean not */ + + IR_VAR, /* variable reference */ + IR_VAR_DECL,/* var declaration */ + + IR_ELEMENT, /* array element */ + IR_FIELD, /* struct field */ + IR_SWIZZLE, /* swizzled storage access */ + + IR_TEX, /* texture lookup */ + IR_TEXB, /* texture lookup with LOD bias */ + IR_TEXP, /* texture lookup with projection */ + + IR_FLOAT, + IR_I_TO_F, /* int[4] to float[4] conversion */ + IR_F_TO_I, /* float[4] to int[4] conversion */ + + IR_KILL /* fragment kill/discard */ +} slang_ir_opcode; + + +/** + * Describes where data storage is allocated. + */ +struct _slang_ir_storage +{ + enum register_file File; /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */ + GLint Index; /**< -1 means unallocated */ + GLint Size; /**< number of floats */ + GLuint Swizzle; + GLint RefCount; /**< Used during IR tree delete */ +}; + +typedef struct _slang_ir_storage slang_ir_storage; + + +/** + * Intermediate Representation (IR) tree node + * Basically a binary tree, but IR_LRP and IR_CLAMP have three children. + */ +typedef struct slang_ir_node_ +{ + slang_ir_opcode Opcode; + struct slang_ir_node_ *Children[3]; + slang_ir_storage *Store; /**< location of result of this operation */ + GLint InstLocation; /**< Location of instruction emitted for this node */ + + /** special fields depending on Opcode: */ + const char *Field; /**< If Opcode == IR_FIELD */ + int FieldOffset; /**< If Opcode == IR_FIELD */ + GLuint Writemask; /**< If Opcode == IR_MOVE */ + GLfloat Value[4]; /**< If Opcode == IR_FLOAT */ + slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */ + struct slang_ir_node_ *List; /**< For various linked lists */ + struct slang_ir_node_ *Parent; /**< Pointer to logical parent (ie. loop) */ + slang_label *Label; /**< Used for branches */ +} slang_ir_node; + + + +/** + * Assembly and IR info + */ +typedef struct +{ + slang_ir_opcode IrOpcode; + const char *IrName; + gl_inst_opcode InstOpcode; + GLuint ResultSize, NumParams; +} slang_ir_info; + + + +extern const slang_ir_info * +_slang_ir_info(slang_ir_opcode opcode); + + +extern void +_slang_free_ir_tree(slang_ir_node *n); + + +extern void +_slang_print_ir_tree(const slang_ir_node *n, int indent); + + +#endif /* SLANG_IR_H */ diff --git a/dist/Mesa/src/mesa/shader/slang/slang_label.c b/dist/Mesa/src/mesa/shader/slang/slang_label.c new file mode 100644 index 000000000..1ca1ef0c7 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_label.c @@ -0,0 +1,104 @@ + + +/** + * Functions for managing instruction labels. + * Basically, this is used to manage the problem of forward branches where + * we have a branch instruciton but don't know the target address yet. + */ + + +#include "slang_label.h" +#include "slang_mem.h" + + + +slang_label * +_slang_label_new(const char *name) +{ + slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label)); + if (l) { + l->Name = _slang_strdup(name); + l->Location = -1; + } + return l; +} + +/** + * As above, but suffix the name with a unique number. + */ +slang_label * +_slang_label_new_unique(const char *name) +{ + static int id = 1; + slang_label *l = (slang_label *) _slang_alloc(sizeof(slang_label)); + if (l) { + l->Name = (char *) _slang_alloc(_mesa_strlen(name) + 10); + if (!l->Name) { + _mesa_free(l); + return NULL; + } + _mesa_sprintf(l->Name, "%s_%d", name, id); + id++; + l->Location = -1; + } + return l; +} + +void +_slang_label_delete(slang_label *l) +{ + if (l->Name) { + _slang_free(l->Name); + l->Name = NULL; + } + if (l->References) { + _slang_free(l->References); + l->References = NULL; + } + _slang_free(l); +} + + +void +_slang_label_add_reference(slang_label *l, GLuint inst) +{ + const GLuint oldSize = l->NumReferences * sizeof(GLuint); + assert(l->Location < 0); + l->References = _slang_realloc(l->References, + oldSize, oldSize + sizeof(GLuint)); + if (l->References) { + l->References[l->NumReferences] = inst; + l->NumReferences++; + } +} + + +GLint +_slang_label_get_location(const slang_label *l) +{ + return l->Location; +} + + +void +_slang_label_set_location(slang_label *l, GLint location, + struct gl_program *prog) +{ + GLuint i; + + assert(l->Location < 0); + assert(location >= 0); + + l->Location = location; + + /* for the instructions that were waiting to learn the label's location: */ + for (i = 0; i < l->NumReferences; i++) { + const GLuint j = l->References[i]; + prog->Instructions[j].BranchTarget = location; + } + + if (l->References) { + _slang_free(l->References); + l->References = NULL; + } +} diff --git a/dist/Mesa/src/mesa/shader/slang/slang_label.h b/dist/Mesa/src/mesa/shader/slang/slang_label.h new file mode 100644 index 000000000..0f1a45b30 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_label.h @@ -0,0 +1,45 @@ +#ifndef SLANG_LABEL_H +#define SLANG_LABEL_H 1 + +#include "imports.h" +#include "mtypes.h" +#include "prog_instruction.h" + + +struct slang_label_ +{ + char *Name; + GLint Location; + /** + * List of instruction references (numbered starting at zero) which need + * their BranchTarget field filled in with the location eventually + * assigned to the label. + */ + GLuint NumReferences; + GLuint *References; /** Array [NumReferences] */ +}; + +typedef struct slang_label_ slang_label; + + +extern slang_label * +_slang_label_new(const char *name); + +extern slang_label * +_slang_label_new_unique(const char *name); + +extern void +_slang_label_delete(slang_label *l); + +extern void +_slang_label_add_reference(slang_label *l, GLuint inst); + +extern GLint +_slang_label_get_location(const slang_label *l); + +extern void +_slang_label_set_location(slang_label *l, GLint location, + struct gl_program *prog); + + +#endif /* SLANG_LABEL_H */ diff --git a/dist/Mesa/src/mesa/shader/slang/slang_log.c b/dist/Mesa/src/mesa/shader/slang/slang_log.c new file mode 100644 index 000000000..e9234bafe --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_log.c @@ -0,0 +1,143 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "imports.h" +#include "slang_log.h" +#include "slang_utility.h" + + + +static char *out_of_memory = "Error: Out of memory.\n"; + +void +slang_info_log_construct(slang_info_log * log) +{ + log->text = NULL; + log->dont_free_text = GL_FALSE; + log->error_flag = GL_FALSE; +} + +void +slang_info_log_destruct(slang_info_log * log) +{ + if (!log->dont_free_text) +#if 0 + slang_alloc_free(log->text); +#else + _mesa_free(log->text); +#endif +} + +static int +slang_info_log_message(slang_info_log * log, const char *prefix, + const char *msg) +{ + GLuint size; + + if (log->dont_free_text) + return 0; + size = slang_string_length(msg) + 2; + if (prefix != NULL) + size += slang_string_length(prefix) + 2; + if (log->text != NULL) { + GLuint old_len = slang_string_length(log->text); + log->text = (char *) +#if 0 + slang_alloc_realloc(log->text, old_len + 1, old_len + size); +#else + _mesa_realloc(log->text, old_len + 1, old_len + size); +#endif + } + else { +#if 0 + log->text = (char *) (slang_alloc_malloc(size)); +#else + log->text = (char *) (_mesa_malloc(size)); +#endif + if (log->text != NULL) + log->text[0] = '\0'; + } + if (log->text == NULL) + return 0; + if (prefix != NULL) { + slang_string_concat(log->text, prefix); + slang_string_concat(log->text, ": "); + } + slang_string_concat(log->text, msg); + slang_string_concat(log->text, "\n"); + return 1; +} + +int +slang_info_log_print(slang_info_log * log, const char *msg, ...) +{ + va_list va; + char buf[1024]; + + va_start(va, msg); + _mesa_vsprintf(buf, msg, va); + va_end(va); + return slang_info_log_message(log, NULL, buf); +} + +int +slang_info_log_error(slang_info_log * log, const char *msg, ...) +{ + va_list va; + char buf[1024]; + + va_start(va, msg); + _mesa_vsprintf(buf, msg, va); + va_end(va); + log->error_flag = GL_TRUE; + if (slang_info_log_message(log, "Error", buf)) + return 1; + slang_info_log_memory(log); + return 0; +} + +int +slang_info_log_warning(slang_info_log * log, const char *msg, ...) +{ + va_list va; + char buf[1024]; + + va_start(va, msg); + _mesa_vsprintf(buf, msg, va); + va_end(va); + if (slang_info_log_message(log, "Warning", buf)) + return 1; + slang_info_log_memory(log); + return 0; +} + +void +slang_info_log_memory(slang_info_log * log) +{ + if (!slang_info_log_message(log, "Error", "Out of memory.")) { + log->dont_free_text = GL_TRUE; + log->error_flag = GL_TRUE; + log->text = out_of_memory; + } +} diff --git a/dist/Mesa/src/mesa/shader/slang/slang_log.h b/dist/Mesa/src/mesa/shader/slang/slang_log.h new file mode 100644 index 000000000..dcaba0285 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_log.h @@ -0,0 +1,57 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef SLANG_LOG_H +#define SLANG_LOG_H + + +typedef struct slang_info_log_ +{ + char *text; + GLboolean dont_free_text; + GLboolean error_flag; +} slang_info_log; + + +extern void +slang_info_log_construct(slang_info_log *); + +extern void +slang_info_log_destruct(slang_info_log *); + +extern int +slang_info_log_print(slang_info_log *, const char *, ...); + +extern int +slang_info_log_error(slang_info_log *, const char *, ...); + +extern int +slang_info_log_warning(slang_info_log *, const char *, ...); + +extern void +slang_info_log_memory(slang_info_log *); + + +#endif /* SLANG_LOG_H */ diff --git a/dist/Mesa/src/mesa/shader/slang/slang_mem.c b/dist/Mesa/src/mesa/shader/slang/slang_mem.c new file mode 100644 index 000000000..e1d1e6ba1 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_mem.c @@ -0,0 +1,241 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_mem.c + * + * Memory manager for GLSL compiler. The general idea is to do all + * allocations out of a large pool then just free the pool when done + * compiling to avoid intricate malloc/free tracking and memory leaks. + * + * \author Brian Paul + */ + +#include "context.h" +#include "macros.h" +#include "slang_mem.h" + + +#define GRANULARITY 8 +#define ROUND_UP(B) ( ((B) + (GRANULARITY - 1)) & ~(GRANULARITY - 1) ) + + +/** If 1, use conventional malloc/free. Helpful for debugging */ +#define USE_MALLOC_FREE 0 + + +struct slang_mempool_ +{ + GLuint Size, Used, Count, Largest; + char *Data; + struct slang_mempool_ *Next; +}; + + +slang_mempool * +_slang_new_mempool(GLuint initialSize) +{ + slang_mempool *pool = (slang_mempool *) _mesa_calloc(sizeof(slang_mempool)); + if (pool) { + pool->Data = (char *) _mesa_calloc(initialSize); + /*printf("ALLOC MEMPOOL %d at %p\n", initialSize, pool->Data);*/ + if (!pool->Data) { + _mesa_free(pool); + return NULL; + } + pool->Size = initialSize; + pool->Used = 0; + } + return pool; +} + + +void +_slang_delete_mempool(slang_mempool *pool) +{ + GLuint total = 0; + while (pool) { + slang_mempool *next = pool->Next; + /* + printf("DELETE MEMPOOL %u / %u count=%u largest=%u\n", + pool->Used, pool->Size, pool->Count, pool->Largest); + */ + total += pool->Used; + _mesa_free(pool->Data); + _mesa_free(pool); + pool = next; + } + /*printf("TOTAL ALLOCATED: %u\n", total);*/ +} + + +#ifdef DEBUG +static void +check_zero(const char *addr, GLuint n) +{ + GLuint i; + for (i = 0; i < n; i++) { + assert(addr[i]==0); + } +} +#endif + + +#ifdef DEBUG +static GLboolean +is_valid_address(const slang_mempool *pool, void *addr) +{ + while (pool) { + if ((char *) addr >= pool->Data && + (char *) addr < pool->Data + pool->Used) + return GL_TRUE; + + pool = pool->Next; + } + return GL_FALSE; +} +#endif + + +/** + * Alloc 'bytes' from shader mempool. + */ +void * +_slang_alloc(GLuint bytes) +{ +#if USE_MALLOC_FREE + return _mesa_calloc(bytes); +#else + slang_mempool *pool; + GET_CURRENT_CONTEXT(ctx); + pool = (slang_mempool *) ctx->Shader.MemPool; + + if (bytes == 0) + bytes = 1; + + while (pool) { + if (pool->Used + bytes <= pool->Size) { + /* found room */ + void *addr = (void *) (pool->Data + pool->Used); +#ifdef DEBUG + check_zero((char*) addr, bytes); +#endif + pool->Used += ROUND_UP(bytes); + pool->Largest = MAX2(pool->Largest, bytes); + pool->Count++; + /*printf("alloc %u Used %u\n", bytes, pool->Used);*/ + return addr; + } + else if (pool->Next) { + /* try next block */ + pool = pool->Next; + } + else { + /* alloc new pool */ + const GLuint sz = MAX2(bytes, pool->Size); + pool->Next = _slang_new_mempool(sz); + if (!pool->Next) { + /* we're _really_ out of memory */ + return NULL; + } + else { + pool = pool->Next; + pool->Largest = bytes; + pool->Count++; + pool->Used = ROUND_UP(bytes); +#ifdef DEBUG + check_zero((char*) pool->Data, bytes); +#endif + return (void *) pool->Data; + } + } + } + return NULL; +#endif +} + + +void * +_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize) +{ +#if USE_MALLOC_FREE + return _mesa_realloc(oldBuffer, oldSize, newSize); +#else + GET_CURRENT_CONTEXT(ctx); + slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool; + + if (newSize < oldSize) { + return oldBuffer; + } + else { + const GLuint copySize = (oldSize < newSize) ? oldSize : newSize; + void *newBuffer = _slang_alloc(newSize); + + if (oldBuffer) + ASSERT(is_valid_address(pool, oldBuffer)); + + if (newBuffer && oldBuffer && copySize > 0) + _mesa_memcpy(newBuffer, oldBuffer, copySize); + + return newBuffer; + } +#endif +} + + +/** + * Clone string, storing in current mempool. + */ +char * +_slang_strdup(const char *s) +{ + if (s) { + size_t l = _mesa_strlen(s); + char *s2 = (char *) _slang_alloc(l + 1); + if (s2) + _mesa_strcpy(s2, s); + return s2; + } + else { + return NULL; + } +} + + +/** + * Don't actually free memory, but mark it (for debugging). + */ +void +_slang_free(void *addr) +{ +#if USE_MALLOC_FREE + _mesa_free(addr); +#else + if (addr) { + GET_CURRENT_CONTEXT(ctx); + slang_mempool *pool = (slang_mempool *) ctx->Shader.MemPool; + ASSERT(is_valid_address(pool, addr)); + } +#endif +} diff --git a/dist/Mesa/src/mesa/shader/slang/slang_mem.h b/dist/Mesa/src/mesa/shader/slang/slang_mem.h new file mode 100644 index 000000000..49885b6c9 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_mem.h @@ -0,0 +1,55 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 2005-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef SLANG_MEM_H +#define SLANG_MEM_H + + +#include "imports.h" + + +typedef struct slang_mempool_ slang_mempool; + + +extern slang_mempool * +_slang_new_mempool(GLuint initialSize); + +extern void +_slang_delete_mempool(slang_mempool *pool); + +extern void * +_slang_alloc(GLuint bytes); + +extern void * +_slang_realloc(void *oldBuffer, GLuint oldSize, GLuint newSize); + +extern char * +_slang_strdup(const char *s); + +extern void +_slang_free(void *addr); + + +#endif diff --git a/dist/Mesa/src/mesa/shader/slang/slang_print.c b/dist/Mesa/src/mesa/shader/slang/slang_print.c new file mode 100644 index 000000000..f3e127cb1 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_print.c @@ -0,0 +1,813 @@ + +/** + * Dump/print a slang_operation tree + */ + + +#include "imports.h" +#include "slang_compile.h" +#include "slang_print.h" + + +static void +spaces(int n) +{ + while (n--) + printf(" "); +} + + +static void +print_type(const slang_fully_specified_type *t) +{ + switch (t->qualifier) { + case SLANG_QUAL_NONE: + /*printf("");*/ + break; + case SLANG_QUAL_CONST: + printf("const "); + break; + case SLANG_QUAL_ATTRIBUTE: + printf("attrib "); + break; + case SLANG_QUAL_VARYING: + printf("varying "); + break; + case SLANG_QUAL_UNIFORM: + printf("uniform "); + break; + case SLANG_QUAL_OUT: + printf("output "); + break; + case SLANG_QUAL_INOUT: + printf("inout "); + break; + case SLANG_QUAL_FIXEDOUTPUT: + printf("fixedoutput"); + break; + case SLANG_QUAL_FIXEDINPUT: + printf("fixedinput"); + break; + default: + printf("unknown qualifer!"); + } + + switch (t->specifier.type) { + case SLANG_SPEC_VOID: + printf("void"); + break; + case SLANG_SPEC_BOOL: + printf("bool"); + break; + case SLANG_SPEC_BVEC2: + printf("bvec2"); + break; + case SLANG_SPEC_BVEC3: + printf("bvec3"); + break; + case SLANG_SPEC_BVEC4: + printf("bvec4"); + break; + case SLANG_SPEC_INT: + printf("int"); + break; + case SLANG_SPEC_IVEC2: + printf("ivec2"); + break; + case SLANG_SPEC_IVEC3: + printf("ivec3"); + break; + case SLANG_SPEC_IVEC4: + printf("ivec4"); + break; + case SLANG_SPEC_FLOAT: + printf("float"); + break; + case SLANG_SPEC_VEC2: + printf("vec2"); + break; + case SLANG_SPEC_VEC3: + printf("vec3"); + break; + case SLANG_SPEC_VEC4: + printf("vec4"); + break; + case SLANG_SPEC_MAT2: + printf("mat2"); + break; + case SLANG_SPEC_MAT3: + printf("mat3"); + break; + case SLANG_SPEC_MAT4: + printf("mat4"); + break; + case SLANG_SPEC_MAT23: + printf("mat2x3"); + break; + case SLANG_SPEC_MAT32: + printf("mat3x2"); + break; + case SLANG_SPEC_MAT24: + printf("mat2x4"); + break; + case SLANG_SPEC_MAT42: + printf("mat4x2"); + break; + case SLANG_SPEC_MAT34: + printf("mat3x4"); + break; + case SLANG_SPEC_MAT43: + printf("mat4x3"); + break; + case SLANG_SPEC_SAMPLER1D: + printf("sampler1D"); + break; + case SLANG_SPEC_SAMPLER2D: + printf("sampler2D"); + break; + case SLANG_SPEC_SAMPLER3D: + printf("sampler3D"); + break; + case SLANG_SPEC_SAMPLERCUBE: + printf("samplerCube"); + break; + case SLANG_SPEC_SAMPLER1DSHADOW: + printf("sampler1DShadow"); + break; + case SLANG_SPEC_SAMPLER2DSHADOW: + printf("sampler2DShadow"); + break; + case SLANG_SPEC_STRUCT: + printf("struct"); + break; + case SLANG_SPEC_ARRAY: + printf("array"); + break; + default: + printf("unknown type"); + } + /*printf("\n");*/ +} + + +static void +print_variable(const slang_variable *v, int indent) +{ + spaces(indent); + printf("VAR "); + print_type(&v->type); + printf(" %s", (char *) v->a_name); + if (v->initializer) { + printf(" :=\n"); + slang_print_tree(v->initializer, indent + 3); + } + else { + printf(";\n"); + } +} + + +static void +print_binary(const slang_operation *op, const char *oper, int indent) +{ + assert(op->num_children == 2); + slang_print_tree(&op->children[0], indent + 3); + spaces(indent); + printf("%s\n", oper); + slang_print_tree(&op->children[1], indent + 3); +} + + +static void +print_generic2(const slang_operation *op, const char *oper, + const char *s, int indent) +{ + int i; + if (oper) { + spaces(indent); + printf("[%p locals %p] %s %s\n", (void*) op, (void*) op->locals, oper, s); + } + for (i = 0; i < op->num_children; i++) { + spaces(indent); + printf("//child %d:\n", i); + slang_print_tree(&op->children[i], indent); + } +} + +static void +print_generic(const slang_operation *op, const char *oper, int indent) +{ + print_generic2(op, oper, "", indent); +} + + +static const slang_variable_scope * +find_scope(const slang_variable_scope *s, slang_atom name) +{ + GLuint i; + for (i = 0; i < s->num_variables; i++) { + if (s->variables[i]->a_name == name) + return s; + } + if (s->outer_scope) + return find_scope(s->outer_scope, name); + else + return NULL; +} + +static const slang_variable * +find_var(const slang_variable_scope *s, slang_atom name) +{ + GLuint i; + for (i = 0; i < s->num_variables; i++) { + if (s->variables[i]->a_name == name) + return s->variables[i]; + } + if (s->outer_scope) + return find_var(s->outer_scope, name); + else + return NULL; +} + + +void +slang_print_tree(const slang_operation *op, int indent) +{ + int i; + + switch (op->type) { + + case SLANG_OPER_NONE: + spaces(indent); + printf("SLANG_OPER_NONE\n"); + break; + + case SLANG_OPER_BLOCK_NO_NEW_SCOPE: + spaces(indent); + printf("{ locals %p outer %p\n", (void*)op->locals, (void*)op->locals->outer_scope); + print_generic(op, NULL, indent+3); + spaces(indent); + printf("}\n"); + break; + + case SLANG_OPER_BLOCK_NEW_SCOPE: + spaces(indent); + printf("{{ // new scope locals %p\n", (void*)op->locals); + print_generic(op, NULL, indent+3); + spaces(indent); + printf("}}\n"); + break; + + case SLANG_OPER_VARIABLE_DECL: + assert(op->num_children == 0 || op->num_children == 1); + { + slang_variable *v; + v = _slang_locate_variable(op->locals, op->a_id, GL_TRUE); + if (v) { + spaces(indent); + printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope); + print_type(&v->type); + printf(" %s (%p)", (char *) op->a_id, + (void *) find_var(op->locals, op->a_id)); + + printf(" (in scope %p) ", + (void *) find_scope(op->locals, op->a_id)); + if (op->num_children == 1) { + printf(" :=\n"); + slang_print_tree(&op->children[0], indent + 3); + } + else if (v->initializer) { + printf(" := INITIALIZER\n"); + slang_print_tree(v->initializer, indent + 3); + } + else { + printf(";\n"); + } + /* + spaces(indent); + printf("TYPE: "); + print_type(&v->type); + spaces(indent); + printf("ADDR: %d size: %d\n", v->address, v->size); + */ + } + else { + spaces(indent); + printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id); + } + } + break; + + case SLANG_OPER_ASM: + spaces(indent); + printf("ASM: %s\n", (char*) op->a_id); + print_generic(op, NULL, indent+3); + break; + + case SLANG_OPER_BREAK: + spaces(indent); + printf("BREAK\n"); + break; + + case SLANG_OPER_CONTINUE: + spaces(indent); + printf("CONTINUE\n"); + break; + + case SLANG_OPER_DISCARD: + spaces(indent); + printf("DISCARD\n"); + break; + + case SLANG_OPER_RETURN: + spaces(indent); + printf("RETURN\n"); + if (op->num_children > 0) + slang_print_tree(&op->children[0], indent + 3); + break; + + case SLANG_OPER_LABEL: + spaces(indent); + printf("LABEL %s\n", (char *) op->a_id); + break; + + case SLANG_OPER_EXPRESSION: + spaces(indent); + printf("EXPR: locals %p\n", (void*) op->locals); + /*print_generic(op, "SLANG_OPER_EXPRESSION", indent);*/ + slang_print_tree(&op->children[0], indent + 3); + break; + + case SLANG_OPER_IF: + spaces(indent); + printf("IF\n"); + slang_print_tree(&op->children[0], indent + 3); + spaces(indent); + printf("THEN\n"); + slang_print_tree(&op->children[1], indent + 3); + spaces(indent); + printf("ELSE\n"); + slang_print_tree(&op->children[2], indent + 3); + spaces(indent); + printf("ENDIF\n"); + break; + + case SLANG_OPER_WHILE: + assert(op->num_children == 2); + spaces(indent); + printf("WHILE cond:\n"); + slang_print_tree(&op->children[0], indent + 3); + spaces(indent); + printf("WHILE body:\n"); + slang_print_tree(&op->children[1], indent + 3); + break; + + case SLANG_OPER_DO: + spaces(indent); + printf("DO body:\n"); + slang_print_tree(&op->children[0], indent + 3); + spaces(indent); + printf("DO cond:\n"); + slang_print_tree(&op->children[1], indent + 3); + break; + + case SLANG_OPER_FOR: + spaces(indent); + printf("FOR init:\n"); + slang_print_tree(&op->children[0], indent + 3); + spaces(indent); + printf("FOR while:\n"); + slang_print_tree(&op->children[1], indent + 3); + spaces(indent); + printf("FOR step:\n"); + slang_print_tree(&op->children[2], indent + 3); + spaces(indent); + printf("FOR body:\n"); + slang_print_tree(&op->children[3], indent + 3); + spaces(indent); + printf("ENDFOR\n"); + /* + print_generic(op, "FOR", indent + 3); + */ + break; + + case SLANG_OPER_VOID: + spaces(indent); + printf("(oper-void)\n"); + break; + + case SLANG_OPER_LITERAL_BOOL: + spaces(indent); + printf("LITERAL ("); + for (i = 0; i < op->literal_size; i++) + printf("%s ", op->literal[0] ? "TRUE" : "FALSE"); + printf(")\n"); + + break; + + case SLANG_OPER_LITERAL_INT: + spaces(indent); + printf("LITERAL ("); + for (i = 0; i < op->literal_size; i++) + printf("%d ", (int) op->literal[i]); + printf(")\n"); + break; + + case SLANG_OPER_LITERAL_FLOAT: + spaces(indent); + printf("LITERAL ("); + for (i = 0; i < op->literal_size; i++) + printf("%f ", op->literal[i]); + printf(")\n"); + break; + + case SLANG_OPER_IDENTIFIER: + spaces(indent); + if (op->var && op->var->a_name) + printf("VAR %s (in scope %p)\n", (char *) op->var->a_name, + (void *) find_scope(op->locals, op->a_id)); + else + printf("VAR' %s (in scope %p)\n", (char *) op->a_id, + (void *) find_scope(op->locals, op->a_id)); + break; + + case SLANG_OPER_SEQUENCE: + print_generic(op, "COMMA-SEQ", indent+3); + break; + + case SLANG_OPER_ASSIGN: + spaces(indent); + printf("ASSIGNMENT locals %p\n", (void*)op->locals); + print_binary(op, ":=", indent); + break; + + case SLANG_OPER_ADDASSIGN: + spaces(indent); + printf("ASSIGN\n"); + print_binary(op, "+=", indent); + break; + + case SLANG_OPER_SUBASSIGN: + spaces(indent); + printf("ASSIGN\n"); + print_binary(op, "-=", indent); + break; + + case SLANG_OPER_MULASSIGN: + spaces(indent); + printf("ASSIGN\n"); + print_binary(op, "*=", indent); + break; + + case SLANG_OPER_DIVASSIGN: + spaces(indent); + printf("ASSIGN\n"); + print_binary(op, "/=", indent); + break; + + /*SLANG_OPER_MODASSIGN,*/ + /*SLANG_OPER_LSHASSIGN,*/ + /*SLANG_OPER_RSHASSIGN,*/ + /*SLANG_OPER_ORASSIGN,*/ + /*SLANG_OPER_XORASSIGN,*/ + /*SLANG_OPER_ANDASSIGN,*/ + case SLANG_OPER_SELECT: + spaces(indent); + printf("SLANG_OPER_SELECT n=%d\n", op->num_children); + assert(op->num_children == 3); + slang_print_tree(&op->children[0], indent+3); + spaces(indent); + printf("?\n"); + slang_print_tree(&op->children[1], indent+3); + spaces(indent); + printf(":\n"); + slang_print_tree(&op->children[2], indent+3); + break; + + case SLANG_OPER_LOGICALOR: + print_binary(op, "||", indent); + break; + + case SLANG_OPER_LOGICALXOR: + print_binary(op, "^^", indent); + break; + + case SLANG_OPER_LOGICALAND: + print_binary(op, "&&", indent); + break; + + /*SLANG_OPER_BITOR*/ + /*SLANG_OPER_BITXOR*/ + /*SLANG_OPER_BITAND*/ + case SLANG_OPER_EQUAL: + print_binary(op, "==", indent); + break; + + case SLANG_OPER_NOTEQUAL: + print_binary(op, "!=", indent); + break; + + case SLANG_OPER_LESS: + print_binary(op, "<", indent); + break; + + case SLANG_OPER_GREATER: + print_binary(op, ">", indent); + break; + + case SLANG_OPER_LESSEQUAL: + print_binary(op, "<=", indent); + break; + + case SLANG_OPER_GREATEREQUAL: + print_binary(op, ">=", indent); + break; + + /*SLANG_OPER_LSHIFT*/ + /*SLANG_OPER_RSHIFT*/ + case SLANG_OPER_ADD: + print_binary(op, "+", indent); + break; + + case SLANG_OPER_SUBTRACT: + print_binary(op, "-", indent); + break; + + case SLANG_OPER_MULTIPLY: + print_binary(op, "*", indent); + break; + + case SLANG_OPER_DIVIDE: + print_binary(op, "/", indent); + break; + + /*SLANG_OPER_MODULUS*/ + case SLANG_OPER_PREINCREMENT: + spaces(indent); + printf("PRE++\n"); + slang_print_tree(&op->children[0], indent+3); + break; + + case SLANG_OPER_PREDECREMENT: + spaces(indent); + printf("PRE--\n"); + slang_print_tree(&op->children[0], indent+3); + break; + + case SLANG_OPER_PLUS: + spaces(indent); + printf("SLANG_OPER_PLUS\n"); + break; + + case SLANG_OPER_MINUS: + spaces(indent); + printf("SLANG_OPER_MINUS\n"); + break; + + /*SLANG_OPER_COMPLEMENT*/ + case SLANG_OPER_NOT: + spaces(indent); + printf("NOT\n"); + slang_print_tree(&op->children[0], indent+3); + break; + + case SLANG_OPER_SUBSCRIPT: + spaces(indent); + printf("SLANG_OPER_SUBSCRIPT\n"); + print_generic(op, NULL, indent+3); + break; + + case SLANG_OPER_CALL: +#if 0 + slang_function *fun + = _slang_locate_function(A->space.funcs, oper->a_id, + oper->children, + oper->num_children, &A->space, A->atoms); +#endif + spaces(indent); + printf("CALL %s(\n", (char *) op->a_id); + for (i = 0; i < op->num_children; i++) { + slang_print_tree(&op->children[i], indent+3); + if (i + 1 < op->num_children) { + spaces(indent + 3); + printf(",\n"); + } + } + spaces(indent); + printf(")\n"); + break; + + case SLANG_OPER_FIELD: + spaces(indent); + printf("FIELD %s of\n", (char*) op->a_id); + slang_print_tree(&op->children[0], indent+3); + break; + + case SLANG_OPER_POSTINCREMENT: + spaces(indent); + printf("POST++\n"); + slang_print_tree(&op->children[0], indent+3); + break; + + case SLANG_OPER_POSTDECREMENT: + spaces(indent); + printf("POST--\n"); + slang_print_tree(&op->children[0], indent+3); + break; + + default: + printf("unknown op->type %d\n", (int) op->type); + } + +} + + + +void +slang_print_function(const slang_function *f, GLboolean body) +{ + int i; + +#if 0 + if (_mesa_strcmp((char *) f->header.a_name, "main") != 0) + return; +#endif + + printf("FUNCTION %s (\n", + (char *) f->header.a_name); + + for (i = 0; i < f->param_count; i++) { + print_variable(f->parameters->variables[i], 3); + } + + printf(")\n"); + if (body && f->body) + slang_print_tree(f->body, 0); +} + + + + + +const char * +slang_type_qual_string(slang_type_qualifier q) +{ + switch (q) { + case SLANG_QUAL_NONE: + return "none"; + case SLANG_QUAL_CONST: + return "const"; + case SLANG_QUAL_ATTRIBUTE: + return "attribute"; + case SLANG_QUAL_VARYING: + return "varying"; + case SLANG_QUAL_UNIFORM: + return "uniform"; + case SLANG_QUAL_OUT: + return "out"; + case SLANG_QUAL_INOUT: + return "inout"; + case SLANG_QUAL_FIXEDOUTPUT: + return "fixedoutput"; + case SLANG_QUAL_FIXEDINPUT: + return "fixedinputk"; + default: + return "qual?"; + } +} + + +static const char * +slang_type_string(slang_type_specifier_type t) +{ + switch (t) { + case SLANG_SPEC_VOID: + return "void"; + case SLANG_SPEC_BOOL: + return "bool"; + case SLANG_SPEC_BVEC2: + return "bvec2"; + case SLANG_SPEC_BVEC3: + return "bvec3"; + case SLANG_SPEC_BVEC4: + return "bvec4"; + case SLANG_SPEC_INT: + return "int"; + case SLANG_SPEC_IVEC2: + return "ivec2"; + case SLANG_SPEC_IVEC3: + return "ivec3"; + case SLANG_SPEC_IVEC4: + return "ivec4"; + case SLANG_SPEC_FLOAT: + return "float"; + case SLANG_SPEC_VEC2: + return "vec2"; + case SLANG_SPEC_VEC3: + return "vec3"; + case SLANG_SPEC_VEC4: + return "vec4"; + case SLANG_SPEC_MAT2: + return "mat2"; + case SLANG_SPEC_MAT3: + return "mat3"; + case SLANG_SPEC_MAT4: + return "mat4"; + case SLANG_SPEC_SAMPLER1D: + return "sampler1D"; + case SLANG_SPEC_SAMPLER2D: + return "sampler2D"; + case SLANG_SPEC_SAMPLER3D: + return "sampler3D"; + case SLANG_SPEC_SAMPLERCUBE: + return "samplerCube"; + case SLANG_SPEC_SAMPLER1DSHADOW: + return "sampler1DShadow"; + case SLANG_SPEC_SAMPLER2DSHADOW: + return "sampler2DShadow"; + case SLANG_SPEC_SAMPLER2DRECT: + return "sampler2DRect"; + case SLANG_SPEC_SAMPLER2DRECTSHADOW: + return "sampler2DRectShadow"; + case SLANG_SPEC_STRUCT: + return "struct"; + case SLANG_SPEC_ARRAY: + return "array"; + default: + return "type?"; + } +} + + +static const char * +slang_fq_type_string(const slang_fully_specified_type *t) +{ + static char str[1000]; + sprintf(str, "%s %s", slang_type_qual_string(t->qualifier), + slang_type_string(t->specifier.type)); + return str; +} + + +void +slang_print_type(const slang_fully_specified_type *t) +{ + printf("%s %s", slang_type_qual_string(t->qualifier), + slang_type_string(t->specifier.type)); +} + + +#if 0 +static char * +slang_var_string(const slang_variable *v) +{ + static char str[1000]; + sprintf(str, "%s : %s", + (char *) v->a_name, + slang_fq_type_string(&v->type)); + return str; +} +#endif + + +void +slang_print_variable(const slang_variable *v) +{ + printf("Name: %s\n", (char *) v->a_name); + printf("Type: %s\n", slang_fq_type_string(&v->type)); +} + + +void +_slang_print_var_scope(const slang_variable_scope *vars, int indent) +{ + GLuint i; + + spaces(indent); + printf("Var scope %p %d vars:\n", (void *) vars, vars->num_variables); + for (i = 0; i < vars->num_variables; i++) { + spaces(indent + 3); + printf("%s (at %p)\n", (char *) vars->variables[i]->a_name, (void*) (vars->variables + i)); + } + spaces(indent + 3); + printf("outer_scope = %p\n", (void*) vars->outer_scope); + + if (vars->outer_scope) { + /*spaces(indent + 3);*/ + _slang_print_var_scope(vars->outer_scope, indent + 3); + } +} + + + +int +slang_checksum_tree(const slang_operation *op) +{ + int s = op->num_children; + int i; + + for (i = 0; i < op->num_children; i++) { + s += slang_checksum_tree(&op->children[i]); + } + return s; +} diff --git a/dist/Mesa/src/mesa/shader/slang/slang_print.h b/dist/Mesa/src/mesa/shader/slang/slang_print.h new file mode 100644 index 000000000..46605c806 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_print.h @@ -0,0 +1,29 @@ + + +#ifndef SLANG_PRINT +#define SLANG_PRINT + +extern void +slang_print_function(const slang_function *f, GLboolean body); + +extern void +slang_print_tree(const slang_operation *op, int indent); + +extern const char * +slang_type_qual_string(slang_type_qualifier q); + +extern void +slang_print_type(const slang_fully_specified_type *t); + +extern void +slang_print_variable(const slang_variable *v); + +extern void +_slang_print_var_scope(const slang_variable_scope *s, int indent); + + +extern int +slang_checksum_tree(const slang_operation *op); + +#endif /* SLANG_PRINT */ + diff --git a/dist/Mesa/src/mesa/shader/slang/slang_simplify.c b/dist/Mesa/src/mesa/shader/slang/slang_simplify.c new file mode 100644 index 000000000..21d004db8 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_simplify.c @@ -0,0 +1,449 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_assemble_typeinfo.c + * slang type info + * \author Michal Krol + */ + +#include "imports.h" +#include "macros.h" +#include "get.h" +#include "slang_compile.h" +#include "slang_codegen.h" +#include "slang_simplify.h" +#include "slang_print.h" + + + + +/** + * Lookup the value of named constant, such as gl_MaxLights. + * \return value of constant, or -1 if unknown + */ +GLint +_slang_lookup_constant(const char *name) +{ + struct constant_info { + const char *Name; + const GLenum Token; + }; + static const struct constant_info info[] = { + { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES }, + { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS }, + { "gl_MaxDrawBuffers", GL_MAX_DRAW_BUFFERS }, + { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS }, + { "gl_MaxLights", GL_MAX_LIGHTS }, + { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS }, + { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS }, + { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS }, + { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS }, + { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS }, + { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS }, + { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS }, + { NULL, 0 } + }; + GLuint i; + + for (i = 0; info[i].Name; i++) { + if (strcmp(info[i].Name, name) == 0) { + /* found */ + GLint value = -1.0; + _mesa_GetIntegerv(info[i].Token, &value); + ASSERT(value >= 0); /* sanity check that glGetFloatv worked */ + return value; + } + } + return -1; +} + + + +/** + * Recursively traverse an AST tree, applying simplifications wherever + * possible. + * At the least, we do constant folding. We need to do that much so that + * compile-time expressions can be evaluated for things like array + * declarations. I.e.: float foo[3 + 5]; + */ +void +_slang_simplify(slang_operation *oper, + const slang_name_space * space, + slang_atom_pool * atoms) +{ + GLboolean isFloat[4]; + GLboolean isBool[4]; + GLuint i, n; + + if (oper->type == SLANG_OPER_IDENTIFIER) { + /* see if it's a named constant */ + GLint value = _slang_lookup_constant((char *) oper->a_id); + if (value >= 0) { + oper->literal[0] = + oper->literal[1] = + oper->literal[2] = + oper->literal[3] = value; + oper->type = SLANG_OPER_LITERAL_INT; + return; + } + } + + /* first, simplify children */ + for (i = 0; i < oper->num_children; i++) { + _slang_simplify(&oper->children[i], space, atoms); + } + + /* examine children */ + n = MIN2(oper->num_children, 4); + for (i = 0; i < n; i++) { + isFloat[i] = (oper->children[i].type == SLANG_OPER_LITERAL_FLOAT || + oper->children[i].type == SLANG_OPER_LITERAL_INT); + isBool[i] = (oper->children[i].type == SLANG_OPER_LITERAL_BOOL); + } + + if (oper->num_children == 2 && isFloat[0] && isFloat[1]) { + /* probably simple arithmetic */ + switch (oper->type) { + case SLANG_OPER_ADD: + for (i = 0; i < 4; i++) { + oper->literal[i] + = oper->children[0].literal[i] + oper->children[1].literal[i]; + } + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_FLOAT; + return; + case SLANG_OPER_SUBTRACT: + for (i = 0; i < 4; i++) { + oper->literal[i] + = oper->children[0].literal[i] - oper->children[1].literal[i]; + } + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_FLOAT; + return; + case SLANG_OPER_MULTIPLY: + for (i = 0; i < 4; i++) { + oper->literal[i] + = oper->children[0].literal[i] * oper->children[1].literal[i]; + } + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_FLOAT; + return; + case SLANG_OPER_DIVIDE: + for (i = 0; i < 4; i++) { + oper->literal[i] + = oper->children[0].literal[i] / oper->children[1].literal[i]; + } + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_FLOAT; + return; + default: + ; /* nothing */ + } + } + + if (oper->num_children == 1 && isFloat[0]) { + switch (oper->type) { + case SLANG_OPER_MINUS: + for (i = 0; i < 4; i++) { + oper->literal[i] = -oper->children[0].literal[i]; + } + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_FLOAT; + return; + case SLANG_OPER_PLUS: + COPY_4V(oper->literal, oper->children[0].literal); + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_FLOAT; + return; + default: + ; /* nothing */ + } + } + + if (oper->num_children == 2 && isBool[0] && isBool[1]) { + /* simple boolean expression */ + switch (oper->type) { + case SLANG_OPER_LOGICALAND: + for (i = 0; i < 4; i++) { + const GLint a = oper->children[0].literal[i] ? 1 : 0; + const GLint b = oper->children[1].literal[i] ? 1 : 0; + oper->literal[i] = (GLfloat) (a && b); + } + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_BOOL; + return; + case SLANG_OPER_LOGICALOR: + for (i = 0; i < 4; i++) { + const GLint a = oper->children[0].literal[i] ? 1 : 0; + const GLint b = oper->children[1].literal[i] ? 1 : 0; + oper->literal[i] = (GLfloat) (a || b); + } + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_BOOL; + return; + case SLANG_OPER_LOGICALXOR: + for (i = 0; i < 4; i++) { + const GLint a = oper->children[0].literal[i] ? 1 : 0; + const GLint b = oper->children[1].literal[i] ? 1 : 0; + oper->literal[i] = (GLfloat) (a ^ b); + } + oper->literal_size = oper->children[0].literal_size; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_BOOL; + return; + default: + ; /* nothing */ + } + } + + if (oper->num_children == 4 + && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) { + /* vec4(flt, flt, flt, flt) constructor */ + if (oper->type == SLANG_OPER_CALL) { + if (strcmp((char *) oper->a_id, "vec4") == 0) { + oper->literal[0] = oper->children[0].literal[0]; + oper->literal[1] = oper->children[1].literal[0]; + oper->literal[2] = oper->children[2].literal[0]; + oper->literal[3] = oper->children[3].literal[0]; + oper->literal_size = 4; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_FLOAT; + return; + } + } + } + + if (oper->num_children == 3 && isFloat[0] && isFloat[1] && isFloat[2]) { + /* vec3(flt, flt, flt) constructor */ + if (oper->type == SLANG_OPER_CALL) { + if (strcmp((char *) oper->a_id, "vec3") == 0) { + oper->literal[0] = oper->children[0].literal[0]; + oper->literal[1] = oper->children[1].literal[0]; + oper->literal[2] = oper->children[2].literal[0]; + oper->literal[3] = oper->literal[2]; + oper->literal_size = 3; + slang_operation_destruct(oper); + oper->type = SLANG_OPER_LITERAL_FLOAT; + return; + } + } + } + + if (oper->num_children == 2 && isFloat[0] && isFloat[1]) { + /* vec2(flt, flt) constructor */ + if (oper->type == SLANG_OPER_CALL) { + if (strcmp((char *) oper->a_id, "vec2") == 0) { + oper->literal[0] = oper->children[0].literal[0]; + oper->literal[1] = oper->children[1].literal[0]; + oper->literal[2] = oper->literal[1]; + oper->literal[3] = oper->literal[1]; + oper->literal_size = 2; + slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */ + oper->type = SLANG_OPER_LITERAL_FLOAT; + assert(oper->num_children == 0); + return; + } + } + } + + if (oper->num_children == 1 && isFloat[0]) { + /* vec2/3/4(flt, flt) constructor */ + if (oper->type == SLANG_OPER_CALL) { + const char *func = (const char *) oper->a_id; + if (strncmp(func, "vec", 3) == 0 && func[3] >= '2' && func[3] <= '4') { + oper->literal[0] = + oper->literal[1] = + oper->literal[2] = + oper->literal[3] = oper->children[0].literal[0]; + oper->literal_size = func[3] - '0'; + assert(oper->literal_size >= 2); + assert(oper->literal_size <= 4); + slang_operation_destruct(oper); /* XXX oper->locals goes NULL! */ + oper->type = SLANG_OPER_LITERAL_FLOAT; + assert(oper->num_children == 0); + return; + } + } + } +} + + + +/** + * Adapt the arguments for a function call to match the parameters of + * the given function. + * This is for: + * 1. converting/casting argument types to match parameters + * 2. breaking up vector/matrix types into individual components to + * satisfy constructors. + */ +GLboolean +_slang_adapt_call(slang_operation *callOper, const slang_function *fun, + const slang_name_space * space, + slang_atom_pool * atoms, slang_info_log *log) +{ + const GLboolean haveRetValue = _slang_function_has_return_value(fun); + const int numParams = fun->param_count - haveRetValue; + int i; + int dbg = 0; + + if (dbg) printf("Adapt %d args to %d parameters\n", + callOper->num_children, numParams); + + /* Only try adapting for constructors */ + if (fun->kind != SLANG_FUNC_CONSTRUCTOR) + return GL_FALSE; + + if (callOper->num_children != numParams) { + /* number of arguments doesn't match number of parameters */ + + if (fun->kind == SLANG_FUNC_CONSTRUCTOR) { + /* For constructor calls, we can try to unroll vector/matrix args + * into individual floats/ints and try to match the function params. + */ + for (i = 0; i < numParams; i++) { + slang_typeinfo argType; + GLint argSz, j; + + /* Get type of arg[i] */ + if (!slang_typeinfo_construct(&argType)) + return GL_FALSE; + if (!_slang_typeof_operation_(&callOper->children[i], space, + &argType, atoms, log)) { + slang_typeinfo_destruct(&argType); + return GL_FALSE; + } + + /* + paramSz = _slang_sizeof_type_specifier(¶mVar->type.specifier); + assert(paramSz == 1); + */ + argSz = _slang_sizeof_type_specifier(&argType.spec); + if (argSz > 1) { + slang_operation origArg; + /* break up arg[i] into components */ + if (dbg) + printf("Break up arg %d from 1 to %d elements\n", i, argSz); + + slang_operation_construct(&origArg); + slang_operation_copy(&origArg, + &callOper->children[i]); + + /* insert argSz-1 new children/args */ + for (j = 0; j < argSz - 1; j++) { + (void) slang_operation_insert(&callOper->num_children, + &callOper->children, i); + } + + /* replace arg[i+j] with subscript/index oper */ + for (j = 0; j < argSz; j++) { + callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT; + callOper->children[i + j].num_children = 2; + callOper->children[i + j].children = slang_operation_new(2); + slang_operation_copy(&callOper->children[i + j].children[0], + &origArg); + callOper->children[i + j].children[1].type + = SLANG_OPER_LITERAL_INT; + callOper->children[i + j].children[1].literal[0] = j; + } + + } + } /* for i */ + } + else { + /* non-constructor function: number of args must match number + * of function params. + */ + return GL_FALSE; /* caller will record an error msg */ + } + } + + if (callOper->num_children < numParams) { + /* still not enough args for all params */ + return GL_FALSE; + } + else if (callOper->num_children > numParams) { + /* now too many arguments */ + /* XXX this isn't always an error, see spec */ + return GL_FALSE; + } + + /* + * Second phase, argument casting. + * Example: + * void foo(int i, bool b) {} + * x = foo(3.15, 9); + * Gets translated into: + * x = foo(int(3.15), bool(9)) + */ + for (i = 0; i < numParams; i++) { + slang_typeinfo argType; + slang_variable *paramVar = fun->parameters->variables[i]; + + /* Get type of arg[i] */ + if (!slang_typeinfo_construct(&argType)) + return GL_FALSE; + if (!_slang_typeof_operation_(&callOper->children[i], space, + &argType, atoms, log)) { + slang_typeinfo_destruct(&argType); + return GL_FALSE; + } + + /* see if arg type matches parameter type */ + if (!slang_type_specifier_equal(&argType.spec, + ¶mVar->type.specifier)) { + /* need to adapt arg type to match param type */ + const char *constructorName = + slang_type_specifier_type_to_string(paramVar->type.specifier.type); + slang_operation *child = slang_operation_new(1); + + slang_operation_copy(child, &callOper->children[i]); + child->locals->outer_scope = callOper->children[i].locals; + + callOper->children[i].type = SLANG_OPER_CALL; + callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName); + callOper->children[i].num_children = 1; + callOper->children[i].children = child; + } + + slang_typeinfo_destruct(&argType); + } + + if (dbg) { + printf("===== New call to %s with adapted arguments ===============\n", + (char*) fun->header.a_name); + slang_print_tree(callOper, 5); + } + + return GL_TRUE; +} diff --git a/dist/Mesa/src/mesa/shader/slang/slang_simplify.h b/dist/Mesa/src/mesa/shader/slang/slang_simplify.h new file mode 100644 index 000000000..b3840ee9d --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_simplify.h @@ -0,0 +1,22 @@ + +#ifndef SLANG_SIMPLIFY_H +#define SLANG_SIMPLIFY_H + + +extern GLint +_slang_lookup_constant(const char *name); + + +extern void +_slang_simplify(slang_operation *oper, + const slang_name_space * space, + slang_atom_pool * atoms); + + +extern GLboolean +_slang_adapt_call(slang_operation *callOper, const slang_function *fun, + const slang_name_space * space, + slang_atom_pool * atoms, slang_info_log *log); + + +#endif /* SLANG_SIMPLIFY_H */ diff --git a/dist/Mesa/src/mesa/shader/slang/slang_typeinfo.c b/dist/Mesa/src/mesa/shader/slang/slang_typeinfo.c new file mode 100644 index 000000000..da0b32bc4 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_typeinfo.c @@ -0,0 +1,1022 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file slang_assemble_typeinfo.c + * slang type info + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_typeinfo.h" +#include "slang_compile.h" +#include "slang_log.h" +#include "slang_mem.h" +#include "prog_instruction.h" + + +/** + * Checks if a field selector is a general swizzle (an r-value swizzle + * with replicated components or an l-value swizzle mask) for a + * vector. Returns GL_TRUE if this is the case, <swz> is filled with + * swizzle information. Returns GL_FALSE otherwise. + */ +GLboolean +_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz) +{ + GLuint i; + GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE; + + /* init to undefined. + * We rely on undefined/nil values to distinguish between + * regular swizzles and writemasks. + * For example, the swizzle ".xNNN" is the writemask ".x". + * That's different than the swizzle ".xxxx". + */ + for (i = 0; i < 4; i++) + swz->swizzle[i] = SWIZZLE_NIL; + + /* the swizzle can be at most 4-component long */ + swz->num_components = slang_string_length(field); + if (swz->num_components > 4) + return GL_FALSE; + + for (i = 0; i < swz->num_components; i++) { + /* mark which swizzle group is used */ + switch (field[i]) { + case 'x': + case 'y': + case 'z': + case 'w': + xyzw = GL_TRUE; + break; + case 'r': + case 'g': + case 'b': + case 'a': + rgba = GL_TRUE; + break; + case 's': + case 't': + case 'p': + case 'q': + stpq = GL_TRUE; + break; + default: + return GL_FALSE; + } + + /* collect swizzle component */ + switch (field[i]) { + case 'x': + case 'r': + case 's': + swz->swizzle[i] = 0; + break; + case 'y': + case 'g': + case 't': + swz->swizzle[i] = 1; + break; + case 'z': + case 'b': + case 'p': + swz->swizzle[i] = 2; + break; + case 'w': + case 'a': + case 'q': + swz->swizzle[i] = 3; + break; + } + + /* check if the component is valid for given vector's row count */ + if (rows <= swz->swizzle[i]) + return GL_FALSE; + } + + /* only one swizzle group can be used */ + if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq)) + return GL_FALSE; + + return GL_TRUE; +} + + + +/** + * Checks if a general swizzle is an l-value swizzle - these swizzles + * do not have duplicated fields. Returns GL_TRUE if this is a + * swizzle mask. Returns GL_FALSE otherwise + */ +GLboolean +_slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows) +{ + GLuint i, c = 0; + + /* the swizzle may not be longer than the vector dim */ + if (swz->num_components > rows) + return GL_FALSE; + + /* the swizzle components cannot be duplicated */ + for (i = 0; i < swz->num_components; i++) { + if ((c & (1 << swz->swizzle[i])) != 0) + return GL_FALSE; + c |= 1 << swz->swizzle[i]; + } + + return GL_TRUE; +} + + +/** + * Combines (multiplies) two swizzles to form single swizzle. + * Example: "vec.wzyx.yx" --> "vec.zw". + */ +GLvoid +_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left, + const slang_swizzle * right) +{ + GLuint i; + + dst->num_components = right->num_components; + for (i = 0; i < right->num_components; i++) + dst->swizzle[i] = left->swizzle[right->swizzle[i]]; +} + + +GLvoid +slang_type_specifier_ctr(slang_type_specifier * self) +{ + self->type = SLANG_SPEC_VOID; + self->_struct = NULL; + self->_array = NULL; +} + +GLvoid +slang_type_specifier_dtr(slang_type_specifier * self) +{ + if (self->_struct != NULL) { + slang_struct_destruct(self->_struct); + _slang_free(self->_struct); + } + if (self->_array != NULL) { + slang_type_specifier_dtr(self->_array); + _slang_free(self->_array); + } +} + +GLboolean +slang_type_specifier_copy(slang_type_specifier * x, + const slang_type_specifier * y) +{ + slang_type_specifier z; + + slang_type_specifier_ctr(&z); + z.type = y->type; + if (z.type == SLANG_SPEC_STRUCT) { + z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct)); + if (z._struct == NULL) { + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + if (!slang_struct_construct(z._struct)) { + _slang_free(z._struct); + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + if (!slang_struct_copy(z._struct, y->_struct)) { + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + } + else if (z.type == SLANG_SPEC_ARRAY) { + z._array = (slang_type_specifier *) + _slang_alloc(sizeof(slang_type_specifier)); + if (z._array == NULL) { + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + slang_type_specifier_ctr(z._array); + if (!slang_type_specifier_copy(z._array, y->_array)) { + slang_type_specifier_dtr(&z); + return GL_FALSE; + } + } + slang_type_specifier_dtr(x); + *x = z; + return GL_TRUE; +} + + +/** + * Test if two types are equal. + */ +GLboolean +slang_type_specifier_equal(const slang_type_specifier * x, + const slang_type_specifier * y) +{ + if (x->type != y->type) + return GL_FALSE; + if (x->type == SLANG_SPEC_STRUCT) + return slang_struct_equal(x->_struct, y->_struct); + if (x->type == SLANG_SPEC_ARRAY) + return slang_type_specifier_equal(x->_array, y->_array); + return GL_TRUE; +} + + +/** + * As above, but allow float/int casting. + */ +static GLboolean +slang_type_specifier_compatible(const slang_type_specifier * x, + const slang_type_specifier * y) +{ + /* special case: float == int */ + if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) { + return GL_TRUE; + } + /* XXX may need to add bool/int compatibility, etc */ + + if (x->type != y->type) + return GL_FALSE; + if (x->type == SLANG_SPEC_STRUCT) + return slang_struct_equal(x->_struct, y->_struct); + if (x->type == SLANG_SPEC_ARRAY) + return slang_type_specifier_compatible(x->_array, y->_array); + return GL_TRUE; +} + + +GLboolean +slang_typeinfo_construct(slang_typeinfo * ti) +{ + slang_type_specifier_ctr(&ti->spec); + ti->array_len = 0; + return GL_TRUE; +} + +GLvoid +slang_typeinfo_destruct(slang_typeinfo * ti) +{ + slang_type_specifier_dtr(&ti->spec); +} + + + +/** + * Determine the return type of a function. + * \param a_name the function name + * \param param function parameters (overloading) + * \param num_params number of parameters to function + * \param space namespace to search + * \param spec returns the type + * \param funFound returns pointer to the function, or NULL if not found. + * \return GL_TRUE for success, GL_FALSE if failure (bad function name) + */ +static GLboolean +_slang_typeof_function(slang_atom a_name, + slang_operation * params, GLuint num_params, + const slang_name_space * space, + slang_type_specifier * spec, + slang_function **funFound, + slang_atom_pool *atoms, slang_info_log *log) +{ + *funFound = _slang_locate_function(space->funcs, a_name, params, + num_params, space, atoms, log); + if (!*funFound) + return GL_TRUE; /* yes, not false */ + return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier); +} + + +/** + * Determine the type of a math function. + * \param name name of the operator, one of +,-,*,/ or unary - + * \param params array of function parameters + * \param num_params number of parameters + * \param space namespace to use + * \param spec returns the function's type + * \param atoms atom pool + * \return GL_TRUE for success, GL_FALSE if failure + */ +static GLboolean +typeof_math_call(const char *name, slang_operation *call, + const slang_name_space * space, + slang_type_specifier * spec, + slang_atom_pool * atoms, + slang_info_log *log) +{ + if (call->fun) { + /* we've previously resolved this function call */ + slang_type_specifier_copy(spec, &call->fun->header.type.specifier); + return GL_TRUE; + } + else { + slang_atom atom; + slang_function *fun; + + /* number of params: */ + assert(call->num_children == 1 || call->num_children == 2); + + atom = slang_atom_pool_atom(atoms, name); + if (!_slang_typeof_function(atom, call->children, call->num_children, + space, spec, &fun, atoms, log)) + return GL_FALSE; + + if (fun) { + /* Save pointer to save time in future */ + call->fun = fun; + return GL_TRUE; + } + return GL_FALSE; + } +} + +GLboolean +_slang_typeof_operation(const slang_assemble_ctx * A, + slang_operation * op, + slang_typeinfo * ti) +{ + return _slang_typeof_operation_(op, &A->space, ti, A->atoms, A->log); +} + + +/** + * Determine the return type of an operation. + * \param op the operation node + * \param space the namespace to use + * \param ti the returned type + * \param atoms atom pool + * \return GL_TRUE for success, GL_FALSE if failure + */ +GLboolean +_slang_typeof_operation_(slang_operation * op, + const slang_name_space * space, + slang_typeinfo * ti, + slang_atom_pool * atoms, + slang_info_log *log) +{ + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + + switch (op->type) { + case SLANG_OPER_BLOCK_NO_NEW_SCOPE: + case SLANG_OPER_BLOCK_NEW_SCOPE: + case SLANG_OPER_VARIABLE_DECL: + case SLANG_OPER_ASM: + case SLANG_OPER_BREAK: + case SLANG_OPER_CONTINUE: + case SLANG_OPER_DISCARD: + case SLANG_OPER_RETURN: + case SLANG_OPER_IF: + case SLANG_OPER_WHILE: + case SLANG_OPER_DO: + case SLANG_OPER_FOR: + case SLANG_OPER_VOID: + ti->spec.type = SLANG_SPEC_VOID; + break; + case SLANG_OPER_EXPRESSION: + case SLANG_OPER_ASSIGN: + case SLANG_OPER_ADDASSIGN: + case SLANG_OPER_SUBASSIGN: + case SLANG_OPER_MULASSIGN: + case SLANG_OPER_DIVASSIGN: + case SLANG_OPER_PREINCREMENT: + case SLANG_OPER_PREDECREMENT: + if (!_slang_typeof_operation_(op->children, space, ti, atoms, log)) + return GL_FALSE; + break; + case SLANG_OPER_LITERAL_BOOL: + if (op->literal_size == 1) + ti->spec.type = SLANG_SPEC_BOOL; + else if (op->literal_size == 2) + ti->spec.type = SLANG_SPEC_BVEC2; + else if (op->literal_size == 3) + ti->spec.type = SLANG_SPEC_BVEC3; + else if (op->literal_size == 4) + ti->spec.type = SLANG_SPEC_BVEC4; + else { + _mesa_problem(NULL, + "Unexpected bool literal_size %d in _slang_typeof_operation()", + op->literal_size); + ti->spec.type = SLANG_SPEC_BOOL; + } + break; + case SLANG_OPER_LOGICALOR: + case SLANG_OPER_LOGICALXOR: + case SLANG_OPER_LOGICALAND: + case SLANG_OPER_EQUAL: + case SLANG_OPER_NOTEQUAL: + case SLANG_OPER_LESS: + case SLANG_OPER_GREATER: + case SLANG_OPER_LESSEQUAL: + case SLANG_OPER_GREATEREQUAL: + case SLANG_OPER_NOT: + ti->spec.type = SLANG_SPEC_BOOL; + break; + case SLANG_OPER_LITERAL_INT: + if (op->literal_size == 1) + ti->spec.type = SLANG_SPEC_INT; + else if (op->literal_size == 2) + ti->spec.type = SLANG_SPEC_IVEC2; + else if (op->literal_size == 3) + ti->spec.type = SLANG_SPEC_IVEC3; + else if (op->literal_size == 4) + ti->spec.type = SLANG_SPEC_IVEC4; + else { + _mesa_problem(NULL, + "Unexpected int literal_size %d in _slang_typeof_operation()", + op->literal_size); + ti->spec.type = SLANG_SPEC_INT; + } + break; + case SLANG_OPER_LITERAL_FLOAT: + if (op->literal_size == 1) + ti->spec.type = SLANG_SPEC_FLOAT; + else if (op->literal_size == 2) + ti->spec.type = SLANG_SPEC_VEC2; + else if (op->literal_size == 3) + ti->spec.type = SLANG_SPEC_VEC3; + else if (op->literal_size == 4) + ti->spec.type = SLANG_SPEC_VEC4; + else { + _mesa_problem(NULL, + "Unexpected float literal_size %d in _slang_typeof_operation()", + op->literal_size); + ti->spec.type = SLANG_SPEC_FLOAT; + } + break; + case SLANG_OPER_IDENTIFIER: + { + slang_variable *var; + var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE); + if (!var) { + slang_info_log_error(log, "undefined variable '%s'", + (char *) op->a_id); + return GL_FALSE; + } + if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) { + slang_info_log_memory(log); + return GL_FALSE; + } + ti->can_be_referenced = GL_TRUE; + ti->array_len = var->array_len; + } + break; + case SLANG_OPER_SEQUENCE: + /* TODO: check [0] and [1] if they match */ + if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) { + return GL_FALSE; + } + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + break; + /*case SLANG_OPER_MODASSIGN: */ + /*case SLANG_OPER_LSHASSIGN: */ + /*case SLANG_OPER_RSHASSIGN: */ + /*case SLANG_OPER_ORASSIGN: */ + /*case SLANG_OPER_XORASSIGN: */ + /*case SLANG_OPER_ANDASSIGN: */ + case SLANG_OPER_SELECT: + /* TODO: check [1] and [2] if they match */ + if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) { + return GL_FALSE; + } + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + break; + /*case SLANG_OPER_BITOR: */ + /*case SLANG_OPER_BITXOR: */ + /*case SLANG_OPER_BITAND: */ + /*case SLANG_OPER_LSHIFT: */ + /*case SLANG_OPER_RSHIFT: */ + case SLANG_OPER_ADD: + assert(op->num_children == 2); + if (!typeof_math_call("+", op, space, &ti->spec, atoms, log)) + return GL_FALSE; + break; + case SLANG_OPER_SUBTRACT: + assert(op->num_children == 2); + if (!typeof_math_call("-", op, space, &ti->spec, atoms, log)) + return GL_FALSE; + break; + case SLANG_OPER_MULTIPLY: + assert(op->num_children == 2); + if (!typeof_math_call("*", op, space, &ti->spec, atoms, log)) + return GL_FALSE; + break; + case SLANG_OPER_DIVIDE: + assert(op->num_children == 2); + if (!typeof_math_call("/", op, space, &ti->spec, atoms, log)) + return GL_FALSE; + break; + /*case SLANG_OPER_MODULUS: */ + case SLANG_OPER_PLUS: + if (!_slang_typeof_operation_(op->children, space, ti, atoms, log)) + return GL_FALSE; + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + break; + case SLANG_OPER_MINUS: + assert(op->num_children == 1); + if (!typeof_math_call("-", op, space, &ti->spec, atoms, log)) + return GL_FALSE; + break; + /*case SLANG_OPER_COMPLEMENT: */ + case SLANG_OPER_SUBSCRIPT: + { + slang_typeinfo _ti; + + if (!slang_typeinfo_construct(&_ti)) + return GL_FALSE; + if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) { + slang_typeinfo_destruct(&_ti); + return GL_FALSE; + } + ti->can_be_referenced = _ti.can_be_referenced; + if (_ti.spec.type == SLANG_SPEC_ARRAY) { + if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) { + slang_typeinfo_destruct(&_ti); + return GL_FALSE; + } + } + else { + if (!_slang_type_is_vector(_ti.spec.type) + && !_slang_type_is_matrix(_ti.spec.type)) { + slang_typeinfo_destruct(&_ti); + slang_info_log_error(log, "cannot index a non-array type"); + return GL_FALSE; + } + ti->spec.type = _slang_type_base(_ti.spec.type); + } + slang_typeinfo_destruct(&_ti); + } + break; + case SLANG_OPER_CALL: + if (op->fun) { + /* we've resolved this call before */ + slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier); + } + else { + slang_function *fun; + if (!_slang_typeof_function(op->a_id, op->children, op->num_children, + space, &ti->spec, &fun, atoms, log)) + return GL_FALSE; + if (fun) { + /* save result for future use */ + op->fun = fun; + } + else { + slang_struct *s = + slang_struct_scope_find(space->structs, op->a_id, GL_TRUE); + if (s) { + /* struct initializer */ + ti->spec.type = SLANG_SPEC_STRUCT; + ti->spec._struct = + (slang_struct *) _slang_alloc(sizeof(slang_struct)); + if (ti->spec._struct == NULL) + return GL_FALSE; + if (!slang_struct_construct(ti->spec._struct)) { + _slang_free(ti->spec._struct); + ti->spec._struct = NULL; + return GL_FALSE; + } + if (!slang_struct_copy(ti->spec._struct, s)) + return GL_FALSE; + } + else { + /* float, int, vec4, mat3, etc. constructor? */ + const char *name; + slang_type_specifier_type type; + + name = slang_atom_pool_id(atoms, op->a_id); + type = slang_type_specifier_type_from_string(name); + if (type == SLANG_SPEC_VOID) { + slang_info_log_error(log, "undefined function '%s'", name); + return GL_FALSE; + } + ti->spec.type = type; + } + } + } + break; + case SLANG_OPER_FIELD: + { + slang_typeinfo _ti; + + if (!slang_typeinfo_construct(&_ti)) + return GL_FALSE; + if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) { + slang_typeinfo_destruct(&_ti); + return GL_FALSE; + } + if (_ti.spec.type == SLANG_SPEC_STRUCT) { + slang_variable *field; + + field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id, + GL_FALSE); + if (field == NULL) { + slang_typeinfo_destruct(&_ti); + return GL_FALSE; + } + if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) { + slang_typeinfo_destruct(&_ti); + return GL_FALSE; + } + ti->can_be_referenced = _ti.can_be_referenced; + } + else { + GLuint rows; + const char *swizzle; + slang_type_specifier_type base; + + /* determine the swizzle of the field expression */ + if (!_slang_type_is_vector(_ti.spec.type)) { + slang_typeinfo_destruct(&_ti); + slang_info_log_error(log, "Can't swizzle scalar expression"); + return GL_FALSE; + } + rows = _slang_type_dim(_ti.spec.type); + swizzle = slang_atom_pool_id(atoms, op->a_id); + if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) { + slang_typeinfo_destruct(&_ti); + slang_info_log_error(log, "bad swizzle '%s'", swizzle); + return GL_FALSE; + } + ti->is_swizzled = GL_TRUE; + ti->can_be_referenced = _ti.can_be_referenced + && _slang_is_swizzle_mask(&ti->swz, rows); + if (_ti.is_swizzled) { + slang_swizzle swz; + + /* swizzle the swizzle */ + _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz); + ti->swz = swz; + } + base = _slang_type_base(_ti.spec.type); + switch (ti->swz.num_components) { + case 1: + ti->spec.type = base; + break; + case 2: + switch (base) { + case SLANG_SPEC_FLOAT: + ti->spec.type = SLANG_SPEC_VEC2; + break; + case SLANG_SPEC_INT: + ti->spec.type = SLANG_SPEC_IVEC2; + break; + case SLANG_SPEC_BOOL: + ti->spec.type = SLANG_SPEC_BVEC2; + break; + default: + break; + } + break; + case 3: + switch (base) { + case SLANG_SPEC_FLOAT: + ti->spec.type = SLANG_SPEC_VEC3; + break; + case SLANG_SPEC_INT: + ti->spec.type = SLANG_SPEC_IVEC3; + break; + case SLANG_SPEC_BOOL: + ti->spec.type = SLANG_SPEC_BVEC3; + break; + default: + break; + } + break; + case 4: + switch (base) { + case SLANG_SPEC_FLOAT: + ti->spec.type = SLANG_SPEC_VEC4; + break; + case SLANG_SPEC_INT: + ti->spec.type = SLANG_SPEC_IVEC4; + break; + case SLANG_SPEC_BOOL: + ti->spec.type = SLANG_SPEC_BVEC4; + break; + default: + break; + } + break; + default: + break; + } + } + slang_typeinfo_destruct(&_ti); + } + break; + case SLANG_OPER_POSTINCREMENT: + case SLANG_OPER_POSTDECREMENT: + if (!_slang_typeof_operation_(op->children, space, ti, atoms, log)) + return GL_FALSE; + ti->can_be_referenced = GL_FALSE; + ti->is_swizzled = GL_FALSE; + break; + default: + return GL_FALSE; + } + + return GL_TRUE; +} + + +/** + * Lookup a function according to name and parameter count/types. + */ +slang_function * +_slang_locate_function(const slang_function_scope * funcs, slang_atom a_name, + slang_operation * args, GLuint num_args, + const slang_name_space * space, slang_atom_pool * atoms, + slang_info_log *log) +{ + GLuint i; + + for (i = 0; i < funcs->num_functions; i++) { + slang_function *f = &funcs->functions[i]; + const GLuint haveRetValue = _slang_function_has_return_value(f); + GLuint j; + + if (a_name != f->header.a_name) + continue; + if (f->param_count - haveRetValue != num_args) + continue; + + /* compare parameter / argument types */ + for (j = 0; j < num_args; j++) { + slang_typeinfo ti; + + if (!slang_typeinfo_construct(&ti)) + return NULL; + if (!_slang_typeof_operation_(&args[j], space, &ti, atoms, log)) { + slang_typeinfo_destruct(&ti); + return NULL; + } + if (!slang_type_specifier_compatible(&ti.spec, + &f->parameters->variables[j]->type.specifier)) { + slang_typeinfo_destruct(&ti); + break; + } + slang_typeinfo_destruct(&ti); + + /* "out" and "inout" formal parameter requires the actual + * parameter to be l-value. + */ + if (!ti.can_be_referenced && + (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT || + f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) + break; + } + if (j == num_args) + return f; + } + if (funcs->outer_scope != NULL) + return _slang_locate_function(funcs->outer_scope, a_name, args, + num_args, space, atoms, log); + return NULL; +} + + +/** + * Determine if a type is a matrix. + * \return GL_TRUE if is a matrix, GL_FALSE otherwise. + */ +GLboolean +_slang_type_is_matrix(slang_type_specifier_type ty) +{ + switch (ty) { + case SLANG_SPEC_MAT2: + case SLANG_SPEC_MAT3: + case SLANG_SPEC_MAT4: + case SLANG_SPEC_MAT23: + case SLANG_SPEC_MAT32: + case SLANG_SPEC_MAT24: + case SLANG_SPEC_MAT42: + case SLANG_SPEC_MAT34: + case SLANG_SPEC_MAT43: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Determine if a type is a vector. + * \return GL_TRUE if is a vector, GL_FALSE otherwise. + */ +GLboolean +_slang_type_is_vector(slang_type_specifier_type ty) +{ + switch (ty) { + case SLANG_SPEC_VEC2: + case SLANG_SPEC_VEC3: + case SLANG_SPEC_VEC4: + case SLANG_SPEC_IVEC2: + case SLANG_SPEC_IVEC3: + case SLANG_SPEC_IVEC4: + case SLANG_SPEC_BVEC2: + case SLANG_SPEC_BVEC3: + case SLANG_SPEC_BVEC4: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Given a vector type, return the type of the vector's elements. + * For a matrix, return the type of the columns. + */ +slang_type_specifier_type +_slang_type_base(slang_type_specifier_type ty) +{ + switch (ty) { + case SLANG_SPEC_FLOAT: + case SLANG_SPEC_VEC2: + case SLANG_SPEC_VEC3: + case SLANG_SPEC_VEC4: + return SLANG_SPEC_FLOAT; + case SLANG_SPEC_INT: + case SLANG_SPEC_IVEC2: + case SLANG_SPEC_IVEC3: + case SLANG_SPEC_IVEC4: + return SLANG_SPEC_INT; + case SLANG_SPEC_BOOL: + case SLANG_SPEC_BVEC2: + case SLANG_SPEC_BVEC3: + case SLANG_SPEC_BVEC4: + return SLANG_SPEC_BOOL; + case SLANG_SPEC_MAT2: + return SLANG_SPEC_VEC2; + case SLANG_SPEC_MAT3: + return SLANG_SPEC_VEC3; + case SLANG_SPEC_MAT4: + return SLANG_SPEC_VEC4; + case SLANG_SPEC_MAT23: + return SLANG_SPEC_VEC3; + case SLANG_SPEC_MAT32: + return SLANG_SPEC_VEC2; + case SLANG_SPEC_MAT24: + return SLANG_SPEC_VEC4; + case SLANG_SPEC_MAT42: + return SLANG_SPEC_VEC2; + case SLANG_SPEC_MAT34: + return SLANG_SPEC_VEC4; + case SLANG_SPEC_MAT43: + return SLANG_SPEC_VEC3; + default: + return SLANG_SPEC_VOID; + } +} + + +/** + * Return the dimensionality of a vector, or for a matrix, return number + * of columns. + */ +GLuint +_slang_type_dim(slang_type_specifier_type ty) +{ + switch (ty) { + case SLANG_SPEC_FLOAT: + case SLANG_SPEC_INT: + case SLANG_SPEC_BOOL: + return 1; + case SLANG_SPEC_VEC2: + case SLANG_SPEC_IVEC2: + case SLANG_SPEC_BVEC2: + case SLANG_SPEC_MAT2: + return 2; + case SLANG_SPEC_VEC3: + case SLANG_SPEC_IVEC3: + case SLANG_SPEC_BVEC3: + case SLANG_SPEC_MAT3: + return 3; + case SLANG_SPEC_VEC4: + case SLANG_SPEC_IVEC4: + case SLANG_SPEC_BVEC4: + case SLANG_SPEC_MAT4: + return 4; + + case SLANG_SPEC_MAT23: + return 2; + case SLANG_SPEC_MAT32: + return 3; + case SLANG_SPEC_MAT24: + return 2; + case SLANG_SPEC_MAT42: + return 4; + case SLANG_SPEC_MAT34: + return 3; + case SLANG_SPEC_MAT43: + return 4; + + default: + return 0; + } +} + + +/** + * Return the GL_* type that corresponds to a SLANG_SPEC_* type. + */ +GLenum +_slang_gltype_from_specifier(const slang_type_specifier *type) +{ + switch (type->type) { + case SLANG_SPEC_BOOL: + return GL_BOOL; + case SLANG_SPEC_BVEC2: + return GL_BOOL_VEC2; + case SLANG_SPEC_BVEC3: + return GL_BOOL_VEC3; + case SLANG_SPEC_BVEC4: + return GL_BOOL_VEC4; + case SLANG_SPEC_INT: + return GL_INT; + case SLANG_SPEC_IVEC2: + return GL_INT_VEC2; + case SLANG_SPEC_IVEC3: + return GL_INT_VEC3; + case SLANG_SPEC_IVEC4: + return GL_INT_VEC4; + case SLANG_SPEC_FLOAT: + return GL_FLOAT; + case SLANG_SPEC_VEC2: + return GL_FLOAT_VEC2; + case SLANG_SPEC_VEC3: + return GL_FLOAT_VEC3; + case SLANG_SPEC_VEC4: + return GL_FLOAT_VEC4; + case SLANG_SPEC_MAT2: + return GL_FLOAT_MAT2; + case SLANG_SPEC_MAT3: + return GL_FLOAT_MAT3; + case SLANG_SPEC_MAT4: + return GL_FLOAT_MAT4; + case SLANG_SPEC_MAT23: + return GL_FLOAT_MAT2x3; + case SLANG_SPEC_MAT32: + return GL_FLOAT_MAT3x2; + case SLANG_SPEC_MAT24: + return GL_FLOAT_MAT2x4; + case SLANG_SPEC_MAT42: + return GL_FLOAT_MAT4x2; + case SLANG_SPEC_MAT34: + return GL_FLOAT_MAT3x4; + case SLANG_SPEC_MAT43: + return GL_FLOAT_MAT4x3; + case SLANG_SPEC_SAMPLER1D: + return GL_SAMPLER_1D; + case SLANG_SPEC_SAMPLER2D: + return GL_SAMPLER_2D; + case SLANG_SPEC_SAMPLER3D: + return GL_SAMPLER_3D; + case SLANG_SPEC_SAMPLERCUBE: + return GL_SAMPLER_CUBE; + case SLANG_SPEC_SAMPLER1DSHADOW: + return GL_SAMPLER_1D_SHADOW; + case SLANG_SPEC_SAMPLER2DSHADOW: + return GL_SAMPLER_2D_SHADOW; + case SLANG_SPEC_SAMPLER2DRECT: + return GL_SAMPLER_2D_RECT_ARB; + case SLANG_SPEC_SAMPLER2DRECTSHADOW: + return GL_SAMPLER_2D_RECT_SHADOW_ARB; + case SLANG_SPEC_ARRAY: + return _slang_gltype_from_specifier(type->_array); + case SLANG_SPEC_STRUCT: + /* fall-through */ + default: + return GL_NONE; + } +} + diff --git a/dist/Mesa/src/mesa/shader/slang/slang_typeinfo.h b/dist/Mesa/src/mesa/shader/slang/slang_typeinfo.h new file mode 100644 index 000000000..587331e8b --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_typeinfo.h @@ -0,0 +1,202 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef SLANG_TYPEINFO_H +#define SLANG_TYPEINFO_H 1 + +#include "imports.h" +#include "mtypes.h" +#include "slang_log.h" +#include "slang_utility.h" +#include "slang_vartable.h" + + +struct slang_operation_; + + +/** + * Holds complete information about vector swizzle - the <swizzle> + * array contains vector component source indices, where 0 is "x", 1 + * is "y", 2 is "z" and 3 is "w". + * Example: "xwz" --> { 3, { 0, 3, 2, not used } }. + */ +typedef struct slang_swizzle_ +{ + GLuint num_components; + GLuint swizzle[4]; +} slang_swizzle; + +typedef struct slang_name_space_ +{ + struct slang_function_scope_ *funcs; + struct slang_struct_scope_ *structs; + struct slang_variable_scope_ *vars; +} slang_name_space; + + +typedef struct slang_assemble_ctx_ +{ + slang_atom_pool *atoms; + slang_name_space space; + struct gl_program *program; + slang_var_table *vartable; + slang_info_log *log; + struct slang_label_ *curFuncEndLabel; + struct slang_ir_node_ *CurLoop; + struct slang_function_ *CurFunction; +} slang_assemble_ctx; + + +extern struct slang_function_ * +_slang_locate_function(const struct slang_function_scope_ *funcs, + slang_atom name, struct slang_operation_ *params, + GLuint num_params, + const slang_name_space *space, + slang_atom_pool *atoms, slang_info_log *log); + + +extern GLboolean +_slang_is_swizzle(const char *field, GLuint rows, slang_swizzle *swz); + +extern GLboolean +_slang_is_swizzle_mask(const slang_swizzle *swz, GLuint rows); + +extern GLvoid +_slang_multiply_swizzles(slang_swizzle *, const slang_swizzle *, + const slang_swizzle *); + + +/** + * The basic shading language types (float, vec4, mat3, etc) + */ +typedef enum slang_type_specifier_type_ +{ + SLANG_SPEC_VOID, + SLANG_SPEC_BOOL, + SLANG_SPEC_BVEC2, + SLANG_SPEC_BVEC3, + SLANG_SPEC_BVEC4, + SLANG_SPEC_INT, + SLANG_SPEC_IVEC2, + SLANG_SPEC_IVEC3, + SLANG_SPEC_IVEC4, + SLANG_SPEC_FLOAT, + SLANG_SPEC_VEC2, + SLANG_SPEC_VEC3, + SLANG_SPEC_VEC4, + SLANG_SPEC_MAT2, + SLANG_SPEC_MAT3, + SLANG_SPEC_MAT4, + SLANG_SPEC_MAT23, + SLANG_SPEC_MAT32, + SLANG_SPEC_MAT24, + SLANG_SPEC_MAT42, + SLANG_SPEC_MAT34, + SLANG_SPEC_MAT43, + SLANG_SPEC_SAMPLER1D, + SLANG_SPEC_SAMPLER2D, + SLANG_SPEC_SAMPLER3D, + SLANG_SPEC_SAMPLERCUBE, + SLANG_SPEC_SAMPLER2DRECT, + SLANG_SPEC_SAMPLER1DSHADOW, + SLANG_SPEC_SAMPLER2DSHADOW, + SLANG_SPEC_SAMPLER2DRECTSHADOW, + SLANG_SPEC_STRUCT, + SLANG_SPEC_ARRAY +} slang_type_specifier_type; + + +/** + * Describes more sophisticated types, like structs and arrays. + */ +typedef struct slang_type_specifier_ +{ + slang_type_specifier_type type; + struct slang_struct_ *_struct; /**< used if type == spec_struct */ + struct slang_type_specifier_ *_array; /**< used if type == spec_array */ +} slang_type_specifier; + + +extern GLvoid +slang_type_specifier_ctr(slang_type_specifier *); + +extern GLvoid +slang_type_specifier_dtr(slang_type_specifier *); + +extern GLboolean +slang_type_specifier_copy(slang_type_specifier *, const slang_type_specifier *); + +extern GLboolean +slang_type_specifier_equal(const slang_type_specifier *, + const slang_type_specifier *); + + +typedef struct slang_typeinfo_ +{ + GLboolean can_be_referenced; + GLboolean is_swizzled; + slang_swizzle swz; + slang_type_specifier spec; + GLuint array_len; +} slang_typeinfo; + +extern GLboolean +slang_typeinfo_construct(slang_typeinfo *); + +extern GLvoid +slang_typeinfo_destruct(slang_typeinfo *); + + +/** + * Retrieves type information about an operation. + * Returns GL_TRUE on success. + * Returns GL_FALSE otherwise. + */ +extern GLboolean +_slang_typeof_operation(const slang_assemble_ctx *, + struct slang_operation_ *, + slang_typeinfo *); + +extern GLboolean +_slang_typeof_operation_(struct slang_operation_ *, + const slang_name_space *, + slang_typeinfo *, slang_atom_pool *, + slang_info_log *log); + +extern GLboolean +_slang_type_is_matrix(slang_type_specifier_type); + +extern GLboolean +_slang_type_is_vector(slang_type_specifier_type); + +extern slang_type_specifier_type +_slang_type_base(slang_type_specifier_type); + +extern GLuint +_slang_type_dim(slang_type_specifier_type); + +extern GLenum +_slang_gltype_from_specifier(const slang_type_specifier *type); + +#endif diff --git a/dist/Mesa/src/mesa/shader/slang/slang_vartable.c b/dist/Mesa/src/mesa/shader/slang/slang_vartable.c new file mode 100644 index 000000000..8a3c299d1 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_vartable.c @@ -0,0 +1,334 @@ + +#include "imports.h" +#include "slang_compile.h" +#include "slang_compile_variable.h" +#include "slang_mem.h" +#include "slang_vartable.h" +#include "slang_ir.h" +#include "prog_instruction.h" + + +static int dbg = 0; + + +typedef enum { + FREE, + VAR, + TEMP +} TempState; + + +/** + * Variable/register info for one variable scope. + */ +struct table +{ + int Level; + int NumVars; + slang_variable **Vars; /* array [NumVars] */ + + TempState Temps[MAX_PROGRAM_TEMPS * 4]; /* per-component state */ + int ValSize[MAX_PROGRAM_TEMPS]; /* For debug only */ + + struct table *Parent; /** Parent scope table */ +}; + + +/** + * A variable table is a stack of tables, one per scope. + */ +struct slang_var_table_ +{ + GLint CurLevel; + GLuint MaxRegisters; + struct table *Top; /**< Table at top of stack */ +}; + + + +slang_var_table * +_slang_new_var_table(GLuint maxRegisters) +{ + slang_var_table *vt + = (slang_var_table *) _slang_alloc(sizeof(slang_var_table)); + if (vt) { + vt->MaxRegisters = maxRegisters; + } + return vt; +} + + +void +_slang_delete_var_table(slang_var_table *vt) +{ + if (vt->Top) { + _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()"); + return; + } + _slang_free(vt); +} + + + +/** + * Create new table, put at head, return ptr to it. + * XXX we should take a maxTemps parameter to indicate how many temporaries + * are available for the current shader/program target. + */ +void +_slang_push_var_table(slang_var_table *vt) +{ + struct table *t = (struct table *) _slang_alloc(sizeof(struct table)); + if (t) { + t->Level = vt->CurLevel++; + t->Parent = vt->Top; + if (t->Parent) { + /* copy the info indicating which temp regs are in use */ + memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps)); + memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize)); + } + vt->Top = t; + if (dbg) printf("Pushing level %d\n", t->Level); + } +} + + +/** + * Destroy given table, return ptr to Parent + */ +void +_slang_pop_var_table(slang_var_table *vt) +{ + struct table *t = vt->Top; + int i; + + if (dbg) printf("Popping level %d\n", t->Level); + + /* free the storage allocated for each variable */ + for (i = 0; i < t->NumVars; i++) { + slang_ir_storage *store = (slang_ir_storage *) t->Vars[i]->aux; + GLint j; + GLuint comp; + if (dbg) printf(" Free var %s, size %d at %d\n", + (char*) t->Vars[i]->a_name, store->Size, + store->Index); + + if (store->Size == 1) + comp = GET_SWZ(store->Swizzle, 0); + else + comp = 0; + + assert(store->Index >= 0); + for (j = 0; j < store->Size; j++) { + assert(t->Temps[store->Index * 4 + j + comp] == VAR); + t->Temps[store->Index * 4 + j + comp] = FREE; + } + store->Index = -1; + } + if (t->Parent) { + /* just verify that any remaining allocations in this scope + * were for temps + */ + for (i = 0; i < vt->MaxRegisters * 4; i++) { + if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) { + if (dbg) printf(" Free reg %d\n", i/4); + assert(t->Temps[i] == TEMP); + } + } + } + + if (t->Vars) { + _slang_free(t->Vars); + t->Vars = NULL; + } + + vt->Top = t->Parent; + _slang_free(t); + vt->CurLevel--; +} + + +/** + * Add a new variable to the given symbol table. + */ +void +_slang_add_variable(slang_var_table *vt, slang_variable *v) +{ + struct table *t; + assert(vt); + t = vt->Top; + assert(t); + if (dbg) printf("Adding var %s\n", (char *) v->a_name); + t->Vars = (slang_variable **) + _slang_realloc(t->Vars, + t->NumVars * sizeof(slang_variable *), + (t->NumVars + 1) * sizeof(slang_variable *)); + t->Vars[t->NumVars] = v; + t->NumVars++; +} + + +/** + * Look for variable by name in given table. + * If not found, Parent table will be searched. + */ +slang_variable * +_slang_find_variable(const slang_var_table *vt, slang_atom name) +{ + struct table *t = vt->Top; + while (1) { + int i; + for (i = 0; i < t->NumVars; i++) { + if (t->Vars[i]->a_name == name) + return t->Vars[i]; + } + if (t->Parent) + t = t->Parent; + else + return NULL; + } +} + + +/** + * Allocation helper. + * \param size var size in floats + * \return position for var, measured in floats + */ +static GLint +alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp) +{ + struct table *t = vt->Top; + /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */ + const GLuint step = (size == 1) ? 1 : 4; + GLuint i, j; + assert(size > 0); /* number of floats */ + + for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) { + GLuint found = 0; + for (j = 0; j < size; j++) { + if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) { + found++; + } + else { + break; + } + } + if (found == size) { + /* found block of size free regs */ + if (size > 1) + assert(i % 4 == 0); + for (j = 0; j < size; j++) + t->Temps[i + j] = isTemp ? TEMP : VAR; + t->ValSize[i] = size; + return i; + } + } + return -1; +} + + +/** + * Allocate temp register(s) for storing a variable. + * \param size size needed, in floats + * \param swizzle returns swizzle mask for accessing var in register + * \return register allocated, or -1 + */ +GLboolean +_slang_alloc_var(slang_var_table *vt, slang_ir_storage *store) +{ + struct table *t = vt->Top; + const int i = alloc_reg(vt, store->Size, GL_FALSE); + if (i < 0) + return GL_FALSE; + + store->Index = i / 4; + if (store->Size == 1) { + const GLuint comp = i % 4; + store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp); + if (dbg) printf("Alloc var sz %d at %d.%c (level %d)\n", + store->Size, store->Index, "xyzw"[comp], t->Level); + } + else { + store->Swizzle = SWIZZLE_NOOP; + if (dbg) printf("Alloc var sz %d at %d.xyzw (level %d)\n", + store->Size, store->Index, t->Level); + } + return GL_TRUE; +} + + + +/** + * Allocate temp register(s) for storing an unnamed intermediate value. + */ +GLboolean +_slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store) +{ + struct table *t = vt->Top; + const int i = alloc_reg(vt, store->Size, GL_TRUE); + if (i < 0) + return GL_FALSE; + + store->Index = i / 4; + if (store->Size == 1) { + const GLuint comp = i % 4; + store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp); + if (dbg) printf("Alloc temp sz %d at %d.%c (level %d)\n", + store->Size, store->Index, "xyzw"[comp], t->Level); + } + else { + store->Swizzle = SWIZZLE_NOOP; + if (dbg) printf("Alloc temp sz %d at %d.xyzw (level %d)\n", + store->Size, store->Index, t->Level); + } + return GL_TRUE; +} + + +void +_slang_free_temp(slang_var_table *vt, slang_ir_storage *store) +{ + struct table *t = vt->Top; + GLuint i; + GLuint r = store->Index; + assert(store->Size > 0); + assert(r >= 0); + assert(r + store->Size <= vt->MaxRegisters * 4); + if (dbg) printf("Free temp sz %d at %d (level %d)\n", store->Size, r, t->Level); + if (store->Size == 1) { + const GLuint comp = GET_SWZ(store->Swizzle, 0); + assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp)); + assert(comp < 4); + assert(t->ValSize[r * 4 + comp] == 1); + assert(t->Temps[r * 4 + comp] == TEMP); + t->Temps[r * 4 + comp] = FREE; + } + else { + /*assert(store->Swizzle == SWIZZLE_NOOP);*/ + assert(t->ValSize[r*4] == store->Size); + for (i = 0; i < store->Size; i++) { + assert(t->Temps[r * 4 + i] == TEMP); + t->Temps[r * 4 + i] = FREE; + } + } +} + + +GLboolean +_slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store) +{ + struct table *t = vt->Top; + GLuint comp; + assert(store->Index >= 0); + assert(store->Index < vt->MaxRegisters); + if (store->Swizzle == SWIZZLE_NOOP) + comp = 0; + else + comp = GET_SWZ(store->Swizzle, 0); + + if (t->Temps[store->Index * 4 + comp] == TEMP) + return GL_TRUE; + else + return GL_FALSE; +} diff --git a/dist/Mesa/src/mesa/shader/slang/slang_vartable.h b/dist/Mesa/src/mesa/shader/slang/slang_vartable.h new file mode 100644 index 000000000..8a3b992c9 --- /dev/null +++ b/dist/Mesa/src/mesa/shader/slang/slang_vartable.h @@ -0,0 +1,42 @@ + +#ifndef SLANG_VARTABLE_H +#define SLANG_VARTABLE_H + +struct _slang_ir_storage; + +typedef struct slang_var_table_ slang_var_table; + +struct slang_variable_; + +extern slang_var_table * +_slang_new_var_table(GLuint maxRegisters); + +extern void +_slang_delete_var_table(slang_var_table *vt); + +extern void +_slang_push_var_table(slang_var_table *parent); + +extern void +_slang_pop_var_table(slang_var_table *t); + +extern void +_slang_add_variable(slang_var_table *t, struct slang_variable_ *v); + +extern struct slang_variable_ * +_slang_find_variable(const slang_var_table *t, slang_atom name); + +extern GLboolean +_slang_alloc_var(slang_var_table *t, struct _slang_ir_storage *store); + +extern GLboolean +_slang_alloc_temp(slang_var_table *t, struct _slang_ir_storage *store); + +extern void +_slang_free_temp(slang_var_table *t, struct _slang_ir_storage *store); + +extern GLboolean +_slang_is_temp(const slang_var_table *t, const struct _slang_ir_storage *store); + + +#endif /* SLANG_VARTABLE_H */ diff --git a/dist/Mesa/src/mesa/swrast/s_fragprog.c b/dist/Mesa/src/mesa/swrast/s_fragprog.c new file mode 100644 index 000000000..e47dbbdaf --- /dev/null +++ b/dist/Mesa/src/mesa/swrast/s_fragprog.c @@ -0,0 +1,224 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "prog_instruction.h" + +#include "s_fragprog.h" +#include "s_span.h" + + +/** + * Fetch a texel. + */ +static void +fetch_texel( GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda, + GLuint unit, GLfloat color[4] ) +{ + GLchan rgba[4]; + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + /* XXX use a float-valued TextureSample routine here!!! */ + swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current, + 1, (const GLfloat (*)[4]) texcoord, + &lambda, &rgba); + color[0] = CHAN_TO_FLOAT(rgba[0]); + color[1] = CHAN_TO_FLOAT(rgba[1]); + color[2] = CHAN_TO_FLOAT(rgba[2]); + color[3] = CHAN_TO_FLOAT(rgba[3]); +} + + +/** + * Fetch a texel with the given partial derivatives to compute a level + * of detail in the mipmap. + */ +static void +fetch_texel_deriv( GLcontext *ctx, const GLfloat texcoord[4], + const GLfloat texdx[4], const GLfloat texdy[4], + GLuint unit, GLfloat color[4] ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; + const struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel]; + const GLfloat texW = (GLfloat) texImg->WidthScale; + const GLfloat texH = (GLfloat) texImg->HeightScale; + GLchan rgba[4]; + + GLfloat lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */ + texdx[1], texdy[1], /* dt/dx, dt/dy */ + texdx[3], texdy[2], /* dq/dx, dq/dy */ + texW, texH, + texcoord[0], texcoord[1], texcoord[3], + 1.0F / texcoord[3]); + + swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current, + 1, (const GLfloat (*)[4]) texcoord, + &lambda, &rgba); + color[0] = CHAN_TO_FLOAT(rgba[0]); + color[1] = CHAN_TO_FLOAT(rgba[1]); + color[2] = CHAN_TO_FLOAT(rgba[2]); + color[3] = CHAN_TO_FLOAT(rgba[3]); +} + + +/** + * Initialize the virtual fragment program machine state prior to running + * fragment program on a fragment. This involves initializing the input + * registers, condition codes, etc. + * \param machine the virtual machine state to init + * \param program the fragment program we're about to run + * \param span the span of pixels we'll operate on + * \param col which element (column) of the span we'll operate on + */ +static void +init_machine(GLcontext *ctx, struct gl_program_machine *machine, + const struct gl_fragment_program *program, + const SWspan *span, GLuint col) +{ + if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) { + /* Clear temporary registers (undefined for ARB_f_p) */ + _mesa_bzero(machine->Temporaries, + MAX_PROGRAM_TEMPS * 4 * sizeof(GLfloat)); + } + + /* Setup pointer to input attributes */ + machine->Attribs = span->array->attribs; + + machine->DerivX = (GLfloat (*)[4]) span->attrStepX; + machine->DerivY = (GLfloat (*)[4]) span->attrStepY; + machine->NumDeriv = FRAG_ATTRIB_MAX; + + if (ctx->Shader.CurrentProgram) { + /* Store front/back facing value in register FOGC.Y */ + machine->Attribs[FRAG_ATTRIB_FOGC][col][1] = (GLfloat) ctx->_Facing; + } + + machine->CurElement = col; + + /* init condition codes */ + machine->CondCodes[0] = COND_EQ; + machine->CondCodes[1] = COND_EQ; + machine->CondCodes[2] = COND_EQ; + machine->CondCodes[3] = COND_EQ; + + /* init call stack */ + machine->StackDepth = 0; + + machine->FetchTexelLod = fetch_texel; + machine->FetchTexelDeriv = fetch_texel_deriv; +} + + +/** + * Run fragment program on the pixels in span from 'start' to 'end' - 1. + */ +static void +run_program(GLcontext *ctx, SWspan *span, GLuint start, GLuint end) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + const struct gl_fragment_program *program = ctx->FragmentProgram._Current; + const GLbitfield outputsWritten = program->Base.OutputsWritten; + struct gl_program_machine *machine = &swrast->FragProgMachine; + GLuint i; + + for (i = start; i < end; i++) { + if (span->array->mask[i]) { + init_machine(ctx, machine, program, span, i); + + if (_mesa_execute_program(ctx, &program->Base, machine)) { + + /* Store result color */ + if (outputsWritten & (1 << FRAG_RESULT_COLR)) { + COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i], + machine->Outputs[FRAG_RESULT_COLR]); + } + else { + /* Multiple drawbuffers / render targets + * Note that colors beyond 0 and 1 will overwrite other + * attributes, such as FOGC, TEX0, TEX1, etc. That's OK. + */ + GLuint output; + for (output = 0; output < swrast->_NumColorOutputs; output++) { + if (outputsWritten & (1 << (FRAG_RESULT_DATA0 + output))) { + COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0+output][i], + machine->Outputs[FRAG_RESULT_DATA0 + output]); + } + } + } + + /* Store result depth/z */ + if (outputsWritten & (1 << FRAG_RESULT_DEPR)) { + const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPR][2]; + if (depth <= 0.0) + span->array->z[i] = 0; + else if (depth >= 1.0) + span->array->z[i] = ctx->DrawBuffer->_DepthMax; + else + span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF); + } + } + else { + /* killed fragment */ + span->array->mask[i] = GL_FALSE; + span->writeAll = GL_FALSE; + } + } + } +} + + +/** + * Execute the current fragment program for all the fragments + * in the given span. + */ +void +_swrast_exec_fragment_program( GLcontext *ctx, SWspan *span ) +{ + const struct gl_fragment_program *program = ctx->FragmentProgram._Current; + + /* incoming colors should be floats */ + if (program->Base.InputsRead & FRAG_BIT_COL0) { + ASSERT(span->array->ChanType == GL_FLOAT); + } + + ctx->_CurrentProgram = GL_FRAGMENT_PROGRAM_ARB; /* or NV, doesn't matter */ + + run_program(ctx, span, 0, span->end); + + if (program->Base.OutputsWritten & (1 << FRAG_RESULT_COLR)) { + span->interpMask &= ~SPAN_RGBA; + span->arrayMask |= SPAN_RGBA; + } + + if (program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR)) { + span->interpMask &= ~SPAN_Z; + span->arrayMask |= SPAN_Z; + } + + ctx->_CurrentProgram = 0; +} + diff --git a/dist/Mesa/src/mesa/swrast/s_fragprog.h b/dist/Mesa/src/mesa/swrast/s_fragprog.h new file mode 100644 index 000000000..e1b7e6791 --- /dev/null +++ b/dist/Mesa/src/mesa/swrast/s_fragprog.h @@ -0,0 +1,38 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef S_FRAGPROG_H +#define S_FRAGPROG_H + + +#include "s_context.h" + + +extern void +_swrast_exec_fragment_program(GLcontext *ctx, SWspan *span); + + +#endif /* S_FRAGPROG_H */ + diff --git a/dist/Mesa/src/mesa/tnl/t_draw.c b/dist/Mesa/src/mesa/tnl/t_draw.c new file mode 100644 index 000000000..5b2b2ae54 --- /dev/null +++ b/dist/Mesa/src/mesa/tnl/t_draw.c @@ -0,0 +1,409 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "context.h" +#include "imports.h" +#include "state.h" +#include "mtypes.h" +#include "macros.h" +#include "enums.h" + +#include "t_context.h" +#include "t_pipeline.h" +#include "t_vp_build.h" +#include "t_vertex.h" +#include "tnl.h" + + + +static GLubyte *get_space(GLcontext *ctx, GLuint bytes) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLubyte *space = _mesa_malloc(bytes); + + tnl->block[tnl->nr_blocks++] = space; + return space; +} + + +static void free_space(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint i; + for (i = 0; i < tnl->nr_blocks; i++) + _mesa_free(tnl->block[i]); + tnl->nr_blocks = 0; +} + + +/* Convert the incoming array to GLfloats. Understands the + * array->Normalized flag and selects the correct conversion method. + */ +#define CONVERT( TYPE, MACRO ) do { \ + GLuint i, j; \ + if (input->Normalized) { \ + for (i = 0; i < count; i++) { \ + const TYPE *in = (TYPE *)ptr; \ + for (j = 0; j < sz; j++) { \ + *fptr++ = MACRO(*in); \ + in++; \ + } \ + ptr += input->StrideB; \ + } \ + } else { \ + for (i = 0; i < count; i++) { \ + const TYPE *in = (TYPE *)ptr; \ + for (j = 0; j < sz; j++) { \ + *fptr++ = (GLfloat)(*in); \ + in++; \ + } \ + ptr += input->StrideB; \ + } \ + } \ +} while (0) + + + +/* Adjust pointer to point at first requested element, convert to + * floating point, populate VB->AttribPtr[]. + */ +static void _tnl_import_array( GLcontext *ctx, + GLuint attrib, + GLuint count, + const struct gl_client_array *input, + const GLubyte *ptr ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint stride = input->StrideB; + + if (input->Type != GL_FLOAT) { + const GLuint sz = input->Size; + GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat)); + GLfloat *fptr = (GLfloat *)buf; + + switch (input->Type) { + case GL_BYTE: + CONVERT(GLbyte, BYTE_TO_FLOAT); + break; + case GL_UNSIGNED_BYTE: + CONVERT(GLubyte, UBYTE_TO_FLOAT); + break; + case GL_SHORT: + CONVERT(GLshort, SHORT_TO_FLOAT); + break; + case GL_UNSIGNED_SHORT: + CONVERT(GLushort, USHORT_TO_FLOAT); + break; + case GL_INT: + CONVERT(GLint, INT_TO_FLOAT); + break; + case GL_UNSIGNED_INT: + CONVERT(GLuint, UINT_TO_FLOAT); + break; + case GL_DOUBLE: + CONVERT(GLdouble, (GLfloat)); + break; + default: + assert(0); + break; + } + + ptr = buf; + stride = sz * sizeof(GLfloat); + } + + VB->AttribPtr[attrib] = &tnl->tmp_inputs[attrib]; + VB->AttribPtr[attrib]->data = (GLfloat (*)[4])ptr; + VB->AttribPtr[attrib]->start = (GLfloat *)ptr; + VB->AttribPtr[attrib]->count = count; + VB->AttribPtr[attrib]->stride = stride; + VB->AttribPtr[attrib]->size = input->Size; + + /* This should die, but so should the whole GLvector4f concept: + */ + VB->AttribPtr[attrib]->flags = (((1<<input->Size)-1) | + VEC_NOT_WRITEABLE | + (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE)); + + VB->AttribPtr[attrib]->storage = NULL; +} + +#define CLIPVERTS ((6 + MAX_CLIP_PLANES) * 2) + + +static GLboolean *_tnl_import_edgeflag( GLcontext *ctx, + const GLvector4f *input, + GLuint count) +{ + const GLubyte *ptr = (const GLubyte *)input->data; + const GLuint stride = input->stride; + GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS); + GLboolean *bptr = space; + GLuint i; + + for (i = 0; i < count; i++) { + *bptr++ = ((GLfloat *)ptr)[0] == 1.0; + ptr += stride; + } + + return space; +} + + +static void bind_inputs( GLcontext *ctx, + const struct gl_client_array *inputs[], + GLint count, + struct gl_buffer_object **bo, + GLuint *nr_bo ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + + /* Map all the VBOs + */ + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + const void *ptr; + + if (inputs[i]->BufferObj->Name) { + if (!inputs[i]->BufferObj->Pointer) { + bo[*nr_bo] = inputs[i]->BufferObj; + (*nr_bo)++; + ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER, + GL_READ_ONLY_ARB, + inputs[i]->BufferObj); + + assert(inputs[i]->BufferObj->Pointer); + } + + ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer, + inputs[i]->Ptr); + } + else + ptr = inputs[i]->Ptr; + + /* Just make sure the array is floating point, otherwise convert to + * temporary storage. + * + * XXX: remove the GLvector4f type at some stage and just use + * client arrays. + */ + _tnl_import_array(ctx, i, count, inputs[i], ptr); + } + + /* We process only the vertices between min & max index: + */ + VB->Count = count; + + + /* Legacy pointers -- remove one day. + */ + VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS]; + VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; + VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0]; + VB->ColorPtr[1] = NULL; + VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR_INDEX]; + VB->IndexPtr[1] = NULL; + VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1]; + VB->SecondaryColorPtr[1] = NULL; + VB->FogCoordPtr = VB->AttribPtr[_TNL_ATTRIB_FOG]; + + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { + VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]; + } + + /* Clipping and drawing code still requires this to be a packed + * array of ubytes which can be written into. TODO: Fix and + * remove. + */ + if (ctx->Polygon.FrontMode != GL_FILL || + ctx->Polygon.BackMode != GL_FILL) + { + VB->EdgeFlag = _tnl_import_edgeflag( ctx, + VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG], + VB->Count ); + } + else { + /* the data previously pointed to by EdgeFlag may have been freed */ + VB->EdgeFlag = NULL; + } +} + + +/* Translate indices to GLuints and store in VB->Elts. + */ +static void bind_indices( GLcontext *ctx, + const struct _mesa_index_buffer *ib, + struct gl_buffer_object **bo, + GLuint *nr_bo) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + void *ptr; + + if (!ib) { + VB->Elts = NULL; + return; + } + + if (ib->obj->Name && !ib->obj->Pointer) { + bo[*nr_bo] = ib->obj; + (*nr_bo)++; + ctx->Driver.MapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER, + GL_READ_ONLY_ARB, + ib->obj); + + assert(ib->obj->Pointer); + } + + ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + + if (ib->type == GL_UNSIGNED_INT) { + VB->Elts = (GLuint *) ptr; + } + else { + GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint)); + VB->Elts = elts; + + if (ib->type == GL_UNSIGNED_SHORT) { + const GLushort *in = (GLushort *)ptr; + for (i = 0; i < ib->count; i++) + *elts++ = (GLuint)(*in++); + } + else { + const GLubyte *in = (GLubyte *)ptr; + for (i = 0; i < ib->count; i++) + *elts++ = (GLuint)(*in++); + } + } +} + +static void bind_prims( GLcontext *ctx, + const struct _mesa_prim *prim, + GLuint nr_prims ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + + VB->Primitive = prim; + VB->PrimitiveCount = nr_prims; +} + +static void unmap_vbos( GLcontext *ctx, + struct gl_buffer_object **bo, + GLuint nr_bo ) +{ + GLuint i; + for (i = 0; i < nr_bo; i++) { + ctx->Driver.UnmapBuffer(ctx, + 0, /* target -- I don't see why this would be needed */ + bo[i]); + } +} + + + +/* This is the main entrypoint into the slimmed-down software tnl + * module. In a regular swtnl driver, this can be plugged straight + * into the vbo->Driver.DrawPrims() callback. + */ +void _tnl_draw_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + const GLuint TEST_SPLIT = 0; + const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES; + + if (0) + { + GLuint i; + _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + for (i = 0; i < nr_prims; i++) + _mesa_printf("prim %d: %s start %d count %d\n", i, + _mesa_lookup_enum_by_nr(prim[i].mode), + prim[i].start, + prim[i].count); + } + + if (min_index) { + /* We always translate away calls with min_index != 0. + */ + vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, + min_index, max_index, + _tnl_draw_prims ); + return; + } + else if (max_index >= max) { + /* The software TNL pipeline has a fixed amount of storage for + * vertices and it is necessary to split incoming drawing commands + * if they exceed that limit. + */ + struct split_limits limits; + limits.max_verts = max; + limits.max_vb_size = ~0; + limits.max_indices = ~0; + + /* This will split the buffers one way or another and + * recursively call back into this function. + */ + vbo_split_prims( ctx, arrays, prim, nr_prims, ib, + 0, max_index, + _tnl_draw_prims, + &limits ); + } + else { + /* May need to map a vertex buffer object for every attribute plus + * one for the index buffer. + */ + struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1]; + GLuint nr_bo = 0; + + /* Binding inputs may imply mapping some vertex buffer objects. + * They will need to be unmapped below. + */ + bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo); + bind_indices(ctx, ib, bo, &nr_bo); + bind_prims(ctx, prim, nr_prims ); + + TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); + + unmap_vbos(ctx, bo, nr_bo); + free_space(ctx); + } +} + diff --git a/dist/Mesa/src/mesa/vbo/descrip.mms b/dist/Mesa/src/mesa/vbo/descrip.mms new file mode 100644 index 000000000..4ab22e400 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/descrip.mms @@ -0,0 +1,60 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl +# Last revision : 7 March 2007 + +.first + define gl [---.include.gl] + define math [-.math] + define vbo [-.vbo] + define tnl [-.tnl] + define shader [-.shader] + define swrast [-.swrast] + define swrast_setup [-.swrast_setup] + +.include [---]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [---.include],[-.main],[-.glapi],[-.shader],[-.shader.slang] +LIBDIR = [---.lib] +CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm + +SOURCES =vbo_context.c,vbo_exec.c,vbo_exec_api.c,vbo_exec_array.c,\ + vbo_exec_draw.c,vbo_exec_eval.c,vbo_rebase.c,vbo_save.c,\ + vbo_save_api.c,vbo_save_draw.c,vbo_save_loopback.c,\ + vbo_split.c,vbo_split_copy.c,vbo_split_inplace.c + +OBJECTS =vbo_context.obj,vbo_exec.obj,vbo_exec_api.obj,vbo_exec_array.obj,\ + vbo_exec_draw.obj,vbo_exec_eval.obj,vbo_rebase.obj,vbo_save.obj,\ + vbo_save_api.obj,vbo_save_draw.obj,vbo_save_loopback.obj,\ + vbo_split.obj,vbo_split_copy.obj,vbo_split_inplace.obj + +##### RULES ##### + +VERSION=Mesa V3.4 + +##### TARGETS ##### +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS) + @ library $(LIBDIR)$(GL_LIB) $(OBJECTS) + +clean : + purge + delete *.obj;* + +vbo_context.obj : vbo_context.c +vbo_exec.obj : vbo_exec.c +vbo_exec_api.obj : vbo_exec_api.c +vbo_exec_array.obj : vbo_exec_array.c +vbo_exec_draw.obj : vbo_exec_draw.c +vbo_exec_eval.obj : vbo_exec_eval.c +vbo_rebase.obj : vbo_rebase.c +vbo_save.obj : vbo_save.c +vbo_save_api.obj : vbo_save_api.c +vbo_save_draw.obj : vbo_save_draw.c +vbo_save_loopback.obj : vbo_save_loopback.c +vbo_split.obj : vbo_split.c +vbo_split_copy.obj : vbo_split_copy.c +vbo_split_inplace.obj : vbo_split_inplace.c diff --git a/dist/Mesa/src/mesa/vbo/vbo.h b/dist/Mesa/src/mesa/vbo/vbo.h new file mode 100644 index 000000000..874a5f9e0 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo.h @@ -0,0 +1,117 @@ +/* + * mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file vbo_context.h + * \brief VBO builder module datatypes and definitions. + * \author Keith Whitwell + */ + + +#ifndef _VBO_H +#define _VBO_H + +#include "mtypes.h" + +struct _mesa_prim { + GLuint mode:8; + GLuint indexed:1; + GLuint begin:1; + GLuint end:1; + GLuint weak:1; + GLuint pad:20; + + GLuint start; + GLuint count; +}; + +/* Would like to call this a "vbo_index_buffer", but this would be + * confusing as the indices are not neccessarily yet in a non-null + * buffer object. + */ +struct _mesa_index_buffer { + GLuint count; + GLenum type; + struct gl_buffer_object *obj; + const void *ptr; +}; + + + +GLboolean _vbo_CreateContext( GLcontext *ctx ); +void _vbo_DestroyContext( GLcontext *ctx ); +void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state ); + + +typedef void (*vbo_draw_func)( GLcontext *ctx, + const struct gl_client_array **arrays, + const struct _mesa_prim *prims, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index ); + + + + +/* Utility function to cope with various constraints on tnl modules or + * hardware. This can be used to split an incoming set of arrays and + * primitives against the following constraints: + * - Maximum number of indices in index buffer. + * - Maximum number of vertices referenced by index buffer. + * - Maximum hardware vertex buffer size. + */ +struct split_limits { + GLuint max_verts; + GLuint max_indices; + GLuint max_vb_size; /* bytes */ +}; + + +void vbo_split_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw, + const struct split_limits *limits ); + + +/* Helpers for dealing translating away non-zero min_index. + */ +GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] ); + +void vbo_rebase_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw ); + + +#endif diff --git a/dist/Mesa/src/mesa/vbo/vbo_attrib.h b/dist/Mesa/src/mesa/vbo/vbo_attrib.h new file mode 100644 index 000000000..0ae928f2a --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_attrib.h @@ -0,0 +1,107 @@ +/* + Copyright (C) Intel Corp. 2006. All Rights Reserved. + Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + develop this 3D driver. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice (including the + next paragraph) shall be included in all copies or substantial + portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + **********************************************************************/ + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef VBO_ATTRIB_H +#define VBO_ATTRIB_H + + +/* + * Note: The first attributes match the VERT_ATTRIB_* definitions + * in mtypes.h. However, the tnl module has additional attributes + * for materials, color indexes, edge flags, etc. + */ +/* Although it's nice to use these as bit indexes in a DWORD flag, we + * could manage without if necessary. Another limit currently is the + * number of bits allocated for these numbers in places like vertex + * program instruction formats and register layouts. + */ +enum { + VBO_ATTRIB_POS = 0, + VBO_ATTRIB_WEIGHT = 1, + VBO_ATTRIB_NORMAL = 2, + VBO_ATTRIB_COLOR0 = 3, + VBO_ATTRIB_COLOR1 = 4, + VBO_ATTRIB_FOG = 5, + VBO_ATTRIB_INDEX = 6, + VBO_ATTRIB_EDGEFLAG = 7, + VBO_ATTRIB_TEX0 = 8, + VBO_ATTRIB_TEX1 = 9, + VBO_ATTRIB_TEX2 = 10, + VBO_ATTRIB_TEX3 = 11, + VBO_ATTRIB_TEX4 = 12, + VBO_ATTRIB_TEX5 = 13, + VBO_ATTRIB_TEX6 = 14, + VBO_ATTRIB_TEX7 = 15, + + VBO_ATTRIB_GENERIC0 = 16, /* Not used? */ + VBO_ATTRIB_GENERIC1 = 17, + VBO_ATTRIB_GENERIC2 = 18, + VBO_ATTRIB_GENERIC3 = 19, + VBO_ATTRIB_GENERIC4 = 20, + VBO_ATTRIB_GENERIC5 = 21, + VBO_ATTRIB_GENERIC6 = 22, + VBO_ATTRIB_GENERIC7 = 23, + VBO_ATTRIB_GENERIC8 = 24, + VBO_ATTRIB_GENERIC9 = 25, + VBO_ATTRIB_GENERIC10 = 26, + VBO_ATTRIB_GENERIC11 = 27, + VBO_ATTRIB_GENERIC12 = 28, + VBO_ATTRIB_GENERIC13 = 29, + VBO_ATTRIB_GENERIC14 = 30, + VBO_ATTRIB_GENERIC15 = 31, + + /* XXX: in the vertex program InputsRead flag, we alias + * materials and generics and use knowledge about the program + * (whether it is a fixed-function emulation) to + * differentiate. Here we must keep them apart instead. + */ + VBO_ATTRIB_MAT_FRONT_AMBIENT = 32, + VBO_ATTRIB_MAT_BACK_AMBIENT = 33, + VBO_ATTRIB_MAT_FRONT_DIFFUSE = 34, + VBO_ATTRIB_MAT_BACK_DIFFUSE = 35, + VBO_ATTRIB_MAT_FRONT_SPECULAR = 36, + VBO_ATTRIB_MAT_BACK_SPECULAR = 37, + VBO_ATTRIB_MAT_FRONT_EMISSION = 38, + VBO_ATTRIB_MAT_BACK_EMISSION = 39, + VBO_ATTRIB_MAT_FRONT_SHININESS = 40, + VBO_ATTRIB_MAT_BACK_SHININESS = 41, + VBO_ATTRIB_MAT_FRONT_INDEXES = 42, + VBO_ATTRIB_MAT_BACK_INDEXES = 43, + + VBO_ATTRIB_MAX = 44 +}; + +#define VBO_ATTRIB_FIRST_MATERIAL VBO_ATTRIB_MAT_FRONT_AMBIENT +#define VBO_ATTRIB_LAST_MATERIAL VBO_ATTRIB_MAT_BACK_INDEXES + +#define VBO_MAX_COPIED_VERTS 3 + +#endif diff --git a/dist/Mesa/src/mesa/vbo/vbo_attrib_tmp.h b/dist/Mesa/src/mesa/vbo/vbo_attrib_tmp.h new file mode 100644 index 000000000..ff11c7d59 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_attrib_tmp.h @@ -0,0 +1,486 @@ +/************************************************************************** + +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#define ATTR1FV( A, V ) ATTR( A, 1, (V)[0], 0, 0, 1 ) +#define ATTR2FV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 ) +#define ATTR3FV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 ) +#define ATTR4FV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] ) + +#define ATTR1F( A, X ) ATTR( A, 1, X, 0, 0, 1 ) +#define ATTR2F( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 ) +#define ATTR3F( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 ) +#define ATTR4F( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W ) + +#define MAT_ATTR( A, N, V ) ATTR( A, N, (V)[0], (V)[1], (V)[2], (V)[3] ) + +static void GLAPIENTRY TAG(Vertex2f)( GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR2F( VBO_ATTRIB_POS, x, y ); +} + +static void GLAPIENTRY TAG(Vertex2fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR2FV( VBO_ATTRIB_POS, v ); +} + +static void GLAPIENTRY TAG(Vertex3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_POS, x, y, z ); +} + +static void GLAPIENTRY TAG(Vertex3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_POS, v ); +} + +static void GLAPIENTRY TAG(Vertex4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4F( VBO_ATTRIB_POS, x, y, z, w ); +} + +static void GLAPIENTRY TAG(Vertex4fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4FV( VBO_ATTRIB_POS, v ); +} + +static void GLAPIENTRY TAG(TexCoord1f)( GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1F( VBO_ATTRIB_TEX0, x ); +} + +static void GLAPIENTRY TAG(TexCoord1fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1FV( VBO_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY TAG(TexCoord2f)( GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR2F( VBO_ATTRIB_TEX0, x, y ); +} + +static void GLAPIENTRY TAG(TexCoord2fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR2FV( VBO_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY TAG(TexCoord3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_TEX0, x, y, z ); +} + +static void GLAPIENTRY TAG(TexCoord3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY TAG(TexCoord4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4F( VBO_ATTRIB_TEX0, x, y, z, w ); +} + +static void GLAPIENTRY TAG(TexCoord4fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4FV( VBO_ATTRIB_TEX0, v ); +} + +static void GLAPIENTRY TAG(Normal3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_NORMAL, x, y, z ); +} + +static void GLAPIENTRY TAG(Normal3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_NORMAL, v ); +} + +static void GLAPIENTRY TAG(FogCoordfEXT)( GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1F( VBO_ATTRIB_FOG, x ); +} + +static void GLAPIENTRY TAG(FogCoordfvEXT)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1FV( VBO_ATTRIB_FOG, v ); +} + +static void GLAPIENTRY TAG(Color3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_COLOR0, x, y, z ); +} + +static void GLAPIENTRY TAG(Color3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_COLOR0, v ); +} + +static void GLAPIENTRY TAG(Color4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4F( VBO_ATTRIB_COLOR0, x, y, z, w ); +} + +static void GLAPIENTRY TAG(Color4fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR4FV( VBO_ATTRIB_COLOR0, v ); +} + +static void GLAPIENTRY TAG(SecondaryColor3fEXT)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3F( VBO_ATTRIB_COLOR1, x, y, z ); +} + +static void GLAPIENTRY TAG(SecondaryColor3fvEXT)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR3FV( VBO_ATTRIB_COLOR1, v ); +} + + +static void GLAPIENTRY TAG(EdgeFlag)( GLboolean b ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1F( VBO_ATTRIB_EDGEFLAG, (GLfloat)b ); +} + +static void GLAPIENTRY TAG(Indexf)( GLfloat f ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1F( VBO_ATTRIB_INDEX, f ); +} + +static void GLAPIENTRY TAG(Indexfv)( const GLfloat *f ) +{ + GET_CURRENT_CONTEXT( ctx ); + ATTR1FV( VBO_ATTRIB_INDEX, f ); +} + + +static void GLAPIENTRY TAG(MultiTexCoord1f)( GLenum target, GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR1F( attr, x ); +} + +static void GLAPIENTRY TAG(MultiTexCoord1fv)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR1FV( attr, v ); +} + +static void GLAPIENTRY TAG(MultiTexCoord2f)( GLenum target, GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR2F( attr, x, y ); +} + +static void GLAPIENTRY TAG(MultiTexCoord2fv)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR2FV( attr, v ); +} + +static void GLAPIENTRY TAG(MultiTexCoord3f)( GLenum target, GLfloat x, GLfloat y, + GLfloat z) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR3F( attr, x, y, z ); +} + +static void GLAPIENTRY TAG(MultiTexCoord3fv)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR3FV( attr, v ); +} + +static void GLAPIENTRY TAG(MultiTexCoord4f)( GLenum target, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR4F( attr, x, y, z, w ); +} + +static void GLAPIENTRY TAG(MultiTexCoord4fv)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0; + ATTR4FV( attr, v ); +} + + +static void GLAPIENTRY TAG(VertexAttrib1fARB)( GLuint index, GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR1F(0, x); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR1F(VBO_ATTRIB_GENERIC0 + index, x); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib1fvARB)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR1FV(0, v); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR1FV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib2fARB)( GLuint index, GLfloat x, + GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR2F(0, x, y); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR2F(VBO_ATTRIB_GENERIC0 + index, x, y); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib2fvARB)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR2FV(0, v); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR2FV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib3fARB)( GLuint index, GLfloat x, + GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR3F(0, x, y, z); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR3F(VBO_ATTRIB_GENERIC0 + index, x, y, z); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib3fvARB)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR3FV(0, v); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR3FV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib4fARB)( GLuint index, GLfloat x, + GLfloat y, GLfloat z, + GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR4F(0, x, y, z, w); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR4F(VBO_ATTRIB_GENERIC0 + index, x, y, z, w); + else + ERROR(); +} + +static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index == 0) + ATTR4FV(0, v); + else if (index < MAX_VERTEX_ATTRIBS) + ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v); + else + ERROR(); +} + + +/* In addition to supporting NV_vertex_program, these entrypoints are + * used by the display list and other code specifically because of + * their property of aliasing with other attributes. (See + * vbo_save_loopback.c) + */ +static void GLAPIENTRY TAG(VertexAttrib1fNV)( GLuint index, GLfloat x ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR1F(index, x); +} + +static void GLAPIENTRY TAG(VertexAttrib1fvNV)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR1FV(index, v); +} + +static void GLAPIENTRY TAG(VertexAttrib2fNV)( GLuint index, GLfloat x, + GLfloat y ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR2F(index, x, y); +} + +static void GLAPIENTRY TAG(VertexAttrib2fvNV)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR2FV(index, v); +} + +static void GLAPIENTRY TAG(VertexAttrib3fNV)( GLuint index, GLfloat x, + GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR3F(index, x, y, z); +} + +static void GLAPIENTRY TAG(VertexAttrib3fvNV)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR3FV(index, v); +} + +static void GLAPIENTRY TAG(VertexAttrib4fNV)( GLuint index, GLfloat x, + GLfloat y, GLfloat z, + GLfloat w ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR4F(index, x, y, z, w); +} + +static void GLAPIENTRY TAG(VertexAttrib4fvNV)( GLuint index, + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + if (index < VBO_ATTRIB_MAX) + ATTR4FV(index, v); +} + + +#define MAT( ATTR, N, face, params ) \ +do { \ + if (face != GL_BACK) \ + MAT_ATTR( ATTR, N, params ); /* front */ \ + if (face != GL_FRONT) \ + MAT_ATTR( ATTR + 1, N, params ); /* back */ \ +} while (0) + + +/* Colormaterial conflicts are dealt with later. + */ +static void GLAPIENTRY TAG(Materialfv)( GLenum face, GLenum pname, + const GLfloat *params ) +{ + GET_CURRENT_CONTEXT( ctx ); + switch (pname) { + case GL_EMISSION: + MAT( VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params ); + break; + case GL_AMBIENT: + MAT( VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + break; + case GL_DIFFUSE: + MAT( VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + break; + case GL_SPECULAR: + MAT( VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params ); + break; + case GL_SHININESS: + MAT( VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params ); + break; + case GL_COLOR_INDEXES: + MAT( VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params ); + break; + case GL_AMBIENT_AND_DIFFUSE: + MAT( VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + MAT( VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + break; + default: + ERROR(); + return; + } +} + + +#undef ATTR1FV +#undef ATTR2FV +#undef ATTR3FV +#undef ATTR4FV + +#undef ATTR1F +#undef ATTR2F +#undef ATTR3F +#undef ATTR4F + +#undef MAT +#undef MAT_ATTR diff --git a/dist/Mesa/src/mesa/vbo/vbo_context.c b/dist/Mesa/src/mesa/vbo/vbo_context.c new file mode 100644 index 000000000..f64f59d11 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_context.c @@ -0,0 +1,247 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "mtypes.h" +#include "vbo.h" +#include "vbo_context.h" +#include "imports.h" +#include "api_arrayelt.h" + +/* Reach out and grab this to use as the default: + */ +extern void _tnl_draw_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prims, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index ); + + + +#define NR_LEGACY_ATTRIBS 16 +#define NR_GENERIC_ATTRIBS 16 +#define NR_MAT_ATTRIBS 12 + +static GLuint check_size( const GLfloat *attr ) +{ + if (attr[3] != 1.0) return 4; + if (attr[2] != 0.0) return 3; + if (attr[1] != 0.0) return 2; + return 1; +} + +static void init_legacy_currval(GLcontext *ctx) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct gl_client_array *arrays = vbo->legacy_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_LEGACY_ATTRIBS); + + /* Set up a constant (StrideB == 0) array for each current + * attribute: + */ + for (i = 0; i < NR_LEGACY_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + /* Size will have to be determined at runtime: + */ + cl->Size = check_size(ctx->Current.Attrib[i]); + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)ctx->Current.Attrib[i]; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + + +static void init_generic_currval(GLcontext *ctx) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct gl_client_array *arrays = vbo->generic_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS); + + for (i = 0; i < NR_GENERIC_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + /* This will have to be determined at runtime: + */ + cl->Size = 1; + cl->Type = GL_FLOAT; + cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + + +static void init_mat_currval(GLcontext *ctx) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct gl_client_array *arrays = vbo->mat_currval; + GLuint i; + + memset(arrays, 0, sizeof(*arrays) * NR_MAT_ATTRIBS); + + /* Set up a constant (StrideB == 0) array for each current + * attribute: + */ + for (i = 0; i < NR_MAT_ATTRIBS; i++) { + struct gl_client_array *cl = &arrays[i]; + + /* Size is fixed for the material attributes, for others will + * be determined at runtime: + */ + switch (i - VERT_ATTRIB_GENERIC0) { + case MAT_ATTRIB_FRONT_SHININESS: + case MAT_ATTRIB_BACK_SHININESS: + cl->Size = 1; + break; + case MAT_ATTRIB_FRONT_INDEXES: + case MAT_ATTRIB_BACK_INDEXES: + cl->Size = 3; + break; + default: + cl->Size = 4; + break; + } + + if (i < MAT_ATTRIB_MAX) + cl->Ptr = (const void *)ctx->Light.Material.Attrib[i]; + else + cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]; + + cl->Type = GL_FLOAT; + cl->Stride = 0; + cl->StrideB = 0; + cl->Enabled = 1; + cl->BufferObj = ctx->Array.NullBufferObj; + } +} + +#if 0 + +static void vbo_exec_current_init( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + GLint i; + + /* setup the pointers for the typical 16 vertex attributes */ + for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++) + exec->vtx.current[i] = ctx->Current.Attrib[i]; + + /* setup pointers for the 12 material attributes */ + for (i = 0; i < MAT_ATTRIB_MAX; i++) + exec->vtx.current[VBO_ATTRIB_FIRST_MATERIAL + i] = + ctx->Light.Material.Attrib[i]; +} +#endif + +GLboolean _vbo_CreateContext( GLcontext *ctx ) +{ + struct vbo_context *vbo = CALLOC_STRUCT(vbo_context); + + ctx->swtnl_im = (void *)vbo; + + /* Initialize the arrayelt helper + */ + if (!ctx->aelt_context && + !_ae_create_context( ctx )) { + return GL_FALSE; + } + + /* TODO: remove these pointers. + */ + vbo->legacy_currval = &vbo->currval[VBO_ATTRIB_POS]; + vbo->generic_currval = &vbo->currval[VBO_ATTRIB_GENERIC0]; + vbo->mat_currval = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT]; + + init_legacy_currval( ctx ); + init_generic_currval( ctx ); + init_mat_currval( ctx ); + + /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type + * of vertex program active. + */ + { + GLuint i; + + /* When no vertex program, pull in the material attributes in + * the 16..32 generic range. + */ + for (i = 0; i < 16; i++) + vbo->map_vp_none[i] = i; + for (i = 0; i < 12; i++) + vbo->map_vp_none[16+i] = VBO_ATTRIB_MAT_FRONT_AMBIENT + i; + for (i = 0; i < 4; i++) + vbo->map_vp_none[28+i] = i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + vbo->map_vp_arb[i] = i; + } + + + /* By default: + */ + vbo->draw_prims = _tnl_draw_prims; + + /* Hook our functions into exec and compile dispatch tables. These + * will pretty much be permanently installed, which means that the + * vtxfmt mechanism can be removed now. + */ + vbo_exec_init( ctx ); + vbo_save_init( ctx ); + + + return GL_TRUE; +} + +void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state ) +{ + _ae_invalidate_state(ctx, new_state); + vbo_exec_invalidate_state(ctx, new_state); +} + + +void _vbo_DestroyContext( GLcontext *ctx ) +{ + if (ctx->aelt_context) { + _ae_destroy_context( ctx ); + ctx->aelt_context = NULL; + } + + vbo_exec_destroy(ctx); + FREE(vbo_context(ctx)); + ctx->swtnl_im = NULL; +} diff --git a/dist/Mesa/src/mesa/vbo/vbo_context.h b/dist/Mesa/src/mesa/vbo/vbo_context.h new file mode 100644 index 000000000..013f81bdd --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_context.h @@ -0,0 +1,108 @@ +/* + * mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file vbo_context.h + * \brief VBO builder module datatypes and definitions. + * \author Keith Whitwell + */ + + +/** + * \mainpage The VBO builder module + * + * This module hooks into the GL dispatch table and catches all vertex + * building and drawing commands, such as glVertex3f, glBegin and + * glDrawArrays. The module stores all incoming vertex data as arrays + * in GL vertex buffer objects (VBOs), and translates all drawing + * commands into calls to a driver supplied DrawPrimitives() callback. + * + * The module captures both immediate mode and display list drawing, + * and manages the allocation, reference counting and deallocation of + * vertex buffer objects itself. + * + * The DrawPrimitives() callback can be either implemented by the + * driver itself or hooked to the tnl module's _tnl_draw_primitives() + * function for hardware without tnl capablilties or during fallbacks. + */ + + +#ifndef _VBO_CONTEXT_H +#define _VBO_CONTEXT_H + +#include "vbo.h" +#include "vbo_attrib.h" +#include "vbo_save.h" +#include "vbo_exec.h" + + +struct vbo_context { + struct gl_client_array currval[VBO_ATTRIB_MAX]; + + /* These point into the above. TODO: remove. + */ + struct gl_client_array *legacy_currval; + struct gl_client_array *generic_currval; + struct gl_client_array *mat_currval; + + GLuint map_vp_none[32]; + GLuint map_vp_arb[32]; + + GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */ + GLfloat CurrentFloatEdgeFlag; + + + struct vbo_exec_context exec; + struct vbo_save_context save; + + /* Callback into the driver. This must always succeed, the driver + * is responsible for initiating any fallback actions required: + */ + vbo_draw_func draw_prims; +}; + + +static INLINE struct vbo_context *vbo_context(GLcontext *ctx) +{ + return (struct vbo_context *)(ctx->swtnl_im); +} + +enum { + VP_NONE = 1, + VP_NV, + VP_ARB +}; + +static INLINE GLuint get_program_mode( GLcontext *ctx ) +{ + if (!ctx->VertexProgram._Current) + return VP_NONE; + else if (ctx->VertexProgram._Current->IsNVProgram) + return VP_NV; + else + return VP_ARB; +} + + +#endif diff --git a/dist/Mesa/src/mesa/vbo/vbo_exec.c b/dist/Mesa/src/mesa/vbo/vbo_exec.c new file mode 100644 index 000000000..7d9587324 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_exec.c @@ -0,0 +1,97 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + +#include "api_arrayelt.h" +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "macros.h" +#include "mtypes.h" +#include "dlist.h" +#include "vtxfmt.h" + +#include "vbo_context.h" + +void vbo_exec_init( GLcontext *ctx ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + exec->ctx = ctx; + + /* Initialize the arrayelt helper + */ + if (!ctx->aelt_context && + !_ae_create_context( ctx )) + return; + + vbo_exec_vtx_init( exec ); + vbo_exec_array_init( exec ); + + /* Hook our functions into exec and compile dispatch tables. + */ + _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt ); + + ctx->Driver.NeedFlush = 0; + ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; + ctx->Driver.FlushVertices = vbo_exec_FlushVertices; + + vbo_exec_invalidate_state( ctx, ~0 ); +} + + +void vbo_exec_destroy( GLcontext *ctx ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (ctx->aelt_context) { + _ae_destroy_context( ctx ); + ctx->aelt_context = NULL; + } + + vbo_exec_vtx_destroy( exec ); + vbo_exec_array_destroy( exec ); +} + +/* Really want to install these callbacks to a central facility to be + * invoked according to the state flags. That will have to wait for a + * mesa rework: + */ +void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (new_state & (_NEW_PROGRAM|_NEW_EVAL)) + exec->eval.recalculate_maps = 1; + + _ae_invalidate_state(ctx, new_state); +} + + + + + diff --git a/dist/Mesa/src/mesa/vbo/vbo_exec.h b/dist/Mesa/src/mesa/vbo/vbo_exec.h new file mode 100644 index 000000000..a9b01e08e --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_exec.h @@ -0,0 +1,165 @@ +/************************************************************************** + +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#ifndef __VBO_EXEC_H__ +#define __VBO_EXEC_H__ + +#include "mtypes.h" +#include "vbo.h" +#include "vbo_attrib.h" + + +#define VBO_MAX_PRIM 64 + +/* Wierd implementation stuff: + */ +#define VBO_VERT_BUFFER_SIZE (1024*16) /* dwords == 64k */ +#define VBO_MAX_ATTR_CODEGEN 16 +#define ERROR_ATTRIB 16 + + + + +struct vbo_exec_eval1_map { + struct gl_1d_map *map; + GLuint sz; +}; + +struct vbo_exec_eval2_map { + struct gl_2d_map *map; + GLuint sz; +}; + + + +struct vbo_exec_copied_vtx { + GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS]; + GLuint nr; +}; + + +typedef void (*vbo_attrfv_func)( const GLfloat * ); + + +struct vbo_exec_context +{ + GLcontext *ctx; + GLvertexformat vtxfmt; + + struct { + struct gl_buffer_object *bufferobj; + GLubyte *buffer_map; + + GLuint vertex_size; + + struct _mesa_prim prim[VBO_MAX_PRIM]; + GLuint prim_count; + + GLfloat *vbptr; /* cursor, points into buffer */ + GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */ + + GLuint vert_count; + GLuint max_vert; + struct vbo_exec_copied_vtx copied; + + GLubyte attrsz[VBO_ATTRIB_MAX]; + GLubyte active_sz[VBO_ATTRIB_MAX]; + + GLfloat *attrptr[VBO_ATTRIB_MAX]; + struct gl_client_array arrays[VBO_ATTRIB_MAX]; + + /* According to program mode, the values above plus current + * values are squashed down to the 32 attributes passed to the + * vertex program below: + */ + GLuint program_mode; + GLuint enabled_flags; + const struct gl_client_array *inputs[VERT_ATTRIB_MAX]; + } vtx; + + + struct { + GLboolean recalculate_maps; + struct vbo_exec_eval1_map map1[VERT_ATTRIB_MAX]; + struct vbo_exec_eval2_map map2[VERT_ATTRIB_MAX]; + } eval; + + struct { + GLuint program_mode; + GLuint enabled_flags; + GLuint array_obj; + + /* These just mirror the current arrayobj (todo: make arrayobj + * look like this and remove the mirror): + */ + const struct gl_client_array *legacy_array[16]; + const struct gl_client_array *generic_array[16]; + + /* Arrays and current values manipulated according to program + * mode, etc. These are the attributes as seen by vertex + * programs: + */ + const struct gl_client_array *inputs[VERT_ATTRIB_MAX]; + } array; +}; + + + +/* External API: + */ +void vbo_exec_init( GLcontext *ctx ); +void vbo_exec_destroy( GLcontext *ctx ); +void vbo_exec_invalidate_state( GLcontext *ctx, GLuint new_state ); +void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ); + + +/* Internal functions: + */ +void vbo_exec_array_init( struct vbo_exec_context *exec ); +void vbo_exec_array_destroy( struct vbo_exec_context *exec ); + + +void vbo_exec_vtx_init( struct vbo_exec_context *exec ); +void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ); +void vbo_exec_vtx_flush( struct vbo_exec_context *exec ); +void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ); + +void vbo_exec_eval_update( struct vbo_exec_context *exec ); + +void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec, + GLfloat u, GLfloat v ); + +void vbo_exec_do_EvalCoord1f( struct vbo_exec_context *exec, + GLfloat u); + +#endif diff --git a/dist/Mesa/src/mesa/vbo/vbo_exec_api.c b/dist/Mesa/src/mesa/vbo/vbo_exec_api.c new file mode 100644 index 000000000..2d4ded0f9 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_exec_api.c @@ -0,0 +1,708 @@ +/************************************************************************** + +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "vtxfmt.h" +#include "dlist.h" +#include "state.h" +#include "light.h" +#include "api_arrayelt.h" +#include "api_noop.h" +#include "dispatch.h" + +#include "vbo_context.h" + +#ifdef ERROR +#undef ERROR +#endif + + +static void reset_attrfv( struct vbo_exec_context *exec ); + + +/* Close off the last primitive, execute the buffer, restart the + * primitive. + */ +static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec ) +{ + if (exec->vtx.prim_count == 0) { + exec->vtx.copied.nr = 0; + exec->vtx.vert_count = 0; + exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; + } + else { + GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin; + GLuint last_count; + + if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + GLint i = exec->vtx.prim_count - 1; + assert(i >= 0); + exec->vtx.prim[i].count = (exec->vtx.vert_count - + exec->vtx.prim[i].start); + } + + last_count = exec->vtx.prim[exec->vtx.prim_count-1].count; + + /* Execute the buffer and save copied vertices. + */ + if (exec->vtx.vert_count) + vbo_exec_vtx_flush( exec ); + else { + exec->vtx.prim_count = 0; + exec->vtx.copied.nr = 0; + } + + /* Emit a glBegin to start the new list. + */ + assert(exec->vtx.prim_count == 0); + + if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive; + exec->vtx.prim[0].start = 0; + exec->vtx.prim[0].count = 0; + exec->vtx.prim_count++; + + if (exec->vtx.copied.nr == last_count) + exec->vtx.prim[0].begin = last_begin; + } + } +} + + +/* Deal with buffer wrapping where provoked by the vertex buffer + * filling up, as opposed to upgrade_vertex(). + */ +void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) +{ + GLfloat *data = exec->vtx.copied.buffer; + GLuint i; + + /* Run pipeline on current vertices, copy wrapped vertices + * to exec->vtx.copied. + */ + vbo_exec_wrap_buffers( exec ); + + /* Copy stored stored vertices to start of new list. + */ + assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); + + for (i = 0 ; i < exec->vtx.copied.nr ; i++) { + _mesa_memcpy( exec->vtx.vbptr, data, + exec->vtx.vertex_size * sizeof(GLfloat)); + exec->vtx.vbptr += exec->vtx.vertex_size; + data += exec->vtx.vertex_size; + exec->vtx.vert_count++; + } + + exec->vtx.copied.nr = 0; +} + + +/* + * Copy the active vertex's values to the ctx->Current fields. + */ +static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); + GLuint i; + + for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + if (exec->vtx.attrsz[i]) { + GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + + /* Note: the exec->vtx.current[i] pointers point into the + * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays. + */ + COPY_CLEAN_4V(current, + exec->vtx.attrsz[i], + exec->vtx.attrptr[i]); + + + /* Given that we explicitly state size here, there is no need + * for the COPY_CLEAN above, could just copy 16 bytes and be + * done. The only problem is when Mesa accesses ctx->Current + * directly. + */ + vbo->currval[i].Size = exec->vtx.attrsz[i]; + + /* This triggers rather too much recalculation of Mesa state + * that doesn't get used (eg light positions). + */ + if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && + i <= VBO_ATTRIB_MAT_BACK_INDEXES) + ctx->NewState |= _NEW_LIGHT; + } + } + + /* Colormaterial -- this kindof sucks. + */ + if (ctx->Light.ColorMaterialEnabled && + exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) { + _mesa_update_color_material(ctx, + ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); + } + + ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; +} + + +static void vbo_exec_copy_from_current( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); + GLint i; + + for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + switch (exec->vtx.attrsz[i]) { + case 4: exec->vtx.attrptr[i][3] = current[3]; + case 3: exec->vtx.attrptr[i][2] = current[2]; + case 2: exec->vtx.attrptr[i][1] = current[1]; + case 1: exec->vtx.attrptr[i][0] = current[0]; + break; + } + } + + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; +} + + +/* Flush existing data, set new attrib size, replay copied vertices. + */ +static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, + GLuint attr, + GLuint newsz ) +{ + GLcontext *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); + GLint lastcount = exec->vtx.vert_count; + GLfloat *tmp; + GLuint oldsz; + GLuint i; + + /* Run pipeline on current vertices, copy wrapped vertices + * to exec->vtx.copied. + */ + vbo_exec_wrap_buffers( exec ); + + + /* Do a COPY_TO_CURRENT to ensure back-copying works for the case + * when the attribute already exists in the vertex and is having + * its size increased. + */ + vbo_exec_copy_to_current( exec ); + + + /* Heuristic: Attempt to isolate attributes received outside + * begin/end so that they don't bloat the vertices. + */ + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && + exec->vtx.attrsz[attr] == 0 && + lastcount > 8 && + exec->vtx.vertex_size) { + reset_attrfv( exec ); + } + + /* Fix up sizes: + */ + oldsz = exec->vtx.attrsz[attr]; + exec->vtx.attrsz[attr] = newsz; + + exec->vtx.vertex_size += newsz - oldsz; + exec->vtx.max_vert = VBO_VERT_BUFFER_SIZE / exec->vtx.vertex_size; + exec->vtx.vert_count = 0; + exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; + + + /* Recalculate all the attrptr[] values + */ + for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) { + if (exec->vtx.attrsz[i]) { + exec->vtx.attrptr[i] = tmp; + tmp += exec->vtx.attrsz[i]; + } + else + exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ + } + + /* Copy from current to repopulate the vertex with correct values. + */ + vbo_exec_copy_from_current( exec ); + + /* Replay stored vertices to translate them + * to new format here. + * + * -- No need to replay - just copy piecewise + */ + if (exec->vtx.copied.nr) + { + GLfloat *data = exec->vtx.copied.buffer; + GLfloat *dest = exec->vtx.vbptr; + GLuint j; + + assert(exec->vtx.vbptr == (GLfloat *)exec->vtx.buffer_map); + + for (i = 0 ; i < exec->vtx.copied.nr ; i++) { + for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { + if (exec->vtx.attrsz[j]) { + if (j == attr) { + if (oldsz) { + COPY_CLEAN_4V( dest, oldsz, data ); + data += oldsz; + dest += newsz; + } else { + const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr; + COPY_SZ_4V( dest, newsz, current ); + dest += newsz; + } + } + else { + GLuint sz = exec->vtx.attrsz[j]; + COPY_SZ_4V( dest, sz, data ); + dest += sz; + data += sz; + } + } + } + } + + exec->vtx.vbptr = dest; + exec->vtx.vert_count += exec->vtx.copied.nr; + exec->vtx.copied.nr = 0; + } +} + + +static void vbo_exec_fixup_vertex( GLcontext *ctx, + GLuint attr, GLuint sz ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + int i; + + if (sz > exec->vtx.attrsz[attr]) { + /* New size is larger. Need to flush existing vertices and get + * an enlarged vertex format. + */ + vbo_exec_wrap_upgrade_vertex( exec, attr, sz ); + } + else if (sz < exec->vtx.active_sz[attr]) { + static const GLfloat id[4] = { 0, 0, 0, 1 }; + + /* New size is smaller - just need to fill in some + * zeros. Don't need to flush or wrap. + */ + for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++) + exec->vtx.attrptr[attr][i-1] = id[i-1]; + } + + exec->vtx.active_sz[attr] = sz; + + /* Does setting NeedFlush belong here? Necessitates resetting + * vtxfmt on each flush (otherwise flags won't get reset + * afterwards). + */ + if (attr == 0) + exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; + else + exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; +} + + + + +/* + */ +#define ATTR( A, N, V0, V1, V2, V3 ) \ +do { \ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \ + \ + if (exec->vtx.active_sz[A] != N) \ + vbo_exec_fixup_vertex(ctx, A, N); \ + \ + { \ + GLfloat *dest = exec->vtx.attrptr[A]; \ + if (N>0) dest[0] = V0; \ + if (N>1) dest[1] = V1; \ + if (N>2) dest[2] = V2; \ + if (N>3) dest[3] = V3; \ + } \ + \ + if ((A) == 0) { \ + GLuint i; \ + \ + for (i = 0; i < exec->vtx.vertex_size; i++) \ + exec->vtx.vbptr[i] = exec->vtx.vertex[i]; \ + \ + exec->vtx.vbptr += exec->vtx.vertex_size; \ + exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ + \ + if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ + vbo_exec_vtx_wrap( exec ); \ + } \ +} while (0) + + +#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ) +#define TAG(x) vbo_##x + +#include "vbo_attrib_tmp.h" + + + + + +/* Eval + */ +static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u ) +{ + GET_CURRENT_CONTEXT( ctx ); + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + { + GLint i; + if (exec->eval.recalculate_maps) + vbo_exec_eval_update( exec ); + + for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { + if (exec->eval.map1[i].map) + if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz) + vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz ); + } + } + + + _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, + exec->vtx.vertex_size * sizeof(GLfloat)); + + vbo_exec_do_EvalCoord1f( exec, u ); + + _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, + exec->vtx.vertex_size * sizeof(GLfloat)); +} + +static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v ) +{ + GET_CURRENT_CONTEXT( ctx ); + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + { + GLint i; + if (exec->eval.recalculate_maps) + vbo_exec_eval_update( exec ); + + for (i = 0; i <= VBO_ATTRIB_TEX7; i++) { + if (exec->eval.map2[i].map) + if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz) + vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz ); + } + + if (ctx->Eval.AutoNormal) + if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3) + vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 ); + } + + _mesa_memcpy( exec->vtx.copied.buffer, exec->vtx.vertex, + exec->vtx.vertex_size * sizeof(GLfloat)); + + vbo_exec_do_EvalCoord2f( exec, u, v ); + + _mesa_memcpy( exec->vtx.vertex, exec->vtx.copied.buffer, + exec->vtx.vertex_size * sizeof(GLfloat)); +} + +static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u ) +{ + vbo_exec_EvalCoord1f( u[0] ); +} + +static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u ) +{ + vbo_exec_EvalCoord2f( u[0], u[1] ); +} + +static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) / + (GLfloat) ctx->Eval.MapGrid1un); + GLfloat u = i * du + ctx->Eval.MapGrid1u1; + + vbo_exec_EvalCoord1f( u ); +} + + +static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j ) +{ + GET_CURRENT_CONTEXT( ctx ); + GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / + (GLfloat) ctx->Eval.MapGrid2un); + GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / + (GLfloat) ctx->Eval.MapGrid2vn); + GLfloat u = i * du + ctx->Eval.MapGrid2u1; + GLfloat v = j * dv + ctx->Eval.MapGrid2v1; + + vbo_exec_EvalCoord2f( u, v ); +} + + +/* Build a list of primitives on the fly. Keep + * ctx->Driver.CurrentExecPrimitive uptodate as well. + */ +static void GLAPIENTRY vbo_exec_Begin( GLenum mode ) +{ + GET_CURRENT_CONTEXT( ctx ); + + if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + int i; + + if (ctx->NewState) { + _mesa_update_state( ctx ); + + /* XXX also need to check if shader enabled, but invalid */ + if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) || + (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBegin (invalid vertex/fragment program)"); + return; + } + + CALL_Begin(ctx->Exec, (mode)); + return; + } + + /* Heuristic: attempt to isolate attributes occuring outside + * begin/end pairs. + */ + if (exec->vtx.vertex_size && !exec->vtx.attrsz[0]) + vbo_exec_FlushVertices( ctx, ~0 ); + + i = exec->vtx.prim_count++; + exec->vtx.prim[i].mode = mode; + exec->vtx.prim[i].begin = 1; + exec->vtx.prim[i].end = 0; + exec->vtx.prim[i].indexed = 0; + exec->vtx.prim[i].weak = 0; + exec->vtx.prim[i].pad = 0; + exec->vtx.prim[i].start = exec->vtx.vert_count; + exec->vtx.prim[i].count = 0; + + ctx->Driver.CurrentExecPrimitive = mode; + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); + +} + +static void GLAPIENTRY vbo_exec_End( void ) +{ + GET_CURRENT_CONTEXT( ctx ); + + if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + int idx = exec->vtx.vert_count; + int i = exec->vtx.prim_count - 1; + + exec->vtx.prim[i].end = 1; + exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start; + + ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; + + if (exec->vtx.prim_count == VBO_MAX_PRIM) + vbo_exec_vtx_flush( exec ); + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); +} + + +static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec ) +{ + GLvertexformat *vfmt = &exec->vtxfmt; + + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Begin = vbo_exec_Begin; + vfmt->CallList = _mesa_CallList; + vfmt->CallLists = _mesa_CallLists; + vfmt->End = vbo_exec_End; + vfmt->EvalCoord1f = vbo_exec_EvalCoord1f; + vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv; + vfmt->EvalCoord2f = vbo_exec_EvalCoord2f; + vfmt->EvalCoord2fv = vbo_exec_EvalCoord2fv; + vfmt->EvalPoint1 = vbo_exec_EvalPoint1; + vfmt->EvalPoint2 = vbo_exec_EvalPoint2; + + vfmt->Rectf = _mesa_noop_Rectf; + vfmt->EvalMesh1 = _mesa_noop_EvalMesh1; + vfmt->EvalMesh2 = _mesa_noop_EvalMesh2; + + + /* from attrib_tmp.h: + */ + vfmt->Color3f = vbo_Color3f; + vfmt->Color3fv = vbo_Color3fv; + vfmt->Color4f = vbo_Color4f; + vfmt->Color4fv = vbo_Color4fv; + vfmt->FogCoordfEXT = vbo_FogCoordfEXT; + vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT; + vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f; + vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv; + vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f; + vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv; + vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f; + vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv; + vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f; + vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv; + vfmt->Normal3f = vbo_Normal3f; + vfmt->Normal3fv = vbo_Normal3fv; + vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT; + vfmt->TexCoord1f = vbo_TexCoord1f; + vfmt->TexCoord1fv = vbo_TexCoord1fv; + vfmt->TexCoord2f = vbo_TexCoord2f; + vfmt->TexCoord2fv = vbo_TexCoord2fv; + vfmt->TexCoord3f = vbo_TexCoord3f; + vfmt->TexCoord3fv = vbo_TexCoord3fv; + vfmt->TexCoord4f = vbo_TexCoord4f; + vfmt->TexCoord4fv = vbo_TexCoord4fv; + vfmt->Vertex2f = vbo_Vertex2f; + vfmt->Vertex2fv = vbo_Vertex2fv; + vfmt->Vertex3f = vbo_Vertex3f; + vfmt->Vertex3fv = vbo_Vertex3fv; + vfmt->Vertex4f = vbo_Vertex4f; + vfmt->Vertex4fv = vbo_Vertex4fv; + + vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB; + vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB; + vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB; + vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB; + vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB; + vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB; + vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB; + vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB; + + vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV; + + vfmt->Materialfv = vbo_Materialfv; + + vfmt->EdgeFlag = vbo_EdgeFlag; + vfmt->Indexf = vbo_Indexf; + vfmt->Indexfv = vbo_Indexfv; + +} + + +void vbo_exec_vtx_init( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + struct vbo_context *vbo = vbo_context(ctx); + GLuint i; + + /* Allocate a buffer object. Will just reuse this object + * continuously. + */ + exec->vtx.bufferobj = ctx->Array.NullBufferObj; + exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64); + + vbo_exec_vtxfmt_init( exec ); + + /* Hook our functions into the dispatch table. + */ + _mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt ); + + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + exec->vtx.attrsz[i] = 0; + exec->vtx.active_sz[i] = 0; + exec->vtx.inputs[i] = &exec->vtx.arrays[i]; + } + + { + struct gl_client_array *arrays = exec->vtx.arrays; + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + } + + exec->vtx.vertex_size = 0; +} + + +void vbo_exec_vtx_destroy( struct vbo_exec_context *exec ) +{ + if (exec->vtx.buffer_map) { + ALIGN_FREE(exec->vtx.buffer_map); + exec->vtx.buffer_map = NULL; + } +} + + +void vbo_exec_FlushVertices( GLcontext *ctx, GLuint flags ) +{ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; + + if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) + return; + + if (exec->vtx.vert_count) { + vbo_exec_vtx_flush( exec ); + } + + if (exec->vtx.vertex_size) { + vbo_exec_copy_to_current( exec ); + reset_attrfv( exec ); + } + + exec->ctx->Driver.NeedFlush = 0; +} + + +static void reset_attrfv( struct vbo_exec_context *exec ) +{ + GLuint i; + + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + exec->vtx.attrsz[i] = 0; + exec->vtx.active_sz[i] = 0; + } + + exec->vtx.vertex_size = 0; +} + diff --git a/dist/Mesa/src/mesa/vbo/vbo_exec_array.c b/dist/Mesa/src/mesa/vbo/vbo_exec_array.c new file mode 100644 index 000000000..1e4c31020 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_exec_array.c @@ -0,0 +1,387 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "glheader.h" +#include "context.h" +#include "state.h" +#include "api_validate.h" +#include "api_noop.h" +#include "dispatch.h" + +#include "vbo_context.h" + +/* Compute min and max elements for drawelements calls. + */ +static void get_minmax_index( GLuint count, GLuint type, + const GLvoid *indices, + GLuint *min_index, + GLuint *max_index) +{ + GLint i; + + switch(type) { + case GL_UNSIGNED_INT: { + const GLuint *ui_indices = (const GLuint *)indices; + GLuint max_ui = ui_indices[0]; + GLuint min_ui = ui_indices[0]; + for (i = 1; i < count; i++) { + if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; + if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; + } + *min_index = min_ui; + *max_index = max_ui; + break; + } + case GL_UNSIGNED_SHORT: { + const GLushort *us_indices = (const GLushort *)indices; + GLuint max_us = us_indices[0]; + GLuint min_us = us_indices[0]; + for (i = 1; i < count; i++) { + if (us_indices[i] > max_us) max_us = us_indices[i]; + if (us_indices[i] < min_us) min_us = us_indices[i]; + } + *min_index = min_us; + *max_index = max_us; + break; + } + case GL_UNSIGNED_BYTE: { + const GLubyte *ub_indices = (const GLubyte *)indices; + GLuint max_ub = ub_indices[0]; + GLuint min_ub = ub_indices[0]; + for (i = 1; i < count; i++) { + if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; + if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; + } + *min_index = min_ub; + *max_index = max_ub; + break; + } + default: + assert(0); + break; + } +} + + +/* Just translate the arrayobj into a sane layout. + */ +static void bind_array_obj( GLcontext *ctx ) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + GLuint i; + + /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array + * rather than as individual named arrays. Then this function can + * go away. + */ + exec->array.legacy_array[VERT_ATTRIB_POS] = &ctx->Array.ArrayObj->Vertex; + exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &vbo->legacy_currval[VERT_ATTRIB_WEIGHT]; + exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &ctx->Array.ArrayObj->Normal; + exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &ctx->Array.ArrayObj->Color; + exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &ctx->Array.ArrayObj->SecondaryColor; + exec->array.legacy_array[VERT_ATTRIB_FOG] = &ctx->Array.ArrayObj->FogCoord; + exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &ctx->Array.ArrayObj->Index; + exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &ctx->Array.ArrayObj->EdgeFlag; + + for (i = 0; i < 8; i++) + exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &ctx->Array.ArrayObj->TexCoord[i]; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + exec->array.generic_array[i] = &ctx->Array.ArrayObj->VertexAttrib[i]; + + exec->array.array_obj = ctx->Array.ArrayObj->Name; +} + +static void recalculate_input_bindings( GLcontext *ctx ) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + const struct gl_client_array **inputs = &exec->array.inputs[0]; + GLuint i; + + exec->array.program_mode = get_program_mode(ctx); + exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled; + + switch (exec->array.program_mode) { + case VP_NONE: + /* When no vertex program is active, we put the material values + * into the generic slots. This is the only situation where + * material values are available as per-vertex attributes. + */ + for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { + if (exec->array.legacy_array[i]->Enabled) + inputs[i] = exec->array.legacy_array[i]; + else + inputs[i] = &vbo->legacy_currval[i]; + } + + for (i = 0; i < MAT_ATTRIB_MAX; i++) { + inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i]; + } + + /* Could use just about anything, just to fill in the empty + * slots: + */ + for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) + inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; + + break; + case VP_NV: + /* NV_vertex_program - attribute arrays alias and override + * conventional, legacy arrays. No materials, and the generic + * slots are vacant. + */ + for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { + if (exec->array.generic_array[i]->Enabled) + inputs[i] = exec->array.generic_array[i]; + else if (exec->array.legacy_array[i]->Enabled) + inputs[i] = exec->array.legacy_array[i]; + else + inputs[i] = &vbo->legacy_currval[i]; + } + + /* Could use just about anything, just to fill in the empty + * slots: + */ + for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) + inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0]; + + break; + case VP_ARB: + /* ARB_vertex_program - Only the attribute zero (position) array + * aliases and overrides the legacy position array. + * + * Otherwise, legacy attributes available in the legacy slots, + * generic attributes in the generic slots and materials are not + * available as per-vertex attributes. + */ + if (exec->array.generic_array[0]->Enabled) + inputs[0] = exec->array.generic_array[0]; + else if (exec->array.legacy_array[0]->Enabled) + inputs[0] = exec->array.legacy_array[0]; + else + inputs[0] = &vbo->legacy_currval[0]; + + + for (i = 1; i <= VERT_ATTRIB_TEX7; i++) { + if (exec->array.legacy_array[i]->Enabled) + inputs[i] = exec->array.legacy_array[i]; + else + inputs[i] = &vbo->legacy_currval[i]; + } + + for (i = 0; i < 16; i++) { + if (exec->array.generic_array[i]->Enabled) + inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i]; + else + inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; + } + break; + } +} + +static void bind_arrays( GLcontext *ctx ) +{ +#if 0 + if (ctx->Array.ArrayObj.Name != exec->array.array_obj) { + bind_array_obj(ctx); + recalculate_input_bindings(ctx); + } + else if (exec->array.program_mode != get_program_mode(ctx) || + exec->array.enabled_flags != ctx->Array.ArrayObj->_Enabled) { + + recalculate_input_bindings(ctx); + } +#else + bind_array_obj(ctx); + recalculate_input_bindings(ctx); +#endif +} + + + +/*********************************************************************** + * API functions. + */ + +static void GLAPIENTRY +vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + struct _mesa_prim prim[1]; + + if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) + return; + + FLUSH_CURRENT( ctx, 0 ); + + if (ctx->NewState) + _mesa_update_state( ctx ); + + bind_arrays( ctx ); + + prim[0].begin = 1; + prim[0].end = 1; + prim[0].weak = 0; + prim[0].pad = 0; + prim[0].mode = mode; + prim[0].start = start; + prim[0].count = count; + prim[0].indexed = 0; + + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count - 1 ); +} + + + +static void GLAPIENTRY +vbo_exec_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + struct _mesa_index_buffer ib; + struct _mesa_prim prim[1]; + + if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices )) + return; + + FLUSH_CURRENT( ctx, 0 ); + + if (ctx->NewState) + _mesa_update_state( ctx ); + + bind_arrays( ctx ); + + ib.count = count; + ib.type = type; + ib.obj = ctx->Array.ElementArrayBufferObj; + ib.ptr = indices; + + prim[0].begin = 1; + prim[0].end = 1; + prim[0].weak = 0; + prim[0].pad = 0; + prim[0].mode = mode; + prim[0].start = 0; + prim[0].count = count; + prim[0].indexed = 1; + + /* Need to give special consideration to rendering a range of + * indices starting somewhere above zero. Typically the + * application is issuing multiple DrawRangeElements() to draw + * successive primitives layed out linearly in the vertex arrays. + * Unless the vertex arrays are all in a VBO (or locked as with + * CVA), the OpenGL semantics imply that we need to re-read or + * re-upload the vertex data on each draw call. + * + * In the case of hardware tnl, we want to avoid starting the + * upload at zero, as it will mean every draw call uploads an + * increasing amount of not-used vertex data. Worse - in the + * software tnl module, all those vertices might be transformed and + * lit but never rendered. + * + * If we just upload or transform the vertices in start..end, + * however, the indices will be incorrect. + * + * At this level, we don't know exactly what the requirements of + * the backend are going to be, though it will likely boil down to + * either: + * + * 1) Do nothing, everything is in a VBO and is processed once + * only. + * + * 2) Adjust the indices and vertex arrays so that start becomes + * zero. + * + * Rather than doing anything here, I'll provide a helper function + * for the latter case elsewhere. + */ + + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end ); +} + +static void GLAPIENTRY +vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint min_index = 0; + GLuint max_index = 0; + + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) + return; + + if (ctx->Array.ElementArrayBufferObj->Name) { + const GLvoid *map = ctx->Driver.MapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + GL_READ_ONLY, + ctx->Array.ElementArrayBufferObj); + + get_minmax_index(count, type, ADD_POINTERS(map, indices), &min_index, &max_index); + + ctx->Driver.UnmapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + ctx->Array.ElementArrayBufferObj); + } + else { + get_minmax_index(count, type, indices, &min_index, &max_index); + } + + vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices); +} + + +/*********************************************************************** + * Initialization + */ + + + + +void vbo_exec_array_init( struct vbo_exec_context *exec ) +{ +#if 1 + exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays; + exec->vtxfmt.DrawElements = vbo_exec_DrawElements; + exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements; +#else + exec->vtxfmt.DrawArrays = _mesa_noop_DrawArrays; + exec->vtxfmt.DrawElements = _mesa_noop_DrawElements; + exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements; +#endif +} + + +void vbo_exec_array_destroy( struct vbo_exec_context *exec ) +{ + /* nothing to do */ +} diff --git a/dist/Mesa/src/mesa/vbo/vbo_exec_draw.c b/dist/Mesa/src/mesa/vbo/vbo_exec_draw.c new file mode 100644 index 000000000..d8f167b35 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_exec_draw.c @@ -0,0 +1,228 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "context.h" +#include "enums.h" +#include "state.h" +#include "macros.h" + +#include "vbo_context.h" + + +static void vbo_exec_debug_verts( struct vbo_exec_context *exec ) +{ + GLuint count = exec->vtx.vert_count; + GLuint i; + + _mesa_printf("%s: %u vertices %d primitives, %d vertsize\n", + __FUNCTION__, + count, + exec->vtx.prim_count, + exec->vtx.vertex_size); + + for (i = 0 ; i < exec->vtx.prim_count ; i++) { + struct _mesa_prim *prim = &exec->vtx.prim[i]; + _mesa_printf(" prim %d: %s%s %d..%d %s %s\n", + i, + _mesa_lookup_enum_by_nr(prim->mode), + prim->weak ? " (weak)" : "", + prim->start, + prim->start + prim->count, + prim->begin ? "BEGIN" : "(wrap)", + prim->end ? "END" : "(wrap)"); + } +} + + +/* + * NOTE: Need to have calculated primitives by this point -- do it on the fly. + * NOTE: Old 'parity' issue is gone. + */ +static GLuint vbo_copy_vertices( struct vbo_exec_context *exec ) +{ + GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count; + GLuint ovf, i; + GLuint sz = exec->vtx.vertex_size; + GLfloat *dst = exec->vtx.copied.buffer; + GLfloat *src = ((GLfloat *)exec->vtx.buffer_map + + exec->vtx.prim[exec->vtx.prim_count-1].start * + exec->vtx.vertex_size); + + + switch( exec->ctx->Driver.CurrentExecPrimitive ) + { + case GL_POINTS: + return 0; + case GL_LINES: + ovf = nr&1; + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); + return i; + case GL_TRIANGLES: + ovf = nr%3; + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); + return i; + case GL_QUADS: + ovf = nr&3; + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); + return i; + case GL_LINE_STRIP: + if (nr == 0) + return 0; + else { + _mesa_memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) ); + return 1; + } + case GL_LINE_LOOP: + case GL_TRIANGLE_FAN: + case GL_POLYGON: + if (nr == 0) + return 0; + else if (nr == 1) { + _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) ); + return 1; + } else { + _mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) ); + _mesa_memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) ); + return 2; + } + case GL_TRIANGLE_STRIP: + /* no parity issue, but need to make sure the tri is not drawn twice */ + if (nr & 1) { + exec->vtx.prim[exec->vtx.prim_count-1].count--; + } + /* fallthrough */ + case GL_QUAD_STRIP: + switch (nr) { + case 0: ovf = 0; break; + case 1: ovf = 1; break; + default: ovf = 2 + (nr&1); break; + } + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); + return i; + case GL_POLYGON+1: + return 0; + default: + assert(0); + return 0; + } +} + + + +/* TODO: populate these as the vertex is defined: + */ +static void vbo_exec_bind_arrays( GLcontext *ctx ) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_exec_context *exec = &vbo->exec; + struct gl_client_array *arrays = exec->vtx.arrays; + GLuint count = exec->vtx.vert_count; + GLubyte *data = exec->vtx.buffer_map; + const GLuint *map; + GLuint attr; + + /* Install the default (ie Current) attributes first, then overlay + * all active ones. + */ + switch (get_program_mode(exec->ctx)) { + case VP_NONE: + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->mat_currval, MAT_ATTRIB_MAX * sizeof(arrays[0])); + map = vbo->map_vp_none; + break; + case VP_NV: + case VP_ARB: + /* The aliasing of attributes for NV vertex programs has already + * occurred. NV vertex programs cannot access material values, + * nor attributes greater than VERT_ATTRIB_TEX7. + */ + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + map = vbo->map_vp_arb; + break; + } + + /* Make all active attributes (including edgeflag) available as + * arrays of floats. + */ + for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) { + GLuint src = map[attr]; + + if (exec->vtx.attrsz[src]) { + arrays[attr].Ptr = (void *)data; + arrays[attr].Size = exec->vtx.attrsz[src]; + arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat); + arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); + arrays[attr].Type = GL_FLOAT; + arrays[attr].Enabled = 1; + arrays[attr].BufferObj = exec->vtx.bufferobj; /* NullBufferObj */ + arrays[attr]._MaxElement = count; /* ??? */ + + data += exec->vtx.attrsz[attr] * sizeof(GLfloat); + } + } +} + + +/** + * Execute the buffer and save copied verts. + */ +void vbo_exec_vtx_flush( struct vbo_exec_context *exec ) +{ + if (0) + vbo_exec_debug_verts( exec ); + + + if (exec->vtx.prim_count && + exec->vtx.vert_count) { + + exec->vtx.copied.nr = vbo_copy_vertices( exec ); + + if (exec->vtx.copied.nr != exec->vtx.vert_count) { + GLcontext *ctx = exec->ctx; + + vbo_exec_bind_arrays( ctx ); + + vbo_context(ctx)->draw_prims( ctx, + exec->vtx.inputs, + exec->vtx.prim, + exec->vtx.prim_count, + NULL, + 0, + exec->vtx.vert_count - 1); + } + } + + exec->vtx.prim_count = 0; + exec->vtx.vert_count = 0; + exec->vtx.vbptr = (GLfloat *)exec->vtx.buffer_map; +} diff --git a/dist/Mesa/src/mesa/vbo/vbo_exec_eval.c b/dist/Mesa/src/mesa/vbo/vbo_exec_eval.c new file mode 100644 index 000000000..fe533290b --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_exec_eval.c @@ -0,0 +1,255 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "api_eval.h" +#include "context.h" +#include "macros.h" +#include "math/m_eval.h" +#include "vbo_exec.h" +#include "dispatch.h" + + +static void clear_active_eval1( struct vbo_exec_context *exec, GLuint attr ) +{ + exec->eval.map1[attr].map = NULL; +} + +static void clear_active_eval2( struct vbo_exec_context *exec, GLuint attr ) +{ + exec->eval.map2[attr].map = NULL; +} + +static void set_active_eval1( struct vbo_exec_context *exec, GLuint attr, GLuint dim, + struct gl_1d_map *map ) +{ + if (!exec->eval.map1[attr].map) { + exec->eval.map1[attr].map = map; + exec->eval.map1[attr].sz = dim; + } +} + +static void set_active_eval2( struct vbo_exec_context *exec, GLuint attr, GLuint dim, + struct gl_2d_map *map ) +{ + if (!exec->eval.map2[attr].map) { + exec->eval.map2[attr].map = map; + exec->eval.map2[attr].sz = dim; + } +} + +void vbo_exec_eval_update( struct vbo_exec_context *exec ) +{ + GLcontext *ctx = exec->ctx; + GLuint attr; + + /* Vertex program maps have priority over conventional attribs */ + + for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) { + clear_active_eval1( exec, attr ); + clear_active_eval2( exec, attr ); + } + + /* _NEW_PROGRAM */ + if (ctx->VertexProgram._Enabled) { + for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) { + /* _NEW_EVAL */ + if (ctx->Eval.Map1Attrib[attr]) + set_active_eval1( exec, attr, 4, &ctx->EvalMap.Map1Attrib[attr] ); + + if (ctx->Eval.Map2Attrib[attr]) + set_active_eval2( exec, attr, 4, &ctx->EvalMap.Map2Attrib[attr] ); + } + } + + if (ctx->Eval.Map1Color4) + set_active_eval1( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map1Color4 ); + + if (ctx->Eval.Map2Color4) + set_active_eval2( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map2Color4 ); + + if (ctx->Eval.Map1TextureCoord4) + set_active_eval1( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map1Texture4 ); + else if (ctx->Eval.Map1TextureCoord3) + set_active_eval1( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map1Texture3 ); + else if (ctx->Eval.Map1TextureCoord2) + set_active_eval1( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map1Texture2 ); + else if (ctx->Eval.Map1TextureCoord1) + set_active_eval1( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map1Texture1 ); + + if (ctx->Eval.Map2TextureCoord4) + set_active_eval2( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map2Texture4 ); + else if (ctx->Eval.Map2TextureCoord3) + set_active_eval2( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map2Texture3 ); + else if (ctx->Eval.Map2TextureCoord2) + set_active_eval2( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map2Texture2 ); + else if (ctx->Eval.Map2TextureCoord1) + set_active_eval2( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map2Texture1 ); + + if (ctx->Eval.Map1Normal) + set_active_eval1( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map1Normal ); + + if (ctx->Eval.Map2Normal) + set_active_eval2( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map2Normal ); + + if (ctx->Eval.Map1Vertex4) + set_active_eval1( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map1Vertex4 ); + else if (ctx->Eval.Map1Vertex3) + set_active_eval1( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map1Vertex3 ); + + if (ctx->Eval.Map2Vertex4) + set_active_eval2( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map2Vertex4 ); + else if (ctx->Eval.Map2Vertex3) + set_active_eval2( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map2Vertex3 ); + + exec->eval.recalculate_maps = 0; +} + + + +void vbo_exec_do_EvalCoord1f(struct vbo_exec_context *exec, GLfloat u) +{ + GLuint attr; + + for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) { + struct gl_1d_map *map = exec->eval.map1[attr].map; + if (map) { + GLfloat uu = (u - map->u1) * map->du; + GLfloat data[4]; + + ASSIGN_4V(data, 0, 0, 0, 1); + + _math_horner_bezier_curve(map->Points, data, uu, + exec->eval.map1[attr].sz, + map->Order); + + COPY_SZ_4V( exec->vtx.attrptr[attr], + exec->vtx.attrsz[attr], + data ); + } + } + + /** Vertex -- EvalCoord1f is a noop if this map not enabled: + **/ + if (exec->eval.map1[0].map) { + struct gl_1d_map *map = exec->eval.map1[0].map; + GLfloat uu = (u - map->u1) * map->du; + GLfloat vertex[4]; + + ASSIGN_4V(vertex, 0, 0, 0, 1); + + _math_horner_bezier_curve(map->Points, vertex, uu, + exec->eval.map1[0].sz, + map->Order); + + if (exec->eval.map1[0].sz == 4) + CALL_Vertex4fv(GET_DISPATCH(), ( vertex )); + else + CALL_Vertex3fv(GET_DISPATCH(), ( vertex )); + } +} + + + +void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec, + GLfloat u, GLfloat v ) +{ + GLuint attr; + + for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) { + struct gl_2d_map *map = exec->eval.map2[attr].map; + if (map) { + GLfloat uu = (u - map->u1) * map->du; + GLfloat vv = (v - map->v1) * map->dv; + GLfloat data[4]; + + ASSIGN_4V(data, 0, 0, 0, 1); + + _math_horner_bezier_surf(map->Points, + data, + uu, vv, + exec->eval.map2[attr].sz, + map->Uorder, map->Vorder); + + COPY_SZ_4V( exec->vtx.attrptr[attr], + exec->vtx.attrsz[attr], + data ); + } + } + + /** Vertex -- EvalCoord2f is a noop if this map not enabled: + **/ + if (exec->eval.map2[0].map) { + struct gl_2d_map *map = exec->eval.map2[0].map; + GLfloat uu = (u - map->u1) * map->du; + GLfloat vv = (v - map->v1) * map->dv; + GLfloat vertex[4]; + + ASSIGN_4V(vertex, 0, 0, 0, 1); + + if (exec->ctx->Eval.AutoNormal) { + GLfloat normal[4]; + GLfloat du[4], dv[4]; + + _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, + exec->eval.map2[0].sz, + map->Uorder, map->Vorder); + + if (exec->eval.map2[0].sz == 4) { + du[0] = du[0]*vertex[3] - du[3]*vertex[0]; + du[1] = du[1]*vertex[3] - du[3]*vertex[1]; + du[2] = du[2]*vertex[3] - du[3]*vertex[2]; + + dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0]; + dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1]; + dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2]; + } + + + CROSS3(normal, du, dv); + NORMALIZE_3FV(normal); + normal[3] = 1.0; + + COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL], + exec->vtx.attrsz[VBO_ATTRIB_NORMAL], + normal ); + + } + else { + _math_horner_bezier_surf(map->Points, vertex, uu, vv, + exec->eval.map2[0].sz, + map->Uorder, map->Vorder); + } + + if (exec->vtx.attrsz[0] == 4) + CALL_Vertex4fv(GET_DISPATCH(), ( vertex )); + else + CALL_Vertex3fv(GET_DISPATCH(), ( vertex )); + } +} + + diff --git a/dist/Mesa/src/mesa/vbo/vbo_rebase.c b/dist/Mesa/src/mesa/vbo/vbo_rebase.c new file mode 100644 index 000000000..bc4211d85 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_rebase.c @@ -0,0 +1,222 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +/* Helper for drivers which find themselves rendering a range of + * indices starting somewhere above zero. Typically the application + * is issuing multiple DrawArrays() or DrawElements() to draw + * successive primitives layed out linearly in the vertex arrays. + * Unless the vertex arrays are all in a VBO, the OpenGL semantics + * imply that we need to re-upload the vertex data on each draw call. + * In that case, we want to avoid starting the upload at zero, as it + * will mean every draw call uploads an increasing amount of not-used + * vertex data. Worse - in the software tnl module, all those + * vertices will be transformed and lit. + * + * If we just upload the new data, however, the indices will be + * incorrect as we tend to upload each set of vertex data to a new + * region. + * + * This file provides a helper to adjust the arrays, primitives and + * indices of a draw call so that it can be re-issued with a min_index + * of zero. + */ + +#include "glheader.h" +#include "imports.h" +#include "mtypes.h" + +#include "vbo.h" + + +#define REBASE(TYPE) \ +static void *rebase_##TYPE( const void *ptr, \ + GLuint count, \ + TYPE min_index ) \ +{ \ + const TYPE *in = (TYPE *)ptr; \ + TYPE *tmp_indices = malloc(count * sizeof(TYPE)); \ + GLuint i; \ + \ + for (i = 0; i < count; i++) \ + tmp_indices[i] = in[i] - min_index; \ + \ + return (void *)tmp_indices; \ +} + + +REBASE(GLuint) +REBASE(GLushort) +REBASE(GLubyte) + +GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] ) +{ + GLuint i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + if (arrays[i]->StrideB && + arrays[i]->BufferObj->Name == 0) + return GL_FALSE; + + return GL_TRUE; +} + +/* Adjust primitives, indices and vertex definitions so that min_index + * becomes zero. There are lots of reasons for wanting to do this, eg: + * + * Software tnl: + * - any time min_index != 0, otherwise unused vertices lower than + * min_index will be transformed. + * + * Hardware tnl: + * - if ib != NULL and min_index != 0, otherwise vertices lower than + * min_index will be uploaded. Requires adjusting index values. + * + * - if ib == NULL and min_index != 0, just for convenience so this doesn't + * have to be handled within the driver. + * + * Hardware tnl with VBO support: + * - as above, but only when vertices are not (all?) in VBO's. + * - can't save time by trying to upload half a vbo - typically it is + * all or nothing. + */ +void vbo_rebase_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw ) +{ + struct gl_client_array tmp_arrays[VERT_ATTRIB_MAX]; + const struct gl_client_array *tmp_array_pointers[VERT_ATTRIB_MAX]; + + struct _mesa_index_buffer tmp_ib; + struct _mesa_prim *tmp_prims = NULL; + void *tmp_indices = NULL; + GLuint i; + + assert(min_index != 0); + + if (0) + _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); + + if (ib) { + /* Unfortunately need to adjust each index individually. + */ + GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer; + void *ptr; + + if (map_ib) + ctx->Driver.MapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER, + GL_READ_ONLY_ARB, + ib->obj); + + + ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); + + /* Some users might prefer it if we translated elements to + * GLuints here. Others wouldn't... + */ + switch (ib->type) { + case GL_UNSIGNED_INT: + tmp_indices = rebase_GLuint( ptr, ib->count, min_index ); + break; + case GL_UNSIGNED_SHORT: + tmp_indices = rebase_GLushort( ptr, ib->count, min_index ); + break; + case GL_UNSIGNED_BYTE: + tmp_indices = rebase_GLubyte( ptr, ib->count, min_index ); + break; + } + + if (map_ib) + ctx->Driver.UnmapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER, + ib->obj); + + tmp_ib.obj = ctx->Array.NullBufferObj; + tmp_ib.ptr = tmp_indices; + tmp_ib.count = ib->count; + tmp_ib.type = ib->type; + + ib = &tmp_ib; + } + else { + /* Otherwise the primitives need adjustment. + */ + tmp_prims = (struct _mesa_prim *)_mesa_malloc(sizeof(*prim) * nr_prims); + + for (i = 0; i < nr_prims; i++) { + /* If this fails, it could indicate an application error: + */ + assert(prim[i].start >= min_index); + + tmp_prims[i] = prim[i]; + tmp_prims[i].start -= min_index; + } + + prim = tmp_prims; + } + + /* Just need to adjust the pointer values on each incoming array. + * This works for VBO and non-vbo rendering and shouldn't pesimize + * VBO-based upload schemes. However this may still not be a fast + * path for hardware tnl for VBO based rendering as most machines + * will be happier if you just specify a starting vertex value in + * each primitive. + * + * For drivers with hardware tnl, you only want to do this if you + * are forced to, eg non-VBO indexed rendering with start != 0. + */ + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + tmp_arrays[i] = *arrays[i]; + tmp_arrays[i].Ptr += min_index * tmp_arrays[i].StrideB; + tmp_array_pointers[i] = &tmp_arrays[i]; + } + + /* Re-issue the draw call. + */ + draw( ctx, + tmp_array_pointers, + prim, + nr_prims, + ib, + 0, + max_index - min_index ); + + if (tmp_indices) + _mesa_free(tmp_indices); + + if (tmp_prims) + _mesa_free(tmp_prims); +} + + + diff --git a/dist/Mesa/src/mesa/vbo/vbo_save.c b/dist/Mesa/src/mesa/vbo/vbo_save.c new file mode 100644 index 000000000..e7f468796 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_save.c @@ -0,0 +1,89 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + +#include "mtypes.h" +#include "dlist.h" +#include "vtxfmt.h" +#include "imports.h" + +#include "vbo_context.h" + + + +static void vbo_save_callback_init( GLcontext *ctx ) +{ + ctx->Driver.NewList = vbo_save_NewList; + ctx->Driver.EndList = vbo_save_EndList; + ctx->Driver.SaveFlushVertices = vbo_save_SaveFlushVertices; + ctx->Driver.BeginCallList = vbo_save_BeginCallList; + ctx->Driver.EndCallList = vbo_save_EndCallList; + ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin; +} + + + +void vbo_save_init( GLcontext *ctx ) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_save_context *save = &vbo->save; + + save->ctx = ctx; + + vbo_save_api_init( save ); + vbo_save_callback_init(ctx); + + { + struct gl_client_array *arrays = save->arrays; + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + } + + ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; +} + + +void vbo_save_destroy( GLcontext *ctx ) +{ +} + + + + +/* Note that this can occur during the playback of a display list: + */ +void vbo_save_fallback( GLcontext *ctx, GLboolean fallback ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + if (fallback) + save->replay_flags |= VBO_SAVE_FALLBACK; + else + save->replay_flags &= ~VBO_SAVE_FALLBACK; +} + + diff --git a/dist/Mesa/src/mesa/vbo/vbo_save.h b/dist/Mesa/src/mesa/vbo/vbo_save.h new file mode 100644 index 000000000..b81f275a6 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_save.h @@ -0,0 +1,177 @@ +/************************************************************************** + +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#ifndef VBO_SAVE_H +#define VBO_SAVE_H + +#include "mtypes.h" +#include "vbo.h" +#include "vbo_attrib.h" + + +struct vbo_save_copied_vtx { + GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS]; + GLuint nr; +}; + + +/* For display lists, this structure holds a run of vertices of the + * same format, and a strictly well-formed set of begin/end pairs, + * starting on the first vertex and ending at the last. Vertex + * copying on buffer breaks is precomputed according to these + * primitives, though there are situations where the copying will need + * correction at execute-time, perhaps by replaying the list as + * immediate mode commands. + * + * On executing this list, the 'current' values may be updated with + * the values of the final vertex, and often no fixup of the start of + * the vertex list is required. + * + * Eval and other commands that don't fit into these vertex lists are + * compiled using the fallback opcode mechanism provided by dlist.c. + */ +struct vbo_save_vertex_list { + GLubyte attrsz[VBO_ATTRIB_MAX]; + GLuint vertex_size; + + GLuint buffer_offset; + GLuint count; + GLuint wrap_count; /* number of copied vertices at start */ + GLboolean dangling_attr_ref; /* current attr implicitly referenced + outside the list */ + + struct _mesa_prim *prim; + GLuint prim_count; + + struct vbo_save_vertex_store *vertex_store; + struct vbo_save_primitive_store *prim_store; +}; + +/* These buffers should be a reasonable size to support upload to + * hardware. Current vbo implementation will re-upload on any + * changes, so don't make too big or apps which dynamically create + * dlists and use only a few times will suffer. + * + * Consider stategy of uploading regions from the VBO on demand in the + * case of dynamic vbos. Then make the dlist code signal that + * likelyhood as it occurs. No reason we couldn't change usage + * internally even though this probably isn't allowed for client VBOs? + */ +#define VBO_SAVE_BUFFER_SIZE (8*1024) /* dwords */ +#define VBO_SAVE_PRIM_SIZE 128 +#define VBO_SAVE_PRIM_WEAK 0x40 + +#define VBO_SAVE_FALLBACK 0x10000000 + +/* Storage to be shared among several vertex_lists. + */ +struct vbo_save_vertex_store { + struct gl_buffer_object *bufferobj; + GLfloat *buffer; + GLuint used; + GLuint refcount; +}; + +struct vbo_save_primitive_store { + struct _mesa_prim buffer[VBO_SAVE_PRIM_SIZE]; + GLuint used; + GLuint refcount; +}; + + +struct vbo_save_context { + GLcontext *ctx; + GLvertexformat vtxfmt; + struct gl_client_array arrays[VBO_ATTRIB_MAX]; + const struct gl_client_array *inputs[VBO_ATTRIB_MAX]; + + GLubyte attrsz[VBO_ATTRIB_MAX]; + GLubyte active_sz[VBO_ATTRIB_MAX]; + GLuint vertex_size; + + GLfloat *buffer; + GLuint count; + GLuint wrap_count; + GLuint replay_flags; + + struct _mesa_prim *prim; + GLuint prim_count, prim_max; + + struct vbo_save_vertex_store *vertex_store; + struct vbo_save_primitive_store *prim_store; + + GLfloat *vbptr; /* cursor, points into buffer */ + GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */ + GLfloat *attrptr[VBO_ATTRIB_MAX]; + GLuint vert_count; + GLuint max_vert; + GLboolean dangling_attr_ref; + GLboolean have_materials; + + GLuint opcode_vertex_list; + + struct vbo_save_copied_vtx copied; + + GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */ + GLubyte *currentsz[VBO_ATTRIB_MAX]; +}; + + +void vbo_save_init( GLcontext *ctx ); +void vbo_save_destroy( GLcontext *ctx ); +void vbo_save_fallback( GLcontext *ctx, GLboolean fallback ); + +/* save_loopback.c: + */ +void vbo_loopback_vertex_list( GLcontext *ctx, + const GLfloat *buffer, + const GLubyte *attrsz, + const struct _mesa_prim *prim, + GLuint prim_count, + GLuint wrap_count, + GLuint vertex_size); + +/* Callbacks: + */ +void vbo_save_EndList( GLcontext *ctx ); +void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode ); +void vbo_save_EndCallList( GLcontext *ctx ); +void vbo_save_BeginCallList( GLcontext *ctx, struct mesa_display_list *list ); +void vbo_save_SaveFlushVertices( GLcontext *ctx ); +GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode ); + +void vbo_save_playback_vertex_list( GLcontext *ctx, void *data ); + +void vbo_save_api_init( struct vbo_save_context *save ); + +#endif diff --git a/dist/Mesa/src/mesa/vbo/vbo_save_api.c b/dist/Mesa/src/mesa/vbo/vbo_save_api.c new file mode 100644 index 000000000..e7794c2a6 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_save_api.c @@ -0,0 +1,1151 @@ +/************************************************************************** + +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + + +/* Display list compiler attempts to store lists of vertices with the + * same vertex layout. Additionally it attempts to minimize the need + * for execute-time fixup of these vertex lists, allowing them to be + * cached on hardware. + * + * There are still some circumstances where this can be thwarted, for + * example by building a list that consists of one very long primitive + * (eg Begin(Triangles), 1000 vertices, End), and calling that list + * from inside a different begin/end object (Begin(Lines), CallList, + * End). + * + * In that case the code will have to replay the list as individual + * commands through the Exec dispatch table, or fix up the copied + * vertices at execute-time. + * + * The other case where fixup is required is when a vertex attribute + * is introduced in the middle of a primitive. Eg: + * Begin(Lines) + * TexCoord1f() Vertex2f() + * TexCoord1f() Color3f() Vertex2f() + * End() + * + * If the current value of Color isn't known at compile-time, this + * primitive will require fixup. + * + * + * The list compiler currently doesn't attempt to compile lists + * containing EvalCoord or EvalPoint commands. On encountering one of + * these, compilation falls back to opcodes. + * + * This could be improved to fallback only when a mix of EvalCoord and + * Vertex commands are issued within a single primitive. + */ + + +#include "glheader.h" +#include "context.h" +#include "dlist.h" +#include "enums.h" +#include "macros.h" +#include "api_validate.h" +#include "api_arrayelt.h" +#include "vtxfmt.h" +#include "dispatch.h" + +#include "vbo_context.h" + + +#ifdef ERROR +#undef ERROR +#endif + + +/* + * NOTE: Old 'parity' issue is gone, but copying can still be + * wrong-footed on replay. + */ +static GLuint _save_copy_vertices( GLcontext *ctx, + const struct vbo_save_vertex_list *node, + const GLfloat *src_buffer) +{ + struct vbo_save_context *save = &vbo_context( ctx )->save; + const struct _mesa_prim *prim = &node->prim[node->prim_count-1]; + GLuint nr = prim->count; + GLuint sz = save->vertex_size; + const GLfloat *src = src_buffer + prim->start * sz; + GLfloat *dst = save->copied.buffer; + GLuint ovf, i; + + if (prim->end) + return 0; + + switch( prim->mode ) + { + case GL_POINTS: + return 0; + case GL_LINES: + ovf = nr&1; + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + case GL_TRIANGLES: + ovf = nr%3; + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + case GL_QUADS: + ovf = nr&3; + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + case GL_LINE_STRIP: + if (nr == 0) + return 0; + else { + _mesa_memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) ); + return 1; + } + case GL_LINE_LOOP: + case GL_TRIANGLE_FAN: + case GL_POLYGON: + if (nr == 0) + return 0; + else if (nr == 1) { + _mesa_memcpy( dst, src+0, sz*sizeof(GLfloat) ); + return 1; + } else { + _mesa_memcpy( dst, src+0, sz*sizeof(GLfloat) ); + _mesa_memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) ); + return 2; + } + case GL_TRIANGLE_STRIP: + case GL_QUAD_STRIP: + switch (nr) { + case 0: ovf = 0; break; + case 1: ovf = 1; break; + default: ovf = 2 + (nr&1); break; + } + for (i = 0 ; i < ovf ; i++) + _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + default: + assert(0); + return 0; + } +} + + +static struct vbo_save_vertex_store *alloc_vertex_store( GLcontext *ctx ) +{ + struct vbo_save_vertex_store *vertex_store = CALLOC_STRUCT(vbo_save_vertex_store); + + /* obj->Name needs to be non-zero, but won't ever be examined more + * closely than that. In particular these buffers won't be entered + * into the hash and can never be confused with ones visible to the + * user. Perhaps there could be a special number for internal + * buffers: + */ + vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); + + ctx->Driver.BufferData( ctx, + GL_ARRAY_BUFFER_ARB, + VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat), + NULL, + GL_STATIC_DRAW_ARB, + vertex_store->bufferobj); + + vertex_store->buffer = NULL; + vertex_store->used = 0; + vertex_store->refcount = 1; + + return vertex_store; +} + +static void free_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store ) +{ + assert(!vertex_store->buffer); + + if (vertex_store->bufferobj) + ctx->Driver.DeleteBuffer( ctx, vertex_store->bufferobj ); + + FREE( vertex_store ); +} + +static GLfloat *map_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store ) +{ + assert(vertex_store->bufferobj); + assert(!vertex_store->buffer); + vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, /* not used */ + GL_WRITE_ONLY, /* not used */ + vertex_store->bufferobj); + + assert(vertex_store->buffer); + return vertex_store->buffer + vertex_store->used; +} + +static void unmap_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *vertex_store ) +{ + ctx->Driver.UnmapBuffer( ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj ); + vertex_store->buffer = NULL; +} + + +static struct vbo_save_primitive_store *alloc_prim_store( GLcontext *ctx ) +{ + struct vbo_save_primitive_store *store = CALLOC_STRUCT(vbo_save_primitive_store); + (void) ctx; + store->used = 0; + store->refcount = 1; + return store; +} + +static void _save_reset_counters( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + save->prim = save->prim_store->buffer + save->prim_store->used; + save->buffer = (save->vertex_store->buffer + + save->vertex_store->used); + + assert(save->buffer == save->vbptr); + + if (save->vertex_size) + save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / + save->vertex_size); + else + save->max_vert = 0; + + save->vert_count = 0; + save->prim_count = 0; + save->prim_max = VBO_SAVE_PRIM_SIZE - save->prim_store->used; + save->dangling_attr_ref = 0; +} + + +/* Insert the active immediate struct onto the display list currently + * being built. + */ +static void _save_compile_vertex_list( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + struct vbo_save_vertex_list *node; + + /* Allocate space for this structure in the display list currently + * being compiled. + */ + node = (struct vbo_save_vertex_list *) + _mesa_alloc_instruction(ctx, save->opcode_vertex_list, sizeof(*node)); + + if (!node) + return; + + /* Duplicate our template, increment refcounts to the storage structs: + */ + _mesa_memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz)); + node->vertex_size = save->vertex_size; + node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat); + node->count = save->vert_count; + node->wrap_count = save->copied.nr; + node->dangling_attr_ref = save->dangling_attr_ref; + node->prim = save->prim; + node->prim_count = save->prim_count; + node->vertex_store = save->vertex_store; + node->prim_store = save->prim_store; + + node->vertex_store->refcount++; + node->prim_store->refcount++; + + assert(node->attrsz[VBO_ATTRIB_POS] != 0 || + node->count == 0); + + if (save->dangling_attr_ref) + ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS; + + save->vertex_store->used += save->vertex_size * node->count; + save->prim_store->used += node->prim_count; + + + /* Copy duplicated vertices + */ + save->copied.nr = _save_copy_vertices( ctx, node, save->buffer ); + + + /* Deal with GL_COMPILE_AND_EXECUTE: + */ + if (ctx->ExecuteFlag) { + struct _glapi_table *dispatch = GET_DISPATCH(); + + _glapi_set_dispatch(ctx->Exec); + + vbo_loopback_vertex_list( ctx, + (const GLfloat *)((const char *)save->vertex_store->buffer + + node->buffer_offset), + node->attrsz, + node->prim, + node->prim_count, + node->wrap_count, + node->vertex_size); + + _glapi_set_dispatch(dispatch); + } + + + /* Decide whether the storage structs are full, or can be used for + * the next vertex lists as well. + */ + if (save->vertex_store->used > + VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) { + + /* Unmap old store: + */ + unmap_vertex_store( ctx, save->vertex_store ); + + /* Release old reference: + */ + save->vertex_store->refcount--; + assert(save->vertex_store->refcount != 0); + save->vertex_store = NULL; + + /* Allocate and map new store: + */ + save->vertex_store = alloc_vertex_store( ctx ); + save->vbptr = map_vertex_store( ctx, save->vertex_store ); + } + + if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) { + save->prim_store->refcount--; + assert(save->prim_store->refcount != 0); + save->prim_store = alloc_prim_store( ctx ); + } + + /* Reset our structures for the next run of vertices: + */ + _save_reset_counters( ctx ); +} + + +/* TODO -- If no new vertices have been stored, don't bother saving + * it. + */ +static void _save_wrap_buffers( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLint i = save->prim_count - 1; + GLenum mode; + GLboolean weak; + + assert(i < (GLint) save->prim_max); + assert(i >= 0); + + /* Close off in-progress primitive. + */ + save->prim[i].count = (save->vert_count - + save->prim[i].start); + mode = save->prim[i].mode; + weak = save->prim[i].weak; + + /* store the copied vertices, and allocate a new list. + */ + _save_compile_vertex_list( ctx ); + + /* Restart interrupted primitive + */ + save->prim[0].mode = mode; + save->prim[0].weak = weak; + save->prim[0].begin = 0; + save->prim[0].end = 0; + save->prim[0].pad = 0; + save->prim[0].start = 0; + save->prim[0].count = 0; + save->prim_count = 1; +} + + + +/* Called only when buffers are wrapped as the result of filling the + * vertex_store struct. + */ +static void _save_wrap_filled_vertex( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLfloat *data = save->copied.buffer; + GLuint i; + + /* Emit a glEnd to close off the last vertex list. + */ + _save_wrap_buffers( ctx ); + + /* Copy stored stored vertices to start of new list. + */ + assert(save->max_vert - save->vert_count > save->copied.nr); + + for (i = 0 ; i < save->copied.nr ; i++) { + _mesa_memcpy( save->vbptr, data, save->vertex_size * sizeof(GLfloat)); + data += save->vertex_size; + save->vbptr += save->vertex_size; + save->vert_count++; + } +} + + +static void _save_copy_to_current( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLuint i; + + for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + if (save->attrsz[i]) { + save->currentsz[i][0] = save->attrsz[i]; + COPY_CLEAN_4V(save->current[i], + save->attrsz[i], + save->attrptr[i]); + } + } +} + + +static void _save_copy_from_current( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLint i; + + for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + switch (save->attrsz[i]) { + case 4: save->attrptr[i][3] = save->current[i][3]; + case 3: save->attrptr[i][2] = save->current[i][2]; + case 2: save->attrptr[i][1] = save->current[i][1]; + case 1: save->attrptr[i][0] = save->current[i][0]; + case 0: break; + } + } +} + + + + +/* Flush existing data, set new attrib size, replay copied vertices. + */ +static void _save_upgrade_vertex( GLcontext *ctx, + GLuint attr, + GLuint newsz ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLuint oldsz; + GLuint i; + GLfloat *tmp; + + /* Store the current run of vertices, and emit a GL_END. Emit a + * BEGIN in the new buffer. + */ + if (save->vert_count) + _save_wrap_buffers( ctx ); + else + assert( save->copied.nr == 0 ); + + /* Do a COPY_TO_CURRENT to ensure back-copying works for the case + * when the attribute already exists in the vertex and is having + * its size increased. + */ + _save_copy_to_current( ctx ); + + /* Fix up sizes: + */ + oldsz = save->attrsz[attr]; + save->attrsz[attr] = newsz; + + save->vertex_size += newsz - oldsz; + save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / + save->vertex_size); + save->vert_count = 0; + + /* Recalculate all the attrptr[] values: + */ + for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) { + if (save->attrsz[i]) { + save->attrptr[i] = tmp; + tmp += save->attrsz[i]; + } + else + save->attrptr[i] = NULL; /* will not be dereferenced. */ + } + + /* Copy from current to repopulate the vertex with correct values. + */ + _save_copy_from_current( ctx ); + + /* Replay stored vertices to translate them to new format here. + * + * If there are copied vertices and the new (upgraded) attribute + * has not been defined before, this list is somewhat degenerate, + * and will need fixup at runtime. + */ + if (save->copied.nr) + { + GLfloat *data = save->copied.buffer; + GLfloat *dest = save->buffer; + GLuint j; + + /* Need to note this and fix up at runtime (or loopback): + */ + if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) { + assert(oldsz == 0); + save->dangling_attr_ref = GL_TRUE; + } + + for (i = 0 ; i < save->copied.nr ; i++) { + for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { + if (save->attrsz[j]) { + if (j == attr) { + if (oldsz) { + COPY_CLEAN_4V( dest, oldsz, data ); + data += oldsz; + dest += newsz; + } + else { + COPY_SZ_4V( dest, newsz, save->current[attr] ); + dest += newsz; + } + } + else { + GLint sz = save->attrsz[j]; + COPY_SZ_4V( dest, sz, data ); + data += sz; + dest += sz; + } + } + } + } + + save->vbptr = dest; + save->vert_count += save->copied.nr; + } +} + +static void save_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + if (sz > save->attrsz[attr]) { + /* New size is larger. Need to flush existing vertices and get + * an enlarged vertex format. + */ + _save_upgrade_vertex( ctx, attr, sz ); + } + else if (sz < save->active_sz[attr]) { + static GLfloat id[4] = { 0, 0, 0, 1 }; + GLuint i; + + /* New size is equal or smaller - just need to fill in some + * zeros. + */ + for (i = sz ; i <= save->attrsz[attr] ; i++) + save->attrptr[attr][i-1] = id[i-1]; + } + + save->active_sz[attr] = sz; +} + +static void _save_reset_vertex( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLuint i; + + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + save->attrsz[i] = 0; + save->active_sz[i] = 0; + } + + save->vertex_size = 0; +} + + + +#define ERROR() _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); + + +/* Only one size for each attribute may be active at once. Eg. if + * Color3f is installed/active, then Color4f may not be, even if the + * vertex actually contains 4 color coordinates. This is because the + * 3f version won't otherwise set color[3] to 1.0 -- this is the job + * of the chooser function when switching between Color4f and Color3f. + */ +#define ATTR( A, N, V0, V1, V2, V3 ) \ +do { \ + struct vbo_save_context *save = &vbo_context(ctx)->save; \ + \ + if (save->active_sz[A] != N) \ + save_fixup_vertex(ctx, A, N); \ + \ + { \ + GLfloat *dest = save->attrptr[A]; \ + if (N>0) dest[0] = V0; \ + if (N>1) dest[1] = V1; \ + if (N>2) dest[2] = V2; \ + if (N>3) dest[3] = V3; \ + } \ + \ + if ((A) == 0) { \ + GLuint i; \ + \ + for (i = 0; i < save->vertex_size; i++) \ + save->vbptr[i] = save->vertex[i]; \ + \ + save->vbptr += save->vertex_size; \ + \ + if (++save->vert_count >= save->max_vert) \ + _save_wrap_filled_vertex( ctx ); \ + } \ +} while (0) + +#define TAG(x) _save_##x + +#include "vbo_attrib_tmp.h" + + + + +/* Cope with EvalCoord/CallList called within a begin/end object: + * -- Flush current buffer + * -- Fallback to opcodes for the rest of the begin/end object. + */ +#define DO_FALLBACK(ctx) \ +do { \ + struct vbo_save_context *save = &vbo_context(ctx)->save; \ + \ + if (save->vert_count || save->prim_count) \ + _save_compile_vertex_list( ctx ); \ + \ + _save_copy_to_current( ctx ); \ + _save_reset_vertex( ctx ); \ + _save_reset_counters( ctx ); \ + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); \ + ctx->Driver.SaveNeedFlush = 0; \ +} while (0) + +static void GLAPIENTRY _save_EvalCoord1f( GLfloat u ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalCoord1f( u ); +} + +static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalCoord1fv( v ); +} + +static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalCoord2f( u, v ); +} + +static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalCoord2fv( v ); +} + +static void GLAPIENTRY _save_EvalPoint1( GLint i ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalPoint1( i ); +} + +static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->EvalPoint2( i, j ); +} + +static void GLAPIENTRY _save_CallList( GLuint l ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->CallList( l ); +} + +static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v ) +{ + GET_CURRENT_CONTEXT(ctx); + DO_FALLBACK(ctx); + ctx->Save->CallLists( n, type, v ); +} + + + + +/* This begin is hooked into ... Updating of + * ctx->Driver.CurrentSavePrimitive is already taken care of. + */ +GLboolean vbo_save_NotifyBegin( GLcontext *ctx, GLenum mode ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + GLuint i = save->prim_count++; + + assert(i < save->prim_max); + save->prim[i].mode = mode & ~VBO_SAVE_PRIM_WEAK; + save->prim[i].begin = 1; + save->prim[i].end = 0; + save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0; + save->prim[i].pad = 0; + save->prim[i].start = save->vert_count; + save->prim[i].count = 0; + + _mesa_install_save_vtxfmt( ctx, &save->vtxfmt ); + ctx->Driver.SaveNeedFlush = 1; + return GL_TRUE; +} + + + +static void GLAPIENTRY _save_End( void ) +{ + GET_CURRENT_CONTEXT( ctx ); + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLint i = save->prim_count - 1; + + ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; + save->prim[i].end = 1; + save->prim[i].count = (save->vert_count - + save->prim[i].start); + + if (i == (GLint) save->prim_max - 1) { + _save_compile_vertex_list( ctx ); + assert(save->copied.nr == 0); + } + + /* Swap out this vertex format while outside begin/end. Any color, + * etc. received between here and the next begin will be compiled + * as opcodes. + */ + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); +} + + +/* These are all errors as this vtxfmt is only installed inside + * begin/end pairs. + */ +static void GLAPIENTRY _save_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + (void) mode; (void) count; (void) type; (void) indices; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" ); +} + + +static void GLAPIENTRY _save_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + (void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" ); +} + +static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + (void) mode; (void) start; (void) count; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" ); +} + +static void GLAPIENTRY _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + GET_CURRENT_CONTEXT(ctx); + (void) x1; (void) y1; (void) x2; (void) y2; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glRectf" ); +} + +static void GLAPIENTRY _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 ) +{ + GET_CURRENT_CONTEXT(ctx); + (void) mode; (void) i1; (void) i2; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh1" ); +} + +static void GLAPIENTRY _save_EvalMesh2( GLenum mode, GLint i1, GLint i2, + GLint j1, GLint j2 ) +{ + GET_CURRENT_CONTEXT(ctx); + (void) mode; (void) i1; (void) i2; (void) j1; (void) j2; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh2" ); +} + +static void GLAPIENTRY _save_Begin( GLenum mode ) +{ + GET_CURRENT_CONTEXT( ctx ); + (void) mode; + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive glBegin" ); +} + + +/* Unlike the functions above, these are to be hooked into the vtxfmt + * maintained in ctx->ListState, active when the list is known or + * suspected to be outside any begin/end primitive. + */ +static void GLAPIENTRY _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + GET_CURRENT_CONTEXT(ctx); + vbo_save_NotifyBegin( ctx, GL_QUADS | VBO_SAVE_PRIM_WEAK ); + CALL_Vertex2f(GET_DISPATCH(), ( x1, y1 )); + CALL_Vertex2f(GET_DISPATCH(), ( x2, y1 )); + CALL_Vertex2f(GET_DISPATCH(), ( x2, y2 )); + CALL_Vertex2f(GET_DISPATCH(), ( x1, y2 )); + CALL_End(GET_DISPATCH(), ()); +} + + +static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) + return; + + _ae_map_vbos( ctx ); + + vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK ); + + for (i = 0; i < count; i++) + CALL_ArrayElement(GET_DISPATCH(), (start + i)); + CALL_End(GET_DISPATCH(), ()); + + _ae_unmap_vbos( ctx ); +} + +/* Could do better by copying the arrays and element list intact and + * then emitting an indexed prim at runtime. + */ +static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) + return; + + _ae_map_vbos( ctx ); + + vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK ); + + switch (type) { + case GL_UNSIGNED_BYTE: + for (i = 0 ; i < count ; i++) + CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] )); + break; + case GL_UNSIGNED_SHORT: + for (i = 0 ; i < count ; i++) + CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] )); + break; + case GL_UNSIGNED_INT: + for (i = 0 ; i < count ; i++) + CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] )); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + break; + } + + CALL_End(GET_DISPATCH(), ()); + + _ae_unmap_vbos( ctx ); +} + +static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + if (_mesa_validate_DrawRangeElements( ctx, mode, + start, end, + count, type, indices )) + _save_OBE_DrawElements( mode, count, type, indices ); +} + + + + + +static void _save_vtxfmt_init( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLvertexformat *vfmt = &save->vtxfmt; + + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Begin = _save_Begin; + vfmt->Color3f = _save_Color3f; + vfmt->Color3fv = _save_Color3fv; + vfmt->Color4f = _save_Color4f; + vfmt->Color4fv = _save_Color4fv; + vfmt->EdgeFlag = _save_EdgeFlag; + vfmt->End = _save_End; + vfmt->FogCoordfEXT = _save_FogCoordfEXT; + vfmt->FogCoordfvEXT = _save_FogCoordfvEXT; + vfmt->Indexf = _save_Indexf; + vfmt->Indexfv = _save_Indexfv; + vfmt->Materialfv = _save_Materialfv; + vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f; + vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv; + vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f; + vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv; + vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f; + vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv; + vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f; + vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv; + vfmt->Normal3f = _save_Normal3f; + vfmt->Normal3fv = _save_Normal3fv; + vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT; + vfmt->TexCoord1f = _save_TexCoord1f; + vfmt->TexCoord1fv = _save_TexCoord1fv; + vfmt->TexCoord2f = _save_TexCoord2f; + vfmt->TexCoord2fv = _save_TexCoord2fv; + vfmt->TexCoord3f = _save_TexCoord3f; + vfmt->TexCoord3fv = _save_TexCoord3fv; + vfmt->TexCoord4f = _save_TexCoord4f; + vfmt->TexCoord4fv = _save_TexCoord4fv; + vfmt->Vertex2f = _save_Vertex2f; + vfmt->Vertex2fv = _save_Vertex2fv; + vfmt->Vertex3f = _save_Vertex3f; + vfmt->Vertex3fv = _save_Vertex3fv; + vfmt->Vertex4f = _save_Vertex4f; + vfmt->Vertex4fv = _save_Vertex4fv; + vfmt->VertexAttrib1fARB = _save_VertexAttrib1fARB; + vfmt->VertexAttrib1fvARB = _save_VertexAttrib1fvARB; + vfmt->VertexAttrib2fARB = _save_VertexAttrib2fARB; + vfmt->VertexAttrib2fvARB = _save_VertexAttrib2fvARB; + vfmt->VertexAttrib3fARB = _save_VertexAttrib3fARB; + vfmt->VertexAttrib3fvARB = _save_VertexAttrib3fvARB; + vfmt->VertexAttrib4fARB = _save_VertexAttrib4fARB; + vfmt->VertexAttrib4fvARB = _save_VertexAttrib4fvARB; + + vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV; + + /* This will all require us to fallback to saving the list as opcodes: + */ + vfmt->CallList = _save_CallList; /* inside begin/end */ + vfmt->CallLists = _save_CallLists; /* inside begin/end */ + vfmt->EvalCoord1f = _save_EvalCoord1f; + vfmt->EvalCoord1fv = _save_EvalCoord1fv; + vfmt->EvalCoord2f = _save_EvalCoord2f; + vfmt->EvalCoord2fv = _save_EvalCoord2fv; + vfmt->EvalPoint1 = _save_EvalPoint1; + vfmt->EvalPoint2 = _save_EvalPoint2; + + /* These are all errors as we at least know we are in some sort of + * begin/end pair: + */ + vfmt->EvalMesh1 = _save_EvalMesh1; + vfmt->EvalMesh2 = _save_EvalMesh2; + vfmt->Begin = _save_Begin; + vfmt->Rectf = _save_Rectf; + vfmt->DrawArrays = _save_DrawArrays; + vfmt->DrawElements = _save_DrawElements; + vfmt->DrawRangeElements = _save_DrawRangeElements; + +} + + +void vbo_save_SaveFlushVertices( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + /* Noop when we are actually active: + */ + if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM || + ctx->Driver.CurrentSavePrimitive <= GL_POLYGON) + return; + + if (save->vert_count || + save->prim_count) + _save_compile_vertex_list( ctx ); + + _save_copy_to_current( ctx ); + _save_reset_vertex( ctx ); + _save_reset_counters( ctx ); + ctx->Driver.SaveNeedFlush = 0; +} + +void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + (void) list; (void) mode; + + if (!save->prim_store) + save->prim_store = alloc_prim_store( ctx ); + + if (!save->vertex_store) + save->vertex_store = alloc_vertex_store( ctx ); + + save->vbptr = map_vertex_store( ctx, save->vertex_store ); + + _save_reset_vertex( ctx ); + _save_reset_counters( ctx ); + ctx->Driver.SaveNeedFlush = 0; +} + +void vbo_save_EndList( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + unmap_vertex_store( ctx, save->vertex_store ); + + assert(save->vertex_size == 0); +} + +void vbo_save_BeginCallList( GLcontext *ctx, struct mesa_display_list *dlist ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + save->replay_flags |= dlist->flags; +} + +void vbo_save_EndCallList( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + + if (ctx->ListState.CallDepth == 1) { + /* This is correct: want to keep only the VBO_SAVE_FALLBACK + * flag, if it is set: + */ + save->replay_flags &= VBO_SAVE_FALLBACK; + } +} + + +static void vbo_destroy_vertex_list( GLcontext *ctx, void *data ) +{ + struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data; + (void) ctx; + + if ( --node->vertex_store->refcount == 0 ) + free_vertex_store( ctx, node->vertex_store ); + + if ( --node->prim_store->refcount == 0 ) + FREE( node->prim_store ); +} + + +static void vbo_print_vertex_list( GLcontext *ctx, void *data ) +{ + struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data; + GLuint i; + (void) ctx; + + _mesa_debug(NULL, "VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n", + node->count, + node->prim_count, + node->vertex_size); + + for (i = 0 ; i < node->prim_count ; i++) { + struct _mesa_prim *prim = &node->prim[i]; + _mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n", + i, + _mesa_lookup_enum_by_nr(prim->mode), + prim->weak ? " (weak)" : "", + prim->start, + prim->start + prim->count, + (prim->begin) ? "BEGIN" : "(wrap)", + (prim->end) ? "END" : "(wrap)"); + } +} + + +static void _save_current_init( GLcontext *ctx ) +{ + struct vbo_save_context *save = &vbo_context(ctx)->save; + GLint i; + + for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) { + const GLuint j = i - VBO_ATTRIB_POS; + ASSERT(j < VERT_ATTRIB_MAX); + save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j]; + save->current[i] = ctx->ListState.CurrentAttrib[j]; + } + + for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) { + const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL; + ASSERT(j < MAT_ATTRIB_MAX); + save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j]; + save->current[i] = ctx->ListState.CurrentMaterial[j]; + } +} + +/** + * Initialize the display list compiler + */ +void vbo_save_api_init( struct vbo_save_context *save ) +{ + GLcontext *ctx = save->ctx; + GLuint i; + + save->opcode_vertex_list = + _mesa_alloc_opcode( ctx, + sizeof(struct vbo_save_vertex_list), + vbo_save_playback_vertex_list, + vbo_destroy_vertex_list, + vbo_print_vertex_list ); + + ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin; + + _save_vtxfmt_init( ctx ); + _save_current_init( ctx ); + + for (i = 0; i < VBO_ATTRIB_MAX; i++) + save->inputs[i] = &save->arrays[i]; + + /* Hook our array functions into the outside-begin-end vtxfmt in + * ctx->ListState. + */ + ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf; + ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays; + ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements; + ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements; + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); +} + diff --git a/dist/Mesa/src/mesa/vbo/vbo_save_draw.c b/dist/Mesa/src/mesa/vbo/vbo_save_draw.c new file mode 100644 index 000000000..8940551d0 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_save_draw.c @@ -0,0 +1,230 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Author: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "context.h" +#include "imports.h" +#include "mtypes.h" +#include "macros.h" +#include "light.h" +#include "state.h" + +#include "vbo_context.h" + + +/* + * After playback, copy everything but the position from the + * last vertex to the saved state + */ +static void _playback_copy_to_current( GLcontext *ctx, + const struct vbo_save_vertex_list *node ) +{ + struct vbo_context *vbo = vbo_context(ctx); + GLfloat vertex[VBO_ATTRIB_MAX * 4], *data = vertex; + GLuint i, offset; + + if (node->count) + offset = (node->buffer_offset + + (node->count-1) * node->vertex_size * sizeof(GLfloat)); + else + offset = node->buffer_offset; + + ctx->Driver.GetBufferSubData( ctx, 0, offset, + node->vertex_size * sizeof(GLfloat), + data, node->vertex_store->bufferobj ); + + data += node->attrsz[0]; /* skip vertex position */ + + for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { + if (node->attrsz[i]) { + GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + + COPY_CLEAN_4V(current, + node->attrsz[i], + data); + + vbo->currval[i].Size = node->attrsz[i]; + + data += node->attrsz[i]; + + if (i >= VBO_ATTRIB_FIRST_MATERIAL && + i <= VBO_ATTRIB_LAST_MATERIAL) + ctx->NewState |= _NEW_LIGHT; + } + } + + /* Colormaterial -- this kindof sucks. + */ + if (ctx->Light.ColorMaterialEnabled) { + _mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]); + } + + /* CurrentExecPrimitive + */ + if (node->prim_count) { + const struct _mesa_prim *prim = &node->prim[node->prim_count - 1]; + if (prim->end) + ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; + else + ctx->Driver.CurrentExecPrimitive = prim->mode; + } +} + + + +/* Treat the vertex storage as a VBO, define vertex arrays pointing + * into it: + */ +static void vbo_bind_vertex_list( GLcontext *ctx, + const struct vbo_save_vertex_list *node ) +{ + struct vbo_context *vbo = vbo_context(ctx); + struct vbo_save_context *save = &vbo->save; + struct gl_client_array *arrays = save->arrays; + GLuint data = node->buffer_offset; + const GLuint *map; + GLuint attr; + + /* Install the default (ie Current) attributes first, then overlay + * all active ones. + */ + switch (get_program_mode(ctx)) { + case VP_NONE: + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->mat_currval, MAT_ATTRIB_MAX * sizeof(arrays[0])); + map = vbo->map_vp_none; + break; + case VP_NV: + case VP_ARB: + /* The aliasing of attributes for NV vertex programs has already + * occurred. NV vertex programs cannot access material values, + * nor attributes greater than VERT_ATTRIB_TEX7. + */ + memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); + memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + map = vbo->map_vp_arb; + break; + } + + for (attr = 0; attr < VBO_ATTRIB_MAX; attr++) { + if (node->attrsz[attr]) { + arrays[attr].Ptr = (const GLubyte *)data; + arrays[attr].Size = node->attrsz[attr]; + arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); + arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); + arrays[attr].Type = GL_FLOAT; + arrays[attr].Enabled = 1; + arrays[attr].BufferObj = node->vertex_store->bufferobj; + arrays[attr]._MaxElement = node->count; /* ??? */ + + assert(arrays[attr].BufferObj->Name); + + data += node->attrsz[attr] * sizeof(GLfloat); + } + } +} + +static void vbo_save_loopback_vertex_list( GLcontext *ctx, + const struct vbo_save_vertex_list *list ) +{ + const char *buffer = ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, + GL_READ_ONLY, /* ? */ + list->vertex_store->bufferobj); + + vbo_loopback_vertex_list( ctx, + (const GLfloat *)(buffer + list->buffer_offset), + list->attrsz, + list->prim, + list->prim_count, + list->wrap_count, + list->vertex_size); + + ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, + list->vertex_store->bufferobj); +} + + +/** + * Execute the buffer and save copied verts. + */ +void vbo_save_playback_vertex_list( GLcontext *ctx, void *data ) +{ + const struct vbo_save_vertex_list *node = (const struct vbo_save_vertex_list *) data; + struct vbo_save_context *save = &vbo_context(ctx)->save; + + FLUSH_CURRENT(ctx, 0); + + if (node->prim_count > 0 && node->count > 0) { + + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END && + node->prim[0].begin) { + + /* Degenerate case: list is called inside begin/end pair and + * includes operations such as glBegin or glDrawArrays. + */ + if (0) + _mesa_printf("displaylist recursive begin"); + + vbo_save_loopback_vertex_list( ctx, node ); + return; + } + else if (save->replay_flags) { + /* Various degnerate cases: translate into immediate mode + * calls rather than trying to execute in place. + */ + vbo_save_loopback_vertex_list( ctx, node ); + return; + } + + if (ctx->NewState) + _mesa_update_state( ctx ); + + /* XXX also need to check if shader enabled, but invalid */ + if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) || + (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBegin (invalid vertex/fragment program)"); + return; + } + + vbo_bind_vertex_list( ctx, node ); + + vbo_context(ctx)->draw_prims( ctx, + save->inputs, + node->prim, + node->prim_count, + NULL, + 0, /* Node is a VBO, so this is ok */ + node->count - 1); + } + + /* Copy to current? + */ + _playback_copy_to_current( ctx, node ); +} diff --git a/dist/Mesa/src/mesa/vbo/vbo_save_loopback.c b/dist/Mesa/src/mesa/vbo/vbo_save_loopback.c new file mode 100644 index 000000000..430333b84 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_save_loopback.c @@ -0,0 +1,194 @@ +/************************************************************************** + * + * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "swrast_setup/swrast_setup.h" +#include "swrast/swrast.h" +#include "tnl/tnl.h" +#include "context.h" + +#include "vbo_context.h" + +#include "glheader.h" +#include "enums.h" +#include "glapi.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "dispatch.h" + + +typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * ); + + +/* This file makes heavy use of the aliasing of NV vertex attributes + * with the legacy attributes, and also with ARB and Material + * attributes as currently implemented. + */ +static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib1fvNV(ctx->Exec, (target, v)); +} + +static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib2fvNV(ctx->Exec, (target, v)); +} + +static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib3fvNV(ctx->Exec, (target, v)); +} + +static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + CALL_VertexAttrib4fvNV(ctx->Exec, (target, v)); +} + +static attr_func vert_attrfunc[4] = { + VertexAttrib1fvNV, + VertexAttrib2fvNV, + VertexAttrib3fvNV, + VertexAttrib4fvNV +}; + +struct loopback_attr { + GLint target; + GLint sz; + attr_func func; +}; + +/* Don't emit ends and begins on wrapped primitives. Don't replay + * wrapped vertices. If we get here, it's probably because the the + * precalculated wrapping is wrong. + */ +static void loopback_prim( GLcontext *ctx, + const GLfloat *buffer, + const struct _mesa_prim *prim, + GLuint wrap_count, + GLuint vertex_size, + const struct loopback_attr *la, GLuint nr ) +{ + GLint start = prim->start; + GLint end = start + prim->count; + const GLfloat *data; + GLint j; + GLuint k; + + if (0) + _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n", + _mesa_lookup_enum_by_nr(prim->mode), + prim->begin ? "begin" : "..", + prim->end ? "end" : "..", + start, + end); + + if (prim->begin) { + CALL_Begin(GET_DISPATCH(), ( prim->mode )); + } + else { + assert(start == 0); + start += wrap_count; + } + + data = buffer + start * vertex_size; + + for (j = start ; j < end ; j++) { + const GLfloat *tmp = data + la[0].sz; + + for (k = 1 ; k < nr ; k++) { + la[k].func( ctx, la[k].target, tmp ); + tmp += la[k].sz; + } + + /* Fire the vertex + */ + la[0].func( ctx, VBO_ATTRIB_POS, data ); + data = tmp; + } + + if (prim->end) { + CALL_End(GET_DISPATCH(), ()); + } +} + +/* Primitives generated by DrawArrays/DrawElements/Rectf may be + * caught here. If there is no primitive in progress, execute them + * normally, otherwise need to track and discard the generated + * primitives. + */ +static void loopback_weak_prim( GLcontext *ctx, + const struct _mesa_prim *prim ) +{ + /* Use the prim_weak flag to ensure that if this primitive + * wraps, we don't mistake future vertex_lists for part of the + * surrounding primitive. + * + * While this flag is set, we are simply disposing of data + * generated by an operation now known to be a noop. + */ + if (prim->begin) + ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK; + if (prim->end) + ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK; +} + + +void vbo_loopback_vertex_list( GLcontext *ctx, + const GLfloat *buffer, + const GLubyte *attrsz, + const struct _mesa_prim *prim, + GLuint prim_count, + GLuint wrap_count, + GLuint vertex_size) +{ + struct loopback_attr la[VBO_ATTRIB_MAX]; + GLuint i, nr = 0; + + /* All Legacy, NV, ARB and Material attributes are routed through + * the NV attributes entrypoints: + */ + for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { + if (attrsz[i]) { + la[nr].target = i; + la[nr].sz = attrsz[i]; + la[nr].func = vert_attrfunc[attrsz[i]-1]; + nr++; + } + } + + for (i = 0 ; i < prim_count ; i++) { + if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) && + (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)) + { + loopback_weak_prim( ctx, &prim[i] ); + } + else + { + loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr ); + } + } +} diff --git a/dist/Mesa/src/mesa/vbo/vbo_split.c b/dist/Mesa/src/mesa/vbo/vbo_split.c new file mode 100644 index 000000000..ef205a3bb --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_split.c @@ -0,0 +1,161 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +/* Deal with hardware and/or swtnl maximums: + * - maximum number of vertices in buffer + * - maximum number of elements (maybe zero) + * + * The maximums may vary with opengl state (eg if a larger hardware + * vertex is required in this state, the maximum number of vertices + * may be smaller than in another state). + * + * We want buffer splitting to be a convenience function for the code + * actually drawing the primitives rather than a system-wide maximum, + * otherwise it is hard to avoid pessimism. + * + * For instance, if a driver has no hardware limits on vertex buffer + * dimensions, it would not ordinarily want to split vbos. But if + * there is an unexpected fallback, eg memory manager fails to upload + * textures, it will want to pass the drawing commands onto swtnl, + * which does have limitations. A convenience function allows swtnl + * to split the drawing and vbos internally without imposing its + * limitations on drivers which want to use it as a fallback path. + */ + +#include "glheader.h" +#include "imports.h" +#include "mtypes.h" + +#include "vbo_split.h" +#include "vbo.h" + +/* True if a primitive can be split without copying of vertices, false + * otherwise. + */ +GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr) +{ + switch (mode) { + case GL_POINTS: + *first = 1; + *incr = 1; + return GL_TRUE; + case GL_LINES: + *first = 2; + *incr = 2; + return GL_TRUE; + case GL_LINE_STRIP: + *first = 2; + *incr = 1; + return GL_TRUE; + case GL_TRIANGLES: + *first = 3; + *incr = 3; + return GL_TRUE; + case GL_TRIANGLE_STRIP: + *first = 3; + *incr = 1; + return GL_TRUE; + case GL_QUADS: + *first = 4; + *incr = 4; + return GL_TRUE; + case GL_QUAD_STRIP: + *first = 4; + *incr = 2; + return GL_TRUE; + default: + *first = 0; + *incr = 1; /* so that count % incr works */ + return GL_FALSE; + } +} + + + +void vbo_split_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw, + const struct split_limits *limits ) +{ + + if (ib) { + if (limits->max_indices == 0) { + /* Could traverse the indices, re-emitting vertices in turn. + * But it's hard to see why this case would be needed - for + * software tnl, it is better to convert to non-indexed + * rendering after transformation is complete, as is done in + * the t_dd_rendertmp.h templates. Are there any devices + * with hardware tnl that cannot do indexed rendering? + * + * For now, this path is disabled. + */ + assert(0); + } + else if (max_index - min_index >= limits->max_verts) { + /* The vertex buffers are too large for hardware (or the + * swtnl module). Traverse the indices, re-emitting vertices + * in turn. Use a vertex cache to preserve some of the + * sharing from the original index list. + */ + vbo_split_copy(ctx, arrays, prim, nr_prims, ib, + draw, limits ); + } + else if (ib->count > limits->max_indices) { + /* The index buffer is too large for hardware. Try to split + * on whole-primitive boundaries, otherwise try to split the + * individual primitives. + */ + vbo_split_inplace(ctx, arrays, prim, nr_prims, ib, + min_index, max_index, draw, limits ); + } + else { + /* Why were we called? */ + assert(0); + } + } + else { + if (max_index - min_index >= limits->max_verts) { + /* The vertex buffer is too large for hardware (or the swtnl + * module). Try to split on whole-primitive boundaries, + * otherwise try to split the individual primitives. + */ + vbo_split_inplace(ctx, arrays, prim, nr_prims, ib, + min_index, max_index, draw, limits ); + } + else { + /* Why were we called? */ + assert(0); + } + } +} + diff --git a/dist/Mesa/src/mesa/vbo/vbo_split.h b/dist/Mesa/src/mesa/vbo/vbo_split.h new file mode 100644 index 000000000..05888d048 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_split.h @@ -0,0 +1,72 @@ +/* + * mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file vbo_context.h + * \brief VBO builder module datatypes and definitions. + * \author Keith Whitwell + */ + + +/** + * \mainpage The VBO splitter + * + * This is the private data used internally to the vbo_split_prims() + * helper function. Nobody outside the vbo_split* files needs to + * include or know about this structure. + */ + + +#ifndef _VBO_SPLIT_H +#define _VBO_SPLIT_H + +#include "vbo.h" + + +/* True if a primitive can be split without copying of vertices, false + * otherwise. + */ +GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr); + +void vbo_split_inplace( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw, + const struct split_limits *limits ); + +/* Requires ib != NULL: + */ +void vbo_split_copy( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + vbo_draw_func draw, + const struct split_limits *limits ); + +#endif diff --git a/dist/Mesa/src/mesa/vbo/vbo_split_copy.c b/dist/Mesa/src/mesa/vbo/vbo_split_copy.c new file mode 100644 index 000000000..e142dde68 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_split_copy.c @@ -0,0 +1,551 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +/* Split indexed primitives with per-vertex copying. + */ + +#include "glheader.h" +#include "imports.h" +#include "macros.h" +#include "enums.h" +#include "mtypes.h" + +#include "vbo_split.h" +#include "vbo.h" + + +#define ELT_TABLE_SIZE 16 + +/* Used for vertex-level splitting of indexed buffers. Note that + * non-indexed primitives may be converted to indexed in some cases + * (eg loops, fans) in order to use this splitting path. + */ +struct copy_context { + + GLcontext *ctx; + const struct gl_client_array **array; + const struct _mesa_prim *prim; + GLuint nr_prims; + const struct _mesa_index_buffer *ib; + vbo_draw_func draw; + + const struct split_limits *limits; + + struct { + GLuint attr; + GLuint size; + const struct gl_client_array *array; + const GLubyte *src_ptr; + + struct gl_client_array dstarray; + + } varying[VERT_ATTRIB_MAX]; + GLuint nr_varying; + + const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX]; + struct _mesa_index_buffer dstib; + + GLuint *translated_elt_buf; + const GLuint *srcelt; + + /* A baby hash table to avoid re-emitting (some) duplicate + * vertices when splitting indexed primitives. + */ + struct { + GLuint in; + GLuint out; + } vert_cache[ELT_TABLE_SIZE]; + + + GLuint vertex_size; + GLubyte *dstbuf; + GLubyte *dstptr; /* dstptr == dstbuf + dstelt_max * vertsize */ + GLuint dstbuf_size; /* in vertices */ + GLuint dstbuf_nr; /* count of emitted vertices, also the + * largest value in dstelt. Our + * MaxIndex. + */ + + GLuint *dstelt; + GLuint dstelt_nr; + GLuint dstelt_size; + +#define MAX_PRIM 32 + struct _mesa_prim dstprim[MAX_PRIM]; + GLuint dstprim_nr; + +}; + + +static GLuint type_size( GLenum type ) +{ + switch(type) { + case GL_BYTE: return sizeof(GLbyte); + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + case GL_SHORT: return sizeof(GLshort); + case GL_UNSIGNED_SHORT: return sizeof(GLushort); + case GL_INT: return sizeof(GLint); + case GL_UNSIGNED_INT: return sizeof(GLuint); + case GL_FLOAT: return sizeof(GLfloat); + case GL_DOUBLE: return sizeof(GLdouble); + default: return 0; + } +} + +static GLuint attr_size( const struct gl_client_array *array ) +{ + return array->Size * type_size(array->Type); +} + + +/* Starts returning true slightly before the buffer fills, to ensure + * that there is sufficient room for any remaining vertices to finish + * off the prim: + */ +static GLboolean check_flush( struct copy_context *copy ) +{ + if (copy->dstbuf_nr + 4 > copy->dstbuf_size) + return GL_TRUE; + + if (copy->dstelt_nr + 4 > copy->dstelt_size) + return GL_TRUE; + + return GL_FALSE; +} + +static void flush( struct copy_context *copy ) +{ + GLuint i; + + /* Set some counters: + */ + copy->dstib.count = copy->dstelt_nr; + + copy->draw( copy->ctx, + copy->dstarray_ptr, + copy->dstprim, + copy->dstprim_nr, + ©->dstib, + 0, + copy->dstbuf_nr ); + + /* Reset all pointers: + */ + copy->dstprim_nr = 0; + copy->dstelt_nr = 0; + copy->dstbuf_nr = 0; + copy->dstptr = copy->dstbuf; + + /* Clear the vertex cache: + */ + for (i = 0; i < ELT_TABLE_SIZE; i++) + copy->vert_cache[i].in = ~0; +} + + + +static void begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag ) +{ + struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr]; + +/* _mesa_printf("begin %s (%d)\n", _mesa_lookup_enum_by_nr(mode), begin_flag); */ + + prim->mode = mode; + prim->begin = begin_flag; +} + + +/* Use a hashtable to attempt to identify recently-emitted vertices + * and avoid re-emitting them. + */ +static GLuint elt(struct copy_context *copy, GLuint elt_idx) +{ + GLuint elt = copy->srcelt[elt_idx]; + GLuint slot = elt & (ELT_TABLE_SIZE-1); + +/* _mesa_printf("elt %d\n", elt); */ + + /* Look up the incoming element in the vertex cache. Re-emit if + * necessary. + */ + if (copy->vert_cache[slot].in != elt) { + GLubyte *csr = copy->dstptr; + GLuint i; + +/* _mesa_printf(" --> emit to dstelt %d\n", copy->dstbuf_nr); */ + + for (i = 0; i < copy->nr_varying; i++) { + const struct gl_client_array *srcarray = copy->varying[i].array; + const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB; + + memcpy(csr, srcptr, copy->varying[i].size); + csr += copy->varying[i].size; + + if (0) + { + const GLuint *f = (const GLuint *)srcptr; + GLuint j; + _mesa_printf(" varying %d: ", i); + for(j = 0; j < copy->varying[i].size / 4; j++) + _mesa_printf("%x ", f[j]); + _mesa_printf("\n"); + } + + } + + copy->vert_cache[slot].in = elt; + copy->vert_cache[slot].out = copy->dstbuf_nr++; + copy->dstptr += copy->vertex_size; + + assert(csr == copy->dstptr); + assert(copy->dstptr == (copy->dstbuf + + copy->dstbuf_nr * + copy->vertex_size)); + } +/* else */ +/* _mesa_printf(" --> reuse vertex\n"); */ + +/* _mesa_printf(" --> emit %d\n", copy->vert_cache[slot].out); */ + copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out; + return check_flush(copy); +} + +static void end( struct copy_context *copy, GLboolean end_flag ) +{ + struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr]; + +/* _mesa_printf("end (%d)\n", end_flag); */ + + prim->end = end_flag; + prim->count = copy->dstelt_nr - prim->start; + + if (++copy->dstprim_nr == MAX_PRIM || + check_flush(copy)) + flush(copy); +} + + + +static void replay_elts( struct copy_context *copy ) +{ + GLuint i, j, k; + GLboolean split; + + for (i = 0; i < copy->nr_prims; i++) { + const struct _mesa_prim *prim = ©->prim[i]; + const GLuint start = prim->start; + GLuint first, incr; + + switch (prim->mode) { + + case GL_LINE_LOOP: + /* Convert to linestrip and emit the final vertex explicitly, + * but only in the resultant strip that requires it. + */ + j = 0; + while (j != prim->count) { + begin(copy, GL_LINE_STRIP, prim->begin && j == 0); + + for (split = GL_FALSE; j != prim->count && !split; j++) + split = elt(copy, start + j); + + if (j == prim->count) { + /* Done, emit final line. Split doesn't matter as + * it is always raised a bit early so we can emit + * the last verts if necessary! + */ + if (prim->end) + (void)elt(copy, start + 0); + + end(copy, prim->end); + } + else { + /* Wrap + */ + assert(split); + end(copy, 0); + j--; + } + } + break; + + case GL_TRIANGLE_FAN: + case GL_POLYGON: + j = 2; + while (j != prim->count) { + begin(copy, prim->mode, prim->begin && j == 0); + + split = elt(copy, start+0); + assert(!split); + + split = elt(copy, start+j-1); + assert(!split); + + for (; j != prim->count && !split; j++) + split = elt(copy, start+j); + + end(copy, prim->end && j == prim->count); + + if (j != prim->count) { + /* Wrapped the primitive, need to repeat some vertices: + */ + j -= 1; + } + } + break; + + default: + (void)split_prim_inplace(prim->mode, &first, &incr); + + j = 0; + while (j != prim->count) { + + begin(copy, prim->mode, prim->begin && j == 0); + + split = 0; + for (k = 0; k < first; k++, j++) + split |= elt(copy, start+j); + + assert(!split); + + for (; j != prim->count && !split; ) + for (k = 0; k < incr; k++, j++) + split |= elt(copy, start+j); + + end(copy, prim->end && j == prim->count); + + if (j != prim->count) { + /* Wrapped the primitive, need to repeat some vertices: + */ + assert(j > first - incr); + j -= (first - incr); + } + } + break; + } + } + + if (copy->dstprim_nr) + flush(copy); +} + + +static void replay_init( struct copy_context *copy ) +{ + GLcontext *ctx = copy->ctx; + GLuint i; + GLuint offset; + const GLvoid *srcptr; + + /* Make a list of varying attributes and their vbo's. Also + * calculate vertex size. + */ + copy->vertex_size = 0; + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + struct gl_buffer_object *vbo = copy->array[i]->BufferObj; + + if (copy->array[i]->StrideB == 0) { + copy->dstarray_ptr[i] = copy->array[i]; + } + else { + GLuint j = copy->nr_varying++; + + copy->varying[j].attr = i; + copy->varying[j].array = copy->array[i]; + copy->varying[j].size = attr_size(copy->array[i]); + copy->vertex_size += attr_size(copy->array[i]); + + if (vbo->Name && !vbo->Pointer) + ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, + GL_WRITE_ONLY, /* XXX */ + vbo); + + copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer, + copy->array[i]->Ptr); + + copy->dstarray_ptr[i] = ©->varying[j].dstarray; + } + } + + /* There must always be an index buffer. Currently require the + * caller convert non-indexed prims to indexed. Could alternately + * do it internally. + */ + if (copy->ib->obj->Name && !copy->ib->obj->Pointer) + ctx->Driver.MapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, /* XXX */ + GL_WRITE_ONLY, /* XXX */ + copy->ib->obj); + + srcptr = (const GLubyte *)ADD_POINTERS(copy->ib->obj->Pointer, copy->ib->ptr); + + switch (copy->ib->type) { + case GL_UNSIGNED_BYTE: + copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count); + copy->srcelt = copy->translated_elt_buf; + + for (i = 0; i < copy->ib->count; i++) + copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i]; + break; + + case GL_UNSIGNED_SHORT: + copy->translated_elt_buf = _mesa_malloc(sizeof(GLuint) * copy->ib->count); + copy->srcelt = copy->translated_elt_buf; + + for (i = 0; i < copy->ib->count; i++) + copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i]; + break; + + case GL_UNSIGNED_INT: + copy->translated_elt_buf = NULL; + copy->srcelt = (const GLuint *)srcptr; + break; + } + + + /* Figure out the maximum allowed vertex buffer size: + */ + if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) { + copy->dstbuf_size = copy->limits->max_verts; + } + else { + copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size; + } + + /* Allocate an output vertex buffer: + * + * XXX: This should be a VBO! + */ + copy->dstbuf = _mesa_malloc(copy->dstbuf_size * + copy->vertex_size); + copy->dstptr = copy->dstbuf; + + /* Setup new vertex arrays to point into the output buffer: + */ + for (offset = 0, i = 0; i < copy->nr_varying; i++) { + const struct gl_client_array *src = copy->varying[i].array; + struct gl_client_array *dst = ©->varying[i].dstarray; + + dst->Size = src->Size; + dst->Type = src->Type; + dst->Stride = copy->vertex_size; + dst->StrideB = copy->vertex_size; + dst->Ptr = copy->dstbuf + offset; + dst->Enabled = GL_TRUE; + dst->Normalized = GL_TRUE; + dst->BufferObj = ctx->Array.NullBufferObj; + dst->_MaxElement = copy->dstbuf_size; /* may be less! */ + + offset += copy->varying[i].size; + } + + /* Allocate an output element list: + */ + copy->dstelt_size = MIN2(65536, + copy->ib->count * 2 + 3); + copy->dstelt_size = MIN2(copy->dstelt_size, + copy->limits->max_indices); + copy->dstelt = _mesa_malloc(sizeof(GLuint) * copy->dstelt_size); + copy->dstelt_nr = 0; + + /* Setup the new index buffer to point to the allocated element + * list: + */ + copy->dstib.count = 0; /* duplicates dstelt_nr */ + copy->dstib.type = GL_UNSIGNED_INT; + copy->dstib.obj = ctx->Array.NullBufferObj; + copy->dstib.ptr = copy->dstelt; +} + + +static void replay_finish( struct copy_context *copy ) +{ + GLcontext *ctx = copy->ctx; + GLuint i; + + /* Free our vertex and index buffers: + */ + _mesa_free(copy->translated_elt_buf); + _mesa_free(copy->dstbuf); + _mesa_free(copy->dstelt); + + /* Unmap VBO's + */ + for (i = 0; i < copy->nr_varying; i++) { + struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj; + + if (vbo->Name && vbo->Pointer) + ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, vbo); + } + + /* Unmap index buffer: + */ + if (copy->ib->obj->Name && copy->ib->obj->Pointer) { + ctx->Driver.UnmapBuffer(ctx, + GL_ARRAY_BUFFER_ARB, /* XXX */ + copy->ib->obj); + } +} + +void vbo_split_copy( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + vbo_draw_func draw, + const struct split_limits *limits ) +{ + struct copy_context copy; + GLuint i; + + memset(©, 0, sizeof(copy)); + + /* Require indexed primitives: + */ + assert(ib); + + copy.ctx = ctx; + copy.array = arrays; + copy.prim = prim; + copy.nr_prims = nr_prims; + copy.ib = ib; + copy.draw = draw; + copy.limits = limits; + + + /* Clear the vertex cache: + */ + for (i = 0; i < ELT_TABLE_SIZE; i++) + copy.vert_cache[i].in = ~0; + + + replay_init(©); + replay_elts(©); + replay_finish(©); +} diff --git a/dist/Mesa/src/mesa/vbo/vbo_split_inplace.c b/dist/Mesa/src/mesa/vbo/vbo_split_inplace.c new file mode 100644 index 000000000..ea62866e7 --- /dev/null +++ b/dist/Mesa/src/mesa/vbo/vbo_split_inplace.c @@ -0,0 +1,286 @@ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + +#include "mtypes.h" +#include "macros.h" +#include "enums.h" +#include "vbo_split.h" + + +#define MAX_PRIM 32 + +/* Used for splitting without copying. + */ +struct split_context { + GLcontext *ctx; + const struct gl_client_array **array; + const struct _mesa_prim *prim; + GLuint nr_prims; + const struct _mesa_index_buffer *ib; + GLuint min_index; + GLuint max_index; + vbo_draw_func draw; + + const struct split_limits *limits; + + struct _mesa_prim dstprim[MAX_PRIM]; + GLuint dstprim_nr; +}; + + + + +static void flush_vertex( struct split_context *split ) +{ + GLint min_index, max_index; + + if (!split->dstprim_nr) + return; + + if (split->ib) { + /* This should basically be multipass rendering over the same + * unchanging set of VBO's. Would like the driver not to + * re-upload the data, or swtnl not to re-transform the + * vertices. + */ + assert(split->max_index - split->min_index < split->limits->max_verts); + min_index = split->min_index; + max_index = split->max_index; + } + else { + /* Non-indexed rendering. Cannot assume that the primitives are + * ordered by increasing vertex, because of entrypoints like + * MultiDrawArrays. + */ + GLuint i; + min_index = split->dstprim[0].start; + max_index = min_index + split->dstprim[0].count - 1; + + for (i = 1; i < split->dstprim_nr; i++) { + GLuint tmp_min = split->dstprim[i].start; + GLuint tmp_max = tmp_min + split->dstprim[i].count - 1; + + if (tmp_min < min_index) + min_index = tmp_min; + + if (tmp_max > max_index) + max_index = tmp_max; + } + } + + assert(max_index >= min_index); + + split->draw( split->ctx, + split->array, + split->dstprim, + split->dstprim_nr, + NULL, + min_index, + max_index); + + split->dstprim_nr = 0; +} + + +static struct _mesa_prim *next_outprim( struct split_context *split ) +{ + if (split->dstprim_nr == MAX_PRIM-1) { + flush_vertex(split); + } + + { + struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++]; + memset(prim, 0, sizeof(*prim)); + return prim; + } +} + +static int align(int value, int alignment) +{ + return (value + alignment - 1) & ~(alignment - 1); +} + + + +/* Break large primitives into smaller ones. If not possible, convert + * the primitive to indexed and pass to split_elts(). + */ +static void split_prims( struct split_context *split) +{ + GLuint csr = 0; + GLuint i; + + for (i = 0; i < split->nr_prims; i++) { + const struct _mesa_prim *prim = &split->prim[i]; + GLuint first, incr; + GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr); + GLuint count; + + /* Always wrap on an even numbered vertex to avoid problems with + * triangle strips. + */ + GLuint available = align(split->limits->max_verts - csr - 1, 2); + assert(split->limits->max_verts >= csr); + + if (prim->count < first) + continue; + + count = prim->count - (prim->count - first) % incr; + + + if ((available < count && !split_inplace) || + (available < first && split_inplace)) { + flush_vertex(split); + csr = 0; + available = align(split->limits->max_verts - csr - 1, 2); + } + + if (available >= count) { + struct _mesa_prim *outprim = next_outprim(split); + *outprim = *prim; + csr += prim->count; + available = align(split->limits->max_verts - csr - 1, 2); + } + else if (split_inplace) { + GLuint j, nr; + + + for (j = 0 ; j < count ; ) { + GLuint remaining = count - j; + struct _mesa_prim *outprim = next_outprim(split); + + nr = MIN2( available, remaining ); + + nr -= (nr - first) % incr; + + outprim->mode = prim->mode; + outprim->begin = (j == 0 && prim->begin); + outprim->end = (nr == remaining && prim->end); + outprim->start = prim->start + j; + outprim->count = nr; + + if (nr == remaining) { + /* Finished. + */ + j += nr; + csr += nr; + available = align(split->limits->max_verts - csr - 1, 2); + } + else { + /* Wrapped the primitive: + */ + j += nr - (first - incr); + flush_vertex(split); + csr = 0; + available = align(split->limits->max_verts - csr - 1, 2); + } + } + } + else if (split->ib == NULL) { + /* XXX: could at least send the first max_verts off from the + * inplace buffers. + */ + + /* else convert to indexed primitive and pass to split_elts, + * which will do the necessary copying and turn it back into a + * vertex primitive for rendering... + */ + struct _mesa_index_buffer ib; + struct _mesa_prim tmpprim; + GLuint *elts = malloc(count * sizeof(GLuint)); + GLuint j; + + for (j = 0; j < count; j++) + elts[j] = prim->start + j; + + ib.count = count; + ib.type = GL_UNSIGNED_INT; + ib.obj = split->ctx->Array.NullBufferObj; + ib.ptr = elts; + + tmpprim = *prim; + tmpprim.indexed = 1; + tmpprim.start = 0; + tmpprim.count = count; + + flush_vertex(split); + + vbo_split_copy(split->ctx, + split->array, + &tmpprim, 1, + &ib, + split->draw, + split->limits); + + free(elts); + } + else { + flush_vertex(split); + + vbo_split_copy(split->ctx, + split->array, + prim, 1, + split->ib, + split->draw, + split->limits); + } + } + + flush_vertex(split); +} + + +void vbo_split_inplace( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLuint min_index, + GLuint max_index, + vbo_draw_func draw, + const struct split_limits *limits ) +{ + struct split_context split; + + memset(&split, 0, sizeof(split)); + + split.ctx = ctx; + split.array = arrays; + split.prim = prim; + split.nr_prims = nr_prims; + split.ib = ib; + split.min_index = min_index; + split.max_index = max_index; + split.draw = draw; + split.limits = limits; + + split_prims( &split ); +} + + |