static int _getModifierMask(const char* accel) { int ret = 0; if(dStrstr(accel, "ctrl")) ret |= kMenuControlModifier; if(dStrstr(accel, "shift")) ret |= kMenuShiftModifier; if(dStrstr(accel, "alt")) ret |= kMenuOptionModifier; if(!(dStrstr(accel, "cmd") || dStrstr(accel, "command"))) ret |= kMenuNoCommandModifier; return ret; }
//----------------------------------------------------------------------------- // Destroy any fields. //----------------------------------------------------------------------------- void FieldBrushObject::destroyFields() { // Fetch Dynamic-Field Dictionary. SimFieldDictionary* pFieldDictionary = getFieldDictionary(); // Any Field Dictionary? if ( pFieldDictionary == NULL ) { // No, so we're done. return; } // Iterate fields. for ( SimFieldDictionaryIterator itr(pFieldDictionary); *itr; ++itr ) { // Fetch Field Entry. SimFieldDictionary::Entry* fieldEntry = *itr; // Internal Field? if ( dStrstr( fieldEntry->slotName, INTERNAL_FIELD_PREFIX ) == fieldEntry->slotName ) { // Yes, so remove it. pFieldDictionary->setFieldValue( fieldEntry->slotName, "" ); } } }
bool DecalManager::_createDataFile() { AssertFatal( !mData, "DecalManager::tried to create duplicate data file?" ); // We need to construct a default file name char fileName[1024]; fileName[0] = 0; // See if we know our current mission name char missionName[1024]; dStrcpy( missionName, Con::getVariable( "$Client::MissionFile" ) ); char *dot = dStrstr((const char*)missionName, ".mis"); if(dot) *dot = '\0'; dSprintf( fileName, sizeof(fileName), "%s.mis.decals", missionName ); mDataFileName = StringTable->insert( fileName ); if( !Torque::FS::IsFile( fileName ) ) { DecalDataFile *file = new DecalDataFile(); file->write( mDataFileName ); delete file; } mData = ResourceManager::get().load( mDataFileName ); return (bool)mData; }
void initDisplayDeviceInfo() { Con::printf( "Reading Display Device information..." ); U8 i = 0; DISPLAY_DEVICEA ddData; ddData.cb = sizeof( DISPLAY_DEVICEA ); // Search for the primary display adapter, because that is what the rendering // context will get created on. while( EnumDisplayDevicesA( NULL, i, &ddData, 0 ) != 0 ) { // If we find the primary display adapter, break out if( ddData.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE ) break; i++; } Con::printf( " Primary Display Device Found:" ); // Ok, now we have the primary display device. Parse the device information. char ven[9]; char dev[9]; ven[8] = dev[8] = '\0'; // It may seem a bit silly here to cast, but there are two implimentations in Platform.h // This usage is the "const" version... char *pos = dStrstr( ddData.DeviceID, (const char *)"VEN_"); dStrncpy( ven, ( pos ) ? pos : "VEN_0000", 8 ); Con::printf( " Vendor Id: %s", ven ); pos = dStrstr( ddData.DeviceID, (const char *)"DEV_" ); dStrncpy( dev, ( pos ) ? pos : "DEV_0000", 8 ); Con::printf( " Device Id: %s", dev ); // We now have the information, set them to console variables so we can parse // the file etc in script using getField and so on. Con::setVariable( "$PCI_VEN", ven ); Con::setVariable( "$PCI_DEV", dev ); }
//************************************************************************** // General operation //************************************************************************** GenOp::GenOp( const char * statement, ... ) : Parent( NULL, NULL ) { VECTOR_SET_ASSOCIATION( mElemList ); va_list args; va_start(args, statement); char* lastEntry = (char*)statement; while( 1 ) { // search 'statement' for @ symbol char * str = dStrstr( lastEntry, (char *)"@" ); if( !str ) { // not found, handle end of line str = (char*)&statement[ dStrlen( (char*)statement ) ]; U64 diff = str - lastEntry + 1; if( diff == 1 ) break; char * newStr = new char[diff]; dMemcpy( (void*)newStr, lastEntry, diff ); mElemList.push_back( new EchoOp( newStr ) ); break; } // create and store statement fragment U64 diff = str - lastEntry + 1; if( diff == 1 ) { // store langElement LangElement *elem = va_arg(args, LangElement* ); AssertFatal( elem, "NULL arguement." ); mElemList.push_back( elem ); lastEntry++; continue; } char * newStr = new char[diff]; dMemcpy( (void*)newStr, lastEntry, diff ); newStr[diff-1] = '\0'; lastEntry = str + 1; mElemList.push_back( new EchoOp( newStr ) ); // store langElement LangElement *elem = va_arg(args, LangElement* ); AssertFatal( elem, "NULL argument." ); mElemList.push_back( elem ); }
static void dumpDoc( Stream& stream, const char* text, bool checkUngrouped = true ) { // Extract brief. String brief; if( text ) { const char* briefTag = dStrstr( text, "@brief" ); if( !briefTag ) { const char* newline = dStrchr( text, '\n' ); if( newline ) { brief = String( text, newline - text ); text = newline + 1; } else { brief = text; text = NULL; } } } // Write doc comment. if( !brief.isEmpty() ) { stream.writeText( "@brief " ); stream.writeText( brief ); stream.writeText( "\r\n\r\n" ); } if( text ) stream.writeText( text ); #ifdef USE_UNDOCUMENTED_GROUP if( checkUngrouped && ( !text || !dStrstr( text, "@ingroup" ) ) ) { smDocGroups.insertUnique( "UNDOCUMENTED", 0 ); stream.writeText( "\r\n@ingroup UNDOCUMENTED\r\n" ); } #endif }
ASMShaderParameter* ASMShader::getNamedParameter(StringTableEntry name) { for(U32 i = 0; i < mParameters.size(); i++) { if(dStricmp(mParameters[i]->mName, name) == 0) { return mParameters[i]; } } //No parameter... const char* paramString; ASMShaderParameter* param = NULL; paramString = dStrstr(mVertexSourceString, name); if(paramString) { param = new ASMShaderParameter; const char* openBracket = dStrstr(paramString, "["); const char* closeBracket = dStrstr(paramString, "]"); char* num = (char *)dMalloc((closeBracket - openBracket + 1) * sizeof(U8)); num = dStrncpy(num, openBracket + 1, (closeBracket - (openBracket + 1))); num[(closeBracket - (openBracket + 1))] = NULL; param->mName = StringTable->insert(name); param->mVertexId = dAtoi(num); const char* env = dStrstr(paramString, "program.env"); param->mVertexIsEnv = (env != NULL && env < openBracket); param->mFragmentId = -1; param->mFragmentIsEnv = false; mParameters.push_back(param); dFree(num); } paramString = dStrstr(mPixelSourceString, name); if(paramString) { if(!param) { param = new ASMShaderParameter; mParameters.push_back(param); param->mVertexId = -1; param->mVertexIsEnv = false; param->mName = StringTable->insert(name); } const char* openBracket = dStrstr(paramString, "["); const char* closeBracket = dStrstr(paramString, "]"); char* num = (char *)dMalloc((closeBracket - openBracket + 1) * sizeof(U8)); num = dStrncpy(num, openBracket + 1, (closeBracket - (openBracket + 1))); num[(closeBracket - (openBracket + 1))] = NULL; param->mFragmentId = dAtoi(num); const char* env = dStrstr(paramString, "program.env"); param->mFragmentIsEnv = (env != NULL && env < openBracket); dFree(num); } return param; }
bool GFXInit::compareAdapterOutputDevice(const GFXAdapter* adapter, const char* outputDevice) { // If the adapter doesn't have an output display device, then it supports all of them if(!adapter->mOutputName[0]) return true; // Try and match the first part of the output device display name. For example, // an adapter->mOutputName of "\\.\DISPLAY1" might correspond to a display name // of "\\.\DISPLAY1\Monitor0". If two monitors are set up in duplicate mode then // they will have the same 'display' part in their display name. return (dStrstr(outputDevice, adapter->mOutputName) == outputDevice); }
bool hasExtension( const char *name, const char *extensions ) { // Extensions are compared against the extension strings if (extensions && *extensions) { const char* ptr = dStrstr(extensions,name); if (ptr) { char end = ptr[dStrlen(name)]; if (end == ' ' || end == 0) return true; } } return false; }
static void dumpEnum( Stream& stream, const EngineTypeInfo* type ) { if( !type->getEnumTable() ) // Sanity check. return; // Skip internals... don't export them. if ( type->getDocString() && ( dStrstr( type->getDocString(), "@hide" ) || dStrstr( type->getDocString(), "@internal" ) ) ) return; // Write documentation. stream.writeText( "/*!\r\n" ); dumpDoc( stream, type->getDocString() ); stream.writeText( "*/\r\n" ); // Write definition. stream.writeText( "enum " ); stream.writeText( type->getTypeName() ); stream.writeText( " {\r\n" ); const EngineEnumTable& table = *( type->getEnumTable() ); const U32 numValues = table.getNumValues(); for( U32 i = 0; i < numValues; ++ i ) { const EngineEnumTable::Value& value = table[ i ]; stream.writeText( "/*!\r\n" ); dumpDoc( stream, value.getDocString(), false ); stream.writeText( "*/\r\n" ); stream.writeText( value.getName() ); stream.writeText( ",\r\n" ); } stream.writeText( "};\r\n" ); }
S32 Win32WindowManager::findFirstMatchingMonitor(const char* name) { // Try and match the first part of the output device display name. For example, // a Monitor name of "\\.\DISPLAY1" might correspond to a display name // of "\\.\DISPLAY1\Monitor0". If two monitors are set up in duplicate mode then // they will have the same 'display' part in their display name. for(U32 i=0; i<mMonitors.size(); ++i) { if(dStrstr(name, mMonitors[i].name) == name) return i; } return -1; }
bool Platform::stringToFileTime(const char * string, FileTime * time) { if(!time || !string) return(false); char buf[80]; dSprintf(buf, sizeof(buf), (char *)string); char * sep = (char *)dStrstr((const char *)buf, (const char *)":"); if(!sep) return(false); *sep = 0; sep++; time->v2 = dAtoi(buf); time->v1 = dAtoi(sep); return(true); }
//----------------------------------------------------------------------------- // perform a modification on the specified file. allowed modifications are // specified in the enum above. bool ModifyFile(const char * name, S32 modType) { if(!name || (dStrlen(name) >= MaxPath) || dStrstr(name, "../") != NULL) return(false); // if its absolute skip it if (name[0]=='/' || name[0]=='\\') return(false); // only modify files in home directory char prefPathName[MaxPath]; MungePath(prefPathName, MaxPath, name, GetPrefDir()); if (modType == TOUCH) return(utime(prefPathName, 0) != -1); else if (modType == DELETE) return (remove(prefPathName) != -1); else AssertFatal(false, "Unknown File Mod type"); return false; }
//----------------------------------------------------------------------------- bool Platform::getFileTimes(const char *filePath, FileTime *createTime, FileTime *modifyTime) { char pathName[MaxPath]; // if it starts with cwd, we need to strip that off so that we can look for // the file in the pref dir char cwd[MaxPath]; getcwd(cwd, MaxPath); if (dStrstr(filePath, cwd) == filePath) filePath = filePath + dStrlen(cwd) + 1; // if its relative, first look in the pref dir if (filePath[0] != '/' && filePath[0] != '\\') { MungePath(pathName, MaxPath, filePath, GetPrefDir()); if (GetFileTimes(pathName, createTime, modifyTime)) return true; } // here if the path is absolute or not in the pref dir MungePath(pathName, MaxPath, filePath, cwd); return GetFileTimes(pathName, createTime, modifyTime); }
void SimConsoleEvent::process(SimObject* object) { // #ifdef DEBUG // Con::printf("Executing schedule: %d", sequenceCount); // #endif if(mOnObject) Con::execute(object, mArgc, const_cast<const char**>( mArgv )); else { // Grab the function name. If '::' doesn't exist, then the schedule is // on a global function. char* func = dStrstr( mArgv[0], (char*)"::" ); if( func ) { // Set the first colon to NULL, so we can reference the namespace. // This is okay because events are deleted immediately after // processing. Maybe a bad idea anyway? func[0] = '\0'; // Move the pointer forward to the function name. func += 2; // Lookup the namespace and function entry. Namespace* ns = Namespace::find( StringTable->insert( mArgv[0] ) ); if( ns ) { Namespace::Entry* nse = ns->lookup( StringTable->insert( func ) ); if( nse ) // Execute. nse->execute( mArgc, (const char**)mArgv, &gEvalState ); } } else Con::execute(mArgc, const_cast<const char**>( mArgv )); } }
PlatformFont::CharInfo& MacCarbFont::getCharInfo(const UTF16 ch) const { // We use some static data here to avoid re allocating the same variable in a loop. // this func is primarily called by GFont::loadCharInfo(), Rect imageRect; CGContextRef imageCtx; U32 bitmapDataSize; ATSUTextMeasurement tbefore, tafter, tascent, tdescent; OSStatus err; // 16 bit character buffer for the ATUSI calls. // -- hey... could we cache this at the class level, set style and loc *once*, // then just write to this buffer and clear the layout cache, to speed up drawing? static UniChar chUniChar[1]; chUniChar[0] = ch; // Declare and clear out the CharInfo that will be returned. static PlatformFont::CharInfo c; dMemset(&c, 0, sizeof(c)); // prep values for GFont::addBitmap() c.bitmapIndex = 0; c.xOffset = 0; c.yOffset = 0; // put the text in the layout. // we've hardcoded a string length of 1 here, but this could work for longer strings... (hint hint) // note: ATSUSetTextPointerLocation() also clears the previous cached layout information. ATSUSetTextPointerLocation( mLayout, chUniChar, 0, 1, 1); ATSUSetRunStyle( mLayout, mStyle, 0,1); // get the typographic bounds. this tells us how characters are placed relative to other characters. ATSUGetUnjustifiedBounds( mLayout, 0, 1, &tbefore, &tafter, &tascent, &tdescent); c.xIncrement = FixedToInt(tafter); // find out how big of a bitmap we'll need. // as a bonus, we also get the origin where we should draw, encoded in the Rect. ATSUMeasureTextImage( mLayout, 0, 1, 0, 0, &imageRect); U32 xFudge = 2; U32 yFudge = 1; c.width = imageRect.right - imageRect.left + xFudge; // add 2 because small fonts don't always have enough room c.height = imageRect.bottom - imageRect.top + yFudge; c.xOrigin = imageRect.left; // dist x0 -> center line c.yOrigin = -imageRect.top; // dist y0 -> base line // kick out early if the character is undrawable if( c.width == xFudge || c.height == yFudge) return c; // allocate a greyscale bitmap and clear it. bitmapDataSize = c.width * c.height; c.bitmapData = new U8[bitmapDataSize]; dMemset(c.bitmapData,0x00,bitmapDataSize); // get a graphics context on the bitmap imageCtx = CGBitmapContextCreate( c.bitmapData, c.width, c.height, 8, c.width, mColorSpace, kCGImageAlphaNone); if(!imageCtx) { Con::errorf("Error: failed to create a graphics context on the CharInfo bitmap! Drawing a blank block."); c.xIncrement = c.width; dMemset(c.bitmapData,0x0F,bitmapDataSize); return c; } // Turn off antialiasing for monospaced console fonts. yes, this is cheating. if(mSize < 12 && ( dStrstr(mName,"Monaco")!=NULL || dStrstr(mName,"Courier")!=NULL )) CGContextSetShouldAntialias(imageCtx, false); // Set up drawing options for the context. // Since we're not going straight to the screen, we need to adjust accordingly CGContextSetShouldSmoothFonts(imageCtx, false); CGContextSetRenderingIntent(imageCtx, kCGRenderingIntentAbsoluteColorimetric); CGContextSetInterpolationQuality( imageCtx, kCGInterpolationNone); CGContextSetGrayFillColor( imageCtx, 1.0, 1.0); CGContextSetTextDrawingMode( imageCtx, kCGTextFill); // tell ATSUI to substitute fonts as needed for missing glyphs ATSUSetTransientFontMatching(mLayout, true); // set up three parrallel arrays for setting up attributes. // this is how most options in ATSUI are set, by passing arrays of options. ATSUAttributeTag theTags[] = { kATSUCGContextTag }; ByteCount theSizes[] = { sizeof(CGContextRef) }; ATSUAttributeValuePtr theValues[] = { &imageCtx }; // bind the layout to the context. ATSUSetLayoutControls( mLayout, 1, theTags, theSizes, theValues ); // Draw the character! int yoff = c.height < 3 ? 1 : 0; // kludge for 1 pixel high characters, such as '-' and '_' int xoff = 1; err = ATSUDrawText( mLayout, 0, 1, IntToFixed(-imageRect.left + xoff), IntToFixed(imageRect.bottom + yoff ) ); CGContextRelease(imageCtx); if(err != noErr) { Con::errorf("Error: could not draw the character! Drawing a blank box."); dMemset(c.bitmapData,0x0F,bitmapDataSize); } #if TORQUE_DEBUG // Con::printf("Font Metrics: Rect = %2i %2i %2i %2i Char= %C, 0x%x Size= %i, Baseline= %i, Height= %i",imageRect.top, imageRect.bottom, imageRect.left, imageRect.right,ch,ch, mSize,mBaseline, mHeight); // Con::printf("Font Bounds: left= %2i right= %2i Char= %C, 0x%x Size= %i",FixedToInt(tbefore), FixedToInt(tafter), ch,ch, mSize); #endif return c; }
void ShaderConnectorHLSL::sortVars() { if ( GFX->getPixelShaderVersion() >= 2.0 ) return; // Sort connector variables - They must be sorted on hardware that is running // ps 1.4 and below. The reason is that texture coordinate registers MUST // map exactly to their respective texture stage. Ie. if you have fog // coordinates being passed into a pixel shader in texture coordinate register // number 4, the fog texture MUST reside in texture stage 4 for it to work. // The problem is solved by pushing non-texture coordinate data to the end // of the structure so that the texture coodinates are all at the "top" of the // structure in the order that the features are processed. // create list of just the texCoords, sorting by 'mapsToSampler' Vector< Var * > texCoordList; // - first pass is just coords mapped to a sampler for( U32 i=0; i<mElementList.size(); i++ ) { Var *var = mElementList[i]; if( var->mapsToSampler ) { texCoordList.push_back( var ); } } // - next pass is for the others for( U32 i=0; i<mElementList.size(); i++ ) { Var *var = mElementList[i]; if( dStrstr( (const char *)var->connectName, "TEX" ) && !var->mapsToSampler ) { texCoordList.push_back( var ); } } // rename the connectNames for( U32 i=0; i<texCoordList.size(); i++ ) { char out[32]; dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", i ); texCoordList[i]->setConnectName( out ); } // write new, sorted list over old one if( texCoordList.size() ) { U32 index = 0; for( U32 i=0; i<mElementList.size(); i++ ) { Var *var = mElementList[i]; if( dStrstr( (const char *)var->connectName, "TEX" ) ) { mElementList[i] = texCoordList[index]; index++; } } } }
static void dumpVariable( Stream& stream, Dictionary::Entry* entry, const char* inClass = NULL ) { // Skip variables defined in script. if( entry->type < 0 ) return; // Skip internals... don't export them. if ( entry->mUsage && ( dStrstr( entry->mUsage, "@hide" ) || dStrstr( entry->mUsage, "@internal" ) ) ) return; // Split up qualified name. Vector< String > nameComponents; String( entry->name ).split( "::", nameComponents ); if( !nameComponents.size() ) // Safety check. return; // Match filter. if( inClass ) { // Make sure first qualifier in name components is a // namespace qualifier matching the given class name. if( nameComponents.size() <= 1 || dStricmp( nameComponents.first().c_str() + 1, inClass ) != 0 ) // Skip '$'. return; } else { // Make sure, this is *not* in a class namespace. if( nameComponents.size() > 1 && Con::lookupNamespace( nameComponents.first().c_str() + 1 )->mClassRep ) return; } // Skip variables for which we can't decipher their type. ConsoleBaseType* type = ConsoleBaseType::getType( entry->type ); if( !type ) { Con::errorf( "Can't find type for variable '%s'", entry->name ); return; } // Write doc comment. stream.writeText( "/*!\r\n" ); if( !inClass ) { stream.writeText( "@var " ); stream.writeText( type->getTypeClassName() ); stream.writeText( " " ); stream.writeText( entry->name ); stream.writeText( ";\r\n" ); } dumpDoc( stream, entry->mUsage ); stream.writeText( "*/\r\n" ); // Write definition. const U32 numNameComponents = nameComponents.size(); if( !inClass && numNameComponents > 1 ) for( U32 i = 0; i < ( numNameComponents - 1 ); ++ i ) { stream.writeText( "namespace " ); stream.writeText( nameComponents[ i ] ); stream.writeText( " { " ); } if( inClass ) stream.writeText( "static " ); if( entry->mIsConstant ) stream.writeText( "const " ); stream.writeText( type->getTypeClassName() ); stream.writeText( " " ); stream.writeText( nameComponents.last() ); stream.writeText( ";" ); if( !inClass && numNameComponents > 1 ) for( U32 i = 0; i < ( numNameComponents - 1 ); ++ i ) stream.writeText( " } " ); stream.writeText( "\r\n" ); }
// Find out which extensions are available for this renderer. void getGLCapabilities( ) { AssertFatal(platState.engine, "getGLCapabilities() was called before a monitor was chosen!"); // silently create an opengl context on the current display, // so that we can get valid renderer and capability info. // we save off the current context so that we can silently restore it. // the user should not be aware of this little shuffle. //CGLContextObj curr_ctx = CGLGetCurrentContext (); //CGLContextObj temp_ctx = getContextForCapsCheck(); /* if(!temp_ctx) { Con::errorf("OpenGL may not be set up correctly!"); return; } */ //CGLSetCurrentContext(temp_ctx); // Get the OpenGL info strings we'll need const char* pVendString = (const char*) glGetString( GL_VENDOR ); const char* pRendString = (const char*) glGetString( GL_RENDERER ); const char* pVersString = (const char*) glGetString( GL_VERSION ); const char* pExtString = (const char*) glGetString( GL_EXTENSIONS ); // Output some driver info to the console: Con::printf( "OpenGL driver information:" ); if ( pVendString ) Con::printf( " Vendor: %s", pVendString ); if ( pRendString ) Con::printf( " Renderer: %s", pRendString ); if ( pVersString ) Con::printf( " Version: %s", pVersString ); // pre-clear the structure dMemset(&gGLState, 0, sizeof(gGLState)); if(pExtString) { // EXT_paletted_texture ======================================== if (dStrstr(pExtString, (const char*)"GL_EXT_paletted_texture") != NULL) gGLState.suppPalettedTexture = true; // EXT_compiled_vertex_array ======================================== gGLState.suppLockedArrays = false; if (dStrstr(pExtString, (const char*)"GL_EXT_compiled_vertex_array") != NULL) gGLState.suppLockedArrays = true; // ARB_multitexture ======================================== if (dStrstr(pExtString, (const char*)"GL_ARB_multitexture") != NULL) gGLState.suppARBMultitexture = true; // EXT_blend_color if(dStrstr(pExtString, (const char*)"GL_EXT_blend_color") != NULL) gGLState.suppEXTblendcolor = true; // EXT_blend_minmax if(dStrstr(pExtString, (const char*)"GL_EXT_blend_minmax") != NULL) gGLState.suppEXTblendminmax = true; // NV_vertex_array_range ======================================== // does not appear to be supported by apple, at all. ( as of 10.4.3 ) // GL_APPLE_vertex_array_range is similar, and may be nearly identical. if (dStrstr(pExtString, (const char*)"GL_NV_vertex_array_range") != NULL) gGLState.suppVertexArrayRange = true; // EXT_fog_coord ======================================== if (dStrstr(pExtString, (const char*)"GL_EXT_fog_coord") != NULL) gGLState.suppFogCoord = true; // ARB_texture_compression ======================================== if (dStrstr(pExtString, (const char*)"GL_ARB_texture_compression") != NULL) gGLState.suppTextureCompression = true; // 3DFX_texture_compression_FXT1 ======================================== if (dStrstr(pExtString, (const char*)"GL_3DFX_texture_compression_FXT1") != NULL) gGLState.suppFXT1 = true; // EXT_texture_compression_S3TC ======================================== if (dStrstr(pExtString, (const char*)"GL_EXT_texture_compression_s3tc") != NULL) gGLState.suppS3TC = true; // EXT_vertex_buffer ======================================== // This extension is deprecated, and not supported by Apple. ( 10.4.3 ) // Instead, the ARB Vertex Buffer extension is supported. // The new extension has a different API, so TGE should be updated to use it. if (dStrstr(pExtString, (const char*)"GL_EXT_vertex_buffer") != NULL) gGLState.suppVertexBuffer = true; // Anisotropic filtering ======================================== gGLState.suppTexAnisotropic = (dStrstr(pExtString, (const char*)"GL_EXT_texture_filter_anisotropic") != NULL); if (gGLState.suppTexAnisotropic) glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGLState.maxAnisotropy); // Binary states, i.e., no supporting functions ======================================== // NOTE: // Some of these have multiple representations, via EXT and|or ARB and|or NV and|or SGIS ... etc. // Check all relative versions. gGLState.suppPackedPixels = (dStrstr(pExtString, (const char*)"GL_EXT_packed_pixels") != NULL); gGLState.suppPackedPixels |= (dStrstr(pExtString, (const char*)"GL_APPLE_packed_pixel") != NULL); gGLState.suppTextureEnvCombine = (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_combine") != NULL); gGLState.suppTextureEnvCombine|= (dStrstr(pExtString, (const char*)"GL_ARB_texture_env_combine") != NULL); gGLState.suppEdgeClamp = (dStrstr(pExtString, (const char*)"GL_EXT_texture_edge_clamp") != NULL); gGLState.suppEdgeClamp |= (dStrstr(pExtString, (const char*)"GL_SGIS_texture_edge_clamp") != NULL); gGLState.suppEdgeClamp |= (dStrstr(pExtString, (const char*)"GL_ARB_texture_border_clamp") != NULL); gGLState.suppEdgeClamp = true; gGLState.suppTexEnvAdd = (dStrstr(pExtString, (const char*)"GL_ARB_texture_env_add") != NULL); gGLState.suppTexEnvAdd |= (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_add") != NULL); } // Texture combine units ======================================== // if (gGLState.suppARBMultitexture) // glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gGLState.maxTextureUnits); gGLState.suppARBMultitexture = false; gGLState.maxTextureUnits = 1; // Swap interval ======================================== // Mac inherently supports a swap interval via AGL-set-integer. gGLState.suppSwapInterval = true; // FSAA support, TODO: check for ARB multisample support // multisample support should be checked via CGL gGLState.maxFSAASamples = 4; // dump found extensions to the console... Con::printf("OpenGL Init: Enabled Extensions"); if (gGLState.suppARBMultitexture) Con::printf(" ARB_multitexture (Max Texture Units: %d)", gGLState.maxTextureUnits); if (gGLState.suppEXTblendcolor) Con::printf(" EXT_blend_color"); if (gGLState.suppEXTblendminmax) Con::printf(" EXT_blend_minmax"); if (gGLState.suppPalettedTexture) Con::printf(" EXT_paletted_texture"); if (gGLState.suppLockedArrays) Con::printf(" EXT_compiled_vertex_array"); if (gGLState.suppVertexArrayRange) Con::printf(" NV_vertex_array_range"); if (gGLState.suppTextureEnvCombine) Con::printf(" EXT_texture_env_combine"); if (gGLState.suppPackedPixels) Con::printf(" EXT_packed_pixels"); if (gGLState.suppFogCoord) Con::printf(" EXT_fog_coord"); if (gGLState.suppTextureCompression) Con::printf(" ARB_texture_compression"); if (gGLState.suppS3TC) Con::printf(" EXT_texture_compression_s3tc"); if (gGLState.suppFXT1) Con::printf(" 3DFX_texture_compression_FXT1"); if (gGLState.suppTexEnvAdd) Con::printf(" (ARB|EXT)_texture_env_add"); if (gGLState.suppTexAnisotropic) Con::printf(" EXT_texture_filter_anisotropic (Max anisotropy: %f)", gGLState.maxAnisotropy); if (gGLState.suppSwapInterval) Con::printf(" Vertical Sync"); if (gGLState.maxFSAASamples) Con::printf(" ATI_FSAA"); Con::warnf("OpenGL Init: Disabled Extensions"); if (!gGLState.suppARBMultitexture) Con::warnf(" ARB_multitexture"); if (!gGLState.suppEXTblendcolor) Con::warnf(" EXT_blend_color"); if (!gGLState.suppEXTblendminmax) Con::warnf(" EXT_blend_minmax"); if (!gGLState.suppPalettedTexture) Con::warnf(" EXT_paletted_texture"); if (!gGLState.suppLockedArrays) Con::warnf(" EXT_compiled_vertex_array"); if (!gGLState.suppVertexArrayRange) Con::warnf(" NV_vertex_array_range"); if (!gGLState.suppTextureEnvCombine) Con::warnf(" EXT_texture_env_combine"); if (!gGLState.suppPackedPixels) Con::warnf(" EXT_packed_pixels"); if (!gGLState.suppFogCoord) Con::warnf(" EXT_fog_coord"); if (!gGLState.suppTextureCompression) Con::warnf(" ARB_texture_compression"); if (!gGLState.suppS3TC) Con::warnf(" EXT_texture_compression_s3tc"); if (!gGLState.suppFXT1) Con::warnf(" 3DFX_texture_compression_FXT1"); if (!gGLState.suppTexEnvAdd) Con::warnf(" (ARB|EXT)_texture_env_add"); if (!gGLState.suppTexAnisotropic) Con::warnf(" EXT_texture_filter_anisotropic"); if (!gGLState.suppSwapInterval) Con::warnf(" Vertical Sync"); if (!gGLState.maxFSAASamples) Con::warnf(" ATI_FSAA"); Con::printf(""); // Set some console variables: Con::setBoolVariable( "$FogCoordSupported", gGLState.suppFogCoord ); Con::setBoolVariable( "$TextureCompressionSupported", gGLState.suppTextureCompression ); Con::setBoolVariable( "$AnisotropySupported", gGLState.suppTexAnisotropic ); Con::setBoolVariable( "$PalettedTextureSupported", gGLState.suppPalettedTexture ); Con::setBoolVariable( "$SwapIntervalSupported", gGLState.suppSwapInterval ); if (!gGLState.suppPalettedTexture && Con::getBoolVariable("$pref::OpenGL::forcePalettedTexture",false)) { Con::setBoolVariable("$pref::OpenGL::forcePalettedTexture", false); Con::setBoolVariable("$pref::OpenGL::force16BitTexture", true); } // get fsaa samples. default to normal, no antialiasing // TODO: clamp this against ARB_multisample capabilities. gFSAASamples = Con::getIntVariable("$pref::OpenGL::numFSAASamples", 1); }
static void dumpFunction( Stream &stream, bool isClassMethod, Namespace::Entry* entry ) { String doc = entry->getDocString().trim(); String prototype = entry->getPrototypeString().trim(); // If the doc string contains @hide, skip this function. if( dStrstr( doc.c_str(), "@hide" ) || dStrstr( doc.c_str(), "@internal" ) ) return; // Make sure we have a valid function prototype. if( prototype.isEmpty() ) { Con::errorf( "Function '%s::%s' has no prototype!", entry->mNamespace->mName, entry->mFunctionName ); return; } // See if it's a static method. bool isStaticMethod = false; if( entry->mHeader ) isStaticMethod = entry->mHeader->mIsStatic; // Emit the doc comment. if( !doc.isEmpty() ) { stream.writeText( "/*!\r\n" ); // If there's no @brief, take the first line of the doc text body // as the description. const char* brief = dStrstr( doc, "@brief" ); if( !brief ) { String brief = entry->getBriefDescription( &doc ); brief.trim(); if( !brief.isEmpty() ) { stream.writeText( "@brief " ); stream.writeText( brief ); stream.writeText( "\r\n\r\n" ); } } stream.writeText( doc ); // Emit @ingroup if it's not a class method. if ( !isClassMethod && !isStaticMethod ) // Extra static method check for static classes (which will come out as non-class namespaces). { const char *group = dStrstr( doc, "@ingroup" ); if( group ) { char groupName[ 256 ] = { 0 }; dSscanf( group, "@ingroup %s", groupName ); smDocGroups.insertUnique( groupName, 0 ); } #ifdef USE_UNDOCUMENTED_GROUP else { smDocGroups.insertUnique( "UNDOCUMENTED", 0 ); stream.writeText( "\r\n@ingroup UNDOCUMENTED\r\n" ); } #endif } stream.writeText( "*/\r\n" ); } #ifdef USE_UNDOCUMENTED_GROUP else if( !isClassMethod ) { smDocGroups.insertUnique( "UNDOCUMENTED", 0 ); stream.writeText( "/*! UNDOCUMENTED!\r\n@ingroup UNDOCUMENTED\r\n */\r\n" ); } #endif if( isStaticMethod ) stream.writeText( "static " ); stream.writeText( prototype ); stream.writeText( ";\r\n" ); }
static void dumpClassHeader( Stream &stream, const char *usage, const char *className, const char *superClassName ) { if ( usage ) { stream.writeText( "/*!\r\n" ); stream.writeText( usage ); const char *group = dStrstr( usage, "@ingroup" ); if ( group ) { char groupName[256] = { 0 }; dSscanf( group, "@ingroup %s", groupName ); smDocGroups.insertUnique( groupName, 0 ); } #ifdef USE_UNDOCUMENTED_GROUP else { smDocGroups.insertUnique( "UNDOCUMENTED", 0 ); stream.writeText( "\r\n@ingroup UNDOCUMENTED\r\n" ); } #endif stream.writeText( "\r\n*/\r\n" ); } else { // No documentation string. Check whether ther is a separate // class doc fragement. bool haveClassDocFragment = false; if( className ) { char buffer[ 1024 ]; dSprintf( buffer, sizeof( buffer ), "@class %s", className ); for( ConsoleDocFragment* fragment = ConsoleDocFragment::smFirst; fragment != NULL; fragment = fragment->mNext ) if( !fragment->mClass && dStrstr( fragment->mText, buffer ) != NULL ) { haveClassDocFragment = true; break; } } #ifdef USE_UNDOCUMENTED_GROUP if( !haveClassDocFragment ) { smDocGroups.insertUnique( "UNDOCUMENTED", 0 ); stream.writeText( "/*! UNDOCUMENTED!\r\n@ingroup UNDOCUMENTED\r\n */\r\n" ); } #endif } // Print out appropriate class header if ( superClassName ) stream.writeText( String::ToString( "class %s : public %s {\r\npublic:\r\n", className, superClassName ? superClassName : "" ) ); else if ( className ) stream.writeText( String::ToString( "class %s {\r\npublic:\r\n", className ) ); else stream.writeText( "namespace {\r\n" ); }
static void dumpClasses( Stream &stream ) { Namespace::trashCache(); VectorPtr<Namespace*> vec; vec.reserve( 1024 ); // We use mHashSequence to mark if we have traversed... // so mark all as zero to start. for ( Namespace *walk = Namespace::mNamespaceList; walk; walk = walk->mNext ) walk->mHashSequence = 0; for(Namespace *walk = Namespace::mNamespaceList; walk; walk = walk->mNext) { VectorPtr<Namespace*> stack; stack.reserve( 1024 ); // Get all the parents of this namespace... (and mark them as we go) Namespace *parentWalk = walk; while(parentWalk) { if(parentWalk->mHashSequence != 0) break; if(parentWalk->mPackage == 0) { parentWalk->mHashSequence = 1; // Mark as traversed. stack.push_back(parentWalk); } parentWalk = parentWalk->mParent; } // Load stack into our results vector. while(stack.size()) { vec.push_back(stack[stack.size() - 1]); stack.pop_back(); } } // Go through previously discovered classes U32 i; for(i = 0; i < vec.size(); i++) { const char *className = vec[i]->mName; const char *superClassName = vec[i]->mParent ? vec[i]->mParent->mName : NULL; // Skip the global namespace, that gets dealt with in dumpFunctions if(!className) continue; // We're just dumping engine functions, then we don't want to dump // a class that only contains script functions. So, we iterate over // all the functions. bool found = false; for( Namespace::Entry *ewalk = vec[i]->mEntryList; ewalk; ewalk = ewalk->mNext ) { if( ewalk->mType != Namespace::Entry::ConsoleFunctionType ) { found = true; break; } } // If we don't have engine functions and the namespace name // doesn't match the class name... then its a script class. if ( !found && !vec[i]->isClass() ) continue; // If we hit a class with no members and no classRep, do clever filtering. if(vec[i]->mEntryList == NULL && vec[i]->mClassRep == NULL) { // Print out a short stub so we get a proper class hierarchy. if ( superClassName ) { // Filter hack; we don't want non-inheriting classes... dumpClassHeader( stream, NULL, className, superClassName ); dumpClassFooter( stream ); } continue; } // Skip over hidden or internal classes. if( vec[i]->mUsage && ( dStrstr( vec[i]->mUsage, "@hide" ) || dStrstr( vec[i]->mUsage, "@internal" ) ) ) continue; // Print the header for the class.. dumpClassHeader( stream, vec[i]->mUsage, className, superClassName ); // Dump all fragments for this class. for( ConsoleDocFragment* fragment = ConsoleDocFragment::smFirst; fragment != NULL; fragment = fragment->mNext ) if( fragment->mClass && dStricmp( fragment->mClass, className ) == 0 ) dumpFragment( stream, fragment ); // Dump member functions. dumpNamespaceEntries( stream, vec[ i ], false ); // Dump callbacks. dumpGroupStart( stream, "Callbacks" ); dumpNamespaceEntries( stream, vec[ i ], true ); dumpGroupEnd( stream ); // Dump static member variables. dumpVariables( stream, className ); // Deal with the classRep (to get members)... AbstractClassRep *rep = vec[i]->mClassRep; AbstractClassRep::FieldList emptyList; AbstractClassRep::FieldList *parentList = &emptyList; AbstractClassRep::FieldList *fieldList = &emptyList; if ( rep ) { // Get information about the parent's fields... AbstractClassRep *parentRep = vec[i]->mParent ? vec[i]->mParent->mClassRep : NULL; if(parentRep) parentList = &(parentRep->mFieldList); // Get information about our fields fieldList = &(rep->mFieldList); // Go through all our fields... for(U32 j = 0; j < fieldList->size(); j++) { const AbstractClassRep::Field &field = (*fieldList)[j]; switch( field.type ) { case AbstractClassRep::StartArrayFieldType: case AbstractClassRep::EndArrayFieldType: break; case AbstractClassRep::StartGroupFieldType: dumpGroupStart( stream, field.pGroupname, field.pFieldDocs ); break; case AbstractClassRep::EndGroupFieldType: dumpGroupEnd( stream ); break; default: case AbstractClassRep::DeprecatedFieldType: // Skip over fields that are already defined in // our parent class. if ( parentRep && parentRep->findField( field.pFieldname ) ) continue; dumpClassMember( stream, field ); break; } } } // Close the class/namespace. dumpClassFooter( stream ); } }
char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) { // TODO: The #line pragma on GLSL takes something called a // "source-string-number" which it then never explains. // // Until i resolve this mystery i disabled this. // //String linePragma = String::ToString( "#line 1 \r\n"); //U32 linePragmaLen = linePragma.length(); U32 shaderLen = s->getStreamSize(); char* buffer = (char*)dMalloc(shaderLen + 1); //dStrncpy( buffer, linePragma.c_str(), linePragmaLen ); s->read(shaderLen, buffer); buffer[shaderLen] = 0; char* p = dStrstr(buffer, "#include"); while(p) { char* q = p; p += 8; if(dIsspace(*p)) { U32 n = 0; while(dIsspace(*p)) ++p; AssertFatal(*p == '"', "Bad #include directive"); ++p; static char includeFile[256]; while(*p != '"') { AssertFatal(*p != 0, "Bad #include directive"); includeFile[n++] = *p++; AssertFatal(n < sizeof(includeFile), "#include directive too long"); } ++p; includeFile[n] = 0; // First try it as a local file. Torque::Path includePath = Torque::Path::Join(path.getPath(), '/', includeFile); includePath = Torque::Path::CompressPath(includePath); FileStream includeStream; if ( !includeStream.open( includePath, Torque::FS::File::Read ) ) { // Try again assuming the path is absolute // and/or relative. includePath = String( includeFile ); includePath = Torque::Path::CompressPath(includePath); if ( !includeStream.open( includePath, Torque::FS::File::Read ) ) { AssertISV(false, avar("failed to open include '%s'.", includePath.getFullPath().c_str())); if ( smLogErrors ) Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.", includePath.getFullPath().c_str() ); // Fail... don't return the buffer. dFree(buffer); return NULL; } } char* includedText = _handleIncludes(includePath, &includeStream); // If a sub-include fails... cleanup and return. if ( !includedText ) { dFree(buffer); return NULL; } // TODO: Disabled till this is fixed correctly. // // Count the number of lines in the file // before the include. /* U32 includeLine = 0; { char* nl = dStrstr( buffer, "\n" ); while ( nl ) { includeLine++; nl = dStrstr( nl, "\n" ); if(nl) ++nl; } } */ String manip(buffer); manip.erase(q-buffer, p-q); String sItx(includedText); // TODO: Disabled till this is fixed correctly. // // Add a new line pragma to restore the proper // file and line number after the include. //sItx += String::ToString( "\r\n#line %d \r\n", includeLine ); dFree(includedText); manip.insert(q-buffer, sItx); char* manipBuf = dStrdup(manip.c_str()); p = manipBuf + (p - buffer); dFree(buffer); buffer = manipBuf; } p = dStrstr(p, "#include"); } return buffer; }
////-------------------------------------- /// Spawn the default Operating System web browser with a URL /// @param webAddress URL to pass to browser /// @return true if browser successfully spawned bool Platform::openWebBrowser( const char* webAddress ) { static bool sHaveKey = false; static wchar_t sWebKey[512]; char utf8WebKey[512]; { HKEY regKey; DWORD size = sizeof( sWebKey ); if ( RegOpenKeyEx( HKEY_CLASSES_ROOT, dT("\\http\\shell\\open\\command"), 0, KEY_QUERY_VALUE, ®Key ) != ERROR_SUCCESS ) { Con::errorf( ConsoleLogEntry::General, "Platform::openWebBrowser - Failed to open the HKCR\\http registry key!!!"); return( false ); } if ( RegQueryValueEx( regKey, dT(""), NULL, NULL, (U8 *)sWebKey, &size ) != ERROR_SUCCESS ) { Con::errorf( ConsoleLogEntry::General, "Platform::openWebBrowser - Failed to query the open command registry key!!!" ); return( false ); } RegCloseKey( regKey ); sHaveKey = true; convertUTF16toUTF8(sWebKey,utf8WebKey,512); #ifdef UNICODE char *p = dStrstr((const char *)utf8WebKey, "%1"); #else char *p = strstr( (const char *) sWebKey , "%1"); #endif if (p) *p = 0; } STARTUPINFO si; dMemset( &si, 0, sizeof( si ) ); si.cb = sizeof( si ); char buf[1024]; #ifdef UNICODE dSprintf( buf, sizeof( buf ), "%s %s", utf8WebKey, webAddress ); UTF16 b[1024]; convertUTF8toUTF16((UTF8 *)buf, b, sizeof(b)); #else dSprintf( buf, sizeof( buf ), "%s %s", sWebKey, webAddress ); #endif //Con::errorf( ConsoleLogEntry::General, "** Web browser command = %s **", buf ); PROCESS_INFORMATION pi; dMemset( &pi, 0, sizeof( pi ) ); CreateProcess( NULL, #ifdef UNICODE b, #else buf, #endif NULL, NULL, false, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi ); return( true ); }
// JMQTODO: really need a platform-shared version of this nastiness bool GL_EXT_Init( ) { // Load extensions... // const char* pExtString = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); gGLState.primMode = 0; U32 extBitMask = 0; // GL_EXT_paletted_texture if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_paletted_texture") != NULL) { extBitMask |= EXT_paletted_texture; gGLState.suppPalettedTexture = true; } else gGLState.suppPalettedTexture = false; // EXT_compiled_vertex_array if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_compiled_vertex_array") != NULL) { extBitMask |= EXT_compiled_vertex_array; gGLState.suppLockedArrays = true; } else { gGLState.suppLockedArrays = false; } // ARB_multitexture if (pExtString && dStrstr(pExtString, (const char*)"GL_ARB_multitexture") != NULL) { extBitMask |= ARB_multitexture; gGLState.suppARBMultitexture = true; } else { gGLState.suppARBMultitexture = false; } // EXT_blend_color if(pExtString && dStrstr(pExtString, (const char*)"GL_EXT_blend_color") != NULL) { extBitMask |= EXT_blend_color; gGLState.suppEXTblendcolor = true; } else { gGLState.suppEXTblendcolor = false; } // EXT_blend_minmax if(pExtString && dStrstr(pExtString, (const char*)"GL_EXT_blend_minmax") != NULL) { extBitMask |= EXT_blend_color; gGLState.suppEXTblendminmax = true; } else { gGLState.suppEXTblendminmax = false; } // EXT_fog_coord if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_fog_coord") != NULL) { extBitMask |= EXT_fog_coord; gGLState.suppFogCoord = true; } else { gGLState.suppFogCoord = false; } // EXT_texture_compression_s3tc if (pExtString && dStrstr(pExtString, (const char*)"GL_EXT_texture_compression_s3tc") != NULL) gGLState.suppS3TC = true; else gGLState.suppS3TC = false; // ARB_texture_compression if (pExtString && dStrstr(pExtString, (const char*)"GL_ARB_texture_compression") != NULL) { extBitMask |= ARB_texture_compression; gGLState.suppTextureCompression = true; } else { gGLState.suppTextureCompression = false; } // NV_vertex_array_range (not on *nix) gGLState.suppVertexArrayRange = false; // 3DFX_texture_compression_FXT1 if (pExtString && dStrstr(pExtString, (const char*)"3DFX_texture_compression_FXT1") != NULL) gGLState.suppFXT1 = true; else gGLState.suppFXT1 = false; if (!bindEXTFunctions(extBitMask)) Con::warnf("You are missing some OpenGL Extensions. You may experience rendering problems."); // Binary states, i.e., no supporting functions // EXT_packed_pixels // EXT_texture_env_combine // // dhc note: a number of these can have multiple matching 'versions', private, ext, and arb. gGLState.suppPackedPixels = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_packed_pixels") != NULL) : false; gGLState.suppTextureEnvCombine = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_combine") != NULL) : false; gGLState.suppEdgeClamp = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_edge_clamp") != NULL) : false; gGLState.suppEdgeClamp |= pExtString? (dStrstr(pExtString, (const char*)"GL_SGIS_texture_edge_clamp") != NULL) : false; gGLState.suppTexEnvAdd = pExtString? (dStrstr(pExtString, (const char*)"GL_ARB_texture_env_add") != NULL) : false; gGLState.suppTexEnvAdd |= pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_env_add") != NULL) : false; // Anisotropic filtering gGLState.suppTexAnisotropic = pExtString? (dStrstr(pExtString, (const char*)"GL_EXT_texture_filter_anisotropic") != NULL) : false; if (gGLState.suppTexAnisotropic) glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGLState.maxAnisotropy); if (gGLState.suppARBMultitexture) glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gGLState.maxTextureUnits); else gGLState.maxTextureUnits = 1; // JMQ: vsync/swap interval skipped gGLState.suppSwapInterval = false; Con::printf("OpenGL Init: Enabled Extensions"); if (gGLState.suppARBMultitexture) Con::printf(" ARB_multitexture (Max Texture Units: %d)", gGLState.maxTextureUnits); if (gGLState.suppEXTblendcolor) Con::printf(" EXT_blend_color"); if (gGLState.suppEXTblendminmax) Con::printf(" EXT_blend_minmax"); if (gGLState.suppPalettedTexture) Con::printf(" EXT_paletted_texture"); if (gGLState.suppLockedArrays) Con::printf(" EXT_compiled_vertex_array"); if (gGLState.suppVertexArrayRange) Con::printf(" NV_vertex_array_range"); if (gGLState.suppTextureEnvCombine) Con::printf(" EXT_texture_env_combine"); if (gGLState.suppPackedPixels) Con::printf(" EXT_packed_pixels"); if (gGLState.suppFogCoord) Con::printf(" EXT_fog_coord"); if (gGLState.suppTextureCompression) Con::printf(" ARB_texture_compression"); if (gGLState.suppS3TC) Con::printf(" EXT_texture_compression_s3tc"); if (gGLState.suppFXT1) Con::printf(" 3DFX_texture_compression_FXT1"); if (gGLState.suppTexEnvAdd) Con::printf(" (ARB|EXT)_texture_env_add"); if (gGLState.suppTexAnisotropic) Con::printf(" EXT_texture_filter_anisotropic (Max anisotropy: %f)", gGLState.maxAnisotropy); if (gGLState.suppSwapInterval) Con::printf(" WGL_EXT_swap_control"); Con::warnf("OpenGL Init: Disabled Extensions"); if (!gGLState.suppARBMultitexture) Con::warnf(" ARB_multitexture"); if (!gGLState.suppEXTblendcolor) Con::warnf(" EXT_blend_color"); if (!gGLState.suppEXTblendminmax) Con::warnf(" EXT_blend_minmax"); if (!gGLState.suppPalettedTexture) Con::warnf(" EXT_paletted_texture"); if (!gGLState.suppLockedArrays) Con::warnf(" EXT_compiled_vertex_array"); if (!gGLState.suppVertexArrayRange) Con::warnf(" NV_vertex_array_range"); if (!gGLState.suppTextureEnvCombine) Con::warnf(" EXT_texture_env_combine"); if (!gGLState.suppPackedPixels) Con::warnf(" EXT_packed_pixels"); if (!gGLState.suppFogCoord) Con::warnf(" EXT_fog_coord"); if (!gGLState.suppTextureCompression) Con::warnf(" ARB_texture_compression"); if (!gGLState.suppS3TC) Con::warnf(" EXT_texture_compression_s3tc"); if (!gGLState.suppFXT1) Con::warnf(" 3DFX_texture_compression_FXT1"); if (!gGLState.suppTexEnvAdd) Con::warnf(" (ARB|EXT)_texture_env_add"); if (!gGLState.suppTexAnisotropic) Con::warnf(" EXT_texture_filter_anisotropic"); if (!gGLState.suppSwapInterval) Con::warnf(" WGL_EXT_swap_control"); Con::printf(" "); // Set some console variables: Con::setBoolVariable( "$FogCoordSupported", gGLState.suppFogCoord ); Con::setBoolVariable( "$TextureCompressionSupported", gGLState.suppTextureCompression ); Con::setBoolVariable( "$AnisotropySupported", gGLState.suppTexAnisotropic ); Con::setBoolVariable( "$PalettedTextureSupported", gGLState.suppPalettedTexture ); Con::setBoolVariable( "$SwapIntervalSupported", gGLState.suppSwapInterval ); if (!gGLState.suppPalettedTexture && Con::getBoolVariable("$pref::OpenGL::forcePalettedTexture",false)) { Con::setBoolVariable("$pref::OpenGL::forcePalettedTexture", false); Con::setBoolVariable("$pref::OpenGL::force16BitTexture", true); } return true; }