示例#1
0
TEST(RuleSetTest, findBestRuleSetAndAdd_TagThenAttrThenId) {
  CSSTestHelper helper;

  helper.addCSSRules("div[attr]#id { }");
  RuleSet& ruleSet = helper.ruleSet();
  AtomicString str("id");
  const TerminatedArray<RuleData>* rules = ruleSet.idRules(str);
  ASSERT_EQ(1u, rules->size());
  AtomicString tagStr("div");
  ASSERT_EQ(tagStr, rules->at(0).selector().tagQName().localName());
}
NS_IMETHODIMP 
RDFContentSinkImpl::HandleEndElement(const PRUnichar *aName)
{
  FlushText();

  nsIRDFResource* resource;
  if (NS_FAILED(PopContext(resource, mState, mParseMode))) {
      // XXX parser didn't catch unmatched tags?
#ifdef PR_LOGGING
      if (PR_LOG_TEST(gLog, PR_LOG_WARNING)) {
          nsAutoString tagStr(aName);
          char* tagCStr = ToNewCString(tagStr);

          PR_LogPrint
                 ("rdfxml: extra close tag '%s' at line %d",
                  tagCStr, 0/*XXX fix me */);

          NS_Free(tagCStr);
      }
#endif

      return NS_ERROR_UNEXPECTED; // XXX
  }

  // If we've just popped a member or property element, _now_ is the
  // time to add that element to the graph.
  switch (mState) {
    case eRDFContentSinkState_InMemberElement: 
      {
        nsCOMPtr<nsIRDFContainer> container;
        NS_NewRDFContainer(getter_AddRefs(container));
        container->Init(mDataSource, GetContextElement(1));
        container->AppendElement(resource);
      } 
      break;

    case eRDFContentSinkState_InPropertyElement: 
      {
        mDataSource->Assert(GetContextElement(1), GetContextElement(0), resource, PR_TRUE);                                          
      } break;
    default:
      break;
  }
  
  if (mContextStack->IsEmpty())
      mState = eRDFContentSinkState_InEpilog;

  NS_IF_RELEASE(resource);
  return NS_OK;
}
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;
}
示例#4
0
const Material MaterialLoader::loadFromXML(const std::string &path) {
  std::string dir = path.substr(0, path.find_last_of("/\\"));
  XMLDocument doc;
  XMLError error = doc.LoadFile((Environment::getDataDir() + "/textures/" + path + ".gmd").c_str());

  if (error != XML_NO_ERROR) {
    System::Log(Error, "MaterialLoader") << "XML Error " << doc.ErrorID() << ": " <<
      doc.ErrorName() << " in " << path;
  }

  XMLHandle docHandle(&doc);
  XMLElement *root = docHandle.FirstChildElement().ToElement();
  XMLHandle rootH(root);

  std::string name = root->Attribute("name");
  std::string fancyname = root->Attribute("fancyname");

  Material mat;

  mat.name = name;
  mat.fancyname = fancyname;

  XMLElement *diffE = rootH.FirstChildElement("diffuse").ToElement();
  if (diffE) {
    std::string diffP = diffE->Attribute("path");
    if (diffP.length() > 0) {
      diffP = dir + "/" + diffP;
      System::Log(Debug, "MaterialLoader") << mat.name << ": load " << diffP;
      mat.diffuse = TextureLoader::getTexture(diffP);
    }
  } else {
    mat.diffuse = TextureLoader::getEmptyDiffuse();
  }

  XMLElement *normE = rootH.FirstChildElement("normal").ToElement();
  if (normE) {
    std::string normP = normE->Attribute("path");
    if (normP.length() > 0) {
      normP = dir + "/" + normP;
      System::Log(Debug, "MaterialLoader") << mat.name << ": load " << normP;
      mat.normal = TextureLoader::getTexture(normP);
    }
  } else {
    mat.normal = TextureLoader::getEmptyNormal();
  }

  XMLElement *specE = rootH.FirstChildElement("specular").ToElement();
  if (specE) {
    std::string specP = specE->Attribute("path");
    if (specP.length() > 0) {
      specP = dir + "/" + specP;
      System::Log(Debug, "MaterialLoader") << mat.name << ": load " << specP;
      mat.specular = TextureLoader::getTexture(specP);
    }
    specE->QueryFloatAttribute("shininess", &mat.shininess);
  } else {
    mat.specular = TextureLoader::getEmptySpecular();
  }

  XMLElement *surfaceE = rootH.FirstChildElement("surface").ToElement();
  mat.portalable = false;
  if (surfaceE) {
    surfaceE->QueryBoolAttribute("portalable", &mat.portalable);
  }

  XMLElement *scaleE = rootH.FirstChildElement("scale").ToElement();
  if (scaleE) {
    scaleE->QueryFloatAttribute("u", &mat.scaleU);
    scaleE->QueryFloatAttribute("v", &mat.scaleV);
  }

  XMLElement *kindE = rootH.FirstChildElement("kind").ToElement();
  if (kindE) {
    mat.kind = std::string(kindE->GetText());
  }

  XMLElement *tagsE = rootH.FirstChildElement("tags").ToElement();
  if (tagsE) {
    std::string tagStr(tagsE->GetText());
    size_t start = 0;
    size_t index = tagStr.find(",", start);
    while (index != std::string::npos) {
      mat.tags.push_back(tagStr.substr(start, index - start));
      start = index + 1;
      index = tagStr.find(",", start);
    }
    if (start != std::string::npos) {
      mat.tags.push_back(tagStr.substr(start));
    }
  }

  // TODO

  return mat;
}