gfxGLStateBlock.cpp
Engine/source/gfx/gl/gfxGLStateBlock.cpp
Namespaces:
namespace
Public Defines
define
CHECK_TOGGLE_STATE(state, enum) (!oldState || oldState->mDesc.state != mDesc.state) (mDesc.state) glEnable(enum); else glDisable(enum)
define
STATE_CHANGE(state) (!oldState || oldState->mDesc.state != mDesc.state)
define
TOGGLE_STATE(state, enum) (mDesc.state) glEnable(enum); else glDisable(enum)
Detailed Description
Public Defines
CHECK_TOGGLE_STATE(state, enum) (!oldState || oldState->mDesc.state != mDesc.state) (mDesc.state) glEnable(enum); else glDisable(enum)
STATE_CHANGE(state) (!oldState || oldState->mDesc.state != mDesc.state)
TOGGLE_STATE(state, enum) (mDesc.state) glEnable(enum); else glDisable(enum)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "gfx/gl/gfxGLStateBlock.h" 25#include "gfx/gl/gfxGLDevice.h" 26#include "gfx/gl/gfxGLEnumTranslate.h" 27#include "gfx/gl/gfxGLUtils.h" 28#include "gfx/gl/gfxGLTextureObject.h" 29#include "core/crc.h" 30 31namespace DictHash 32{ 33 inline U32 hash(const GFXSamplerStateDesc &data) 34 { 35 return CRC::calculateCRC(&data, sizeof(GFXSamplerStateDesc));; 36 } 37} 38 39GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) : 40 mDesc(desc), 41 mCachedHashValue(desc.getHashValue()) 42{ 43 static Map<GFXSamplerStateDesc, U32> mSamplersMap; 44 45 for(int i = 0; i < GFX_TEXTURE_STAGE_COUNT; ++i) 46 { 47 GLuint &id = mSamplerObjects[i]; 48 GFXSamplerStateDesc &ssd = mDesc.samplers[i]; 49 Map<GFXSamplerStateDesc, U32>::Iterator itr = mSamplersMap.find(ssd); 50 if(itr == mSamplersMap.end()) 51 { 52 glGenSamplers(1, &id); 53 54 glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, 1) ); 55 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]); 56 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]); 57 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]); 58 glSamplerParameteri(id, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]); 59 60 //compare modes 61 const bool comparison = ssd.samplerFunc != GFXCmpNever; 62 glSamplerParameteri(id, GL_TEXTURE_COMPARE_MODE, comparison ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ); 63 glSamplerParameteri(id, GL_TEXTURE_COMPARE_FUNC, GFXGLCmpFunc[ssd.samplerFunc]); 64 65 if (static_cast< GFXGLDevice* >(GFX)->supportsAnisotropic()) 66 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, ssd.maxAnisotropy); 67 68 mSamplersMap[ssd] = id; 69 } 70 else 71 id = itr->value; 72 } 73} 74 75GFXGLStateBlock::~GFXGLStateBlock() 76{ 77} 78 79/// Returns the hash value of the desc that created this block 80U32 GFXGLStateBlock::getHashValue() const 81{ 82 return mCachedHashValue; 83} 84 85/// Returns a GFXStateBlockDesc that this block represents 86const GFXStateBlockDesc& GFXGLStateBlock::getDesc() const 87{ 88 return mDesc; 89} 90 91/// Called by OpenGL device to active this state block. 92/// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states. 93void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState) 94{ 95 PROFILE_SCOPE(GFXGLStateBlock_Activate); 96 // Big scary warning copied from Apple docs 97 // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_performance/chapter_13_section_2.html#//apple_ref/doc/uid/TP40001987-CH213-SW12 98 // Don't set a state that's already set. Once a feature is enabled, it does not need to be enabled again. 99 // Calling an enable function more than once does nothing except waste time because OpenGL does not check 100 // the state of a feature when you call glEnable or glDisable. For instance, if you call glEnable(GL_LIGHTING) 101 // more than once, OpenGL does not check to see if the lighting state is already enabled. It simply updates 102 // the state value even if that value is identical to the current value. 103 104#define STATE_CHANGE(state) (!oldState || oldState->mDesc.state != mDesc.state) 105#define TOGGLE_STATE(state, enum) if(mDesc.state) glEnable(enum); else glDisable(enum) 106#define CHECK_TOGGLE_STATE(state, enum) if(!oldState || oldState->mDesc.state != mDesc.state) if(mDesc.state) glEnable(enum); else glDisable(enum) 107 108 // Blending 109 CHECK_TOGGLE_STATE(blendEnable, GL_BLEND); 110 if(STATE_CHANGE(blendSrc) || STATE_CHANGE(blendDest)) 111 glBlendFunc(GFXGLBlend[mDesc.blendSrc], GFXGLBlend[mDesc.blendDest]); 112 if(STATE_CHANGE(blendOp)) 113 glBlendEquation(GFXGLBlendOp[mDesc.blendOp]); 114 115 if (mDesc.separateAlphaBlendEnable == true) 116 { 117 if (STATE_CHANGE(separateAlphaBlendSrc) || STATE_CHANGE(separateAlphaBlendDest)) 118 glBlendFuncSeparate(GFXGLBlend[mDesc.blendSrc], GFXGLBlend[mDesc.blendDest], GFXGLBlend[mDesc.separateAlphaBlendSrc], GFXGLBlend[mDesc.separateAlphaBlendDest]); 119 if (STATE_CHANGE(separateAlphaBlendOp)) 120 glBlendEquationSeparate(GFXGLBlendOp[mDesc.blendOp], GFXGLBlendOp[mDesc.separateAlphaBlendOp]); 121 } 122 123 // Color write masks 124 if(STATE_CHANGE(colorWriteRed) || STATE_CHANGE(colorWriteBlue) || STATE_CHANGE(colorWriteGreen) || STATE_CHANGE(colorWriteAlpha)) 125 glColorMask(mDesc.colorWriteRed, mDesc.colorWriteBlue, mDesc.colorWriteGreen, mDesc.colorWriteAlpha); 126 127 // Culling 128 if(STATE_CHANGE(cullMode)) 129 { 130 TOGGLE_STATE(cullMode, GL_CULL_FACE); 131 glCullFace(GFXGLCullMode[mDesc.cullMode]); 132 } 133 134 // Depth 135 CHECK_TOGGLE_STATE(zEnable, GL_DEPTH_TEST); 136 137 if(STATE_CHANGE(zFunc)) 138 glDepthFunc(GFXGLCmpFunc[mDesc.zFunc]); 139 140 if (STATE_CHANGE(zBias)) 141 { 142 if (mDesc.zBias == 0) 143 { 144 glDisable(GL_POLYGON_OFFSET_FILL); 145 } 146 else 147 { 148 //this assumes 24bit depth 149 const F32 depthMul = F32((1 << 24) - 1); 150 glEnable(GL_POLYGON_OFFSET_FILL); 151 glPolygonOffset(mDesc.zSlopeBias, mDesc.zBias * depthMul); 152 } 153 } 154 155 if(STATE_CHANGE(zWriteEnable)) 156 glDepthMask(mDesc.zWriteEnable); 157 158 // Stencil 159 CHECK_TOGGLE_STATE(stencilEnable, GL_STENCIL_TEST); 160 if(STATE_CHANGE(stencilFunc) || STATE_CHANGE(stencilRef) || STATE_CHANGE(stencilMask)) 161 glStencilFunc(GFXGLCmpFunc[mDesc.stencilFunc], mDesc.stencilRef, mDesc.stencilMask); 162 if(STATE_CHANGE(stencilFailOp) || STATE_CHANGE(stencilZFailOp) || STATE_CHANGE(stencilPassOp)) 163 glStencilOp(GFXGLStencilOp[mDesc.stencilFailOp], GFXGLStencilOp[mDesc.stencilZFailOp], GFXGLStencilOp[mDesc.stencilPassOp]); 164 if(STATE_CHANGE(stencilWriteMask)) 165 glStencilMask(mDesc.stencilWriteMask); 166 167 168 if(STATE_CHANGE(fillMode)) 169 glPolygonMode(GL_FRONT_AND_BACK, GFXGLFillMode[mDesc.fillMode]); 170 171#undef CHECK_STATE 172#undef TOGGLE_STATE 173#undef CHECK_TOGGLE_STATE 174 175 //sampler objects 176 for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) GFX_TEXTURE_STAGE_COUNT); i++) 177 { 178 if(!oldState || oldState->mSamplerObjects[i] != mSamplerObjects[i]) 179 glBindSampler(i, mSamplerObjects[i] ); 180 } 181 // TODO: states added for detail blend 182} 183