Back to index

nux  3.0.0
GLTextureStates.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "GLResource.h"
00024 #include "GLTextureStates.h"
00025 
00026 namespace nux
00027 {
00028 
00029   const struct TextureStateLookUpTable
00030   {
00031     TextureStateLookUpTable()
00032     {
00033       // setup render state map
00034 #define UL_MAP(state__, default_value__, checked__)                          \
00035         default_texture_state[GFXTS_##state__].iValue     = default_value__;  \
00036         default_texture_state[GFXTS_##state__].Checked   = checked__;
00037 
00038 #define UL_MAP_FLOAT(state__, default_value__, checked__)                    \
00039     default_texture_state[GFXTS_##state__].fValue     = default_value__;      \
00040     default_texture_state[GFXTS_##state__].Checked   = checked__;
00041 
00042       UL_MAP(ADDRESSU               ,           GL_REPEAT       ,       1);
00043       UL_MAP(ADDRESSV               ,           GL_REPEAT       ,       1);
00044       UL_MAP(ADDRESSW               ,           GL_REPEAT       ,       1);
00045 
00046       UL_MAP(MINFILTER              ,           GL_NEAREST      ,       1);
00047       UL_MAP(MAGFILTER              ,           GL_NEAREST      ,       1);
00048       UL_MAP(MIPFILTER              ,           GL_NEAREST      ,       1);
00049 
00050       UL_MAP(MIP_BASE_LEVEL         ,           0               ,       1);
00051       UL_MAP(MIP_MAX_LEVEL          ,           1000            ,       1);
00052       UL_MAP_FLOAT(MIN_LOD          ,           -1000           ,       1);
00053       UL_MAP_FLOAT(MAX_LOD          ,           +1000           ,       1);
00054 
00055       UL_MAP(BORDERCOLOR            ,           0x0             ,       1);
00056 
00057 #undef UL_MAP
00058 #undef UL_MAP_FLOAT
00059     };
00060 
00061     TextureStateMap default_texture_state[GFXTS_MAX_TEXTURESTATES];
00062   } s_TextureStateLUT;
00063 
00064 
00065   GLTextureStates::GLTextureStates(GLuint Type)
00066   {
00067     SetType(Type);
00068     Memcpy(&m_TextureStateChanges, &s_TextureStateLUT.default_texture_state, sizeof(m_TextureStateChanges));
00069   }
00070 
00071   GLTextureStates::~GLTextureStates()
00072   {
00073 
00074   }
00075 
00076   void GLTextureStates::SetType(GLuint Type)
00077   {
00078 #ifndef NUX_OPENGLES_20
00079     nuxAssertMsg(
00080       (Type == GL_TEXTURE_1D) ||
00081       (Type == GL_TEXTURE_2D) ||
00082       (Type == GL_TEXTURE_RECTANGLE_ARB) ||
00083       (Type == GL_TEXTURE_3D) ||
00084       (Type == GL_TEXTURE_CUBE_MAP_ARB),
00085       "Error[GLTextureStates::GLTextureStates]: Invalid texture type.");
00086 #else
00087     nuxAssertMsg(
00088       (Type == GL_TEXTURE_2D),
00089       "Error[GLTextureStates::GLTextureStates]: Invalid texture type.");
00090 #endif
00091 
00092     m_Type = Type;
00093   }
00094 
00095   void GLTextureStates::ResetDefault()
00096   {
00097 
00098   }
00099 
00100   void GLTextureStates::ResetStateChangeToDefault()
00101   {
00102 
00103   }
00104 
00105   void GLTextureStates::SetRenderStates()
00106   {
00107     HW_SetFiltering();
00108     HW_SetWrap();
00109     HW_SetLOD();
00110     HW_SetMipLevel();
00111   }
00112 
00113 #define SET_TS_VALUE(a, b)  if (a.iValue != b){(a).iValue = (b); (a).Dirty = true;}
00114 #define TS_VALUE(a, b)      (a).iValue
00115 
00116 #define SET_TS_VALUE_FLOAT(a, b)  if (a.fValue != b){(a).fValue = (b); (a).Dirty = true;}
00117 #define TS_VALUE_FLOAT(a, b)      (a).fValue
00118 
00119 
00120   void GLTextureStates::HW_SetFiltering()
00121   {
00122     if (m_TextureStateChanges[GFXTS_MINFILTER].Dirty || m_TextureStateChanges[GFXTS_MAGFILTER].Dirty)
00123     {
00124       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MIN_FILTER,   m_TextureStateChanges[GFXTS_MINFILTER].iValue ));
00125       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MAG_FILTER,   m_TextureStateChanges[GFXTS_MAGFILTER].iValue));
00126       m_TextureStateChanges[GFXTS_MINFILTER].Dirty = false;
00127       m_TextureStateChanges[GFXTS_MAGFILTER].Dirty = false;
00128     }
00129   }
00130 
00131   void GLTextureStates::HW_SetWrap()
00132   {
00133     if (m_TextureStateChanges[GFXTS_ADDRESSU].Dirty ||
00134         m_TextureStateChanges[GFXTS_ADDRESSV].Dirty ||
00135         m_TextureStateChanges[GFXTS_ADDRESSW].Dirty)
00136     {
00137       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_WRAP_S,       m_TextureStateChanges[GFXTS_ADDRESSU].iValue));
00138       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_WRAP_T,       m_TextureStateChanges[GFXTS_ADDRESSV].iValue));
00139 #ifndef NUX_OPENGLES_20
00140       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_WRAP_R,       m_TextureStateChanges[GFXTS_ADDRESSW].iValue));
00141 #endif
00142       m_TextureStateChanges[GFXTS_ADDRESSU].Dirty = false;
00143       m_TextureStateChanges[GFXTS_ADDRESSV].Dirty = false;
00144       m_TextureStateChanges[GFXTS_ADDRESSW].Dirty = false;
00145     }
00146   }
00147 
00148   void GLTextureStates::HW_SetLOD()
00149   {
00150 #ifndef NUX_OPENGLES_20
00151     if (m_Type == GL_TEXTURE_RECTANGLE_ARB)
00152     {
00153       // No support for mip LOP on rectangle texture.
00154       // ATI seems to not generate and Error.
00155       // Nvidia generates an error
00156       m_TextureStateChanges[GFXTS_MIN_LOD].Dirty = false;
00157       m_TextureStateChanges[GFXTS_MAX_LOD].Dirty = false;
00158       return;
00159     }
00160 
00161     if (m_TextureStateChanges[GFXTS_MIN_LOD].Dirty || m_TextureStateChanges[GFXTS_MAX_LOD].Dirty)
00162     {
00163       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MIN_LOD,  m_TextureStateChanges[GFXTS_MIN_LOD].fValue));
00164       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MAX_LOD,  m_TextureStateChanges[GFXTS_MAX_LOD].fValue));
00165       m_TextureStateChanges[GFXTS_MIN_LOD].Dirty = false;
00166       m_TextureStateChanges[GFXTS_MAX_LOD].Dirty = false;
00167     }
00168 #endif
00169   }
00170 
00171   void GLTextureStates::HW_SetMipLevel()
00172   {
00173 #ifndef NUX_OPENGLES_20
00174     if (m_TextureStateChanges[GFXTS_MIN_LOD].Dirty || m_TextureStateChanges[GFXTS_MAX_LOD].Dirty)
00175     {
00176       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MIN_LOD,  m_TextureStateChanges[GFXTS_MIN_LOD].fValue));
00177       CHECKGL(glTexParameteri(m_Type, GL_TEXTURE_MAX_LOD,  m_TextureStateChanges[GFXTS_MAX_LOD].fValue));
00178       m_TextureStateChanges[GFXTS_MIN_LOD].Dirty = false;
00179       m_TextureStateChanges[GFXTS_MAX_LOD].Dirty = false;
00180     }
00181 #endif
00182   }
00183 
00184   void GLTextureStates::HW_SetBorderColor()
00185   {
00186 
00187   }
00188 
00189   void GLTextureStates::SetFiltering(
00190     unsigned int MinFilter,
00191     unsigned int MagFilter
00192     /*,unsigned int MIP*/)
00193   {
00194     nuxAssertMsg(
00195       (MinFilter == GL_LINEAR) ||
00196       (MinFilter == GL_NEAREST) ||
00197       (MinFilter == GL_NEAREST_MIPMAP_NEAREST) ||
00198       (MinFilter == GL_LINEAR_MIPMAP_NEAREST) ||
00199       (MinFilter == GL_NEAREST_MIPMAP_LINEAR) ||
00200       (MinFilter == GL_LINEAR_MIPMAP_LINEAR),
00201       "Error[GLTextureStates::SetFiltering]: Invalid MinFilter state");
00202 
00203     nuxAssertMsg(
00204       (MagFilter == GL_LINEAR) ||
00205       (MagFilter == GL_NEAREST),
00206       "Error[GLTextureStates::SetFiltering]: Invalid MagFilter state");
00207 
00208     //    nuxAssertMsg(
00209     //        (MIP == GL_LINEAR) ||
00210     //        (MIP == GL_NEAREST),
00211     //        "Error[GLTextureStates::SetFiltering]: Invalid Mipmap Filter State");
00212 
00213 #ifndef NUX_OPENGLES_20
00214     if (m_Type == GL_TEXTURE_RECTANGLE_ARB)
00215     {
00216       if ((MinFilter != GL_NEAREST) && (MinFilter != GL_LINEAR))
00217       {
00218         nuxError("[GLTextureStates::SetFiltering] Incorrect MinFilter for rectangle texture.");
00219         SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], GL_LINEAR);
00220       }
00221       else
00222       {
00223         SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], MinFilter);
00224       }
00225 
00226       if ((MagFilter != GL_NEAREST) && (MagFilter != GL_LINEAR))
00227       {
00228         nuxError("[GLTextureStates::SetFiltering] Incorrect MagFilter for rectangle texture.");
00229         SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], GL_LINEAR);
00230       }
00231       else
00232       {
00233         SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], MagFilter);
00234       }
00235     }
00236     else
00237     {
00238       SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], MinFilter);
00239       SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], MagFilter);
00240     }
00241 #else
00242     SET_TS_VALUE(m_TextureStateChanges[GFXTS_MINFILTER], MinFilter);
00243     SET_TS_VALUE(m_TextureStateChanges[GFXTS_MAGFILTER], MagFilter);
00244 #endif
00245 
00246     //SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIPFILTER], MIP);
00247   }
00248 
00249   void GLTextureStates::SetWrap(
00250     unsigned int U,
00251     unsigned int V,
00252     unsigned int W)
00253   {
00254 #ifndef NUX_OPENGLES_20
00255     nuxAssertMsg(
00256       (U == GL_CLAMP) ||
00257       (U == GL_CLAMP_TO_EDGE) ||
00258       (U == GL_CLAMP_TO_BORDER) ||
00259       (U == GL_MIRRORED_REPEAT) ||
00260       (U == GL_MIRROR_CLAMP_EXT) ||
00261       (U == GL_MIRROR_CLAMP_TO_EDGE_EXT) ||
00262       (U == GL_MIRROR_CLAMP_TO_BORDER_EXT) ||
00263       (U == GL_REPEAT),
00264       "Error[GLTextureStates::SetWrap]: Invalid U Wrap State");
00265 
00266     nuxAssertMsg(
00267       (V == GL_CLAMP) ||
00268       (V == GL_CLAMP_TO_EDGE) ||
00269       (V == GL_CLAMP_TO_BORDER) ||
00270       (V == GL_MIRRORED_REPEAT) ||
00271       (V == GL_MIRROR_CLAMP_EXT) ||
00272       (V == GL_MIRROR_CLAMP_TO_EDGE_EXT) ||
00273       (V == GL_MIRROR_CLAMP_TO_BORDER_EXT) ||
00274       (V == GL_REPEAT),
00275       "Error[GLTextureStates::SetWrap]: Invalid V Wrap State");
00276     nuxAssertMsg(
00277       (W == GL_CLAMP) ||
00278       (W == GL_CLAMP_TO_EDGE) ||
00279       (W == GL_CLAMP_TO_BORDER) ||
00280       (W == GL_MIRRORED_REPEAT) ||
00281       (W == GL_MIRROR_CLAMP_EXT) ||
00282       (W == GL_MIRROR_CLAMP_TO_EDGE_EXT) ||
00283       (W == GL_MIRROR_CLAMP_TO_BORDER_EXT) ||
00284       (W == GL_REPEAT),
00285       "Error[GLTextureStates::SetWrap]: Invalid W Wrap State");
00286 
00287     if (m_Type == GL_TEXTURE_RECTANGLE_ARB)
00288     {
00289       if ((U != GL_CLAMP) && (U != GL_CLAMP_TO_BORDER) && (U != GL_CLAMP_TO_EDGE))
00290       {
00291         nuxError("[GLTextureStates::SetFiltering] Incorrect warp for rectangle texture.");
00292         SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], GL_CLAMP_TO_EDGE);
00293       }
00294       else
00295       {
00296         SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], U);
00297       }
00298 
00299       if ((V != GL_CLAMP) && (V != GL_CLAMP_TO_BORDER) && (V != GL_CLAMP_TO_EDGE))
00300       {
00301         nuxError("[GLTextureStates::SetFiltering] Incorrect warp for rectangle texture.");
00302         SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], GL_CLAMP_TO_EDGE);
00303       }
00304       else
00305       {
00306         SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], V);
00307       }
00308 
00309       if ((W != GL_CLAMP) && (W != GL_CLAMP_TO_BORDER) && (W != GL_CLAMP_TO_EDGE))
00310       {
00311         nuxError("[GLTextureStates::SetFiltering] Incorrect warp for rectangle texture.");
00312         SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSW], GL_CLAMP_TO_EDGE);
00313       }
00314       else
00315       {
00316         SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSW], W);
00317       }
00318     }
00319     else
00320     {
00321       SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], U);
00322       SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], V);
00323       SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSW], W);
00324     }
00325 #else
00326     nuxAssertMsg(
00327       (U == GL_CLAMP) ||
00328       (U == GL_CLAMP_TO_EDGE) ||
00329       (U == GL_CLAMP_TO_BORDER) ||
00330       (U == GL_MIRRORED_REPEAT) ||
00331       (U == GL_REPEAT),
00332       "Error[GLTextureStates::SetWrap]: Invalid U Wrap State");
00333 
00334     nuxAssertMsg(
00335       (V == GL_CLAMP) ||
00336       (V == GL_CLAMP_TO_EDGE) ||
00337       (V == GL_CLAMP_TO_BORDER) ||
00338       (V == GL_MIRRORED_REPEAT) ||
00339       (V == GL_REPEAT),
00340       "Error[GLTextureStates::SetWrap]: Invalid V Wrap State");
00341 
00342     SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSU], U);
00343     SET_TS_VALUE(m_TextureStateChanges[GFXTS_ADDRESSV], V);
00344 #endif
00345   }
00346 
00347   void GLTextureStates::SetLOD(float MinLod,
00348                                 float MaxLod)
00349   {
00350     SET_TS_VALUE_FLOAT(m_TextureStateChanges[GFXTS_MIN_LOD], MinLod);
00351     SET_TS_VALUE_FLOAT(m_TextureStateChanges[GFXTS_MAX_LOD], MaxLod);
00352   }
00353 
00354   void GLTextureStates::SetMipLevel(
00355     unsigned int MinMip,
00356     unsigned int MaxMip)
00357   {
00358     SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIP_BASE_LEVEL], MinMip);
00359     SET_TS_VALUE(m_TextureStateChanges[GFXTS_MIP_MAX_LEVEL], MaxMip);
00360   }
00361 
00362   void GLTextureStates::SetBorderColor(
00363     float R,
00364     float G,
00365     float B,
00366     float A)
00367   {
00368     unsigned int r, g, b, a;
00369     r = 255 * Clamp(R, 0.0f, 1.0f);
00370     g = 255 * Clamp(G, 0.0f, 1.0f);
00371     b = 255 * Clamp(B, 0.0f, 1.0f);
00372     a = 255 * Clamp(A, 0.0f, 1.0f);
00373     unsigned int color = (unsigned int) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b));
00374 
00375     SET_TS_VALUE(m_TextureStateChanges[GFXTS_BORDERCOLOR], color);
00376   }
00377 
00378 #undef SET_TS_VALUE
00379 #undef TS_VALUE
00380 
00381 #undef SET_TS_VALUE_FLOAT
00382 #undef TS_VALUE_FLOAT
00383 
00384 }