bool csShaderGLCGCommon::LoadProgramWithPS1 () { pswrap = shaderPlug->psplg->CreateProgram ("fp"); if (!pswrap) return false; const char* objectCode = cgGetProgramString (program, CG_COMPILED_PROGRAM); if (!objectCode || !*objectCode) // Program did not actually compile return false; csArray<csShaderVarMapping> mappings; for (size_t i = 0; i < variablemap.GetSize (); i++) { // Get the Cg parameter ShaderParameter* sparam = reinterpret_cast<ShaderParameter*> (variablemap[i].userVal); // Make sure it's a C-register CGresource resource = cgGetParameterResource (sparam->param); if (resource == CG_C) { // Get the register number, and create a mapping csString regnum; regnum.Format ("c%lu", cgGetParameterResourceIndex (sparam->param)); mappings.Push (csShaderVarMapping (variablemap[i].name, regnum)); } } if (pswrap->Load (0, objectCode, mappings)) { bool ret = pswrap->Compile (0); if (shaderPlug->debugDump) DoDebugDump(); return ret; } else { return false; } }
bool TPanelWindowView::GetOptions( const char *option, BMessage *msg ) { if ( !strcasecmp( option, "TransparentMenus" ) ) msg->AddBool( "response", fUseTransparentMenus ); else if ( !strcasecmp( option, "DrawOuterFrame" ) ) msg->AddBool( "response", fDrawOuterFrame ); else if ( !strcasecmp( option, "DockLocation" ) ) { BString where; switch ( fLocation ) { case kLocationBottom: where = "bottom"; break; case kLocationTop: where = "top"; break; case kLocationLeft: where = "left"; break; case kLocationRight: where = "right"; break; } msg->AddString( "response", where ); } else if ( !strcasecmp( option, "BackColor" ) ) msg->AddData( "response", B_RGB_COLOR_TYPE, &fColor2, sizeof(fColor2) ); else if ( !strcasecmp( option, "OuterFrameColor" ) ) msg->AddData( "response", B_RGB_COLOR_TYPE, &fOuterFrameColor, sizeof(fOuterFrameColor) ); else if ( !strcasecmp( option, "AutoHide" ) ) msg->AddBool( "response", ((TPanelWindow*)Window())->IsAutoHiding() ); else if ( !strcasecmp( option, "HideEffectDelay" ) ) msg->AddInt32( "response", ((TPanelWindow*)Window())->CurrentHideEffectDelay() ); else if ( !strcasecmp( option, "AlwaysOnTop" ) ) msg->AddBool( "response", fAlwaysOnTop ); else if ( !strcasecmp( option, "HideStandardDeskbar" ) ) msg->AddBool( "response", fHideStandardDeskbar ); #ifdef USE_WINDOW_SHAPING else if ( !strcasecmp( option, "UseWindowShapping" ) ) msg->AddBool( "response", fUseWindowShapping ); #endif else if ( !strcasecmp( option, "DebugLevel" ) ) msg->AddInt32( "response", fDebugLevel ); else if ( !strcasecmp( option, "DebugDump" ) ) DoDebugDump(); else if ( !strcasecmp( option, "DoCheckup" ) ) DoCheckup(); else if ( !strcasecmp( option, "tabs" ) ) { // fPanelListLock.Lock(); fPanels.Lock(); msg->AddInt32( "response", fPanels.CountItems() ); fPanels.Unlock(); // fPanelListLock.Unlock(); } else if ( !strcasecmp( option, "AboutInfo" ) ) msg->AddString( "about", BString("DockBert - by Hugo Santos (linn) and Daniel T. Bender (HarvestMoon)") ); else if ( !strcasecmp( option, "VersionInfo" ) ) { msg->AddString( "status", BString( BUILDSTATUS ) ); msg->AddString( "build_nr", BString( BUILDNR ) ); msg->AddString( "version", BString( BUILDVERSION ) ); msg->AddString( "build_date", BString( BUILDDATE ) ); } else return false; return true; }
iShaderProgram::CacheLoadResult csShaderGLCGCommon::LoadFromCache ( iHierarchicalCache* cache, iBase* previous, iDocumentNode* node, csRef<iString>* failReason, csRef<iString>* tag, ProfileLimitsPair* cacheLimits) { if (!cache) return iShaderProgram::loadFail; csRef<iShaderProgramCG> prevCG (scfQueryInterfaceSafe<iShaderProgramCG> ( previous)); csRef<iStringArray> allCachedPrograms; if ((programType == progVP) && prevCG.IsValid()) { csShaderGLCGFP* prevFP = static_cast<csShaderGLCGFP*> ( (iShaderProgramCG*)prevCG); csString tagStr ("CG"); tagStr += prevFP->cacheLimits.ToString(); if (failReason) failReason->AttachNew ( new scfString ("paired cached programs not found")); allCachedPrograms.AttachNew (new scfStringArray); allCachedPrograms->Push (tagStr); } else allCachedPrograms = cache->GetSubItems ("/"); if (!allCachedPrograms.IsValid() || (allCachedPrograms->GetSize() == 0)) { if (failReason) failReason->AttachNew ( new scfString ("no cached programs found")); return iShaderProgram::loadFail; } if (!GetProgramNode (node)) return iShaderProgram::loadFail; csRef<iDataBuffer> programBuffer = GetProgramData(); CS::Utility::Checksum::MD5::Digest progHash = CS::Utility::Checksum::MD5::Encode ( programBuffer->GetData(), programBuffer->GetSize()); csArray<CachedShaderWrapper> cachedProgWrappers; for (size_t i = 0; i < allCachedPrograms->GetSize(); i++) { const char* tag = allCachedPrograms->Get (i); if ((tag[0] != 'C') || (tag[1] != 'G')) continue; CachedShaderWrapper wrapper; if (!wrapper.limits.FromString (tag+2)) continue; wrapper.name = tag; csString cachePath ("/"); cachePath.Append (tag); csRef<iDataBuffer> cacheBuf = cache->ReadCache (cachePath); if (!cacheBuf.IsValid()) continue; csRef<iFile> cacheFile; cacheFile.AttachNew (new csMemFile (cacheBuf, true)); wrapper.cacheFile = cacheFile; uint32 diskMagic; if (cacheFile->Read ((char*)&diskMagic, sizeof (diskMagic)) != sizeof (diskMagic)) continue; if (csLittleEndian::UInt32 (diskMagic) != cacheFileMagic) continue; CS::Utility::Checksum::MD5::Digest diskHash; if (cacheFile->Read ((char*)&diskHash, sizeof (diskHash)) != sizeof (diskHash)) continue; if (diskHash != progHash) continue; cachedProgWrappers.Push (wrapper); } if (cachedProgWrappers.GetSize() == 0) { if (failReason && !*failReason) failReason->AttachNew ( new scfString ("all cached programs failed to read")); return iShaderProgram::loadFail; } cachedProgWrappers.Sort (); ProfileLimits currentLimits ( (programType == progVP) ? shaderPlug->currentLimits.vp : shaderPlug->currentLimits.fp); bool strictMatch = (programType == progVP) ? shaderPlug->strictMatchVP : shaderPlug->strictMatchFP; const char* progTypeNode = 0; switch (programType) { case progVP: progTypeNode = "cgvp"; break; case progFP: progTypeNode = "cgfp"; break; } csString allReasons; bool oneReadCorrectly = false; ProfileLimits bestLimits ( CS::PluginCommon::ShaderProgramPluginGL::Other, CG_PROFILE_UNKNOWN); bool bestLimitsSet = false; for (size_t i = cachedProgWrappers.GetSize(); i-- > 0;) { const CachedShaderWrapper& wrapper = cachedProgWrappers[i]; const ProfileLimits& limits = (programType == progVP) ? wrapper.limits.vp : wrapper.limits.fp; if (!bestLimitsSet) { bestLimits = limits; bestLimitsSet = true; } if (strictMatch && (limits != currentLimits)) { allReasons += wrapper.name; allReasons += ": strict mismatch; "; continue; } bool profileSupported = (shaderPlug->ProfileNeedsRouting (limits.profile) && shaderPlug->IsRoutedProfileSupported (limits.profile)) || cgGLIsProfileSupported (limits.profile); if (!profileSupported) { allReasons += wrapper.name; allReasons += ": Profile unsupported; "; continue; } if ((limits.vendor != currentLimits.vendor) && (limits.vendor != CS::PluginCommon::ShaderProgramPluginGL::Other)) { allReasons += wrapper.name; allReasons += ": vendor mismatch; "; continue; } bool limitsSupported = currentLimits >= limits; if (!limitsSupported) { allReasons += wrapper.name; allReasons += ": Limits exceeded; "; continue; } iFile* cacheFile = wrapper.cacheFile; { uint32 diskState; if (cacheFile->Read ((char*)&diskState, sizeof (diskState)) != sizeof (diskState)) continue; if (csLittleEndian::UInt32 (diskState) != cpsValid) { oneReadCorrectly = true; continue; } } description = CS::PluginCommon::ShaderCacheHelper::ReadString (cacheFile); bool breakFail = false; csRef<iDocumentNode> cgNode = node->GetNode (progTypeNode); if (!cgNode.IsValid()) continue; csRef<iDocumentNodeIterator> nodes = cgNode->GetNodes(); while(nodes->HasNext() && !breakFail) { csRef<iDocumentNode> child = nodes->Next(); if(child->GetType() != CS_NODE_ELEMENT) continue; const char* value = child->GetValue (); csStringID id = xmltokens.Request (value); switch(id) { case XMLTOKEN_VARIABLEMAP: if (!ParseVmap (child)) breakFail = true; break; case XMLTOKEN_CLIP: if (!ParseClip (child)) breakFail = true; break; default: /* Ignore unknown nodes. Invalid nodes would have been caught by the first (not from cache) parsing */ break; } } if (breakFail) continue; csString objectCodeCachePathArc = CS::PluginCommon::ShaderCacheHelper::ReadString (cacheFile); if (objectCodeCachePathArc.IsEmpty()) continue; csString objectCodeCachePathItem = CS::PluginCommon::ShaderCacheHelper::ReadString (cacheFile); if (objectCodeCachePathItem.IsEmpty()) continue; ProgramObjectID progId (objectCodeCachePathArc, objectCodeCachePathItem); ProgramObject programObj; //if (!LoadObjectCodeFromCompileCache (limits, cache)) if (!shaderPlug->progCache.LoadObject (progId, programObj)) continue; oneReadCorrectly = true; if (program) { cgDestroyProgram (program); program = 0; } if (!programObj.IsValid()) continue; cgGetError(); // Clear error program = cgCreateProgram (shaderPlug->context, CG_OBJECT, programObj.GetObjectCode(), limits.profile, 0, 0); if (!program) continue; CGerror err = cgGetError(); if (err != CG_NO_ERROR) { const char* errStr = cgGetErrorString (err); shaderPlug->Report (CS_REPORTER_SEVERITY_WARNING, "Cg error %s", errStr); continue; } programProfile = limits.profile; programPositionInvariant = programObj.GetFlags() & ProgramObject::flagPositionInvariant; unusedParams = programObj.GetUnusedParams(); ClipsToVmap(); GetParamsFromVmap(); bool doLoadToGL = !shaderPlug->ProfileNeedsRouting (programProfile); cgGetError(); // Clear error if (doLoadToGL) { cgGLLoadProgram (program); } else { cgCompileProgram (program); } shaderPlug->PrintAnyListing(); err = cgGetError(); if ((err != CG_NO_ERROR) || (doLoadToGL && !cgGLIsProgramLoaded (program))) { //if (shaderPlug->debugDump) //DoDebugDump(); const char* errStr = cgGetErrorString (err); shaderPlug->Report (CS_REPORTER_SEVERITY_WARNING, "Cg error %s", errStr); if (shaderPlug->doVerbose && (((programType == progVP) && (programProfile >= CG_PROFILE_ARBVP1)) || ((programType == progFP) && (programProfile >= CG_PROFILE_ARBFP1)))) { const char* err = (char*)glGetString (GL_PROGRAM_ERROR_STRING_ARB); shaderPlug->Report (CS_REPORTER_SEVERITY_WARNING, "OpenGL error string: %s", err); } shaderPlug->SetCompiledSource (0); continue; } GetPostCompileParamProps (); if (shaderPlug->debugDump) DoDebugDump(); tag->AttachNew (new scfString (wrapper.name)); if (cacheLimits != 0) *cacheLimits = wrapper.limits; bool loaded = !shaderPlug->ProfileNeedsRouting (programProfile) || LoadProgramWithPS1 (); if (loaded && (bestLimits < currentLimits)) { /* The best found program is worse than the current limits, so pretend that the shader program failed (instead just being 'invalid') - that will make xmlshader try to load the program from scratch, ie with current limits, which may just work. */ if (failReason) failReason->AttachNew (new scfString ("Provoking clean load with current limits")); return iShaderProgram::loadFail; } return loaded ? iShaderProgram::loadSuccessShaderValid : iShaderProgram::loadSuccessShaderInvalid; } if (oneReadCorrectly) { if (bestLimits < currentLimits) { /* The 'invalid' programs may compile with the current limits - so again, provoke clean load */ if (failReason) failReason->AttachNew (new scfString ("Provoking clean load with current limits")); return iShaderProgram::loadFail; } else return iShaderProgram::loadSuccessShaderInvalid; } else return iShaderProgram::loadFail; }
bool csShaderGLCGCommon::DefaultLoadProgram (iShaderProgramCG* cgResolve, const char* programStr, ProgramType _type, const ProfileLimitsPair& customLimitsPair, uint flags) { if (!programStr || !*programStr) return false; const ProfileLimits& customLimits = (_type == progVP) ? customLimitsPair.vp : customLimitsPair.fp; CGGLenum type = (_type == progVP) ? CG_GL_VERTEX : CG_GL_FRAGMENT; size_t i; csString augmentedProgramStr = GetAugmentedProgram (programStr, (flags & loadFlagUnusedV2FForInit) != 0); programStr = augmentedProgramStr; CGprofile profile = customLimits.profile; CS::PluginCommon::ShaderProgramPluginGL::HardwareVendor vendor = customLimits.vendor; if (shaderPlug->doVerbose || shaderPlug->doVerbosePrecache) { shaderPlug->Report (CS_REPORTER_SEVERITY_NOTIFY, "Cg %s program %s: using profile %s[%d]", GetProgramType(), CS::Quote::Single (description.GetData ()), cgGetProfileString (profile), profile); } ArgumentArray args; shaderPlug->GetProfileCompilerArgs (GetProgramType(), profile, customLimitsPair, vendor, (flags & loadIgnoreConfigProgramOpts) ? csGLShader_CG::argsNoConfig : csGLShader_CG::argsAll, args); for (i = 0; i < compilerArgs.GetSize(); i++) args.Push (compilerArgs[i]); programPositionInvariant = false; for (i = 0; i < args.GetSize(); ) { if (strcmp (args[i], "-posinv") == 0) { if (profile >= CG_PROFILE_GPU_VP) { /* Work around Cg 2.0 and above (including 3.0) bug: it emits "OPTION ARB_position_invariant;" AND computes result.position in the VP - doing both is verboten. Affected are the GP4VP and higher profiles. Remedy: remove -posinv argument */ args.DeleteIndex (i); continue; } programPositionInvariant = true; } i++; } customLimits.ToCgOptions (args); args.Push (0); if (program) { cgDestroyProgram (program); } shaderPlug->SetCompiledSource (programStr); shaderPlug->SetIgnoreErrors (true); program = cgCreateProgram (shaderPlug->context, CG_SOURCE, programStr, profile, !entrypoint.IsEmpty() ? entrypoint : "main", args.GetArray()); shaderPlug->SetIgnoreErrors (false); if (!(flags & loadIgnoreErrors)) shaderPlug->PrintAnyListing(); if (!program) { shaderPlug->SetCompiledSource (0); /*if (shaderPlug->debugDump) { EnsureDumpFile(); WriteAdditionalDumpInfo ("Failed program source", programStr); }*/ return false; } programProfile = cgGetProgramProfile (program); GetParamsFromVmapConstants(); if (flags & loadApplyVmap) GetParamsFromVmap(); if (flags & loadIgnoreErrors) shaderPlug->SetIgnoreErrors (true); cgCompileProgram (program); if (flags & loadIgnoreErrors) shaderPlug->SetIgnoreErrors (false); else shaderPlug->PrintAnyListing(); if (flags & loadApplyVmap) GetPostCompileParamProps (); if (flags & loadLoadToGL) { cgGetError(); // Clear error cgGLLoadProgram (program); if (!(flags & loadIgnoreErrors)) shaderPlug->PrintAnyListing(); if ((cgGetError() != CG_NO_ERROR) || !cgGLIsProgramLoaded (program)) { if (shaderPlug->debugDump) DoDebugDump(); if (shaderPlug->doVerbose && (((type == CG_GL_VERTEX) && (profile >= CG_PROFILE_ARBVP1)) || ((type == CG_GL_FRAGMENT) && (profile >= CG_PROFILE_ARBFP1)))) { csString err = (char*)glGetString (GL_PROGRAM_ERROR_STRING_ARB); if (!err.IsEmpty()) shaderPlug->Report (CS_REPORTER_SEVERITY_WARNING, "OpenGL error string: %s", err.GetData()); } shaderPlug->SetCompiledSource (0); return false; } } if (shaderPlug->debugDump) DoDebugDump(); shaderPlug->SetCompiledSource (0); bool result = true; if (programType == progFP) { int numVaryings = 0; CGparameter param = cgGetFirstLeafParameter (program, CG_PROGRAM); while (param) { if (cgIsParameterUsed (param, program) && cgIsParameterReferenced (param)) { const CGenum var = cgGetParameterVariability (param); if (var == CG_VARYING) numVaryings++; } param = cgGetNextLeafParameter (param); } /* WORKAROUND: Even NVs G80 doesn't support passing more than 16 attribs into an FP, yet Cg happily generates code that uses more (and GL falls back to SW). So manually check the number of varying inputs and reject more than 16. @@@ This should be at least configurable */ const int maxNumVaryings = 16; if (numVaryings > maxNumVaryings) { if (shaderPlug->doVerbose || shaderPlug->doVerbosePrecache) { shaderPlug->Report (CS_REPORTER_SEVERITY_NOTIFY, "Discarding compiled program for having too much varyings " "(%d, limit is %d)", numVaryings, maxNumVaryings); } cgDestroyProgram (program); program = 0; result = false; } } if (!result && !debugFN.IsEmpty()) { csRef<iVFS> vfs = csQueryRegistry<iVFS> (objectReg); vfs->DeleteFile (debugFN); } return result; }