From b92e6bb26ae545a95e72c563b5112e4ffa9443dd Mon Sep 17 00:00:00 2001 From: Nigel Stewart Date: Fri, 6 Sep 2013 09:40:29 -0500 Subject: [PATCH] Consolidation of various GL context limits into RegalEmu.h and ContextInfo Improved array bounds checking for emulation More querable states for GL database --- Makefile.regal | 21 + README.rst | 4 + build/android/Regal/jni/Android.mk | 3 +- .../ios/Regal/Regal.xcodeproj/project.pbxproj | 4 + build/regal.inc | 1 + build/win32/vs2010/Regal/Regal.vcxproj | 1 + build/win32/vs2010/Regal/Regallib.vcxproj | 1 + build/win32/vs2010/Regal/Regalm.vcxproj | 1 + build/win32/vs2010/Regal/Regalmlib.vcxproj | 1 + scripts/EmuHint.py | 2 +- scripts/EmuIff.py | 12 +- scripts/EmuInit.py | 13 +- scripts/EmuTexC.py | 74 +- scripts/api/gl.py | 22 + scripts/regal/RegalContextInfo.py | 125 +- scripts/regal/RegalDispatchEmu.py | 6 +- src/regal/Regal.cpp | 5 +- src/regal/RegalBaseVertex.h | 18 +- src/regal/RegalClientState.h | 174 +- src/regal/RegalContextInfo.cpp | 71 +- src/regal/RegalContextInfo.h | 28 +- src/regal/RegalDispatchEmu.cpp | 269 +-- src/regal/RegalDispatcherGlobal.cpp | 2 +- src/regal/RegalDsa.h | 6 +- src/regal/RegalEmu.cpp | 95 + src/regal/RegalEmu.h | 55 +- src/regal/RegalFilt.cpp | 4 +- src/regal/RegalHint.h | 2 +- src/regal/RegalIff.cpp | 2107 ++++++++++++----- src/regal/RegalIff.h | 1918 +++++++++------ src/regal/RegalPpa.h | 193 +- src/regal/RegalPpca.h | 29 +- src/regal/RegalRect.h | 2 +- src/regal/RegalSo.cpp | 58 +- src/regal/RegalSo.h | 53 +- src/regal/RegalState.h | 798 +++++-- src/regal/RegalTexC.cpp | 59 +- src/regal/RegalTexC.h | 7 +- src/regal/RegalUtil.h | 18 +- src/regal/RegalVao.h | 82 +- src/regal/RegalX11.cpp | 6 +- src/regal/RegalXfer.h | 21 +- tests/testRegalPpca.cpp | 6 +- tests/testRegalTexC.cpp | 30 +- 44 files changed, 4206 insertions(+), 2201 deletions(-) create mode 100644 src/regal/RegalEmu.cpp diff --git a/Makefile.regal b/Makefile.regal index 476a68f..86cdf57 100644 --- a/Makefile.regal +++ b/Makefile.regal @@ -99,6 +99,27 @@ endif ifeq ($(MODE),custom) endif +# Emscripten options + +ifneq ($(filter nacl% emscripten%,$(SYSTEM)),) +REGAL.CFLAGS += -DREGAL_SYS_EMSCRIPTEN=1 -DREGAL_SYS_EGL=1 -DREGAL_SYS_ES2=1 +REGAL.CFLAGS += -DREGAL_NO_HTTP=1 +REGAL.CFLAGS += -DREGAL_STATISTICS=0 +REGAL.CFLAGS += -Wno-constant-logical-operand +REGAL.CFLAGS += -DREGAL_PLUGIN=0 +REGAL.CFLAGS += -DREGAL_TRACE=0 +REGAL.CFLAGS += -DREGAL_NAMESPACE=1 -DREGAL_STATIC_ES2 -DREGAL_STATIC_EGL +REGAL_LOG = 0 +REGAL_NO_TLS = 1 + +# Enabling this requires the library to be built with it, as well as all code +# that uses it. Defining this means that Regal will link statically to GL +# and EGL, and code will have to #include before any GL +# includes to pull in a bunch of #defines (e.g. #define glGetError rglGetError) +#LIB.CFLAGS += -DREGAL_SYS_EMSCRIPTEN_STATIC=1 + +endif + # # Emscripten-specific # diff --git a/README.rst b/README.rst index 33cde3d..b9bc309 100644 --- a/README.rst +++ b/README.rst @@ -384,6 +384,10 @@ Related Efforts * Mesa3D mail thread: `Mesa as part of OpenGL-on-OpenGL ES 2.0 `_ +* `glshim `_, `Pandora forum thread `_. + +* Runtime OpenGL to OpenGL ES translator: `glesport `_, `OpenGL ES for Maemo `_. + License and Credits =================== diff --git a/build/android/Regal/jni/Android.mk b/build/android/Regal/jni/Android.mk index 2ceeeaf..e7f45d0 100644 --- a/build/android/Regal/jni/Android.mk +++ b/build/android/Regal/jni/Android.mk @@ -118,7 +118,8 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := apitrace LOCAL_SRC_FILES := $(apitrace_src_files) -LOCAL_CFLAGS := $(regal_cflags) -DAPITRACE_TLS=0 -DTRACE_OS_LOG=0 -DTRACE_BACKTRACE=0 +LOCAL_CFLAGS := $(regal_cflags) -DAPITRACE_TLS=0 -DTRACE_OS_LOG=0 -DTRACE_BACKTRACE=0 -DTRACE_ENABLED_CHECK=0 + LOCAL_C_INCLUDES := $(apitrace_c_includes) LOCAL_EXPORT_C_INCLUDES := $(apitrace_export_c_includes) LOCAL_EXPORT_LDLIBS := diff --git a/build/ios/Regal/Regal.xcodeproj/project.pbxproj b/build/ios/Regal/Regal.xcodeproj/project.pbxproj index 13cf91f..2ac8e26 100644 --- a/build/ios/Regal/Regal.xcodeproj/project.pbxproj +++ b/build/ios/Regal/Regal.xcodeproj/project.pbxproj @@ -61,6 +61,7 @@ 43FC5FA315C4619B00D0177C /* RegalUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 43FC5F7615C4619B00D0177C /* RegalUtil.h */; }; 43FC5FA415C4619B00D0177C /* RegalVao.h in Headers */ = {isa = PBXBuildFile; fileRef = 43FC5F7715C4619B00D0177C /* RegalVao.h */; }; 43FC5FA715C461AC00D0177C /* mongoose.c in Sources */ = {isa = PBXBuildFile; fileRef = 43FC5FA615C461AC00D0177C /* mongoose.c */; }; + 754D3C9517CFFD7200E4C0E0 /* RegalEmu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 754D3C9417CFFD7200E4C0E0 /* RegalEmu.cpp */; }; BC020947160D1919003FAB99 /* RegalMarker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC020946160D1919003FAB99 /* RegalMarker.cpp */; }; BC020958160D1C73003FAB99 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = BC020957160D1C73003FAB99 /* md5.c */; }; BC3209D416F3A0E600D1A9E0 /* RegalCacheShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3209D016F3A0E600D1A9E0 /* RegalCacheShader.cpp */; }; @@ -226,6 +227,7 @@ 43FC5F7615C4619B00D0177C /* RegalUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegalUtil.h; path = ../../../src/regal/RegalUtil.h; sourceTree = ""; }; 43FC5F7715C4619B00D0177C /* RegalVao.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegalVao.h; path = ../../../src/regal/RegalVao.h; sourceTree = ""; }; 43FC5FA615C461AC00D0177C /* mongoose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mongoose.c; path = ../../../src/mongoose/mongoose.c; sourceTree = ""; }; + 754D3C9417CFFD7200E4C0E0 /* RegalEmu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegalEmu.cpp; path = ../../../src/regal/RegalEmu.cpp; sourceTree = ""; }; BC020946160D1919003FAB99 /* RegalMarker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegalMarker.cpp; path = ../../../src/regal/RegalMarker.cpp; sourceTree = ""; }; BC020957160D1C73003FAB99 /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.c; path = ../../../src/md5/src/md5.c; sourceTree = ""; }; BC3209D016F3A0E600D1A9E0 /* RegalCacheShader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegalCacheShader.cpp; path = ../../../src/regal/RegalCacheShader.cpp; sourceTree = ""; }; @@ -424,6 +426,7 @@ BCBF1846175EBB3000CB653A /* RegalDispatchTrace.cpp */, 43FC5F5D15C4619B00D0177C /* RegalDllMain.cpp */, 43FC5F5E15C4619B00D0177C /* RegalDsa.h */, + 754D3C9417CFFD7200E4C0E0 /* RegalEmu.cpp */, 43FC5F5F15C4619B00D0177C /* RegalEmu.h */, 4366EEEA15C9B54E00211205 /* RegalEnum.h */, 4366EEEB15C9B54E00211205 /* RegalFavicon.cpp */, @@ -806,6 +809,7 @@ BCDF670D178F179800EE9569 /* gltrace_state.cpp in Sources */, BCDF670F178F179800EE9569 /* regaltrace.cpp in Sources */, BCDF6710178F179800EE9569 /* trace.cpp in Sources */, + 754D3C9517CFFD7200E4C0E0 /* RegalEmu.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/build/regal.inc b/build/regal.inc index 1bb39ff..8a433e4 100644 --- a/build/regal.inc +++ b/build/regal.inc @@ -12,6 +12,7 @@ REGAL.CXX += src/regal/RegalLog.cpp REGAL.CXX += src/regal/RegalInit.cpp REGAL.CXX += src/regal/RegalBreak.cpp REGAL.CXX += src/regal/RegalUtil.cpp +REGAL.CXX += src/regal/RegalEmu.cpp REGAL.CXX += src/regal/RegalFrame.cpp REGAL.CXX += src/regal/RegalHelper.cpp REGAL.CXX += src/regal/RegalMarker.cpp diff --git a/build/win32/vs2010/Regal/Regal.vcxproj b/build/win32/vs2010/Regal/Regal.vcxproj index d2e5ba9..7e72cd9 100755 --- a/build/win32/vs2010/Regal/Regal.vcxproj +++ b/build/win32/vs2010/Regal/Regal.vcxproj @@ -274,6 +274,7 @@ + diff --git a/build/win32/vs2010/Regal/Regallib.vcxproj b/build/win32/vs2010/Regal/Regallib.vcxproj index f31277d..6ed9254 100644 --- a/build/win32/vs2010/Regal/Regallib.vcxproj +++ b/build/win32/vs2010/Regal/Regallib.vcxproj @@ -274,6 +274,7 @@ + diff --git a/build/win32/vs2010/Regal/Regalm.vcxproj b/build/win32/vs2010/Regal/Regalm.vcxproj index 8699688..d6381cf 100644 --- a/build/win32/vs2010/Regal/Regalm.vcxproj +++ b/build/win32/vs2010/Regal/Regalm.vcxproj @@ -274,6 +274,7 @@ + diff --git a/build/win32/vs2010/Regal/Regalmlib.vcxproj b/build/win32/vs2010/Regal/Regalmlib.vcxproj index ebed260..594d8ac 100644 --- a/build/win32/vs2010/Regal/Regalmlib.vcxproj +++ b/build/win32/vs2010/Regal/Regalmlib.vcxproj @@ -274,6 +274,7 @@ + diff --git a/scripts/EmuHint.py b/scripts/EmuHint.py index 8636710..4cfcc96 100644 --- a/scripts/EmuHint.py +++ b/scripts/EmuHint.py @@ -6,7 +6,7 @@ hintFormulae = { 'impl' : [ 'if( ! _context->hint->glHint( *_context, ${arg0plus} ) ) {', ' _context->dispatcher.emulation.glHint( ${arg0plus} );', - '}', + '}', ], }, 'Get' : { diff --git a/scripts/EmuIff.py b/scripts/EmuIff.py index d24b665..9cc6758 100644 --- a/scripts/EmuIff.py +++ b/scripts/EmuIff.py @@ -99,11 +99,7 @@ iffFormulae = { 'FfnShadowARB' : { 'entries' : [ 'glActiveTexture(ARB|)' ], - 'impl' : [ - 'if( ! _context->iff->ShadowActiveTexture( ${arg0plus} ) ) {', - ' _context->dispatcher.emulation.glActiveTexture${m1}( ${arg0plus} );', - '}', - ], + 'prefix' : [ '_context->iff->ShadowActiveTexture( ${arg0} ); ', ], }, 'FfnShadeModel' : { 'entries' : [ 'glShadeModel' ], @@ -169,7 +165,11 @@ iffFormulae = { }, 'FfnTexGen' : { 'entries' : [ 'glTexGen(i|f|d)(v|)' ], - 'impl' : [ '_context->iff->TexGen( ${arg0plus} );', ], + 'impl' : [ + 'if ( ! _context->iff->TexGen( ${arg0plus} ) ) {', + ' _context->dispatcher.emulation.glTexGen${m1}${m2}( ${arg0plus} );', + '}', + ], }, 'FfnAlphaFunc' : { 'entries' : [ 'glAlphaFunc' ], diff --git a/scripts/EmuInit.py b/scripts/EmuInit.py index fe4eca6..ef1241b 100644 --- a/scripts/EmuInit.py +++ b/scripts/EmuInit.py @@ -12,11 +12,11 @@ formulae = { 'EmuInit' : { - 'entries' : [ - 'CGLChoosePixelFormat', 'CGLGetCurrentContext', + 'entries' : [ + 'CGLChoosePixelFormat', 'CGLGetCurrentContext', 'eglGetDisplay', 'eglGetCurrentContext', 'glXGetProcAddress', 'glXQueryExtension', 'glXGetProcAddressARB' - # 'glX.*' + # 'glX.*' ], 'prefix' : [ 'Init::init();' ] } @@ -65,8 +65,11 @@ formulaeGlobal = { 'eglMakeCurrent' : { 'entries' : [ 'eglMakeCurrent' ], - 'init' : [ 'if (ret)', - ' Init::makeCurrent(ctx);' ] + 'init' : ''' +#if !REGAL_SYS_PPAPI +if (ret) + Init::makeCurrent(ctx); +#endif''' }, 'eglDestroyContext' : { diff --git a/scripts/EmuTexC.py b/scripts/EmuTexC.py index 1f2ccd4..379a983 100644 --- a/scripts/EmuTexC.py +++ b/scripts/EmuTexC.py @@ -44,79 +44,61 @@ they are so as to convert the texture correctly.""" texCFormulae = { 'ShadowActiveTextureUnit' : { 'entries' : [ 'glActiveTexture(ARB|)' ], - 'impl' : [ - '_context->texc->ShadowActiveTexture( ${arg0plus} );', - '_context->dispatcher.emulation.glActiveTexture( ${arg0plus} );', - ], + 'prefix' : '_context->texc->ShadowActiveTexture( ${arg0plus} );', }, 'ShadowBindTexture' : { 'entries' : [ 'glBindTexture(EXT|)' ], - 'impl' : [ - '_context->texc->ShadowBindTexture( ${arg0plus} );', - '_context->dispatcher.emulation.glBindTexture( ${arg0plus} );', - ], + 'prefix' : '_context->texc->ShadowBindTexture( ${arg0plus} );', }, 'ShadowDeleteTexture' : { 'entries' : [ 'glDeleteTextures(EXT|)' ], - 'impl' : [ - '_context->texc->ShadowDeleteTextures( ${arg0plus} );', - '_context->dispatcher.emulation.glDeleteTextures( ${arg0plus} );', - ], + 'prefix' : '_context->texc->ShadowDeleteTextures( ${arg0plus} );', }, 'ShadowGenTextures' : { 'entries' : [ 'glGenTextures(EXT|)' ], - 'impl' : [ - '_context->dispatcher.emulation.glGenTextures( ${arg0plus} );', - '_context->texc->ShadowGenTextures( ${arg0}, ${arg1} );', - ], + 'impl' : +''' +_context->dispatcher.emulation.glGenTextures( ${arg0plus} ); +_context->texc->ShadowGenTextures( ${arg0}, ${arg1} );''' }, 'ShadowGenerateMipmap' : { 'entries' : [ 'glGenerateMipmap(EXT|)' ], - 'impl' : [ - '_context->texc->ShadowGenerateMipmap( ${arg0plus} );', - '_context->dispatcher.emulation.glGenerateMipmap( ${arg0plus} );', - ], + 'prefix' : '_context->texc->ShadowGenerateMipmap( ${arg0plus} );', }, 'ShadowPixelStorei' : { 'entries' : [ 'glPixelStorei' ], - 'impl' : [ - '_context->texc->ShadowPixelStore( ${arg0plus} );', - '_context->dispatcher.emulation.glPixelStorei( ${arg0plus} );', - ], + 'prefix' : '_context->texc->ShadowPixelStore( ${arg0plus} );', }, 'ShadowTexImage2D' : { 'entries' : [ 'glTexImage2D' ], - 'impl' : [ - '_context->texc->ShadowTexImage2D( ${arg0}, ${arg1}, ${arg6}, ${arg7} );', - '_context->dispatcher.emulation.glTexImage2D( ${arg0plus} );', - ], + 'prefix' : '_context->texc->ShadowTexImage2D( ${arg0}, ${arg1}, ${arg6}, ${arg7} );', }, 'ConvertTexSubImage2D' : { 'entries' : [ 'glTexSubImage2D' ], - 'impl' : [ - 'GLenum targetFormat;', - 'GLenum targetType;', - '_context->texc->GetFormatAndType( ${arg0}, ${arg1}, &targetFormat, &targetType );', - 'Emu::ConvertedBuffer _buffer( _context->texc->unpackPSS, targetFormat, targetType );', - 'if ( _buffer.ConvertFrom( ${arg4}, ${arg5}, ${arg6}, ${arg7}, ${arg8} ) )', - '{', - ' if (_context->texc->unpackPSS.alignment != 4)', - ' _context->dispatcher.emulation.glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );', - ' _context->dispatcher.emulation.glTexSubImage2D( ${arg0}, ${arg1}, ${arg2}, ${arg3}, ${arg4}, ${arg5}, targetFormat, targetType, _buffer.Get() );', - ' if (_context->texc->unpackPSS.alignment != 4)', - ' _context->dispatcher.emulation.glPixelStorei( GL_UNPACK_ALIGNMENT, _context->texc->unpackPSS.alignment );', - '}', - 'else', - '{', - ' _context->dispatcher.emulation.glTexSubImage2D( ${arg0plus} );', - '}', - ], + 'impl' : +''' +GLenum targetFormat; +GLenum targetType; +_context->texc->GetFormatAndType( ${arg0}, ${arg1}, &targetFormat, &targetType ); +Emu::ConvertedBuffer _buffer( _context->texc->unpackPSS, targetFormat, targetType ); +if ( _buffer.ConvertFrom( ${arg4}, ${arg5}, ${arg6}, ${arg7}, ${arg8} ) ) +{ + if (_context->texc->unpackPSS.alignment != 4) + _context->dispatcher.emulation.glPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); + _context->dispatcher.emulation.glTexSubImage2D( ${arg0}, ${arg1}, ${arg2}, ${arg3}, ${arg4}, ${arg5}, targetFormat, targetType, _buffer.Get() ); + if (_context->texc->unpackPSS.alignment != 4) + _context->dispatcher.emulation.glPixelStorei( GL_UNPACK_ALIGNMENT, _context->texc->unpackPSS.alignment ); +} +else +{ + _context->dispatcher.emulation.glTexSubImage2D( ${arg0plus} ); +}''' }, } diff --git a/scripts/api/gl.py b/scripts/api/gl.py index 72f2008..3af4569 100644 --- a/scripts/api/gl.py +++ b/scripts/api/gl.py @@ -45534,3 +45534,25 @@ gl.add(A) gl.add(Y) gl.add(nbytype) gl.add(nstarbytype) + +# states + +MAX_ATTRIB_STACK_DEPTH = State('MAX_ATTRIB_STACK_DEPTH', 'Zplus', 'glGetIntegerv', '16', 'Max depth of the server attribute stack', '21.6', '-') +MAX_CLIENT_ATTRIB_STACK_DEPTH = State('MAX_CLIENT_ATTRIB_STACK_DEPTH', 'Zplus', 'glGetIntegerv', '16', 'Max depth of the client attribute stack', '21.6', '-') +MAX_VERTEX_ATTRIB_BINDINGS = State('MAX_VERTEX_ATTRIB_BINDINGS', 'Zkstar', 'glGetIntegerv', '16', 'Max no. of vertex buffers', '10.3', '-') +MAX_VERTEX_ATTRIBS = State('MAX_VERTEX_ATTRIBS', 'Zplus', 'glGetIntegerv', '16', 'Max no. of active vertex attributes', '10.2', '-') +MAX_TEXTURE_UNITS = State('MAX_TEXTURE_UNITS', 'Zplus', 'glGetIntegerv', '2', 'No. of fixed-function texture units', '10', '-') +MAX_TEXTURE_COORDS = State('MAX_TEXTURE_COORDS', 'Zplus', 'glGetIntegerv', '8', 'No. of texture coordinate sets', '10.2.2', '-') +MAX_COMBINED_TEXTURE_IMAGE_UNITS = State('MAX_COMBINED_TEXTURE_IMAGE_UNITS', 'Zplus', 'glGetIntegerv', '96', 'Total no. of texture units accessible by the GL', '11.1.3.5', '-') +MAX_DRAW_BUFFERS = State('MAX_DRAW_BUFFERS', 'Zplus', 'glGetIntegerv', '8', 'Max no. of active draw buffers', '17.4.1', '-') +MAX_VIEWPORTS = State('MAX_VIEWPORTS', 'Zplus', 'glGetIntegerv', '16', 'Max no. of active viewports', '13.6.1', '-') + +gl.add(MAX_ATTRIB_STACK_DEPTH) +gl.add(MAX_CLIENT_ATTRIB_STACK_DEPTH) +gl.add(MAX_VERTEX_ATTRIB_BINDINGS) +gl.add(MAX_VERTEX_ATTRIBS) +gl.add(MAX_TEXTURE_UNITS) +gl.add(MAX_TEXTURE_COORDS) +gl.add(MAX_COMBINED_TEXTURE_IMAGE_UNITS) +gl.add(MAX_DRAW_BUFFERS) +gl.add(MAX_VIEWPORTS) diff --git a/scripts/regal/RegalContextInfo.py b/scripts/regal/RegalContextInfo.py index daf30a9..fba783f 100755 --- a/scripts/regal/RegalContextInfo.py +++ b/scripts/regal/RegalContextInfo.py @@ -59,8 +59,10 @@ struct ContextInfo ${VERSION_DECLARE} - GLuint maxVertexAttribs; - GLuint maxVaryings; + // Implementation dependent values + +${IMPL_DECLARE} + }; REGAL_NAMESPACE_END @@ -89,7 +91,7 @@ using namespace boost::print; #include "RegalToken.h" #include "RegalContext.h" #include "RegalContextInfo.h" -#include "RegalIff.h" // For REGAL_MAX_VERTEX_ATTRIBS +#include "RegalEmu.h" REGAL_GLOBAL_END @@ -101,8 +103,7 @@ using namespace ::REGAL_NAMESPACE_INTERNAL::Token; ContextInfo::ContextInfo() : ${VERSION_INIT} - maxVertexAttribs(0), - maxVaryings(0) +${IMPL_INIT} { Internal("ContextInfo::ContextInfo","()"); } @@ -350,30 +351,21 @@ ${VERSION_DETECT} ${EXT_INIT} RegalAssert(context.dispatcher.driver.glGetIntegerv); - if (es1) - { - maxVertexAttribs = 8; - maxVaryings = 0; - } - else - { - context.dispatcher.driver.glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, reinterpret_cast(&maxVertexAttribs)); - context.dispatcher.driver.glGetIntegerv( es2 ? GL_MAX_VARYING_VECTORS : GL_MAX_VARYING_FLOATS, reinterpret_cast(&maxVaryings)); - } +${IMPL_GET} - Info("OpenGL v attribs : ",maxVertexAttribs); - Info("OpenGL varyings : ",maxVaryings); + Info("OpenGL v attribs : ",gl_max_vertex_attribs); + Info("OpenGL varyings : ",gl_max_varying_floats); - if (maxVertexAttribs > REGAL_EMU_IFF_VERTEX_ATTRIBS) - maxVertexAttribs = REGAL_EMU_IFF_VERTEX_ATTRIBS; + if (gl_max_vertex_attribs > REGAL_EMU_MAX_VERTEX_ATTRIBS) + gl_max_vertex_attribs = REGAL_EMU_MAX_VERTEX_ATTRIBS; // Qualcomm fails with float4 attribs with 256 byte stride, so artificially limit to 8 attribs (n*16 is used // as the stride in RegalIFF). WebGL (and Pepper) explicitly disallows stride > 255 as well. if (vendor == "Qualcomm" || vendor == "Chromium" || webgl) - maxVertexAttribs = 8; + gl_max_vertex_attribs = 8; - Info("Regal v attribs : ",maxVertexAttribs); + Info("Regal v attribs : ",gl_max_vertex_attribs); } ${EXT_CODE} @@ -540,6 +532,94 @@ def versionDetectCode(apis, args): return code +def implDeclareCode(apis, args): + + code = '' + for api in apis: + name = api.name.lower() + + if name == 'gl': + code += '\n' + + states = [] + for state in api.states: + states.append(state.getValue.lower()) + + for state in sorted(states): + code += ' GLuint gl_%s;\n' % (state) + + code += '\n' + code += ' // Max values currently being used\n' + code += '\n' + + for state in sorted(states): + code += ' GLuint %s;\n' % (state) + + code += '\n' + code += ' GLuint gl_max_varying_floats;\n' + + return code + +def implInitCode(apis, args): + + code = '' + for api in apis: + name = api.name.lower() + + if name == 'gl': + + states = [] + for state in api.states: + states.append(state.getValue.lower()) + + for state in sorted(states): + code += ' gl_%s(0),\n' % (state) + + for state in sorted(states): + code += ' %s(0),\n' % (state) + + code += ' gl_max_varying_floats(0)\n' + + return code + +def implGetCode(apis, args): + + code = '' + for api in apis: + name = api.name.lower() + + if name == 'gl': + + states = [] + for state in api.states: + states.append(state.getValue) + + code += ' if (es1)\n' + code += ' {\n' + + for state in sorted(states): + code += ' gl_%s = 0;\n' % state.lower() + + code += '\n' + code += ' gl_max_vertex_attribs = 8;\n' + code += ' }\n' + code += ' else\n' + code += ' {\n' + + for state in sorted(states): + code += ' context.dispatcher.driver.glGetIntegerv( GL_%s, reinterpret_cast(&gl_%s));\n' % (state, state.lower()) + + code += ' context.dispatcher.driver.glGetIntegerv( es2 ? GL_MAX_VARYING_VECTORS : GL_MAX_VARYING_FLOATS, reinterpret_cast(&gl_max_varying_floats));\n' + code += ' }\n' + code += '\n' + + for state in sorted(states): + code += ' %s = std::min( gl_%s, static_cast(REGAL_EMU_%s) );\n' % (state.lower(), state.lower(), state) + + code += '\n' + + return code + def extensionStringCode(apis, args): code = '' @@ -611,6 +691,7 @@ def generateContextInfoHeader(apis, args): substitute['COPYRIGHT'] = args.copyright substitute['HEADER_NAME'] = "REGAL_CONTEXT_INFO" substitute['VERSION_DECLARE'] = versionDeclareCode(apis,args) + substitute['IMPL_DECLARE'] = implDeclareCode(apis,args) outputCode( '%s/RegalContextInfo.h' % args.srcdir, contextInfoHeaderTemplate.substitute(substitute)) def generateContextInfoSource(apis, args): @@ -623,4 +704,6 @@ def generateContextInfoSource(apis, args): substitute['VERSION_DETECT'] = versionDetectCode(apis,args) substitute['EXT_INIT'] = extensionStringCode(apis,args) substitute['EXT_CODE'] = getExtensionCode(apis,args) + substitute['IMPL_INIT'] = implInitCode(apis,args) + substitute['IMPL_GET'] = implGetCode(apis,args) outputCode( '%s/RegalContextInfo.cpp' % args.srcdir, contextInfoSourceTemplate.substitute(substitute)) diff --git a/scripts/regal/RegalDispatchEmu.py b/scripts/regal/RegalDispatchEmu.py index 1f9f6ec..f78291c 100755 --- a/scripts/regal/RegalDispatchEmu.py +++ b/scripts/regal/RegalDispatchEmu.py @@ -96,8 +96,7 @@ def apiEmuFuncDefineCode(apis, args): code += ' _instance.nextDispatchTable = &_context->dispatcher.emulation;\n' code += ' #endif\n' - for j in e['prefix'] : - code += ' %s\n' % j + code += listToString(indent(e['prefix'],' ')) if l['member'] : code += ' }\n' if e!= None and 'impl' in e and l['member']: @@ -146,8 +145,7 @@ def apiEmuFuncDefineCode(apis, args): code += ' _instance.nextDispatchTable = &_context->dispatcher.emulation;\n' code += ' #endif\n' - for j in e['impl'] : - code += ' %s\n' % j + code += listToString(indent(e['impl'],' ')) if l['member'] : if l['member'] != "filt" and typeIsVoid(rType): code += ' return;\n' diff --git a/src/regal/Regal.cpp b/src/regal/Regal.cpp index 03e748b..0ff5691 100644 --- a/src/regal/Regal.cpp +++ b/src/regal/Regal.cpp @@ -31930,8 +31930,11 @@ extern "C" { RegalAssert(_next); EGLBoolean ret = 0; ret = _next->call(&_next->eglMakeCurrent)(dpy, draw, read, ctx); + + #if !REGAL_SYS_PPAPI if (ret) - Init::makeCurrent(ctx); + Init::makeCurrent(ctx); + #endif return ret; } diff --git a/src/regal/RegalBaseVertex.h b/src/regal/RegalBaseVertex.h index 7562a83..96ee57a 100644 --- a/src/regal/RegalBaseVertex.h +++ b/src/regal/RegalBaseVertex.h @@ -81,8 +81,10 @@ struct BaseVertex : public ClientState::VertexArray GLuint currentVBO = ClientState::VertexArray::arrayBufferBinding; - for (GLuint ii=0; ii(b.offset + (b.stride*basevertex)); @@ -143,12 +148,13 @@ struct BaseVertex : public ClientState::VertexArray dt.call(&dt.glBindBuffer)(GL_ARRAY_BUFFER, currentVBO); } + GLsizei index = static_cast(ii); if (g.isInteger) - dt.call(&dt.glVertexAttribIPointer)(ii, g.size, g.type, b.stride, p); + dt.call(&dt.glVertexAttribIPointer)(index, g.size, g.type, b.stride, p); else if (g.isLong) - dt.call(&dt.glVertexAttribLPointer)(ii, g.size, g.type, b.stride, p); + dt.call(&dt.glVertexAttribLPointer)(index, g.size, g.type, b.stride, p); else - dt.call(&dt.glVertexAttribPointer)(ii, g.size, g.type, g.normalized, b.stride, p); + dt.call(&dt.glVertexAttribPointer)(index, g.size, g.type, g.normalized, b.stride, p); } } diff --git a/src/regal/RegalClientState.h b/src/regal/RegalClientState.h index dd1914d..bbaa55b 100644 --- a/src/regal/RegalClientState.h +++ b/src/regal/RegalClientState.h @@ -154,7 +154,7 @@ namespace ClientState GLuint buffer; // GL_x_ARRAY_BUFFER_BINDING GLint size; // GL_x_ARRAY_SIZE GLenum type; // GL_x_ARRAY_TYPE - GLint stride; // GL_x_ARRAY_STRIDE + GLsizei stride; // GL_x_ARRAY_STRIDE inline NamedVertexArray() { @@ -672,9 +672,16 @@ namespace ClientState arrayBufferBinding = 0; vertexArrayBinding = 0; - for (GLuint ii=0; ii(&vertexArrayBinding)); if (vertexArrayBinding) dt.call(&dt.glBindVertexArray)(0); - for (GLuint ii=0; ii(ii)); - for (GLuint ii=0; ii(ii)); + n = array_size( generic ); + for (size_t ii=0; ii(ii)); dt.call(&dt.glGetIntegerv)(GL_ELEMENT_ARRAY_BUFFER_BINDING,reinterpret_cast(&elementArrayBufferBinding)); dt.call(&dt.glGetIntegerv)(GL_CLIENT_ACTIVE_TEXTURE,reinterpret_cast(&clientActiveTexture)); primitiveRestartFixedIndex = dt.call(&dt.glIsEnabled)(GL_PRIMITIVE_RESTART_FIXED_INDEX); @@ -732,12 +747,15 @@ namespace ClientState const VertexArray &set(DispatchTableGL &dt, bool driverAllowsVertexAttributeArraysWithoutBoundBuffer) const { dt.call(&dt.glBindVertexArray)(0); - for (GLint ii=nNamedArrays-1; ii>=0; ii--) - named[ii].set(dt,static_cast(ii),driverAllowsVertexAttributeArraysWithoutBoundBuffer); - for (GLuint ii=0; ii=0; ii--) - generic[ii].set(dt,ii); + size_t n = array_size( named ); + for (size_t ii=0; ii(n-ii-1),driverAllowsVertexAttributeArraysWithoutBoundBuffer); + n = array_size( bindings ); + for (size_t ii=0; ii(ii)); + n = array_size( generic ); + for (size_t ii=0; ii(n-ii-1)); dt.call(&dt.glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER,elementArrayBufferBinding); dt.call(&dt.glClientActiveTexture)(clientActiveTexture); if (primitiveRestartFixedIndex) @@ -761,12 +779,15 @@ namespace ClientState vertexArrayBinding = 0; dt.call(&dt.glBindVertexArray)(vertexArrayBinding); } - for (GLint ii=nNamedArrays-1; ii>=0; ii--) - named[ii].transition(dt,to.named[ii],static_cast(ii),driverAllowsVertexAttributeArraysWithoutBoundBuffer); - for (GLuint ii=0; ii=0; ii--) - generic[ii].transition(dt,to.generic[ii],ii); + size_t n = array_size( named ); + for (size_t ii=0; ii(n-ii-1),driverAllowsVertexAttributeArraysWithoutBoundBuffer); + n = array_size( bindings ); + for (size_t ii=0; ii(ii)); + n = array_size( generic ); + for (size_t ii=0; ii(n-ii-1)); if (elementArrayBufferBinding != to.elementArrayBufferBinding) { elementArrayBufferBinding = to.elementArrayBufferBinding; dt.call(&dt.glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER,elementArrayBufferBinding); @@ -806,15 +827,18 @@ namespace ClientState std::string toString(const char *delim = "\n") const { string_list tmp; - for (GLuint ii=0; ii(ii),delim); - for (GLuint ii=0; ii(ii),delim); + n = array_size( generic ); + for (size_t ii=0; ii(ii),delim); tmp << print_string("glBindBuffer(GL_ELEMENT_ARRAY_BUFFER",elementArrayBufferBinding,");",delim); - tmp << print_string("glClientActiveTexture(",clientActiveTexture,");",delim); + tmp << print_string("glClientActiveTexture(",Token::GLtextureToString(clientActiveTexture),");",delim); if (primitiveRestartFixedIndex) tmp << print_string("glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);",delim); @@ -886,29 +910,39 @@ namespace ClientState switch (cap) { case GL_VERTEX_ARRAY: + RegalAssertArrayIndex( named, VERTEX ); named[VERTEX].enabled = enabled; break; case GL_NORMAL_ARRAY: + RegalAssertArrayIndex( named, NORMAL ); named[NORMAL].enabled = enabled; break; case GL_FOG_COORD_ARRAY: + RegalAssertArrayIndex( named, FOG_COORD ); named[FOG_COORD].enabled = enabled; break; case GL_COLOR_ARRAY: + RegalAssertArrayIndex( named, COLOR ); named[COLOR].enabled = enabled; break; case GL_SECONDARY_COLOR_ARRAY: + RegalAssertArrayIndex( named, SECONDARY_COLOR ); named[SECONDARY_COLOR].enabled = enabled; break; case GL_INDEX_ARRAY: + RegalAssertArrayIndex( named, INDEX ); named[INDEX].enabled = enabled; break; case GL_EDGE_FLAG_ARRAY: + RegalAssertArrayIndex( named, EDGE_FLAG ); named[EDGE_FLAG].enabled = enabled; break; case GL_TEXTURE_COORD_ARRAY: - if (index < REGAL_EMU_MAX_TEXTURE_COORDS) + if ( (index+7) < array_size( named ) ) + { + RegalAssertArrayIndex( named, index+7 ); named[index+7].enabled = enabled; + } break; default: break; @@ -975,9 +1009,13 @@ namespace ClientState arrayBufferBinding = 0; if (buffers[ii] == elementArrayBufferBinding) elementArrayBufferBinding = 0; - for (GLsizei jj=0; jj= first) && (first + count) <= REGAL_EMU_MAX_VERTEX_ATTRIB_BINDINGS) + if (!vertexArrayBinding && ((first + count) >= first) && (first + count) <= array_size( bindings )) { if (buffers) for (GLsizei ii = 0; ii < count; ii++) { + RegalAssertArrayIndex( bindings, first ); bindings[first].buffer = buffers[ii]; bindings[first].offset = offsets[ii]; bindings[first].stride = strides[ii]; @@ -1120,6 +1159,7 @@ namespace ClientState else for (GLsizei ii = 0; ii < count; ii++) { + RegalAssertArrayIndex( bindings, first ); bindings[first].buffer = 0; bindings[first].offset = 0; bindings[first].stride = 16; @@ -1136,9 +1176,11 @@ namespace ClientState inline void glVertexAttribDivisor(GLuint index, GLuint divisor) { if (!vertexArrayBinding && - index < REGAL_EMU_MAX_VERTEX_ATTRIBS && - index < REGAL_EMU_MAX_VERTEX_ATTRIB_BINDINGS) + index < array_size( generic ) && + index < array_size( bindings ) ) { + RegalAssertArrayIndex( generic, index ); + RegalAssertArrayIndex( bindings, index ); generic[index].bindingIndex = index; bindings[index].divisor = divisor; } @@ -1146,32 +1188,45 @@ namespace ClientState inline void glVertexBindingDivisor(GLuint bindingindex, GLuint divisor) { - if (!vertexArrayBinding && bindingindex < REGAL_EMU_MAX_VERTEX_ATTRIB_BINDINGS) + if (!vertexArrayBinding && bindingindex < array_size( bindings )) + { + RegalAssertArrayIndex( bindings, bindingindex ); bindings[bindingindex].divisor = divisor; + } } inline void glEnableVertexAttribArray(GLuint index) { - if (!vertexArrayBinding && index < REGAL_EMU_MAX_VERTEX_ATTRIBS) + if (!vertexArrayBinding && index < array_size( generic )) + { + RegalAssertArrayIndex( generic, index ); generic[index].enabled = GL_TRUE; + } } inline void glDisableVertexAttribArray(GLuint index) { - if (!vertexArrayBinding && index < REGAL_EMU_MAX_VERTEX_ATTRIBS) + if (!vertexArrayBinding && index < array_size( generic )) + { + RegalAssertArrayIndex( generic, index ); generic[index].enabled = GL_FALSE; + } } inline void glVertexAttribBinding(GLuint attribindex, GLuint bindingindex) { - if (!vertexArrayBinding && attribindex < REGAL_EMU_MAX_VERTEX_ATTRIBS) + if (!vertexArrayBinding && attribindex < array_size( generic )) + { + RegalAssertArrayIndex( generic, attribindex ); generic[attribindex].bindingIndex = bindingindex; + } } inline void glVertexAttribIFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) { - if (!vertexArrayBinding && attribindex < REGAL_EMU_MAX_VERTEX_ATTRIBS) + if (!vertexArrayBinding && attribindex < array_size( generic )) { + RegalAssertArrayIndex( generic, attribindex ); generic[attribindex].size = size; generic[attribindex].type = type; generic[attribindex].relativeOffset = relativeoffset; @@ -1183,8 +1238,9 @@ namespace ClientState inline void glVertexAttribLFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) { - if (!vertexArrayBinding && attribindex < REGAL_EMU_MAX_VERTEX_ATTRIBS) + if (!vertexArrayBinding && attribindex < array_size( generic )) { + RegalAssertArrayIndex( generic, attribindex ); generic[attribindex].size = size; generic[attribindex].type = type; generic[attribindex].relativeOffset = relativeoffset; @@ -1196,8 +1252,9 @@ namespace ClientState inline void glVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) { - if (!vertexArrayBinding && attribindex < REGAL_EMU_MAX_VERTEX_ATTRIBS) + if (!vertexArrayBinding && attribindex < array_size( generic )) { + RegalAssertArrayIndex( generic, attribindex ); generic[attribindex].size = size; generic[attribindex].type = type; generic[attribindex].relativeOffset = relativeoffset; @@ -1209,8 +1266,11 @@ namespace ClientState inline void glClientActiveTexture(GLenum texture) { - if ( (texture - GL_TEXTURE0) < REGAL_EMU_MAX_TEXTURE_COORDS) + GLuint index = texture - GL_TEXTURE0; + if ( texture >= GL_TEXTURE0 && index < array_size( generic )) clientActiveTexture = texture; + else + Warning( "Client active texture out of range: ", Token::GLtextureToString(texture), " > ", Token::GLtextureToString(static_cast(GL_TEXTURE0 + array_size( generic ) - 1))); } inline void glPrimitiveRestartIndex(GLuint index) @@ -1254,13 +1314,13 @@ namespace ClientState inline void glEnableVertexArrayAttribEXT(GLuint vaobj, GLuint index) { - if (!vaobj && index < REGAL_EMU_MAX_VERTEX_ATTRIBS) + if (!vaobj && index < array_size( generic )) generic[index].enabled = GL_TRUE; } inline void glDisableVertexArrayAttribEXT(GLuint vaobj, GLuint index) { - if (!vaobj && index < REGAL_EMU_MAX_VERTEX_ATTRIBS) + if (!vaobj && index < array_size( generic )) generic[index].enabled = GL_FALSE; } @@ -1268,6 +1328,7 @@ namespace ClientState { if (!vaobj) { + RegalAssertArrayIndex( named, VERTEX ); named[VERTEX].buffer = buffer; named[VERTEX].size = size; named[VERTEX].type = type; @@ -1280,6 +1341,7 @@ namespace ClientState { if (!vaobj) { + RegalAssertArrayIndex( named, NORMAL ); named[NORMAL].buffer = buffer; named[NORMAL].size = 3; named[NORMAL].type = type; @@ -1292,6 +1354,7 @@ namespace ClientState { if (!vaobj) { + RegalAssertArrayIndex( named, COLOR ); named[COLOR].buffer = buffer; named[COLOR].size = size; named[COLOR].type = type; @@ -1304,6 +1367,7 @@ namespace ClientState { if (!vaobj) { + RegalAssertArrayIndex( named, SECONDARY_COLOR ); named[SECONDARY_COLOR].buffer = buffer; named[SECONDARY_COLOR].size = size; named[SECONDARY_COLOR].type = type; @@ -1316,6 +1380,7 @@ namespace ClientState { if (!vaobj) { + RegalAssertArrayIndex( named, INDEX ); named[INDEX].buffer = buffer; named[INDEX].size = 1; named[INDEX].type = type; @@ -1328,6 +1393,7 @@ namespace ClientState { if (!vaobj) { + RegalAssertArrayIndex( named, EDGE_FLAG ); named[EDGE_FLAG].buffer = buffer; named[EDGE_FLAG].size = 1; named[EDGE_FLAG].type = GL_BOOL; @@ -1340,6 +1406,7 @@ namespace ClientState { if (!vaobj) { + RegalAssertArrayIndex( named, FOG_COORD ); named[FOG_COORD].buffer = buffer; named[FOG_COORD].size = 1; named[FOG_COORD].type = type; @@ -1350,12 +1417,13 @@ namespace ClientState void glVertexArrayMultiTexCoordOffsetEXT(GLuint vaobj, GLuint buffer, GLenum texture, GLint size, GLenum type, GLsizei stride, GLintptr offset) { - if (!vaobj) + if (!vaobj && texture >= GL_TEXTURE0) { GLuint index = texture - GL_TEXTURE0; - if (index < REGAL_EMU_MAX_TEXTURE_COORDS && index <= texture) + if ( (index+7) < array_size( named ) ) { GLuint ii = 7 + index; + RegalAssertArrayIndex( named, ii ); named[ii].buffer = buffer; named[ii].size = size; named[ii].type = type; diff --git a/src/regal/RegalContextInfo.cpp b/src/regal/RegalContextInfo.cpp index 1190993..15aa322 100644 --- a/src/regal/RegalContextInfo.cpp +++ b/src/regal/RegalContextInfo.cpp @@ -56,7 +56,7 @@ using namespace boost::print; #include "RegalToken.h" #include "RegalContext.h" #include "RegalContextInfo.h" -#include "RegalIff.h" // For REGAL_MAX_VERTEX_ATTRIBS +#include "RegalEmu.h" REGAL_GLOBAL_END @@ -794,8 +794,26 @@ ContextInfo::ContextInfo() egl_nv_system_time(false), #endif - maxVertexAttribs(0), - maxVaryings(0) + gl_max_attrib_stack_depth(0), + gl_max_client_attrib_stack_depth(0), + gl_max_combined_texture_image_units(0), + gl_max_draw_buffers(0), + gl_max_texture_coords(0), + gl_max_texture_units(0), + gl_max_vertex_attrib_bindings(0), + gl_max_vertex_attribs(0), + gl_max_viewports(0), + max_attrib_stack_depth(0), + max_client_attrib_stack_depth(0), + max_combined_texture_image_units(0), + max_draw_buffers(0), + max_texture_coords(0), + max_texture_units(0), + max_vertex_attrib_bindings(0), + max_vertex_attribs(0), + max_viewports(0), + gl_max_varying_floats(0) + { Internal("ContextInfo::ContextInfo","()"); } @@ -1743,28 +1761,55 @@ ContextInfo::init(const RegalContext &context) RegalAssert(context.dispatcher.driver.glGetIntegerv); if (es1) { - maxVertexAttribs = 8; - maxVaryings = 0; + gl_max_attrib_stack_depth = 0; + gl_max_client_attrib_stack_depth = 0; + gl_max_combined_texture_image_units = 0; + gl_max_draw_buffers = 0; + gl_max_texture_coords = 0; + gl_max_texture_units = 0; + gl_max_vertex_attribs = 0; + gl_max_vertex_attrib_bindings = 0; + gl_max_viewports = 0; + + gl_max_vertex_attribs = 8; } else { - context.dispatcher.driver.glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, reinterpret_cast(&maxVertexAttribs)); - context.dispatcher.driver.glGetIntegerv( es2 ? GL_MAX_VARYING_VECTORS : GL_MAX_VARYING_FLOATS, reinterpret_cast(&maxVaryings)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_ATTRIB_STACK_DEPTH, reinterpret_cast(&gl_max_attrib_stack_depth)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, reinterpret_cast(&gl_max_client_attrib_stack_depth)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, reinterpret_cast(&gl_max_combined_texture_image_units)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_DRAW_BUFFERS, reinterpret_cast(&gl_max_draw_buffers)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_TEXTURE_COORDS, reinterpret_cast(&gl_max_texture_coords)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_TEXTURE_UNITS, reinterpret_cast(&gl_max_texture_units)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, reinterpret_cast(&gl_max_vertex_attribs)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_VERTEX_ATTRIB_BINDINGS, reinterpret_cast(&gl_max_vertex_attrib_bindings)); + context.dispatcher.driver.glGetIntegerv( GL_MAX_VIEWPORTS, reinterpret_cast(&gl_max_viewports)); + context.dispatcher.driver.glGetIntegerv( es2 ? GL_MAX_VARYING_VECTORS : GL_MAX_VARYING_FLOATS, reinterpret_cast(&gl_max_varying_floats)); } - Info("OpenGL v attribs : ",maxVertexAttribs); - Info("OpenGL varyings : ",maxVaryings); + max_attrib_stack_depth = std::min( gl_max_attrib_stack_depth, static_cast(REGAL_EMU_MAX_ATTRIB_STACK_DEPTH) ); + max_client_attrib_stack_depth = std::min( gl_max_client_attrib_stack_depth, static_cast(REGAL_EMU_MAX_CLIENT_ATTRIB_STACK_DEPTH) ); + max_combined_texture_image_units = std::min( gl_max_combined_texture_image_units, static_cast(REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS) ); + max_draw_buffers = std::min( gl_max_draw_buffers, static_cast(REGAL_EMU_MAX_DRAW_BUFFERS) ); + max_texture_coords = std::min( gl_max_texture_coords, static_cast(REGAL_EMU_MAX_TEXTURE_COORDS) ); + max_texture_units = std::min( gl_max_texture_units, static_cast(REGAL_EMU_MAX_TEXTURE_UNITS) ); + max_vertex_attribs = std::min( gl_max_vertex_attribs, static_cast(REGAL_EMU_MAX_VERTEX_ATTRIBS) ); + max_vertex_attrib_bindings = std::min( gl_max_vertex_attrib_bindings, static_cast(REGAL_EMU_MAX_VERTEX_ATTRIB_BINDINGS) ); + max_viewports = std::min( gl_max_viewports, static_cast(REGAL_EMU_MAX_VIEWPORTS) ); - if (maxVertexAttribs > REGAL_EMU_IFF_VERTEX_ATTRIBS) - maxVertexAttribs = REGAL_EMU_IFF_VERTEX_ATTRIBS; + Info("OpenGL v attribs : ",gl_max_vertex_attribs); + Info("OpenGL varyings : ",gl_max_varying_floats); + + if (gl_max_vertex_attribs > REGAL_EMU_MAX_VERTEX_ATTRIBS) + gl_max_vertex_attribs = REGAL_EMU_MAX_VERTEX_ATTRIBS; // Qualcomm fails with float4 attribs with 256 byte stride, so artificially limit to 8 attribs (n*16 is used // as the stride in RegalIFF). WebGL (and Pepper) explicitly disallows stride > 255 as well. if (vendor == "Qualcomm" || vendor == "Chromium" || webgl) - maxVertexAttribs = 8; + gl_max_vertex_attribs = 8; - Info("Regal v attribs : ",maxVertexAttribs); + Info("Regal v attribs : ",gl_max_vertex_attribs); } bool diff --git a/src/regal/RegalContextInfo.h b/src/regal/RegalContextInfo.h index 89465ce..4795a01 100644 --- a/src/regal/RegalContextInfo.h +++ b/src/regal/RegalContextInfo.h @@ -825,8 +825,32 @@ struct ContextInfo GLboolean egl_nv_system_time : 1; #endif - GLuint maxVertexAttribs; - GLuint maxVaryings; + // Implementation dependent values + + GLuint gl_max_attrib_stack_depth; + GLuint gl_max_client_attrib_stack_depth; + GLuint gl_max_combined_texture_image_units; + GLuint gl_max_draw_buffers; + GLuint gl_max_texture_coords; + GLuint gl_max_texture_units; + GLuint gl_max_vertex_attrib_bindings; + GLuint gl_max_vertex_attribs; + GLuint gl_max_viewports; + + // Max values currently being used + + GLuint max_attrib_stack_depth; + GLuint max_client_attrib_stack_depth; + GLuint max_combined_texture_image_units; + GLuint max_draw_buffers; + GLuint max_texture_coords; + GLuint max_texture_units; + GLuint max_vertex_attrib_bindings; + GLuint max_vertex_attribs; + GLuint max_viewports; + + GLuint gl_max_varying_floats; + }; REGAL_NAMESPACE_END diff --git a/src/regal/RegalDispatchEmu.cpp b/src/regal/RegalDispatchEmu.cpp index 47050d1..d277ebe 100644 --- a/src/regal/RegalDispatchEmu.cpp +++ b/src/regal/RegalDispatchEmu.cpp @@ -10098,7 +10098,12 @@ static void REGAL_CALL emu_glPixelStorei(GLenum pname, GLint param) case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowPixelStore( pname, param ); + } #endif case 1 : #if REGAL_EMU_FILTER @@ -10125,16 +10130,6 @@ static void REGAL_CALL emu_glPixelStorei(GLenum pname, GLint param) case 4 : case 3 : case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowPixelStore( pname, param ); - _context->dispatcher.emulation.glPixelStorei( pname, param ); - return; - } - #endif case 1 : #if REGAL_EMU_FILTER if (_context->filt) @@ -16333,7 +16328,9 @@ static void REGAL_CALL emu_glTexGend(GLenum coord, GLenum pname, GLdouble param) { Push pushLevel(_context->emuLevel); _context->emuLevel = 5; - _context->iff->TexGen( coord, pname, param ); + if ( ! _context->iff->TexGen( coord, pname, param ) ) { + _context->dispatcher.emulation.glTexGend( coord, pname, param ); + } return; } #endif @@ -16395,7 +16392,9 @@ static void REGAL_CALL emu_glTexGendv(GLenum coord, GLenum pname, const GLdouble { Push pushLevel(_context->emuLevel); _context->emuLevel = 5; - _context->iff->TexGen( coord, pname, params ); + if ( ! _context->iff->TexGen( coord, pname, params ) ) { + _context->dispatcher.emulation.glTexGendv( coord, pname, params ); + } return; } #endif @@ -16467,7 +16466,9 @@ static void REGAL_CALL emu_glTexGenf(GLenum coord, GLenum pname, GLfloat param) { Push pushLevel(_context->emuLevel); _context->emuLevel = 5; - _context->iff->TexGen( coord, pname, param ); + if ( ! _context->iff->TexGen( coord, pname, param ) ) { + _context->dispatcher.emulation.glTexGenf( coord, pname, param ); + } return; } #endif @@ -16539,7 +16540,9 @@ static void REGAL_CALL emu_glTexGenfv(GLenum coord, GLenum pname, const GLfloat { Push pushLevel(_context->emuLevel); _context->emuLevel = 5; - _context->iff->TexGen( coord, pname, params ); + if ( ! _context->iff->TexGen( coord, pname, params ) ) { + _context->dispatcher.emulation.glTexGenfv( coord, pname, params ); + } return; } #endif @@ -16611,7 +16614,9 @@ static void REGAL_CALL emu_glTexGeni(GLenum coord, GLenum pname, GLint param) { Push pushLevel(_context->emuLevel); _context->emuLevel = 5; - _context->iff->TexGen( coord, pname, param ); + if ( ! _context->iff->TexGen( coord, pname, param ) ) { + _context->dispatcher.emulation.glTexGeni( coord, pname, param ); + } return; } #endif @@ -16683,7 +16688,9 @@ static void REGAL_CALL emu_glTexGeniv(GLenum coord, GLenum pname, const GLint *p { Push pushLevel(_context->emuLevel); _context->emuLevel = 5; - _context->iff->TexGen( coord, pname, params ); + if ( ! _context->iff->TexGen( coord, pname, params ) ) { + _context->dispatcher.emulation.glTexGeniv( coord, pname, params ); + } return; } #endif @@ -16819,7 +16826,12 @@ static void REGAL_CALL emu_glTexImage2D(GLenum target, GLint level, GLint intern case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowTexImage2D( target, level, format, type ); + } #endif case 1 : #if REGAL_EMU_FILTER @@ -16855,16 +16867,6 @@ static void REGAL_CALL emu_glTexImage2D(GLenum target, GLint level, GLint intern case 4 : case 3 : case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowTexImage2D( target, level, format, type ); - _context->dispatcher.emulation.glTexImage2D( target, level, internalformat, width, height, border, format, type, pixels ); - return; - } - #endif case 1 : #if REGAL_EMU_FILTER if (_context->filt) @@ -19012,7 +19014,12 @@ static void REGAL_CALL emu_glBindTexture(GLenum target, GLuint texture) case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowBindTexture( target, texture ); + } #endif case 1 : #if REGAL_EMU_FILTER @@ -19071,16 +19078,6 @@ static void REGAL_CALL emu_glBindTexture(GLenum target, GLuint texture) #endif case 3 : case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowBindTexture( target, texture ); - _context->dispatcher.emulation.glBindTexture( target, texture ); - return; - } - #endif case 1 : #if REGAL_EMU_FILTER if (_context->filt) @@ -19312,7 +19309,12 @@ static void REGAL_CALL emu_glDeleteTextures(GLsizei n, const GLuint *textures) case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowDeleteTextures( n, textures ); + } #endif case 1 : default: @@ -19332,29 +19334,6 @@ static void REGAL_CALL emu_glDeleteTextures(GLsizei n, const GLuint *textures) return; } #endif - case 14 : - case 13 : - case 12 : - case 11 : - case 10 : - case 9 : - case 8 : - case 7 : - case 6 : - case 5 : - case 4 : - case 3 : - case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowDeleteTextures( n, textures ); - _context->dispatcher.emulation.glDeleteTextures( n, textures ); - return; - } - #endif case 1 : default: { @@ -19864,6 +19843,7 @@ static void REGAL_CALL emu_glGenTextures(GLsizei n, GLuint *textures) { Push pushLevel(_context->emuLevel); _context->emuLevel = 1; + _context->dispatcher.emulation.glGenTextures( n, textures ); _context->texc->ShadowGenTextures( n, textures ); return; @@ -20458,6 +20438,7 @@ static void REGAL_CALL emu_glTexSubImage2D(GLenum target, GLint level, GLint xof { Push pushLevel(_context->emuLevel); _context->emuLevel = 1; + GLenum targetFormat; GLenum targetType; _context->texc->GetFormatAndType( target, level, &targetFormat, &targetType ); @@ -20884,7 +20865,12 @@ static void REGAL_CALL emu_glActiveTexture(GLenum texture) case 7 : case 6 : #if REGAL_EMU_IFF - if (_context->iff) break; + if (_context->iff) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 5; + _context->iff->ShadowActiveTexture( texture ); + } #endif case 5 : #if REGAL_EMU_SO @@ -20897,7 +20883,12 @@ static void REGAL_CALL emu_glActiveTexture(GLenum texture) case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowActiveTexture( texture ); + } #endif case 1 : default: @@ -20917,17 +20908,6 @@ static void REGAL_CALL emu_glActiveTexture(GLenum texture) case 8 : case 7 : case 6 : - #if REGAL_EMU_IFF - if (_context->iff) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 5; - if( ! _context->iff->ShadowActiveTexture( texture ) ) { - _context->dispatcher.emulation.glActiveTexture( texture ); - } - return; - } - #endif case 5 : #if REGAL_EMU_SO if (_context->so) @@ -20953,18 +20933,6 @@ static void REGAL_CALL emu_glActiveTexture(GLenum texture) return; } #endif - case 3 : - case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowActiveTexture( texture ); - _context->dispatcher.emulation.glActiveTexture( texture ); - return; - } - #endif case 1 : default: { @@ -34801,7 +34769,12 @@ static void REGAL_CALL emu_glGenerateMipmap(GLenum target) case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowGenerateMipmap( target ); + } #endif case 1 : #if REGAL_EMU_FILTER @@ -34828,16 +34801,6 @@ static void REGAL_CALL emu_glGenerateMipmap(GLenum target) case 4 : case 3 : case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowGenerateMipmap( target ); - _context->dispatcher.emulation.glGenerateMipmap( target ); - return; - } - #endif case 1 : #if REGAL_EMU_FILTER if (_context->filt) @@ -36541,7 +36504,12 @@ static void REGAL_CALL emu_glActiveTextureARB(GLenum texture) case 7 : case 6 : #if REGAL_EMU_IFF - if (_context->iff) break; + if (_context->iff) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 5; + _context->iff->ShadowActiveTexture( texture ); + } #endif case 5 : #if REGAL_EMU_SO @@ -36554,7 +36522,12 @@ static void REGAL_CALL emu_glActiveTextureARB(GLenum texture) case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowActiveTexture( texture ); + } #endif case 1 : #if REGAL_EMU_FILTER @@ -36577,17 +36550,6 @@ static void REGAL_CALL emu_glActiveTextureARB(GLenum texture) case 8 : case 7 : case 6 : - #if REGAL_EMU_IFF - if (_context->iff) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 5; - if( ! _context->iff->ShadowActiveTexture( texture ) ) { - _context->dispatcher.emulation.glActiveTextureARB( texture ); - } - return; - } - #endif case 5 : #if REGAL_EMU_SO if (_context->so) @@ -36615,16 +36577,6 @@ static void REGAL_CALL emu_glActiveTextureARB(GLenum texture) #endif case 3 : case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowActiveTexture( texture ); - _context->dispatcher.emulation.glActiveTexture( texture ); - return; - } - #endif case 1 : #if REGAL_EMU_FILTER if (_context->filt) @@ -64825,7 +64777,12 @@ static void REGAL_CALL emu_glGenerateMipmapEXT(GLenum target) case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowGenerateMipmap( target ); + } #endif case 1 : #if REGAL_EMU_FILTER @@ -64852,16 +64809,6 @@ static void REGAL_CALL emu_glGenerateMipmapEXT(GLenum target) case 4 : case 3 : case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowGenerateMipmap( target ); - _context->dispatcher.emulation.glGenerateMipmap( target ); - return; - } - #endif case 1 : #if REGAL_EMU_FILTER if (_context->filt) @@ -67108,7 +67055,12 @@ static void REGAL_CALL emu_glBindTextureEXT(GLenum target, GLuint texture) case 3 : case 2 : #if REGAL_EMU_TEXC - if (_context->texc) break; + if (_context->texc) + { + Push pushLevel(_context->emuLevel); + _context->emuLevel = 1; + _context->texc->ShadowBindTexture( target, texture ); + } #endif case 1 : default: @@ -67141,18 +67093,6 @@ static void REGAL_CALL emu_glBindTextureEXT(GLenum target, GLuint texture) return; } #endif - case 3 : - case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) - { - Push pushLevel(_context->emuLevel); - _context->emuLevel = 1; - _context->texc->ShadowBindTexture( target, texture ); - _context->dispatcher.emulation.glBindTexture( target, texture ); - return; - } - #endif case 1 : default: { @@ -67196,31 +67136,6 @@ static void REGAL_CALL emu_glDeleteTexturesEXT(GLsizei n, const GLuint *textures } #endif case 3 : - case 2 : - #if REGAL_EMU_TEXC - if (_context->texc) break; - #endif - case 1 : - default: - break; - } - - // impl - switch( _context->emuLevel ) - { - case 15 : - case 14 : - case 13 : - case 12 : - case 11 : - case 10 : - case 9 : - case 8 : - case 7 : - case 6 : - case 5 : - case 4 : - case 3 : case 2 : #if REGAL_EMU_TEXC if (_context->texc) @@ -67228,21 +67143,16 @@ static void REGAL_CALL emu_glDeleteTexturesEXT(GLsizei n, const GLuint *textures Push pushLevel(_context->emuLevel); _context->emuLevel = 1; _context->texc->ShadowDeleteTextures( n, textures ); - _context->dispatcher.emulation.glDeleteTextures( n, textures ); - return; } #endif case 1 : default: - { - DispatchTableGL *_next = _dispatch.next(); - RegalAssert(_next); - _next->call(&_next->glDeleteTexturesEXT)(n, textures); break; - } - } + DispatchTableGL *_next = _dispatch.next(); + RegalAssert(_next); + _next->call(& _next->glDeleteTexturesEXT)(n, textures); } static void REGAL_CALL emu_glGenTexturesEXT(GLsizei n, GLuint *textures) @@ -67298,6 +67208,7 @@ static void REGAL_CALL emu_glGenTexturesEXT(GLsizei n, GLuint *textures) { Push pushLevel(_context->emuLevel); _context->emuLevel = 1; + _context->dispatcher.emulation.glGenTextures( n, textures ); _context->texc->ShadowGenTextures( n, textures ); return; diff --git a/src/regal/RegalDispatcherGlobal.cpp b/src/regal/RegalDispatcherGlobal.cpp index f4738cd..fdfe8e5 100644 --- a/src/regal/RegalDispatcherGlobal.cpp +++ b/src/regal/RegalDispatcherGlobal.cpp @@ -65,7 +65,7 @@ DispatcherGlobal::DispatcherGlobal() // have to check this early for the global dispatches, otherwise we'd use Config #if REGAL_TRACE - { + { getEnv( "REGAL_TRACE", Config::enableTrace); ::memset(&trace, 0, sizeof(trace) ); InitDispatchTableGlobalTrace(trace); diff --git a/src/regal/RegalDsa.h b/src/regal/RegalDsa.h index 2131bdf..8c069f6 100644 --- a/src/regal/RegalDsa.h +++ b/src/regal/RegalDsa.h @@ -154,6 +154,7 @@ struct Dsa if( NotMatrixMode( mode ) ) { dsa.matrixMode = mode; switch( mode ) { + //<> dsn: wtf? Why are these accepted? And why only up to GL_TEXTURE3? case GL_TEXTURE0: case GL_TEXTURE1: case GL_TEXTURE2: case GL_TEXTURE3: DsaActiveTexture( ctx, mode ); dsa.matrixMode = GL_TEXTURE; @@ -175,11 +176,15 @@ struct Dsa return tex != ( dsa.activeTexture != REGAL_DSA_INVALID ? dsa.activeTexture : drv.activeTexture ); } bool ShadowActiveTexture( GLenum realActiveTexture ) { + if ( !validTextureEnum(realActiveTexture) ) + return false; drv.activeTexture = realActiveTexture; bool usingDsa = dsa.activeTexture != REGAL_DSA_INVALID; return usingDsa; } void DsaActiveTexture( RegalContext * ctx, GLenum tex) { + if ( !validTextureEnum(tex) ) + return; if( NotActiveTexture( tex ) ) { dsa.activeTexture = tex; ctx->dispatcher.emulation.glActiveTexture( dsa.activeTexture ); @@ -545,7 +550,6 @@ struct Dsa for( int i = maxTextureUnit; i >= 0; i-- ) { tbl.call(&tbl.glClientActiveTexture)( GL_TEXTURE0 + i ); tbl.call(&tbl.glDisableClientState) ( GL_TEXTURE_COORD_ARRAY ); - } for( int i = 0; i < 16; i++ ) { tbl.call(&tbl.glDisableVertexAttribArray)( i ); diff --git a/src/regal/RegalEmu.cpp b/src/regal/RegalEmu.cpp new file mode 100644 index 0000000..d5a4f44 --- /dev/null +++ b/src/regal/RegalEmu.cpp @@ -0,0 +1,95 @@ +/* + Copyright (c) 2011-2012 NVIDIA Corporation + Copyright (c) 2011-2012 Cass Everitt + Copyright (c) 2012 Scott Nations + Copyright (c) 2012 Mathias Schott + Copyright (c) 2012 Nigel Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + + Regal Emulation layer helpers + Scott Nations + + */ + +#include "RegalUtil.h" + +#if REGAL_EMULATION + +#include "RegalEmu.h" +#include "RegalToken.h" + +REGAL_GLOBAL_BEGIN + +#include + +#include + +REGAL_GLOBAL_END + +REGAL_NAMESPACE_BEGIN + +namespace Emu +{ + +// From the GL spec for ERRORS associated with glActiveTexture + +// An INVALID_ENUM error is generated if an invalid texture is specified. +// texture is a symbolic constant of the form TEXTUREi, indicating that texture +// unit i is to be modified. The constants obey TEXTUREi = TEXTURE0 +i where +// i is in the range 0 to k - 1, and k is the larger of the values of +// MAX_TEXTURE_COORDS and MAX_COMBINED_TEXTURE_IMAGE_UNITS). + +// For backwards compatibility, the implementation-dependent constant +// MAX_TEXTURE_UNITS specifies the number of conventional texture units +// supported by the implementation. Its value must be no larger than the +// minimum of MAX_TEXTURE_COORDS and MAX_COMBINED_TEXTURE_IMAGE_UNITS. + +bool validTextureEnum(GLenum texture) +{ + GLint unit = texture - GL_TEXTURE0; + return validTextureUnit( static_cast(unit) ); +} + +bool validTextureUnit(GLuint unit) +{ + RegalAssert(REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS >= REGAL_EMU_MAX_TEXTURE_COORDS); + if (unit >= REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS) + { + Warning( "Active texture out of range: ", + Token::GLtextureToString(static_cast(GL_TEXTURE0 + unit)), + " > ", + Token::GLtextureToString(static_cast(GL_TEXTURE0 + REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1))); + return false; + } + return true; +} + +}; + +REGAL_NAMESPACE_END + +#endif // REGAL_EMULATION diff --git a/src/regal/RegalEmu.h b/src/regal/RegalEmu.h index 6a4fe3c..1de3eab 100644 --- a/src/regal/RegalEmu.h +++ b/src/regal/RegalEmu.h @@ -30,8 +30,8 @@ /* - Regal Emulation layer base class. - Cass Everitt + Regal Emulation layer constants + Cass Everitt, Scott Nations */ @@ -44,41 +44,78 @@ REGAL_GLOBAL_BEGIN #include -#include - REGAL_GLOBAL_END REGAL_NAMESPACE_BEGIN +namespace Emu +{ + // In ES2 mode, 16 texture units only? +// No. of fixed function texture units. 2 minimum. + #ifndef REGAL_EMU_MAX_TEXTURE_UNITS -#define REGAL_EMU_MAX_TEXTURE_UNITS 32 +#define REGAL_EMU_MAX_TEXTURE_UNITS 4 #endif +// No. of texture coordinate sets. 8 minimum. + #ifndef REGAL_EMU_MAX_TEXTURE_COORDS -#define REGAL_EMU_MAX_TEXTURE_COORDS 8 +#define REGAL_EMU_MAX_TEXTURE_COORDS 16 #endif +// No. of active vertex attributes. 16 minimum. + #ifndef REGAL_EMU_MAX_VERTEX_ATTRIBS #define REGAL_EMU_MAX_VERTEX_ATTRIBS 16 #endif +// Max no. of vertex buffers. 16 minimum + #ifndef REGAL_EMU_MAX_VERTEX_ATTRIB_BINDINGS -#define REGAL_EMU_MAX_VERTEX_ATTRIB_BINDINGS 32 +#define REGAL_EMU_MAX_VERTEX_ATTRIB_BINDINGS 16 #endif -// glspec43.compatibility.20130214.withchanges.pdf Table 23.65, p. 709 -// lists the minumum value for MAX_CLIENT_ATTRIB_STACK_DEPTH as 16 +// Total no. of texture units accessible by the GL. 96 minimum + +#ifndef REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS +#define REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS 96 +#endif + +// Max depth of the server attribute stack. 16 minimum. + +#ifndef REGAL_EMU_MAX_ATTRIB_STACK_DEPTH +#define REGAL_EMU_MAX_ATTRIB_STACK_DEPTH 16 +#endif + +// Max depth of the client attribute stack. 16 minimum. #ifndef REGAL_EMU_MAX_CLIENT_ATTRIB_STACK_DEPTH #define REGAL_EMU_MAX_CLIENT_ATTRIB_STACK_DEPTH 16 #endif +// Max no. of active draw buffers. 8 minimum + +#ifndef REGAL_EMU_MAX_DRAW_BUFFERS +#define REGAL_EMU_MAX_DRAW_BUFFERS 8 +#endif + +// Max no. of active viewports. 16 minimum + +#ifndef REGAL_EMU_MAX_VIEWPORTS +#define REGAL_EMU_MAX_VIEWPORTS 16 +#endif + #if REGAL_EMULATION +extern bool validTextureEnum(GLenum texture); +extern bool validTextureUnit(GLuint unit); + #endif // REGAL_EMULATION +}; + REGAL_NAMESPACE_END #endif // ! __REGAL_EMU_H__ diff --git a/src/regal/RegalFilt.cpp b/src/regal/RegalFilt.cpp index c97cab7..a9a3307 100644 --- a/src/regal/RegalFilt.cpp +++ b/src/regal/RegalFilt.cpp @@ -420,8 +420,8 @@ namespace Emu { case GL_MAX_PIXEL_MAP_TABLE: retVal = 256; break; case GL_MAX_NAME_STACK_DEPTH: retVal = 128; break; case GL_MAX_LIST_NESTING: retVal = 64; break; - case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: - case GL_MAX_ATTRIB_STACK_DEPTH: retVal = 16; break; + case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: retVal = ctx.info->max_client_attrib_stack_depth; break; + case GL_MAX_ATTRIB_STACK_DEPTH: retVal = ctx.info->max_attrib_stack_depth; break; case GL_DEPTH_BITS: retVal = 24; break; diff --git a/src/regal/RegalHint.h b/src/regal/RegalHint.h index 7f9ee2a..fc18a44 100644 --- a/src/regal/RegalHint.h +++ b/src/regal/RegalHint.h @@ -192,4 +192,4 @@ REGAL_NAMESPACE_END #endif // REGAL_EMULATION -#endif // ! __REGAL_BASEVERTEX_H__ +#endif // ! __REGAL_HINT_H__ diff --git a/src/regal/RegalIff.cpp b/src/regal/RegalIff.cpp index e9aa2ab..f85b343 100644 --- a/src/regal/RegalIff.cpp +++ b/src/regal/RegalIff.cpp @@ -49,15 +49,12 @@ typedef boost::print::string_list string_list; #include "RegalToken.h" #include "RegalHelper.h" -#include "lookup3.h" - REGAL_GLOBAL_END REGAL_NAMESPACE_BEGIN -namespace Emu { - -#define REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS 2 +namespace Emu +{ using namespace ::REGAL_NAMESPACE_INTERNAL::Logging; using namespace ::REGAL_NAMESPACE_INTERNAL::Token; @@ -70,7 +67,8 @@ typedef Iff::State::Store Store; typedef Iff::State::StoreUniform StoreUniform; typedef Iff::Program Program; -enum FFLightEl { +enum FFLightEl +{ LE_Ambient = 0, LE_Diffuse = 1, LE_Specular = 2, @@ -79,7 +77,8 @@ enum FFLightEl { LE_Atten = 5, LE_Elements = 6 }; -enum FFMaterialEl { +enum FFMaterialEl +{ ME_Ambient = 0, ME_Diffuse = 1, ME_Specular = 2, @@ -88,14 +87,22 @@ enum FFMaterialEl { ME_Elements = 5 }; -static Iff::TextureTargetBitfield TargetToBitfield( GLenum target ) { - switch( target ) { - case GL_TEXTURE_1D: return Iff::TT_1D; - case GL_TEXTURE_2D: return Iff::TT_2D; - case GL_TEXTURE_RECTANGLE: return Iff::TT_Rect; - case GL_TEXTURE_3D: return Iff::TT_3D; - case GL_TEXTURE_CUBE_MAP: return Iff::TT_CubeMap; - default: break; +static Iff::TextureTargetBitfield TargetToBitfield( GLenum target ) +{ + switch( target ) + { + case GL_TEXTURE_1D: + return Iff::TT_1D; + case GL_TEXTURE_2D: + return Iff::TT_2D; + case GL_TEXTURE_RECTANGLE: + return Iff::TT_Rect; + case GL_TEXTURE_3D: + return Iff::TT_3D; + case GL_TEXTURE_CUBE_MAP: + return Iff::TT_CubeMap; + default: + break; } return Iff::TT_None; } @@ -112,12 +119,20 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat bool hasSphereMap = false; bool hasReflectionMap = false; bool hasEyeLinearTexGen = false; - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { - if( st.tex[i].enables == 0 ) { + + size_t n = array_size( st.tex ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.tex, i ); + if ( st.tex[i].enables == 0 ) + { continue; } - for( int j = 0; j < 4; j++ ) { - if( st.tex[i].texgen[j].enable == false ) { + for ( size_t j = 0; j < 4; j++ ) + { + RegalAssertArrayIndex( st.tex[i].texgen, j ); + if ( st.tex[i].texgen[j].enable == false ) + { continue; } Iff::TexgenMode mode = st.tex[i].texgen[j].mode; @@ -128,11 +143,15 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat } } bool hasClipPlanes = false; - for( int i = 0; i < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES; i++ ) { - hasClipPlanes = hasClipPlanes || st.clip[i].enable; + n = array_size( st.clipPlaneEnabled ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.clipPlaneEnabled, i ); + hasClipPlanes = hasClipPlanes || st.clipPlaneEnabled[i]; } - if( gles ) { + if ( gles ) + { #if REGAL_FORCE_DESKTOP_GLSL // Desktop version 140 corresponds to OpenGL 3.1, // which corresponds to the functionality of ES2. @@ -140,24 +159,33 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat #else src << "#version 100\n"; #endif - } else if ( legacy ) { + } + else if ( legacy ) + { src << "#version 120\n"; - } else { + } + else + { src << "#version 140\n"; } src << "// program number " << rff->progcount << "\n"; - if( gles || legacy ) { + if ( gles || legacy ) + { src << "#define in attribute\n"; src << "#define out varying\n"; } - if( st.shadeModelFlat && ! legacy && ! gles ) { + if ( st.shadeModelFlat && ! legacy && ! gles ) + { src << "#define FLAT flat\n"; - } else { + } + else + { src << "#define FLAT \n"; } - if( st.lighting ) { + if ( st.lighting ) + { src << "\n"; src << "#define ME_AMBIENT " << int(ME_Ambient) << "\n"; src << "#define ME_DIFFUSE " << int(ME_Diffuse) << "\n"; @@ -176,93 +204,135 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat src << "\n"; } - if( gles ) { + if ( gles ) + { src << "precision highp float;\n"; } - if( ~st.attrArrayFlags & ( 1 << rff->ffAttrMap[ RFF2A_Color ] ) ) { - src << "uniform vec4 rglAttrib[" << REGAL_EMU_IFF_VERTEX_ATTRIBS << "];\n"; + RegalAssertArrayIndex( rff->ffAttrMap, RFF2A_Color ); + if ( ~st.attrArrayFlags & ( 1 << rff->ffAttrMap[ RFF2A_Color ] ) ) + { + src << "uniform vec4 rglAttrib[" << REGAL_EMU_MAX_VERTEX_ATTRIBS << "];\n"; } src << "uniform mat4 rglModelview;\n"; src << "uniform mat4 rglProjection;\n"; src << "in vec4 rglVertex;\n"; - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { - if( st.tex[i].useMatrix ) { + n = array_size( st.tex ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.tex, i ); + if ( st.tex[i].useMatrix ) + { src << "uniform mat4 rglTextureMatrix" << i << ";\n"; } } - for( int i = 0; i < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES; i++ ) { - if( st.clip[i].enable ) { + n = array_size( st.clipPlaneEnabled ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.clipPlaneEnabled, i ); + if ( st.clipPlaneEnabled[i] ) + { src << "uniform vec4 rglClipPlane" << i << ";\n"; - if( gles || legacy ) { + if ( gles || legacy ) + { src << "out float rglClipDistance" << i << ";\n"; } } } //src << "in vec4 rglWeight;\n"; - if( st.lighting || hasNormalMap || hasSphereMap || hasReflectionMap ) { + if ( st.lighting || hasNormalMap || hasSphereMap || hasReflectionMap ) + { src << "uniform mat4 rglModelviewInverseTranspose;\n"; src << "in vec3 rglNormal;\n"; } - if( st.lighting ) { + if ( st.lighting ) + { src << "uniform vec4 rglLightModelAmbient;\n"; src << "uniform vec4 rglMaterialFront" << "[ ME_ELEMENTS ];\n"; - if( st.lightModelTwoSide ) { + if ( st.lightModelTwoSide ) + { src << "uniform vec4 rglMaterialBack" << "[ ME_ELEMENTS ];\n"; } - for( int i = 0; i < REGAL_FIXED_FUNCTION_MAX_LIGHTS; i++ ) { - if( st.light[ i ].enable ) { + for ( size_t i = 0; i < REGAL_FIXED_FUNCTION_MAX_LIGHTS; i++ ) + { + if ( st.light[ i ].enable ) + { src << "uniform vec4 rglLight" << i << "[ LE_ELEMENTS ];\n"; } } } - if( st.attrArrayFlags & ( 1 << rff->ffAttrMap[ RFF2A_Color ] ) && ( st.lighting == false || st.colorMaterial ) ) { + RegalAssertArrayIndex( rff->ffAttrMap, RFF2A_Color ); + if ( st.attrArrayFlags & ( 1 << rff->ffAttrMap[ RFF2A_Color ] ) && ( st.lighting == false || st.colorMaterial ) ) + { src << "in vec4 rglColor;\n"; - } else { + } + else + { src << "#define rglColor rglAttrib[" << rff->ffAttrMap[ RFF2A_Color ] << "]\n"; } - if( st.colorSum && st.lighting == false ) { + if ( st.colorSum && st.lighting == false ) + { src << "in vec4 rglSecondaryColor;\n"; } - if( st.fog.enable ) { + if ( st.fog.enable ) + { src << "uniform vec4 rglFog[2];\n"; src << "out vec4 rglFOG;\n"; - if( st.fog.useDepth == false ) { + if ( st.fog.useDepth == false ) + { src << "in float rglFogCoord;\n"; } } - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { - if( st.tex[i].enables == 0 ) { + n = array_size( st.tex ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.tex, i ); + if ( st.tex[i].enables == 0 ) + { continue; } src << "in vec4 rglMultiTexCoord" << i << ";\n"; } src << "FLAT out vec4 rglFrontColor;\n"; - if( st.lighting ) { - if( st.lightModelTwoSide ) { + if ( st.lighting ) + { + if ( st.lightModelTwoSide ) + { src << "FLAT out vec4 rglBackColor;\n"; } - if( st.lightModelSeparateSpecular ) { + if ( st.lightModelSeparateSpecular ) + { src << "out vec4 rglSCOL0;\n"; - if( st.lightModelTwoSide ) { + if ( st.lightModelTwoSide ) + { src << "out vec4 rglSCOL1;\n"; } } - } else if( st.colorSum ) { + } + else if( st.colorSum ) + { src << "out vec4 rglSCOL0;\n"; } - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { + n = array_size( st.tex ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.tex, i ); const State::Texture & t = st.tex[i]; - if( t.enables == 0 ) { + if ( t.enables == 0 ) + { continue; } const char *tc[] = { "S", "T", "R", "Q" }; - for( int j = 0; j < 4; j++ ) { + for ( size_t j = 0; j < 4; j++ ) + { + RegalAssertArrayIndex( t.texgen, j ); const State::Texgen & g = t.texgen[j]; - if( g.enable == false ) { + if ( g.enable == false ) + { continue; } - switch( g.mode ) { + switch( g.mode ) + { case Iff::TG_EyeLinear: src << "uniform vec4 rglTexGen" << i << "Eye" << tc[j] << ";\n"; break; @@ -277,20 +347,23 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat src << "out vec4 rglTEXCOORD" << i << ";\n"; } - if( hasNormalMap ) { + if ( hasNormalMap ) + { src << "vec4 ComputeNormalMap( vec3 n ) {\n"; src << " return vec4( n.x, n.y, n.z, 0.0 );\n"; src << "}\n"; } - if( hasReflectionMap ) { + if ( hasReflectionMap ) + { src << "vec4 ComputeReflectionMap( vec3 i, vec3 n ) {\n"; src << " vec3 r = reflect( i, n );\n"; src << " return vec4( r.x, r.y, r.z, 0.0 );\n"; src << "}\n"; } - if( hasSphereMap ) { + if ( hasSphereMap ) + { src << "vec4 ComputeSphereMap( vec3 i, vec3 n ) {\n"; src << " vec3 r = reflect( i, n );\n"; src << " float minv = 1.0 / sqrt( 2.0 * r.x + 2.0 * r.y + 2.0 * (r.z + 1.0 ) );\n"; @@ -300,27 +373,32 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat src << "void main() {\n"; src << " gl_Position = rglProjection * rglModelview * rglVertex;\n"; - if( st.lighting || hasNormalMap || hasReflectionMap || hasEyeLinearTexGen || - hasClipPlanes || ( st.fog.enable && st.fog.useDepth ) || hasSphereMap ) { + if ( st.lighting || hasNormalMap || hasReflectionMap || hasEyeLinearTexGen || + hasClipPlanes || ( st.fog.enable && st.fog.useDepth ) || hasSphereMap ) + { src << " vec4 eh = rglModelview * rglVertex;\n"; } - if( st.lighting || hasNormalMap || hasReflectionMap || hasSphereMap ) { + if ( st.lighting || hasNormalMap || hasReflectionMap || hasSphereMap ) + { src << " vec4 ep = eh / eh.w;\n"; src << " vec3 ev = -normalize( ep.xyz );\n"; src << " vec3 en = mat3( rglModelviewInverseTranspose ) * rglNormal;\n"; - if( st.normalize ) { + if ( st.normalize ) + { src << " en = normalize( en );\n"; } } - if( st.lighting ) { + if ( st.lighting ) + { src << " vec4 mFront[ ME_ELEMENTS ];\n"; src << " mFront[ ME_AMBIENT ] = rglMaterialFront[ ME_AMBIENT ];\n"; src << " mFront[ ME_DIFFUSE ] = rglMaterialFront[ ME_DIFFUSE ];\n"; src << " mFront[ ME_SPECULAR ] = rglMaterialFront[ ME_SPECULAR ];\n"; src << " mFront[ ME_EMISSION ] = rglMaterialFront[ ME_EMISSION ];\n"; src << " mFront[ ME_SHININESS ] = rglMaterialFront[ ME_SHININESS ];\n"; - if( st.lightModelTwoSide ) { + if ( st.lightModelTwoSide ) + { src << " vec4 mBack [ ME_ELEMENTS ];\n"; src << " mBack [ ME_AMBIENT ] = rglMaterialBack [ ME_AMBIENT ];\n"; src << " mBack [ ME_DIFFUSE ] = rglMaterialBack [ ME_DIFFUSE ];\n"; @@ -328,8 +406,10 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat src << " mBack [ ME_EMISSION ] = rglMaterialBack [ ME_EMISSION ];\n"; src << " mBack [ ME_SHININESS ] = rglMaterialBack [ ME_SHININESS ];\n"; } - if( st.colorMaterial ) { - switch( st.colorMaterialTarget0 ) { + if ( st.colorMaterial ) + { + switch( st.colorMaterialTarget0 ) + { case Iff::CM_None: break; case Iff::CM_Ambient: @@ -352,8 +432,10 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat src << "//ERROR: unsupported color material[0] target\n"; break; } - if( st.lightModelTwoSide ) { - switch( st.colorMaterialTarget1 ) { + if ( st.lightModelTwoSide ) + { + switch( st.colorMaterialTarget1 ) + { case Iff::CM_None: break; case Iff::CM_Ambient: @@ -381,34 +463,46 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat src << " rglFrontColor.xyz = mFront[ ME_EMISSION ].xyz;\n"; src << " rglFrontColor.w = mFront[ ME_DIFFUSE ].w;\n"; src << " rglFrontColor.xyz += rglLightModelAmbient.xyz * mFront[ ME_AMBIENT ].xyz;\n"; - if( st.lightModelSeparateSpecular ) { + if ( st.lightModelSeparateSpecular ) + { src << " rglSCOL0 = vec4( 0, 0, 0, 0);\n"; } - if( st.lightModelTwoSide ) { + if ( st.lightModelTwoSide ) + { src << " rglBackColor.xyz = mBack[ ME_EMISSION ].xyz;\n"; src << " rglBackColor.w = mBack[ ME_DIFFUSE ].w;\n"; src << " rglBackColor.xyz += rglLightModelAmbient.xyz * mBack[ ME_AMBIENT ].xyz;\n"; - if( st.lightModelSeparateSpecular ) { + if ( st.lightModelSeparateSpecular ) + { src << " rglSCOL1 = vec4( 0, 0, 0, 0);\n"; } } - for( int i = 0; i < REGAL_FIXED_FUNCTION_MAX_LIGHTS; i++ ) { - if( st.light[ i ].enable ) { + n = array_size( st.light ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.light, i ); + if ( st.light[ i ].enable ) + { src << " {\n"; string attenmul = ""; src << " vec4 lvec = rglLight" << i << "[ LE_POSITION ];\n"; - if( st.light[ i ].attenuate || st.light[ i ].spotlight ) { + if ( st.light[ i ].attenuate || st.light[ i ].spotlight ) + { src << " float att = 1.0;\n"; attenmul = "att *"; } - if( st.light[ i ].local ) { + if ( st.light[ i ].local ) + { src << " lvec.xyz -= ep.xyz;\n"; src << " float ad = sqrt( dot( lvec.xyz, lvec.xyz ) );\n"; src << " lvec.xyz /= ad;\n"; } - if( st.lightModelLocalViewer ) { + if ( st.lightModelLocalViewer ) + { src << " vec3 hvec = normalize( lvec.xyz + ev );\n"; - } else { + } + else + { src << " vec3 hvec = normalize( lvec.xyz + vec3( 0, 0, 1 ) );\n"; } src << " vec3 ambient = rglLight" << i << "[ LE_AMBIENT ].xyz * mFront[ ME_AMBIENT ].xyz;\n"; @@ -417,42 +511,54 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat src << " vec3 diffuse = dc * rglLight" << i << "[ LE_DIFFUSE ].xyz * mFront[ ME_DIFFUSE ].xyz;\n"; src << " sc = ( dc > 0.0 && sc > 0.0 ) ? exp( mFront[ ME_SHININESS ].x * log( sc ) ) : 0.0;\n"; src << " vec3 specular = sc * rglLight" << i << "[ LE_SPECULAR ].xyz * mFront[ ME_SPECULAR ].xyz;\n"; - if( st.light[ i ].attenuate && st.light[ i ].local ) { + if ( st.light[ i ].attenuate && st.light[ i ].local ) + { src << " vec3 dist = vec3( 1.0, ad, ad * ad );\n"; src << " att = 1.0 / dot( dist, rglLight" << i << "[ LE_ATTEN ].xyz );\n"; } - if( st.light[ i ].spotlight ) { + if ( st.light[ i ].spotlight ) + { src << " float spcut = cos( radians( rglLight" << i << "[ LE_SPOTDIR ].w ) );\n"; src << " float sd = dot( rglLight" << i << "[ LE_SPOTDIR ].xyz, lvec.xyz );\n"; src << " att *= ( sd > spcut ) ? exp( rglLight" << i << "[ LE_ATTEN ].w * log( sd ) ) : 0.0;\n"; } - if( st.lightModelSeparateSpecular ) { + if ( st.lightModelSeparateSpecular ) + { src << " rglFrontColor.xyz += " << attenmul << " ( ambient + diffuse );\n"; src << " rglSCOL0.xyz += " << attenmul << " specular;\n"; - } else { + } + else + { src << " rglFrontColor.xyz += " << attenmul << " ( ambient + diffuse + specular );\n"; } - if( st.lightModelTwoSide ) { + if ( st.lightModelTwoSide ) + { src << " ambient = rglLight" << i << "[ LE_AMBIENT ].xyz * mBack[ ME_AMBIENT ].xyz;\n"; src << " dc = max( dot( -en, lvec.xyz ), 0.0 );\n"; src << " sc = max( dot( -en, hvec ), 0.0 );\n"; src << " diffuse = dc * rglLight" << i << "[ LE_DIFFUSE ].xyz * mBack[ ME_DIFFUSE ].xyz;\n"; src << " sc = ( dc > 0.0 && sc > 0.0 ) ? exp( mBack[ ME_SHININESS ].x * log( sc ) ) : 0.0;\n"; src << " specular = sc * rglLight" << i << "[ LE_SPECULAR ].xyz * mBack[ ME_SPECULAR ].xyz;\n"; - if( st.lightModelSeparateSpecular ) { + if ( st.lightModelSeparateSpecular ) + { src << " rglBackColor.xyz += " << attenmul << " ( ambient + diffuse );\n"; src << " rglSCOL1.xyz += " << attenmul << " specular;\n"; - } else { + } + else + { src << " rglBackColor.xyz += " << attenmul << " ( ambient + diffuse + specular );\n"; } } src << " }\n"; } } - } else { + } + else + { src << " rglFrontColor = rglColor;\n"; - if( st.colorSum ) { + if ( st.colorSum ) + { src << " rglSCOL0 = rglSecondaryColor;\n"; } } @@ -460,56 +566,78 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat // clamp all the output colors to (0.0, 1.0) src << " rglFrontColor = clamp( rglFrontColor, 0.0, 1.0 );\n"; - if( st.lighting ) { - if( st.lightModelTwoSide ) { + if ( st.lighting ) + { + if ( st.lightModelTwoSide ) + { src << " rglBackColor = clamp( rglBackColor, 0.0, 1.0 );\n"; } - if( st.lightModelSeparateSpecular ) { + if ( st.lightModelSeparateSpecular ) + { src << " rglSCOL0 = clamp( rglSCOL0, 0.0, 1.0 );\n"; - if( st.lightModelTwoSide ) { + if ( st.lightModelTwoSide ) + { src << " rglSCOL1 = clamp( rglSCOL1, 0.0, 1.0 );\n"; } } - } else if( st.colorSum ) { + } + else if( st.colorSum ) + { src << " rglSCOL0 = clamp( rglSCOL0, 0.0, 1.0 );\n"; } - if( st.fog.enable ) { - if( st.fog.useDepth ) { + if ( st.fog.enable ) + { + if ( st.fog.useDepth ) + { src << " rglFOG = eh;\n"; - } else { + } + else + { src << " rglFOG = vec4(0, 0, -rglFogCoord, 1);\n"; } } - if( hasNormalMap ) { + if ( hasNormalMap ) + { src << " vec4 nmTc = ComputeNormalMap( en );\n"; } - if( hasReflectionMap ) { + if ( hasReflectionMap ) + { src << " vec4 rmTc = ComputeReflectionMap( -ev, en );\n"; } - if( hasSphereMap ) { + if ( hasSphereMap ) + { src << " vec4 smTc = ComputeSphereMap( -ev, en );\n"; } bool tc_declared = false; - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { + n = array_size( state.processed.tex ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( state.processed.tex, i ); const State::Texture & t = state.processed.tex[i]; - if( t.enables == 0 ) { + if ( t.enables == 0 ) + { continue; } - if ( !tc_declared ) { + if ( !tc_declared ) + { src << " vec4 tc;\n"; tc_declared = true; } src << " tc = rglMultiTexCoord" << i << ";\n"; const char *comp[] = { "x", "y", "z", "w" }; const char *tc[] = { "S", "T", "R", "Q" }; - for( int j = 0; j < 4; j++ ) { - if( t.texgen[j].enable == false ) { + for ( size_t j = 0; j < 4; j++ ) + { + RegalAssertArrayIndex( t.texgen, j ); + if ( t.texgen[j].enable == false ) + { continue; } - switch( t.texgen[j].mode ) { + switch( t.texgen[j].mode ) + { case Iff::TG_ObjectLinear: src << " tc." << comp[j] << " = dot( rglTexGen" << i << "Obj" << tc[j] << ", rglVertex );\n"; break; @@ -530,17 +658,27 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat break; } } - if( t.useMatrix ) { + if ( t.useMatrix ) + { src << " rglTEXCOORD" << i << " = rglTextureMatrix" << i << " * tc;\n"; - } else { + } + else + { src << " rglTEXCOORD" << i << " = tc;\n"; } } - for( int i = 0; i < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES; i++ ) { - if( st.clip[i].enable ) { - if( gles || legacy ) { + n = array_size( st.clipPlaneEnabled ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.clipPlaneEnabled, i ); + if ( st.clipPlaneEnabled[i] ) + { + if ( gles || legacy ) + { src << " rglClipDistance" << i; - } else { + } + else + { src << " gl_ClipDistance[" << i << "]"; } src << " = dot( eh, rglClipPlane" << i << " );\n"; @@ -551,13 +689,15 @@ static void GenerateVertexShaderSource( const Iff * rff, const Iff::State & stat -static void AddTexEnv( int i, Iff::TexenvMode env, GLenum fmt, string_list & s ) +static void AddTexEnv( size_t i, Iff::TexenvMode env, GLenum fmt, string_list & s ) { Internal("Regal::Iff::AddTexEnv","()"); - switch( env ) { + switch( env ) + { case Iff::TEM_Replace: - switch( fmt ) { + switch( fmt ) + { case GL_ALPHA: s << " p.w = s.w;\n"; break; @@ -575,7 +715,8 @@ static void AddTexEnv( int i, Iff::TexenvMode env, GLenum fmt, string_list & s } break; case Iff::TEM_Modulate: - switch( fmt ) { + switch( fmt ) + { case GL_ALPHA: s << " p.w *= s.w;\n"; break; @@ -593,7 +734,8 @@ static void AddTexEnv( int i, Iff::TexenvMode env, GLenum fmt, string_list & s } break; case Iff::TEM_Blend: - switch( fmt ) { + switch( fmt ) + { case GL_ALPHA: s << " p.w *= s.w;\n"; break; @@ -612,7 +754,8 @@ static void AddTexEnv( int i, Iff::TexenvMode env, GLenum fmt, string_list & s } break; case Iff::TEM_Add: - switch( fmt ) { + switch( fmt ) + { case GL_ALPHA: s << " p.w *= s.w;\n"; break; @@ -631,7 +774,8 @@ static void AddTexEnv( int i, Iff::TexenvMode env, GLenum fmt, string_list & s } break; case Iff::TEM_Decal: - switch( fmt ) { + switch( fmt ) + { case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: @@ -662,7 +806,8 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) int rgbSources = 0; int aSources = 0; s << " {\n"; - switch( env.rgb.mode ) { + switch( env.rgb.mode ) + { case Iff::TEC_Replace: rgbSources = 1; break; @@ -679,8 +824,10 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) default: break; } - if( skipAlpha == false ) { - switch( env.a.mode ) { + if ( skipAlpha == false ) + { + switch( env.a.mode ) + { case Iff::TEC_Replace: aSources = 1; break; @@ -699,11 +846,13 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) break; } } - for( int i = 0; i < rgbSources; i++ ) { + for ( int i = 0; i < rgbSources; i++ ) + { bool skip = false; string source; Iff::TexenvCombineSrc src = i == 0 ? env.rgb.src0 : i == 1 ? env.rgb.src1 : env.rgb.src2; - switch( src ) { + switch( src ) + { case Iff::TCS_PrimaryColor: source = "rglFrontColor"; break; @@ -722,7 +871,8 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) } string suffix; Iff::TexenvCombineOp op = i == 0 ? env.rgb.op0 : i == 1 ? env.rgb.op1 : env.rgb.op2; - switch( op ) { + switch( op ) + { case Iff::TCO_Alpha: case Iff::TCO_OneMinusAlpha: suffix = ".www"; @@ -735,17 +885,22 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) skip = true; break; } - if ( skip ) { + if ( skip ) + { s << " vec3 csrc" << i << " = vec3(0.0f, 0.0f, 0.0f);\n"; - } else { + } + else + { s << " vec3 csrc" << i << " = "; - if( op == Iff::TCO_OneMinusColor || op == Iff::TCO_OneMinusAlpha ) { + if ( op == Iff::TCO_OneMinusColor || op == Iff::TCO_OneMinusAlpha ) + { s << "1 - "; } s << source << suffix << ";\n"; } } - switch( env.rgb.mode ) { + switch( env.rgb.mode ) + { case Iff::TEC_Replace: s << " p.xyz = csrc0;\n"; break; @@ -769,19 +924,25 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) s << " p.xyz = mix( csrc0, csrc1, csrc2);\n"; break; default: - s << "//ERROR: Unsupported tex env combine rgb mode\n"; break; + s << "//ERROR: Unsupported tex env combine rgb mode\n"; + break; break; } if ( env.rgb.scale != 1.0 ) s << " p.xyz = clamp(" << env.rgb.scale << " * p.xyz, 0.0, 1.0);\n"; - if( skipAlpha ) { + if ( skipAlpha ) + { s << " p.w = p.x;\n"; - } else { - for( int i = 0; i < aSources; i++ ) { + } + else + { + for ( int i = 0; i < aSources; i++ ) + { bool skip = false; string source; Iff::TexenvCombineSrc src = i == 0 ? env.a.src0 : i == 1 ? env.a.src1 : env.a.src2; - switch( src ) { + switch( src ) + { case Iff::TCS_PrimaryColor: source = "rglFrontColor"; break; @@ -798,18 +959,23 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) skip = true; break; } - if ( skip ) { + if ( skip ) + { s << " float asrc" << i << " = 0.0f;\n"; - } else { + } + else + { Iff::TexenvCombineOp op = i == 0 ? env.a.op0 : i == 1 ? env.a.op1 : env.a.op2; s << " float asrc" << i << " = "; - if( op == Iff::TCO_OneMinusAlpha ) { + if ( op == Iff::TCO_OneMinusAlpha ) + { s << "1 - "; } s << source << ".w;\n"; } } - switch( env.a.mode ) { + switch( env.a.mode ) + { case Iff::TEC_Replace: s << " p.w = asrc0;\n"; break; @@ -829,7 +995,8 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) s << " p.w = mix( asrc0, asrc1, asrc2 );\n"; break; default: - s << "//ERROR: Unsupported tex env combine alpha mode\n"; break; + s << "//ERROR: Unsupported tex env combine alpha mode\n"; + break; break; } if ( env.a.scale != 1.0 ) @@ -838,79 +1005,79 @@ static void AddTexEnvCombine( Iff::TextureEnv & env, string_list & s ) s << " }\n"; } -#if 0 -string TexEnvModeName( GLenum mode ) { - switch( mode ) { - case GL_MODULATE: return "Modulate"; - case GL_ADD: return "Add"; - case GL_REPLACE: return "Replace"; - case GL_COMBINE: return "Combine"; - default: break; - } - return ""; -} -string TexFormatName( GLenum format ) { - switch( format ) { - case GL_ALPHA: return "A"; - case GL_LUMINANCE: return "L"; - case GL_LUMINANCE_ALPHA: return "LA"; - case GL_RGB: return "RGB"; - case GL_RGBA: return "RGBA"; - default: break; - } - return ""; -} -string TexEnvFuncName( GLenum mode, GLenum format ) { - string s; - s += "TexEnv"; - s += TexEnvModeName( mode ); - s += TexFormatName( format ); - return s; -} -#endif - -static string TargetSuffix( GLubyte ttb ) { - switch( ttb ) { - case Iff::TT_1D: return "1D"; - case Iff::TT_2D: return "2D"; - case Iff::TT_Rect: return "Rect"; - case Iff::TT_3D: return "3D"; - case Iff::TT_CubeMap: return "Cube"; - default: break; +static string TargetSuffix( Iff::TextureTargetBitfield ttb ) +{ + switch( ttb ) + { + case Iff::TT_1D: + return "1D"; + case Iff::TT_2D: + return "2D"; + case Iff::TT_Rect: + return "Rect"; + case Iff::TT_3D: + return "3D"; + case Iff::TT_CubeMap: + return "Cube"; + default: + break; } return ""; } -static string TextureFetch( bool es, bool legacy, Iff::TextureTargetBitfield b ) { - if( es || legacy ) { - switch( b ) { - case Iff::TT_1D: return "texture1D"; - case Iff::TT_2D: return "texture2D"; - case Iff::TT_CubeMap: return "textureCube"; - default: break; +static string TextureFetch( bool es, bool legacy, Iff::TextureTargetBitfield b ) +{ + if ( es || legacy ) + { + switch( b ) + { + case Iff::TT_1D: + return "texture1D"; + case Iff::TT_2D: + return "texture2D"; + case Iff::TT_CubeMap: + return "textureCube"; + default: + break; } } return "texture"; } -static string TextureFetchSwizzle( bool es, bool legacy, Iff::TextureTargetBitfield b ) { - if( es || legacy ) { - switch( b ) { - case Iff::TT_1D: return ".x"; - case Iff::TT_2D: return ".xy"; - case Iff::TT_Rect: return ".xy"; - case Iff::TT_3D: return ".xyz"; - case Iff::TT_CubeMap: return ".xyz"; - default: break; +static string TextureFetchSwizzle( bool es, bool legacy, Iff::TextureTargetBitfield b ) +{ + if ( es || legacy ) + { + switch( b ) + { + case Iff::TT_1D: + return ".x"; + case Iff::TT_2D: + return ".xy"; + case Iff::TT_Rect: + return ".xy"; + case Iff::TT_3D: + return ".xyz"; + case Iff::TT_CubeMap: + return ".xyz"; + default: + break; } return ""; } - switch( b ) { - case Iff::TT_1D: return ".x"; - case Iff::TT_2D: return ".xy"; - case Iff::TT_Rect: return ".xy"; - case Iff::TT_3D: return ".xyz"; - case Iff::TT_CubeMap: return ".xyz"; - default: break; + switch( b ) + { + case Iff::TT_1D: + return ".x"; + case Iff::TT_2D: + return ".xy"; + case Iff::TT_Rect: + return ".xy"; + case Iff::TT_3D: + return ".xyz"; + case Iff::TT_CubeMap: + return ".xyz"; + default: + break; } return ""; } @@ -920,108 +1087,154 @@ static void GenerateFragmentShaderSource( Iff * rff, string_list &src ) Internal("Regal::Iff::GenerateFragmentShaderSource", boost::print::optional(rff,Logging::pointers)); const Store & st = rff->ffstate.processed; - if( rff->gles ) { + if ( rff->gles ) + { #if REGAL_FORCE_DESKTOP_GLSL src << "#version 140\n"; #else src << "#version 100\n"; #endif - } else if( rff->legacy ) { + } + else if( rff->legacy ) + { src << "#version 120\n"; - } else { + } + else + { src << "#version 140\n"; } src << "// program number " << rff->progcount << "\n"; - if( rff->gles || rff->legacy ) { + if ( rff->gles || rff->legacy ) + { src << "#define in varying\n"; src << "#define rglFragColor gl_FragColor\n"; - } else { + } + else + { src << "out vec4 rglFragColor;\n"; } - if( st.shadeModelFlat && ! rff->legacy && ! rff->gles ) { + if ( st.shadeModelFlat && ! rff->legacy && ! rff->gles ) + { src << "#define FLAT flat\n"; - } else { + } + else + { src << "#define FLAT \n"; } - if( rff->gles ) { + if ( rff->gles ) + { src << "precision highp float;\n"; } src << "FLAT in vec4 rglFrontColor;\n"; - if( st.lighting ) { - if( st.lightModelTwoSide ) { + if ( st.lighting ) + { + if ( st.lightModelTwoSide ) + { src << "FLAT in vec4 rglBackColor;\n"; } - if( st.lightModelSeparateSpecular ) { + if ( st.lightModelSeparateSpecular ) + { src << "in vec4 rglSCOL0;\n"; - if( st.lightModelTwoSide ) { + if ( st.lightModelTwoSide ) + { src << "in vec4 rglSCOL1;\n"; } } - } else if( st.colorSum ) { + } + else if( st.colorSum ) + { src << "in vec4 rglSCOL0;\n"; } - if( st.fog.enable ) { + if ( st.fog.enable ) + { src << "uniform vec4 rglFog[2];\n"; src << "in vec4 rglFOG;\n"; } bool needsConstantColor = false; - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { + size_t n = array_size( rff->ffstate.processed.tex ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( rff->ffstate.processed.tex, i ); Texture t = rff->ffstate.processed.tex[i]; - if( t.enables == 0 ) { + if ( t.enables == 0 ) + { continue; } - src << "uniform sampler" << TargetSuffix( t.enables ) << " rglSampler" << i << ";\n"; + src << "uniform sampler" << TargetSuffix( static_cast(t.enables) ) << " rglSampler" << i << ";\n"; src << "in vec4 rglTEXCOORD" << i << ";\n"; Iff::TextureEnv & env = t.unit.env; - if( env.mode == Iff::TEM_Combine ) { + if ( env.mode == Iff::TEM_Combine ) + { needsConstantColor = - env.rgb.src0 == Iff::TCS_Constant || - env.rgb.src1 == Iff::TCS_Constant || - env.rgb.src2 == Iff::TCS_Constant ; + env.rgb.src0 == Iff::TCS_Constant || + env.rgb.src1 == Iff::TCS_Constant || + env.rgb.src2 == Iff::TCS_Constant ; } - if( env.mode == Iff::TEM_Blend ) { + if ( env.mode == Iff::TEM_Blend ) + { src << "uniform vec4 rglTexEnvColor" << i << ";\n"; } } - if( needsConstantColor ) { + if ( needsConstantColor ) + { src << "uniform vec4 rglConstantColor;\n"; } - for( int i = 0; i < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES; i++ ) { - if( ( rff->gles || rff->legacy ) && st.clip[i].enable ) { + n = array_size( st.clipPlaneEnabled ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.clipPlaneEnabled, i ); + if ( ( rff->gles || rff->legacy ) && st.clipPlaneEnabled[i] ) + { src << "in float rglClipDistance" << i << ";\n"; } } - if( st.alphaTest.enable ) { - if (st.alphaTest.comp != Iff::CF_Never && st.alphaTest.comp != Iff::CF_Always ) { + if ( st.alphaTest.enable ) + { + if (st.alphaTest.comp != Iff::CF_Never && st.alphaTest.comp != Iff::CF_Always ) + { src << "uniform float rglAlphaRef;\n"; } } src << "void main() {\n"; - if( rff->gles || rff->legacy ) { - for( int i = 0; i < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES; i++ ) { - if( st.clip[i].enable ) { + if ( rff->gles || rff->legacy ) + { + n = array_size( st.clipPlaneEnabled ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( st.clipPlaneEnabled, i ); + if ( st.clipPlaneEnabled[i] ) + { src << " if( rglClipDistance" << i << " < 0.0 ) discard;\n"; } } } - if( st.lighting && st.lightModelTwoSide ) { + if ( st.lighting && st.lightModelTwoSide ) + { src << " vec4 p = gl_FrontFacing ? rglFrontColor : rglBackColor;\n"; - } else { + } + else + { src << " vec4 p = rglFrontColor;\n"; } bool s_declared = false; - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { + n = array_size( rff->ffstate.processed.tex ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( rff->ffstate.processed.tex, i ); Texture t = rff->ffstate.processed.tex[ i ]; Iff::TextureTargetBitfield b = rff->ffstate.GetTextureEnable( i ); - if( b == 0 ) { + if ( b == 0 ) + { continue; } - if ( !s_declared ) { + if ( !s_declared ) + { src << " vec4 s;\n"; s_declared = true; } - switch( b ) { + switch( b ) + { case Iff::TT_1D: case Iff::TT_2D: { @@ -1042,7 +1255,8 @@ static void GenerateFragmentShaderSource( Iff * rff, string_list &src ) src << " s = vec4( 0.0f, 0.0f, 0.0f, 0.0f );\n"; break; } - switch( t.unit.env.mode ) { + switch( t.unit.env.mode ) + { case Iff::TEM_Replace: case Iff::TEM_Modulate: case Iff::TEM_Add: @@ -1059,20 +1273,29 @@ static void GenerateFragmentShaderSource( Iff * rff, string_list &src ) } } src << " rglFragColor = p;\n"; - if( st.lighting ) { - if( st.lightModelSeparateSpecular ) { - if( st.lightModelTwoSide ) { + if ( st.lighting ) + { + if ( st.lightModelSeparateSpecular ) + { + if ( st.lightModelTwoSide ) + { src << " rglFragColor += gl_FrontFacing ? rglSCOL0 : rglSCOL1;\n"; - } else { + } + else + { src << " rglFragColor += rglSCOL0;\n"; } } - } else if( st.colorSum ) { + } + else if( st.colorSum ) + { src << " rglFragColor.xyz += rglSCOL0.xyz;\n"; } - if( st.fog.enable ) { + if ( st.fog.enable ) + { src << " float f = abs( -rglFOG.z / rglFOG.w );\n"; - switch( st.fog.mode ) { + switch( st.fog.mode ) + { case Iff::FG_Linear: src << " float fogFactor = ( rglFog[0].z - f ) / ( rglFog[0].z - rglFog[0].y );\n"; break; @@ -1090,73 +1313,131 @@ static void GenerateFragmentShaderSource( Iff * rff, string_list &src ) src << " fogFactor = clamp( fogFactor, 0.0, 1.0 );\n"; src << " rglFragColor.xyz = mix( rglFog[1].xyz, rglFragColor.xyz, fogFactor );\n"; } - if( st.alphaTest.enable ) { - switch( st.alphaTest.comp ) { - case Iff::CF_Never: src << " discard;\n"; break; - case Iff::CF_Less: src << " if( rglFragColor.w >= rglAlphaRef ) discard;\n"; break; - case Iff::CF_Greater: src << " if( rglFragColor.w <= rglAlphaRef ) discard;\n"; break; - case Iff::CF_Lequal: src << " if( rglFragColor.w > rglAlphaRef ) discard;\n"; break; - case Iff::CF_Gequal: src << " if( rglFragColor.w < rglAlphaRef ) discard;\n"; break; - case Iff::CF_Equal: src << " if( rglFragColor.w != rglAlphaRef ) discard;\n"; break; - case Iff::CF_NotEqual: src << " if( rglFragColor.w == rglAlphaRef ) discard;\n"; break; - case Iff::CF_Always: break; - default: src << "//ERROR: Unsupported alpha comp func\n"; break; + if ( st.alphaTest.enable ) + { + switch( st.alphaTest.comp ) + { + case Iff::CF_Never: + src << " discard;\n"; + break; + case Iff::CF_Less: + src << " if( rglFragColor.w >= rglAlphaRef ) discard;\n"; + break; + case Iff::CF_Greater: + src << " if( rglFragColor.w <= rglAlphaRef ) discard;\n"; + break; + case Iff::CF_Lequal: + src << " if( rglFragColor.w > rglAlphaRef ) discard;\n"; + break; + case Iff::CF_Gequal: + src << " if( rglFragColor.w < rglAlphaRef ) discard;\n"; + break; + case Iff::CF_Equal: + src << " if( rglFragColor.w != rglAlphaRef ) discard;\n"; + break; + case Iff::CF_NotEqual: + src << " if( rglFragColor.w == rglAlphaRef ) discard;\n"; + break; + case Iff::CF_Always: + break; + default: + src << "//ERROR: Unsupported alpha comp func\n"; + break; } } src << "}\n"; } -static void Copy( Float4 & dst, const GLfloat * src ) { - dst.x = src[0]; dst.y = src[1]; dst.z = src[2]; dst.w = src[3]; +static void Copy( Float4 & dst, const GLfloat * src ) +{ + dst.x = src[0]; + dst.y = src[1]; + dst.z = src[2]; + dst.w = src[3]; } -static void Copy( GLfloat * dst, Float4 & src ) { - dst[0] = src.x; dst[1] = src.y; dst[2] = src.z; dst[3] = src.w; +static void Copy( GLfloat * dst, Float4 & src ) +{ + dst[0] = src.x; + dst[1] = src.y; + dst[2] = src.z; + dst[3] = src.w; } -static void Transform( Float4 & dst, const r3::Matrix4f & m, const GLfloat * src ) { +static void Transform( Float4 & dst, const r3::Matrix4f & m, const GLfloat * src ) +{ r3::Vec4f v( src ); m.MultMatrixVec( v ); - dst.x = v.x; dst.y = v.y; dst.z = v.z; dst.w = v.w; + dst.x = v.x; + dst.y = v.y; + dst.z = v.z; + dst.w = v.w; } // Not currently used #if 0 -void TransformDir( Float4 & dst, const r3::Matrix4f & m, const GLfloat * src ) { +void TransformDir( Float4 & dst, const r3::Matrix4f & m, const GLfloat * src ) +{ r3::Vec3f v( src ); m.MultMatrixDir( v ); v.Normalize(); - dst.x = v.x; dst.y = v.y; dst.z = v.z; + dst.x = v.x; + dst.y = v.y; + dst.z = v.z; } #endif -static r3::Matrix4f RescaleNormal( const r3::Matrix4f & m ) { +static r3::Matrix4f RescaleNormal( const r3::Matrix4f & m ) +{ r3::Matrix4f r = m; - for( int i = 0; i < 3; i++ ) { + for ( int i = 0; i < 3; i++ ) + { r3::Vec3f v( r( i, 0 ), r( i, 1 ), r( i, 2 ) ); v.Normalize(); - r( i, 0 ) = v.x; r( i, 1 ) = v.y; r( i, 2 ) = v.z; + r( i, 0 ) = v.x; + r( i, 1 ) = v.y; + r( i, 2 ) = v.z; } return r; } bool State::SetEnable( Iff * ffn, bool enable, GLenum cap ) { - Internal("Regal::State::SetEnable",enable," ",Token::GLenumToString(cap)); + Internal("Regal::Iff::State::SetEnable",enable," ",Token::GLenumToString(cap)); Iff::Version & ver = ffn->ver; int activeTex = ffn->activeTextureIndex; int shift; - switch( cap ) { - case GL_TEXTURE_1D: shift = TP_1D; break; - case GL_TEXTURE_2D: shift = TP_2D; break; - case GL_TEXTURE_RECTANGLE: shift = TP_Rect; break; - case GL_TEXTURE_3D: shift = TP_3D; break; - case GL_TEXTURE_CUBE_MAP: shift = TP_CubeMap; break; - case GL_COLOR_SUM: raw.ver = ver.Update(); raw.colorSum = enable; return true; - case GL_FOG: raw.ver = ver.Update(); raw.fog.enable = enable; return true; - case GL_LIGHTING: raw.ver = ver.Update(); raw.lighting = enable; return true; + switch( cap ) + { + case GL_TEXTURE_1D: + shift = TP_1D; + break; + case GL_TEXTURE_2D: + shift = TP_2D; + break; + case GL_TEXTURE_RECTANGLE: + shift = TP_Rect; + break; + case GL_TEXTURE_3D: + shift = TP_3D; + break; + case GL_TEXTURE_CUBE_MAP: + shift = TP_CubeMap; + break; + case GL_COLOR_SUM: + raw.ver = ver.Update(); + raw.colorSum = enable; + return true; + case GL_FOG: + raw.ver = ver.Update(); + raw.fog.enable = enable; + return true; + case GL_LIGHTING: + raw.ver = ver.Update(); + raw.lighting = enable; + return true; case GL_LIGHT0: case GL_LIGHT1: case GL_LIGHT2: @@ -1164,16 +1445,32 @@ bool State::SetEnable( Iff * ffn, bool enable, GLenum cap ) case GL_LIGHT4: case GL_LIGHT5: case GL_LIGHT6: - case GL_LIGHT7: raw.ver = ver.Update(); raw.light[ cap - GL_LIGHT0 ].enable = enable; return true; - case GL_COLOR_MATERIAL: raw.ver = ver.Update(); raw.colorMaterial = enable; return true; - case GL_RESCALE_NORMAL: raw.ver = ver.Update(); raw.rescaleNormal = enable; return true; - case GL_NORMALIZE: raw.ver = ver.Update(); raw.normalize = enable; return true; + case GL_LIGHT7: + raw.ver = ver.Update(); + RegalAssertArrayIndex( raw.light, cap - GL_LIGHT0 ); + raw.light[ cap - GL_LIGHT0 ].enable = enable; + return true; + case GL_COLOR_MATERIAL: + raw.ver = ver.Update(); + raw.colorMaterial = enable; + return true; + case GL_RESCALE_NORMAL: + raw.ver = ver.Update(); + raw.rescaleNormal = enable; + return true; + case GL_NORMALIZE: + raw.ver = ver.Update(); + raw.normalize = enable; + return true; case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_T: case GL_TEXTURE_GEN_R: - case GL_TEXTURE_GEN_Q: { + case GL_TEXTURE_GEN_Q: + { raw.ver = ver.Update(); int idx = cap - GL_TEXTURE_GEN_S; + RegalAssertArrayIndex( raw.tex, ffn->activeTextureIndex ); + RegalAssertArrayIndex( raw.tex[ ffn->activeTextureIndex ].texgen, idx ); raw.tex[ ffn->activeTextureIndex ].texgen[ idx ].enable = enable; return true; } @@ -1186,46 +1483,65 @@ bool State::SetEnable( Iff * ffn, bool enable, GLenum cap ) case GL_CLIP_PLANE0+6: case GL_CLIP_PLANE0+7: raw.ver = ver.Update(); - raw.clip[ cap - GL_CLIP_PLANE0 ].enable = enable; + RegalAssertArrayIndex( raw.clipPlaneEnabled, cap - GL_CLIP_PLANE0 ); + raw.clipPlaneEnabled[ cap - GL_CLIP_PLANE0 ] = enable; return false; - case GL_ALPHA_TEST: raw.ver = ver.Update(); raw.alphaTest.enable = enable; return true; + case GL_ALPHA_TEST: + raw.ver = ver.Update(); + raw.alphaTest.enable = enable; + return true; default: return false; } - if( activeTex >= REGAL_EMU_IFF_TEXTURE_UNITS ) { - Warning( "Active texture index is too large: ", activeTex, " >= ", REGAL_EMU_IFF_TEXTURE_UNITS ); + if ( activeTex >= REGAL_EMU_MAX_TEXTURE_UNITS ) + { + Warning( "Active texture index is too large: ", activeTex, " >= ", REGAL_EMU_MAX_TEXTURE_UNITS ); return true; } + RegalAssertArrayIndex( raw.tex, activeTex ); Texture & t = raw.tex[ activeTex ]; GLuint v = 1 << shift; - if( enable ) { + if ( enable ) + { t.enables |= v; - } else { + } + else + { t.enables &= ~v; } - Internal("Regal::State::SetEnable","activeTex=",activeTex," enables=",t.enables); + Internal("Regal::Iff::State::SetEnable","activeTex=",activeTex," enables=",t.enables); raw.ver = ver.Update(); return true; } void State::SetLight( Iff * ffn, GLenum light, GLenum pname, const GLfloat * params ) { - Internal("Regal::State::SetLight",light,Token::GLenumToString(pname)); + Internal("Regal::Iff::State::SetLight",light,Token::GLenumToString(pname)); Iff::Version & ver = ffn->ver; int idx = light - GL_LIGHT0; - if( idx < 0 || idx >= REGAL_FIXED_FUNCTION_MAX_LIGHTS ) { + if ( idx < 0 || idx >= REGAL_FIXED_FUNCTION_MAX_LIGHTS ) + { return; } + RegalAssertArrayIndex( uniform.light, idx ); State::LightUniform & lu = uniform.light[ idx ]; - switch( pname ) { - case GL_AMBIENT: Copy( lu.ambient, params ); break; - case GL_DIFFUSE: Copy( lu.diffuse, params ); break; - case GL_SPECULAR: Copy( lu.specular, params ); break; + switch( pname ) + { + case GL_AMBIENT: + Copy( lu.ambient, params ); + break; + case GL_DIFFUSE: + Copy( lu.diffuse, params ); + break; + case GL_SPECULAR: + Copy( lu.specular, params ); + break; case GL_POSITION: { Transform( lu.position, ffn->modelview.Top(), params ); - if (lu.position.w == 0.0) { + if (lu.position.w == 0.0) + { lu.position.w = 1.0f/sqrtf(lu.position.x * lu.position.x + lu.position.y * lu.position.y + lu.position.z * lu.position.z); @@ -1233,12 +1549,16 @@ void State::SetLight( Iff * ffn, GLenum light, GLenum pname, const GLfloat * par lu.position.y *= lu.position.w; lu.position.z *= lu.position.w; lu.position.w = 0.0; + RegalAssertArrayIndex( raw.light, idx ); raw.light[ idx ].local = false; - } else { + } + else + { lu.position.x /= lu.position.w; lu.position.y /= lu.position.w; lu.position.z /= lu.position.w; lu.position.w = 1.0; + RegalAssertArrayIndex( raw.light, idx ); raw.light[ idx ].local = true; } break; @@ -1255,19 +1575,31 @@ void State::SetLight( Iff * ffn, GLenum light, GLenum pname, const GLfloat * par lu.spotDirection.y = y * d; lu.spotDirection.z = z * d; } - break; + break; - case GL_SPOT_EXPONENT: lu.attenuation.w = params[0]; break; - case GL_SPOT_CUTOFF: lu.spotDirection.w = params[0]; break; - case GL_CONSTANT_ATTENUATION: lu.attenuation.x = params[0]; break; - case GL_LINEAR_ATTENUATION: lu.attenuation.y = params[0]; break; - case GL_QUADRATIC_ATTENUATION: lu.attenuation.z = params[0]; break; - default: return; + case GL_SPOT_EXPONENT: + lu.attenuation.w = params[0]; + break; + case GL_SPOT_CUTOFF: + lu.spotDirection.w = params[0]; + break; + case GL_CONSTANT_ATTENUATION: + lu.attenuation.x = params[0]; + break; + case GL_LINEAR_ATTENUATION: + lu.attenuation.y = params[0]; + break; + case GL_QUADRATIC_ATTENUATION: + lu.attenuation.z = params[0]; + break; + default: + return; } // some raw state is derived from uniform state bool updateRawVersion = false; - switch( pname ) { + switch( pname ) + { case GL_POSITION: case GL_SPOT_CUTOFF: case GL_CONSTANT_ATTENUATION: @@ -1279,29 +1611,48 @@ void State::SetLight( Iff * ffn, GLenum light, GLenum pname, const GLfloat * par break; } lu.ver = uniform.ver = ver.Update(); - if( updateRawVersion ) { + if ( updateRawVersion ) + { raw.ver = uniform.ver; } } void State::SetMaterial( Iff * ffn, GLenum face, GLenum pname, const GLfloat * params ) { - Internal("Regal::State::SetMaterial",face,Token::GLenumToString(pname)); + Internal("Regal::Iff::State::SetMaterial",face,Token::GLenumToString(pname)); Iff::Version & ver = ffn->ver; - for( int i = 0; i < 2; i++ ) { - if( ( i == 0 && face == GL_BACK ) || ( i == 1 && face == GL_FRONT ) ) { + for ( int i = 0; i < 2; i++ ) + { + if ( ( i == 0 && face == GL_BACK ) || ( i == 1 && face == GL_FRONT ) ) + { continue; } + RegalAssertArrayIndex( uniform.mat, i ); State::MaterialUniform & m = uniform.mat[ i ]; - switch( pname ) { - case GL_AMBIENT: Copy( m.ambient, params ); break; - case GL_DIFFUSE: Copy( m.diffuse, params ); break; - case GL_AMBIENT_AND_DIFFUSE: Copy( m.ambient, params ); m.diffuse = m.ambient; break; - case GL_SPECULAR: Copy( m.specular, params ); break; - case GL_EMISSION: Copy( m.emission, params ); break; - case GL_SHININESS: m.shininess.x = params[0]; break; - default: return; + switch( pname ) + { + case GL_AMBIENT: + Copy( m.ambient, params ); + break; + case GL_DIFFUSE: + Copy( m.diffuse, params ); + break; + case GL_AMBIENT_AND_DIFFUSE: + Copy( m.ambient, params ); + m.diffuse = m.ambient; + break; + case GL_SPECULAR: + Copy( m.specular, params ); + break; + case GL_EMISSION: + Copy( m.emission, params ); + break; + case GL_SHININESS: + m.shininess.x = params[0]; + break; + default: + return; } m.ver = uniform.ver = ver.Update(); } @@ -1309,47 +1660,75 @@ void State::SetMaterial( Iff * ffn, GLenum face, GLenum pname, const GLfloat * p void State::GetMaterial( Iff * ffn, GLenum face, GLenum pname, GLfloat * params ) { - Internal("Regal::State::GetMaterial",face,Token::GLenumToString(pname)); + Internal("Regal::Iff::State::GetMaterial",face,Token::GLenumToString(pname)); UNUSED_PARAMETER(ffn); - for( int i = 0; i < 2; i++ ) { - if( ( i == 0 && face == GL_BACK ) || ( i == 1 && face == GL_FRONT ) ) { + for ( int i = 0; i < 2; i++ ) + { + if ( ( i == 0 && face == GL_BACK ) || ( i == 1 && face == GL_FRONT ) ) + { continue; } + RegalAssertArrayIndex( uniform.mat, i ); State::MaterialUniform & m = uniform.mat[ i ]; - switch( pname ) { - case GL_AMBIENT: Copy( params, m.ambient ); break; - case GL_DIFFUSE: Copy( params, m.diffuse ); break; - case GL_SPECULAR: Copy( params, m.specular ); break; - case GL_EMISSION: Copy( params, m.emission ); break; - case GL_SHININESS: params[0] = m.shininess.x; break; - default: return; + switch( pname ) + { + case GL_AMBIENT: + Copy( params, m.ambient ); + break; + case GL_DIFFUSE: + Copy( params, m.diffuse ); + break; + case GL_SPECULAR: + Copy( params, m.specular ); + break; + case GL_EMISSION: + Copy( params, m.emission ); + break; + case GL_SHININESS: + params[0] = m.shininess.x; + break; + default: + return; } } } void State::SetTexgen( Iff * ffn, int coord, GLenum space, const GLfloat * params ) { - Internal("State::SetTexgen ",ffn,coord,toString(space),boost::print::array(params,4)); + Internal("Regal::Iff::State::SetTexgen",ffn,coord,toString(space),boost::print::array(params,4)); r3::Matrix4f ident; + RegalAssertArrayIndex( uniform.tex, ffn->activeTextureIndex ); + RegalAssertArrayIndex( uniform.tex[ ffn->activeTextureIndex ].texgen, coord ); TexgenUniform & tgu = uniform.tex[ ffn->activeTextureIndex ].texgen[ coord ]; GLuint64 *tguver = NULL; - switch( space ) { - case GL_OBJECT_PLANE: Transform( tgu.obj, ident, params ); tguver = & tgu.objVer; break; - case GL_EYE_PLANE: Transform( tgu.eye, ffn->modelview.Top().Inverse().Transpose(), params ); tguver = & tgu.eyeVer; break; - default: return; + switch( space ) + { + case GL_OBJECT_PLANE: + Transform( tgu.obj, ident, params ); + tguver = & tgu.objVer; + break; + case GL_EYE_PLANE: + Transform( tgu.eye, ffn->modelview.Top().Inverse().Transpose(), params ); + tguver = & tgu.eyeVer; + break; + default: + return; } *tguver = uniform.ver = ffn->ver.Update(); } void State::GetTexgen( Iff * ffn, int coord, GLenum space, GLfloat * params ) { - Internal("State::GetTexgen ", boost::print::optional(ffn,Logging::pointers)," ",coord," ",toString(space)); + Internal("Regal::Iff::State::GetTexgen", boost::print::optional(ffn,Logging::pointers)," ",coord," ",toString(space)); + RegalAssertArrayIndex( uniform.tex, ffn->activeTextureIndex ); + RegalAssertArrayIndex( uniform.tex[ ffn->activeTextureIndex ].texgen, coord ); TexgenUniform & tgu = uniform.tex[ ffn->activeTextureIndex ].texgen[ coord ]; - switch( space ) { + switch( space ) + { case GL_OBJECT_PLANE: params[0] = tgu.obj.x; params[1] = tgu.obj.y; @@ -1377,16 +1756,18 @@ void State::SetAlphaFunc( Iff * ffn, Iff::CompareFunc comp, GLfloat alphaRef ) void State::SetClip( Iff * ffn, GLenum plane, const GLfloat * equation ) { int idx = plane - GL_CLIP_PLANE0; - if( idx >= REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES ) { + if ( idx >= REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES ) + { return; } + RegalAssertArrayIndex( uniform.clip, idx ); Transform( uniform.clip[ idx ].plane, ffn->modelview.Top().Inverse().Transpose(), equation ); uniform.clip[ idx ].ver = uniform.ver = ffn->ver.Update(); } void Program::Init( RegalContext * ctx, const Store & sstore, const GLchar *vsSrc, const GLchar *fsSrc ) { - Internal("Regal::Program::Init","()"); + Internal("Regal::Iff::Program::Init","()"); ver = ::std::numeric_limits::max(); progcount = 0; @@ -1399,7 +1780,7 @@ void Program::Init( RegalContext * ctx, const Store & sstore, const GLchar *vsSr Attribs( ctx ); tbl.call(&tbl.glLinkProgram)( pg ); - #ifndef NDEBUG +#ifndef NDEBUG GLint status = 0; tbl.call(&tbl.glGetProgramiv)( pg, GL_LINK_STATUS, &status ); if (!status) @@ -1408,7 +1789,7 @@ void Program::Init( RegalContext * ctx, const Store & sstore, const GLchar *vsSr if (helper::getInfoLog(log,tbl.call(&tbl.glGetProgramInfoLog),tbl.call(&tbl.glGetProgramiv),pg)) Warning( "Regal::Program::Init", log); } - #endif +#endif tbl.call(&tbl.glUseProgram)( pg ); Samplers( ctx, tbl ); @@ -1418,7 +1799,7 @@ void Program::Init( RegalContext * ctx, const Store & sstore, const GLchar *vsSr void Program::Shader( RegalContext * ctx, DispatchTableGL & tbl, GLenum type, GLuint & shader, const GLchar *src ) { - Internal("Regal::Program::Shader","()"); + Internal("Regal::Iff::Program::Shader","()"); UNUSED_PARAMETER(ctx); @@ -1429,7 +1810,7 @@ void Program::Shader( RegalContext * ctx, DispatchTableGL & tbl, GLenum type, GL tbl.call(&tbl.glShaderSource)( shader, 1, srcs, len ); tbl.call(&tbl.glCompileShader)( shader ); - #ifndef NDEBUG +#ifndef NDEBUG GLint status = 0; tbl.call(&tbl.glGetShaderiv)( shader, GL_COMPILE_STATUS, &status ); if (!status) @@ -1438,35 +1819,48 @@ void Program::Shader( RegalContext * ctx, DispatchTableGL & tbl, GLenum type, GL if (helper::getInfoLog(log,tbl.call(&tbl.glGetShaderInfoLog),tbl.call(&tbl.glGetShaderiv),shader)) Warning("Regal::Program::Shader", log); } - #endif +#endif tbl.call(&tbl.glAttachShader)( pg, shader ); } void Program::Attribs( RegalContext * ctx ) { - Internal("Regal::Program::Attribs","()"); + Internal("Regal::Iff::Program::Attribs","()"); DispatchTableGL & tbl = ctx->dispatcher.emulation; + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_Vertex ); tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_Vertex ], "rglVertex" ); //tbl.call(&tbl.glBindAttribLocation)( pg, 1, "rglWeight" ); - if( store.lighting ) { + if ( store.lighting ) + { + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_Normal ); tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_Normal ], "rglNormal" ); } - if( store.attrArrayFlags & ( 1 << ctx->iff->ffAttrMap[ RFF2A_Color ] ) && ( store.lighting == false || store.colorMaterial ) ) { + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_Color ); + if ( store.attrArrayFlags & ( 1 << ctx->iff->ffAttrMap[ RFF2A_Color ] ) && ( store.lighting == false || store.colorMaterial ) ) + { + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_Color ); tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_Color ], "rglColor" ); } - if( store.colorSum && store.lighting == false ) { + if ( store.colorSum && store.lighting == false ) + { + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_SecondaryColor ); tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_SecondaryColor ], "rglSecondaryColor" ); } - if( store.fog.enable && store.fog.useDepth == false ) { + if ( store.fog.enable && store.fog.useDepth == false ) + { + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_FogCoord ); tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_FogCoord ], "rglFogCoord" ); } - GLuint units = std::min( (GLuint)ctx->iff->ffAttrNumTex, (GLuint)REGAL_EMU_IFF_TEXTURE_UNITS ); - for( GLuint i = 0; i < units; i++ ) { + GLuint units = std::min( (GLuint)ctx->iff->ffAttrNumTex, (GLuint)REGAL_EMU_MAX_TEXTURE_UNITS ); + for ( GLuint i = 0; i < units; i++ ) + { #ifndef REGAL_HACK_SET_001 - if( store.tex[i].enables == 0 ) { + RegalAssertArrayIndex( store.tex, i ); + if ( store.tex[i].enables == 0 ) + { continue; } #endif @@ -1479,20 +1873,30 @@ void Program::Attribs( RegalContext * ctx ) // seth: for user program mode just do all the bind attribs, aliasing is OK in GL void Program::UserShaderModeAttribs( RegalContext * ctx ) { - Internal("Regal::Program::UserShaderModeAttribs","()"); + Internal("Regal::Iff::Program::UserShaderModeAttribs","()"); DispatchTableGL & tbl = ctx->dispatcher.emulation; + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_Vertex ); + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_Normal ); + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_Color ); + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_SecondaryColor ); + RegalAssertArrayIndex( ctx->iff->ffAttrMap, RFF2A_FogCoord ); + tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_Vertex ], "rglVertex" ); tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_Normal ], "rglNormal" ); tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_Color ], "rglColor" ); - if ( ctx->iff->ffAttrMap[ RFF2A_SecondaryColor ] != RFF2A_Invalid ) { + if ( ctx->iff->ffAttrMap[ RFF2A_SecondaryColor ] != RFF2A_Invalid ) + { tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_SecondaryColor ], "rglSecondaryColor" ); } tbl.call(&tbl.glBindAttribLocation)( pg, ctx->iff->ffAttrMap[ RFF2A_FogCoord ], "rglFogCoord" ); - GLuint units = std::min( /*(GLuint)ctx->iff->ffAttrNumTex*/(GLuint)16, (GLuint)REGAL_EMU_IFF_TEXTURE_UNITS ); - for( GLuint i = 0; i < units; i++ ) { - if( store.tex[i].enables == 0 ) { + GLuint units = std::min( /*(GLuint)ctx->iff->ffAttrNumTex*/(GLuint)16, (GLuint)REGAL_EMU_MAX_TEXTURE_UNITS ); + for ( GLuint i = 0; i < units; i++ ) + { + RegalAssertArrayIndex( store.tex, i ); + if ( store.tex[i].enables == 0 ) + { continue; } string_list ss; @@ -1504,33 +1908,33 @@ void Program::UserShaderModeAttribs( RegalContext * ctx ) void Program::Samplers( RegalContext * ctx, DispatchTableGL & tbl ) { - Internal("Regal::Program::Samplers","()"); + Internal("Regal::Iff::Program::Samplers","()"); UNUSED_PARAMETER(ctx); - GLchar samp[64]; - strcpy( samp, "rglSamplerN" ); - int len = (int)strlen( samp ); - for( GLchar i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { - samp[ len - 1 ] = '0' + i; - GLint slot = tbl.call(&tbl.glGetUniformLocation)( pg, samp ); - if( slot >= 0 ) { - tbl.call(&tbl.glUniform1i)( slot, i ); - } + for ( GLint ii = 0; ii < REGAL_EMU_MAX_TEXTURE_UNITS; ii++ ) + { + std::string samplerName = boost::print::print_string("rglSampler",ii); + GLint slot = tbl.call(&tbl.glGetUniformLocation)( pg, samplerName.c_str() ); + if ( slot >= 0 ) + tbl.call(&tbl.glUniform1i)( slot, ii ); } } void Program::Uniforms( RegalContext * ctx, DispatchTableGL & tbl ) { - Internal("Regal::Program::Uniforms","()"); + Internal("Regal::Iff::Program::Uniforms","()"); UNUSED_PARAMETER(ctx); - for( size_t i = 1; i < sizeof(regalFFUniformInfo)/sizeof(regalFFUniformInfo[0]); i++ ) { + size_t n = array_size( regalFFUniformInfo ); + for ( size_t i = 1; i < n; i++ ) + { + RegalAssertArrayIndex( regalFFUniformInfo, i ); const RegalFFUniformInfo & ri = regalFFUniformInfo[i]; GLint slot = tbl.call(&tbl.glGetUniformLocation)( pg, ri.name ); if (slot > -1) - uniforms[ ri.val ] = UniformInfo(slot,~GLuint64(0)); + uniforms[ ri.val ] = UniformInfo(~GLuint64(0), slot); } } @@ -1545,8 +1949,10 @@ void Iff::Cleanup( RegalContext &ctx ) tbl.call(&tbl.glDeleteBuffers)(1, &immQuadsVbo); tbl.call(&tbl.glDeleteVertexArrays)(1, &immVao); - for (int i = 0; i < (1 << REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE_BITS); ++i) + size_t n = array_size( ffprogs ); + for (size_t i = 0; i < n; ++i) { + RegalAssertArrayIndex( ffprogs, i ); const Program &pgm = ffprogs[i]; if (pgm.pg) { @@ -1565,7 +1971,7 @@ void Iff::Cleanup( RegalContext &ctx ) tbl.glBindBuffer(GL_ARRAY_BUFFER, 0); tbl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - for (GLuint i=0; imaxVertexAttribs; ++i) + for (GLuint i=0; igl_max_vertex_attribs; ++i) { // Chromium/PepperAPI GLES generates an error (visible through glGetError) // and logs a message if a call is made to glVertexAttribPointer and no @@ -1585,24 +1991,6 @@ void Iff::InitFixedFunction(RegalContext &ctx) gles = ctx.info->es2; legacy = ctx.info->compat && ctx.info->gl_version_major<=2; - shadowMatrixMode = GL_MODELVIEW; - currMatrixStack = &modelview; - program = 0; - activeTextureIndex = 0; - shadowActiveTextureIndex = 0; - - currprog = NULL; - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { - textureUnit[ i ] = TextureUnit(); - textureEnvColor[i] = Float4( 0.0f, 0.0f, 0.0f, 0.0f ); - textureEnvColorVer[i] = 0; - } - - for( int i = 0; i < REGAL_EMU_MAX_TEXTURE_UNITS; i++ ) { - textureBinding[ i ] = 0; - } - - currVao = 0; vaoAttrMap[0] = 0; fmtmap[ 1 ] = GL_LUMINANCE; @@ -1698,16 +2086,18 @@ void Iff::ShadowMultiTexBinding( GLenum texunit, GLenum target, GLuint obj ) { Internal("Regal::Iff::ShadowMultiTexBinding",toString(texunit)," ",toString(target)," ",obj); - activeTextureIndex = texunit - GL_TEXTURE0; - if( activeTextureIndex > ( REGAL_EMU_MAX_TEXTURE_UNITS - 1 ) ) { + if ( texunit - GL_TEXTURE0 > ( REGAL_EMU_MAX_TEXTURE_COORDS - 1 ) ) return; - } - // assert( textureInfo.count( obj ) == 0 || target == textureInfo[activeTextureIndex].target ); - GLint fmt = textureObjToFmt[ obj ]; + + activeTextureIndex = texunit - GL_TEXTURE0; + + GLenum fmt = textureObjToFmt[ obj ]; + RegalAssertArrayIndex( textureUnit, activeTextureIndex ); + RegalAssertArrayIndex( textureBinding, activeTextureIndex ); TextureUnit & tu = textureUnit[ activeTextureIndex ]; textureBinding[ activeTextureIndex ] = obj; tu.fmt = fmt; - tu.ttb = static_cast(TargetToBitfield( target )); + tu.ttb = TargetToBitfield( target ); ffstate.raw.ver = ver.Update(); } @@ -1717,25 +2107,35 @@ void Iff::ShadowTextureInfo( GLuint obj, GLenum target, GLint internalFormat ) UNUSED_PARAMETER(target); // assert( target == tip->tgt ); - if( fmtmap.count( internalFormat ) == 0 ) { + if ( fmtmap.count( internalFormat ) == 0 ) + { Warning( "Unknown internal format: ", GLenumToString(internalFormat) ); } - GLint fmt = fmtmap[ internalFormat ]; + GLenum fmt = fmtmap[ internalFormat ]; textureObjToFmt[ obj ] = fmt; ffstate.raw.ver = ver.Update(); } void Iff::ShadowMultiTexInfo( GLenum texunit, GLenum target, GLint internalFormat ) { - activeTextureIndex = texunit - GL_TEXTURE0; - ShadowTexInfo( target, internalFormat ); + if ( (texunit - GL_TEXTURE0) < REGAL_EMU_MAX_TEXTURE_COORDS) + { + activeTextureIndex = texunit - GL_TEXTURE0; + ShadowTexInfo( target, internalFormat ); + } + else + Warning( "Texture unit out of range: ", Token::GLtextureToString(texunit), " > ", Token::GLtextureToString(GL_TEXTURE0 + REGAL_EMU_MAX_TEXTURE_COORDS - 1)); } + void Iff::ShadowTexInfo( GLenum target, GLint internalFormat ) { - if( shadowActiveTextureIndex > ( REGAL_EMU_MAX_TEXTURE_UNITS - 1 ) ) { + if ( shadowActiveTextureIndex > ( REGAL_EMU_MAX_TEXTURE_UNITS - 1 ) ) + { return; } + RegalAssertArrayIndex( textureBinding, shadowActiveTextureIndex ); + RegalAssertArrayIndex( textureUnit, shadowActiveTextureIndex ); ShadowTextureInfo( textureBinding[ shadowActiveTextureIndex ], target, internalFormat ); textureUnit[ shadowActiveTextureIndex ].fmt = fmtmap[ internalFormat ]; } @@ -1743,10 +2143,16 @@ void Iff::ShadowTexInfo( GLenum target, GLint internalFormat ) void Iff::TexEnv( GLenum texunit, GLenum target, GLenum pname, const GLfloat *v ) { activeTextureIndex = texunit - GL_TEXTURE0; - switch( target ) { + switch( target ) + { case GL_TEXTURE_ENV: - switch( pname ) { - case GL_TEXTURE_ENV_COLOR: { + switch( pname ) + { + case GL_TEXTURE_ENV_COLOR: + { + RegalAssertArrayIndex( textureUnit, activeTextureIndex ); + RegalAssertArrayIndex( textureEnvColor, activeTextureIndex ); + RegalAssertArrayIndex( textureEnvColorVer, activeTextureIndex ); TextureUnit *tup = & textureUnit[ activeTextureIndex ]; Copy( textureEnvColor[ activeTextureIndex ], v ); ffstate.SetTexInfo( ver, activeTextureIndex, *tup ); @@ -1768,57 +2174,112 @@ void Iff::TexEnv( GLenum texunit, GLenum target, GLenum pname, const GLint *v ) Internal("Regal::Iff::TexEnv",GLenumToString(texunit)," ",GLenumToString(target)," ",GLenumToString(pname)); activeTextureIndex = texunit - GL_TEXTURE0; - switch( target ) { + switch( target ) + { case GL_TEXTURE_ENV: - switch( pname ) { - case GL_TEXTURE_ENV_MODE: { - if( activeTextureIndex >= REGAL_EMU_IFF_TEXTURE_UNITS ) { + switch( pname ) + { + case GL_TEXTURE_ENV_MODE: + { + if ( activeTextureIndex >= REGAL_EMU_MAX_TEXTURE_UNITS ) + { return; } + RegalAssertArrayIndex( textureUnit, activeTextureIndex ); TextureUnit *tup = & textureUnit[ activeTextureIndex ]; TexenvMode & m = tup->env.mode; - switch( v[0] ) { - case GL_REPLACE: m = TEM_Replace; break; - case GL_MODULATE: m = TEM_Modulate; break; - case GL_ADD: m = TEM_Add; break; - case GL_DECAL: m = TEM_Decal; break; - case GL_BLEND: m = TEM_Blend; break; - case GL_COMBINE: m = TEM_Combine; break; - default: return; // error? + switch( v[0] ) + { + case GL_REPLACE: + m = TEM_Replace; + break; + case GL_MODULATE: + m = TEM_Modulate; + break; + case GL_ADD: + m = TEM_Add; + break; + case GL_DECAL: + m = TEM_Decal; + break; + case GL_BLEND: + m = TEM_Blend; + break; + case GL_COMBINE: + m = TEM_Combine; + break; + default: + return; // error? } // assert( target == tip->tgt ); ffstate.SetTexInfo( ver, activeTextureIndex, *tup ); break; } - case GL_COMBINE_RGB: { + case GL_COMBINE_RGB: + { + RegalAssertArrayIndex( textureUnit, activeTextureIndex ); TextureUnit *tup = & textureUnit[ activeTextureIndex ]; TexenvCombineState & s = tup->env.rgb; - switch( v[0] ) { - case GL_REPLACE: s.mode = TEC_Replace; break; - case GL_MODULATE: s.mode = TEC_Modulate; break; - case GL_ADD: s.mode = TEC_Add; break; - case GL_ADD_SIGNED: s.mode = TEC_AddSigned; break; - case GL_SUBTRACT: s.mode = TEC_Subtract; break; - case GL_DOT3_RGB: s.mode = TEC_Dot3Rgb; break; - case GL_DOT3_RGBA: s.mode = TEC_Dot3Rgba; break; - case GL_INTERPOLATE: s.mode = TEC_Interpolate; break; - default: return; // error? + switch( v[0] ) + { + case GL_REPLACE: + s.mode = TEC_Replace; + break; + case GL_MODULATE: + s.mode = TEC_Modulate; + break; + case GL_ADD: + s.mode = TEC_Add; + break; + case GL_ADD_SIGNED: + s.mode = TEC_AddSigned; + break; + case GL_SUBTRACT: + s.mode = TEC_Subtract; + break; + case GL_DOT3_RGB: + s.mode = TEC_Dot3Rgb; + break; + case GL_DOT3_RGBA: + s.mode = TEC_Dot3Rgba; + break; + case GL_INTERPOLATE: + s.mode = TEC_Interpolate; + break; + default: + return; // error? } // assert( target == tip->tgt ); ffstate.SetTexInfo( ver, activeTextureIndex, *tup ); break; } - case GL_COMBINE_ALPHA: { + case GL_COMBINE_ALPHA: + { + RegalAssertArrayIndex( textureUnit, activeTextureIndex ); TextureUnit *tup = & textureUnit[ activeTextureIndex ]; TexenvCombineState & s = tup->env.a; - switch( v[0] ) { - case GL_REPLACE: s.mode = TEC_Replace; break; - case GL_MODULATE: s.mode = TEC_Modulate; break; - case GL_ADD: s.mode = TEC_Add; break; - case GL_ADD_SIGNED: s.mode = TEC_AddSigned; break; - case GL_SUBTRACT: s.mode = TEC_Subtract; break; - case GL_INTERPOLATE: s.mode = TEC_Interpolate; break; - default: return; // error? + switch( v[0] ) + { + case GL_REPLACE: + s.mode = TEC_Replace; + break; + case GL_MODULATE: + s.mode = TEC_Modulate; + break; + case GL_ADD: + s.mode = TEC_Add; + break; + case GL_ADD_SIGNED: + s.mode = TEC_AddSigned; + break; + case GL_SUBTRACT: + s.mode = TEC_Subtract; + break; + case GL_INTERPOLATE: + s.mode = TEC_Interpolate; + break; + default: + return; // error? } // assert( target == tip->tgt ); ffstate.SetTexInfo( ver, activeTextureIndex, *tup ); @@ -1829,38 +2290,76 @@ void Iff::TexEnv( GLenum texunit, GLenum target, GLenum pname, const GLint *v ) case GL_SRC2_RGB: case GL_SRC0_ALPHA: case GL_SRC1_ALPHA: - case GL_SRC2_ALPHA: { + case GL_SRC2_ALPHA: + { int idx = pname - GL_SRC0_RGB; bool isRgb = true; - if( idx > 3 ) { + if ( idx > 3 ) + { isRgb = false; idx = pname - GL_SRC0_ALPHA; } + RegalAssertArrayIndex( textureUnit, activeTextureIndex ); TextureUnit *tup = & textureUnit[ activeTextureIndex ]; TexenvCombineState & c = isRgb ? tup->env.rgb : tup->env.a; - if( idx == 0 ) { - switch( v[0] ) { - case GL_PREVIOUS: c.src0 = TCS_Previous; break; - case GL_CONSTANT: c.src0 = TCS_Constant; break; - case GL_TEXTURE: c.src0 = TCS_Texture; break; - case GL_PRIMARY_COLOR: c.src0 = TCS_PrimaryColor; break; - default: return; // error? + if ( idx == 0 ) + { + switch( v[0] ) + { + case GL_PREVIOUS: + c.src0 = TCS_Previous; + break; + case GL_CONSTANT: + c.src0 = TCS_Constant; + break; + case GL_TEXTURE: + c.src0 = TCS_Texture; + break; + case GL_PRIMARY_COLOR: + c.src0 = TCS_PrimaryColor; + break; + default: + return; // error? } - } else if( idx == 1 ) { - switch( v[0] ) { - case GL_PREVIOUS: c.src1 = TCS_Previous; break; - case GL_CONSTANT: c.src1 = TCS_Constant; break; - case GL_TEXTURE: c.src1 = TCS_Texture; break; - case GL_PRIMARY_COLOR: c.src1 = TCS_PrimaryColor; break; - default: return; // error? + } + else if( idx == 1 ) + { + switch( v[0] ) + { + case GL_PREVIOUS: + c.src1 = TCS_Previous; + break; + case GL_CONSTANT: + c.src1 = TCS_Constant; + break; + case GL_TEXTURE: + c.src1 = TCS_Texture; + break; + case GL_PRIMARY_COLOR: + c.src1 = TCS_PrimaryColor; + break; + default: + return; // error? } - } else if( idx == 2 ) { - switch( v[0] ) { - case GL_PREVIOUS: c.src2 = TCS_Previous; break; - case GL_CONSTANT: c.src2 = TCS_Constant; break; - case GL_TEXTURE: c.src2 = TCS_Texture; break; - case GL_PRIMARY_COLOR: c.src2 = TCS_PrimaryColor; break; - default: return; // error? + } + else if( idx == 2 ) + { + switch( v[0] ) + { + case GL_PREVIOUS: + c.src2 = TCS_Previous; + break; + case GL_CONSTANT: + c.src2 = TCS_Constant; + break; + case GL_TEXTURE: + c.src2 = TCS_Texture; + break; + case GL_PRIMARY_COLOR: + c.src2 = TCS_PrimaryColor; + break; + default: + return; // error? } } ffstate.SetTexInfo( ver, activeTextureIndex, *tup ); @@ -1871,38 +2370,76 @@ void Iff::TexEnv( GLenum texunit, GLenum target, GLenum pname, const GLint *v ) case GL_OPERAND2_RGB: case GL_OPERAND0_ALPHA: case GL_OPERAND1_ALPHA: - case GL_OPERAND2_ALPHA: { + case GL_OPERAND2_ALPHA: + { int idx = pname - GL_OPERAND0_RGB; bool isRgb = true; - if( idx > 3 ) { + if ( idx > 3 ) + { isRgb = false; idx = pname - GL_OPERAND0_ALPHA; } + RegalAssertArrayIndex( textureUnit, activeTextureIndex ); TextureUnit *tup = & textureUnit[ activeTextureIndex ]; TexenvCombineState & c = isRgb ? tup->env.rgb : tup->env.a; - if( idx == 0 ) { - switch( v[0] ) { - case GL_SRC_COLOR: c.op0 = TCO_Color; break; - case GL_SRC_ALPHA: c.op0 = TCO_Alpha; break; - case GL_ONE_MINUS_SRC_COLOR: c.op0 = TCO_OneMinusColor; break; - case GL_ONE_MINUS_SRC_ALPHA: c.op0 = TCO_OneMinusAlpha; break; - default: return; // error? + if ( idx == 0 ) + { + switch( v[0] ) + { + case GL_SRC_COLOR: + c.op0 = TCO_Color; + break; + case GL_SRC_ALPHA: + c.op0 = TCO_Alpha; + break; + case GL_ONE_MINUS_SRC_COLOR: + c.op0 = TCO_OneMinusColor; + break; + case GL_ONE_MINUS_SRC_ALPHA: + c.op0 = TCO_OneMinusAlpha; + break; + default: + return; // error? } - } else if( idx == 1 ) { - switch( v[0] ) { - case GL_SRC_COLOR: c.op1 = TCO_Color; break; - case GL_SRC_ALPHA: c.op1 = TCO_Alpha; break; - case GL_ONE_MINUS_SRC_COLOR: c.op1 = TCO_OneMinusColor; break; - case GL_ONE_MINUS_SRC_ALPHA: c.op1 = TCO_OneMinusAlpha; break; - default: return; // error? + } + else if( idx == 1 ) + { + switch( v[0] ) + { + case GL_SRC_COLOR: + c.op1 = TCO_Color; + break; + case GL_SRC_ALPHA: + c.op1 = TCO_Alpha; + break; + case GL_ONE_MINUS_SRC_COLOR: + c.op1 = TCO_OneMinusColor; + break; + case GL_ONE_MINUS_SRC_ALPHA: + c.op1 = TCO_OneMinusAlpha; + break; + default: + return; // error? } - } else if( idx == 2 ) { - switch( v[0] ) { - case GL_SRC_COLOR: c.op2 = TCO_Color; break; - case GL_SRC_ALPHA: c.op2 = TCO_Alpha; break; - case GL_ONE_MINUS_SRC_COLOR: c.op2 = TCO_OneMinusColor; break; - case GL_ONE_MINUS_SRC_ALPHA: c.op2 = TCO_OneMinusAlpha; break; - default: return; // error? + } + else if( idx == 2 ) + { + switch( v[0] ) + { + case GL_SRC_COLOR: + c.op2 = TCO_Color; + break; + case GL_SRC_ALPHA: + c.op2 = TCO_Alpha; + break; + case GL_ONE_MINUS_SRC_COLOR: + c.op2 = TCO_OneMinusColor; + break; + case GL_ONE_MINUS_SRC_ALPHA: + c.op2 = TCO_OneMinusAlpha; + break; + default: + return; // error? } } ffstate.SetTexInfo( ver, activeTextureIndex, *tup ); @@ -1911,12 +2448,14 @@ void Iff::TexEnv( GLenum texunit, GLenum target, GLenum pname, const GLint *v ) case GL_RGB_SCALE: case GL_ALPHA_SCALE: { + RegalAssertArrayIndex( textureUnit, activeTextureIndex ); TextureUnit *tup = & textureUnit[ activeTextureIndex ]; TexenvCombineState & c = (pname == GL_RGB_SCALE ? tup->env.rgb : tup->env.a); GLfloat pscale = static_cast(v[0]); - if (pscale != 1.0 && pscale != 2.0 && pscale != 4.0) { - Warning("Invalid value set for TexEnv Scale %f - must be 1.0, 2.0, or 4.0\n", pscale); - return; // error + if (pscale != 1.0 && pscale != 2.0 && pscale != 4.0) + { + Warning("Invalid value set for TexEnv Scale %f - must be 1.0, 2.0, or 4.0\n", pscale); + return; // error } c.scale = pscale; ffstate.SetTexInfo( ver, activeTextureIndex, *tup ); @@ -1931,27 +2470,24 @@ void Iff::TexEnv( GLenum texunit, GLenum target, GLenum pname, const GLint *v ) } } -inline size_t compute_hash(const Store &val) -{ - return Lookup3::hashlittle(reinterpret_cast(&val) + sizeof(GLuint), sizeof(Store)-sizeof(GLuint64)-sizeof(GLuint), 0); -} - void Iff::State::Process( Iff * ffn ) { - Internal("Regal::State::Process","()"); + Internal("Iff::State::Process","()"); const Store & r = raw; Store & p = processed; StoreUniform & u = uniform; - if( r.ver > 0 && r.ver == p.ver ) { + if ( r.ver > 0 && r.ver == p.ver ) + { return; } p = r; r3::Matrix4f identity; - if( p.fog.enable == false ) { + if ( p.fog.enable == false ) + { p.fog.useDepth = true; p.fog.mode = FG_Exp; } @@ -1961,12 +2497,20 @@ void Iff::State::Process( Iff * ffn ) u.alphaTest.alphaRef = floor( u.alphaTest.alphaRef * 255.0f + 0.5f ) / 255.0f; - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { + size_t n = array_size( ffn->textureUnit ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( ffn->textureUnit, i ); TextureUnit & ti = ffn->textureUnit[ i ]; + RegalAssertArrayIndex( raw.tex, i ); raw.tex[i].unit = ti; } - for( int i = 0; i < REGAL_EMU_IFF_TEXTURE_UNITS; i++ ) { + n = array_size( p.tex ); + for ( size_t i = 0; i < n; i++ ) + { + RegalAssertArrayIndex( p.tex, i ); + RegalAssertArrayIndex( r.tex, i ); Texture & pt = p.tex[i]; const Texture & rt= r.tex[i]; // for processed state, only the highest priority texture enable set (others are dont-care) @@ -1977,30 +2521,43 @@ void Iff::State::Process( Iff * ffn ) //<> pt.enables = HighestPriorityTextureEnable( rt.enables & rt.unit.ttb ); pt.enables = HighestPriorityTextureEnable( rt.enables ); pt.unit = rt.unit; + RegalAssertArrayIndex( ffn->texture, i ); pt.useMatrix = pt.enables != 0 && ffn->texture[i].Top() != identity; - if( pt.unit.env.mode != TEM_Combine ) { + if ( pt.unit.env.mode != TEM_Combine ) + { pt.unit.env.rgb = TexenvCombineState(true); pt.unit.env.a = TexenvCombineState(false); } } - if( p.lighting == false ) { + n = array_size( p.light ); + if ( p.lighting == false ) + { p.rescaleNormal = false; p.normalize = false; - for ( int i = 0; i (&p) + sizeof(p.hash) + sizeof(p.ver), + sizeof(p)-sizeof(p.hash)-sizeof(p.ver), 0); } void Iff::UpdateUniforms( RegalContext * ctx ) @@ -2009,44 +2566,57 @@ void Iff::UpdateUniforms( RegalContext * ctx ) Program & pgm = *currprog; DispatchTableGL & tbl = ctx->dispatcher.emulation; - if( pgm.ver != ffstate.Ver() ) { + if ( pgm.ver != ffstate.Ver() ) + { pgm.ver = ffstate.Ver(); const State::Store & p = ffstate.processed; const State::StoreUniform & u = ffstate.uniform; - for( std::map< RegalFFUniformEnum, Program::UniformInfo>::iterator i = pgm.uniforms.begin(); i != pgm.uniforms.end(); ++i ) { + for ( std::map< RegalFFUniformEnum, Program::UniformInfo>::iterator i = pgm.uniforms.begin(); i != pgm.uniforms.end(); ++i ) + { Program::UniformInfo & ui = (*i).second; - switch( (*i).first ) { - case FFU_ModelviewInverseTranspose: { - if( ui.ver != modelview.Ver() ) { + switch( (*i).first ) + { + case FFU_ModelviewInverseTranspose: + { + if ( ui.ver != modelview.Ver() ) + { ui.ver = modelview.Ver(); r3::Matrix4f mvi = modelview.Top().Inverse(); - if( p.rescaleNormal ) { + if ( p.rescaleNormal ) + { mvi = RescaleNormal( mvi ); } tbl.glUniformMatrix4fv( ui.slot, 1, GL_FALSE, mvi.Transpose().m ); } break; } - case FFU_ModelviewInverse: { - if( ui.ver != modelview.Ver() ) { + case FFU_ModelviewInverse: + { + if ( ui.ver != modelview.Ver() ) + { ui.ver = modelview.Ver(); r3::Matrix4f mvi = modelview.Top().Inverse(); - if( p.rescaleNormal ) { + if ( p.rescaleNormal ) + { mvi = RescaleNormal( mvi ); } tbl.glUniformMatrix4fv( ui.slot, 1, GL_FALSE, mvi.Ptr() ); } break; } - case FFU_Modelview: { - if( ui.ver != modelview.Ver() ) { + case FFU_Modelview: + { + if ( ui.ver != modelview.Ver() ) + { ui.ver = modelview.Ver(); tbl.glUniformMatrix4fv( ui.slot, 1, GL_FALSE, modelview.Top().m ); } break; } - case FFU_Projection: { - if( ui.ver != projection.Ver() ) { + case FFU_Projection: + { + if ( ui.ver != projection.Ver() ) + { ui.ver = projection.Ver(); tbl.glUniformMatrix4fv( ui.slot, 1, GL_FALSE, projection.Top().m ); } @@ -2067,9 +2637,12 @@ void Iff::UpdateUniforms( RegalContext * ctx ) case FFU_TextureMatrix12: case FFU_TextureMatrix13: case FFU_TextureMatrix14: - case FFU_TextureMatrix15: { + case FFU_TextureMatrix15: + { int idx = ( ((*i).first) - FFU_TextureMatrix0 ); - if( ui.ver != texture[ idx ].Ver() ) { + RegalAssertArrayIndex( texture, idx ); + if ( ui.ver != texture[ idx ].Ver() ) + { ui.ver = texture[ idx ].Ver(); r3::Matrix4f m = texture[ idx ].Top(); tbl.glUniformMatrix4fv( ui.slot, 1, GL_FALSE, m.m ); @@ -2091,9 +2664,12 @@ void Iff::UpdateUniforms( RegalContext * ctx ) case FFU_TextureEnvColor12: case FFU_TextureEnvColor13: case FFU_TextureEnvColor14: - case FFU_TextureEnvColor15: { + case FFU_TextureEnvColor15: + { int idx = ( ((*i).first) - FFU_TextureEnvColor0 ); - if( ui.ver != textureEnvColorVer[ idx ] ) { + RegalAssertArrayIndex( textureEnvColorVer, idx ); + if ( ui.ver != textureEnvColorVer[ idx ] ) + { ui.ver = textureEnvColorVer[ idx ]; tbl.glUniform4fv( ui.slot, 1, &textureEnvColor[ idx ].x); } @@ -2106,79 +2682,133 @@ void Iff::UpdateUniforms( RegalContext * ctx ) case FFU_Light4: case FFU_Light5: case FFU_Light6: - case FFU_Light7: { + case FFU_Light7: + { int idx = ( ((*i).first) - FFU_Light0 ); - if( ui.ver != u.light[ idx ].ver ) { + RegalAssertArrayIndex( u.light, idx ); + if ( ui.ver != u.light[ idx ].ver ) + { ui.ver = u.light[ idx ].ver; tbl.glUniform4fv( ui.slot, LE_Elements, &u.light[ idx ].ambient.x); } break; } case FFU_MaterialFront: - case FFU_MaterialBack: { + case FFU_MaterialBack: + { int idx = ( ((*i).first) - FFU_MaterialFront ); - if( ui.ver != u.mat[ idx ].ver ) { + RegalAssertArrayIndex( u.mat, idx ); + if ( ui.ver != u.mat[ idx ].ver ) + { ui.ver = u.mat[ idx ].ver; tbl.glUniform4fv( ui.slot, ME_Elements, &u.mat[ idx ].ambient.x); } break; } - case FFU_LightModelAmbient: { + case FFU_LightModelAmbient: + { tbl.glUniform4fv( ui.slot, 1, &u.lightModelAmbient.x); break; } - case FFU_Texgen0ObjS: case FFU_Texgen0ObjT: case FFU_Texgen0ObjR: case FFU_Texgen0ObjQ: - case FFU_Texgen0EyeS: case FFU_Texgen0EyeT: case FFU_Texgen0EyeR: case FFU_Texgen0EyeQ: - case FFU_Texgen1ObjS: case FFU_Texgen1ObjT: case FFU_Texgen1ObjR: case FFU_Texgen1ObjQ: - case FFU_Texgen1EyeS: case FFU_Texgen1EyeT: case FFU_Texgen1EyeR: case FFU_Texgen1EyeQ: - case FFU_Texgen2ObjS: case FFU_Texgen2ObjT: case FFU_Texgen2ObjR: case FFU_Texgen2ObjQ: - case FFU_Texgen2EyeS: case FFU_Texgen2EyeT: case FFU_Texgen2EyeR: case FFU_Texgen2EyeQ: - case FFU_Texgen3ObjS: case FFU_Texgen3ObjT: case FFU_Texgen3ObjR: case FFU_Texgen3ObjQ: - case FFU_Texgen3EyeS: case FFU_Texgen3EyeT: case FFU_Texgen3EyeR: case FFU_Texgen3EyeQ: { + case FFU_Texgen0ObjS: + case FFU_Texgen0ObjT: + case FFU_Texgen0ObjR: + case FFU_Texgen0ObjQ: + case FFU_Texgen0EyeS: + case FFU_Texgen0EyeT: + case FFU_Texgen0EyeR: + case FFU_Texgen0EyeQ: + case FFU_Texgen1ObjS: + case FFU_Texgen1ObjT: + case FFU_Texgen1ObjR: + case FFU_Texgen1ObjQ: + case FFU_Texgen1EyeS: + case FFU_Texgen1EyeT: + case FFU_Texgen1EyeR: + case FFU_Texgen1EyeQ: + case FFU_Texgen2ObjS: + case FFU_Texgen2ObjT: + case FFU_Texgen2ObjR: + case FFU_Texgen2ObjQ: + case FFU_Texgen2EyeS: + case FFU_Texgen2EyeT: + case FFU_Texgen2EyeR: + case FFU_Texgen2EyeQ: + case FFU_Texgen3ObjS: + case FFU_Texgen3ObjT: + case FFU_Texgen3ObjR: + case FFU_Texgen3ObjQ: + case FFU_Texgen3EyeS: + case FFU_Texgen3EyeT: + case FFU_Texgen3EyeR: + case FFU_Texgen3EyeQ: + { int idx = ( (*i).first ) - FFU_Texgen0ObjS; int comp = idx % 4; int unit = idx >> 3; + RegalAssertArrayIndex( u.tex, unit ); + RegalAssertArrayIndex( u.tex[unit].texgen, comp ); const State::TexgenUniform & tg = u.tex[unit].texgen[comp]; - if( idx & 4 ) { - if( ui.ver != tg.eyeVer ) { + if ( idx & 4 ) + { + if ( ui.ver != tg.eyeVer ) + { ui.ver = tg.eyeVer; tbl.glUniform4fv( ui.slot, 1, & tg.eye.x ); } - } else { - if( ui.ver != tg.objVer ) { + } + else + { + if ( ui.ver != tg.objVer ) + { ui.ver = tg.objVer; tbl.glUniform4fv( ui.slot, 1, & tg.obj.x ); } } break; } - case FFU_ClipPlane0: case FFU_ClipPlane1: case FFU_ClipPlane2: case FFU_ClipPlane3: - case FFU_ClipPlane4: case FFU_ClipPlane5: case FFU_ClipPlane6: case FFU_ClipPlane7: { + case FFU_ClipPlane0: + case FFU_ClipPlane1: + case FFU_ClipPlane2: + case FFU_ClipPlane3: + case FFU_ClipPlane4: + case FFU_ClipPlane5: + case FFU_ClipPlane6: + case FFU_ClipPlane7: + { int idx = ( (*i).first ) - FFU_ClipPlane0; - if( ui.ver != u.clip[idx].ver ) { + RegalAssertArrayIndex( u.clip, idx ); + if ( ui.ver != u.clip[idx].ver ) + { ui.ver = u.clip[idx].ver; tbl.glUniform4fv( ui.slot, 1, & u.clip[idx].plane.x ); } break; } - case FFU_Fog: { - if( ui.ver != u.fog.ver ) { + case FFU_Fog: + { + if ( ui.ver != u.fog.ver ) + { ui.ver = u.fog.ver; tbl.glUniform4fv( ui.slot, 2, &u.fog.params[0].x); } break; } - case FFU_AlphaRef: { - if( ui.ver != u.alphaTest.ver ) { + case FFU_AlphaRef: + { + if ( ui.ver != u.alphaTest.ver ) + { ui.ver = u.alphaTest.ver; tbl.glUniform1f( ui.slot, u.alphaTest.alphaRef ); } break; } - case FFU_Attrib: { - if( ui.ver != u.vabVer ) { + case FFU_Attrib: + { + if ( ui.ver != u.vabVer ) + { ui.ver = u.vabVer; - tbl.glUniform4fv( ui.slot, REGAL_EMU_IFF_VERTEX_ATTRIBS, & immVab.attr[0].x ); + tbl.glUniform4fv( ui.slot, REGAL_EMU_MAX_VERTEX_ATTRIBS, & immVab[0].x ); } break; } @@ -2189,73 +2819,200 @@ void Iff::UpdateUniforms( RegalContext * ctx ) } } +inline bool operator == ( const Iff::State::Light & lhs, const Iff::State::Light & rhs ) +{ + if ( !(lhs.enable == rhs.enable) ) + return false; + if ( !(lhs.spotlight == rhs.spotlight) ) + return false; + if ( !(lhs.attenuate == rhs.attenuate) ) + return false; + if ( !(lhs.local == rhs.local) ) + return false; + + return true; +} + +inline bool operator == ( const Iff::TexenvCombineState & lhs, const Iff::TexenvCombineState & rhs ) +{ + if ( !(lhs.mode == rhs.mode) ) + return false; + if ( !(lhs.src0 == rhs.src0) ) + return false; + if ( !(lhs.src1 == rhs.src1) ) + return false; + if ( !(lhs.src2 == rhs.src2) ) + return false; + if ( !(lhs.op0 == rhs.op0) ) + return false; + if ( !(lhs.op1 == rhs.op1) ) + return false; + if ( !(lhs.op2 == rhs.op2) ) + return false; + if ( !(lhs.mode == rhs.mode) ) + return false; + if (lhs.scale != rhs.scale) + return false; + + return true; +} + +inline bool operator == ( const Iff::TextureEnv & lhs, const Iff::TextureEnv & rhs ) +{ + if ( !(lhs.mode == rhs.mode) ) + return false; + if ( !(lhs.rgb == rhs.rgb) ) + return false; + if ( !(lhs.a == rhs.a) ) + return false; + + return true; +} + +inline bool operator == ( const Iff::TextureUnit & lhs, const Iff::TextureUnit & rhs ) +{ + if (lhs.ttb != rhs.ttb) + return false; + if (lhs.fmt != rhs.fmt) + return false; + if ( !(lhs.env == rhs.env) ) + return false; + + return true; +} + +inline bool operator == ( const Iff::State::Texgen & lhs, const Iff::State::Texgen & rhs ) +{ + if (lhs.enable != rhs.enable) + return false; + if ( !(lhs.mode == rhs.mode) ) + return false; + + return true; +} + +inline bool operator == ( const Iff::State::Texture & lhs, const Iff::State::Texture & rhs ) +{ + if (lhs.enables != rhs.enables) + return false; + if (lhs.useMatrix != rhs.useMatrix) + return false; + if ( !(lhs.unit == rhs.unit) ) + return false; + + size_t n = array_size( lhs.texgen ); + for (size_t ii=0; ii wayhist(1 << ( REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE_BITS - REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS ),0); -std::vector evicthist(1 << ( REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE_BITS - REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS ),0); - void Iff::UseFixedFunctionProgram( RegalContext * ctx ) { Internal("Regal::Iff::UseFixedFunctionProgram", boost::print::optional(ctx,Logging::pointers)); - if( currprog != NULL && currprog->ver == ver.Current() ) { + if ( currprog != NULL && currprog->ver == ver.Current() ) + { return; } ffstate.Process( this ); - size_t base = ProgHashToSet( ffstate.processed.hash ) << REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS; + uint32_t base = ( static_cast(ffstate.processed.hash) & REGAL_FIXED_FUNCTION_PROGRAM_CACHE_MASK ) << REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS; int match = -1; - for( int i = 0; i < (1 << REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS); i++ ) { - assert(i<(1 << REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS)); - if( ffprogs[ base + i ].store == ffstate.processed ) { + const uint32_t n = static_cast(array_size( ffprogs )); + for ( uint32_t i = 0; i < REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET; i++ ) + { + RegalAssertArrayIndex( ffprogs, base + i ); + if ( base + i >= n ) + continue; + if ( ffprogs[ base + i ].store == ffstate.processed ) + { match = i; break; } } Program * p = NULL; - if( match < 0 ) { - wayhist[ base >> REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS ]++; - -#if 0 - fprintf( stderr, "wayhist: " ); - GLuint sum = 0; - for( int i = 0; i < 1 << ( REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE_BITS - REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS ); i++ ) { - fprintf( stderr, "%4d ", wayhist[i] ); - sum += wayhist[i]; - } - fprintf( stderr, "-- %d\n", sum ); -#endif + if ( match < 0 ) + { match = 0; progcount++; - for( int i = 0; i < 1 << REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS; i++ ) { - if( ffprogs[ base + i ].ver < ffprogs[ base + match ].ver ) { + for ( int i = 1; i < REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET; i++ ) + { + RegalAssertArrayIndex( ffprogs, base + i ); + RegalAssertArrayIndex( ffprogs, base + match ); + if ( ffprogs[ base + i ].ver < ffprogs[ base + match ].ver ) + { match = i; } } + RegalAssertArrayIndex( ffprogs, base + match ); p = & ffprogs[ base + match ]; // delete this program - if( p->pg != 0 ) { + if ( p->pg != 0 ) + { DispatchTableGL & tbl = ctx->dispatcher.emulation; tbl.call(&tbl.glDeleteShader)( p->vs ); tbl.call(&tbl.glDeleteShader)( p->fs ); tbl.call(&tbl.glDeleteProgram)( p->pg ); *p = Program(); - evicthist[ base >> REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS ]++; -#if 0 - fprintf( stderr, "evicthist: " ); - GLuint sum = 0; - for( int i = 0; i < 1 << ( REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE_BITS - REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS ); i++ ) { - fprintf( stderr, "%4d ", evicthist[i] ); - sum += evicthist[i]; - } - fprintf( stderr, "-- %d\n", sum ); -#endif } string_list vsSrc; GenerateVertexShaderSource( this, ffstate, vsSrc ); @@ -2264,8 +3021,8 @@ void Iff::UseFixedFunctionProgram( RegalContext * ctx ) p->Init( ctx, ffstate.processed, vsSrc.str().c_str(), fsSrc.str().c_str() ); p->progcount = progcount; } - p = & ffprogs[ base + match ]; - currprog = p; + RegalAssertArrayIndex( ffprogs, base + match ); + currprog = & ffprogs[ base + match ]; ctx->dispatcher.emulation.glUseProgram( currprog->pg ); UpdateUniforms( ctx ); } @@ -2274,13 +3031,15 @@ void Iff::UseShaderProgram( RegalContext * ctx ) { Internal("Regal::Iff::UseShaderProgram", boost::print::optional(ctx,Logging::pointers)); - if( currprog != NULL && currprog->ver == ver.Current() ) { + if ( currprog != NULL && currprog->ver == ver.Current() ) + { return; } ffstate.Process( this ); RegalAssert( shprogmap.count( program ) != 0 ); currprog = & shprogmap[ program ]; - if( currprog->pg == 0 ) { + if ( currprog->pg == 0 ) + { Warning( "The program is 0. That can't be right.\n" ); } UpdateUniforms( ctx ); @@ -2346,33 +3105,42 @@ static void replace_ftransform(GLchar *str) } } -static bool uses_string( const char * str, int count, const GLchar * const * srcstr, const GLint *length ) { - for( int i = 0; i < count; i++ ) { - const size_t len = (length && length[i] >= 0) ? length[i] : strlen(srcstr[i]); - std::string seg(srcstr[i],len); - if( seg.find( str ) != std::string::npos ) { - return true; - } +static bool uses_string( const char * str, int count, const GLchar * const * srcstr, const GLint *length ) +{ + for ( int i = 0; i < count; i++ ) + { + const size_t len = (length && length[i] >= 0) ? length[i] : strlen(srcstr[i]); + std::string seg(srcstr[i],len); + if ( seg.find( str ) != std::string::npos ) + { + return true; } - return false; + } + return false; } void Iff::ShaderSource( RegalContext *ctx, GLuint shader, GLsizei count, const GLchar * const * srcstr, const GLint *length) { bool uses_ftransform = false; - for( int i = 0; i < count && uses_ftransform == false; i++ ) { + for ( int i = 0; i < count && uses_ftransform == false; i++ ) + { std::string seg; - if( length != NULL ) { + if ( length != NULL ) + { seg = std::string( srcstr[i], length[i] ); - } else { + } + else + { seg = std::string( srcstr[i] ); } - if( seg.find( "ftransform()" ) != std::string::npos ) { + if ( seg.find( "ftransform()" ) != std::string::npos ) + { uses_ftransform = true; } } //uses_ftransform = false; // hack - if( srcstr[0][0] == '#' && srcstr[0][1] == 'v' ) { + if ( srcstr[0][0] == '#' && srcstr[0][1] == 'v' ) + { ctx->dispatcher.emulation.glShaderSource( shader, count, srcstr, length ); return; } @@ -2393,7 +3161,7 @@ void Iff::ShaderSource( RegalContext *ctx, GLuint shader, GLsizei count, const G version = remove_version(s[i+1]); if (uses_ftransform && gles ) replace_ftransform(s[i+1]); - if( legacy ) + if ( legacy ) remove_precision(s[i+1]); } @@ -2404,10 +3172,13 @@ void Iff::ShaderSource( RegalContext *ctx, GLuint shader, GLsizei count, const G if (gles) { // hack around #version 100 on x86 failing compilation - if( ctx->info->gl_version_major >= 3 ) { + if ( ctx->info->gl_version_major >= 3 ) + { ss << "#version 120\n"; ss << "#define precision\n"; - } else { + } + else + { #if REGAL_FORCE_DESKTOP_GLSL ss << "#version 140\n"; #else @@ -2422,7 +3193,8 @@ void Iff::ShaderSource( RegalContext *ctx, GLuint shader, GLsizei count, const G } else { - if (version > 0) { + if (version > 0) + { // We should honor the version in the original shader if we can, but leave out for now. //ss << "#version " << version << "\n"; if (shaderTypeMap[ shader ] == GL_VERTEX_SHADER) @@ -2434,7 +3206,9 @@ void Iff::ShaderSource( RegalContext *ctx, GLuint shader, GLsizei count, const G { ss << "#define in varying\n"; } - } else { + } + else + { ss << "#version 140\n"; } } @@ -2449,10 +3223,15 @@ void Iff::ShaderSource( RegalContext *ctx, GLuint shader, GLsizei count, const G { ss << "#define in varying\n"; } - } else { - if( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) { + } + else + { + if ( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) + { - } else { + } + else + { ss << "#define gl_FragColor rglFragColor\n"; ss << "out vec4 rglFragColor;\n"; ss << "#define texture1D texture\n"; @@ -2460,77 +3239,99 @@ void Iff::ShaderSource( RegalContext *ctx, GLuint shader, GLsizei count, const G ss << "#define textureCube texture\n"; } } - if( gles ) { + if ( gles ) + { ss << "precision highp float;\n"; } ss << "#define centroid \n"; ss << "#define gl_FogFragCoord rglFogFragCoord\n"; - if( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) { + if ( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) + { ss << "#define gl_Color rglColor\n"; - } else { + } + else + { ss << "#define gl_Color rglFrontColor\n"; } ss << "#define gl_FrontColor rglFrontColor\n"; - if( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) { + if ( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) + { ss << "#define gl_SecondaryColor rglSecondaryColor\n"; - } else { + } + else + { ss << "#define gl_SecondaryColor rglFrontSecondaryColor\n"; } ss << "#define gl_FrontSecondaryColor rglFrontSecondaryColor\n"; ss << "#define gl_ClipVertex rglClipVertex\n"; ss << "#define gl_FragDepth rglFragDepth\n"; -if( gles ) { - ss << "#define texture3d texture2d\n"; - ss << "#define texture3D(a,b) texture2D(a,b.xy)\n"; - ss << "#define sampler3D sampler2D\n"; -} + if ( gles ) + { + ss << "#define texture3d texture2d\n"; + ss << "#define texture3D(a,b) texture2D(a,b.xy)\n"; + ss << "#define sampler3D sampler2D\n"; + } -if( uses_string( "gl_FogFragCoord", count, srcstr, length ) ) { - ss << "out float rglFogFragCoord;\n"; -} + if ( uses_string( "gl_FogFragCoord", count, srcstr, length ) ) + { + ss << "out float rglFogFragCoord;\n"; + } // NOTE: ES 2.0 does not support gl_FragDepth, so we just discard it, for now // See: http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf -if( uses_string( "gl_FragDepth", count, srcstr, length ) ) { - ss << (shaderTypeMap[shader]==GL_VERTEX_SHADER ? "out" : " ") << " float rglFragDepth;\n"; -} - - -if( uses_string( "gl_Color", count, srcstr, length ) ) { - if( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) { - ss << "in vec4 rglColor;\n"; - } else { - ss << "in vec4 rglFrontColor;\n"; + if ( uses_string( "gl_FragDepth", count, srcstr, length ) ) + { + ss << (shaderTypeMap[shader]==GL_VERTEX_SHADER ? "out" : " ") << " float rglFragDepth;\n"; + } + + + if ( uses_string( "gl_Color", count, srcstr, length ) ) + { + if ( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) + { + ss << "in vec4 rglColor;\n"; + } + else + { + ss << "in vec4 rglFrontColor;\n"; + } + } + if ( uses_string( "gl_FrontColor", count, srcstr, length ) ) + { + ss << "out vec4 rglFrontColor;\n"; } -} -if( uses_string( "gl_FrontColor", count, srcstr, length ) ) { - ss << "out vec4 rglFrontColor;\n"; -} // NOTE: gl_SecondaryColor can be a vertex shader output, or a fragment shader input. // See: http://www.opengl.org/registry/doc/GLSLangSpec.4.30.7.pdf -if( uses_string( "gl_SecondaryColor", count, srcstr, length ) ) { - if( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) { - ss << "in vec4 rglSecondaryColor;\n"; - } else { - ss << "in vec4 rglFrontSecondaryColor;\n"; + if ( uses_string( "gl_SecondaryColor", count, srcstr, length ) ) + { + if ( shaderTypeMap[ shader ] == GL_VERTEX_SHADER ) + { + ss << "in vec4 rglSecondaryColor;\n"; + } + else + { + ss << "in vec4 rglFrontSecondaryColor;\n"; + } } -} -if( uses_string( "gl_FrontSecondaryColor", count, srcstr, length ) ) { - ss << "out vec4 rglFrontSecondaryColor;\n"; -} -if( uses_string( "gl_ClipVertex", count, srcstr, length ) ) { - // should be "out", but temporarily disabled due to register pressure concerns - // ss << "out vec4 rglClipVertex;\n"; - ss << "vec4 rglClipVertex;\n"; -} + if ( uses_string( "gl_FrontSecondaryColor", count, srcstr, length ) ) + { + ss << "out vec4 rglFrontSecondaryColor;\n"; + } + if ( uses_string( "gl_ClipVertex", count, srcstr, length ) ) + { + // should be "out", but temporarily disabled due to register pressure concerns + // ss << "out vec4 rglClipVertex;\n"; + ss << "vec4 rglClipVertex;\n"; + } - if ( uses_ftransform && gles ) { + if ( uses_ftransform && gles ) + { ss << "uniform mat4 rglModelview;\n"; ss << "uniform mat4 rglProjection;\n"; // should be "in", but temporarily disabled due to register pressure concerns @@ -2543,7 +3344,8 @@ if( uses_string( "gl_ClipVertex", count, srcstr, length ) ) { ss << "#define gl_TextureMatrix0 rglTextureMatrix0\n"; ss << "#define gl_Sampler0 rglSampler0\n\n"; - if ( uses_ftransform && gles ) { + if ( uses_ftransform && gles ) + { ss << "vec4 rgl_ftform() { return gl_Projection * gl_Modelview * rglVertex; }\n\n"; } //Logging::Output( "foo:\n%s", ss.str().c_str() ); @@ -2554,10 +3356,13 @@ if( uses_string( "gl_ClipVertex", count, srcstr, length ) ) { ctx->dispatcher.emulation.glShaderSource( shader, count + 1, const_cast(&s[0]), &l[0] ); } -void Iff::LinkProgram( RegalContext *ctx, GLuint program ) { +void Iff::LinkProgram( RegalContext *ctx, GLuint program ) +{ // need to bind attribs just before link for Regal-generated attribs - if ( program != 0 ) { - if( shprogmap.count( program ) == 0 ) { + if ( program != 0 ) + { + if ( shprogmap.count( program ) == 0 ) + { ffstate.Process( this ); Program & p = shprogmap[ program ]; p.pg = program; diff --git a/src/regal/RegalIff.h b/src/regal/RegalIff.h index 763d0bd..7220683 100644 --- a/src/regal/RegalIff.h +++ b/src/regal/RegalIff.h @@ -40,26 +40,17 @@ #include "RegalUtil.h" +#include "lookup3.h" + #define REGAL_IMMEDIATE_BUFFER_SIZE 8192 -// Configurable - #define REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE_BITS 8 +#define REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SET_BITS 2 -// Derived +#define REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE (1< bool RFFIsVector( const T p ) { UNUSED_PARAMETER(p); return false; } -template bool RFFIsVector( const T * p ) { UNUSED_PARAMETER(p); return true; } +template bool RFFIsVector( const T p ) +{ + UNUSED_PARAMETER(p); + return false; +} +template bool RFFIsVector( const T * p ) +{ + UNUSED_PARAMETER(p); + return true; +} -template GLfloat RFFToFloat( int i, const T p ) { UNUSED_PARAMETER(i); return GLfloat( p ); } -template GLfloat RFFToFloat( int i, const T * p ) { return GLfloat( p[i] ); } -template GLfloat RFFToFloatN( int i, const T p ) { UNUSED_PARAMETER(i); return GLfloat( p ); } -template GLfloat RFFToFloatN( int i, const T * p ) { return GLfloat( p[i] ); } -template <> inline GLfloat RFFToFloatN( int i, const GLint p ) { UNUSED_PARAMETER(i); return GLfloat( double( p ) / double( INT_MAX ) ); } -template <> inline GLfloat RFFToFloatN( int i, const int * p ) { return GLfloat( double( p[i] ) / double( INT_MAX ) ); } +template GLfloat RFFToFloat( int i, const T p ) +{ + UNUSED_PARAMETER(i); + return GLfloat( p ); +} +template GLfloat RFFToFloat( int i, const T * p ) +{ + return GLfloat( p[i] ); +} +template GLfloat RFFToFloatN( int i, const T p ) +{ + UNUSED_PARAMETER(i); + return GLfloat( p ); +} +template GLfloat RFFToFloatN( int i, const T * p ) +{ + return GLfloat( p[i] ); +} +template <> inline GLfloat RFFToFloatN( int i, const GLint p ) +{ + UNUSED_PARAMETER(i); + return GLfloat( double( p ) / double( INT_MAX ) ); +} +template <> inline GLfloat RFFToFloatN( int i, const int * p ) +{ + return GLfloat( double( p[i] ) / double( INT_MAX ) ); +} struct Iff { Iff() - : progcount(0) + : progcount(0) + , catIndex(0) + , ffAttrTexBegin(0) + , ffAttrTexEnd(0) + , ffAttrNumTex(0) + , max_vertex_attribs(0) + , immActive(false) + , immProvoking(0) + , immCurrent(0) + , immPrim(GL_POINTS) + , immVbo(0) + , immVao(0) + , immQuadsVbo(0) + , immShadowVao(0) + , shadowMatrixMode(GL_MODELVIEW) + , shadowActiveTextureIndex(0) + , activeTextureIndex(0) + , programPipeline(0) + , program(0) + , currprog(NULL) + , currMatrixStack(&modelview) + , currVao(0) + , gles(false) + , legacy(false) { - } + memset(immArray,0,sizeof(immArray)); - Iff(const Iff &other) - : progcount(0) - { - UNUSED_PARAMETER(other); - } - - Iff &operator=(const Iff &other) - { - UNUSED_PARAMETER(other); - if (&other!=this) + size_t n = array_size( ffAttrMap ); + RegalAssert( array_size( ffAttrInvMap ) == n); + for (size_t i = 0; i < n; i++) { + ffAttrMap[ i ] = 0; + ffAttrInvMap[ i ] = 0; } - return *this; - } - ~Iff() - { + n = array_size( texture ); + RegalAssert( array_size( textureUnit ) == n); + RegalAssert( array_size( textureEnvColor ) == n); + RegalAssert( array_size( textureEnvColorVer ) == n); + RegalAssert( array_size( textureBinding ) == n); + for (size_t i = 0; i < n; i++) + { + textureEnvColor[ i ] = Float4( 0.0f, 0.0f, 0.0f, 0.0f ); + textureEnvColorVer[ i ] = 0; + textureBinding[ i ] = 0; + } + n = array_size( ffprogs ); + for (size_t i = 0; i < n; ++i) + ffprogs[ i ] = Program(); } void Cleanup( RegalContext &ctx ); - // Info int progcount; // Vertex arrays GLuint catIndex; - GLuint ffAttrMap[ REGAL_EMU_IFF_VERTEX_ATTRIBS ]; - GLuint ffAttrInvMap[ REGAL_EMU_IFF_VERTEX_ATTRIBS ]; + GLuint ffAttrMap[ REGAL_EMU_MAX_VERTEX_ATTRIBS ]; + GLuint ffAttrInvMap[ REGAL_EMU_MAX_VERTEX_ATTRIBS ]; GLuint ffAttrTexBegin; GLuint ffAttrTexEnd; GLuint ffAttrNumTex; - GLuint maxVertexAttribs; + GLuint max_vertex_attribs; void InitVertexArray(RegalContext &ctx) { - maxVertexAttribs = ctx.info->maxVertexAttribs; + max_vertex_attribs = ctx.info->gl_max_vertex_attribs; - if( maxVertexAttribs >= 16 ) { - RegalAssert( REGAL_EMU_IFF_VERTEX_ATTRIBS == 16); - //RegalOutput( "Setting up for %d Vertex Attribs\n", maxVertexAttribs ); - for( int i = 0; i < 16; i++ ) { + if (max_vertex_attribs >= 16) + { + RegalAssert( REGAL_EMU_MAX_VERTEX_ATTRIBS == 16); + //RegalOutput( "Setting up for %d Vertex Attribs\n", max_vertex_attribs ); + for (size_t i = 0; i < 16; i++) + { ffAttrMap[i] = RFF2AMap16[i]; ffAttrInvMap[i] = RFF2AInvMap16[i]; } ffAttrTexBegin = RFF2ATexBegin16; ffAttrTexEnd = RFF2ATexEnd16; - } else { - RegalAssert( maxVertexAttribs >= 8 ); + } + else + { + RegalAssert( max_vertex_attribs >= 8 ); //RegalOutput( "Setting up for 8 Vertex Attribs" ); - for( int i = 0; i < 8; i++ ) { + for (size_t i = 0; i < 8; i++) + { ffAttrMap[i] = RFF2AMap8[i]; ffAttrInvMap[i] = RFF2AInvMap8[i]; } - for( int i = 8; i < REGAL_EMU_IFF_VERTEX_ATTRIBS; i++ ) { + for (size_t i = 8; i < REGAL_EMU_MAX_VERTEX_ATTRIBS; i++) + { ffAttrMap[i] = GLuint(-1); ffAttrInvMap[i] = GLuint(-1); } @@ -422,46 +483,55 @@ struct Iff catIndex = 0; } - GLuint ClientStateToIndex( GLenum state ) { - switch( state ) { - case GL_VERTEX_ARRAY: return ffAttrMap[ RFF2A_Vertex ]; - case GL_NORMAL_ARRAY: return ffAttrMap[ RFF2A_Normal ]; - case GL_COLOR_ARRAY: return ffAttrMap[ RFF2A_Color ]; - case GL_SECONDARY_COLOR_ARRAY: return ffAttrMap[ RFF2A_SecondaryColor ]; - case GL_FOG_COORD_ARRAY: return ffAttrMap[ RFF2A_FogCoord ]; - case GL_EDGE_FLAG_ARRAY: return ffAttrMap[ RFF2A_EdgeFlag ]; - case GL_TEXTURE_COORD_ARRAY: { - if( catIndex < ffAttrNumTex ) { + GLuint ClientStateToIndex( GLenum state ) + { + switch( state ) + { + case GL_VERTEX_ARRAY: + return ffAttrMap[ RFF2A_Vertex ]; + case GL_NORMAL_ARRAY: + return ffAttrMap[ RFF2A_Normal ]; + case GL_COLOR_ARRAY: + return ffAttrMap[ RFF2A_Color ]; + case GL_SECONDARY_COLOR_ARRAY: + return ffAttrMap[ RFF2A_SecondaryColor ]; + case GL_FOG_COORD_ARRAY: + return ffAttrMap[ RFF2A_FogCoord ]; + case GL_EDGE_FLAG_ARRAY: + return ffAttrMap[ RFF2A_EdgeFlag ]; + case GL_TEXTURE_COORD_ARRAY: + if (catIndex < ffAttrNumTex) return ffAttrTexBegin + catIndex; - } break; - } - default: break; + default: + break; } return ~0u; } - void EnableClientState( RegalContext * ctx, GLenum state ) { + void EnableClientState( RegalContext * ctx, GLenum state ) + { const GLuint idx = ClientStateToIndex( state ); - if( idx == GLuint(~0) ) { + if (idx == GLuint(~0)) return; - } RestoreVao( ctx ); - RegalAssert( idx < maxVertexAttribs ); - if ( idx < maxVertexAttribs ) { + RegalAssert( idx < max_vertex_attribs ); + if ( idx < max_vertex_attribs ) + { ctx->dispatcher.emulation.glEnableVertexAttribArray( idx ); EnableArray( ctx, idx ); // keep ffn up to date } } - void DisableClientState( RegalContext * ctx, GLenum state ) { + void DisableClientState( RegalContext * ctx, GLenum state ) + { const GLuint idx = ClientStateToIndex( state ); - if( idx == GLuint(~0) ) { + if (idx == GLuint(~0)) return; - } RestoreVao( ctx ); - RegalAssert( idx < maxVertexAttribs ); - if ( idx < maxVertexAttribs ) { + RegalAssert( idx < max_vertex_attribs ); + if ( idx < max_vertex_attribs ) + { ctx->dispatcher.emulation.glDisableVertexAttribArray( idx ); DisableArray( ctx, idx ); // keep ffn up to date } @@ -469,9 +539,6 @@ struct Iff void VertexPointer( RegalContext * ctx, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) { - //<> if ( insideBeginEnd == true ) - //<> return; - switch (size) { case 2: @@ -500,40 +567,46 @@ struct Iff ctx->dispatcher.emulation.glVertexAttribPointer( ffAttrMap[ RFF2A_Vertex ], size, type, GL_FALSE, stride, pointer ); } - void NormalPointer( RegalContext * ctx, GLenum type, GLsizei stride, const GLvoid *pointer ) { + void NormalPointer( RegalContext * ctx, GLenum type, GLsizei stride, const GLvoid *pointer ) + { RestoreVao( ctx ); GLboolean n = type == GL_FLOAT ? GL_FALSE : GL_TRUE; ctx->dispatcher.emulation.glVertexAttribPointer( ffAttrMap[ RFF2A_Normal ], 3, type, n, stride, pointer ); } - void ColorPointer( RegalContext * ctx, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) { + void ColorPointer( RegalContext * ctx, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) + { RestoreVao( ctx ); GLboolean n = type == GL_FLOAT ? GL_FALSE : GL_TRUE; ctx->dispatcher.emulation.glVertexAttribPointer( ffAttrMap[ RFF2A_Color ], size, type, n, stride, pointer ); } - void SecondaryColorPointer( RegalContext * ctx, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) { + void SecondaryColorPointer( RegalContext * ctx, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) + { RestoreVao( ctx ); GLboolean n = type == GL_FLOAT ? GL_FALSE : GL_TRUE; ctx->dispatcher.emulation.glVertexAttribPointer( ffAttrMap[ RFF2A_SecondaryColor ], size, type, n, stride, pointer ); } - void FogCoordPointer( RegalContext * ctx, GLenum type, GLsizei stride, const GLvoid *pointer ) { + void FogCoordPointer( RegalContext * ctx, GLenum type, GLsizei stride, const GLvoid *pointer ) + { RestoreVao( ctx ); ctx->dispatcher.emulation.glVertexAttribPointer( ffAttrMap[ RFF2A_FogCoord ], 1, type, GL_FALSE, stride, pointer ); } - void EdgeFlagPointer( RegalContext * ctx, GLsizei stride, const GLvoid *pointer ) { + void EdgeFlagPointer( RegalContext * ctx, GLsizei stride, const GLvoid *pointer ) + { RestoreVao( ctx ); GLuint index = ffAttrMap[ RFF2A_EdgeFlag ]; - if( index == RFF2A_Invalid ) { + if (index == RFF2A_Invalid) return; - } ctx->dispatcher.emulation.glVertexAttribPointer( index, 1, GL_UNSIGNED_BYTE, GL_FALSE, stride, pointer ); } - void TexCoordPointer( RegalContext * ctx, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) { - if( catIndex >= ffAttrNumTex ) { + void TexCoordPointer( RegalContext * ctx, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer ) + { + if (catIndex >= ffAttrNumTex) + { // FIXME: set an error here! return; } @@ -541,22 +614,26 @@ struct Iff ctx->dispatcher.emulation.glVertexAttribPointer( ffAttrTexBegin + catIndex, size, type, GL_FALSE, stride, pointer ); } - void GetAttrib( RegalContext * ctx, GLuint index, GLenum pname, GLdouble * d ) { + void GetAttrib( RegalContext * ctx, GLuint index, GLenum pname, GLdouble * d ) + { ctx->dispatcher.emulation.glGetVertexAttribdv( index, pname, d ); } - void GetAttrib( RegalContext * ctx, GLuint index, GLenum pname, GLfloat * f ) { + void GetAttrib( RegalContext * ctx, GLuint index, GLenum pname, GLfloat * f ) + { ctx->dispatcher.emulation.glGetVertexAttribfv( index, pname, f ); } - void GetAttrib( RegalContext * ctx, GLuint index, GLenum pname, GLint * i ) { + void GetAttrib( RegalContext * ctx, GLuint index, GLenum pname, GLint * i ) + { ctx->dispatcher.emulation.glGetVertexAttribiv( index, pname, i ); } - template bool VaGet( RegalContext * ctx, GLenum pname, T * params ) { - + template bool VaGet( RegalContext * ctx, GLenum pname, T * params ) + { GLuint index = 0; - switch (pname) { + switch (pname) + { case GL_VERTEX_ARRAY_BUFFER_BINDING: case GL_VERTEX_ARRAY_SIZE: case GL_VERTEX_ARRAY_TYPE: @@ -576,7 +653,6 @@ struct Iff case GL_COLOR_ARRAY_STRIDE: case GL_COLOR_ARRAY_POINTER: index = ffAttrMap[ RFF2A_Color ]; - //if( pname == GL_COLOR_ARRAY_SIZE ) RegalOutput( "Passing index = %d to VA GetAttrib for COLOR_INDEX_SIZE\n", index ); break; case GL_SECONDARY_COLOR_ARRAY_SIZE: // This is a convenient lie. --Cass @@ -594,27 +670,26 @@ struct Iff case GL_FOG_COORD_ARRAY_POINTER: index = ffAttrMap[ RFF2A_FogCoord ]; break; - case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING: case GL_EDGE_FLAG_ARRAY_STRIDE: case GL_EDGE_FLAG_ARRAY_POINTER: index = ffAttrMap[ RFF2A_EdgeFlag ]; break; - case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: case GL_TEXTURE_COORD_ARRAY_SIZE: case GL_TEXTURE_COORD_ARRAY_TYPE: case GL_TEXTURE_COORD_ARRAY_STRIDE: - case GL_TEXTURE_COORD_ARRAY_POINTER: { - if( catIndex >= ffAttrNumTex ) { + case GL_TEXTURE_COORD_ARRAY_POINTER: + if (catIndex >= ffAttrNumTex) + { // FIXME need to set an error here! return false; } index = ffAttrTexBegin + catIndex; - } break; // INDEX arrays are not supported + case GL_INDEX_ARRAY_TYPE: *params = GL_FLOAT; break; @@ -625,7 +700,8 @@ struct Iff return false; } - switch (pname) { + switch (pname) + { case GL_VERTEX_ARRAY_BUFFER_BINDING: case GL_NORMAL_ARRAY_BUFFER_BINDING: case GL_COLOR_ARRAY_BUFFER_BINDING: @@ -640,7 +716,6 @@ struct Iff case GL_TEXTURE_COORD_ARRAY_SIZE: pname = GL_VERTEX_ATTRIB_ARRAY_SIZE; break; - case GL_VERTEX_ARRAY_TYPE: case GL_NORMAL_ARRAY_TYPE: case GL_COLOR_ARRAY_TYPE: @@ -649,7 +724,6 @@ struct Iff case GL_TEXTURE_COORD_ARRAY_TYPE: pname = GL_VERTEX_ATTRIB_ARRAY_TYPE; break; - case GL_VERTEX_ARRAY_STRIDE: case GL_NORMAL_ARRAY_STRIDE: case GL_COLOR_ARRAY_STRIDE: @@ -659,7 +733,6 @@ struct Iff case GL_TEXTURE_COORD_ARRAY_STRIDE: pname = GL_VERTEX_ATTRIB_ARRAY_STRIDE; break; - case GL_VERTEX_ARRAY_POINTER: case GL_NORMAL_ARRAY_POINTER: case GL_COLOR_ARRAY_POINTER: @@ -669,12 +742,12 @@ struct Iff case GL_TEXTURE_COORD_ARRAY_POINTER: pname = GL_VERTEX_ATTRIB_ARRAY_POINTER; break; - default: return false; } RestoreVao( ctx ); - if( index == RFF2A_Invalid ) { + if (index == RFF2A_Invalid) + { // What to return in this case? return false; } @@ -684,17 +757,18 @@ struct Iff bool IsEnabled( RegalContext * ctx, GLenum pname, GLboolean &enabled ) { + if (activeTextureIndex >= ctx->info->max_texture_units) + return false; + State::Store & st = ffstate.raw; int idx = 0; - switch( pname ) { + switch (pname) + { case GL_TEXTURE_GEN_S: case GL_TEXTURE_GEN_T: case GL_TEXTURE_GEN_R: case GL_TEXTURE_GEN_Q: idx = pname - GL_TEXTURE_GEN_S; - if( activeTextureIndex >= REGAL_EMU_IFF_TEXTURE_UNITS ) { - return false; - } enabled = st.tex[ activeTextureIndex ].texgen[ idx ].enable; return true; default: @@ -702,10 +776,10 @@ struct Iff } const GLuint index = ClientStateToIndex( pname ); - if( index == GLuint(~0) ) { + if (index == GLuint(~0)) return false; - } - RegalAssert( index < maxVertexAttribs ); + + RegalAssert( index < max_vertex_attribs ); GLint ret; GetAttrib( ctx, index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &ret ); enabled = static_cast(ret); @@ -714,36 +788,20 @@ struct Iff // immediate mode - struct Attributes { Float4 attr[ REGAL_EMU_IFF_VERTEX_ATTRIBS ]; }; + bool immActive; + GLuint immProvoking; + GLuint immCurrent; + GLenum immPrim; + Float4 immVab[ REGAL_EMU_MAX_VERTEX_ATTRIBS ]; + GLubyte immArray[ REGAL_IMMEDIATE_BUFFER_SIZE * REGAL_EMU_MAX_VERTEX_ATTRIBS * sizeof(Float4) ]; - bool immActive; - GLuint immProvoking; - int immCurrent; - GLenum immPrim; - Attributes immVab; - GLubyte immArray[ REGAL_IMMEDIATE_BUFFER_SIZE * REGAL_EMU_IFF_VERTEX_ATTRIBS * 16 ]; - - GLuint immVbo; - GLuint immVao; - GLuint immQuadsVbo; - GLuint immShadowVao; + GLuint immVbo; + GLuint immVao; + GLuint immQuadsVbo; + GLuint immShadowVao; void InitImmediate(RegalContext &ctx) { - immActive = false; - immProvoking = 0; - immCurrent = 0; - immPrim = GL_POINTS; - for( GLuint i = 0; i < maxVertexAttribs; i++ ) { - Float4 & a = immVab.attr[i]; - a.x = a.y = a.z = 0.0f; a.w = 1.0f; - } - - memset(immArray,0,sizeof(immArray)); - memset(&immVab, 0, sizeof(immVab)); - - immShadowVao = 0; - DispatchTableGL &tbl = ctx.dispatcher.emulation; tbl.glGenVertexArrays( 1, & immVao ); tbl.glBindVertexArray( immVao ); @@ -751,19 +809,26 @@ struct Iff tbl.glGenBuffers( 1, & immVbo ); tbl.glGenBuffers( 1, & immQuadsVbo ); tbl.glBindBuffer( GL_ARRAY_BUFFER, immVbo ); + #if REGAL_SYS_EMSCRIPTEN // We need this to be an allocated buffer for WebGL, because a dangling VertexAttribPointer // doesn't work. XXX -- this might be a Firefox bug, check? tbl.glBufferData( GL_ARRAY_BUFFER, sizeof( immArray ), NULL, GL_STATIC_DRAW ); #endif - for( GLuint i = 0; i < maxVertexAttribs; i++ ) { + + for (GLuint i = 0; i < max_vertex_attribs; i++) + { EnableArray( &ctx, i ); // to keep ffn current tbl.glEnableVertexAttribArray( i ); - tbl.glVertexAttribPointer( i, 4, GL_FLOAT, GL_FALSE, maxVertexAttribs * 16, (GLubyte *)NULL + i * 16 ); + tbl.glVertexAttribPointer( i, 4, GL_FLOAT, GL_FALSE, max_vertex_attribs * sizeof(Float4), (GLubyte *)NULL + i * sizeof(Float4) ); } tbl.glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, immQuadsVbo ); GLushort quadIndexes[ REGAL_IMMEDIATE_BUFFER_SIZE * 3 / 2 ]; - for ( GLushort i = 0; i < REGAL_IMMEDIATE_BUFFER_SIZE / 4; i++ ) { + const size_t n = array_size( quadIndexes ); + RegalAssert( n == (REGAL_IMMEDIATE_BUFFER_SIZE * 3 / 2) ); + for ( GLushort i = 0; i < static_cast(n / 6); i++ ) + { + RegalAssertArrayIndex( quadIndexes, (i*6+5) ); quadIndexes[ i * 6 + 0 ] = i * 4 + 0; // first triangle quadIndexes[ i * 6 + 1 ] = i * 4 + 1; quadIndexes[ i * 6 + 2 ] = i * 4 + 2; @@ -778,9 +843,9 @@ struct Iff // The initial texture coordinates are (s; t; r; q) = (0; 0; 0; 1) // for each texture coordinate set. - for( catIndex = 0; catIndex < REGAL_EMU_MAX_TEXTURE_UNITS; catIndex++ ) { + for (catIndex = 0; catIndex < REGAL_EMU_MAX_TEXTURE_UNITS; catIndex++) Attr<4>( &ctx, AttrIndex( RFF2A_TexCoord ), 0, 0, 0, 1 ); - } + catIndex = 0; // The initial current normal has coordinates (0; 0; 1). @@ -804,11 +869,11 @@ struct Iff void DeleteVertexArrays( RegalContext * ctx, GLsizei n, const GLuint * arrays ) { RegalAssert( ctx != NULL ); - for( GLsizei i = 0; i < n; i++ ) { + for (GLsizei i = 0; i < n; i++) + { GLuint name = arrays[ i ]; - if( name != immVao ) { + if (name != immVao) ctx->dispatcher.emulation.glDeleteVertexArrays( 1, &name ); - } } } @@ -820,19 +885,25 @@ struct Iff return ctx->dispatcher.emulation.glIsVertexArray( name ); } - void ShadowVao( RegalContext *ctx, GLuint vao ) { + void ShadowVao( RegalContext *ctx, GLuint vao ) + { immShadowVao = vao; - if( immActive == false ) { + if (immActive == false) BindVertexArray( ctx, vao ); - } } - void ShadowClientActiveTexture( GLenum unit ) { - catIndex = unit - GL_TEXTURE0; + void ShadowClientActiveTexture( GLenum texture ) + { + if ( (texture - GL_TEXTURE0) < REGAL_EMU_MAX_TEXTURE_COORDS) + catIndex = texture - GL_TEXTURE0; + else + Warning( "Client active texture out of range: ", Token::GLtextureToString(texture), " > ", Token::GLtextureToString(GL_TEXTURE0 + REGAL_EMU_MAX_TEXTURE_COORDS - 1)); } - void Begin( RegalContext * ctx, GLenum mode ) { - if( immActive == false ) { + void Begin( RegalContext * ctx, GLenum mode ) + { + if (immActive == false) + { immActive = true; ctx->dispatcher.emulation.glBindVertexArray( immVao ); BindVertexArray( ctx, immVao ); // keep ffn current @@ -842,13 +913,15 @@ struct Iff immPrim = mode; } - void End( RegalContext * ctx ) { + void End( RegalContext * ctx ) + { Flush( ctx ); } - void RestoreVao( RegalContext * ctx ) { - if( immActive == true ) { - //RegalOutput( "Restoring vao to %d in Iff\n", immShadowVao ); + void RestoreVao( RegalContext * ctx ) + { + if (immActive) + { ctx->dispatcher.emulation.glBindVertexArray( immShadowVao ); BindVertexArray( ctx, immShadowVao ); immActive = false; @@ -857,16 +930,22 @@ struct Iff void Flush( RegalContext * ctx ) { - if (immCurrent>0) { // Do nothing for empty buffer + if (immCurrent>0) // Do nothing for empty buffer + { DispatchTableGL &tbl = ctx->dispatcher.emulation; - tbl.glBufferData( GL_ARRAY_BUFFER, immCurrent * sizeof( Attributes ), immArray, GL_DYNAMIC_DRAW ); - if( ( ctx->info->core == true || ctx->info->es2 ) && immPrim == GL_QUADS ) { + tbl.glBufferData( GL_ARRAY_BUFFER, immCurrent * max_vertex_attribs * sizeof(Float4), immArray, GL_DYNAMIC_DRAW ); + if (( ctx->info->core == true || ctx->info->es2 ) && immPrim == GL_QUADS) + { tbl.glDrawElements( GL_TRIANGLES, ( immCurrent / 4 ) * 6, GL_UNSIGNED_SHORT, 0 ); - } else { + } + else + { GLenum derivedPrim = immPrim; GLsizei derivedCount = immCurrent; - if( ( ctx->info->core == true || ctx->info->es2 ) ) { - switch( immPrim ) { + if (( ctx->info->core == true || ctx->info->es2 )) + { + switch( immPrim ) + { case GL_POLYGON: derivedPrim = GL_TRIANGLE_FAN; break; @@ -883,14 +962,17 @@ struct Iff } } - void Provoke( RegalContext * ctx ) { - memcpy( immArray + immCurrent * maxVertexAttribs * 16, &immVab.attr[0].x, maxVertexAttribs * 16 ); + void Provoke( RegalContext * ctx ) + { + memcpy( immArray + immCurrent * max_vertex_attribs * sizeof(Float4), &immVab[0].x, max_vertex_attribs * sizeof(Float4) ); immCurrent++; - if ( immCurrent >= REGAL_IMMEDIATE_BUFFER_SIZE ) { + if ( immCurrent >= ((REGAL_IMMEDIATE_BUFFER_SIZE * REGAL_EMU_MAX_VERTEX_ATTRIBS) / max_vertex_attribs) ) + { Flush( ctx ); int restartVerts = 0; - switch( immPrim ) { + switch( immPrim ) + { case GL_QUADS: restartVerts = REGAL_IMMEDIATE_BUFFER_SIZE % 4; break; @@ -918,69 +1000,77 @@ struct Iff if (immPrim==GL_TRIANGLE_FAN) { - memcpy( immArray + maxVertexAttribs * 16, immArray + (REGAL_IMMEDIATE_BUFFER_SIZE - 1) * maxVertexAttribs * 16, maxVertexAttribs * 16); + memcpy( immArray + max_vertex_attribs * sizeof(Float4), immArray + (REGAL_IMMEDIATE_BUFFER_SIZE - 1) * max_vertex_attribs * sizeof(Float4), max_vertex_attribs * sizeof(Float4)); immCurrent = 2; } else { int offset = REGAL_IMMEDIATE_BUFFER_SIZE - restartVerts; - memcpy( immArray, immArray + offset * maxVertexAttribs * 16, restartVerts * maxVertexAttribs * 16); + memcpy( immArray, immArray + offset * max_vertex_attribs * sizeof(Float4), restartVerts * max_vertex_attribs * sizeof(Float4)); immCurrent = restartVerts; } } } - template void Attribute( RegalContext * ctx, GLuint idx, const T * v ) { - if( idx >= maxVertexAttribs ) { + template void Attribute( RegalContext * ctx, GLuint idx, const T * v ) + { + if (idx >= max_vertex_attribs) + { // FIXME: set an error return; } - Float4 & a = immVab.attr[ idx ]; + RegalAssertArrayIndex( immVab, idx ); + Float4 & a = immVab[ idx ]; a.x = ToFloat( v[0] ); a.y = N > 1 ? ToFloat( v[1] ) : 0.0f; a.z = N > 2 ? ToFloat( v[2] ) : 0.0f; a.w = N > 3 ? ToFloat( v[3] ) : 1.0f; ffstate.uniform.ver = ffstate.uniform.vabVer = ver.Update(); - if( idx == immProvoking ) { + if (idx == immProvoking) Provoke( ctx ); - } } - template void Attr( RegalContext *ctx, GLuint idx, T x, T y = 0, T z = 0, T w = 1 ) { + template void Attr( RegalContext *ctx, GLuint idx, T x, T y = 0, T z = 0, T w = 1 ) + { T v[4] = { x, y, z, w }; Attribute( ctx, idx,v ); } - template void AttrN( RegalContext *ctx, GLuint idx, T x, T y = 0, T z = 0, T w = 1 ) { + template void AttrN( RegalContext *ctx, GLuint idx, T x, T y = 0, T z = 0, T w = 1 ) + { T v[4] = { x, y, z, w }; Attribute( ctx, idx, v ); } - template void Attr( RegalContext *ctx, GLuint idx, const T * v ) { + + template void Attr( RegalContext *ctx, GLuint idx, const T * v ) + { Attribute( ctx, idx, v ); } - template void AttrN( RegalContext *ctx, GLuint idx, const T * v ) { + template void AttrN( RegalContext *ctx, GLuint idx, const T * v ) + { Attribute( ctx, idx, v ); } - GLuint AttrIndex( RegalFixedFunctionAttrib attr, int cat = -1 ) const { - if( attr < RFF2A_TexCoord ) { + GLuint AttrIndex( RegalFixedFunctionAttrib attr, int cat = -1 ) const + { + if (attr < RFF2A_TexCoord) + { + RegalAssertArrayIndex( ffAttrMap, attr ); return ffAttrMap[ attr ]; } - if( cat < 0 ) { + if (cat < 0) cat = catIndex; - } - if( attr == RFF2A_TexCoord && GLuint(cat) < ffAttrNumTex ) { + if (attr == RFF2A_TexCoord && GLuint(cat) < ffAttrNumTex) return ffAttrTexBegin + cat; - } return ~0u; } - // fixed function - enum CompareFunc { + enum CompareFunc + { CF_Invalid, CF_Never, CF_Less, @@ -992,7 +1082,8 @@ struct Iff CF_Always }; - enum TexturePriority { + enum TexturePriority + { TP_1D = 0, TP_2D = 1, TP_Rect = 2, @@ -1000,7 +1091,8 @@ struct Iff TP_CubeMap = 4 }; - enum TextureTargetBitfield { + enum TextureTargetBitfield + { TT_None = 0, TT_1D = 1< what should this be really? { - memset(this,0,sizeof(TextureUnit)); - env = TextureEnv(); } - TextureUnit(const TextureUnit &other) - { - memcpy(this,&other,sizeof(TextureUnit)); - } - - TextureUnit &operator=(const TextureUnit &other) - { - if (&other!=this) - memcpy(this,&other,sizeof(TextureUnit)); - return *this; - } - - GLubyte ttb; - GLint fmt; - TextureEnv env; + TextureEnv env; + TextureTargetBitfield ttb; + GLenum fmt; }; - struct Version { + struct Version + { Version() - : val( 0 ) - , updated( false ) - {} - GLuint64 Current() const { + : val( 0 ) + , updated( false ) + { + } + + GLuint64 Current() const + { return val; } - GLuint64 Update() { - if( updated == false ) { + + GLuint64 Update() + { + if (updated == false) + { val++; updated = true; } return val; } - void Reset() { + + void Reset() + { updated = false; } + GLuint64 val; bool updated; }; - struct State { - + struct State + { struct Texgen { Texgen() + : mode(TG_EyeLinear) + , enable(GL_FALSE) { - memset(this, 0, sizeof(Texgen)); - mode = TG_EyeLinear; } - Texgen(const Texgen &other) - { - memcpy(this, &other, sizeof(Texgen)); - } - - Texgen &operator=(const Texgen &other) - { - if (&other!=this) - memcpy(this, &other, sizeof(Texgen)); - return *this; - } - - GLboolean enable; TexgenMode mode; + GLboolean enable; }; struct TexgenUniform { TexgenUniform() + : objVer(0) + , eyeVer(0) + , obj( 0, 0, 0, 0 ) + , eye( 0, 0, 0, 0 ) { - memset(this, 0, sizeof(TexgenUniform)); } - Float4 obj; - Float4 eye; + GLuint64 objVer; GLuint64 eyeVer; + Float4 obj; + Float4 eye; }; struct Texture { Texture() + : enables(0) + , useMatrix(false) + , pad1(false) + , pad2(false) + , pad3(false) { - memset(this, 0, sizeof(Texture)); - texgen[0] = texgen[1] = texgen[2] = texgen[3] = Texgen(); - unit = TextureUnit(); } - Texture(const Texture &other) - { - memcpy(this, &other, sizeof(Texture)); - } - - Texture &operator=(const Texture &other) - { - if (&other!=this) - memcpy(this, &other, sizeof(Texture)); - return *this; - } - - GLubyte enables; - bool useMatrix; - Texgen texgen[4]; + Texgen texgen[4]; TextureUnit unit; + GLuint enables; + bool useMatrix; + bool pad1; + bool pad2; + bool pad3; }; - struct TextureUniform { + struct TextureUniform + { TextureUniform() { texgen[0].obj = texgen[0].eye = Float4( 1, 0, 0, 0 ); texgen[1].obj = texgen[1].eye = Float4( 0, 1, 0, 0 ); } + TexgenUniform texgen[4]; }; - struct AlphaTest { + struct AlphaTest + { AlphaTest() + : comp(CF_Always) + , enable(false) { - memset( this, 0, sizeof( *this ) ); - enable = false; - comp = CF_Always; - } - AlphaTest( const AlphaTest & cpy ) { - memcpy( this, &cpy, sizeof( *this) ); } - GLboolean enable; CompareFunc comp; + GLboolean enable; }; - struct AlphaTestUniform { + struct AlphaTestUniform + { AlphaTestUniform() - : alphaRef( 0 ) - , ver( 0 ) - {} + : ver( 0 ) + , alphaRef( 0 ) + { + } + + GLuint64 ver; GLfloat alphaRef; - GLuint64 ver; }; - struct Clip { - Clip() - : enable( false ) - { - } - bool enable; - }; - - struct ClipUniform { + struct ClipUniform + { ClipUniform() - : plane( 0, 0, 0, 0 ) - , ver( 0 ) - {} - Float4 plane; - GLuint64 ver; - }; - - struct Fog { - Fog() + : ver( 0 ) + , plane( 0, 0, 0, 0 ) { - memset( this, 0, sizeof( *this ) ); - enable = false; - useDepth = true; - mode = FG_Exp; } - Fog( const Fog & cpy ) { - memcpy( this, &cpy, sizeof( *this) ); - } - bool enable; - bool useDepth; - FogMode mode : 4; + + GLuint64 ver; + Float4 plane; }; - struct FogUniform { + struct Fog + { + Fog() + : mode(FG_Exp) + , enable(false) + , useDepth(true) + { + } + + FogMode mode; + bool enable; + bool useDepth; + }; + + struct FogUniform + { FogUniform() - : ver( 0 ) + : ver( 0 ) { params[0] = Float4( 1, 0, 1, 0 ); params[1] = Float4( 0, 0, 0, 0 ); } - Float4 params[2]; // .x = density, .y = start, .z = end, .w = d/c + GLuint64 ver; + Float4 params[2]; // .x = density, .y = start, .z = end, .w = d/c }; - struct Light { + struct Light + { Light() + : enable(false) + , spotlight(false) + , attenuate(false) + , local(false) { - memset( this, 0, sizeof( *this ) ); - enable = false; - spotlight = false; - attenuate = false; - local = false; - } - Light( const Light & cpy ) { - memcpy( this, &cpy, sizeof( *this) ); } bool enable; @@ -1334,37 +1403,46 @@ struct Iff bool local; }; - struct LightUniform { + struct LightUniform + { LightUniform() - : position( 0, 0, 1, 0 ) - , spotDirection( 0.0f, 0.0f, -1.0f, 180.0f ) - , attenuation( 1, 0, 0, 0 ) - , ver( 0 ) - {} - Float4 ambient; - Float4 diffuse; - Float4 specular; - Float4 position; - Float4 spotDirection; // spotCutoff is in .w - Float4 attenuation; // spotExponent is in .w + : ver( 0 ) + , ambient( 0, 0, 0, 0 ) + , diffuse( 0, 0, 0, 0 ) + , specular( 0, 0, 0, 0 ) + , position( 0, 0, 1, 0 ) + , spotDirection( 0.0f, 0.0f, -1.0f, 180.0f ) + , attenuation( 1, 0, 0, 0 ) + { + } + GLuint64 ver; + Float4 ambient; + Float4 diffuse; + Float4 specular; + Float4 position; + Float4 spotDirection; // spotCutoff is in .w + Float4 attenuation; // spotExponent is in .w }; - struct MaterialUniform { + struct MaterialUniform + { MaterialUniform() - : ambient( 0.2f, 0.2f, 0.2f, 1.0f ) - , diffuse( 0.8f, 0.8f, 0.8f, 1.0f ) - , specular( 0, 0, 0, 1 ) - , emission( 0, 0, 0, 1 ) - , shininess( 0, 0, 0, 0 ) - , ver( 0 ) - {} - Float4 ambient; - Float4 diffuse; - Float4 specular; - Float4 emission; - Float4 shininess; // shininess is in .x + : ver( 0 ) + , ambient( 0.2f, 0.2f, 0.2f, 1.0f ) + , diffuse( 0.8f, 0.8f, 0.8f, 1.0f ) + , specular( 0, 0, 0, 1 ) + , emission( 0, 0, 0, 1 ) + , shininess( 0, 0, 0, 0 ) + { + } + GLuint64 ver; + Float4 ambient; + Float4 diffuse; + Float4 specular; + Float4 emission; + Float4 shininess; // shininess is in .x }; // Iff::State::Store @@ -1373,91 +1451,93 @@ struct Iff { Store() { - memset(this, 0, sizeof(Store)); + // Using memset here is potentially evil since it only works + // on POD and clobbers any vtables & etc. See: + // + // http://stackoverflow.com/questions/2481654/memset-for-initialization-in-c + // + // But we use every byte of Store() for the hash computation, + // including any padding added by the compiler, so we need to + // make sure that it all starts with the same initial value so... - // all the booleans and uints want zero initialization anyway, so don't bother doing them individually - alphaTest = AlphaTest(); - fog = Fog(); - colorMaterialTarget0 = colorMaterialTarget1 = CM_AmbientAndDiffuse; - for (int ii=0; ii= REGAL_EMU_IFF_TEXTURE_UNITS ) { + void SetTexInfo( Version & ver, GLuint activeTex, TextureUnit & unit ) + { + if (activeTex >= REGAL_EMU_MAX_TEXTURE_UNITS) return; - } + raw.tex[ activeTex ].unit = unit; raw.ver = ver.Update(); } @@ -1481,44 +1562,56 @@ struct Iff void SetAlphaFunc( Iff * ffn, CompareFunc comp, GLfloat ref ); void SetClip( Iff * ffn, GLenum plane, const GLfloat * equation ); - TextureTargetBitfield GetTextureEnable( int unit ) const { + TextureTargetBitfield GetTextureEnable( size_t unit ) const + { return TextureTargetBitfield( ( processed.tex[unit].enables ) ); } - GLuint64 Ver() const { + inline GLuint64 Ver() const + { return uniform.ver; } - GLubyte HighestPriorityTextureEnable( GLubyte enables ) { - for( int i = TP_CubeMap; i >= 0; i-- ) { - if( enables & ( 1 << i ) ) { + GLuint HighestPriorityTextureEnable( GLuint enables ) + { + for (int i = TP_CubeMap; i >= 0; i--) + { + if (enables & ( 1 << i )) return static_cast(1 << i); - } } return 0; } + void Process( Iff * ffn ); }; - struct MatrixStack { - struct El { + struct MatrixStack + { + struct El + { El() - : ver( 1 ) - {} - r3::Matrix4f mat; + : ver( 1 ) + { + } + GLuint64 ver; + r3::Matrix4f mat; }; - MatrixStack() { + + MatrixStack() + { stack.push_back( El() ); } - void Push() { + + void Push() + { RegalAssert( stack.size() < REGAL_FIXED_FUNCTION_MATRIX_STACK_DEPTH ); - if( stack.size() < REGAL_FIXED_FUNCTION_MATRIX_STACK_DEPTH ) { + if (stack.size() < REGAL_FIXED_FUNCTION_MATRIX_STACK_DEPTH) stack.push_back( stack.back() ); - } } - void Pop() { + void Pop() + { /* The stack size warning messages ought to be the responsibility of the debug layer, rather than emulation. (Opt-in only) Should emulation set an error in the underflow situation here? */ @@ -1528,16 +1621,43 @@ struct Iff stack.pop_back(); } - r3::Matrix4f &Top() { RegalAssert( stack.size() ); return stack.back().mat; } - const r3::Matrix4f &Top() const { RegalAssert( stack.size() ); return stack.back().mat; } + r3::Matrix4f &Top() + { + RegalAssert( stack.size() ); + return stack.back().mat; + } + const r3::Matrix4f &Top() const + { + RegalAssert( stack.size() ); + return stack.back().mat; + } - GLuint64 &Ver() { RegalAssert( stack.size() ); return stack.back().ver; } - const GLuint64 &Ver() const { RegalAssert( stack.size() ); return stack.back().ver; } + GLuint64 &Ver() + { + RegalAssert( stack.size() ); + return stack.back().ver; + } + const GLuint64 &Ver() const + { + RegalAssert( stack.size() ); + return stack.back().ver; + } - std::size_t size() const { return stack.size(); } + std::size_t size() const + { + return stack.size(); + } - El &operator[](const std::size_t i) { RegalAssert( stack.size() ); return stack[i]; } - const El &operator[](const std::size_t i) const { RegalAssert( stack.size() ); return stack[i]; } + El &operator[](const std::size_t i) + { + RegalAssert( stack.size() ); + return stack[i]; + } + const El &operator[](const std::size_t i) const + { + RegalAssert( stack.size() ); + return stack[i]; + } private: std::vector stack; @@ -1547,74 +1667,36 @@ struct Iff struct Program { - // Iff::Program::UniformInfo struct UniformInfo { - UniformInfo(const GLint s = -1, const GLuint64 v = 0) + UniformInfo(GLuint64 v = 0, GLint s = -1) + : ver(v) + , slot(s) { - memset(this, 0, sizeof(UniformInfo)); - slot = s; - ver = v; } - UniformInfo(const UniformInfo &other) - { - memcpy(this, &other, sizeof(UniformInfo)); - } - - UniformInfo &operator=(const UniformInfo &other) - { - if (&other!=this) - memcpy(this, &other, sizeof(UniformInfo)); - return *this; - } - - GLint slot; GLuint64 ver; + GLint slot; }; - // Iff::Program + // Iff::Program Program() - : pg(0), - uniforms(), - store() + : ver(0) + , pg(0) + , vs(0) + , fs(0) + , progcount(0) { - // Clear plain-old-data (POD) memory - memset(this, 0, reinterpret_cast(&this->uniforms)-reinterpret_cast(this)); } - Program(const Program &other) - : pg(0), - uniforms(other.uniforms), - store(other.store) - { - // Copy plain-old-data (POD) memory - memcpy(this, &other, reinterpret_cast(&this->uniforms)-reinterpret_cast(this)); - } - - Program &operator=(const Program &other) - { - if (&other!=this) - { - // Copy plain-old-data (POD) memory - memcpy(this, &other, reinterpret_cast(&this->uniforms)-reinterpret_cast(this)); - uniforms = other.uniforms; - store = other.store; - } - return *this; - } - - // POD - - GLuint pg; - GLuint vs, fs; GLuint64 ver; - int progcount; - - // non-POD + GLuint pg; + GLuint vs; + GLuint fs; + int progcount; std::map< RegalFFUniformEnum, UniformInfo> uniforms; State::Store store; @@ -1629,12 +1711,12 @@ struct Iff MatrixStack modelview; MatrixStack projection; - MatrixStack texture[ REGAL_EMU_IFF_TEXTURE_UNITS ]; + MatrixStack texture[ REGAL_EMU_MAX_TEXTURE_UNITS ]; GLenum shadowMatrixMode; - TextureUnit textureUnit[ REGAL_EMU_IFF_TEXTURE_UNITS ]; - Float4 textureEnvColor[ REGAL_EMU_IFF_TEXTURE_UNITS ]; - GLuint64 textureEnvColorVer[ REGAL_EMU_IFF_TEXTURE_UNITS ]; + TextureUnit textureUnit[ REGAL_EMU_MAX_TEXTURE_UNITS ]; + Float4 textureEnvColor[ REGAL_EMU_MAX_TEXTURE_UNITS ]; + GLuint64 textureEnvColorVer[ REGAL_EMU_MAX_TEXTURE_UNITS ]; GLuint textureBinding[ REGAL_EMU_MAX_TEXTURE_UNITS]; GLuint shadowActiveTextureIndex; GLuint activeTextureIndex; @@ -1647,12 +1729,13 @@ struct Iff Version ver; State ffstate; - Program ffprogs[ 1 << REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE_BITS ]; + Program ffprogs[ REGAL_FIXED_FUNCTION_PROGRAM_CACHE_SIZE ]; - shared_map textureObjToFmt; + shared_map textureObjToFmt; // Program uniforms are tied to context state, so we cannot share IFF // programs, however we share user programs in general. + std::map fmtmap; std::map shaderTypeMap; std::map shprogmap; @@ -1665,88 +1748,104 @@ struct Iff void InitFixedFunction(RegalContext &ctx); - void PreDraw( RegalContext * ctx ) { - if( programPipeline != 0 ) { - // FIXME: Eventually will need to handle empty or partially populated PPO - return; - } + void PreDraw( RegalContext * ctx ) + { + if (programPipeline) + return; // FIXME: Eventually will need to handle empty or partially populated PPO + ver.Reset(); - if( program != 0 ) { + if (program) UseShaderProgram( ctx ); - } else { + else UseFixedFunctionProgram( ctx ); - } } - void SetCurrentMatrixStack( GLenum mode ) { - switch( mode ) { - case GL_MODELVIEW: currMatrixStack = &modelview; break; - case GL_PROJECTION: currMatrixStack = &projection; break; + void SetCurrentMatrixStack( GLenum mode ) + { + switch( mode ) + { + case GL_MODELVIEW: + currMatrixStack = &modelview; + break; + case GL_PROJECTION: + currMatrixStack = &projection; + break; case GL_TEXTURE: - if( activeTextureIndex > GLuint( REGAL_EMU_IFF_TEXTURE_UNITS - 1 ) ) { - break; - } - currMatrixStack = &texture[ activeTextureIndex ]; + if (activeTextureIndex < GLuint( REGAL_EMU_MAX_TEXTURE_UNITS )) + currMatrixStack = &texture[ activeTextureIndex ]; break; case GL_TEXTURE0: case GL_TEXTURE1: case GL_TEXTURE2: - case GL_TEXTURE3: { + case GL_TEXTURE3: + { GLuint idx = mode - GL_TEXTURE0; - if( idx > GLuint( REGAL_EMU_IFF_TEXTURE_UNITS - 1 ) ) { + if (idx > GLuint( REGAL_EMU_MAX_TEXTURE_UNITS - 1 )) break; - } currMatrixStack = &texture[ idx ]; - break; } + break; default: - RegalAssert( true && "WTF." ); + RegalAssert( true && "WTF?" ); break; } } - bool ShadowMatrixMode( GLenum mode ) { + bool ShadowMatrixMode( GLenum mode ) + { shadowMatrixMode = mode; return true; } - bool ShadowActiveTexture( GLenum tex ) { - shadowActiveTextureIndex = tex - GL_TEXTURE0; - return false; + void ShadowActiveTexture( GLenum texture ) + { + if (validTextureEnum(texture)) + shadowActiveTextureIndex = texture - GL_TEXTURE0; } - bool ShadowEnable( GLenum cap ) { + bool ShadowEnable( GLenum cap ) + { return EnableIndexed( cap, shadowActiveTextureIndex ); } - bool ShadowDisable( GLenum cap ) { + bool ShadowDisable( GLenum cap ) + { return DisableIndexed( cap, shadowActiveTextureIndex ); } - bool EnableIndexed( GLenum cap, GLuint index ) { + bool EnableIndexed( GLenum cap, GLuint index ) + { + if (index >= GLuint( REGAL_EMU_MAX_TEXTURE_UNITS )) + return false; activeTextureIndex = index; bool ret = ffstate.SetEnable( this, true, cap ); return ret; } - bool DisableIndexed( GLenum cap, GLuint index ) { + bool DisableIndexed( GLenum cap, GLuint index ) + { + if (index >= GLuint( REGAL_EMU_MAX_TEXTURE_UNITS )) + return false; activeTextureIndex = index; bool ret = ffstate.SetEnable( this, false, cap ); return ret; } - bool ShadowUseProgram( GLuint prog ) { + bool ShadowUseProgram( GLuint prog ) + { program = prog; return prog == 0; // pass the call along only if it's non-zero } - bool ShadowBindProgramPipeline( GLuint progPipeline ) { + bool ShadowBindProgramPipeline( GLuint progPipeline ) + { programPipeline = progPipeline; return false; // always pass this through since we're not emulating it } void ShadowMultiTexBinding( GLenum texunit, GLenum target, GLuint obj ); - void ShadowTexBinding( GLenum target, GLuint obj ) { + void ShadowTexBinding( GLenum target, GLuint obj ) + { ShadowMultiTexBinding( GL_TEXTURE0 + shadowActiveTextureIndex, target, obj ); } @@ -1756,121 +1855,162 @@ struct Iff void TexEnv( GLenum texunit, GLenum target, GLenum pname, const GLfloat *v ); void TexEnv( GLenum texunit, GLenum target, GLenum pname, const GLint *v ); - void TexEnv( GLenum texunit, GLenum target, GLenum pname, GLfloat v ) { TexEnv( texunit, target, pname, &v ); } - void TexEnv( GLenum texunit, GLenum target, GLenum pname, GLint v ) { TexEnv( texunit, target, pname, &v ); } + void TexEnv( GLenum texunit, GLenum target, GLenum pname, GLfloat v ) + { + TexEnv( texunit, target, pname, &v ); + } + void TexEnv( GLenum texunit, GLenum target, GLenum pname, GLint v ) + { + TexEnv( texunit, target, pname, &v ); + } template - void TexEnv( GLenum target, GLenum pname, T v ) { TexEnv( GL_TEXTURE0 + shadowActiveTextureIndex, target, pname, v ); } + void TexEnv( GLenum target, GLenum pname, T v ) + { + TexEnv( GL_TEXTURE0 + shadowActiveTextureIndex, target, pname, v ); + } template - bool GetTexEnv( GLenum target, GLenum pname, T * params ) { - if( target != GL_TEXTURE_ENV ) { + bool GetTexEnv( GLenum target, GLenum pname, T * params ) + { + if (target != GL_TEXTURE_ENV) return false; - } - switch( pname ) { - case GL_TEXTURE_ENV_MODE: { - RegalAssert(activeTextureIndex(textureUnit[ activeTextureIndex ].env.mode) < array_size( texenvModeGL )); *params = static_cast(texenvModeGL[ textureUnit[ activeTextureIndex ].env.mode ]); - break; } - case GL_TEXTURE_ENV_COLOR: { - RegalAssert(activeTextureIndex(c.mode) < array_size(texenvCombineGL)); *params = static_cast(texenvCombineGL[ c.mode ]); - break; } + break; case GL_SOURCE0_RGB: case GL_SOURCE1_RGB: case GL_SOURCE2_RGB: case GL_SOURCE0_ALPHA: case GL_SOURCE1_ALPHA: - case GL_SOURCE2_ALPHA: { - RegalAssert(activeTextureIndex 3 ) { + if ( idx > 3 ) + { isRgb = false; idx = pname - GL_SOURCE0_ALPHA; } TexenvCombineState & c = (isRgb ? - textureUnit[ activeTextureIndex ].env.rgb : - textureUnit[ activeTextureIndex ].env.a); + textureUnit[ activeTextureIndex ].env.rgb : + textureUnit[ activeTextureIndex ].env.a); TexenvCombineSrc src = c.src0; switch ( idx ) { - case 0: src = c.src0; break; - case 1: src = c.src1; break; - case 2: src = c.src2; break; - default: break; + case 0: + src = c.src0; + break; + case 1: + src = c.src1; + break; + case 2: + src = c.src2; + break; + default: + break; } + RegalAssert(static_cast(src) < array_size(texenvCombineSrcGL)); *params = static_cast(texenvCombineSrcGL[ src ]); - break; } + break; case GL_OPERAND0_RGB: case GL_OPERAND1_RGB: case GL_OPERAND2_RGB: case GL_OPERAND0_ALPHA: case GL_OPERAND1_ALPHA: - case GL_OPERAND2_ALPHA: { - RegalAssert(activeTextureIndex 3 ) { + if (idx > 3) + { isRgb = false; idx = pname - GL_OPERAND0_ALPHA; } TexenvCombineState & c = (isRgb ? - textureUnit[ activeTextureIndex ].env.rgb : - textureUnit[ activeTextureIndex ].env.a); + textureUnit[ activeTextureIndex ].env.rgb : + textureUnit[ activeTextureIndex ].env.a); TexenvCombineOp op = c.op0; switch ( idx ) { - case 0: op = c.op0; break; - case 1: op = c.op1; break; - case 2: op = c.op2; break; - default: break; + case 0: + op = c.op0; + break; + case 1: + op = c.op1; + break; + case 2: + op = c.op2; + break; + default: + break; } + RegalAssert(static_cast(op) < array_size(texenvCombineOpGL)); *params = static_cast(texenvCombineOpGL[ op ]); - break; } + break; case GL_RGB_SCALE: - case GL_ALPHA_SCALE: { - RegalAssert(activeTextureIndex(c.scale); - break; } + break; default: return false; } return true; } - void ShadeModel( GLenum mode ) { + void ShadeModel( GLenum mode ) + { State::Store & r = ffstate.raw; - switch( mode ) { + switch( mode ) + { case GL_FLAT: - if ( r.shadeModelFlat == false ) { + if (!r.shadeModelFlat) + { r.shadeModelFlat = true; r.ver = ver.Update(); } break; case GL_SMOOTH: - if ( r.shadeModelFlat == true ) { + if (r.shadeModelFlat) + { r.shadeModelFlat = false; r.ver = ver.Update(); } @@ -1878,75 +2018,133 @@ struct Iff } } - template void Light( GLenum light, GLenum pname, const T param ) { + template void Light( GLenum light, GLenum pname, const T param ) + { int comp = 4; - switch( pname ) { - case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: case GL_POSITION: break; - case GL_SPOT_DIRECTION: comp = 3; break; - case GL_SPOT_EXPONENT: case GL_SPOT_CUTOFF: - case GL_CONSTANT_ATTENUATION: case GL_LINEAR_ATTENUATION: - case GL_QUADRATIC_ATTENUATION: comp = 1; break; - default: return; + switch( pname ) + { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_POSITION: + break; + case GL_SPOT_DIRECTION: + comp = 3; + break; + case GL_SPOT_EXPONENT: + case GL_SPOT_CUTOFF: + case GL_CONSTANT_ATTENUATION: + case GL_LINEAR_ATTENUATION: + case GL_QUADRATIC_ATTENUATION: + comp = 1; + break; + default: + return; } GLfloat v[4]; - for( int i = 0; i < comp; i++ ) v[ i ] = RFFToFloatN( i, param ); + for (int i = 0; i < comp; i++) + v[ i ] = RFFToFloatN( i, param ); ffstate.SetLight( this, light, pname, v ); } - template void Material( GLenum face, GLenum pname, const T param ) { + template void Material( GLenum face, GLenum pname, const T param ) + { int comp = 4; - switch( pname ) { - case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: - case GL_AMBIENT_AND_DIFFUSE: case GL_EMISSION: break; - case GL_SHININESS: comp = 1; break; - default: return; + switch( pname ) + { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_AMBIENT_AND_DIFFUSE: + case GL_EMISSION: + break; + case GL_SHININESS: + comp = 1; + break; + default: + return; } GLfloat v[4]; - for( int i = 0; i < comp; i++ ) v[ i ] = RFFToFloatN( i, param ); + for (int i = 0; i < comp; i++) + v[ i ] = RFFToFloatN( i, param ); ffstate.SetMaterial( this, face, pname, v ); } - template void GetMaterial( GLenum face, GLenum pname, T *params ) { - int comp = 4; - switch( pname ) { - case GL_AMBIENT: case GL_DIFFUSE: case GL_SPECULAR: - case GL_AMBIENT_AND_DIFFUSE: case GL_EMISSION: break; - case GL_SHININESS: comp = 1; break; - default: return; + template void GetMaterial( GLenum face, GLenum pname, T *params ) + { + size_t comp = 4; + switch( pname ) + { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_EMISSION: + break; + case GL_SHININESS: + comp = 1; + break; + default: + return; } GLfloat v[4]; ffstate.GetMaterial( this, face, pname, v ); - for( int i = 0; i < comp; i++ ) params[i] = static_cast(v[i]); + for (size_t i = 0; i < comp; i++) + params[i] = static_cast(v[i]); } - template void LightModel( GLenum pname, const T param ) { + template void LightModel( GLenum pname, const T param ) + { State::Store & r = ffstate.raw; State::StoreUniform & u = ffstate.uniform; - switch( pname ) { - case GL_LIGHT_MODEL_AMBIENT: { + switch( pname ) + { + case GL_LIGHT_MODEL_AMBIENT: + { GLfloat *v = & u.lightModelAmbient.x; - for( int i = 0; i < 4; i++ ) v[i] = RFFToFloatN( i, param ); - break; + for (int i = 0; i < 4; i++) + v[i] = RFFToFloatN( i, param ); } - case GL_LIGHT_MODEL_LOCAL_VIEWER: r.lightModelLocalViewer = RFFToFloat( 0, param ) != 0.0f; break; - case GL_LIGHT_MODEL_TWO_SIDE: r.lightModelTwoSide = RFFToFloat( 0, param ) != 0.0f; break; - case GL_LIGHT_MODEL_COLOR_CONTROL: r.lightModelSeparateSpecular = RFFToFloat(0, param) == GL_SEPARATE_SPECULAR_COLOR; break; - default: return; + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + r.lightModelLocalViewer = RFFToFloat( 0, param ) != 0.0f; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + r.lightModelTwoSide = RFFToFloat( 0, param ) != 0.0f; + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + r.lightModelSeparateSpecular = RFFToFloat(0, param) == GL_SEPARATE_SPECULAR_COLOR; + break; + default: + return; } u.ver = r.ver = ver.Update(); } - void ColorMaterial( GLenum face, GLenum mode ) { + void ColorMaterial( GLenum face, GLenum mode ) + { ColorMaterialMode m; - switch( mode ) { - case GL_EMISSION: m = CM_Emission; break; - case GL_AMBIENT: m = CM_Ambient; break; - case GL_DIFFUSE: m = CM_Diffuse; break; - case GL_SPECULAR: m = CM_Specular; break; - case GL_AMBIENT_AND_DIFFUSE: m = CM_AmbientAndDiffuse; break; - default: return; + switch( mode ) + { + case GL_EMISSION: + m = CM_Emission; + break; + case GL_AMBIENT: + m = CM_Ambient; + break; + case GL_DIFFUSE: + m = CM_Diffuse; + break; + case GL_SPECULAR: + m = CM_Specular; + break; + case GL_AMBIENT_AND_DIFFUSE: + m = CM_AmbientAndDiffuse; + break; + default: + return; } - switch( face ) { + switch( face ) + { case GL_FRONT: ffstate.raw.colorMaterialTarget0 = m; ffstate.raw.colorMaterialTarget1 = CM_None; @@ -1965,40 +2163,61 @@ struct Iff ffstate.raw.ver = ver.Update(); } - template void TexGen( GLenum coord, GLenum pname, const T param ) { - RegalAssert(activeTextureIndex < REGAL_EMU_IFF_TEXTURE_UNITS); - if( activeTextureIndex >= REGAL_EMU_IFF_TEXTURE_UNITS ) { - return; - } + template bool TexGen( GLenum coord, GLenum pname, const T param ) + { + RegalAssert(activeTextureIndex < REGAL_EMU_MAX_TEXTURE_UNITS); + if (activeTextureIndex >= REGAL_EMU_MAX_TEXTURE_UNITS) + return false; + State::Store & st = ffstate.raw; int idx = 0; - switch( coord ) { - case GL_S: case GL_T: case GL_R: case GL_Q: idx = coord - GL_S; break; + switch( coord ) + { + case GL_S: + case GL_T: + case GL_R: + case GL_Q: + idx = coord - GL_S; + break; default: RegalAssert(coord==GL_S || coord==GL_T || coord==GL_R || coord==GL_Q || coord==GL_S); - return; + return false; } - switch( pname ) { - case GL_TEXTURE_GEN_MODE: { + switch( pname ) + { + case GL_TEXTURE_GEN_MODE: + { State::Texgen & tg = st.tex[ activeTextureIndex ].texgen[ idx ]; - switch( GLenum( RFFToFloat( 0, param ) ) ) { - case GL_OBJECT_LINEAR: tg.mode = TG_ObjectLinear; break; - case GL_EYE_LINEAR: tg.mode = TG_EyeLinear; break; - case GL_SPHERE_MAP: tg.mode = TG_SphereMap; break; - case GL_NORMAL_MAP: tg.mode = TG_NormalMap; break; - case GL_REFLECTION_MAP: tg.mode = TG_ReflectionMap; break; + switch( GLenum( RFFToFloat( 0, param ) ) ) + { + case GL_OBJECT_LINEAR: + tg.mode = TG_ObjectLinear; + break; + case GL_EYE_LINEAR: + tg.mode = TG_EyeLinear; + break; + case GL_SPHERE_MAP: + tg.mode = TG_SphereMap; + break; + case GL_NORMAL_MAP: + tg.mode = TG_NormalMap; + break; + case GL_REFLECTION_MAP: + tg.mode = TG_ReflectionMap; + break; default: RegalAssert(0); - return; + return false; } - break; } + break; case GL_EYE_PLANE: - case GL_OBJECT_PLANE: { + case GL_OBJECT_PLANE: + { if (!RFFIsVector( param )) { RegalAssert(0); - return; + return false; } Float4 plane; plane.x = RFFToFloat( 0, param ); @@ -2006,103 +2225,148 @@ struct Iff plane.z = RFFToFloat( 2, param ); plane.w = RFFToFloat( 3, param ); ffstate.SetTexgen( this, idx, pname, & plane.x ); - return; + //<> dsn: is this 'return' right? Shouldn't we be updating ver? + return true; } + break; default: RegalAssert(0); - return; - + return false; } ffstate.uniform.ver = st.ver = ver.Update(); + return true; } - void AlphaFunc( GLenum comp, const GLfloat ref ) { + void AlphaFunc( GLenum comp, const GLfloat ref ) + { CompareFunc cf = CF_Always; - switch( comp ) { - case GL_NEVER: cf = CF_Never; break; - case GL_LESS: cf = CF_Less; break; - case GL_EQUAL: cf = CF_Equal; break; - case GL_LEQUAL: cf = CF_Lequal; break; - case GL_NOTEQUAL: cf = CF_NotEqual; break; - case GL_GREATER: cf = CF_Greater; break; - case GL_GEQUAL: cf = CF_Gequal; break; - case GL_ALWAYS: cf = CF_Always; break; - default: break; // should be an error... + switch( comp ) + { + case GL_NEVER: + cf = CF_Never; + break; + case GL_LESS: + cf = CF_Less; + break; + case GL_EQUAL: + cf = CF_Equal; + break; + case GL_LEQUAL: + cf = CF_Lequal; + break; + case GL_NOTEQUAL: + cf = CF_NotEqual; + break; + case GL_GREATER: + cf = CF_Greater; + break; + case GL_GEQUAL: + cf = CF_Gequal; + break; + case GL_ALWAYS: + cf = CF_Always; + break; + default: + break; // should be an error... } ffstate.SetAlphaFunc( this, cf, ref ); } - void ClipPlane( GLenum plane, const GLdouble * equation ) { + void ClipPlane( GLenum plane, const GLdouble * equation ) + { Float4 eqn( equation[0], equation[1], equation[2], equation[3] ); ffstate.SetClip( this, plane, & eqn.x ); } - template void Fog( GLenum pname, const T param ) { + template void Fog( GLenum pname, const T param ) + { State::Store & r = ffstate.raw; State::StoreUniform & u = ffstate.uniform; - switch( pname ) { - case GL_FOG_MODE: { + switch( pname ) + { + case GL_FOG_MODE: + { FogMode m = FG_Exp; - switch( GLenum( RFFToFloat( 0, param ) ) ) { - case GL_LINEAR: m = FG_Linear; break; - case GL_EXP: m = FG_Exp; break; - case GL_EXP2: m = FG_Exp2; break; - default: return; + switch( GLenum( RFFToFloat( 0, param ) ) ) + { + case GL_LINEAR: + m = FG_Linear; + break; + case GL_EXP: + m = FG_Exp; + break; + case GL_EXP2: + m = FG_Exp2; + break; + default: + return; } r.fog.mode = m; - break; } - case GL_FOG_DENSITY: { + break; + case GL_FOG_DENSITY: u.fog.params[0].x = RFFToFloat( 0, param ); u.fog.ver = ver.Update(); break; - } - case GL_FOG_START: { + case GL_FOG_START: u.fog.params[0].y = RFFToFloat( 0, param ); u.fog.ver = ver.Update(); break; - } - case GL_FOG_END: { + case GL_FOG_END: u.fog.params[0].z = RFFToFloat( 0, param ); u.fog.ver = ver.Update(); break; - } - case GL_FOG_COLOR: { + case GL_FOG_COLOR: u.fog.params[1].x = RFFToFloat( 0, param ); u.fog.params[1].y = RFFToFloat( 1, param ); u.fog.params[1].z = RFFToFloat( 2, param ); u.fog.params[1].w = RFFToFloat( 3, param ); u.fog.ver = ver.Update(); break; - } - case GL_FOG_COORD_SRC: { + case GL_FOG_COORD_SRC: + { bool d = true; - switch( GLenum( RFFToFloat( 0, param ) ) ) { - case GL_FRAGMENT_DEPTH: d = true; break; - case GL_FOG_COORD: d = false; break; - default: return; + switch( GLenum( RFFToFloat( 0, param ) ) ) + { + case GL_FRAGMENT_DEPTH: + d = true; + break; + case GL_FOG_COORD: + d = false; + break; + default: + return; } r.fog.useDepth = d; - break; } - default: return; + break; + default: + return; } u.ver = r.ver = ver.Update(); } template bool GetIndexedTexGenv( RegalContext * ctx, GLuint textureIndex, - GLenum coord, GLenum pname, T * params ) + GLenum coord, GLenum pname, T * params ) { UNUSED_PARAMETER(ctx); - if( textureIndex >= REGAL_EMU_IFF_TEXTURE_UNITS ) { + if (textureIndex >= REGAL_EMU_MAX_TEXTURE_UNITS) return false; - } + int idx = 0; - switch( coord ) { - case GL_S: case GL_T: case GL_R: case GL_Q: idx = coord - GL_S; break; - default: return false; + switch( coord ) + { + case GL_S: + case GL_T: + case GL_R: + case GL_Q: + idx = coord - GL_S; + break; + default: + return false; } + switch( pname ) { case GL_TEXTURE_GEN_MODE: @@ -2129,8 +2393,8 @@ struct Iff return false; } *params = static_cast(glmode); - break; } + break; case GL_OBJECT_PLANE: case GL_EYE_PLANE: { @@ -2140,8 +2404,8 @@ struct Iff *(params+1) = static_cast(plane.y); *(params+2) = static_cast(plane.z); *(params+3) = static_cast(plane.w); - break; } + break; default: return false; } @@ -2149,13 +2413,13 @@ struct Iff } template bool GetTexGenv( RegalContext * ctx, GLenum coord, - GLenum pname, T * params ) + GLenum pname, T * params ) { return GetIndexedTexGenv( ctx, shadowActiveTextureIndex, coord, pname, params ); } template bool GetMultiTexGenv( RegalContext * ctx, GLenum texunit, - GLenum coord, GLenum pname, T * params ) + GLenum coord, GLenum pname, T * params ) { return GetIndexedTexGenv( ctx, texunit - GL_TEXTURE0, coord, pname, params ); } @@ -2166,10 +2430,24 @@ struct Iff State::StoreUniform & u = ffstate.uniform; // FIXME: implement all FF gets! - if( VaGet( ctx, pname, params ) ) + + if (VaGet( ctx, pname, params )) return true; - switch( pname ) { + switch( pname ) + { + case GL_MAX_VERTEX_ATTRIBS: + *params = static_cast(ctx->info->max_vertex_attribs); + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + *params = static_cast(ctx->info->max_combined_texture_image_units); + break; + case GL_MAX_TEXTURE_COORDS: + *params = static_cast(ctx->info->max_texture_coords); + break; + case GL_MAX_TEXTURE_UNITS: + *params = static_cast(ctx->info->max_texture_units); + break; case GL_CURRENT_PROGRAM: *params = static_cast(program); break; @@ -2197,197 +2475,257 @@ struct Iff *params = static_cast(projection.size()); break; case GL_TEXTURE_STACK_DEPTH: - RegalAssert(activeTextureIndex(texture[activeTextureIndex].size()); break; - case GL_MODELVIEW_MATRIX: { + case GL_MODELVIEW_MATRIX: + { const GLfloat * p = modelview.Top().Ptr(); - for( int i = 0; i < 16; i++ ) params[i] = static_cast(p[i]); - break; + for (size_t i = 0; i < 16; i++) + params[i] = static_cast(p[i]); } - case GL_PROJECTION_MATRIX: { + break; + case GL_PROJECTION_MATRIX: + { const GLfloat * p = projection.Top().Ptr(); - for( int i = 0; i < 16; i++ ) params[i] = static_cast(p[i]); - break; + for (size_t i = 0; i < 16; i++) + params[i] = static_cast(p[i]); } - case GL_TEXTURE_MATRIX: { - RegalAssert(activeTextureIndex(p[i]); - break; + for (size_t i = 0; i < 16; i++) + params[i] = static_cast(p[i]); } - case GL_MATRIX_MODE: { + break; + case GL_MATRIX_MODE: *params = static_cast(shadowMatrixMode); break; - } - case GL_MAX_LIGHTS: { + case GL_MAX_LIGHTS: *params = static_cast(REGAL_FIXED_FUNCTION_MAX_LIGHTS); break; - } - case GL_MAX_TEXTURE_UNITS: { - *params = static_cast(REGAL_EMU_IFF_TEXTURE_UNITS); - break; - } - case GL_MAX_CLIP_PLANES: { + case GL_MAX_CLIP_PLANES: *params = static_cast(REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES); break; - } - case GL_FOG_MODE: { + case GL_FOG_MODE: *params = static_cast(r.fog.mode); break; - } - case GL_FOG_DENSITY: { + case GL_FOG_DENSITY: *params = static_cast(u.fog.params[0].x); break; - } - case GL_FOG_START: { + case GL_FOG_START: *params = static_cast(u.fog.params[0].y); break; - } - case GL_FOG_END: { + case GL_FOG_END: *params = static_cast(u.fog.params[0].z); break; - } - case GL_FOG_COLOR: { + case GL_FOG_COLOR: + { const GLfloat * p = &u.fog.params[1].x; - for( int i = 0; i < 4; i++ ) + for (size_t i = 0; i < 4; i++) params[i] = static_cast(p[i]); - break; } + break; default: return false; } return true; } - void MatrixPush( GLenum mode ) { + void MatrixPush( GLenum mode ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Push(); } - void MatrixPop( GLenum mode ) { + void MatrixPop( GLenum mode ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Pop(); UpdateMatrixVer(); } - void UpdateMatrixVer() { + void UpdateMatrixVer() + { currMatrixStack->Ver() = ffstate.uniform.ver = ver.Update(); - if( currMatrixStack != &modelview && currMatrixStack != &projection ) { + if (currMatrixStack != &modelview && currMatrixStack != &projection) ffstate.raw.ver = ffstate.uniform.ver; - } } - void MatrixLoadIdentity( GLenum mode ) { + void MatrixLoadIdentity( GLenum mode ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top().MakeIdentity(); UpdateMatrixVer(); } - void MatrixLoad( GLenum mode, const r3::Matrix4f & m ) { + void MatrixLoad( GLenum mode, const r3::Matrix4f & m ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top() = m; UpdateMatrixVer(); } - void MatrixLoadTranspose( GLenum mode, const r3::Matrix4f & m ) { + void MatrixLoadTranspose( GLenum mode, const r3::Matrix4f & m ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top() = m.Transpose(); UpdateMatrixVer(); } - void MatrixMult( GLenum mode, const r3::Matrix4f & m ) { + void MatrixMult( GLenum mode, const r3::Matrix4f & m ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top().MultRight( m ); UpdateMatrixVer(); } - void MatrixMultTranspose( GLenum mode, const r3::Matrix4f & m ) { + void MatrixMultTranspose( GLenum mode, const r3::Matrix4f & m ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top().MultRight( m.Transpose() ); UpdateMatrixVer(); } - template void MatrixRotate( GLenum mode, T angle, T x, T y, T z ) { + template void MatrixRotate( GLenum mode, T angle, T x, T y, T z ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top().MultRight( r3::Rotationf( r3::Vec3f( x, y, z ), r3::ToRadians( static_cast(angle) ) ).GetMatrix4() ); UpdateMatrixVer(); } - template void MatrixTranslate( GLenum mode, T x, T y, T z ) { + template void MatrixTranslate( GLenum mode, T x, T y, T z ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top().MultRight( r3::Matrix4f::Translate( r3::Vec3f( x, y, z ) ) ); UpdateMatrixVer(); } - template void MatrixScale( GLenum mode, T x, T y, T z ) { + template void MatrixScale( GLenum mode, T x, T y, T z ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top().MultRight( r3::Matrix4f::Scale( r3::Vec3f( x, y, z ) ) ); UpdateMatrixVer(); } - template void MatrixFrustum( GLenum mode, T left, T right, T bottom, T top, T zNear, T zFar ) { + template void MatrixFrustum( GLenum mode, T left, T right, T bottom, T top, T zNear, T zFar ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top().MultRight( r3::Frustum( static_cast(left), static_cast(right), static_cast(bottom), static_cast(top), static_cast(zNear), static_cast(zFar) ) ); UpdateMatrixVer(); } - template void MatrixOrtho( GLenum mode, T left, T right, T bottom, T top, T zNear, T zFar ) { + template void MatrixOrtho( GLenum mode, T left, T right, T bottom, T top, T zNear, T zFar ) + { SetCurrentMatrixStack( mode ); currMatrixStack->Top().MultRight( r3::Ortho( static_cast(left), static_cast(right), static_cast(bottom), static_cast(top), static_cast(zNear), static_cast(zFar) ) ); UpdateMatrixVer(); } - void PushMatrix() { MatrixPush( shadowMatrixMode ); } - void PopMatrix() { MatrixPop( shadowMatrixMode ); } - void LoadIdentity() { MatrixLoadIdentity( shadowMatrixMode ); } - void LoadMatrix( const r3::Matrix4f & m ) { MatrixLoad( shadowMatrixMode, m ); } - void LoadTransposeMatrix( const r3::Matrix4f & m ) { MatrixLoadTranspose( shadowMatrixMode, m ); } - void MultMatrix( const r3::Matrix4f & m ) { MatrixMult( shadowMatrixMode, m ); } - void MultTransposeMatrix( const r3::Matrix4f & m ) { MatrixMultTranspose( shadowMatrixMode, m ); } - template void Rotate( T angle, T x, T y, T z ) { MatrixRotate( shadowMatrixMode, angle, x, y, z ); } - template void Translate( T x, T y, T z ) { MatrixTranslate( shadowMatrixMode, x, y, z ); } - template void Scale( T x, T y, T z ) { MatrixScale( shadowMatrixMode, x, y, z ); } - template void Frustum( T left, T right, T bottom, T top, T zNear, T zFar ) { MatrixFrustum( shadowMatrixMode, left, right, bottom, top, zNear, zFar ); } - template void Ortho( T left, T right, T bottom, T top, T zNear, T zFar ) { MatrixOrtho( shadowMatrixMode, left, right, bottom, top, zNear, zFar ); } + void PushMatrix() + { + MatrixPush( shadowMatrixMode ); + } + void PopMatrix() + { + MatrixPop( shadowMatrixMode ); + } + void LoadIdentity() + { + MatrixLoadIdentity( shadowMatrixMode ); + } + void LoadMatrix( const r3::Matrix4f & m ) + { + MatrixLoad( shadowMatrixMode, m ); + } + void LoadTransposeMatrix( const r3::Matrix4f & m ) + { + MatrixLoadTranspose( shadowMatrixMode, m ); + } + void MultMatrix( const r3::Matrix4f & m ) + { + MatrixMult( shadowMatrixMode, m ); + } + void MultTransposeMatrix( const r3::Matrix4f & m ) + { + MatrixMultTranspose( shadowMatrixMode, m ); + } + template void Rotate( T angle, T x, T y, T z ) + { + MatrixRotate( shadowMatrixMode, angle, x, y, z ); + } + template void Translate( T x, T y, T z ) + { + MatrixTranslate( shadowMatrixMode, x, y, z ); + } + template void Scale( T x, T y, T z ) + { + MatrixScale( shadowMatrixMode, x, y, z ); + } + template void Frustum( T left, T right, T bottom, T top, T zNear, T zFar ) + { + MatrixFrustum( shadowMatrixMode, left, right, bottom, top, zNear, zFar ); + } + template void Ortho( T left, T right, T bottom, T top, T zNear, T zFar ) + { + MatrixOrtho( shadowMatrixMode, left, right, bottom, top, zNear, zFar ); + } // cache viewport - struct Viewport { - Viewport() : zn( 0.0f ), zf( 1.0f ) {} + struct Viewport + { + Viewport() + : x(0) + , y(0) + , w(0) + , h(0) + , zn( 0.0f ) + , zf( 1.0f ) + { + } + GLint x, y; GLsizei w, h; GLfloat zn, zf; }; + Viewport viewport; - void Viewport( GLint x, GLint y, GLsizei w, GLsizei h ) { + void Viewport( GLint x, GLint y, GLsizei w, GLsizei h ) + { viewport.x = x; viewport.y = y; viewport.w = w; viewport.h = h; } - void DepthRange( GLfloat znear, GLfloat zfar ) { + void DepthRange( GLfloat znear, GLfloat zfar ) + { viewport.zn = znear; viewport.zf = zfar; } - template void RasterPosition( RegalContext * ctx, T x, T y, T z = 0 ) { + template void RasterPosition( RegalContext * ctx, T x, T y, T z = 0 ) + { const GLdouble xd = ToDouble(x); const GLdouble yd = ToDouble(y); const GLdouble zd = ToDouble(z); RasterPos( ctx, xd, yd, zd ); } - template void WindowPosition( RegalContext * ctx, T x, T y, T z = 0 ) { + template void WindowPosition( RegalContext * ctx, T x, T y, T z = 0 ) + { const GLdouble xd = ToDouble(x); const GLdouble yd = ToDouble(y); const GLdouble zd = ToDouble(z); WindowPos( ctx, xd, yd, zd ); } - void RasterPos( RegalContext * ctx, GLdouble x, GLdouble y, GLdouble z ) { + void RasterPos( RegalContext * ctx, GLdouble x, GLdouble y, GLdouble z ) + { r3::Vec3f pos( x, y, z ); r3::Vec3f s( 0.5f * GLfloat(viewport.w), 0.5f * GLfloat(viewport.h), 0.5f * GLfloat( viewport.zf - viewport.zn ) ); r3::Vec3f b( GLfloat(viewport.x), GLfloat(viewport.y), 0.5f + GLfloat(viewport.zn) ); @@ -2399,15 +2737,18 @@ struct Iff WindowPos( ctx, pos.x, pos.y, pos.z ); } - void WindowPos( RegalContext * ctx, GLdouble x, GLdouble y, GLdouble z ) { - if( ctx->isCore() || ctx->isCompat() ) { + void WindowPos( RegalContext * ctx, GLdouble x, GLdouble y, GLdouble z ) + { + if (ctx->isCore() || ctx->isCompat()) + { // todo - cache rasterpos and implement glDrawPixels and glBitmap return; } ctx->dispatcher.emulation.glWindowPos3d( x, y, z ); } - void BindVertexArray( RegalContext * ctx, GLuint vao ) { + void BindVertexArray( RegalContext * ctx, GLuint vao ) + { UNUSED_PARAMETER(ctx); vaoAttrMap[ currVao ] = ffstate.raw.attrArrayFlags; currVao = vao; @@ -2415,13 +2756,15 @@ struct Iff ffstate.uniform.vabVer = ver.Update(); } - void EnableArray( RegalContext * ctx, GLuint index ) { + void EnableArray( RegalContext * ctx, GLuint index ) + { RestoreVao( ctx ); ffstate.raw.attrArrayFlags |= 1 << index; ffstate.raw.ver = ffstate.uniform.vabVer = ver.Update(); } - void DisableArray( RegalContext * ctx, GLuint index ) { + void DisableArray( RegalContext * ctx, GLuint index ) + { RestoreVao( ctx ); ffstate.raw.attrArrayFlags &= ~( 1 << index ); ffstate.raw.ver = ffstate.uniform.vabVer = ver.Update(); @@ -2434,21 +2777,22 @@ struct Iff void ShaderSource( RegalContext *ctx, GLuint shader, GLsizei count, const GLchar * const * string, const GLint *length); void LinkProgram( RegalContext *ctx, GLuint program ); - GLuint CreateShader( RegalContext *ctx, GLenum shaderType ) { + GLuint CreateShader( RegalContext *ctx, GLenum shaderType ) + { GLuint sh = ctx->dispatcher.emulation.glCreateShader( shaderType ); shaderTypeMap[ sh ] = shaderType; return sh; } - // void Init( RegalContext &ctx ) { - shadowMatrixMode = 0; + shadowMatrixMode = GL_MODELVIEW; shadowActiveTextureIndex = 0; activeTextureIndex = 0; - program = 0; programPipeline = 0; + program = 0; currprog = NULL; + currMatrixStack = &modelview; currVao = 0; gles = false; legacy = false; diff --git a/src/regal/RegalPpa.h b/src/regal/RegalPpa.h index 1384243..929c925 100644 --- a/src/regal/RegalPpa.h +++ b/src/regal/RegalPpa.h @@ -627,11 +627,17 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo case GL_MAX_NAME_STACK_DEPTH: case GL_MAX_LIST_NESTING: case GL_MAX_EVAL_ORDER: - case GL_MAX_ATTRIB_STACK_DEPTH: - case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: if (params) params[0] = 0; break; + case GL_ATTRIB_STACK_DEPTH: + if (params) + params[0] = static_cast(maskStack.size()); + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + if (params) + params[0] = static_cast(ctx->info->max_attrib_stack_depth); + break; default: return false; } @@ -720,9 +726,14 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo case GL_DRAW_BUFFER14: case GL_DRAW_BUFFER15: { - if (!State::ColorBuffer::fullyDefined()) - State::ColorBuffer::getUndefined(ctx->dispatcher.emulation); - params[0] = static_cast(State::ColorBuffer::drawBuffers[pname-GL_DRAW_BUFFER0]); + GLuint index = static_cast(pname - GL_DRAW_BUFFER0); + if ( index < array_size( State::ColorBuffer::drawBuffers )) + { + if (!State::ColorBuffer::fullyDefined()) + State::ColorBuffer::getUndefined(ctx->dispatcher.emulation); + RegalAssertArrayIndex( State::ColorBuffer::drawBuffers, index ); + params[0] = static_cast(State::ColorBuffer::drawBuffers[index]); + } } break; case GL_FOG_COLOR: @@ -832,6 +843,24 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo case GL_MAP_COLOR: params[0] = static_cast(State::PixelMode::mapColor); break; + case GL_ATTRIB_STACK_DEPTH: + params[0] = static_cast(maskStack.size()); + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + params[0] = static_cast(ctx->info->max_attrib_stack_depth); + break; + case GL_MAX_VERTEX_ATTRIBS: + *params = static_cast(ctx->info->max_vertex_attribs); + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + params[0] = static_cast(ctx->info->max_combined_texture_image_units); + break; + case GL_MAX_TEXTURE_COORDS: + params[0] = static_cast(ctx->info->max_texture_coords); + break; + case GL_MAX_TEXTURE_UNITS: + params[0] = static_cast(ctx->info->max_texture_units); + break; case GL_MAP_STENCIL: params[0] = static_cast(State::PixelMode::mapStencil); break; @@ -1017,31 +1046,49 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo switch (pname) { case GL_BLEND_DST_ALPHA: - if (index < REGAL_MAX_DRAW_BUFFERS) + if (index < array_size( State::ColorBuffer::blendDstAlpha )) + { + RegalAssertArrayIndex( State::ColorBuffer::blendDstAlpha, index ); params[0] = static_cast(State::ColorBuffer::blendDstAlpha[index]); + } break; case GL_BLEND_DST_RGB: - if (index < REGAL_MAX_DRAW_BUFFERS) + if (index < array_size( State::ColorBuffer::blendDstRgb )) + { + RegalAssertArrayIndex( State::ColorBuffer::blendDstRgb, index ); params[0] = static_cast(State::ColorBuffer::blendDstRgb[index]); + } break; case GL_BLEND_EQUATION_ALPHA: - if (index < REGAL_MAX_DRAW_BUFFERS) + if (index < array_size( State::ColorBuffer::blendEquationAlpha )) + { + RegalAssertArrayIndex( State::ColorBuffer::blendEquationAlpha, index ); params[0] = static_cast(State::ColorBuffer::blendEquationAlpha[index]); + } break; case GL_BLEND_EQUATION_RGB: - if (index < REGAL_MAX_DRAW_BUFFERS) + if (index < array_size( State::ColorBuffer::blendEquationRgb )) + { + RegalAssertArrayIndex( State::ColorBuffer::blendEquationRgb, index ); params[0] = static_cast(State::ColorBuffer::blendEquationRgb[index]); + } break; case GL_BLEND_SRC_ALPHA: - if (index < REGAL_MAX_DRAW_BUFFERS) + if (index < array_size( State::ColorBuffer::blendSrcAlpha )) + { + RegalAssertArrayIndex( State::ColorBuffer::blendSrcAlpha, index ); params[0] = static_cast(State::ColorBuffer::blendSrcAlpha[index]); + } break; case GL_BLEND_SRC_RGB: - if (index < REGAL_MAX_DRAW_BUFFERS) + if (index < array_size( State::ColorBuffer::blendSrcRgb )) + { + RegalAssertArrayIndex( State::ColorBuffer::blendSrcRgb, index ); params[0] = static_cast(State::ColorBuffer::blendSrcRgb[index]); + } break; case GL_COLOR_WRITEMASK: - if (index < REGAL_MAX_DRAW_BUFFERS) + if (index < ctx->info->max_draw_buffers) { params[0] = static_cast(State::ColorBuffer::colorWritemask[index][0]); params[1] = static_cast(State::ColorBuffer::colorWritemask[index][1]); @@ -1050,14 +1097,14 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo } break; case GL_DEPTH_RANGE: - if (index < REGAL_MAX_VIEWPORTS) + if (index < ctx->info->max_viewports) { params[0] = static_cast(State::Viewport::depthRange[index][0]); params[1] = static_cast(State::Viewport::depthRange[index][1]); } break; case GL_SCISSOR_BOX: - if (index < REGAL_MAX_VIEWPORTS) + if (index < ctx->info->max_viewports) { if (!State::Scissor::fullyDefined()) State::Scissor::getUndefined(ctx->dispatcher.emulation); @@ -1068,7 +1115,7 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo } break; case GL_VIEWPORT: - if (index < REGAL_MAX_VIEWPORTS) + if (index < ctx->info->max_viewports) { if (!State::Viewport::fullyDefined()) State::Viewport::getUndefined(ctx->dispatcher.emulation); @@ -1195,9 +1242,10 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo UNUSED_PARAMETER(ctx); GLint ii = light - GL_LIGHT0; - if (ii < 0 || ii >= REGAL_FIXED_FUNCTION_MAX_LIGHTS) + if (ii < 0 || static_cast(ii) >= array_size( State::Point::coordReplace )) return false; + RegalAssertArrayIndex( State::Lighting::lights, ii ); State::LightingLight l = State::Lighting::lights[ii]; GLuint num = 0; @@ -1248,7 +1296,7 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo return false; } - for (GLuint ii = 0; ii < num; ii++) + for (size_t ii = 0; ii < num; ii++) params[ii] = static_cast(p[ii]); return true; @@ -1295,7 +1343,7 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo return false; } - for (GLuint ii = 0; ii < num; ii++) + for (size_t ii = 0; ii < num; ii++) params[ii] = static_cast(p[ii]); return true; @@ -1309,9 +1357,10 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo return false; GLint ii = texunit - GL_TEXTURE0; - if (ii < 0 || ii >= REGAL_EMU_MAX_TEXTURE_UNITS) + if (ii < 0 || static_cast(ii) >= array_size( State::Point::coordReplace )) return false; + RegalAssertArrayIndex( State::Point::coordReplace, ii ); *params = static_cast(State::Point::coordReplace[ii]); return true; @@ -1345,6 +1394,7 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo case GL_CLIP_DISTANCE5: case GL_CLIP_DISTANCE6: case GL_CLIP_DISTANCE7: + RegalAssertArrayIndex( State::Enable::clipDistance, pname-GL_CLIP_DISTANCE0 ); enabled = State::Enable::clipDistance[pname-GL_CLIP_DISTANCE0]; break; case GL_COLOR_LOGIC_OP: @@ -1397,6 +1447,7 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo case GL_LIGHT5: case GL_LIGHT6: case GL_LIGHT7: + RegalAssertArrayIndex( State::Enable::light, pname-GL_LIGHT0 ); enabled = State::Enable::light[pname-GL_LIGHT0]; break; case GL_LIGHTING: @@ -1526,27 +1577,39 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo enabled = State::Enable::stencilTest; break; case GL_TEXTURE_1D: + RegalAssertArrayIndex( State::Enable::texture1d, activeTextureUnit ); enabled = State::Enable::texture1d[activeTextureUnit]; break; case GL_TEXTURE_2D: + RegalAssertArrayIndex( State::Enable::texture2d, activeTextureUnit ); enabled = State::Enable::texture2d[activeTextureUnit]; break; case GL_TEXTURE_3D: + RegalAssertArrayIndex( State::Enable::texture3d, activeTextureUnit ); enabled = State::Enable::texture3d[activeTextureUnit]; break; case GL_TEXTURE_CUBE_MAP: + RegalAssertArrayIndex( State::Enable::textureCubeMap, activeTextureUnit ); enabled = State::Enable::textureCubeMap[activeTextureUnit]; break; + case GL_TEXTURE_RECTANGLE: + RegalAssertArrayIndex( State::Enable::textureRectangle, activeTextureUnit ); + enabled = State::Enable::textureRectangle[activeTextureUnit]; + break; case GL_TEXTURE_GEN_S: + RegalAssertArrayIndex( State::Enable::textureGenS, activeTextureUnit ); enabled = State::Enable::textureGenS[activeTextureUnit]; break; case GL_TEXTURE_GEN_T: + RegalAssertArrayIndex( State::Enable::textureGenT, activeTextureUnit ); enabled = State::Enable::textureGenT[activeTextureUnit]; break; case GL_TEXTURE_GEN_R: + RegalAssertArrayIndex( State::Enable::textureGenR, activeTextureUnit ); enabled = State::Enable::textureGenR[activeTextureUnit]; break; case GL_TEXTURE_GEN_Q: + RegalAssertArrayIndex( State::Enable::textureGenQ, activeTextureUnit ); enabled = State::Enable::textureGenQ[activeTextureUnit]; break; case GL_VERTEX_PROGRAM_TWO_SIDE: @@ -1566,14 +1629,16 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo switch (pname) { case GL_BLEND: - if (index >= REGAL_MAX_DRAW_BUFFERS) + if (index >= array_size( State::Enable::blend )) return false; + RegalAssertArrayIndex( State::Enable::blend, index ); enabled = State::Enable::blend[index]; break; case GL_SCISSOR_TEST: - if (index >= REGAL_MAX_VIEWPORTS) + if (index >= array_size( State::Enable::scissorTest )) return false; + RegalAssertArrayIndex( State::Enable::scissorTest, index ); enabled = State::Enable::scissorTest[index]; break; @@ -1592,8 +1657,14 @@ struct Ppa : public State::Stencil, State::Depth, State::Polygon, State::Transfo break; case GL_BLEND: { - for (GLuint ii=0; ii= GL_TEXTURE0 && texture < static_cast(GL_TEXTURE0 + REGAL_EMU_MAX_TEXTURE_UNITS) ) + activeTextureUnit = texture - GL_TEXTURE0; else - { - Warning( "Active texture out of range: ", Token::GLtextureToString(tex), " > ", Token::GLtextureToString(GL_TEXTURE0 + REGAL_EMU_MAX_TEXTURE_UNITS - 1)); - return; - } + Warning( "Active texture out of range: ", Token::GLtextureToString(texture), " > ", Token::GLtextureToString(GL_TEXTURE0 + REGAL_EMU_MAX_TEXTURE_UNITS - 1)); } inline void glClampColor( GLenum target, GLenum clamp ) diff --git a/src/regal/RegalPpca.h b/src/regal/RegalPpca.h index 11cf282..78ec231 100644 --- a/src/regal/RegalPpca.h +++ b/src/regal/RegalPpca.h @@ -107,7 +107,7 @@ struct Ppca : public ClientState::VertexArray, ClientState::PixelStore // // TODO: set correct GL error here - if (maskStack.size() >= REGAL_EMU_MAX_CLIENT_ATTRIB_STACK_DEPTH) + if (maskStack.size() >= ctx.info->max_client_attrib_stack_depth) return; maskStack.push_back(mask); @@ -241,8 +241,6 @@ struct Ppca : public ClientState::VertexArray, ClientState::PixelStore bool glGetv(RegalContext &ctx, GLenum pname, GLboolean *params) { - UNUSED_PARAMETER(ctx); - switch (pname) { case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: @@ -251,6 +249,15 @@ struct Ppca : public ClientState::VertexArray, ClientState::PixelStore case GL_CLIENT_ATTRIB_STACK_DEPTH: params[0] = (maskStack.size() != 0); break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + params[0] = ctx.info->max_combined_texture_image_units != 0; + break; + case GL_MAX_TEXTURE_COORDS: + params[0] = ctx.info->max_texture_coords != 0; + break; + case GL_MAX_TEXTURE_UNITS: + params[0] = ctx.info->max_texture_units != 0; + break; default: return false; @@ -260,16 +267,26 @@ struct Ppca : public ClientState::VertexArray, ClientState::PixelStore template bool glGetv(RegalContext &ctx, GLenum pname, T *params) { - UNUSED_PARAMETER(ctx); - switch (pname) { case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: - params[0] = static_cast(REGAL_EMU_MAX_CLIENT_ATTRIB_STACK_DEPTH); + params[0] = static_cast(ctx.info->max_client_attrib_stack_depth); break; case GL_CLIENT_ATTRIB_STACK_DEPTH: params[0] = static_cast(maskStack.size()); break; + case GL_MAX_VERTEX_ATTRIBS: + params[0] = static_cast(ctx.info->max_vertex_attribs); + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + params[0] = static_cast(ctx.info->max_combined_texture_image_units); + break; + case GL_MAX_TEXTURE_COORDS: + params[0] = static_cast(ctx.info->max_texture_coords); + break; + case GL_MAX_TEXTURE_UNITS: + params[0] = static_cast(ctx.info->max_texture_units); + break; default: return false; diff --git a/src/regal/RegalRect.h b/src/regal/RegalRect.h index c9dd7be..4308230 100644 --- a/src/regal/RegalRect.h +++ b/src/regal/RegalRect.h @@ -135,4 +135,4 @@ REGAL_NAMESPACE_END #endif // REGAL_EMULATION -#endif // ! __REGAL_BASEVERTEX_H__ +#endif // ! __REGAL_RECT_H__ diff --git a/src/regal/RegalSo.cpp b/src/regal/RegalSo.cpp index 10437f6..f71857c 100644 --- a/src/regal/RegalSo.cpp +++ b/src/regal/RegalSo.cpp @@ -49,7 +49,7 @@ namespace Emu { using namespace ::REGAL_NAMESPACE_INTERNAL::Logging; using namespace ::REGAL_NAMESPACE_INTERNAL::Token; -const GLenum So::index2Enum[17] = { GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, REGAL_NUM_TEXTURE_TARGETS }; +const GLenum So::index2Enum[REGAL_NUM_TEXTURE_TARGETS] = { GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; void @@ -75,10 +75,12 @@ So::DeleteSamplers(GLsizei count, const GLuint * samplers) if (s && samplerObjects.count(s) > 0) { SamplingState* p = samplerObjects[s]; - for (GLsizei unit=0; unit < REGAL_EMU_MAX_TEXTURE_UNITS; unit++) + size_t n = array_size( textureUnits ); + for (size_t unit=0; unit < n; unit++) { + RegalAssertArrayIndex( textureUnits, unit ); if (textureUnits[unit].boundSamplerObject == p) - BindSampler(unit, 0); + BindSampler(static_cast(unit), 0); } samplerObjects.erase(s); delete p; @@ -95,9 +97,9 @@ So::IsSampler(GLuint sampler) void So::BindSampler(GLuint unit, GLuint so) { - if (unit >= REGAL_EMU_MAX_TEXTURE_UNITS) + if (unit >= array_size( textureUnits )) { - Warning("Texture unit out of range: ", unit, " >= ", REGAL_EMU_MAX_TEXTURE_UNITS); + Warning("Texture unit out of range: ", unit, " >= ", REGAL_EMU_MAX_TEXTURE_COORDS); return; } @@ -112,6 +114,7 @@ So::BindSampler(GLuint unit, GLuint so) SamplingState *pso = so != 0 ? samplerObjects[so] : NULL; + RegalAssertArrayIndex( textureUnits, unit ); textureUnits[unit].boundSamplerObject = pso; } @@ -141,18 +144,22 @@ So::DeleteTextures(RegalContext &ctx, GLsizei count, const GLuint * textures) { TextureState* p = textureObjects[t]; - for (GLuint unit=0; unit < REGAL_EMU_MAX_TEXTURE_UNITS; unit++) + size_t n = array_size( textureUnits ); + for (size_t unit=0; unit < n; unit++) { + RegalAssertArrayIndex( textureUnits, unit ); TextureUnit &tu = textureUnits[unit]; - for (GLuint jj=0; jj < REGAL_NUM_TEXTURE_TARGETS; jj++) + size_t num = array_size( tu.boundTextureObjects ); + for (size_t jj=0; jj(GL_TEXTURE0 + unit)); - BindTexture(ctx, unit, TT_Index2Enum(jj), 0); + BindTexture(ctx, static_cast(unit), TT_Index2Enum(jj), 0); } } } @@ -177,9 +184,9 @@ So::BindTexture(RegalContext &ctx, GLuint unit, GLenum target, GLuint to) { Internal("Regal::So::BindTexture",&ctx," unit=",unit," target=",target," to=",to); - if (unit >= REGAL_EMU_MAX_TEXTURE_UNITS) + if (unit >= array_size( textureUnits )) { - Warning("Texture unit out of range: ", unit, " >= ", REGAL_EMU_MAX_TEXTURE_UNITS); + Warning("Texture unit out of range: ", unit, " >= ", REGAL_EMU_MAX_TEXTURE_COORDS); return false; } @@ -220,24 +227,21 @@ So::BindTexture(RegalContext &ctx, GLuint unit, GLenum target, GLuint to) if (activeTextureUnit != originallyActiveUnit) ActiveTexture(ctx, GL_TEXTURE0 + originallyActiveUnit ); + RegalAssertArrayIndex( textureUnits, unit ); textureUnits[unit].boundTextureObjects[tti] = ts; return true; } bool -So::ActiveTexture( RegalContext &ctx, GLenum tex ) +So::ActiveTexture( RegalContext &ctx, GLenum texture ) { - GLuint unit = tex - GL_TEXTURE0; - if (unit >= REGAL_EMU_MAX_TEXTURE_UNITS) - { - Warning( "Active texture out of range: ", tex, " >= ", - Token::GLenumToString(GL_TEXTURE0 + REGAL_EMU_MAX_TEXTURE_UNITS)); - return false; - } - activeTextureUnit = unit; - ctx.dispatcher.emulation.glActiveTexture( tex ); - return true; + if (!validTextureEnum(texture)) + return false; + + activeTextureUnit = texture - GL_TEXTURE0; + ctx.dispatcher.emulation.glActiveTexture( texture ); + return true; } void @@ -251,13 +255,17 @@ So::PreDraw( RegalContext &ctx ) GLuint originallyActiveUnit = activeTextureUnit; // ignoring sampler objects on the last unit... FIXME - cass - for (int unit=REGAL_EMU_MAX_TEXTURE_UNITS-1; unit >= 0; unit--) + const int n = static_cast(array_size( textureUnits )); + for (int unit=n-1; unit >= 0; unit--) { + RegalAssertArrayIndex( textureUnits, unit ); TextureUnit &tu = textureUnits[unit]; SamplingState *pSS = tu.boundSamplerObject; - for (GLuint tt=0; tt < REGAL_NUM_TEXTURE_TARGETS; tt++) + size_t num = array_size( tu.boundTextureObjects ); + for (size_t tt=0; tt < num; tt++) { + RegalAssertArrayIndex( tu.boundTextureObjects, tt ); TextureState* ts = tu.boundTextureObjects[tt]; GLenum target = TT_Index2Enum( tt ); if( target != GL_TEXTURE_2D ) @@ -285,7 +293,7 @@ So::PreDraw( RegalContext &ctx ) SamplingState *newState = pSS ? pSS : &ts->app; //Internal( "RegalSo", "about to send update samplerVer=", ts->samplerVer, " newState->ver=", newState->ver ); - if (SendStateToDriver(ctx, unit, ts->target, *newState, ts->drv)) { + if (SendStateToDriver(ctx, static_cast(unit), ts->target, *newState, ts->drv)) { //Internal( "RegalSo", "updated unit ", unit, " texture ", ts ? ts->name : 0, " for sampler ", pSS ? pSS->name : 0 ); } else { //Internal( "RegalSo", "no update occurred" ); diff --git a/src/regal/RegalSo.h b/src/regal/RegalSo.h index ce598c9..851dae0 100644 --- a/src/regal/RegalSo.h +++ b/src/regal/RegalSo.h @@ -91,13 +91,16 @@ struct So UNUSED_PARAMETER(ctx); } - static GLenum TT_Index2Enum(GLuint index) + static GLenum TT_Index2Enum(size_t index) { - if( index > REGAL_NUM_TEXTURE_TARGETS ) { - Warning( "Unhandled texture target index: index = ", index); - index = REGAL_NUM_TEXTURE_TARGETS; + if (index < array_size( index2Enum )) + { + RegalAssertArrayIndex( index2Enum, index ); + return index2Enum[index]; } - return index2Enum[index]; + + Warning( "Unhandled texture target index: index = ", index); + return GL_TEXTURE_2D; } static GLuint TT_Enum2Index(GLenum texture) @@ -213,8 +216,10 @@ struct So TextureUnit() : boundSamplerObject(NULL) { - for (int tti = 0; tti< REGAL_NUM_TEXTURE_TARGETS; tti++) + size_t n = array_size( boundTextureObjects ); + for (size_t tti = 0; tti < n; tti++) { + RegalAssertArrayIndex( boundTextureObjects, tti ); boundTextureObjects[tti] = NULL; } } @@ -412,8 +417,13 @@ struct So if (tti >= REGAL_NUM_TEXTURE_TARGETS) return false; + RegalAssertArrayIndex( textureUnits, activeTextureUnit ); + if (activeTextureUnit >= array_size( textureUnits )) + return false; + TextureUnit &tu = textureUnits[activeTextureUnit]; + RegalAssertArrayIndex( tu.boundTextureObjects, tti ); TextureState* ts = tu.boundTextureObjects[tti]; SamplingState *as = NULL; @@ -508,8 +518,13 @@ struct So if (tti >= REGAL_NUM_TEXTURE_TARGETS) return false; + RegalAssertArrayIndex( textureUnits, activeTextureUnit ); + if (activeTextureUnit >= array_size( textureUnits )) + return false; + TextureUnit &tu = textureUnits[activeTextureUnit]; + RegalAssertArrayIndex( tu.boundTextureObjects, tti ); TextureState* txs = tu.boundTextureObjects[tti]; if (!txs) @@ -524,6 +539,18 @@ struct So switch (pname) { + case GL_MAX_VERTEX_ATTRIBS: + *params = static_cast(ctx.info->max_vertex_attribs); + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + *params = static_cast(ctx.info->max_combined_texture_image_units); + break; + case GL_MAX_TEXTURE_COORDS: + *params = static_cast(ctx.info->max_texture_coords); + break; + case GL_MAX_TEXTURE_UNITS: + *params = static_cast(ctx.info->max_texture_units); + break; case GL_TEXTURE_BORDER_COLOR: params[0] = static_cast(ts->BorderColor[0]); params[1] = static_cast(ts->BorderColor[1]); @@ -607,6 +634,9 @@ struct So case GL_SAMPLER_BINDING: { + RegalAssertArrayIndex( textureUnits, activeTextureUnit ); + if (activeTextureUnit >= array_size( textureUnits )) + return false; SamplingState *pso = textureUnits[activeTextureUnit].boundSamplerObject; *params = static_cast(pso ? pso->name : 0); } @@ -659,8 +689,15 @@ struct So if (tti >= REGAL_NUM_TEXTURE_TARGETS) return false; + RegalAssertArrayIndex( textureUnits, activeTextureUnit ); + if (activeTextureUnit >= array_size( textureUnits )) + return false; + TextureUnit &tu = textureUnits[activeTextureUnit]; + + RegalAssertArrayIndex( tu.boundTextureObjects, tti ); TextureState* ts = tu.boundTextureObjects[tti]; + *params = static_cast(ts ? ts->name : 0); return true; @@ -685,10 +722,10 @@ struct So GLuint nextSamplerObjectId; bool supportSrgb; bool noSamplersInUse; - TextureUnit textureUnits[REGAL_EMU_MAX_TEXTURE_UNITS]; + TextureUnit textureUnits[REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; std::map samplerObjects; std::map textureObjects; - static const GLenum index2Enum[17]; + static const GLenum index2Enum[REGAL_NUM_TEXTURE_TARGETS]; }; } diff --git a/src/regal/RegalState.h b/src/regal/RegalState.h index 232f4be..6af9235 100644 --- a/src/regal/RegalState.h +++ b/src/regal/RegalState.h @@ -87,14 +87,6 @@ REGAL_NAMESPACE_BEGIN #define REGAL_FIXED_FUNCTION_MAX_CLIP_DISTANCES 8 #endif -#ifndef REGAL_MAX_VIEWPORTS -#define REGAL_MAX_VIEWPORTS 16 -#endif - -#ifndef REGAL_MAX_DRAW_BUFFERS -#define REGAL_MAX_DRAW_BUFFERS 8 -#endif - namespace State { @@ -136,7 +128,7 @@ struct Enable { GLboolean alphaTest; // GL_ALPHA_TEST GLboolean autoNormal; // GL_AUTO_NORMAL - GLboolean blend[REGAL_MAX_DRAW_BUFFERS]; // GL_BLEND + GLboolean blend[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_BLEND GLboolean clipDistance[REGAL_FIXED_FUNCTION_MAX_CLIP_DISTANCES]; // GL_CLIP_DISTANCEi GLenum clampFragmentColor; // GL_CLAMP_FRAGMENT_COLOR GLenum clampReadColor; // GL_CLAMP_READ_COLOR @@ -196,16 +188,17 @@ struct Enable GLboolean sampleCoverage; // GL_SAMPLE_COVERAGE GLboolean sampleShading; // GL_SAMPLE_SHADING GLboolean separable2d; // GL_SEPARABLE_2D - GLboolean scissorTest[REGAL_MAX_VIEWPORTS]; // GL_SCISSOR_TEST + GLboolean scissorTest[REGAL_EMU_MAX_VIEWPORTS]; // GL_SCISSOR_TEST GLboolean stencilTest; // GL_STENCIL_TEST - GLboolean texture1d[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_1D - GLboolean texture2d[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_2D - GLboolean texture3d[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_3D - GLboolean textureCubeMap[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_CUBE_MAP - GLboolean textureGenS[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_GEN_S - GLboolean textureGenT[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_GEN_T - GLboolean textureGenR[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_GEN_R - GLboolean textureGenQ[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_GEN_Q + GLboolean texture1d[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_1D + GLboolean texture2d[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_2D + GLboolean texture3d[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_3D + GLboolean textureCubeMap[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_CUBE_MAP + GLboolean textureRectangle[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_RECTANGLE + GLboolean textureGenS[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_GEN_S + GLboolean textureGenT[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_GEN_T + GLboolean textureGenR[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_GEN_R + GLboolean textureGenQ[REGAL_EMU_MAX_TEXTURE_UNITS]; // GL_TEXTURE_GEN_Q GLboolean vertexProgramTwoSide; // GL_VERTEX_PROGRAM_TWO_SIDE inline Enable() @@ -271,20 +264,46 @@ struct Enable , stencilTest(GL_FALSE) , vertexProgramTwoSide(GL_FALSE) { - for (GLuint ii=0; ii(ii)); + } dt.call(&dt.glGetIntegerv)(GL_CLAMP_FRAGMENT_COLOR,reinterpret_cast(&clampFragmentColor)); dt.call(&dt.glGetIntegerv)(GL_CLAMP_READ_COLOR,reinterpret_cast(&clampReadColor)); dt.call(&dt.glGetIntegerv)(GL_CLAMP_VERTEX_COLOR,reinterpret_cast(&clampVertexColor)); - for (int ii=0; ii(GL_CLIP_DISTANCE0+ii)); + } colorLogicOp = dt.call(&dt.glIsEnabled)(GL_COLOR_LOGIC_OP); colorMaterial = dt.call(&dt.glIsEnabled)(GL_COLOR_MATERIAL); colorSum = dt.call(&dt.glIsEnabled)(GL_COLOR_SUM); @@ -401,8 +429,12 @@ struct Enable framebufferSRGB = dt.call(&dt.glIsEnabled)(GL_FRAMEBUFFER_SRGB); histogram = dt.call(&dt.glIsEnabled)(GL_HISTOGRAM); indexLogicOp = dt.call(&dt.glIsEnabled)(GL_INDEX_LOGIC_OP); - for (int ii=0; ii(GL_LIGHT0+ii)); + } lighting = dt.call(&dt.glIsEnabled)(GL_LIGHTING); lineSmooth = dt.call(&dt.glIsEnabled)(GL_LINE_SMOOTH); lineStipple = dt.call(&dt.glIsEnabled)(GL_LINE_STIPPLE); @@ -444,14 +476,28 @@ struct Enable sampleShading = dt.call(&dt.glIsEnabled)(GL_SAMPLE_SHADING); separable2d = dt.call(&dt.glIsEnabled)(GL_SEPARABLE_2D); stencilTest = dt.call(&dt.glIsEnabled)(GL_STENCIL_TEST); - for (GLuint ii=0; ii(ii)); + } + n = array_size( texture1d ); + RegalAssert( array_size( texture2d ) == n ); + RegalAssert( array_size( texture3d ) == n ); + RegalAssert( array_size( textureCubeMap ) == n ); + RegalAssert( array_size( textureRectangle ) == n ); + RegalAssert( array_size( textureGenS ) == n ); + RegalAssert( array_size( textureGenT ) == n ); + RegalAssert( array_size( textureGenR ) == n ); + RegalAssert( array_size( textureGenQ ) == n ); + for (GLuint ii=0; ii(n); ii++) { texture1d[ii] = dt.call(&dt.glIsEnabledi)(GL_TEXTURE_1D,ii); texture2d[ii] = dt.call(&dt.glIsEnabledi)(GL_TEXTURE_2D,ii); texture3d[ii] = dt.call(&dt.glIsEnabledi)(GL_TEXTURE_3D,ii); textureCubeMap[ii] = dt.call(&dt.glIsEnabledi)(GL_TEXTURE_CUBE_MAP,ii); + textureRectangle[ii] = dt.call(&dt.glIsEnabledi)(GL_TEXTURE_RECTANGLE,ii); textureGenS[ii] = dt.call(&dt.glIsEnabledi)(GL_TEXTURE_GEN_S,ii); textureGenT[ii] = dt.call(&dt.glIsEnabledi)(GL_TEXTURE_GEN_T,ii); textureGenR[ii] = dt.call(&dt.glIsEnabledi)(GL_TEXTURE_GEN_R,ii); @@ -465,14 +511,22 @@ struct Enable { setEnable(dt,GL_ALPHA_TEST,alphaTest); setEnable(dt,GL_AUTO_NORMAL,autoNormal); - for (GLuint ii=0; ii(ii),blend[ii]); + } setEnable(dt,GL_COLOR_LOGIC_OP,colorLogicOp); dt.call(&dt.glClampColor)(GL_CLAMP_FRAGMENT_COLOR,clampFragmentColor); dt.call(&dt.glClampColor)(GL_CLAMP_READ_COLOR,clampReadColor); dt.call(&dt.glClampColor)(GL_CLAMP_VERTEX_COLOR,clampVertexColor); - for (int ii=0; ii(GL_CLIP_DISTANCE0+ii),clipDistance[ii]); + } setEnable(dt,GL_COLOR_MATERIAL,colorMaterial); setEnable(dt,GL_COLOR_SUM,colorSum); setEnable(dt,GL_COLOR_TABLE,colorTable); @@ -486,8 +540,12 @@ struct Enable setEnable(dt,GL_FRAMEBUFFER_SRGB,framebufferSRGB); setEnable(dt,GL_HISTOGRAM,histogram); setEnable(dt,GL_INDEX_LOGIC_OP,indexLogicOp); - for (int ii=0; ii(GL_LIGHT0+ii),light[ii]); + } setEnable(dt,GL_LIGHTING,lighting); setEnable(dt,GL_LINE_SMOOTH,lineSmooth); setEnable(dt,GL_LINE_STIPPLE,lineStipple); @@ -529,14 +587,28 @@ struct Enable setEnable(dt,GL_SAMPLE_SHADING,sampleShading); setEnable(dt,GL_SEPARABLE_2D,separable2d); setEnable(dt,GL_STENCIL_TEST,stencilTest); - for (GLuint ii=0; ii(ii),scissorTest[ii]); + } + n = array_size( texture1d ); + RegalAssert( array_size( texture2d ) == n ); + RegalAssert( array_size( texture3d ) == n ); + RegalAssert( array_size( textureCubeMap ) == n ); + RegalAssert( array_size( textureRectangle ) == n ); + RegalAssert( array_size( textureGenS ) == n ); + RegalAssert( array_size( textureGenT ) == n ); + RegalAssert( array_size( textureGenR ) == n ); + RegalAssert( array_size( textureGenQ ) == n ); + for (GLuint ii=0; ii(n); ii++) { setEnablei(dt,GL_TEXTURE_1D,ii,texture1d[ii]); setEnablei(dt,GL_TEXTURE_2D,ii,texture2d[ii]); setEnablei(dt,GL_TEXTURE_3D,ii,texture3d[ii]); setEnablei(dt,GL_TEXTURE_CUBE_MAP,ii,textureCubeMap[ii]); + setEnablei(dt,GL_TEXTURE_RECTANGLE,ii,textureRectangle[ii]); setEnablei(dt,GL_TEXTURE_GEN_S,ii,textureGenS[ii]); setEnablei(dt,GL_TEXTURE_GEN_T,ii,textureGenT[ii]); setEnablei(dt,GL_TEXTURE_GEN_R,ii,textureGenR[ii]); @@ -551,13 +623,21 @@ struct Enable string_list tmp; enableToString(tmp, alphaTest, "GL_ALPHA_TEST",delim); enableToString(tmp, autoNormal, "GL_AUTO_NORMAL",delim); - for (GLuint ii=0; ii(ii),delim); + } tmp << print_string("glClampColor(GL_CLAMP_FRAGMENT_COLOR",Token::toString(clampFragmentColor),");",delim); tmp << print_string("glClampColor(GL_CLAMP_READ_COLOR",Token::toString(clampReadColor),");",delim); tmp << print_string("glClampColor(GL_CLAMP_VERTEX_COLOR",Token::toString(clampVertexColor),");",delim); - for (int ii=0; ii(ii), delim); + } enableToString(tmp, colorLogicOp, "GL_COLOR_LOGIC_OP",delim); enableToString(tmp, colorMaterial, "GL_COLOR_MATERIAL",delim); enableToString(tmp, colorSum, "GL_COLOR_SUM",delim); @@ -571,9 +651,11 @@ struct Enable enableToString(tmp, fog, "GL_FOG",delim); enableToString(tmp, framebufferSRGB, "GL_FRAMEBUFFER_SRGB",delim); enableToString(tmp, histogram, "GL_HISTOGRAM",delim); - for (int ii=0; ii(GL_LIGHT0 + ii); + RegalAssertArrayIndex( light, ii ); tmp << print_string(light[ii] ? "glEnable(" : "glDisable(",Token::toString(lightx),");",delim); } enableToString(tmp, lighting, "GL_LIGHTING",delim); @@ -618,14 +700,28 @@ struct Enable enableToString(tmp, sampleShading, "GL_SAMPLE_SHADING",delim); enableToString(tmp, separable2d, "GL_SEPARABLE_2D",delim); enableToString(tmp, stencilTest, "GL_STENCIL_TEST",delim); - for (GLuint ii=0; ii(ii),delim); + } + n = array_size( texture1d ); + RegalAssert( array_size( texture2d ) == n ); + RegalAssert( array_size( texture3d ) == n ); + RegalAssert( array_size( textureCubeMap ) == n ); + RegalAssert( array_size( textureRectangle ) == n ); + RegalAssert( array_size( textureGenS ) == n ); + RegalAssert( array_size( textureGenT ) == n ); + RegalAssert( array_size( textureGenR ) == n ); + RegalAssert( array_size( textureGenQ ) == n ); + for (GLuint ii=0; ii(n); ii++) { enableiToString(tmp, texture1d[ii], "GL_TEXTURE_1D", ii, delim); enableiToString(tmp, texture2d[ii], "GL_TEXTURE_2D", ii, delim); enableiToString(tmp, texture3d[ii], "GL_TEXTURE_3D", ii, delim); enableiToString(tmp, textureCubeMap[ii], "GL_TEXTURE_CUBE_MAP", ii, delim); + enableiToString(tmp, textureRectangle[ii], "GL_TEXTURE_RECTANGLE", ii, delim); enableiToString(tmp, textureGenS[ii], "GL_TEXTURE_GEN_S", ii, delim); enableiToString(tmp, textureGenT[ii], "GL_TEXTURE_GEN_T", ii, delim); enableiToString(tmp, textureGenR[ii], "GL_TEXTURE_GEN_R", ii, delim); @@ -969,7 +1065,7 @@ struct Polygon cullEnable = dt.call(&dt.glIsEnabled)(GL_CULL_FACE); dt.call(&dt.glGetIntegerv)(GL_CULL_FACE_MODE,reinterpret_cast(&cullFaceMode)); dt.call(&dt.glGetIntegerv)(GL_FRONT_FACE,reinterpret_cast(&frontFace)); - dt.call(&dt.glGetIntegerv)(GL_POLYGON_MODE,reinterpret_cast(&mode)); + dt.call(&dt.glGetIntegerv)(GL_POLYGON_MODE,reinterpret_cast(mode)); dt.call(&dt.glGetIntegerv)(GL_FRONT_FACE,reinterpret_cast(&frontFace)); smoothEnable = dt.call(&dt.glIsEnabled)(GL_POLYGON_SMOOTH); stippleEnable = dt.call(&dt.glIsEnabled)(GL_POLYGON_STIPPLE); @@ -1100,6 +1196,12 @@ struct Transform inline Transform() : matrixMode(GL_MODELVIEW), normalize(GL_FALSE), rescaleNormal(GL_FALSE), depthClamp(GL_FALSE) { + size_t n = array_size( clipPlane ); + for (size_t i = 0; i < n; i++) + { + RegalAssertArrayIndex( clipPlane, i ); + clipPlane[i] = ClipPlane(); + } } inline size_t maxPlanes() const @@ -1119,13 +1221,15 @@ struct Transform inline const Transform &transition(DispatchTableGL &dt, Transform ¤t) const { - for (GLint i = 0; i < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES; i++) + size_t n = array_size( clipPlane ); + for (size_t i = 0; i < n; i++) { + RegalAssertArrayIndex( clipPlane, i ); if (current.clipPlane[i].enabled != clipPlane[i].enabled) - setEnable(dt, GL_CLIP_PLANE0 + i, clipPlane[i].enabled); + setEnable(dt, static_cast(GL_CLIP_PLANE0 + i), clipPlane[i].enabled); if (current.clipPlane[i].equation != clipPlane[i].equation) - dt.call(&dt.glClipPlane)(GL_CLIP_PLANE0 + i, clipPlane[i].equation.data); + dt.call(&dt.glClipPlane)(static_cast(GL_CLIP_PLANE0 + i), clipPlane[i].equation.data); } if (current.matrixMode != matrixMode) @@ -1146,9 +1250,11 @@ struct Transform inline std::string toString(const char *delim = "\n") const { string_list tmp; - for (GLint i = 0; i < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES; i++) + size_t n = array_size( clipPlane ); + for (size_t i = 0; i < n; i++) { - GLenum plane = GL_CLIP_PLANE0 + i; + RegalAssertArrayIndex( clipPlane, i ); + GLenum plane = static_cast(GL_CLIP_PLANE0 + i); enableToString(tmp, clipPlane[i].enabled, Token::toString(plane), delim); tmp << print_string("glClipPlane(",Token::toString(plane),", [ ", clipPlane[i].equation.data[0], ", ", clipPlane[i].equation.data[1], @@ -1164,10 +1270,11 @@ struct Transform inline void glClipPlane(GLenum plane, const GLdouble *equation) { - GLuint planeIndex = plane - GL_CLIP_PLANE0; - RegalAssert(planeIndex < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES); - if (planeIndex < REGAL_FIXED_FUNCTION_MAX_CLIP_PLANES) + GLint planeIndex = plane - GL_CLIP_PLANE0; + RegalAssert(planeIndex >= 0 && static_cast(planeIndex) < array_size( clipPlane )); + if (planeIndex >= 0 && static_cast(planeIndex) < array_size( clipPlane )) { + RegalAssertArrayIndex( clipPlane, planeIndex ); clipPlane[planeIndex].equation.data[0] = equation[0]; clipPlane[planeIndex].equation.data[1] = equation[1]; clipPlane[planeIndex].equation.data[2] = equation[2]; @@ -1392,14 +1499,18 @@ struct AccumBuffer struct Scissor { - GLboolean scissorTest[REGAL_MAX_VIEWPORTS]; // GL_SCISSOR_TEST - GLint scissorBox[REGAL_MAX_VIEWPORTS][4]; // GL_SCISSOR_BOX - bool valid[REGAL_MAX_VIEWPORTS]; + GLboolean scissorTest[REGAL_EMU_MAX_VIEWPORTS]; // GL_SCISSOR_TEST + GLint scissorBox[REGAL_EMU_MAX_VIEWPORTS][4]; // GL_SCISSOR_BOX + bool valid[REGAL_EMU_MAX_VIEWPORTS]; inline Scissor() { - for (GLuint ii=0; ii(ii), &scissorBox[ii][0]); valid[ii] = true; } } @@ -1439,18 +1554,22 @@ struct Scissor inline Scissor &swap(Scissor &other) { - std::swap_ranges(scissorTest,scissorTest+REGAL_MAX_VIEWPORTS,other.scissorTest); - std::swap_ranges(&scissorBox[0][0],&scissorBox[0][0]+(REGAL_MAX_VIEWPORTS*4),&other.scissorBox[0][0]); - std::swap_ranges(valid,valid+REGAL_MAX_VIEWPORTS,other.valid); + std::swap_ranges(scissorTest,scissorTest+REGAL_EMU_MAX_VIEWPORTS,other.scissorTest); + std::swap_ranges(&scissorBox[0][0],&scissorBox[0][0]+(REGAL_EMU_MAX_VIEWPORTS*4),&other.scissorBox[0][0]); + std::swap_ranges(valid,valid+REGAL_EMU_MAX_VIEWPORTS,other.valid); return *this; } inline Scissor &get(DispatchTableGL &dt) { - for (GLuint ii=0; ii(ii)); + dt.call(&dt.glGetIntegeri_v)(GL_SCISSOR_BOX, static_cast(ii), &scissorBox[ii][0]); valid[ii] = true; } return *this; @@ -1458,11 +1577,15 @@ struct Scissor inline const Scissor &set(DispatchTableGL &dt) const { - for (GLuint ii=0; ii(ii),scissorTest[ii]); if (valid[ii]) - dt.call(&dt.glScissorIndexedv)(ii, &scissorBox[ii][0]); + dt.call(&dt.glScissorIndexedv)(static_cast(ii), &scissorBox[ii][0]); } return *this; } @@ -1470,20 +1593,30 @@ struct Scissor inline std::string toString(const char *delim = "\n") const { string_list tmp; - for (GLuint ii=0; ii(ii), delim); + } + n = array_size( valid ); + for (size_t ii=0; ii REGAL_MAX_VIEWPORTS) - last = REGAL_MAX_VIEWPORTS; - for (GLuint ii = first; ii < last; ii++) + size_t last = static_cast(first + count); + size_t n = array_size( valid ); + if (last < n) { - scissorBox[ii][0] = v[0]; - scissorBox[ii][1] = v[1]; - scissorBox[ii][2] = v[2]; - scissorBox[ii][3] = v[3]; - valid[ii] = true; - v += 4; + for (size_t ii=first; ii(index) < array_size( valid )) { + RegalAssertArrayIndex( valid, index ); scissorBox[index][0] = left; scissorBox[index][1] = bottom; scissorBox[index][2] = width; @@ -1522,8 +1659,9 @@ struct Scissor void glScissorIndexedv( GLuint index, const GLint *v ) { - if (index < REGAL_MAX_VIEWPORTS) + if (static_cast(index) < array_size( valid )) { + RegalAssertArrayIndex( valid, index ); scissorBox[index][0] = v[0]; scissorBox[index][1] = v[1]; scissorBox[index][2] = v[2]; @@ -1539,14 +1677,16 @@ struct Scissor struct Viewport { - GLfloat viewport[REGAL_MAX_VIEWPORTS][4]; // GL_VIEWPORT - GLclampd depthRange[REGAL_MAX_VIEWPORTS][2]; // GL_DEPTH_RANGE - bool valid[REGAL_MAX_VIEWPORTS]; + GLfloat viewport[REGAL_EMU_MAX_VIEWPORTS][4]; // GL_VIEWPORT + GLclampd depthRange[REGAL_EMU_MAX_VIEWPORTS][2]; // GL_DEPTH_RANGE + bool valid[REGAL_EMU_MAX_VIEWPORTS]; inline Viewport() { - for (GLuint ii=0; ii(ii), &viewport[ii][0]); valid[ii] = true; } } inline Viewport &swap(Viewport &other) { - std::swap_ranges(&viewport[0][0],&viewport[0][0]+(REGAL_MAX_VIEWPORTS*4),&other.viewport[0][0]); - std::swap_ranges(&depthRange[0][0],&depthRange[0][0]+(REGAL_MAX_VIEWPORTS*2),&other.depthRange[0][0]); - std::swap_ranges(valid,valid+REGAL_MAX_VIEWPORTS,other.valid); + std::swap_ranges(&viewport[0][0],&viewport[0][0]+(REGAL_EMU_MAX_VIEWPORTS*4),&other.viewport[0][0]); + std::swap_ranges(&depthRange[0][0],&depthRange[0][0]+(REGAL_EMU_MAX_VIEWPORTS*2),&other.depthRange[0][0]); + std::swap_ranges(valid,valid+REGAL_EMU_MAX_VIEWPORTS,other.valid); return *this; } inline Viewport &get(DispatchTableGL &dt) { - for (GLuint ii=0; ii(ii), &viewport[ii][0]); + dt.call(&dt.glGetDoublei_v)(GL_DEPTH_RANGE, static_cast(ii), &depthRange[ii][0]); valid[ii] = true; } return *this; @@ -1597,29 +1743,37 @@ struct Viewport inline const Viewport &set(DispatchTableGL &dt) const { - dt.call(&dt.glDepthRangeArrayv)(0, REGAL_MAX_VIEWPORTS, &depthRange[0][0] ); - for (GLuint ii=0; ii(ii), &viewport[ii][0] ); + } return *this; } inline std::string toString(const char *delim = "\n") const { string_list tmp; - for (GLuint ii=0; ii void glDepthRange( T n, T f ) { - for (GLuint ii=0; ii(n); depthRange[ii][1] = static_cast(f); @@ -1629,9 +1783,9 @@ struct Viewport void glDepthRangeArrayv( GLuint first, GLsizei count, const GLdouble *v ) { GLuint last = first + count; - if (last > REGAL_MAX_VIEWPORTS) - last = REGAL_MAX_VIEWPORTS; - for (GLuint ii = first; ii < last; ii++) + if (last > REGAL_EMU_MAX_VIEWPORTS) + last = REGAL_EMU_MAX_VIEWPORTS; + for (size_t ii = first; ii < last; ii++) { depthRange[ii][0] = v[0]; depthRange[ii][1] = v[1]; @@ -1641,7 +1795,7 @@ struct Viewport void glDepthRangeIndexed( GLuint index, GLdouble n, GLdouble f ) { - if (index < REGAL_MAX_VIEWPORTS) + if (index < REGAL_EMU_MAX_VIEWPORTS) { depthRange[index][0] = n; depthRange[index][1] = f; @@ -1651,7 +1805,7 @@ struct Viewport void glViewport( GLint x, GLint y, GLsizei w, GLsizei h ) { Internal("Regal::State::Viewport::glViewport( ",x,", ",y,", ",w,", ",h," )"); - for (GLuint ii=0; ii(x); viewport[ii][1] = static_cast(y); @@ -1663,24 +1817,28 @@ struct Viewport void glViewportArrayv( GLuint first, GLsizei count, const GLfloat *v ) { - GLuint last = first + count; - if (last > REGAL_MAX_VIEWPORTS) - last = REGAL_MAX_VIEWPORTS; - for (GLuint ii = first; ii < last; ii++) + size_t n = array_size( valid ); + size_t last = static_cast(first + count); + if (last < n) { - viewport[ii][0] = v[0]; - viewport[ii][1] = v[1]; - viewport[ii][2] = v[2]; - viewport[ii][3] = v[3]; - valid[ii] = true; - v += 4; + for (size_t ii=first; ii(index) < array_size( valid )) { + RegalAssertArrayIndex( valid, index ); viewport[index][0] = x; viewport[index][1] = y; viewport[index][2] = w; @@ -1691,8 +1849,9 @@ struct Viewport void glViewportIndexedfv( GLuint index, const GLfloat *v ) { - if (index < REGAL_MAX_VIEWPORTS) + if (static_cast(index) < array_size( valid )) { + RegalAssertArrayIndex( valid, index ); viewport[index][0] = v[0]; viewport[index][1] = v[1]; viewport[index][2] = v[2]; @@ -1885,7 +2044,7 @@ struct Eval { RegalAssert(static_cast(GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4) == 8); RegalAssert(static_cast(GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4) == 8); - for (GLuint ii=0; ii<9; ii++) + for (size_t ii=0; ii<9; ii++) { map1dEnables[ii] = GL_FALSE; map2dEnables[ii] = GL_FALSE; @@ -1915,10 +2074,10 @@ struct Eval inline Eval &get(DispatchTableGL &dt) { autoNormal = dt.call(&dt.glIsEnabled)(GL_AUTO_NORMAL); - for (GLuint ii=0; ii<9; ii++) - map1dEnables[ii] = dt.call(&dt.glIsEnabled)(GL_MAP1_COLOR_4+ii); - for (GLuint ii=0; ii<9; ii++) - map2dEnables[ii] = dt.call(&dt.glIsEnabled)(GL_MAP2_COLOR_4+ii); + for (size_t ii=0; ii<9; ii++) + map1dEnables[ii] = dt.call(&dt.glIsEnabled)(static_cast(GL_MAP1_COLOR_4+ii)); + for (size_t ii=0; ii<9; ii++) + map2dEnables[ii] = dt.call(&dt.glIsEnabled)(static_cast(GL_MAP2_COLOR_4+ii)); dt.call(&dt.glGetDoublev)(GL_MAP1_GRID_DOMAIN, map1GridDomain); dt.call(&dt.glGetDoublev)(GL_MAP2_GRID_DOMAIN, map2GridDomain); dt.call(&dt.glGetIntegerv)(GL_MAP1_GRID_SEGMENTS,reinterpret_cast(&map1GridSegments)); @@ -1929,10 +2088,10 @@ struct Eval inline const Eval &set(DispatchTableGL &dt) const { setEnable(dt,GL_AUTO_NORMAL,autoNormal); - for (GLuint ii=0; ii<9; ii++) - setEnable(dt,GL_MAP1_COLOR_4+ii,map1dEnables[ii]); - for (GLuint ii=0; ii<9; ii++) - setEnable(dt,GL_MAP2_COLOR_4+ii,map1dEnables[ii]); + for (size_t ii=0; ii<9; ii++) + setEnable(dt,static_cast(GL_MAP1_COLOR_4+ii),map1dEnables[ii]); + for (size_t ii=0; ii<9; ii++) + setEnable(dt,static_cast(GL_MAP2_COLOR_4+ii),map2dEnables[ii]); dt.call(&dt.glMapGrid1d)(map1GridSegments, map1GridDomain[0], map1GridDomain[1]); dt.call(&dt.glMapGrid2d)(map2GridSegments[0], map2GridDomain[0], map2GridDomain[1], map2GridSegments[1], map2GridDomain[2], map2GridDomain[3]); @@ -1943,10 +2102,10 @@ struct Eval { string_list tmp; enableToString(tmp, autoNormal, "GL_AUTO_NORMAL",delim); - for (GLuint ii=0; ii<9; ii++) - enableToString(tmp,map1dEnables[ii],Token::toString(GL_MAP1_COLOR_4+ii),delim); - for (GLuint ii=0; ii<9; ii++) - enableToString(tmp,map2dEnables[ii],Token::toString(GL_MAP2_COLOR_4+ii),delim); + for (size_t ii=0; ii<9; ii++) + enableToString(tmp,map1dEnables[ii],Token::toString(static_cast(GL_MAP1_COLOR_4+ii)),delim); + for (size_t ii=0; ii<9; ii++) + enableToString(tmp,map2dEnables[ii],Token::toString(static_cast(GL_MAP2_COLOR_4+ii)),delim); tmp << print_string("glMapGrid1d(",map1GridSegments,",",map1GridDomain[0],",",map1GridDomain[1],");",delim); tmp << print_string("glMapGrid2d(",map2GridSegments[0],",",map2GridDomain[0],",",map2GridDomain[1], map2GridSegments[1],",",map2GridDomain[2],",",map2GridDomain[3],");",delim); @@ -2089,8 +2248,12 @@ struct Point distanceAttenuation[0] = 1.0f; distanceAttenuation[1] = 0.0f; distanceAttenuation[2] = 0.0f; - for (GLuint ii=0; ii(&spriteCoordOrigin)); - for (GLuint ii=0; ii(GL_TEXTURE0+ii),GL_POINT_SPRITE,GL_COORD_REPLACE,&coord); + RegalAssertArrayIndex( coordReplace, ii ); coordReplace[ii] = static_cast(coord); } return *this; @@ -2137,8 +2301,12 @@ struct Point dt.call(&dt.glPointParameterf)(GL_POINT_FADE_THRESHOLD_SIZE,fadeThresholdSize); dt.call(&dt.glPointParameterfv)(GL_POINT_DISTANCE_ATTENUATION,distanceAttenuation); dt.call(&dt.glPointParameteri)(GL_POINT_SPRITE_COORD_ORIGIN,spriteCoordOrigin); - for (GLuint ii=0; ii(GL_TEXTURE0+ii),GL_POINT_SPRITE,GL_COORD_REPLACE,coordReplace[ii]); + } return *this; } @@ -2155,28 +2323,30 @@ struct Point distanceAttenuation[1],", ", distanceAttenuation[2]," ]);",delim); tmp << print_string("glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN",Token::toString(spriteCoordOrigin),");",delim); - for (GLuint ii=0; ii(GL_TEXTURE0+ii)),",GL_POINT_SPRITE,GL_COORD_REPLACE,",coordReplace[ii],");",delim); + } return tmp; } template void glMultiTexEnv(GLenum texunit, GLenum target, GLenum pname, T param) { - if ((target == GL_POINT_SPRITE) && (pname == GL_COORD_REPLACE)) - { - GLint unit = texunit = GL_TEXTURE0; - if ((unit >= 0) && (unit(param); - } + glMultiTexEnvv(texunit, target, pname, ¶m); } template void glMultiTexEnvv(GLenum texunit, GLenum target, GLenum pname, const T *params) { if ((target == GL_POINT_SPRITE) && (pname == GL_COORD_REPLACE)) { - GLint unit = texunit = GL_TEXTURE0; - if ((unit >= 0) && (unit= 0) && (static_cast(unit) < array_size( coordReplace ))) + { + RegalAssertArrayIndex( coordReplace, unit ); coordReplace[unit] = static_cast(params[0]); + } } } @@ -2256,7 +2426,7 @@ struct PolygonStipple { string_list tmp; tmp << print_string("glPolygonStipple(["); - for (int ii=0; ii<(32*4)-1; ii++) + for (size_t ii=0; ii<(32*4)-1; ii++) tmp << print_string(" 0x",hex(pattern[ii]),","); tmp << print_string(" 0x",hex(pattern[(32*4)-1]),"]);",delim); return tmp; @@ -2264,7 +2434,7 @@ struct PolygonStipple void glPolygonStipple( const GLubyte *p ) { - for (int ii=0; ii<(32*4); ii++) + for (size_t ii=0; ii<(32*4); ii++) pattern[ii] = p[ii]; } }; @@ -2280,13 +2450,13 @@ struct ColorBuffer GLboolean alphaTest; // GL_ALPHA_TEST GLenum alphaTestFunc; // GL_ALPHA_TEST_FUNC GLclampf alphaTestRef; // GL_ALPHA_TEST_REF - GLboolean blend[REGAL_MAX_DRAW_BUFFERS]; // GL_BLEND - GLenum blendSrcRgb[REGAL_MAX_DRAW_BUFFERS]; // GL_BLEND_SRC_RGB - GLenum blendSrcAlpha[REGAL_MAX_DRAW_BUFFERS]; // GL_BLEND_SRC_ALPHA - GLenum blendDstRgb[REGAL_MAX_DRAW_BUFFERS]; // GL_BLEND_DST_RGB - GLenum blendDstAlpha[REGAL_MAX_DRAW_BUFFERS]; // GL_BLEND_DST_ALPHA - GLenum blendEquationRgb[REGAL_MAX_DRAW_BUFFERS]; // GL_BLEND_EQUATION_RGB - GLenum blendEquationAlpha[REGAL_MAX_DRAW_BUFFERS]; // GL_BLEND_EQUATION_ALPHA + GLboolean blend[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_BLEND + GLenum blendSrcRgb[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_BLEND_SRC_RGB + GLenum blendSrcAlpha[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_BLEND_SRC_ALPHA + GLenum blendDstRgb[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_BLEND_DST_RGB + GLenum blendDstAlpha[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_BLEND_DST_ALPHA + GLenum blendEquationRgb[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_BLEND_EQUATION_RGB + GLenum blendEquationAlpha[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_BLEND_EQUATION_ALPHA GLclampf blendColor[4]; // GL_BLEND_COLOR GLboolean framebufferSRGB; // GL_FRAMEBUFFER_SRGB GLboolean dither; // GL_DITHER @@ -2294,10 +2464,10 @@ struct ColorBuffer GLboolean colorLogicOp; // GL_COLOR_LOGIC_OP GLenum logicOpMode; // GL_LOGIC_OP_MODE GLuint indexWritemask; // GL_INDEX_WRITEMASK - GLboolean colorWritemask[REGAL_MAX_DRAW_BUFFERS][4]; // GL_COLOR_WRITEMASK + GLboolean colorWritemask[REGAL_EMU_MAX_DRAW_BUFFERS][4]; // GL_COLOR_WRITEMASK GLclampf colorClearValue[4]; // GL_COLOR_CLEAR_VALUE GLfloat indexClearValue; // GL_INDEX_CLEAR_VALUE - GLenum drawBuffers[REGAL_MAX_DRAW_BUFFERS]; // GL_DRAW_BUFERi + GLenum drawBuffers[REGAL_EMU_MAX_DRAW_BUFFERS]; // GL_DRAW_BUFERi bool valid; inline ColorBuffer() @@ -2325,8 +2495,17 @@ struct ColorBuffer colorClearValue[2] = 0.0f; colorClearValue[3] = 0.0f; - for (GLuint ii=0; ii(&drawBuffers[ii])); + size_t n = array_size( drawBuffers ); + for (size_t ii=0; ii(GL_DRAW_BUFFER0+ii), reinterpret_cast(&drawBuffers[ii])); + } valid = true; } } @@ -2364,13 +2547,13 @@ struct ColorBuffer std::swap(alphaTest,other.alphaTest); std::swap(alphaTestFunc,other.alphaTestFunc); std::swap(alphaTestRef,other.alphaTestRef); - std::swap_ranges(blend,blend+REGAL_MAX_DRAW_BUFFERS,other.blend); - std::swap_ranges(blendSrcRgb,blendSrcRgb+REGAL_MAX_DRAW_BUFFERS,other.blendSrcRgb); - std::swap_ranges(blendSrcAlpha,blendSrcAlpha+REGAL_MAX_DRAW_BUFFERS,other.blendSrcAlpha); - std::swap_ranges(blendDstRgb,blendDstRgb+REGAL_MAX_DRAW_BUFFERS,other.blendDstRgb); - std::swap_ranges(blendDstAlpha,blendDstAlpha+REGAL_MAX_DRAW_BUFFERS,other.blendDstAlpha); - std::swap_ranges(blendEquationRgb,blendEquationRgb+REGAL_MAX_DRAW_BUFFERS,other.blendEquationRgb); - std::swap_ranges(blendEquationAlpha,blendEquationAlpha+REGAL_MAX_DRAW_BUFFERS,other.blendEquationAlpha); + std::swap_ranges(blend,blend+REGAL_EMU_MAX_DRAW_BUFFERS,other.blend); + std::swap_ranges(blendSrcRgb,blendSrcRgb+REGAL_EMU_MAX_DRAW_BUFFERS,other.blendSrcRgb); + std::swap_ranges(blendSrcAlpha,blendSrcAlpha+REGAL_EMU_MAX_DRAW_BUFFERS,other.blendSrcAlpha); + std::swap_ranges(blendDstRgb,blendDstRgb+REGAL_EMU_MAX_DRAW_BUFFERS,other.blendDstRgb); + std::swap_ranges(blendDstAlpha,blendDstAlpha+REGAL_EMU_MAX_DRAW_BUFFERS,other.blendDstAlpha); + std::swap_ranges(blendEquationRgb,blendEquationRgb+REGAL_EMU_MAX_DRAW_BUFFERS,other.blendEquationRgb); + std::swap_ranges(blendEquationAlpha,blendEquationAlpha+REGAL_EMU_MAX_DRAW_BUFFERS,other.blendEquationAlpha); std::swap_ranges(blendColor,blendColor+4,other.blendColor); std::swap(framebufferSRGB,other.framebufferSRGB); std::swap(dither,other.dither); @@ -2378,10 +2561,10 @@ struct ColorBuffer std::swap(colorLogicOp,other.colorLogicOp); std::swap(logicOpMode,other.logicOpMode); std::swap(indexWritemask,other.indexWritemask); - std::swap_ranges(&colorWritemask[0][0],&colorWritemask[0][0]+(REGAL_MAX_DRAW_BUFFERS*4),&other.colorWritemask[0][0]); + std::swap_ranges(&colorWritemask[0][0],&colorWritemask[0][0]+(REGAL_EMU_MAX_DRAW_BUFFERS*4),&other.colorWritemask[0][0]); std::swap_ranges(colorClearValue,colorClearValue+4,other.colorClearValue); std::swap(indexClearValue,other.indexClearValue); - std::swap_ranges(drawBuffers,drawBuffers+REGAL_MAX_DRAW_BUFFERS,other.drawBuffers); + std::swap_ranges(drawBuffers,drawBuffers+REGAL_EMU_MAX_DRAW_BUFFERS,other.drawBuffers); return *this; } @@ -2392,20 +2575,48 @@ struct ColorBuffer alphaTest = dt.call(&dt.glIsEnabled)(GL_ALPHA_TEST); dt.call(&dt.glGetIntegerv)(GL_ALPHA_TEST_FUNC,reinterpret_cast(&alphaTestFunc)); dt.call(&dt.glGetFloatv)(GL_ALPHA_TEST_REF,&alphaTestRef); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blend, ii ); blend[ii] = dt.call(&dt.glIsEnabledi)(GL_BLEND, ii); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blendSrcRgb, ii ); dt.call(&dt.glGetIntegeri_v)(GL_BLEND_SRC_RGB, ii, reinterpret_cast(&blendSrcRgb[ii])); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blendSrcAlpha, ii ); dt.call(&dt.glGetIntegeri_v)(GL_BLEND_SRC_ALPHA, ii, reinterpret_cast(&blendSrcAlpha[ii])); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blendDstRgb, ii ); dt.call(&dt.glGetIntegeri_v)(GL_BLEND_DST_RGB, ii, reinterpret_cast(&blendDstRgb[ii])); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blendDstAlpha, ii ); dt.call(&dt.glGetIntegeri_v)(GL_BLEND_DST_ALPHA, ii, reinterpret_cast(&blendDstAlpha[ii])); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blendEquationRgb, ii ); dt.call(&dt.glGetIntegeri_v)(GL_BLEND_EQUATION_RGB, ii, reinterpret_cast(&blendEquationRgb[ii])); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blendEquationAlpha, ii ); dt.call(&dt.glGetIntegeri_v)(GL_BLEND_EQUATION_ALPHA, ii, reinterpret_cast(&blendEquationAlpha[ii])); + } dt.call(&dt.glGetFloatv)(GL_BLEND_COLOR,blendColor); framebufferSRGB = dt.call(&dt.glIsEnabled)(GL_FRAMEBUFFER_SRGB); dither = dt.call(&dt.glIsEnabled)(GL_DITHER); @@ -2413,12 +2624,16 @@ struct ColorBuffer colorLogicOp = dt.call(&dt.glIsEnabled)(GL_COLOR_LOGIC_OP); dt.call(&dt.glGetIntegerv)(GL_LOGIC_OP_MODE, reinterpret_cast(&logicOpMode)); dt.call(&dt.glGetIntegerv)(GL_INDEX_WRITEMASK, reinterpret_cast(&indexWritemask)); - for (GLuint ii=0; ii(&drawBuffers[ii])); + n = array_size( drawBuffers ); + for (size_t ii=0; ii(GL_DRAW_BUFFER0+ii), reinterpret_cast(&drawBuffers[ii])); + } return *this; } @@ -2428,12 +2643,28 @@ struct ColorBuffer dt.call(&dt.glClampColor)(GL_CLAMP_READ_COLOR,clampReadColor); setEnable(dt,GL_ALPHA_TEST,alphaTest); dt.call(&dt.glAlphaFunc)(alphaTestFunc,alphaTestRef); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blend, ii ); setEnablei(dt,GL_BLEND,ii,blend[ii]); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blendSrcRgb, ii ); dt.call(&dt.glBlendFuncSeparatei)(ii,blendSrcRgb[ii],blendSrcAlpha[ii],blendDstRgb[ii],blendDstAlpha[ii]); - for (GLuint ii=0; ii(n); ii++) + { + RegalAssertArrayIndex( blendEquationRgb, ii ); dt.call(&dt.glBlendEquationSeparatei)(ii,blendEquationRgb[ii],blendEquationAlpha[ii]); + } dt.call(&dt.glBlendColor)(blendColor[0],blendColor[1],blendColor[2],blendColor[3]); setEnable(dt,GL_FRAMEBUFFER_SRGB,framebufferSRGB); setEnable(dt,GL_DITHER,dither); @@ -2441,12 +2672,15 @@ struct ColorBuffer setEnable(dt,GL_COLOR_LOGIC_OP,colorLogicOp); dt.call(&dt.glLogicOp)(logicOpMode); dt.call(&dt.glIndexMask)(indexWritemask); - for (GLuint ii=0; ii= REGAL_EMU_MAX_DRAW_BUFFERS); + dt.call(&dt.glDrawBuffers)(REGAL_EMU_MAX_DRAW_BUFFERS, drawBuffers); + } return *this; } @@ -2457,12 +2691,28 @@ struct ColorBuffer tmp << print_string("glClampColor(GL_CLAMP_READ_COLOR",",",Token::toString(clampReadColor),");",delim); enableToString(tmp, alphaTest, "GL_ALPHA_TEST",delim); tmp << print_string("glAlphaFunc(",Token::toString(alphaTestFunc),",",alphaTestRef,");",delim); - for (GLuint ii=0; ii(ii),delim); + } + n = array_size( blendSrcRgb ); + RegalAssert(array_size( blendSrcAlpha ) == n); + RegalAssert(array_size( blendDstRgb ) == n); + RegalAssert(array_size( blendDstAlpha ) == n); + for (size_t ii=0; ii= REGAL_EMU_MAX_DRAW_BUFFERS ); + for (size_t ii=0; ii(stop); + size_t n = array_size( drawBuffers ); + if (s < n) { - for (int ii=0; ii(params[ii]); } @@ -3110,7 +3403,7 @@ struct PixelMode return; } RegalAssert(p); - for (int ii=0; ii<4; ii++) + for (size_t ii=0; ii<4; ii++) p[ii] = static_cast(params[ii]); } @@ -3460,6 +3753,13 @@ struct Lighting lightModelAmbient[2] = 0.2f; lightModelAmbient[3] = 1.0f; + size_t n = array_size( lights ); + for (size_t ii=0; ii(&lightModelColorControl)); - for (GLuint ii=0; ii(GL_LIGHT0+ii)); + } return *this; } @@ -3523,8 +3831,12 @@ struct Lighting dt.call(&dt.glLightModeli)(GL_LIGHT_MODEL_LOCAL_VIEWER,lightModelLocalViewer); dt.call(&dt.glLightModeli)(GL_LIGHT_MODEL_TWO_SIDE,lightModelTwoSide); dt.call(&dt.glLightModeli)(GL_LIGHT_MODEL_COLOR_CONTROL,lightModelColorControl); - for (GLuint ii=0; ii(GL_LIGHT0+ii)); + } return *this; } @@ -3545,8 +3857,12 @@ struct Lighting tmp << print_string("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,",lightModelLocalViewer,");",delim); tmp << print_string("glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,",lightModelTwoSide,");",delim); tmp << print_string("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,",Token::toString(lightModelColorControl),");",delim); - for (GLuint ii=0; ii(GL_LIGHT0+ii),delim); + } return tmp; } @@ -3560,10 +3876,13 @@ struct Lighting { GLint ii = static_cast(light-GL_LIGHT0); - if (ii < 0 || ii >= REGAL_FIXED_FUNCTION_MAX_LIGHTS) + size_t n = array_size( lights ); + + if (ii < 0 || static_cast(ii) >= n) return; - LightingLight &ll = State::Lighting::lights[ii]; + RegalAssertArrayIndex( lights, ii ); + LightingLight &ll = lights[ii]; switch (pname) { @@ -3589,12 +3908,15 @@ struct Lighting template void glLightv( GLenum light, GLenum pname, const T *params ) { - GLint ii = static_cast(light-GL_LIGHT0); + size_t ii = static_cast(light-GL_LIGHT0); - if (ii < 0 || ii >= REGAL_FIXED_FUNCTION_MAX_LIGHTS) + size_t n = array_size( lights ); + + if (light < GL_LIGHT0 || ii >= n) return; - LightingLight &ll = State::Lighting::lights[ii]; + RegalAssertArrayIndex( lights, ii ); + LightingLight &ll = lights[ii]; GLfloat *p = NULL; switch (pname) @@ -3619,7 +3941,7 @@ struct Lighting } GLuint stop = (pname == GL_SPOT_DIRECTION) ? 3 : 4; - for (GLuint ii=0; ii(params[ii]); } @@ -3659,13 +3981,13 @@ struct Lighting switch (face) { case GL_FRONT: - State::Lighting::front.shininess = static_cast(param); + front.shininess = static_cast(param); break; case GL_BACK: - State::Lighting::back.shininess = static_cast(param); + back.shininess = static_cast(param); break; case GL_FRONT_AND_BACK: - State::Lighting::front.shininess = State::Lighting::back.shininess = static_cast(param); + front.shininess = back.shininess = static_cast(param); break; default: break; @@ -3693,7 +4015,7 @@ struct Lighting return; } - for (GLuint ii=0; ii<2; ii++) + for (size_t ii=0; ii<2; ii++) { if (f[ii]) { @@ -3730,7 +4052,7 @@ struct Lighting } if (p) - for (GLuint jj=0; jj(params[jj]); } } diff --git a/src/regal/RegalTexC.cpp b/src/regal/RegalTexC.cpp index af0ec52..8b58fe5 100644 --- a/src/regal/RegalTexC.cpp +++ b/src/regal/RegalTexC.cpp @@ -44,6 +44,7 @@ REGAL_GLOBAL_BEGIN #include "RegalTexC.h" #include "RegalContext.h" +#include "RegalToken.h" #include "RegalPixelConversions.h" REGAL_GLOBAL_END @@ -325,28 +326,35 @@ TexC::Reset_() { unpackPSS.Reset(); - currentTextureUnit = GL_TEXTURE0; - for ( size_t i = 0; i < REGAL_EMU_MAX_TEXTURE_UNITS; ++i ) + currentTextureUnit = 0; + const size_t n = array_size( textureUnitArrayState ); + for ( size_t i = 0; i < n; ++i ) { + RegalAssertArrayIndex( textureUnitArrayState, i ); textureUnitArrayState[ i ].UnbindAll(); } textureZero = TextureState(); } TextureState * -TexC::GetBoundTexture_( GLenum textureUnit, GLenum target ) +TexC::GetBoundTexture_( GLenum texture, GLenum target ) { - size_t i = textureUnit - GL_TEXTURE0; - if ( REGAL_EMU_MAX_TEXTURE_UNITS <= i ) + return GetBoundTextureUnit_( static_cast(texture-GL_TEXTURE0), target ); +} + +TextureState * +TexC::GetBoundTextureUnit_( GLuint textureUnit, GLenum target ) +{ + size_t i = static_cast(textureUnit); + const size_t n = array_size( textureUnitArrayState ); + if ( i >= n ) { - RegalAssert( i < REGAL_EMU_MAX_TEXTURE_UNITS ); + RegalAssert( i < n ); return NULL; } + RegalAssertArrayIndex( textureUnitArrayState, i ); TextureState* ts = textureUnitArrayState[ i ].GetBinding( target ); - if ( ts != NULL ) { - return ts; - } - return &textureZero; + return ( ts ? ts : &textureZero ); } TextureState * @@ -369,17 +377,17 @@ TexC::GetTexture_( GLuint texture ) void TexC::GetFormatAndType( GLenum target, GLint level, GLenum* format, GLenum* type ) { - GetBoundTexture_( currentTextureUnit, target )->GetFormatAndType( level, format, type ); + TextureState* p = GetBoundTextureUnit_( currentTextureUnit, target ); + if (p) + p->GetFormatAndType( level, format, type ); } void TexC::ShadowTexImage2D( GLenum target, GLint level, GLenum format, GLenum type ) { - if ( REGAL_EMU_MAX_TEXTURE_UNITS <= currentTextureUnit - GL_TEXTURE0 ) { - return; - } - - GetBoundTexture_( currentTextureUnit, target )->SetFormatAndType( level, format, type ); + TextureState* p = GetBoundTextureUnit_( currentTextureUnit, target ); + if (p) + p->SetFormatAndType( level, format, type ); } void @@ -408,15 +416,18 @@ void TexC::ShadowDeleteTextures( GLsizei n, const GLuint* textures ) void TexC::ShadowActiveTexture( GLenum texture ) { - currentTextureUnit = texture; + if (validTextureEnum(texture)) + currentTextureUnit = texture - GL_TEXTURE0; } void TexC::ShadowBindTexture( GLenum target, GLuint texture ) { - size_t i = currentTextureUnit - GL_TEXTURE0; - if ( REGAL_EMU_MAX_TEXTURE_UNITS <= i ) { + size_t i = currentTextureUnit; + const size_t n = array_size( textureUnitArrayState ); + if ( n <= i ) return; - } + + RegalAssertArrayIndex( textureUnitArrayState, i ); TextureUnitState& textureUnitState = textureUnitArrayState[ i ]; if ( texture == TEXTURE_ZERO ) { @@ -432,11 +443,9 @@ void TexC::ShadowBindTexture( GLenum target, GLuint texture ) void TexC::ShadowGenerateMipmap( GLenum target ) { - if ( REGAL_EMU_MAX_TEXTURE_UNITS <= currentTextureUnit - GL_TEXTURE0 ) { - return; - } - - GetBoundTexture_( currentTextureUnit, target )->SimulateComputeMipMaps(); + TextureState* p = GetBoundTextureUnit_( currentTextureUnit, target ); + if (p) + p->SimulateComputeMipMaps(); } void diff --git a/src/regal/RegalTexC.h b/src/regal/RegalTexC.h index c39c497..b3cec90 100644 --- a/src/regal/RegalTexC.h +++ b/src/regal/RegalTexC.h @@ -187,7 +187,8 @@ struct TexC void Reset_(); - TextureState* GetBoundTexture_( GLenum textureUnit, GLenum target ); + TextureState* GetBoundTexture_( GLenum textureEnum, GLenum target ); + TextureState* GetBoundTextureUnit_( GLuint textureUnit, GLenum target ); TextureState* GetTexture_( GLuint texture ); void GetFormatAndType( GLenum target, GLint level, GLenum* format, GLenum* type ); @@ -217,8 +218,8 @@ struct TexC PixelStorageStateGLES20 unpackPSS; - GLenum currentTextureUnit; - TextureUnitState textureUnitArrayState[ REGAL_EMU_MAX_TEXTURE_UNITS ]; + GLuint currentTextureUnit; + TextureUnitState textureUnitArrayState[ REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS ]; TextureState textureZero; }; diff --git a/src/regal/RegalUtil.h b/src/regal/RegalUtil.h index b4dcbe9..8e0caff 100644 --- a/src/regal/RegalUtil.h +++ b/src/regal/RegalUtil.h @@ -552,6 +552,15 @@ inline bool getEnv(const char * const varname, std::string &var, const bool enab return false; } +// +// Array size - the number of elements of a C array +// +// http://stackoverflow.com/questions/437150/can-someone-explain-this-template-code-that-gives-me-the-size-of-an-array +// + +template +inline size_t array_size(const T (&)[N]) { return N; } + // // RegalCheckGLError // @@ -586,15 +595,6 @@ inline bool getEnv(const char * const varname, std::string &var, const bool enab void AssertFunction(const char *file, const std::size_t line, const char *expr); #endif -// -// Array size - the number of elements of a C array -// -// http://stackoverflow.com/questions/437150/can-someone-explain-this-template-code-that-gives-me-the-size-of-an-array -// - -template -inline size_t array_size(const T (&)[N]) { return N; } - // // // diff --git a/src/regal/RegalVao.h b/src/regal/RegalVao.h index ca1dbf5..4b96fef 100644 --- a/src/regal/RegalVao.h +++ b/src/regal/RegalVao.h @@ -53,8 +53,6 @@ REGAL_GLOBAL_END REGAL_NAMESPACE_BEGIN -#define REGAL_VAO_NUM_ARRAYS 16 - namespace Emu { @@ -90,7 +88,7 @@ struct Vao Object() : vertexBuffer( 0 ), indexBuffer( 0 ) {} GLuint vertexBuffer; GLuint indexBuffer; - Array a[ REGAL_VAO_NUM_ARRAYS ]; + Array a[ REGAL_EMU_MAX_VERTEX_ATTRIBS ]; }; shared_map objects; @@ -105,34 +103,36 @@ struct Vao GLuint maxName; // to alias vertex arrays to generic attribs - GLuint ffAttrMap[ REGAL_VAO_NUM_ARRAYS ]; - GLuint ffAttrInvMap[ REGAL_VAO_NUM_ARRAYS ]; + GLuint ffAttrMap[ REGAL_EMU_MAX_VERTEX_ATTRIBS ]; + GLuint ffAttrInvMap[ REGAL_EMU_MAX_VERTEX_ATTRIBS ]; GLuint ffAttrTexBegin; GLuint ffAttrTexEnd; GLuint ffAttrNumTex; - GLuint maxVertexAttribs; + GLuint max_vertex_attribs; void Init( RegalContext &ctx ) { maxName = 0; clientActiveTexture = GL_TEXTURE0; - maxVertexAttribs = ctx.info->maxVertexAttribs; - RegalAssert( maxVertexAttribs <= REGAL_VAO_NUM_ARRAYS ); + max_vertex_attribs = ctx.info->gl_max_vertex_attribs; + RegalAssert( max_vertex_attribs <= REGAL_EMU_MAX_VERTEX_ATTRIBS ); + if (max_vertex_attribs > REGAL_EMU_MAX_VERTEX_ATTRIBS) + max_vertex_attribs = REGAL_EMU_MAX_VERTEX_ATTRIBS; RegalContext *sharingWith = ctx.groupInitializedContext(); if (sharingWith) objects = sharingWith->vao->objects; // we have RFF2A maps for sets of 8 and 16 attributes. if - // REGAL_VAO_NUM_ARRAYS > 16 a new map needs to be added + // REGAL_EMU_MAX_VERTEX_ATTRIBS > 16 a new map needs to be added - RegalAssert( REGAL_VAO_NUM_ARRAYS <= 16 ); + RegalAssert( REGAL_EMU_MAX_VERTEX_ATTRIBS <= 16 ); - if ( maxVertexAttribs >= 16 ) + if ( max_vertex_attribs >= 16 ) { - RegalAssert( REGAL_VAO_NUM_ARRAYS == 16); - //RegalOutput( "Setting up for %d Vertex Attribs\n", maxVertexAttribs ); + RegalAssert( REGAL_EMU_MAX_VERTEX_ATTRIBS == 16); + //RegalOutput( "Setting up for %d Vertex Attribs\n", max_vertex_attribs ); for( int i = 0; i < 16; i++ ) { ffAttrMap[i] = RFF2AMap16[i]; @@ -140,23 +140,27 @@ struct Vao } ffAttrTexBegin = RFF2ATexBegin16; ffAttrTexEnd = RFF2ATexEnd16; + if (max_vertex_attribs > 16) + max_vertex_attribs = 16; } else { - RegalAssert( maxVertexAttribs >= 8 ); + RegalAssert( max_vertex_attribs >= 8 ); //RegalOutput( "Setting up for 8 Vertex Attribs" ); for( int i = 0; i < 8; i++ ) { ffAttrMap[i] = RFF2AMap8[i]; ffAttrInvMap[i] = RFF2AInvMap8[i]; } - for( int i = 8; i < REGAL_VAO_NUM_ARRAYS; i++ ) + for( int i = 8; i < REGAL_EMU_MAX_VERTEX_ATTRIBS; i++ ) { ffAttrMap[i] = GLuint(-1); ffAttrInvMap[i] = GLuint(-1); } ffAttrTexBegin = RFF2ATexBegin8; ffAttrTexEnd = RFF2ATexEnd8; + if (max_vertex_attribs > 8) + max_vertex_attribs = 8; } ffAttrNumTex = ffAttrTexEnd - ffAttrTexBegin; @@ -212,15 +216,13 @@ struct Vao tbl.glBindBuffer( GL_ARRAY_BUFFER, vao.vertexBuffer ); tbl.glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vao.indexBuffer ); GLuint lastBuffer = vao.vertexBuffer; - for( GLuint i = 0; i < maxVertexAttribs; i++ ) + RegalAssert( max_vertex_attribs <= REGAL_EMU_MAX_VERTEX_ATTRIBS ); + for( GLuint i = 0; i < max_vertex_attribs; i++ ) { Array &a = vao.a[ i ]; if( a.buffer != lastBuffer ) { - //GLint e = tbl.glGetError(); tbl.glBindBuffer( GL_ARRAY_BUFFER, a.buffer ); - //e = tbl.glGetError(); - //RegalOutput( "Binding ARRAY_BUFFER %d - %d\n", a.buffer, e ); lastBuffer = a.buffer; } @@ -281,7 +283,11 @@ struct Vao void EnableDisableVertexAttribArray( RegalContext *ctx, GLboolean enable, GLuint index ) { - RegalAssert( index < maxVertexAttribs ); + RegalAssert( index < REGAL_EMU_MAX_VERTEX_ATTRIBS ); + RegalAssert( index < max_vertex_attribs ); + if (index >= max_vertex_attribs || index >= REGAL_EMU_MAX_VERTEX_ATTRIBS) + return; + DispatchTableGL &tbl = ctx->dispatcher.emulation; Array &a = objects[current].a[index]; a.enabled = enable; @@ -314,7 +320,9 @@ struct Vao if ( ctx->depthBeginEnd ) return; - if (index >= maxVertexAttribs) + RegalAssert( index < REGAL_EMU_MAX_VERTEX_ATTRIBS ); + RegalAssert( index < max_vertex_attribs ); + if (index >= max_vertex_attribs || index >= REGAL_EMU_MAX_VERTEX_ATTRIBS ) return; switch (size) @@ -377,17 +385,11 @@ struct Vao //<> return; //<> } - if( index == GLuint(~0) ) - { - return; - } - if( index >= maxVertexAttribs ) - { - return; - } - RegalAssert( index < maxVertexAttribs ); - RegalAssert( currObject != NULL ); + RegalAssert( index < max_vertex_attribs ); + RegalAssert( index < REGAL_EMU_MAX_VERTEX_ATTRIBS ); Array &a = objects[current].a[index]; + + RegalAssert( currObject != NULL ); a.buffer = currObject->vertexBuffer; a.size = size; a.type = type; @@ -404,7 +406,8 @@ struct Vao { UNUSED_PARAMETER(ctx); RegalAssert( currObject != NULL ); - for( GLuint i = 0; i < maxVertexAttribs; i++ ) + RegalAssert( max_vertex_attribs <= REGAL_EMU_MAX_VERTEX_ATTRIBS ); + for( GLuint i = 0; i < max_vertex_attribs; i++ ) { #if !REGAL_NO_ASSERT const Array &a = currObject->a[ i ]; @@ -415,6 +418,9 @@ struct Vao template void GetAttrib( GLint index, GLenum pname, T *params ) { + if (index >= REGAL_EMU_MAX_VERTEX_ATTRIBS) + return; + Array &a = objects[current].a[index]; switch( pname ) { @@ -425,7 +431,6 @@ struct Vao *params = static_cast(a.buffer); break; case GL_VERTEX_ATTRIB_ARRAY_SIZE: - //if( index == 3 ) RegalOutput( "Returning %d for index 3 from VAO GetAttrib for SIZE\n", a.size ); *params = static_cast(a.size); break; case GL_VERTEX_ATTRIB_ARRAY_TYPE: @@ -443,8 +448,12 @@ struct Vao break; } } + template void GetAttrib( GLint index, GLenum pname, T **params ) { + if (index >= REGAL_EMU_MAX_VERTEX_ATTRIBS) + return; + Array &a = objects[current].a[index]; switch( pname ) { @@ -481,6 +490,9 @@ struct Vao bool GetVertexAttribPointerv( GLuint index, GLenum pname, GLvoid **pointer) { + if (index >= REGAL_EMU_MAX_VERTEX_ATTRIBS) + return false; + if ( pname != GL_VERTEX_ATTRIB_ARRAY_POINTER ) return false; @@ -513,7 +525,7 @@ struct Vao case GL_TEXTURE_COORD_ARRAY: { GLuint index = clientActiveTexture - GL_TEXTURE0; - RegalAssert(index < REGAL_VAO_NUM_ARRAYS); + RegalAssert(index < REGAL_EMU_MAX_VERTEX_ATTRIBS); if ( index >= ffAttrNumTex ) { Warning("Texture unit out of range: ", index, " >= ", ffAttrNumTex, ". Clamping to supported maximum."); @@ -721,7 +733,7 @@ struct Vao GLint index = _texture - GL_TEXTURE0; - if (index >= 0 && index < REGAL_VAO_NUM_ARRAYS) + if (index >= 0 && index < REGAL_EMU_MAX_VERTEX_ATTRIBS) clientActiveTexture = _texture; } diff --git a/src/regal/RegalX11.cpp b/src/regal/RegalX11.cpp index 593e67e..71c44c1 100644 --- a/src/regal/RegalX11.cpp +++ b/src/regal/RegalX11.cpp @@ -96,8 +96,8 @@ extern "C" { } static Colormap dummyColormap = 0; - - REGAL_DECL Colormap + + REGAL_DECL Colormap XCreateColormap(Display *display, Window w, Visual *visual, int alloc) { ::REGAL_NAMESPACE_INTERNAL::Init::init(); @@ -139,7 +139,7 @@ extern "C" { return True; } -} // extern "C" +} // extern "C" REGAL_GLOBAL_END diff --git a/src/regal/RegalXfer.h b/src/regal/RegalXfer.h index 5378484..aecbe0a 100644 --- a/src/regal/RegalXfer.h +++ b/src/regal/RegalXfer.h @@ -47,6 +47,7 @@ REGAL_GLOBAL_BEGIN #include "RegalEmu.h" #include "RegalPrivate.h" #include "RegalContext.h" +#include "RegalToken.h" #include "RegalContextInfo.h" #include @@ -78,20 +79,20 @@ struct Xfer } void PixelStore( RegalContext * ctx, GLenum pname, GLint param ); - void PixelStore( RegalContext * ctx, GLenum pname, GLfloat param ) { + + void PixelStore( RegalContext * ctx, GLenum pname, GLfloat param ) + { PixelStore( ctx, pname, GLint( param ) ); } - void ShadowActiveTexture( GLenum tex ) { - int r = tex - GL_TEXTURE0; - if( r < 0 || r > REGAL_EMU_MAX_TEXTURE_UNITS ) { - Warning("Regal can't share initialized context groups."); - return; - } - activeTextureIndex = tex - GL_TEXTURE0; + void ShadowActiveTexture( GLenum texture ) + { + if (validTextureEnum(texture)) + activeTextureIndex = texture - GL_TEXTURE0; } - void ShadowBindTexture( GLenum target, GLuint name ) { + void ShadowBindTexture( GLenum target, GLuint name ) + { UNUSED_PARAMETER(target); textureBinding2D[ activeTextureIndex ] = name; } @@ -109,7 +110,7 @@ struct Xfer GLint unpackSkipPixels; int activeTextureIndex; - GLuint textureBinding2D[REGAL_EMU_MAX_TEXTURE_UNITS]; + GLuint textureBinding2D[REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; std::map< GLuint, GLuint > name2ifmt; }; diff --git a/tests/testRegalPpca.cpp b/tests/testRegalPpca.cpp index 68a3252..0629944 100644 --- a/tests/testRegalPpca.cpp +++ b/tests/testRegalPpca.cpp @@ -159,6 +159,7 @@ TEST ( RegalPpca, Ppca_Defaults ) ctx.info->core = false; ctx.info->es1 = false; ctx.info->es2 = false; + ctx.info->max_client_attrib_stack_depth = 16; InitDispatchTableGMock( ctx.dispatcher.emulation ); Ppca ppca; @@ -428,6 +429,7 @@ TEST ( RegalPpca, PixelStore_PushPop ) RegalContext ctx; ctx.info = new ContextInfo(); + ctx.info->max_client_attrib_stack_depth = 16; InitDispatchTableGMock( ctx.dispatcher.emulation ); Ppca ppca; @@ -651,7 +653,7 @@ TEST ( RegalPpca, VertexArray_PushPop ) RegalContext ctx; ctx.info = new ContextInfo(); - ctx.info = new ContextInfo(); + ctx.info->max_client_attrib_stack_depth = 16; InitDispatchTableGMock( ctx.dispatcher.emulation ); Ppca ppca; @@ -835,6 +837,7 @@ TEST ( RegalPpca, ClientAttrib_PushPop ) ctx.info->core = false; ctx.info->es1 = false; ctx.info->es2 = false; + ctx.info->max_client_attrib_stack_depth = 16; InitDispatchTableGMock( ctx.dispatcher.emulation ); Ppca ppca; @@ -2814,6 +2817,7 @@ TEST ( RegalPpca, glGet_Shadowing ) { RegalContext ctx; ctx.info = new ContextInfo(); + ctx.info->max_client_attrib_stack_depth = 16; Ppca ppca; ppca.Init(ctx); diff --git a/tests/testRegalTexC.cpp b/tests/testRegalTexC.cpp index d2e4e54..418c5e6 100644 --- a/tests/testRegalTexC.cpp +++ b/tests/testRegalTexC.cpp @@ -580,13 +580,13 @@ TEST ( RegalTexC, GetBoundTexture ) { // Setup texc.textureUnitArrayState[ 0 ].Bind( GL_TEXTURE_CUBE_MAP, &boundToCubemapUnit0 ); - texc.textureUnitArrayState[ REGAL_EMU_MAX_TEXTURE_UNITS - 1 ].Bind( GL_TEXTURE_CUBE_MAP, &boundToCubemapUnitMax ); + texc.textureUnitArrayState[ REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1 ].Bind( GL_TEXTURE_CUBE_MAP, &boundToCubemapUnitMax ); // Test expectations. EXPECT_EQ( &texc.textureZero, texc.GetBoundTexture_( GL_TEXTURE0, GL_TEXTURE_2D ) ); EXPECT_EQ( &boundToCubemapUnit0, texc.GetBoundTexture_( GL_TEXTURE0, GL_TEXTURE_CUBE_MAP ) ); - EXPECT_EQ( &boundToCubemapUnitMax, texc.GetBoundTexture_( GL_TEXTURE0 + REGAL_EMU_MAX_TEXTURE_UNITS - 1, GL_TEXTURE_CUBE_MAP ) ); - EXPECT_EQ( NULL, texc.GetBoundTexture_( GL_TEXTURE0 + REGAL_EMU_MAX_TEXTURE_UNITS, GL_TEXTURE_2D ) ); + EXPECT_EQ( &boundToCubemapUnitMax, texc.GetBoundTexture_( GL_TEXTURE0 + REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1, GL_TEXTURE_CUBE_MAP ) ); + EXPECT_EQ( NULL, texc.GetBoundTexture_( GL_TEXTURE0 + REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GL_TEXTURE_2D ) ); EXPECT_EQ( NULL, texc.GetBoundTexture_( GL_TEXTURE0 - 1, GL_TEXTURE_2D ) ); } @@ -671,7 +671,7 @@ TEST ( RegalTexC, ShadowTexImage2D ) { GLenum type; // Set the current texture unit away from default. - texc.currentTextureUnit = GL_TEXTURE1; + texc.currentTextureUnit = 1; // Test the first overload, affecting textureZero. // Setting the format/type and then getting it should match. @@ -691,7 +691,7 @@ TEST ( RegalTexC, ShadowTexImage2D ) { EXPECT_EQ( 31u, type ); // If the texture unit is out of range, the call silently is ignored. - texc.currentTextureUnit = GL_TEXTURE0 - 1; + texc.currentTextureUnit = -1; texc.ShadowTexImage2D( GL_TEXTURE_2D, 15, 0, 0 ); } @@ -779,15 +779,21 @@ TEST ( RegalTexC, ShadowActiveTexture ) { TexC texc; // Verify initial state - EXPECT_EQ( static_cast( GL_TEXTURE0 ), texc.currentTextureUnit ); + EXPECT_EQ( static_cast( 0 ), texc.currentTextureUnit ); // Each call should just simply change currentTextureUnit. texc.ShadowActiveTexture( GL_TEXTURE1 ); - EXPECT_EQ( static_cast( GL_TEXTURE1 ), texc.currentTextureUnit ); + EXPECT_EQ( static_cast( 1 ), texc.currentTextureUnit ); - // No range checking is done. + // invalid enums should be ignored texc.ShadowActiveTexture( GL_TEXTURE0 - 1 ); - EXPECT_EQ( static_cast( GL_TEXTURE0 - 1 ), texc.currentTextureUnit ); + EXPECT_EQ( static_cast( 1 ), texc.currentTextureUnit ); + + texc.ShadowActiveTexture( GL_TEXTURE0 + REGAL_EMU_MAX_COMBINED_TEXTURE_IMAGE_UNITS ); + EXPECT_EQ( static_cast( 1 ), texc.currentTextureUnit ); + + texc.ShadowActiveTexture( GLenum(~0) ); + EXPECT_EQ( static_cast( 1 ), texc.currentTextureUnit ); } TEST ( RegalTexC, ShadowBindTexture ) { @@ -800,7 +806,7 @@ TEST ( RegalTexC, ShadowBindTexture ) { EXPECT_EQ( NULL, texc.textureUnitArrayState[ 1 ].GetBinding( GL_TEXTURE_2D ) ); // Set the current texture unit to non-default - texc.currentTextureUnit = GL_TEXTURE1; + texc.currentTextureUnit = 1; // Binding texture 123 ... texc.ShadowBindTexture( GL_TEXTURE_2D, 123 ); @@ -819,7 +825,7 @@ TEST ( RegalTexC, ShadowBindTexture ) { EXPECT_EQ( NULL, texc.textureUnitArrayState[ 1 ].GetBinding( GL_TEXTURE_2D ) ); // If the texture unit is out of the valid range ... - texc.currentTextureUnit = GL_TEXTURE0 - 1; + texc.currentTextureUnit = -1; // The call should silently do nothing. texc.ShadowBindTexture( GL_TEXTURE_2D, 123 ); @@ -838,7 +844,7 @@ TEST ( RegalTexC, ShadowGenerateMipmap ) { texc.textureUnitArrayState[ 1 ].Bind( GL_TEXTURE_2D, &boundToUnit1 ); // Invoke the function under test to emulate mipmap generation. - texc.currentTextureUnit = GL_TEXTURE1; + texc.currentTextureUnit = 1; texc.ShadowGenerateMipmap( GL_TEXTURE_2D ); // We expect the texture state to indicate a single default format.